[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