Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandAtomicPseudoInsts.cpp
35266 views
//===-- PPCExpandAtomicPseudoInsts.cpp - Expand atomic pseudo instrs. -----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains a pass that expands atomic pseudo instructions into9// target instructions post RA. With such method, LL/SC loop is considered as10// a whole blob and make spilling unlikely happens in the LL/SC loop.11//12//===----------------------------------------------------------------------===//1314#include "MCTargetDesc/PPCPredicates.h"15#include "PPC.h"16#include "PPCInstrInfo.h"17#include "PPCTargetMachine.h"1819#include "llvm/CodeGen/LivePhysRegs.h"20#include "llvm/CodeGen/MachineFunctionPass.h"21#include "llvm/CodeGen/MachineInstrBuilder.h"2223using namespace llvm;2425#define DEBUG_TYPE "ppc-atomic-expand"2627namespace {2829class PPCExpandAtomicPseudo : public MachineFunctionPass {30public:31const PPCInstrInfo *TII;32const PPCRegisterInfo *TRI;33static char ID;3435PPCExpandAtomicPseudo() : MachineFunctionPass(ID) {36initializePPCExpandAtomicPseudoPass(*PassRegistry::getPassRegistry());37}3839bool runOnMachineFunction(MachineFunction &MF) override;4041private:42bool expandMI(MachineBasicBlock &MBB, MachineInstr &MI,43MachineBasicBlock::iterator &NMBBI);44bool expandAtomicRMW128(MachineBasicBlock &MBB, MachineInstr &MI,45MachineBasicBlock::iterator &NMBBI);46bool expandAtomicCmpSwap128(MachineBasicBlock &MBB, MachineInstr &MI,47MachineBasicBlock::iterator &NMBBI);48};4950static void PairedCopy(const PPCInstrInfo *TII, MachineBasicBlock &MBB,51MachineBasicBlock::iterator MBBI, const DebugLoc &DL,52Register Dest0, Register Dest1, Register Src0,53Register Src1) {54const MCInstrDesc &OR = TII->get(PPC::OR8);55const MCInstrDesc &XOR = TII->get(PPC::XOR8);56if (Dest0 == Src1 && Dest1 == Src0) {57// The most tricky case, swapping values.58BuildMI(MBB, MBBI, DL, XOR, Dest0).addReg(Dest0).addReg(Dest1);59BuildMI(MBB, MBBI, DL, XOR, Dest1).addReg(Dest0).addReg(Dest1);60BuildMI(MBB, MBBI, DL, XOR, Dest0).addReg(Dest0).addReg(Dest1);61} else if (Dest0 != Src0 || Dest1 != Src1) {62if (Dest0 == Src1 || Dest1 != Src0) {63BuildMI(MBB, MBBI, DL, OR, Dest1).addReg(Src1).addReg(Src1);64BuildMI(MBB, MBBI, DL, OR, Dest0).addReg(Src0).addReg(Src0);65} else {66BuildMI(MBB, MBBI, DL, OR, Dest0).addReg(Src0).addReg(Src0);67BuildMI(MBB, MBBI, DL, OR, Dest1).addReg(Src1).addReg(Src1);68}69}70}7172bool PPCExpandAtomicPseudo::runOnMachineFunction(MachineFunction &MF) {73bool Changed = false;74TII = static_cast<const PPCInstrInfo *>(MF.getSubtarget().getInstrInfo());75TRI = &TII->getRegisterInfo();76for (MachineBasicBlock &MBB : MF) {77for (MachineBasicBlock::iterator MBBI = MBB.begin(), MBBE = MBB.end();78MBBI != MBBE;) {79MachineInstr &MI = *MBBI;80MachineBasicBlock::iterator NMBBI = std::next(MBBI);81Changed |= expandMI(MBB, MI, NMBBI);82MBBI = NMBBI;83}84}85if (Changed)86MF.RenumberBlocks();87return Changed;88}8990bool PPCExpandAtomicPseudo::expandMI(MachineBasicBlock &MBB, MachineInstr &MI,91MachineBasicBlock::iterator &NMBBI) {92switch (MI.getOpcode()) {93case PPC::ATOMIC_SWAP_I128:94case PPC::ATOMIC_LOAD_ADD_I128:95case PPC::ATOMIC_LOAD_SUB_I128:96case PPC::ATOMIC_LOAD_XOR_I128:97case PPC::ATOMIC_LOAD_NAND_I128:98case PPC::ATOMIC_LOAD_AND_I128:99case PPC::ATOMIC_LOAD_OR_I128:100return expandAtomicRMW128(MBB, MI, NMBBI);101case PPC::ATOMIC_CMP_SWAP_I128:102return expandAtomicCmpSwap128(MBB, MI, NMBBI);103case PPC::BUILD_QUADWORD: {104Register Dst = MI.getOperand(0).getReg();105Register DstHi = TRI->getSubReg(Dst, PPC::sub_gp8_x0);106Register DstLo = TRI->getSubReg(Dst, PPC::sub_gp8_x1);107Register Lo = MI.getOperand(1).getReg();108Register Hi = MI.getOperand(2).getReg();109PairedCopy(TII, MBB, MI, MI.getDebugLoc(), DstHi, DstLo, Hi, Lo);110MI.eraseFromParent();111return true;112}113default:114return false;115}116}117118bool PPCExpandAtomicPseudo::expandAtomicRMW128(119MachineBasicBlock &MBB, MachineInstr &MI,120MachineBasicBlock::iterator &NMBBI) {121const MCInstrDesc &LL = TII->get(PPC::LQARX);122const MCInstrDesc &SC = TII->get(PPC::STQCX);123DebugLoc DL = MI.getDebugLoc();124MachineFunction *MF = MBB.getParent();125const BasicBlock *BB = MBB.getBasicBlock();126// Create layout of control flow.127MachineFunction::iterator MFI = ++MBB.getIterator();128MachineBasicBlock *LoopMBB = MF->CreateMachineBasicBlock(BB);129MachineBasicBlock *ExitMBB = MF->CreateMachineBasicBlock(BB);130MF->insert(MFI, LoopMBB);131MF->insert(MFI, ExitMBB);132ExitMBB->splice(ExitMBB->begin(), &MBB, std::next(MI.getIterator()),133MBB.end());134ExitMBB->transferSuccessorsAndUpdatePHIs(&MBB);135MBB.addSuccessor(LoopMBB);136137// For non-min/max operations, control flow is kinda like:138// MBB:139// ...140// LoopMBB:141// lqarx in, ptr142// addc out.sub_x1, in.sub_x1, op.sub_x1143// adde out.sub_x0, in.sub_x0, op.sub_x0144// stqcx out, ptr145// bne- LoopMBB146// ExitMBB:147// ...148Register Old = MI.getOperand(0).getReg();149Register OldHi = TRI->getSubReg(Old, PPC::sub_gp8_x0);150Register OldLo = TRI->getSubReg(Old, PPC::sub_gp8_x1);151Register Scratch = MI.getOperand(1).getReg();152Register ScratchHi = TRI->getSubReg(Scratch, PPC::sub_gp8_x0);153Register ScratchLo = TRI->getSubReg(Scratch, PPC::sub_gp8_x1);154Register RA = MI.getOperand(2).getReg();155Register RB = MI.getOperand(3).getReg();156Register IncrLo = MI.getOperand(4).getReg();157Register IncrHi = MI.getOperand(5).getReg();158unsigned RMWOpcode = MI.getOpcode();159160MachineBasicBlock *CurrentMBB = LoopMBB;161BuildMI(CurrentMBB, DL, LL, Old).addReg(RA).addReg(RB);162163switch (RMWOpcode) {164case PPC::ATOMIC_SWAP_I128:165PairedCopy(TII, *CurrentMBB, CurrentMBB->end(), DL, ScratchHi, ScratchLo,166IncrHi, IncrLo);167break;168case PPC::ATOMIC_LOAD_ADD_I128:169BuildMI(CurrentMBB, DL, TII->get(PPC::ADDC8), ScratchLo)170.addReg(IncrLo)171.addReg(OldLo);172BuildMI(CurrentMBB, DL, TII->get(PPC::ADDE8), ScratchHi)173.addReg(IncrHi)174.addReg(OldHi);175break;176case PPC::ATOMIC_LOAD_SUB_I128:177BuildMI(CurrentMBB, DL, TII->get(PPC::SUBFC8), ScratchLo)178.addReg(IncrLo)179.addReg(OldLo);180BuildMI(CurrentMBB, DL, TII->get(PPC::SUBFE8), ScratchHi)181.addReg(IncrHi)182.addReg(OldHi);183break;184185#define TRIVIAL_ATOMICRMW(Opcode, Instr) \186case Opcode: \187BuildMI(CurrentMBB, DL, TII->get((Instr)), ScratchLo) \188.addReg(IncrLo) \189.addReg(OldLo); \190BuildMI(CurrentMBB, DL, TII->get((Instr)), ScratchHi) \191.addReg(IncrHi) \192.addReg(OldHi); \193break194195TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_OR_I128, PPC::OR8);196TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_XOR_I128, PPC::XOR8);197TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_AND_I128, PPC::AND8);198TRIVIAL_ATOMICRMW(PPC::ATOMIC_LOAD_NAND_I128, PPC::NAND8);199#undef TRIVIAL_ATOMICRMW200default:201llvm_unreachable("Unhandled atomic RMW operation");202}203BuildMI(CurrentMBB, DL, SC).addReg(Scratch).addReg(RA).addReg(RB);204BuildMI(CurrentMBB, DL, TII->get(PPC::BCC))205.addImm(PPC::PRED_NE)206.addReg(PPC::CR0)207.addMBB(LoopMBB);208CurrentMBB->addSuccessor(LoopMBB);209CurrentMBB->addSuccessor(ExitMBB);210fullyRecomputeLiveIns({ExitMBB, LoopMBB});211NMBBI = MBB.end();212MI.eraseFromParent();213return true;214}215216bool PPCExpandAtomicPseudo::expandAtomicCmpSwap128(217MachineBasicBlock &MBB, MachineInstr &MI,218MachineBasicBlock::iterator &NMBBI) {219const MCInstrDesc &LL = TII->get(PPC::LQARX);220const MCInstrDesc &SC = TII->get(PPC::STQCX);221DebugLoc DL = MI.getDebugLoc();222MachineFunction *MF = MBB.getParent();223const BasicBlock *BB = MBB.getBasicBlock();224Register Old = MI.getOperand(0).getReg();225Register OldHi = TRI->getSubReg(Old, PPC::sub_gp8_x0);226Register OldLo = TRI->getSubReg(Old, PPC::sub_gp8_x1);227Register Scratch = MI.getOperand(1).getReg();228Register ScratchHi = TRI->getSubReg(Scratch, PPC::sub_gp8_x0);229Register ScratchLo = TRI->getSubReg(Scratch, PPC::sub_gp8_x1);230Register RA = MI.getOperand(2).getReg();231Register RB = MI.getOperand(3).getReg();232Register CmpLo = MI.getOperand(4).getReg();233Register CmpHi = MI.getOperand(5).getReg();234Register NewLo = MI.getOperand(6).getReg();235Register NewHi = MI.getOperand(7).getReg();236// Create layout of control flow.237// loop:238// old = lqarx ptr239// <compare old, cmp>240// bne 0, exit241// succ:242// stqcx new ptr243// bne 0, loop244// exit:245// ....246MachineFunction::iterator MFI = ++MBB.getIterator();247MachineBasicBlock *LoopCmpMBB = MF->CreateMachineBasicBlock(BB);248MachineBasicBlock *CmpSuccMBB = MF->CreateMachineBasicBlock(BB);249MachineBasicBlock *ExitMBB = MF->CreateMachineBasicBlock(BB);250MF->insert(MFI, LoopCmpMBB);251MF->insert(MFI, CmpSuccMBB);252MF->insert(MFI, ExitMBB);253ExitMBB->splice(ExitMBB->begin(), &MBB, std::next(MI.getIterator()),254MBB.end());255ExitMBB->transferSuccessorsAndUpdatePHIs(&MBB);256MBB.addSuccessor(LoopCmpMBB);257// Build loop.258MachineBasicBlock *CurrentMBB = LoopCmpMBB;259BuildMI(CurrentMBB, DL, LL, Old).addReg(RA).addReg(RB);260BuildMI(CurrentMBB, DL, TII->get(PPC::XOR8), ScratchLo)261.addReg(OldLo)262.addReg(CmpLo);263BuildMI(CurrentMBB, DL, TII->get(PPC::XOR8), ScratchHi)264.addReg(OldHi)265.addReg(CmpHi);266BuildMI(CurrentMBB, DL, TII->get(PPC::OR8_rec), ScratchLo)267.addReg(ScratchLo)268.addReg(ScratchHi);269BuildMI(CurrentMBB, DL, TII->get(PPC::BCC))270.addImm(PPC::PRED_NE)271.addReg(PPC::CR0)272.addMBB(ExitMBB);273CurrentMBB->addSuccessor(CmpSuccMBB);274CurrentMBB->addSuccessor(ExitMBB);275// Build succ.276CurrentMBB = CmpSuccMBB;277PairedCopy(TII, *CurrentMBB, CurrentMBB->end(), DL, ScratchHi, ScratchLo,278NewHi, NewLo);279BuildMI(CurrentMBB, DL, SC).addReg(Scratch).addReg(RA).addReg(RB);280BuildMI(CurrentMBB, DL, TII->get(PPC::BCC))281.addImm(PPC::PRED_NE)282.addReg(PPC::CR0)283.addMBB(LoopCmpMBB);284CurrentMBB->addSuccessor(LoopCmpMBB);285CurrentMBB->addSuccessor(ExitMBB);286287fullyRecomputeLiveIns({ExitMBB, CmpSuccMBB, LoopCmpMBB});288NMBBI = MBB.end();289MI.eraseFromParent();290return true;291}292293} // namespace294295INITIALIZE_PASS(PPCExpandAtomicPseudo, DEBUG_TYPE, "PowerPC Expand Atomic",296false, false)297298char PPCExpandAtomicPseudo::ID = 0;299FunctionPass *llvm::createPPCExpandAtomicPseudoPass() {300return new PPCExpandAtomicPseudo();301}302303304