[llvm] [PowerPC][NFC]Update EmitInstrWithCustomInserter to use switch (PR #196114)

Lei Huang via llvm-commits llvm-commits at lists.llvm.org
Wed May 6 09:44:03 PDT 2026


https://github.com/lei137 created https://github.com/llvm/llvm-project/pull/196114

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. 

>From d75045b688a3b2fad4df03f47438e9d13ab31c54 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Wed, 6 May 2026 10:36:35 -0400
Subject: [PATCH 1/2] refactor to one big switch move ATOMIC_CMP_SWAP code to
 helper functions move selectCC code to helper function

---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 996 +++++++++++---------
 1 file changed, 558 insertions(+), 438 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 407093fd2b849..b4bb903f80ffe 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 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.
+    if (Subtarget.is64BitELFABI() && !Subtarget.isUsingPCRelativeCalls())
+      MI.addOperand(MachineOperand::CreateReg(PPC::X2, false, true));
+    return emitPatchPoint(MI, BB);
+
+  case PPC::EH_SjLj_SetJmp32:
+  case PPC::EH_SjLj_SetJmp64:
+    return emitEHSjLjSetJmp(MI, BB);
+
+  case PPC::EH_SjLj_LongJmp32:
+  case PPC::EH_SjLj_LongJmp64:
+    return emitEHSjLjLongJmp(MI, BB);
+
+  case PPC::ReadTB: {
     // To read the 64-bit time-base register on a 32-bit target, we read the
     // two halves. Should the counter have wrapped while it was being read, we
     // need to try again.
@@ -14059,351 +14384,123 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
 
     BB->addSuccessor(readMBB);
     BB->addSuccessor(sinkMBB);
-  } else if (MI.getOpcode() == PPC::ATOMIC_LOAD_ADD_NOWP)
+    break;
+  }
+  case PPC::ATOMIC_LOAD_ADD_NOWP
     BB = EmitPartwordAtomicBinary(MI, BB, PPC::ADD4);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_ADD)
+    break;
+  case PPC::ATOMIC_LOAD_ADD:
     BB = EmitAtomicBinary(MI, BB, PPC::ADD4);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_ADD_I64)
+    break;
+  case PPC::ATOMIC_LOAD_ADD_I64:
     BB = EmitAtomicBinary(MI, BB, PPC::ADD8);
-
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_AND_NOWP)
+    break;
+  case PPC::ATOMIC_LOAD_AND_NOWP:
     BB = EmitPartwordAtomicBinary(MI, BB, PPC::AND);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_AND)
+    break;
+  case PPC::ATOMIC_LOAD_AND:
     BB = EmitAtomicBinary(MI, BB, PPC::AND);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_AND_I64)
+    break;
+  case PPC::ATOMIC_LOAD_AND_I64:
     BB = EmitAtomicBinary(MI, BB, PPC::AND8);
-
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_OR_NOWP)
+    break;
+  case PPC::ATOMIC_LOAD_OR_NOWP:
     BB = EmitPartwordAtomicBinary(MI, BB, PPC::OR);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_OR)
+    break;
+  case PPC::ATOMIC_LOAD_OR:
     BB = EmitAtomicBinary(MI, BB, PPC::OR);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_OR_I64)
+    break;
+  case PPC::ATOMIC_LOAD_OR_I64:
     BB = EmitAtomicBinary(MI, BB, PPC::OR8);
-
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_XOR_NOWP)
+    break;
+  case PPC::ATOMIC_LOAD_XOR_NOWP:
     BB = EmitPartwordAtomicBinary(MI, BB, PPC::XOR);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_XOR)
+    break;
+  case PPC::ATOMIC_LOAD_XOR:
     BB = EmitAtomicBinary(MI, BB, PPC::XOR);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_XOR_I64)
+    break;
+  case PPC::ATOMIC_LOAD_XOR_I64:
     BB = EmitAtomicBinary(MI, BB, PPC::XOR8);
-
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_NAND_NOWP)
+    break;
+  case PPC::ATOMIC_LOAD_NAND_NOWP:
     BB = EmitPartwordAtomicBinary(MI, BB, PPC::NAND);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_NAND)
+    break;
+  case PPC::ATOMIC_LOAD_NAND:
     BB = EmitAtomicBinary(MI, BB, PPC::NAND);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_NAND_I64)
+    break;
+  case PPC::ATOMIC_LOAD_NAND_I64:
     BB = EmitAtomicBinary(MI, BB, PPC::NAND8);
