123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- //===-- PPCExpandAtomicPseudoInsts.cpp - Expand atomic pseudo instrs. -----===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file contains a pass that expands atomic pseudo instructions into
- // target instructions post RA. With such method, LL/SC loop is considered as
- // a whole blob and make spilling unlikely happens in the LL/SC loop.
- //
- //===----------------------------------------------------------------------===//
- #include "MCTargetDesc/PPCPredicates.h"
- #include "PPC.h"
- #include "PPCInstrInfo.h"
- #include "PPCTargetMachine.h"
- #include "llvm/CodeGen/LivePhysRegs.h"
- #include "llvm/CodeGen/MachineFunctionPass.h"
- #include "llvm/CodeGen/MachineInstrBuilder.h"
- using namespace llvm;
- #define DEBUG_TYPE "ppc-atomic-expand"
- namespace {
- class PPCExpandAtomicPseudo : public MachineFunctionPass {
- public:
- const PPCInstrInfo *TII;
- const PPCRegisterInfo *TRI;
- static char ID;
- PPCExpandAtomicPseudo() : MachineFunctionPass(ID) {
- initializePPCExpandAtomicPseudoPass(*PassRegistry::getPassRegistry());
- }
- bool runOnMachineFunction(MachineFunction &MF) override;
- private:
- bool expandMI(MachineBasicBlock &MBB, MachineInstr &MI,
- MachineBasicBlock::iterator &NMBBI);
- bool expandAtomicRMW128(MachineBasicBlock &MBB, MachineInstr &MI,
- MachineBasicBlock::iterator &NMBBI);
- bool expandAtomicCmpSwap128(MachineBasicBlock &MBB, MachineInstr &MI,
- MachineBasicBlock::iterator &NMBBI);
- };
- static void PairedCopy(const PPCInstrInfo *TII, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
- Register Dest0, Register Dest1, Register Src0,
- Register Src1) {
- const MCInstrDesc &OR = TII->get(PPC::OR8);
- const MCInstrDesc &XOR = TII->get(PPC::XOR8);
- if (Dest0 == Src1 && Dest1 == Src0) {
- // The most tricky case, swapping values.
- BuildMI(MBB, MBBI, DL, XOR, Dest0).addReg(Dest0).addReg(Dest1);
- BuildMI(MBB, MBBI, DL, XOR, Dest1).addReg(Dest0).addReg(Dest1);
- BuildMI(MBB, MBBI, DL, XOR, Dest0).addReg(Dest0).addReg(Dest1);
- } else if (Dest0 != Src0 || Dest1 != Src1) {
- if (Dest0 == Src1 || Dest1 != Src0) {
- BuildMI(MBB, MBBI, DL, OR, Dest1).addReg(Src1).addReg(Src1);
- BuildMI(MBB, MBBI, DL, OR, Dest0).addReg(Src0).addReg(Src0);
- } else {
- BuildMI(MBB, MBBI, DL, OR, Dest0).addReg(Src0).addReg(Src0);
- BuildMI(MBB, MBBI, DL, OR, Dest1).addReg(Src1).addReg(Src1);
- }
- }
- }
- bool PPCExpandAtomicPseudo::runOnMachineFunction(MachineFunction &MF) {
- bool Changed = false;
- TII = static_cast<const PPCInstrInfo *>(MF.getSubtarget().getInstrInfo());
- TRI = &TII->getRegisterInfo();
- for (MachineBasicBlock &MBB : MF) {
- for (MachineBasicBlock::iterator MBBI = MBB.begin(), MBBE = MBB.end();
- MBBI != MBBE;) {
- MachineInstr &MI = *MBBI;
- MachineBasicBlock::iterator NMBBI = std::next(MBBI);
- Changed |= expandMI(MBB, MI, NMBBI);
- MBBI = NMBBI;
- }
- }
- if (Changed)
- MF.RenumberBlocks();
- return Changed;
- }
- bool PPCExpandAtomicPseudo::expandMI(MachineBasicBlock &MBB, MachineInstr &MI,
- MachineBasicBlock::iterator &NMBBI) {
- switch (MI.getOpcode()) {
- case PPC::ATOMIC_SWAP_I128:
- case PPC::ATOMIC_LOAD_ADD_I128:
- case PPC::ATOMIC_LOAD_SUB_I128:
- case PPC::ATOMIC_LOAD_XOR_I128:
- case PPC::ATOMIC_LOAD_NAND_I128:
- case PPC::ATOMIC_LOAD_AND_I128:
- case PPC::ATOMIC_LOAD_OR_I128:
- return expandAtomicRMW128(MBB, MI, NMBBI);
- case PPC::ATOMIC_CMP_SWAP_I128:
- return expandAtomicCmpSwap128(MBB, MI, NMBBI);
- case PPC::BUILD_QUADWORD: {
- Register Dst = MI.getOperand(0).getReg();
- Register DstHi = TRI->getSubReg(Dst, PPC::sub_gp8_x0);
- Register DstLo = TRI->getSubReg(Dst, PPC::sub_gp8_x1);
- Register Lo = MI.getOperand(1).getReg();
- Register Hi = MI.getOperand(2).getReg();
- PairedCopy(TII, MBB, MI, MI.getDebugLoc(), DstHi, DstLo, Hi, Lo);
- MI.eraseFromParent();
- return true;
- }
- default:
- return false;
- }
- }
- bool PPCExpandAtomicPseudo::expandAtomicRMW128(
- MachineBasicBlock &MBB, MachineInstr &MI,
- MachineBasicBlock::iterator &NMBBI) {
- const MCInstrDesc &LL = TII->get(PPC::LQARX);
- const MCInstrDesc &SC = TII->get(PPC::STQCX);
- DebugLoc DL = MI.getDebugLoc();
- MachineFunction *MF = MBB.getParent();
- const BasicBlock *BB = MBB.getBasicBlock();
- // Create layout of control flow.
- MachineFunction::iterator MFI = ++MBB.getIterator();
- MachineBasicBlock *LoopMBB = MF->CreateMachineBasicBlock(BB);
- MachineBasicBlock *ExitMBB = MF->CreateMachineBasicBlock(BB);
- MF->insert(MFI, LoopMBB);
- MF->insert(MFI, ExitMBB);
- ExitMBB->splice(ExitMBB->begin(), &MBB, std::next(MI.getIterator()),
- MBB.end());
- ExitMBB->transferSuccessorsAndUpdatePHIs(&MBB);
- MBB.addSuccessor(LoopMBB);
- // For non-min/max operations, control flow is kinda like:
- // MBB:
- // ...
- // LoopMBB:
- // lqarx in, ptr
- // addc out.sub_x1, in.sub_x1, op.sub_x1
- // adde out.sub_x0, in.sub_x0, op.sub_x0
- // stqcx out, ptr
- // bne- LoopMBB
- // ExitMBB:
- // ...
- Register Old = MI.getOperand(0).getReg();
- Register OldHi = TRI->getSubReg(Old, PPC::sub_gp8_x0);
- Register OldLo = TRI->getSubReg(Old, PPC::sub_gp8_x1);
- Register Scratch = MI.getOperand(1).getReg();
- Register ScratchHi = TRI->getSubReg(Scratch, PPC::sub_gp8_x0);
- Register ScratchLo = TRI->getSubReg(Scratch, PPC::sub_gp8_x1);
- Register RA = MI.getOperand(2).getReg();
- Register RB = MI.getOperand(3).getReg();
- Register IncrLo = MI.getOperand(4).getReg();
- Register IncrHi = MI.getOperand(5).getReg();
- unsigned RMWOpcode = MI.getOpcode();
- MachineBasicBlock *CurrentMBB = LoopMBB;
- BuildMI(CurrentMBB, DL, LL, Old).addReg(RA).addReg(RB);
- switch (RMWOpcode) {
- case PPC::ATOMIC_SWAP_I128:
- PairedCopy(TII, *CurrentMBB, CurrentMBB->end(), DL, ScratchHi, ScratchLo,
- IncrHi, IncrLo);
- break;
- case PPC::ATOMIC_LOAD_ADD_I128:
- BuildMI(CurrentMBB, DL, TII->get(PPC::ADDC8), ScratchLo)
- .addReg(IncrLo)
- .addReg(OldLo);
- BuildMI(CurrentMBB, DL, TII->get(PPC::ADDE8), ScratchHi)
- .addReg(IncrHi)
- .addReg(OldHi);
- break;
- case PPC::ATOMIC_LOAD_SUB_I128:
- BuildMI(CurrentMBB, DL, TII->get(PPC::SUBFC8), ScratchLo)
- .addReg(IncrLo)
- .addReg(OldLo);
- BuildMI(CurrentMBB, DL, TII->get(PPC::SUBFE8), ScratchHi)
- .addReg(IncrHi)
- .addReg(OldHi);
- break;
- #define TRIVIAL_ATOMICRMW(Opcode, Instr) \
- case Opcode: \
- BuildMI(CurrentMBB, DL, TII->get((Instr)), ScratchLo) \
- .addReg(IncrLo) \
- .addReg(OldLo); \
- BuildMI(CurrentMBB, DL, TII->get((Instr)), ScratchHi) \
- .addReg(IncrHi) \
- .addReg(OldHi); \
- break
- TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_OR_I128, PPC::OR8);
- TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_XOR_I128, PPC::XOR8);
- TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_AND_I128, PPC::AND8);
- TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_NAND_I128, PPC::NAND8);
- #undef TRIVIAL_ATOMICRMW
- default:
- llvm_unreachable("Unhandled atomic RMW operation");
- }
- BuildMI(CurrentMBB, DL, SC).addReg(Scratch).addReg(RA).addReg(RB);
- BuildMI(CurrentMBB, DL, TII->get(PPC::BCC))
- .addImm(PPC::PRED_NE)
- .addReg(PPC::CR0)
- .addMBB(LoopMBB);
- CurrentMBB->addSuccessor(LoopMBB);
- CurrentMBB->addSuccessor(ExitMBB);
- recomputeLiveIns(*LoopMBB);
- recomputeLiveIns(*ExitMBB);
- NMBBI = MBB.end();
- MI.eraseFromParent();
- return true;
- }
- bool PPCExpandAtomicPseudo::expandAtomicCmpSwap128(
- MachineBasicBlock &MBB, MachineInstr &MI,
- MachineBasicBlock::iterator &NMBBI) {
- const MCInstrDesc &LL = TII->get(PPC::LQARX);
- const MCInstrDesc &SC = TII->get(PPC::STQCX);
- DebugLoc DL = MI.getDebugLoc();
- MachineFunction *MF = MBB.getParent();
- const BasicBlock *BB = MBB.getBasicBlock();
- Register Old = MI.getOperand(0).getReg();
- Register OldHi = TRI->getSubReg(Old, PPC::sub_gp8_x0);
- Register OldLo = TRI->getSubReg(Old, PPC::sub_gp8_x1);
- Register Scratch = MI.getOperand(1).getReg();
- Register ScratchHi = TRI->getSubReg(Scratch, PPC::sub_gp8_x0);
- Register ScratchLo = TRI->getSubReg(Scratch, PPC::sub_gp8_x1);
- Register RA = MI.getOperand(2).getReg();
- Register RB = MI.getOperand(3).getReg();
- Register CmpLo = MI.getOperand(4).getReg();
- Register CmpHi = MI.getOperand(5).getReg();
- Register NewLo = MI.getOperand(6).getReg();
- Register NewHi = MI.getOperand(7).getReg();
- // Create layout of control flow.
- // loop:
- // old = lqarx ptr
- // <compare old, cmp>
- // bne 0, fail
- // succ:
- // stqcx new ptr
- // bne 0, loop
- // b exit
- // fail:
- // stqcx old ptr
- // exit:
- // ....
- MachineFunction::iterator MFI = ++MBB.getIterator();
- MachineBasicBlock *LoopCmpMBB = MF->CreateMachineBasicBlock(BB);
- MachineBasicBlock *CmpSuccMBB = MF->CreateMachineBasicBlock(BB);
- MachineBasicBlock *CmpFailMBB = MF->CreateMachineBasicBlock(BB);
- MachineBasicBlock *ExitMBB = MF->CreateMachineBasicBlock(BB);
- MF->insert(MFI, LoopCmpMBB);
- MF->insert(MFI, CmpSuccMBB);
- MF->insert(MFI, CmpFailMBB);
- MF->insert(MFI, ExitMBB);
- ExitMBB->splice(ExitMBB->begin(), &MBB, std::next(MI.getIterator()),
- MBB.end());
- ExitMBB->transferSuccessorsAndUpdatePHIs(&MBB);
- MBB.addSuccessor(LoopCmpMBB);
- // Build loop.
- MachineBasicBlock *CurrentMBB = LoopCmpMBB;
- BuildMI(CurrentMBB, DL, LL, Old).addReg(RA).addReg(RB);
- BuildMI(CurrentMBB, DL, TII->get(PPC::XOR8), ScratchLo)
- .addReg(OldLo)
- .addReg(CmpLo);
- BuildMI(CurrentMBB, DL, TII->get(PPC::XOR8), ScratchHi)
- .addReg(OldHi)
- .addReg(CmpHi);
- BuildMI(CurrentMBB, DL, TII->get(PPC::OR8_rec), ScratchLo)
- .addReg(ScratchLo)
- .addReg(ScratchHi);
- BuildMI(CurrentMBB, DL, TII->get(PPC::BCC))
- .addImm(PPC::PRED_NE)
- .addReg(PPC::CR0)
- .addMBB(CmpFailMBB);
- CurrentMBB->addSuccessor(CmpSuccMBB);
- CurrentMBB->addSuccessor(CmpFailMBB);
- // Build succ.
- CurrentMBB = CmpSuccMBB;
- PairedCopy(TII, *CurrentMBB, CurrentMBB->end(), DL, ScratchHi, ScratchLo,
- NewHi, NewLo);
- BuildMI(CurrentMBB, DL, SC).addReg(Scratch).addReg(RA).addReg(RB);
- BuildMI(CurrentMBB, DL, TII->get(PPC::BCC))
- .addImm(PPC::PRED_NE)
- .addReg(PPC::CR0)
- .addMBB(LoopCmpMBB);
- BuildMI(CurrentMBB, DL, TII->get(PPC::B)).addMBB(ExitMBB);
- CurrentMBB->addSuccessor(LoopCmpMBB);
- CurrentMBB->addSuccessor(ExitMBB);
- CurrentMBB = CmpFailMBB;
- BuildMI(CurrentMBB, DL, SC).addReg(Old).addReg(RA).addReg(RB);
- CurrentMBB->addSuccessor(ExitMBB);
- recomputeLiveIns(*LoopCmpMBB);
- recomputeLiveIns(*CmpSuccMBB);
- recomputeLiveIns(*CmpFailMBB);
- recomputeLiveIns(*ExitMBB);
- NMBBI = MBB.end();
- MI.eraseFromParent();
- return true;
- }
- } // namespace
- INITIALIZE_PASS(PPCExpandAtomicPseudo, DEBUG_TYPE, "PowerPC Expand Atomic",
- false, false)
- char PPCExpandAtomicPseudo::ID = 0;
- FunctionPass *llvm::createPPCExpandAtomicPseudoPass() {
- return new PPCExpandAtomicPseudo();
- }
|