xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandAtomicPseudoInsts.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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