-
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_NOWP)
+    break;
+  case PPC::ATOMIC_LOAD_SUB_NOWP:
     BB = EmitPartwordAtomicBinary(MI, BB, PPC::SUBF);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_SUB)
+    break;
+  case PPC::ATOMIC_LOAD_SUB:
     BB = EmitAtomicBinary(MI, BB, PPC::SUBF);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_I64)
+    break;
+  case PPC::ATOMIC_LOAD_SUB_I64:
     BB = EmitAtomicBinary(MI, BB, PPC::SUBF8);
-
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_NOWP)
+    break;
+  case PPC::ATOMIC_LOAD_MIN_NOWP:
     BB = EmitPartwordAtomicBinary(MI, BB, 0, PPC::CMPW, PPC::PRED_LT);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MIN)
+    break;
+  case PPC::ATOMIC_LOAD_MIN:
     BB = EmitAtomicBinary(MI, BB, 0, PPC::CMPW, PPC::PRED_LT);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I64)
+    break;
+  case PPC::ATOMIC_LOAD_MIN_I64:
     BB = EmitAtomicBinary(MI, BB, 0, PPC::CMPD, PPC::PRED_LT);
-
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_NOWP)
+    break;
+  case PPC::ATOMIC_LOAD_MAX_NOWP:
     BB = EmitPartwordAtomicBinary(MI, BB, 0, PPC::CMPW, PPC::PRED_GT);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MAX)
+    break;
+  case PPC::ATOMIC_LOAD_MAX:
     BB = EmitAtomicBinary(MI, BB, 0, PPC::CMPW, PPC::PRED_GT);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I64)
+    break;
+  case PPC::ATOMIC_LOAD_MAX_I64:
     BB = EmitAtomicBinary(MI, BB, 0, PPC::CMPD, PPC::PRED_GT);
-
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_NOWP)
+    break;
+  case PPC::ATOMIC_LOAD_UMIN_NOWP:
     BB = EmitPartwordAtomicBinary(MI, BB, 0, PPC::CMPLW, PPC::PRED_LT);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN)
+    break;
+  case PPC::ATOMIC_LOAD_UMIN:
     BB = EmitAtomicBinary(MI, BB, 0, PPC::CMPLW, PPC::PRED_LT);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I64)
+    break;
+  case PPC::ATOMIC_LOAD_UMIN_I64:
     BB = EmitAtomicBinary(MI, BB, 0, PPC::CMPLD, PPC::PRED_LT);
-
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_NOWP)
+    break;
+  case PPC::ATOMIC_LOAD_UMAX_NOWP:
     BB = EmitPartwordAtomicBinary(MI, BB, 0, PPC::CMPLW, PPC::PRED_GT);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX)
+    break;
+  case PPC::ATOMIC_LOAD_UMAX:
     BB = EmitAtomicBinary(MI, BB, 0, PPC::CMPLW, PPC::PRED_GT);
-  else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I64)
+    break;
+  case PPC::ATOMIC_LOAD_UMAX_I64:
     BB = EmitAtomicBinary(MI, BB, 0, PPC::CMPLD, PPC::PRED_GT);
-
-  else if (MI.getOpcode() == PPC::ATOMIC_SWAP_NOWP)
+    break;
+  case PPC::ATOMIC_SWAP_NOWP:
     BB = EmitPartwordAtomicBinary(MI, BB, 0);
-  else if (MI.getOpcode() == PPC::ATOMIC_SWAP ||
-           MI.getOpcode() == PPC::ATOMIC_SWAP_I64)
+    break;
+  case PPC::ATOMIC_SWAP:
+  case PPC::ATOMIC_SWAP_I64:
     BB = EmitAtomicBinary(MI, BB, 0);
