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