1*fe6060f1SDimitry Andric //===-- PPCExpandAtomicPseudoInsts.cpp - Expand atomic pseudo instrs. -----===// 2*fe6060f1SDimitry Andric // 3*fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*fe6060f1SDimitry Andric // 7*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8*fe6060f1SDimitry Andric // 9*fe6060f1SDimitry Andric // This file contains a pass that expands atomic pseudo instructions into 10*fe6060f1SDimitry Andric // target instructions post RA. With such method, LL/SC loop is considered as 11*fe6060f1SDimitry Andric // a whole blob and make spilling unlikely happens in the LL/SC loop. 12*fe6060f1SDimitry Andric // 13*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 14*fe6060f1SDimitry Andric 15*fe6060f1SDimitry Andric #include "MCTargetDesc/PPCPredicates.h" 16*fe6060f1SDimitry Andric #include "PPC.h" 17*fe6060f1SDimitry Andric #include "PPCInstrInfo.h" 18*fe6060f1SDimitry Andric #include "PPCTargetMachine.h" 19*fe6060f1SDimitry Andric 20*fe6060f1SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h" 21*fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 22*fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 23*fe6060f1SDimitry Andric 24*fe6060f1SDimitry Andric using namespace llvm; 25*fe6060f1SDimitry Andric 26*fe6060f1SDimitry Andric #define DEBUG_TYPE "ppc-atomic-expand" 27*fe6060f1SDimitry Andric 28*fe6060f1SDimitry Andric namespace { 29*fe6060f1SDimitry Andric 30*fe6060f1SDimitry Andric class PPCExpandAtomicPseudo : public MachineFunctionPass { 31*fe6060f1SDimitry Andric public: 32*fe6060f1SDimitry Andric const PPCInstrInfo *TII; 33*fe6060f1SDimitry Andric const PPCRegisterInfo *TRI; 34*fe6060f1SDimitry Andric static char ID; 35*fe6060f1SDimitry Andric 36*fe6060f1SDimitry Andric PPCExpandAtomicPseudo() : MachineFunctionPass(ID) { 37*fe6060f1SDimitry Andric initializePPCExpandAtomicPseudoPass(*PassRegistry::getPassRegistry()); 38*fe6060f1SDimitry Andric } 39*fe6060f1SDimitry Andric 40*fe6060f1SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 41*fe6060f1SDimitry Andric 42*fe6060f1SDimitry Andric private: 43*fe6060f1SDimitry Andric bool expandMI(MachineBasicBlock &MBB, MachineInstr &MI, 44*fe6060f1SDimitry Andric MachineBasicBlock::iterator &NMBBI); 45*fe6060f1SDimitry Andric bool expandAtomicRMW128(MachineBasicBlock &MBB, MachineInstr &MI, 46*fe6060f1SDimitry Andric MachineBasicBlock::iterator &NMBBI); 47*fe6060f1SDimitry Andric bool expandAtomicCmpSwap128(MachineBasicBlock &MBB, MachineInstr &MI, 48*fe6060f1SDimitry Andric MachineBasicBlock::iterator &NMBBI); 49*fe6060f1SDimitry Andric }; 50*fe6060f1SDimitry Andric 51*fe6060f1SDimitry Andric static void PairedCopy(const PPCInstrInfo *TII, MachineBasicBlock &MBB, 52*fe6060f1SDimitry Andric MachineBasicBlock::iterator MBBI, const DebugLoc &DL, 53*fe6060f1SDimitry Andric Register Dest0, Register Dest1, Register Src0, 54*fe6060f1SDimitry Andric Register Src1) { 55*fe6060f1SDimitry Andric const MCInstrDesc &OR = TII->get(PPC::OR8); 56*fe6060f1SDimitry Andric const MCInstrDesc &XOR = TII->get(PPC::XOR8); 57*fe6060f1SDimitry Andric if (Dest0 == Src1 && Dest1 == Src0) { 58*fe6060f1SDimitry Andric // The most tricky case, swapping values. 59*fe6060f1SDimitry Andric BuildMI(MBB, MBBI, DL, XOR, Dest0).addReg(Dest0).addReg(Dest1); 60*fe6060f1SDimitry Andric BuildMI(MBB, MBBI, DL, XOR, Dest1).addReg(Dest0).addReg(Dest1); 61*fe6060f1SDimitry Andric BuildMI(MBB, MBBI, DL, XOR, Dest0).addReg(Dest0).addReg(Dest1); 62*fe6060f1SDimitry Andric } else if (Dest0 != Src0 || Dest1 != Src1) { 63*fe6060f1SDimitry Andric if (Dest0 == Src1 || Dest1 != Src0) { 64*fe6060f1SDimitry Andric BuildMI(MBB, MBBI, DL, OR, Dest1).addReg(Src1).addReg(Src1); 65*fe6060f1SDimitry Andric BuildMI(MBB, MBBI, DL, OR, Dest0).addReg(Src0).addReg(Src0); 66*fe6060f1SDimitry Andric } else { 67*fe6060f1SDimitry Andric BuildMI(MBB, MBBI, DL, OR, Dest0).addReg(Src0).addReg(Src0); 68*fe6060f1SDimitry Andric BuildMI(MBB, MBBI, DL, OR, Dest1).addReg(Src1).addReg(Src1); 69*fe6060f1SDimitry Andric } 70*fe6060f1SDimitry Andric } 71*fe6060f1SDimitry Andric } 72*fe6060f1SDimitry Andric 73*fe6060f1SDimitry Andric bool PPCExpandAtomicPseudo::runOnMachineFunction(MachineFunction &MF) { 74*fe6060f1SDimitry Andric bool Changed = false; 75*fe6060f1SDimitry Andric TII = static_cast<const PPCInstrInfo *>(MF.getSubtarget().getInstrInfo()); 76*fe6060f1SDimitry Andric TRI = &TII->getRegisterInfo(); 77*fe6060f1SDimitry Andric for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { 78*fe6060f1SDimitry Andric MachineBasicBlock &MBB = *I; 79*fe6060f1SDimitry Andric for (MachineBasicBlock::iterator MBBI = MBB.begin(), MBBE = MBB.end(); 80*fe6060f1SDimitry Andric MBBI != MBBE;) { 81*fe6060f1SDimitry Andric MachineInstr &MI = *MBBI; 82*fe6060f1SDimitry Andric MachineBasicBlock::iterator NMBBI = std::next(MBBI); 83*fe6060f1SDimitry Andric Changed |= expandMI(MBB, MI, NMBBI); 84*fe6060f1SDimitry Andric MBBI = NMBBI; 85*fe6060f1SDimitry Andric } 86*fe6060f1SDimitry Andric } 87*fe6060f1SDimitry Andric if (Changed) 88*fe6060f1SDimitry Andric MF.RenumberBlocks(); 89*fe6060f1SDimitry Andric return Changed; 90*fe6060f1SDimitry Andric } 91*fe6060f1SDimitry Andric 92*fe6060f1SDimitry Andric bool PPCExpandAtomicPseudo::expandMI(MachineBasicBlock &MBB, MachineInstr &MI, 93*fe6060f1SDimitry Andric MachineBasicBlock::iterator &NMBBI) { 94*fe6060f1SDimitry Andric switch (MI.getOpcode()) { 95*fe6060f1SDimitry Andric case PPC::ATOMIC_SWAP_I128: 96*fe6060f1SDimitry Andric case PPC::ATOMIC_LOAD_ADD_I128: 97*fe6060f1SDimitry Andric case PPC::ATOMIC_LOAD_SUB_I128: 98*fe6060f1SDimitry Andric case PPC::ATOMIC_LOAD_XOR_I128: 99*fe6060f1SDimitry Andric case PPC::ATOMIC_LOAD_NAND_I128: 100*fe6060f1SDimitry Andric case PPC::ATOMIC_LOAD_AND_I128: 101*fe6060f1SDimitry Andric case PPC::ATOMIC_LOAD_OR_I128: 102*fe6060f1SDimitry Andric return expandAtomicRMW128(MBB, MI, NMBBI); 103*fe6060f1SDimitry Andric case PPC::ATOMIC_CMP_SWAP_I128: 104*fe6060f1SDimitry Andric return expandAtomicCmpSwap128(MBB, MI, NMBBI); 105*fe6060f1SDimitry Andric default: 106*fe6060f1SDimitry Andric return false; 107*fe6060f1SDimitry Andric } 108*fe6060f1SDimitry Andric } 109*fe6060f1SDimitry Andric 110*fe6060f1SDimitry Andric bool PPCExpandAtomicPseudo::expandAtomicRMW128( 111*fe6060f1SDimitry Andric MachineBasicBlock &MBB, MachineInstr &MI, 112*fe6060f1SDimitry Andric MachineBasicBlock::iterator &NMBBI) { 113*fe6060f1SDimitry Andric const MCInstrDesc &LL = TII->get(PPC::LQARX); 114*fe6060f1SDimitry Andric const MCInstrDesc &SC = TII->get(PPC::STQCX); 115*fe6060f1SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 116*fe6060f1SDimitry Andric MachineFunction *MF = MBB.getParent(); 117*fe6060f1SDimitry Andric const BasicBlock *BB = MBB.getBasicBlock(); 118*fe6060f1SDimitry Andric // Create layout of control flow. 119*fe6060f1SDimitry Andric MachineFunction::iterator MFI = ++MBB.getIterator(); 120*fe6060f1SDimitry Andric MachineBasicBlock *LoopMBB = MF->CreateMachineBasicBlock(BB); 121*fe6060f1SDimitry Andric MachineBasicBlock *ExitMBB = MF->CreateMachineBasicBlock(BB); 122*fe6060f1SDimitry Andric MF->insert(MFI, LoopMBB); 123*fe6060f1SDimitry Andric MF->insert(MFI, ExitMBB); 124*fe6060f1SDimitry Andric ExitMBB->splice(ExitMBB->begin(), &MBB, std::next(MI.getIterator()), 125*fe6060f1SDimitry Andric MBB.end()); 126*fe6060f1SDimitry Andric ExitMBB->transferSuccessorsAndUpdatePHIs(&MBB); 127*fe6060f1SDimitry Andric MBB.addSuccessor(LoopMBB); 128*fe6060f1SDimitry Andric 129*fe6060f1SDimitry Andric // For non-min/max operations, control flow is kinda like: 130*fe6060f1SDimitry Andric // MBB: 131*fe6060f1SDimitry Andric // ... 132*fe6060f1SDimitry Andric // LoopMBB: 133*fe6060f1SDimitry Andric // lqarx in, ptr 134*fe6060f1SDimitry Andric // addc out.sub_x1, in.sub_x1, op.sub_x1 135*fe6060f1SDimitry Andric // adde out.sub_x0, in.sub_x0, op.sub_x0 136*fe6060f1SDimitry Andric // stqcx out, ptr 137*fe6060f1SDimitry Andric // bne- LoopMBB 138*fe6060f1SDimitry Andric // ExitMBB: 139*fe6060f1SDimitry Andric // ... 140*fe6060f1SDimitry Andric Register Old = MI.getOperand(0).getReg(); 141*fe6060f1SDimitry Andric Register OldHi = TRI->getSubReg(Old, PPC::sub_gp8_x0); 142*fe6060f1SDimitry Andric Register OldLo = TRI->getSubReg(Old, PPC::sub_gp8_x1); 143*fe6060f1SDimitry Andric Register Scratch = MI.getOperand(1).getReg(); 144*fe6060f1SDimitry Andric Register ScratchHi = TRI->getSubReg(Scratch, PPC::sub_gp8_x0); 145*fe6060f1SDimitry Andric Register ScratchLo = TRI->getSubReg(Scratch, PPC::sub_gp8_x1); 146*fe6060f1SDimitry Andric Register RA = MI.getOperand(2).getReg(); 147*fe6060f1SDimitry Andric Register RB = MI.getOperand(3).getReg(); 148*fe6060f1SDimitry Andric Register IncrLo = MI.getOperand(4).getReg(); 149*fe6060f1SDimitry Andric Register IncrHi = MI.getOperand(5).getReg(); 150*fe6060f1SDimitry Andric unsigned RMWOpcode = MI.getOpcode(); 151*fe6060f1SDimitry Andric 152*fe6060f1SDimitry Andric MachineBasicBlock *CurrentMBB = LoopMBB; 153*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, LL, Old).addReg(RA).addReg(RB); 154*fe6060f1SDimitry Andric 155*fe6060f1SDimitry Andric switch (RMWOpcode) { 156*fe6060f1SDimitry Andric case PPC::ATOMIC_SWAP_I128: 157*fe6060f1SDimitry Andric PairedCopy(TII, *CurrentMBB, CurrentMBB->end(), DL, ScratchHi, ScratchLo, 158*fe6060f1SDimitry Andric IncrHi, IncrLo); 159*fe6060f1SDimitry Andric break; 160*fe6060f1SDimitry Andric case PPC::ATOMIC_LOAD_ADD_I128: 161*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get(PPC::ADDC8), ScratchLo) 162*fe6060f1SDimitry Andric .addReg(IncrLo) 163*fe6060f1SDimitry Andric .addReg(OldLo); 164*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get(PPC::ADDE8), ScratchHi) 165*fe6060f1SDimitry Andric .addReg(IncrHi) 166*fe6060f1SDimitry Andric .addReg(OldHi); 167*fe6060f1SDimitry Andric break; 168*fe6060f1SDimitry Andric case PPC::ATOMIC_LOAD_SUB_I128: 169*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get(PPC::SUBFC8), ScratchLo) 170*fe6060f1SDimitry Andric .addReg(IncrLo) 171*fe6060f1SDimitry Andric .addReg(OldLo); 172*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get(PPC::SUBFE8), ScratchHi) 173*fe6060f1SDimitry Andric .addReg(IncrHi) 174*fe6060f1SDimitry Andric .addReg(OldHi); 175*fe6060f1SDimitry Andric break; 176*fe6060f1SDimitry Andric 177*fe6060f1SDimitry Andric #define TRIVIAL_ATOMICRMW(Opcode, Instr) \ 178*fe6060f1SDimitry Andric case Opcode: \ 179*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get((Instr)), ScratchLo) \ 180*fe6060f1SDimitry Andric .addReg(IncrLo) \ 181*fe6060f1SDimitry Andric .addReg(OldLo); \ 182*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get((Instr)), ScratchHi) \ 183*fe6060f1SDimitry Andric .addReg(IncrHi) \ 184*fe6060f1SDimitry Andric .addReg(OldHi); \ 185*fe6060f1SDimitry Andric break 186*fe6060f1SDimitry Andric 187*fe6060f1SDimitry Andric TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_OR_I128, PPC::OR8); 188*fe6060f1SDimitry Andric TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_XOR_I128, PPC::XOR8); 189*fe6060f1SDimitry Andric TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_AND_I128, PPC::AND8); 190*fe6060f1SDimitry Andric TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_NAND_I128, PPC::NAND8); 191*fe6060f1SDimitry Andric #undef TRIVIAL_ATOMICRMW 192*fe6060f1SDimitry Andric default: 193*fe6060f1SDimitry Andric llvm_unreachable("Unhandled atomic RMW operation"); 194*fe6060f1SDimitry Andric } 195*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, SC).addReg(Scratch).addReg(RA).addReg(RB); 196*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get(PPC::BCC)) 197*fe6060f1SDimitry Andric .addImm(PPC::PRED_NE) 198*fe6060f1SDimitry Andric .addReg(PPC::CR0) 199*fe6060f1SDimitry Andric .addMBB(LoopMBB); 200*fe6060f1SDimitry Andric CurrentMBB->addSuccessor(LoopMBB); 201*fe6060f1SDimitry Andric CurrentMBB->addSuccessor(ExitMBB); 202*fe6060f1SDimitry Andric recomputeLiveIns(*LoopMBB); 203*fe6060f1SDimitry Andric recomputeLiveIns(*ExitMBB); 204*fe6060f1SDimitry Andric NMBBI = MBB.end(); 205*fe6060f1SDimitry Andric MI.eraseFromParent(); 206*fe6060f1SDimitry Andric return true; 207*fe6060f1SDimitry Andric } 208*fe6060f1SDimitry Andric 209*fe6060f1SDimitry Andric bool PPCExpandAtomicPseudo::expandAtomicCmpSwap128( 210*fe6060f1SDimitry Andric MachineBasicBlock &MBB, MachineInstr &MI, 211*fe6060f1SDimitry Andric MachineBasicBlock::iterator &NMBBI) { 212*fe6060f1SDimitry Andric const MCInstrDesc &LL = TII->get(PPC::LQARX); 213*fe6060f1SDimitry Andric const MCInstrDesc &SC = TII->get(PPC::STQCX); 214*fe6060f1SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 215*fe6060f1SDimitry Andric MachineFunction *MF = MBB.getParent(); 216*fe6060f1SDimitry Andric const BasicBlock *BB = MBB.getBasicBlock(); 217*fe6060f1SDimitry Andric Register Old = MI.getOperand(0).getReg(); 218*fe6060f1SDimitry Andric Register OldHi = TRI->getSubReg(Old, PPC::sub_gp8_x0); 219*fe6060f1SDimitry Andric Register OldLo = TRI->getSubReg(Old, PPC::sub_gp8_x1); 220*fe6060f1SDimitry Andric Register Scratch = MI.getOperand(1).getReg(); 221*fe6060f1SDimitry Andric Register ScratchHi = TRI->getSubReg(Scratch, PPC::sub_gp8_x0); 222*fe6060f1SDimitry Andric Register ScratchLo = TRI->getSubReg(Scratch, PPC::sub_gp8_x1); 223*fe6060f1SDimitry Andric Register RA = MI.getOperand(2).getReg(); 224*fe6060f1SDimitry Andric Register RB = MI.getOperand(3).getReg(); 225*fe6060f1SDimitry Andric Register CmpLo = MI.getOperand(4).getReg(); 226*fe6060f1SDimitry Andric Register CmpHi = MI.getOperand(5).getReg(); 227*fe6060f1SDimitry Andric Register NewLo = MI.getOperand(6).getReg(); 228*fe6060f1SDimitry Andric Register NewHi = MI.getOperand(7).getReg(); 229*fe6060f1SDimitry Andric // Create layout of control flow. 230*fe6060f1SDimitry Andric // loop: 231*fe6060f1SDimitry Andric // old = lqarx ptr 232*fe6060f1SDimitry Andric // <compare old, cmp> 233*fe6060f1SDimitry Andric // bne 0, fail 234*fe6060f1SDimitry Andric // succ: 235*fe6060f1SDimitry Andric // stqcx new ptr 236*fe6060f1SDimitry Andric // bne 0, loop 237*fe6060f1SDimitry Andric // b exit 238*fe6060f1SDimitry Andric // fail: 239*fe6060f1SDimitry Andric // stqcx old ptr 240*fe6060f1SDimitry Andric // exit: 241*fe6060f1SDimitry Andric // .... 242*fe6060f1SDimitry Andric MachineFunction::iterator MFI = ++MBB.getIterator(); 243*fe6060f1SDimitry Andric MachineBasicBlock *LoopCmpMBB = MF->CreateMachineBasicBlock(BB); 244*fe6060f1SDimitry Andric MachineBasicBlock *CmpSuccMBB = MF->CreateMachineBasicBlock(BB); 245*fe6060f1SDimitry Andric MachineBasicBlock *CmpFailMBB = MF->CreateMachineBasicBlock(BB); 246*fe6060f1SDimitry Andric MachineBasicBlock *ExitMBB = MF->CreateMachineBasicBlock(BB); 247*fe6060f1SDimitry Andric MF->insert(MFI, LoopCmpMBB); 248*fe6060f1SDimitry Andric MF->insert(MFI, CmpSuccMBB); 249*fe6060f1SDimitry Andric MF->insert(MFI, CmpFailMBB); 250*fe6060f1SDimitry Andric MF->insert(MFI, ExitMBB); 251*fe6060f1SDimitry Andric ExitMBB->splice(ExitMBB->begin(), &MBB, std::next(MI.getIterator()), 252*fe6060f1SDimitry Andric MBB.end()); 253*fe6060f1SDimitry Andric ExitMBB->transferSuccessorsAndUpdatePHIs(&MBB); 254*fe6060f1SDimitry Andric MBB.addSuccessor(LoopCmpMBB); 255*fe6060f1SDimitry Andric // Build loop. 256*fe6060f1SDimitry Andric MachineBasicBlock *CurrentMBB = LoopCmpMBB; 257*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, LL, Old).addReg(RA).addReg(RB); 258*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get(PPC::XOR8), ScratchLo) 259*fe6060f1SDimitry Andric .addReg(OldLo) 260*fe6060f1SDimitry Andric .addReg(CmpLo); 261*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get(PPC::XOR8), ScratchHi) 262*fe6060f1SDimitry Andric .addReg(OldHi) 263*fe6060f1SDimitry Andric .addReg(CmpHi); 264*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get(PPC::OR8_rec), ScratchLo) 265*fe6060f1SDimitry Andric .addReg(ScratchLo) 266*fe6060f1SDimitry Andric .addReg(ScratchHi); 267*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get(PPC::BCC)) 268*fe6060f1SDimitry Andric .addImm(PPC::PRED_NE) 269*fe6060f1SDimitry Andric .addReg(PPC::CR0) 270*fe6060f1SDimitry Andric .addMBB(CmpFailMBB); 271*fe6060f1SDimitry Andric CurrentMBB->addSuccessor(CmpSuccMBB); 272*fe6060f1SDimitry Andric CurrentMBB->addSuccessor(CmpFailMBB); 273*fe6060f1SDimitry Andric // Build succ. 274*fe6060f1SDimitry Andric CurrentMBB = CmpSuccMBB; 275*fe6060f1SDimitry Andric PairedCopy(TII, *CurrentMBB, CurrentMBB->end(), DL, ScratchHi, ScratchLo, 276*fe6060f1SDimitry Andric NewHi, NewLo); 277*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, SC).addReg(Scratch).addReg(RA).addReg(RB); 278*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get(PPC::BCC)) 279*fe6060f1SDimitry Andric .addImm(PPC::PRED_NE) 280*fe6060f1SDimitry Andric .addReg(PPC::CR0) 281*fe6060f1SDimitry Andric .addMBB(LoopCmpMBB); 282*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, TII->get(PPC::B)).addMBB(ExitMBB); 283*fe6060f1SDimitry Andric CurrentMBB->addSuccessor(LoopCmpMBB); 284*fe6060f1SDimitry Andric CurrentMBB->addSuccessor(ExitMBB); 285*fe6060f1SDimitry Andric CurrentMBB = CmpFailMBB; 286*fe6060f1SDimitry Andric BuildMI(CurrentMBB, DL, SC).addReg(Old).addReg(RA).addReg(RB); 287*fe6060f1SDimitry Andric CurrentMBB->addSuccessor(ExitMBB); 288*fe6060f1SDimitry Andric 289*fe6060f1SDimitry Andric recomputeLiveIns(*LoopCmpMBB); 290*fe6060f1SDimitry Andric recomputeLiveIns(*CmpSuccMBB); 291*fe6060f1SDimitry Andric recomputeLiveIns(*CmpFailMBB); 292*fe6060f1SDimitry Andric recomputeLiveIns(*ExitMBB); 293*fe6060f1SDimitry Andric NMBBI = MBB.end(); 294*fe6060f1SDimitry Andric MI.eraseFromParent(); 295*fe6060f1SDimitry Andric return true; 296*fe6060f1SDimitry Andric } 297*fe6060f1SDimitry Andric 298*fe6060f1SDimitry Andric } // namespace 299*fe6060f1SDimitry Andric 300*fe6060f1SDimitry Andric INITIALIZE_PASS(PPCExpandAtomicPseudo, DEBUG_TYPE, "PowerPC Expand Atomic", 301*fe6060f1SDimitry Andric false, false) 302*fe6060f1SDimitry Andric 303*fe6060f1SDimitry Andric char PPCExpandAtomicPseudo::ID = 0; 304*fe6060f1SDimitry Andric FunctionPass *llvm::createPPCExpandAtomicPseudoPass() { 305*fe6060f1SDimitry Andric return new PPCExpandAtomicPseudo(); 306*fe6060f1SDimitry Andric } 307