-  else if (MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 ||
-           MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64 ||
-           (Subtarget.hasPartwordAtomics() &&
-            MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8) ||
-           (Subtarget.hasPartwordAtomics() &&
-            MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I16)) {
-    bool is64bit = MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64;
-
-    auto LoadMnemonic = PPC::LDARX;
-    auto 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 CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
-    Register oldval = MI.getOperand(3).getReg();
-    Register newval = MI.getOperand(4).getReg();
-    DebugLoc dl = MI.getDebugLoc();
-
-    MachineBasicBlock *loop1MBB = F->CreateMachineBasicBlock(LLVM_BB);
-    MachineBasicBlock *loop2MBB = F->CreateMachineBasicBlock(LLVM_BB);
-    MachineBasicBlock *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);
-
-    //  thisMBB:
-    //   ...
-    //   fallthrough --> loopMBB
-    BB->addSuccessor(loop1MBB);
-
-    // loop1MBB:
-    //   l[bhwd]arx dest, ptr
-    //   cmp[wd] dest, oldval
-    //   bne- exitBB
-    // loop2MBB:
-    //   st[bhwd]cx. newval, ptr
-    //   bne- loopMBB
-    //   b exitBB
-    // 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);
-
-    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);
-
-    //  exitMBB:
-    //   ...
-    BB = exitMBB;
-  } else if (MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8 ||
-             MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I16) {
-    // We must use 64-bit registers for addresses when targeting 64-bit,
-    // since we're actually doing arithmetic on them.  Other registers
-    // can be 32-bit.
-    bool is64bit = Subtarget.isPPC64();
-    bool isLittleEndian = Subtarget.isLittleEndian();
-    bool is8bit = MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8;
-
-    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 = F->CreateMachineBasicBlock(LLVM_BB);
-    MachineBasicBlock *loop2MBB = F->CreateMachineBasicBlock(LLVM_BB);
-    MachineBasicBlock *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);
-
-    MachineRegisterInfo &RegInfo = F->getRegInfo();
-    const TargetRegisterClass *RC =
-        is64bit ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
-    const TargetRegisterClass *GPRC = &PPC::GPRCRegClass;
-
-    Register PtrReg = RegInfo.createVirtualRegister(RC);
-    Register Shift1Reg = RegInfo.createVirtualRegister(GPRC);
-    Register ShiftReg =
-        isLittleEndian ? Shift1Reg : RegInfo.createVirtualRegister(GPRC);
-    Register NewVal2Reg = RegInfo.createVirtualRegister(GPRC);
-    Register NewVal3Reg = RegInfo.createVirtualRegister(GPRC);
-    Register OldVal2Reg = RegInfo.createVirtualRegister(GPRC);
-    Register OldVal3Reg = RegInfo.createVirtualRegister(GPRC);
-    Register MaskReg = RegInfo.createVirtualRegister(GPRC);
-    Register Mask2Reg = RegInfo.createVirtualRegister(GPRC);
-    Register Mask3Reg = RegInfo.createVirtualRegister(GPRC);
-    Register Tmp2Reg = RegInfo.createVirtualRegister(GPRC);
-    Register Tmp4Reg = RegInfo.createVirtualRegister(GPRC);
-    Register TmpDestReg = RegInfo.createVirtualRegister(GPRC);
-    Register Ptr1Reg;
-    Register TmpReg = RegInfo.createVirtualRegister(GPRC);
-    Register ZeroReg = is64bit ? PPC::ZERO8 : PPC::ZERO;
-    Register CrReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
-    //  thisMBB:
-    //   ...
-    //   fallthrough --> loopMBB
-    BB->addSuccessor(loop1MBB);
-
-    // The 4-byte load must be aligned, while a char or short may be
-    // anywhere in the word.  Hence all this nasty bookkeeping code.
-    //   add ptr1, ptrA, ptrB [copy if ptrA==0]
-    //   rlwinm shift1, ptr1, 3, 27, 28 [3, 27, 27]
-    //   xori shift, shift1, 24 [16]
-    //   rlwinm ptr, ptr1, 0, 0, 29
-    //   slw newval2, newval, shift
-    //   slw oldval2, oldval,shift
-    //   li mask2, 255 [li mask3, 0; ori mask2, mask3, 65535]
-    //   slw mask, mask2, shift
-    //   and newval3, newval2, mask
-    //   and oldval3, oldval2, mask
-    // loop1MBB:
-    //   lwarx tmpDest, ptr
-    //   and tmp, tmpDest, mask
-    //   cmpw tmp, oldval3
-    //   bne- exitBB
-    // loop2MBB:
-    //   andc tmp2, tmpDest, mask
-    //   or tmp4, tmp2, newval3
-    //   stwcx. tmp4, ptr
-    //   bne- loop1MBB
-    //   b exitBB
-    // exitBB:
-    //   srw dest, tmpDest, shift
-    if (ptrA != ZeroReg) {
-      Ptr1Reg = RegInfo.createVirtualRegister(RC);
-      BuildMI(BB, dl, TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg)
-          .addReg(ptrA)
-          .addReg(ptrB);
-    } else {
-      Ptr1Reg = ptrB;
-    }
-
-    // We need use 32-bit subregister to avoid mismatch register class in 64-bit
-    // mode.
-    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);
+    break;
+  case PPC::ATOMIC_CMP_SWAP_I32:
+  case PPC::ATOMIC_CMP_SWAP_I64:
+  case PPC::ATOMIC_CMP_SWAP_I8:
+  case PPC::ATOMIC_CMP_SWAP_I16: {
+    // Use hardware-supported atomic operations if available
+    bool useHardware = MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 ||
+                       MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I64 ||
+                       (Subtarget.hasPartwordAtomics() &&
+                        (MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I8 ||
+                         MI.getOpcode() == PPC::ATOMIC_CMP_SWAP_I16));
+
+    if (useHardware)
+      BB = emitAtomicCmpSwapHardware(MI, BB, TII, Subtarget);
     else
-      BuildMI(BB, dl, TII->get(PPC::RLWINM), PtrReg)
-          .addReg(Ptr1Reg)
-          .addImm(0)
-          .addImm(0)
-          .addImm(29);
-    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);
-
-    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);
-
-    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:
-    //   ...
-    BB = exitMBB;
-    BuildMI(*BB, BB->begin(), dl, TII->get(PPC::SRW), dest)
-        .addReg(TmpReg)
-        .addReg(ShiftReg);
-  } else if (MI.getOpcode() == PPC::FADDrtz) {
+      BB = emitAtomicCmpSwapSoftware(MI, BB, TII, Subtarget);
+    break;
+  }
+  case PPC::FADDrtz: {
     // This pseudo performs an FADD with rounding mode temporarily forced
     // to round-to-zero.  We emit this via custom inserter since the FPSCR
     // is not modeled at the SelectionDAG level.
@@ -14436,10 +14533,12 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
 
     // Restore FPSCR value.
     BuildMI(*BB, MI, dl, TII->get(PPC::MTFSFb)).addImm(1).addReg(MFFSReg);
-  } else if (MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT ||
-             MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT ||
-             MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8 ||
-             MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT8) {
+    break;
+  }
+  case PPC::ANDI_rec_1_EQ_BIT:
+  case PPC::ANDI_rec_1_GT_BIT:
+  case PPC::ANDI_rec_1_EQ_BIT8:
+  case PPC::ANDI_rec_1_GT_BIT8: {
     unsigned Opcode = (MI.getOpcode() == PPC::ANDI_rec_1_EQ_BIT8 ||
                        MI.getOpcode() == PPC::ANDI_rec_1_GT_BIT8)
                           ? PPC::ANDI8_rec
@@ -14458,7 +14557,9 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
     BuildMI(*BB, MI, Dl, TII->get(TargetOpcode::COPY),
             MI.getOperand(0).getReg())
         .addReg(IsEQ ? PPC::CR0EQ : PPC::CR0GT);
-  } else if (MI.getOpcode() == PPC::TCHECK_RET) {
+    break;
+  }
+  case PPC::TCHECK_RET: {
     DebugLoc Dl = MI.getDebugLoc();
     MachineRegisterInfo &RegInfo = F->getRegInfo();
     Register CRReg = RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
@@ -14466,14 +14567,18 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
     BuildMI(*BB, MI, Dl, TII->get(TargetOpcode::COPY),
             MI.getOperand(0).getReg())
         .addReg(CRReg);
-  } else if (MI.getOpcode() == PPC::TBEGIN_RET) {
+    break;
+  }
+  case PPC::TBEGIN_RET: {
     DebugLoc Dl = MI.getDebugLoc();
     unsigned Imm = MI.getOperand(1).getImm();
     BuildMI(*BB, MI, Dl, TII->get(PPC::TBEGIN)).addImm(Imm);
     BuildMI(*BB, MI, Dl, TII->get(TargetOpcode::COPY),
             MI.getOperand(0).getReg())
         .addReg(PPC::CR0EQ);
-  } else if (MI.getOpcode() == PPC::SETRNDi) {
+    break;
+  }
+  case PPC::SETRNDi: {
     DebugLoc dl = MI.getDebugLoc();
     Register OldFPSCRReg = MI.getOperand(0).getReg();
 
@@ -14500,7 +14605,9 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
     BuildMI(*BB, MI, dl, TII->get((Mode & 2) ? PPC::MTFSB1 : PPC::MTFSB0))
         .addImm(30)
         .addReg(PPC::RM, RegState::ImplicitDefine);
-  } else if (MI.getOpcode() == PPC::SETRND) {
+    break;
+  }
+  case PPC::SETRND: {
     DebugLoc dl = MI.getDebugLoc();
 
     // Copy register from F8RCRegClass::SrcReg to G8RCRegClass::DestReg
@@ -14609,7 +14716,9 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
       .addReg(NewFPSCRReg)
       .addImm(0)
       .addImm(0);
-  } else if (MI.getOpcode() == PPC::SETFLM) {
+    break;
+  }
+  case PPC::SETFLM: {
     DebugLoc Dl = MI.getDebugLoc();
 
     // Result of setflm is previous FPSCR content, so we need to save it first.
@@ -14626,10 +14735,13 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
         .addReg(NewFPSCRReg)
         .addImm(0)
         .addImm(0);
-  } else if (MI.getOpcode() == PPC::PROBED_ALLOCA_32 ||
-             MI.getOpcode() == PPC::PROBED_ALLOCA_64) {
+    break;
+  }
+  case PPC::PROBED_ALLOCA_32:
+  case PPC::PROBED_ALLOCA_64:
     return emitProbedAlloca(MI, BB);
