[llvm] [PowerPC][NFC]Update EmitInstrWithCustomInserter to use switch (PR #196114)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 6 09:44:52 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-powerpc
Author: Lei Huang (lei137)
<details>
<summary>Changes</summary>
Currently PPCTargetLowering::EmitInstrWithCustomInserter() uses a large if/else-if structure. Update to use switch and
move ATOMIC_CMP_SWAP and SELECT code to helper functions for better readability and maintenance.
---
Patch is 41.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/196114.diff
1 Files Affected:
- (modified) llvm/lib/Target/PowerPC/PPCISelLowering.cpp (+558-438)
``````````diff
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 407093fd2b849..e959100d713dd 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -13854,8 +13854,13 @@ PPCTargetLowering::emitProbedAlloca(MachineInstr &MI,
return TailMBB;
}
-static bool IsSelectCC(MachineInstr &MI) {
- switch (MI.getOpcode()) {
+/// Check if the opcode is a SELECT or SELECT_CC variant.
+/// @param Opcode The opcode to check
+/// @param CheckOnlyCC If true, only return true for SELECT_CC variants;
+/// if false, return true for both SELECT and SELECT_CC
+static bool IsSelect(unsigned Opcode, bool CheckOnlyCC = false) {
+ switch (Opcode) {
+ // SELECT_CC variants - always return true
case PPC::SELECT_CC_I4:
case PPC::SELECT_CC_I8:
case PPC::SELECT_CC_F4:
@@ -13868,13 +13873,7 @@ static bool IsSelectCC(MachineInstr &MI) {
case PPC::SELECT_CC_SPE4:
case PPC::SELECT_CC_SPE:
return true;
- default:
- return false;
- }
-}
-
-static bool IsSelect(MachineInstr &MI) {
- switch (MI.getOpcode()) {
+ // SELECT variants - only return true if CheckOnlyCC is false
case PPC::SELECT_I4:
case PPC::SELECT_I8:
case PPC::SELECT_F4:
@@ -13886,49 +13885,25 @@ static bool IsSelect(MachineInstr &MI) {
case PPC::SELECT_VSFRC:
case PPC::SELECT_VSSRC:
case PPC::SELECT_VSRC:
- return true;
+ return !CheckOnlyCC; // true if checking all SELECTs, false if only CC
default:
return false;
}
}
+static bool IsSelectCC(unsigned Opcode) { return IsSelect(Opcode, true); }
-MachineBasicBlock *
-PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
- MachineBasicBlock *BB) const {
- if (MI.getOpcode() == TargetOpcode::STACKMAP ||
- MI.getOpcode() == TargetOpcode::PATCHPOINT) {
- if (Subtarget.is64BitELFABI() &&
- MI.getOpcode() == TargetOpcode::PATCHPOINT &&
- !Subtarget.isUsingPCRelativeCalls()) {
- // Call lowering should have added an r2 operand to indicate a dependence
- // on the TOC base pointer value. It can't however, because there is no
- // way to mark the dependence as implicit there, and so the stackmap code
- // will confuse it with a regular operand. Instead, add the dependence
- // here.
- MI.addOperand(MachineOperand::CreateReg(PPC::X2, false, true));
- }
-
- return emitPatchPoint(MI, BB);
- }
-
- if (MI.getOpcode() == PPC::EH_SjLj_SetJmp32 ||
- MI.getOpcode() == PPC::EH_SjLj_SetJmp64) {
- return emitEHSjLjSetJmp(MI, BB);
- } else if (MI.getOpcode() == PPC::EH_SjLj_LongJmp32 ||
- MI.getOpcode() == PPC::EH_SjLj_LongJmp64) {
- return emitEHSjLjLongJmp(MI, BB);
- }
-
- const TargetInstrInfo *TII = Subtarget.getInstrInfo();
-
- // To "insert" these instructions we actually have to insert their
- // control-flow patterns.
- const BasicBlock *LLVM_BB = BB->getBasicBlock();
- MachineFunction::iterator It = ++BB->getIterator();
-
- MachineFunction *F = BB->getParent();
- MachineRegisterInfo &MRI = F->getRegInfo();
-
+/// Emit SELECT instruction, using ISEL if available, otherwise use
+/// branch-based control flow.
+///
+/// For targets with ISEL support (SELECT_CC_I4/I8, SELECT_I4/I8), this
+/// generates a single ISEL instruction. Otherwise, it creates a
+/// branch-based control flow pattern with PHI nodes.
+static MachineBasicBlock *emitSelect(MachineInstr &MI, MachineBasicBlock *BB,
+ const TargetInstrInfo *TII,
+ const PPCSubtarget &Subtarget) {
+ assert(IsSelect(MI.getOpcode()) && "Instruction must be a SELECT variant");
+
+ // Check if we can use ISEL for this SELECT
if (Subtarget.hasISEL() &&
(MI.getOpcode() == PPC::SELECT_CC_I4 ||
MI.getOpcode() == PPC::SELECT_CC_I8 ||
@@ -13944,74 +13919,424 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
DebugLoc dl = MI.getDebugLoc();
TII->insertSelect(*BB, MI, dl, MI.getOperand(0).getReg(), Cond,
MI.getOperand(2).getReg(), MI.getOperand(3).getReg());
- } else if (IsSelectCC(MI) || IsSelect(MI)) {
- // The incoming instruction knows the destination vreg to set, the
- // condition code register to branch on, the true/false values to
- // select between, and a branch opcode to use.
-
- // thisMBB:
- // ...
- // TrueVal = ...
- // cmpTY ccX, r1, r2
- // bCC sinkMBB
- // fallthrough --> copy0MBB
- MachineBasicBlock *thisMBB = BB;
- MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
- MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
- DebugLoc dl = MI.getDebugLoc();
- F->insert(It, copy0MBB);
- F->insert(It, sinkMBB);
+ MI.eraseFromParent();
+ return BB;
+ }
- if (isPhysRegUsedAfter(PPC::CARRY, MI.getIterator())) {
- copy0MBB->addLiveIn(PPC::CARRY);
- sinkMBB->addLiveIn(PPC::CARRY);
- }
+ // Fall back to branch-based SELECT implementation
+ MachineFunction *F = BB->getParent();
+ const BasicBlock *LLVM_BB = BB->getBasicBlock();
+ MachineFunction::iterator It = ++BB->getIterator();
+ DebugLoc dl = MI.getDebugLoc();
- // Set the call frame size on entry to the new basic blocks.
- // See https://reviews.llvm.org/D156113.
- unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
- copy0MBB->setCallFrameSize(CallFrameSize);
- sinkMBB->setCallFrameSize(CallFrameSize);
+ MachineBasicBlock *thisMBB = BB;
+ MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
+ F->insert(It, copy0MBB);
+ F->insert(It, sinkMBB);
- // Transfer the remainder of BB and its successor edges to sinkMBB.
- sinkMBB->splice(sinkMBB->begin(), BB,
- std::next(MachineBasicBlock::iterator(MI)), BB->end());
- sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
+ if (isPhysRegUsedAfter(PPC::CARRY, MI.getIterator())) {
+ copy0MBB->addLiveIn(PPC::CARRY);
+ sinkMBB->addLiveIn(PPC::CARRY);
+ }
- // Next, add the true and fallthrough blocks as its successors.
- BB->addSuccessor(copy0MBB);
- BB->addSuccessor(sinkMBB);
+ // Set the call frame size on entry to the new basic blocks.
+ unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
+ copy0MBB->setCallFrameSize(CallFrameSize);
+ sinkMBB->setCallFrameSize(CallFrameSize);
- if (IsSelect(MI)) {
- BuildMI(BB, dl, TII->get(PPC::BC))
- .addReg(MI.getOperand(1).getReg())
- .addMBB(sinkMBB);
- } else {
- unsigned SelectPred = MI.getOperand(4).getImm();
- BuildMI(BB, dl, TII->get(PPC::BCC))
- .addImm(SelectPred)
- .addReg(MI.getOperand(1).getReg())
- .addMBB(sinkMBB);
- }
+ // Transfer the remainder of BB and its successor edges to sinkMBB.
+ sinkMBB->splice(sinkMBB->begin(), BB,
+ std::next(MachineBasicBlock::iterator(MI)), BB->end());
+ sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
- // copy0MBB:
- // %FalseValue = ...
- // # fallthrough to sinkMBB
- BB = copy0MBB;
+ // Add successors
+ BB->addSuccessor(copy0MBB);
+ BB->addSuccessor(sinkMBB);
- // Update machine-CFG edges
- BB->addSuccessor(sinkMBB);
+ // Build branch instruction
+ if (IsSelectCC(MI.getOpcode()))
+ BuildMI(BB, dl, TII->get(PPC::BCC))
+ .addImm(MI.getOperand(4).getImm())
+ .addReg(MI.getOperand(1).getReg())
+ .addMBB(sinkMBB);
+ else
+ BuildMI(BB, dl, TII->get(PPC::BC))
+ .addReg(MI.getOperand(1).getReg())
+ .addMBB(sinkMBB);
+
+ // copy0MBB: fallthrough to sinkMBB
+ BB = copy0MBB;
+ BB->addSuccessor(sinkMBB);
+
+ // sinkMBB: PHI instruction
+ BB = sinkMBB;
+ BuildMI(*BB, BB->begin(), dl, TII->get(PPC::PHI), MI.getOperand(0).getReg())
+ .addReg(MI.getOperand(3).getReg())
+ .addMBB(copy0MBB)
+ .addReg(MI.getOperand(2).getReg())
+ .addMBB(thisMBB);
+ MI.eraseFromParent();
+ return BB;
+}
+
+/// Helper function to create basic blocks for atomic compare-and-swap.
+/// Creates three basic blocks (loop1MBB, loop2MBB, exitMBB) and sets up
+/// the control flow structure common to both hardware and software
+/// implementations of atomic compare-and-swap operations.
+static void createAtomicLoopBlocks(MachineFunction *F, MachineBasicBlock *BB,
+ MachineBasicBlock *&loop1MBB,
+ MachineBasicBlock *&loop2MBB,
+ MachineBasicBlock *&exitMBB,
+ MachineInstr &MI,
+ MachineFunction::iterator It) {
+ const BasicBlock *LLVM_BB = BB->getBasicBlock();
+ loop1MBB = F->CreateMachineBasicBlock(LLVM_BB);
+ loop2MBB = F->CreateMachineBasicBlock(LLVM_BB);
+ exitMBB = F->CreateMachineBasicBlock(LLVM_BB);
+ F->insert(It, loop1MBB);
+ F->insert(It, loop2MBB);
+ F->insert(It, exitMBB);
+ exitMBB->splice(exitMBB->begin(), BB,
+ std::next(MachineBasicBlock::iterator(MI)), BB->end());
+ exitMBB->transferSuccessorsAndUpdatePHIs(BB);
+ BB->addSuccessor(loop1MBB);
+}
+
+/// Emit hardware-supported atomic compare-and-swap for I32/I64 and I8/I16
+/// with partword atomic support.
+///
+/// This uses native PowerPC atomic instructions (LBARX/LHARX/LWARX/LDARX for
+/// load-and-reserve, STBCX/STHCX/STWCX/STDCX for store-conditional) to
+/// implement atomic compare-and-swap at byte, halfword, word, or doubleword
+/// granularity.
+///
+/// Control flow:
+/// thisMBB -> loop1MBB -> loop2MBB -> exitMBB
+/// | |
+/// +------------+
+///
+/// loop1MBB:
+/// - Load-and-reserve from memory
+/// - Compare loaded value with expected old value
+/// - Branch to exitMBB if not equal (CAS failed)
+/// loop2MBB:
+/// - Store-conditional new value to memory
+/// - Branch back to loop1MBB if store failed (retry)
+/// - Fall through to exitMBB on success
+static MachineBasicBlock *
+emitAtomicCmpSwapHardware(MachineInstr &MI, MachineBasicBlock *BB,
+ const TargetInstrInfo *TII,
+ const PPCSubtarget &Subtarget) {
+ MachineFunction *F = BB->getParent();
+ MachineFunction::iterator It = ++BB->getIterator();
+
+ bool is64bit = MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64;
+
+ unsigned LoadMnemonic = PPC::LDARX;
+ unsigned StoreMnemonic = PPC::STDCX;
+ switch (MI.getOpcode()) {
+ default:
+ llvm_unreachable("Compare and swap of unknown size");
+ case PPC::ATOMIC_CMP_SWAP_I8:
+ LoadMnemonic = PPC::LBARX;
+ StoreMnemonic = PPC::STBCX;
+ assert(Subtarget.hasPartwordAtomics() && "No support partword atomics.");
+ break;
+ case PPC::ATOMIC_CMP_SWAP_I16:
+ LoadMnemonic = PPC::LHARX;
+ StoreMnemonic = PPC::STHCX;
+ assert(Subtarget.hasPartwordAtomics() && "No support partword atomics.");
+ break;
+ case PPC::ATOMIC_CMP_SWAP_I32:
+ LoadMnemonic = PPC::LWARX;
+ StoreMnemonic = PPC::STWCX;
+ break;
+ case PPC::ATOMIC_CMP_SWAP_I64:
+ LoadMnemonic = PPC::LDARX;
+ StoreMnemonic = PPC::STDCX;
+ break;
+ }
+
+ MachineRegisterInfo &RegInfo = F->getRegInfo();
+ Register dest = MI.getOperand(0).getReg();
+ Register ptrA = MI.getOperand(1).getReg();
+ Register ptrB = MI.getOperand(2).getReg();
+ Register oldval = MI.getOperand(3).getReg();
+ Register newval = MI.getOperand(4).getReg();
+ DebugLoc dl = MI.getDebugLoc();
+
+ MachineBasicBlock *loop1MBB, *loop2MBB, *exitMBB;
+ createAtomicLoopBlocks(F, BB, loop1MBB, loop2MBB, exitMBB, MI, It);
+
+ Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
+
+ // loop1MBB:
+ // l[bhwd]arx dest, ptr
+ // cmp[wd] dest, oldval
+ // bne- exitBB
+ BB = loop1MBB;
+ BuildMI(BB, dl, TII->get(LoadMnemonic), dest).addReg(ptrA).addReg(ptrB);
+ BuildMI(BB, dl, TII->get(is64bit ? PPC::CMPD : PPC::CMPW), CrReg)
+ .addReg(dest)
+ .addReg(oldval);
+ BuildMI(BB, dl, TII->get(PPC::BCC))
+ .addImm(PPC::PRED_NE_MINUS)
+ .addReg(CrReg)
+ .addMBB(exitMBB);
+ BB->addSuccessor(loop2MBB);
+ BB->addSuccessor(exitMBB);
+
+ // loop2MBB:
+ // st[bhwd]cx. newval, ptr
+ // bne- loopMBB
+ // b exitBB
+ BB = loop2MBB;
+ BuildMI(BB, dl, TII->get(StoreMnemonic))
+ .addReg(newval)
+ .addReg(ptrA)
+ .addReg(ptrB);
+ BuildMI(BB, dl, TII->get(PPC::BCC))
+ .addImm(PPC::PRED_NE_MINUS)
+ .addReg(PPC::CR0)
+ .addMBB(loop1MBB);
+ BuildMI(BB, dl, TII->get(PPC::B)).addMBB(exitMBB);
+ BB->addSuccessor(loop1MBB);
+ BB->addSuccessor(exitMBB);
+
+ return exitMBB;
+}
+
+/// Emit software-emulated atomic compare-and-swap for I8/I16 without
+/// hardware partword atomic support.
+///
+/// This emulates byte/halfword atomic operations using word (32-bit) atomic
+/// instructions. Since PowerPC atomic instructions work at word granularity,
+/// we must:
+/// 1. Align the pointer to a word boundary
+/// 2. Calculate the bit shift for the target byte/halfword within the word
+/// 3. Create masks to isolate the target byte/halfword
+/// 4. Shift old/new values into the correct bit position
+/// 5. Use LWARX/STWCX on the full word
+/// 6. Mask and merge to preserve other bytes in the word
+/// 7. Extract and shift the result back
+///
+/// Control flow:
+/// thisMBB -> loop1MBB -> loop2MBB -> exitMBB
+/// | |
+/// +------------+
+///
+/// loop1MBB:
+/// - LWARX: Load-and-reserve full word
+/// - Mask to extract target byte/halfword
+/// - Compare with expected old value
+/// - Branch to exitMBB if not equal (CAS failed)
+/// loop2MBB:
+/// - Merge new value with other bytes in the word
+/// - STWCX: Store-conditional full word
+/// - Branch back to loop1MBB if store failed (retry)
+/// - Fall through to exitMBB on success
+/// exitMBB:
+/// - Extract and return the loaded value
+static MachineBasicBlock *
+emitAtomicCmpSwapSoftware(MachineInstr &MI, MachineBasicBlock *BB,
+ const TargetInstrInfo *TII,
+ const PPCSubtarget &Subtarget) {
+ MachineFunction *F = BB->getParent();
+ MachineFunction::iterator It = ++BB->getIterator();
+
+ bool is64bit = Subtarget.isPPC64();
+ bool isLittleEndian = Subtarget.isLittleEndian();
+ bool is8bit = MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8;
- // sinkMBB:
- // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
- // ...
- BB = sinkMBB;
- BuildMI(*BB, BB->begin(), dl, TII->get(PPC::PHI), MI.getOperand(0).getReg())
- .addReg(MI.getOperand(3).getReg())
- .addMBB(copy0MBB)
- .addReg(MI.getOperand(2).getReg())
- .addMBB(thisMBB);
- } else if (MI.getOpcode() == PPC::ReadTB) {
+ Register dest = MI.getOperand(0).getReg();
+ Register ptrA = MI.getOperand(1).getReg();
+ Register ptrB = MI.getOperand(2).getReg();
+ Register oldval = MI.getOperand(3).getReg();
+ Register newval = MI.getOperand(4).getReg();
+ DebugLoc dl = MI.getDebugLoc();
+
+ MachineBasicBlock *loop1MBB, *loop2MBB, *exitMBB;
+ createAtomicLoopBlocks(F, BB, loop1MBB, loop2MBB, exitMBB, MI, It);
+
+ MachineRegisterInfo &RegInfo = F->getRegInfo();
+ const TargetRegisterClass *RC =
+ is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
+ const TargetRegisterClass *GPRC = &PPC::GPRCRegClass;
+
+ // Lambda to create virtual registers
+ auto createVReg = [&](const TargetRegisterClass *RC) {
+ return RegInfo.createVirtualRegister(RC);
+ };
+
+ Register PtrReg = createVReg(RC);
+ Register Shift1Reg = createVReg(GPRC);
+ Register ShiftReg = isLittleEndian ? Shift1Reg : createVReg(GPRC);
+ Register NewVal2Reg = createVReg(GPRC);
+ Register NewVal3Reg = createVReg(GPRC);
+ Register OldVal2Reg = createVReg(GPRC);
+ Register OldVal3Reg = createVReg(GPRC);
+ Register MaskReg = createVReg(GPRC);
+ Register Mask2Reg = createVReg(GPRC);
+ Register Mask3Reg = createVReg(GPRC);
+ Register Tmp2Reg = createVReg(GPRC);
+ Register Tmp4Reg = createVReg(GPRC);
+ Register TmpDestReg = createVReg(GPRC);
+ Register TmpReg = createVReg(GPRC);
+ Register ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
+ Register CrReg = createVReg(&PPC::CRRCRegClass);
+
+ // Compute aligned pointer and shift amount
+ Register Ptr1Reg;
+ if (ptrA != ZeroReg) {
+ Ptr1Reg = createVReg(RC);
+ BuildMI(BB, dl, TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
+ .addReg(ptrA)
+ .addReg(ptrB);
+ } else {
+ Ptr1Reg = ptrB;
+ }
+
+ BuildMI(BB, dl, TII->get(PPC::RLWINM), Shift1Reg)
+ .addReg(Ptr1Reg, {}, is64bit ? PPC::sub_32 : 0)
+ .addImm(3)
+ .addImm(27)
+ .addImm(is8bit ? 28 : 27);
+ if (!isLittleEndian)
+ BuildMI(BB, dl, TII->get(PPC::XORI), ShiftReg)
+ .addReg(Shift1Reg)
+ .addImm(is8bit ? 24 : 16);
+ if (is64bit)
+ BuildMI(BB, dl, TII->get(PPC::RLDICR), PtrReg)
+ .addReg(Ptr1Reg)
+ .addImm(0)
+ .addImm(61);
+ else
+ BuildMI(BB, dl, TII->get(PPC::RLWINM), PtrReg)
+ .addReg(Ptr1Reg)
+ .addImm(0)
+ .addImm(0)
+ .addImm(29);
+
+ // Prepare masked values
+ BuildMI(BB, dl, TII->get(PPC::SLW), NewVal2Reg)
+ .addReg(newval)
+ .addReg(ShiftReg);
+ BuildMI(BB, dl, TII->get(PPC::SLW), OldVal2Reg)
+ .addReg(oldval)
+ .addReg(ShiftReg);
+ if (is8bit)
+ BuildMI(BB, dl, TII->get(PPC::LI), Mask2Reg).addImm(255);
+ else {
+ BuildMI(BB, dl, TII->get(PPC::LI), Mask3Reg).addImm(0);
+ BuildMI(BB, dl, TII->get(PPC::ORI), Mask2Reg)
+ .addReg(Mask3Reg)
+ .addImm(65535);
+ }
+ BuildMI(BB, dl, TII->get(PPC::SLW), MaskReg)
+ .addReg(Mask2Reg)
+ .addReg(ShiftReg);
+ BuildMI(BB, dl, TII->get(PPC::AND), NewVal3Reg)
+ .addReg(NewVal2Reg)
+ .addReg(MaskReg);
+ BuildMI(BB, dl, TII->get(PPC::AND), OldVal3Reg)
+ .addReg(OldVal2Reg)
+ .addReg(MaskReg);
+
+ // loop1MBB:
+ // lwarx tmpDest, ptr
+ // and tmp, tmpDest, mask
+ // cmpw tmp, oldval3
+ // bne- exitBB
+ BB = loop1MBB;
+ BuildMI(BB, dl, TII->get(PPC::LWARX), TmpDestReg)
+ .addReg(ZeroReg)
+ .addReg(PtrReg);
+ BuildMI(BB, dl, TII->get(PPC::AND), TmpReg)
+ .addReg(TmpDestReg)
+ .addReg(MaskReg);
+ BuildMI(BB, dl, TII->get(PPC::CMPW), CrReg).addReg(TmpReg).addReg(OldVal3Reg);
+ BuildMI(BB, dl, TII->get(PPC::BCC))
+ .addImm(PPC::PRED_NE)
+ .addReg(CrReg)
+ .addMBB(exitMBB);
+ BB->addSuccessor(loop2MBB);
+ BB->addSuccessor(exitMBB);
+
+ // loop2MBB:
+ // andc tmp2, tmpDest, mask
+ // or tmp4, tmp2, newval3
+ // stwcx. tmp4, ptr
+ // bne- loop1MBB
+ // b exitBB
+ BB = loop2MBB;
+ BuildMI(BB, dl, TII->get(PPC::ANDC), Tmp2Reg)
+ .addReg(TmpDestReg)
+ .addReg(MaskReg);
+ BuildMI(BB, dl, TII->get(PPC::OR), Tmp4Reg)
+ .addReg(Tmp2Reg)
+ .addReg(NewVal3Reg);
+ BuildMI(BB, dl, TII->get(PPC::STWCX))
+ .addReg(Tmp4Reg)
+ .addReg(ZeroReg)
+ .addReg(PtrReg);
+ BuildMI(BB, dl, TII->get(PPC::BCC))
+ .addImm(PPC::PRED_NE)
+ .addReg(PPC::CR0)
+ .addMBB(loop1MBB);
+ BuildMI(BB, dl, TII->get(PPC::B)).addMBB(exitMBB);
+ BB->addSuccessor(loop1MBB);
+ BB->addSuccessor(exitMBB);
+
+ // exitMBB:
+ // srw dest, tmpDest, shift
+ BB = exitMBB;
+ BuildMI(*BB, BB->begin(), dl, TII->get(PPC::SRW), dest)
+ .addReg(TmpReg)
+ .addReg(ShiftReg);
+
+ return BB;
+}
+
+MachineBasicBlock *
+PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
+ MachineBasicBlock *BB) const {
+ const TargetInstrInfo *TII = Subtarget.getInstrInfo();
+
+ // To "insert" these instructions we actually have to insert their
+ // control-flow patterns.
+ const BasicBlock *LLVM_BB = BB->getBasicBlock();
+ MachineFunction::iterator It = ++BB->getIterator();
+
+ MachineFunction *F = BB->getParent();
+ MachineRegisterInfo &MRI = F->getRegInfo();
+
+ // Handle SELECT with ISEL support first (before generic SELECT handling)
+ if (IsSelect(MI.getOpcode()))
+ return emitSelect(MI, BB, TII, Subtarget);
+
+ switch (MI.getOpcode()) {
+ case TargetOpcode::STACKMAP:
+ return emitPatchPoint(MI, BB);
+ case TargetOpcode::PATCHPOINT:
+ // Call lowering should have added an r2 operand to indicate a dependence
+ // on th...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/196114
More information about the llvm-commits
mailing list