26#define RISCV_EXPAND_ATOMIC_PSEUDO_NAME \
27 "RISC-V atomic pseudo instruction expansion pass"
51 bool IsMasked,
int Width,
71char RISCVExpandAtomicPseudo::ID = 0;
73bool RISCVExpandAtomicPseudo::runOnMachineFunction(
MachineFunction &MF) {
87 assert(OldSize >= NewSize);
111 switch (
MBBI->getOpcode()) {
112 case RISCV::PseudoAtomicSwap32:
115 case RISCV::PseudoAtomicSwap64:
118 case RISCV::PseudoAtomicLoadAdd32:
121 case RISCV::PseudoAtomicLoadAdd64:
124 case RISCV::PseudoAtomicLoadSub32:
127 case RISCV::PseudoAtomicLoadSub64:
130 case RISCV::PseudoAtomicLoadAnd32:
133 case RISCV::PseudoAtomicLoadAnd64:
136 case RISCV::PseudoAtomicLoadOr32:
138 case RISCV::PseudoAtomicLoadOr64:
140 case RISCV::PseudoAtomicLoadXor32:
143 case RISCV::PseudoAtomicLoadXor64:
146 case RISCV::PseudoAtomicLoadNand32:
149 case RISCV::PseudoAtomicLoadNand64:
152 case RISCV::PseudoAtomicLoadMin32:
155 case RISCV::PseudoAtomicLoadMin64:
158 case RISCV::PseudoAtomicLoadMax32:
161 case RISCV::PseudoAtomicLoadMax64:
164 case RISCV::PseudoAtomicLoadUMin32:
167 case RISCV::PseudoAtomicLoadUMin64:
170 case RISCV::PseudoAtomicLoadUMax32:
173 case RISCV::PseudoAtomicLoadUMax64:
176 case RISCV::PseudoMaskedAtomicSwap32:
179 case RISCV::PseudoMaskedAtomicLoadAdd32:
181 case RISCV::PseudoMaskedAtomicLoadSub32:
183 case RISCV::PseudoMaskedAtomicLoadNand32:
186 case RISCV::PseudoMaskedAtomicLoadMax32:
189 case RISCV::PseudoMaskedAtomicLoadMin32:
192 case RISCV::PseudoMaskedAtomicLoadUMax32:
195 case RISCV::PseudoMaskedAtomicLoadUMin32:
198 case RISCV::PseudoCmpXchg32:
199 return expandAtomicCmpXchg(
MBB,
MBBI,
false, 32, NextMBBI);
200 case RISCV::PseudoCmpXchg64:
201 return expandAtomicCmpXchg(
MBB,
MBBI,
false, 64, NextMBBI);
202 case RISCV::PseudoMaskedCmpXchg32:
203 return expandAtomicCmpXchg(
MBB,
MBBI,
true, 32, NextMBBI);
217 if (Subtarget->hasStdExtZtso())
219 return RISCV::LR_W_AQ;
223 if (Subtarget->hasStdExtZtso())
225 return RISCV::LR_W_AQ;
227 return RISCV::LR_W_AQRL;
241 if (Subtarget->hasStdExtZtso())
243 return RISCV::SC_W_RL;
245 if (Subtarget->hasStdExtZtso())
247 return RISCV::SC_W_RL;
249 return RISCV::SC_W_RL;
261 if (Subtarget->hasStdExtZtso())
263 return RISCV::LR_D_AQ;
267 if (Subtarget->hasStdExtZtso())
269 return RISCV::LR_D_AQ;
271 return RISCV::LR_D_AQRL;
285 if (Subtarget->hasStdExtZtso())
287 return RISCV::SC_D_RL;
289 if (Subtarget->hasStdExtZtso())
291 return RISCV::SC_D_RL;
293 return RISCV::SC_D_RL;
300 return getLRForRMW32(Ordering, Subtarget);
302 return getLRForRMW64(Ordering, Subtarget);
309 return getSCForRMW32(Ordering, Subtarget);
311 return getSCForRMW64(Ordering, Subtarget);
322 Register ScratchReg =
MI.getOperand(1).getReg();
333 BuildMI(LoopMBB,
DL,
TII->get(getLRForRMW(Ordering, Width, STI)), DestReg)
397 BuildMI(LoopMBB,
DL,
TII->get(getSCForRMW(Ordering, Width, STI)), ScratchReg)
410 assert(OldValReg != ScratchReg &&
"OldValReg and ScratchReg must be unique");
411 assert(OldValReg != MaskReg &&
"OldValReg and MaskReg must be unique");
412 assert(ScratchReg != MaskReg &&
"ScratchReg and MaskReg must be unique");
435 assert(Width == 32 &&
"Should never need to expand masked 64-bit operations");
437 Register ScratchReg =
MI.getOperand(1).getReg();
452 BuildMI(LoopMBB,
DL,
TII->get(getLRForRMW32(Ordering, STI)), DestReg)
482 insertMaskedMerge(
TII,
DL, LoopMBB, ScratchReg, DestReg, ScratchReg, MaskReg,
485 BuildMI(LoopMBB,
DL,
TII->get(getSCForRMW32(Ordering, STI)), ScratchReg)
494bool RISCVExpandAtomicPseudo::expandAtomicBinOp(
506 MF->
insert(++
MBB.getIterator(), LoopMBB);
514 MBB.addSuccessor(LoopMBB);
517 doAtomicBinOpExpansion(
TII,
MI,
DL, &
MBB, LoopMBB, DoneMBB, BinOp, Width,
520 doMaskedAtomicBinOpExpansion(
TII,
MI,
DL, &
MBB, LoopMBB, DoneMBB, BinOp,
523 NextMBBI =
MBB.end();
524 MI.eraseFromParent();
544static void doAtomicMinMaxOpExpansion(
551 Register ScratchReg =
MI.getOperand(1).getReg();
561 BuildMI(LoopHeadMBB,
DL,
TII->get(getLRForRMW(Ordering, Width, STI)), DestReg)
563 BuildMI(LoopHeadMBB,
DL,
TII->get(RISCV::ADDI), ScratchReg)
599 BuildMI(LoopIfBodyMBB,
DL,
TII->get(RISCV::ADDI), ScratchReg)
606 BuildMI(LoopTailMBB,
DL,
TII->get(getSCForRMW(Ordering, Width, STI)),
616static void doMaskedAtomicMinMaxOpExpansion(
622 assert(Width == 32 &&
"Should never need to expand masked 64-bit operations");
624 Register Scratch1Reg =
MI.getOperand(1).getReg();
625 Register Scratch2Reg =
MI.getOperand(2).getReg();
640 BuildMI(LoopHeadMBB,
DL,
TII->get(getLRForRMW32(Ordering, STI)), DestReg)
642 BuildMI(LoopHeadMBB,
DL,
TII->get(RISCV::AND), Scratch2Reg)
645 BuildMI(LoopHeadMBB,
DL,
TII->get(RISCV::ADDI), Scratch1Reg)
653 insertSext(
TII,
DL, LoopHeadMBB, Scratch2Reg,
MI.getOperand(6).getReg());
661 insertSext(
TII,
DL, LoopHeadMBB, Scratch2Reg,
MI.getOperand(6).getReg());
686 insertMaskedMerge(
TII,
DL, LoopIfBodyMBB, Scratch1Reg, DestReg, IncrReg,
687 MaskReg, Scratch1Reg);
692 BuildMI(LoopTailMBB,
DL,
TII->get(getSCForRMW32(Ordering, STI)), Scratch1Reg)
701bool RISCVExpandAtomicPseudo::expandAtomicMinMaxOp(
706 if (STI->hasPermissiveZalrsc() && STI->hasStdExtZbb() && !IsMasked)
707 return expandAtomicBinOp(
MBB,
MBBI, BinOp, IsMasked, Width, NextMBBI);
718 MF->
insert(++
MBB.getIterator(), LoopHeadMBB);
731 MBB.addSuccessor(LoopHeadMBB);
734 doAtomicMinMaxOpExpansion(
TII,
MI,
DL, &
MBB, LoopHeadMBB, LoopIfBodyMBB,
735 LoopTailMBB, DoneMBB, BinOp, Width, STI);
737 doMaskedAtomicMinMaxOpExpansion(
TII,
MI,
DL, &
MBB, LoopHeadMBB,
738 LoopIfBodyMBB, LoopTailMBB, DoneMBB, BinOp,
741 NextMBBI =
MBB.end();
742 MI.eraseFromParent();
777 if (
MBBI ==
E ||
MBBI->getOpcode() != RISCV::AND)
781 if (!(ANDOp1 == DestReg && ANDOp2 == MaskReg) &&
782 !(ANDOp1 == MaskReg && ANDOp2 == DestReg))
785 DestReg =
MBBI->getOperand(0).getReg();
791 if (
MBBI ==
E ||
MBBI->getOpcode() != RISCV::BNE)
795 if (!(BNEOp0 == DestReg && BNEOp1 == CmpValReg) &&
796 !(BNEOp0 == CmpValReg && BNEOp1 == DestReg))
801 if (BNEOp0 == DestReg && !
MBBI->getOperand(0).isKill())
803 if (BNEOp1 == DestReg && !
MBBI->getOperand(1).isKill())
808 LoopHeadBNETarget =
MBBI->getOperand(2).getMBB();
813 MBB.removeSuccessor(LoopHeadBNETarget);
814 for (
auto *
MI : ToErase)
815 MI->eraseFromParent();
819bool RISCVExpandAtomicPseudo::expandAtomicCmpXchg(
830 Register ScratchReg =
MI.getOperand(1).getReg();
832 Register CmpValReg =
MI.getOperand(3).getReg();
833 Register NewValReg =
MI.getOperand(4).getReg();
837 tryToFoldBNEOnCmpXchgResult(
MBB, std::next(
MBBI), DestReg, CmpValReg, MaskReg,
841 MF->
insert(++
MBB.getIterator(), LoopHeadMBB);
852 MBB.addSuccessor(LoopHeadMBB);
861 BuildMI(LoopHeadMBB,
DL,
TII->get(getLRForRMW(Ordering, Width, STI)),
867 .
addMBB(LoopHeadBNETarget);
871 BuildMI(LoopTailMBB,
DL,
TII->get(getSCForRMW(Ordering, Width, STI)),
885 BuildMI(LoopHeadMBB,
DL,
TII->get(getLRForRMW(Ordering, Width, STI)),
888 BuildMI(LoopHeadMBB,
DL,
TII->get(RISCV::AND), ScratchReg)
894 .
addMBB(LoopHeadBNETarget);
902 insertMaskedMerge(
TII,
DL, LoopTailMBB, ScratchReg, DestReg, NewValReg,
903 MaskReg, ScratchReg);
904 BuildMI(LoopTailMBB,
DL,
TII->get(getSCForRMW(Ordering, Width, STI)),
914 NextMBBI =
MBB.end();
915 MI.eraseFromParent();
931 return new RISCVExpandAtomicPseudo();
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.
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
#define RISCV_EXPAND_ATOMIC_PSEUDO_NAME
static unsigned getInstSizeInBytes(const MachineInstr &MI, const SystemZInstrInfo *TII)
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.
const RISCVInstrInfo * getInstrInfo() const override
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createRISCVExpandAtomicPseudoPass()
IterT skipDebugInstructionsForward(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It until it points to a non-debug instruction or to End and return the resulting iterator.
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().