-  } else if (MI.getOpcode() == PPC::SPLIT_QUADWORD) {
+
+  case PPC::SPLIT_QUADWORD: {
     DebugLoc DL = MI.getDebugLoc();
     Register Src = MI.getOperand(2).getReg();
     Register Lo = MI.getOperand(0).getReg();
@@ -14640,8 +14752,10 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
     BuildMI(*BB, MI, DL, TII->get(TargetOpcode::COPY))
         .addDef(Hi)
         .addUse(Src, {}, PPC::sub_gp8_x0);
-  } else if (MI.getOpcode() == PPC::LQX_PSEUDO ||
-             MI.getOpcode() == PPC::STQX_PSEUDO) {
+    break;
+  }
+  case PPC::LQX_PSEUDO:
+  case PPC::STQX_PSEUDO: {
     DebugLoc DL = MI.getDebugLoc();
     // Ptr is used as the ptr_rc_no_r0 part
     // of LQ/STQ's memory operand and adding result of RA and RB,
@@ -14658,8 +14772,10 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
         .addReg(Val, getDefRegState(MI.getOpcode() == PPC::LQX_PSEUDO))
         .addImm(0)
         .addReg(Ptr);
-  } else if (MI.getOpcode() == PPC::LWAT_PSEUDO ||
-             MI.getOpcode() == PPC::LDAT_PSEUDO) {
+    break;
+  }
+  case PPC::LWAT_PSEUDO:
+  case PPC::LDAT_PSEUDO: {
     DebugLoc DL = MI.getDebugLoc();
     Register DstReg = MI.getOperand(0).getReg();
     Register PtrReg = MI.getOperand(1).getReg();
@@ -14697,8 +14813,10 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
     else
       BuildMI(*BB, MI, DL, TII->get(TargetOpcode::COPY), DstReg)
           .addReg(Result64);
-  } else if (MI.getOpcode() == PPC::LWAT_COND_PSEUDO ||
-             MI.getOpcode() == PPC::LDAT_COND_PSEUDO) {
+    break;
+  }
+  case PPC::LWAT_COND_PSEUDO:
+  case PPC::LDAT_COND_PSEUDO: {
     DebugLoc DL = MI.getDebugLoc();
     Register DstReg = MI.getOperand(0).getReg();
     Register PtrReg = MI.getOperand(1).getReg();
@@ -14723,7 +14841,9 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
     else
       BuildMI(*BB, MI, DL, TII->get(TargetOpcode::COPY), DstReg)
           .addReg(Result64);
-  } else {
+    break;
+  }
+  default:
     llvm_unreachable("Unexpected instr type to insert");
   }
 

>From dae4fc96845a93d0d72c38d7377ef13bd51a311a Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Wed, 6 May 2026 12:40:02 -0400
Subject: [PATCH 2/2] add missing :

---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index b4bb903f80ffe..e959100d713dd 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -14386,7 +14386,7 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
     BB->addSuccessor(sinkMBB);
     break;
   }
-  case PPC::ATOMIC_LOAD_ADD_NOWP
+  case PPC::ATOMIC_LOAD_ADD_NOWP:
     BB = EmitPartwordAtomicBinary(MI, BB, PPC::ADD4);
     break;
   case PPC::ATOMIC_LOAD_ADD:



More information about the llvm-commits mailing list