26#define LoongArch_EXPAND_ATOMIC_PSEUDO_NAME \
27 "LoongArch atomic pseudo instruction expansion pass"
50 bool IsMasked,
int Width,
64char LoongArchExpandAtomicPseudo::ID = 0;
66bool LoongArchExpandAtomicPseudo::runOnMachineFunction(
MachineFunction &MF) {
88bool LoongArchExpandAtomicPseudo::expandMI(
91 switch (
MBBI->getOpcode()) {
92 case LoongArch::PseudoMaskedAtomicSwap32:
95 case LoongArch::PseudoAtomicSwap32:
98 case LoongArch::PseudoMaskedAtomicLoadAdd32:
100 case LoongArch::PseudoMaskedAtomicLoadSub32:
102 case LoongArch::PseudoAtomicLoadNand32:
105 case LoongArch::PseudoAtomicLoadNand64:
108 case LoongArch::PseudoMaskedAtomicLoadNand32:
111 case LoongArch::PseudoAtomicLoadAdd32:
114 case LoongArch::PseudoAtomicLoadSub32:
117 case LoongArch::PseudoAtomicLoadAnd32:
120 case LoongArch::PseudoAtomicLoadOr32:
122 case LoongArch::PseudoAtomicLoadXor32:
125 case LoongArch::PseudoAtomicLoadUMax32:
128 case LoongArch::PseudoAtomicLoadUMin32:
131 case LoongArch::PseudoAtomicLoadMax32:
134 case LoongArch::PseudoAtomicLoadMin32:
137 case LoongArch::PseudoMaskedAtomicLoadUMax32:
140 case LoongArch::PseudoMaskedAtomicLoadUMin32:
143 case LoongArch::PseudoCmpXchg32:
144 return expandAtomicCmpXchg(
MBB,
MBBI,
false, 32, NextMBBI);
145 case LoongArch::PseudoCmpXchg64:
146 return expandAtomicCmpXchg(
MBB,
MBBI,
false, 64, NextMBBI);
147 case LoongArch::PseudoCmpXchg128:
148 case LoongArch::PseudoCmpXchg128Acquire:
149 return expandAtomicCmpXchg128(
MBB,
MBBI, NextMBBI);
150 case LoongArch::PseudoMaskedCmpXchg32:
151 return expandAtomicCmpXchg(
MBB,
MBBI,
true, 32, NextMBBI);
152 case LoongArch::PseudoMaskedAtomicLoadMax32:
155 case LoongArch::PseudoMaskedAtomicLoadMin32:
169 Register ScratchReg =
MI.getOperand(1).getReg();
179 TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)
186 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::OR), ScratchReg)
191 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::AND), ScratchReg)
194 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::NOR), ScratchReg)
199 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::ADD_W), ScratchReg)
204 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::SUB_W), ScratchReg)
209 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::AND), ScratchReg)
214 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::OR), ScratchReg)
219 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::XOR), ScratchReg)
225 TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D), ScratchReg)
239 assert(OldValReg != ScratchReg &&
"OldValReg and ScratchReg must be unique");
240 assert(OldValReg != MaskReg &&
"OldValReg and MaskReg must be unique");
241 assert(ScratchReg != MaskReg &&
"ScratchReg and MaskReg must be unique");
255static void doMaskedAtomicBinOpExpansion(
259 assert(Width == 32 &&
"Should never need to expand masked 64-bit operations");
261 Register ScratchReg =
MI.getOperand(1).getReg();
274 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::LL_W), DestReg)
281 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::ADDI_W), ScratchReg)
286 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::ADD_W), ScratchReg)
291 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::SUB_W), ScratchReg)
296 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::AND), ScratchReg)
299 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::NOR), ScratchReg)
305 insertMaskedMerge(
TII,
DL, LoopMBB, ScratchReg, DestReg, ScratchReg, MaskReg,
308 BuildMI(LoopMBB,
DL,
TII->get(LoongArch::SC_W), ScratchReg)
318bool LoongArchExpandAtomicPseudo::expandAtomicBinOp(
330 MF->
insert(++
MBB.getIterator(), LoopMBB);
338 MBB.addSuccessor(LoopMBB);
341 doMaskedAtomicBinOpExpansion(
TII,
MI,
DL, &
MBB, LoopMBB, DoneMBB, BinOp,
344 doAtomicBinOpExpansion(
TII,
MI,
DL, &
MBB, LoopMBB, DoneMBB, BinOp, Width);
346 NextMBBI =
MBB.end();
347 MI.eraseFromParent();
367bool LoongArchExpandAtomicPseudo::expandAtomicMinMaxOp(
371 assert(Width == 32 &&
"Should never need to expand masked 64-bit operations");
382 MF->
insert(++
MBB.getIterator(), LoopHeadMBB);
383 MF->
insert(++LoopHeadMBB->getIterator(), LoopIfBodyMBB);
384 MF->
insert(++LoopIfBodyMBB->getIterator(), LoopTailMBB);
385 MF->
insert(++LoopTailMBB->getIterator(), DoneMBB);
388 LoopHeadMBB->addSuccessor(LoopIfBodyMBB);
389 LoopHeadMBB->addSuccessor(LoopTailMBB);
390 LoopIfBodyMBB->addSuccessor(LoopTailMBB);
391 LoopTailMBB->addSuccessor(LoopHeadMBB);
392 LoopTailMBB->addSuccessor(DoneMBB);
395 MBB.addSuccessor(LoopHeadMBB);
398 Register ScratchReg =
MI.getOperand(1).getReg();
399 Register AddrReg =
MI.getOperand(IsMasked ? 3 : 2).getReg();
400 Register IncrReg =
MI.getOperand(IsMasked ? 4 : 3).getReg();
406 BuildMI(LoopHeadMBB,
DL,
TII->get(LoongArch::LL_W), DestReg)
412 CmprReg =
MI.getOperand(2).getReg();
413 BuildMI(LoopHeadMBB,
DL,
TII->get(LoongArch::AND), CmprReg)
418 BuildMI(LoopHeadMBB,
DL,
TII->get(LoongArch::OR), ScratchReg)
441 insertSext(
TII,
DL, LoopHeadMBB, CmprReg,
MI.getOperand(6).getReg());
450 insertSext(
TII,
DL, LoopHeadMBB, CmprReg,
MI.getOperand(6).getReg());
466 insertMaskedMerge(
TII,
DL, LoopIfBodyMBB, ScratchReg, DestReg, IncrReg,
467 MaskReg, ScratchReg);
470 BuildMI(LoopIfBodyMBB,
DL,
TII->get(LoongArch::OR), ScratchReg)
478 BuildMI(LoopTailMBB,
DL,
TII->get(LoongArch::SC_W), ScratchReg)
487 NextMBBI =
MBB.end();
488 MI.eraseFromParent();
499bool LoongArchExpandAtomicPseudo::expandAtomicCmpXchg(
511 MF->
insert(++
MBB.getIterator(), LoopHeadMBB);
512 MF->
insert(++LoopHeadMBB->getIterator(), LoopTailMBB);
513 MF->
insert(++LoopTailMBB->getIterator(), TailMBB);
514 MF->
insert(++TailMBB->getIterator(), DoneMBB);
517 LoopHeadMBB->addSuccessor(LoopTailMBB);
518 LoopHeadMBB->addSuccessor(TailMBB);
519 LoopTailMBB->addSuccessor(DoneMBB);
520 LoopTailMBB->addSuccessor(LoopHeadMBB);
521 TailMBB->addSuccessor(DoneMBB);
524 MBB.addSuccessor(LoopHeadMBB);
527 Register ScratchReg =
MI.getOperand(1).getReg();
529 Register CmpValReg =
MI.getOperand(3).getReg();
530 Register NewValReg =
MI.getOperand(4).getReg();
537 TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)
549 BuildMI(LoopTailMBB,
DL,
TII->get(LoongArch::OR), ScratchReg)
553 TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D),
570 TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)
573 BuildMI(LoopHeadMBB,
DL,
TII->get(LoongArch::AND), ScratchReg)
587 BuildMI(LoopTailMBB,
DL,
TII->get(LoongArch::ANDN), ScratchReg)
590 BuildMI(LoopTailMBB,
DL,
TII->get(LoongArch::OR), ScratchReg)
594 TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D),
610 switch (FailureOrdering) {
627 NextMBBI =
MBB.end();
628 MI.eraseFromParent();
639bool LoongArchExpandAtomicPseudo::expandAtomicCmpXchg128(
651 MF->
insert(++
MBB.getIterator(), LoopHeadMBB);
652 MF->
insert(++LoopHeadMBB->getIterator(), LoopTailMBB);
653 MF->
insert(++LoopTailMBB->getIterator(), TailMBB);
654 MF->
insert(++TailMBB->getIterator(), DoneMBB);
657 LoopHeadMBB->addSuccessor(LoopTailMBB);
658 LoopHeadMBB->addSuccessor(TailMBB);
659 LoopTailMBB->addSuccessor(DoneMBB);
660 LoopTailMBB->addSuccessor(LoopHeadMBB);
661 TailMBB->addSuccessor(DoneMBB);
664 MBB.addSuccessor(LoopHeadMBB);
666 Register DestLoReg =
MI.getOperand(0).getReg();
667 Register DestHiReg =
MI.getOperand(1).getReg();
668 Register ScratchReg =
MI.getOperand(2).getReg();
670 Register CmpValLoReg =
MI.getOperand(4).getReg();
671 Register CmpValHiReg =
MI.getOperand(5).getReg();
672 Register NewValLoReg =
MI.getOperand(6).getReg();
673 Register NewValHiReg =
MI.getOperand(7).getReg();
681 BuildMI(LoopHeadMBB,
DL,
TII->get(LoongArch::LL_D), DestLoReg)
685 BuildMI(LoopHeadMBB,
DL,
TII->get(LoongArch::LD_D), DestHiReg)
701 BuildMI(LoopTailMBB,
DL,
TII->get(LoongArch::OR), ScratchReg)
704 BuildMI(LoopTailMBB,
DL,
TII->get(LoongArch::SC_Q), ScratchReg)
715 switch (
MI.getOpcode()) {
716 case LoongArch::PseudoCmpXchg128Acquire:
720 case LoongArch::PseudoCmpXchg128:
732 NextMBBI =
MBB.end();
733 MI.eraseFromParent();
752 return new LoongArchExpandAtomicPseudo();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
#define LoongArch_EXPAND_ATOMIC_PSEUDO_NAME
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ Min
*p = old <signed v ? old : v
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
FunctionPass class - This class is used to implement most global optimizations.
A set of physical registers with utility functions to track liveness when walking backward/forward th...
LLVM_ABI void transferSuccessors(MachineBasicBlock *FromMBB)
Transfers all the successors from MBB to this machine basic block (i.e., copies all the successors Fr...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
Wrapper class representing virtual and physical registers.
StringRef - Represent a constant reference to a string, i.e.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createLoongArchExpandAtomicPseudoPass()
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
AtomicOrdering
Atomic ordering for LLVM's memory model.
void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().