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
PPCExpandAtomicPseudo()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
PairedCopy(const PPCInstrInfo * TII,MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,Register Dest0,Register Dest1,Register Src0,Register Src1)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
runOnMachineFunction(MachineFunction & MF)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
expandMI(MachineBasicBlock & MBB,MachineInstr & MI,MachineBasicBlock::iterator & NMBBI)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
expandAtomicRMW128(MachineBasicBlock & MBB,MachineInstr & MI,MachineBasicBlock::iterator & NMBBI)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
expandAtomicCmpSwap128(MachineBasicBlock & MBB,MachineInstr & MI,MachineBasicBlock::iterator & NMBBI)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;
createPPCExpandAtomicPseudoPass()300fe6060f1SDimitry Andric FunctionPass *llvm::createPPCExpandAtomicPseudoPass() {
301fe6060f1SDimitry Andric return new PPCExpandAtomicPseudo();
302fe6060f1SDimitry Andric }
303