[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