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