123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628 |
- //==- LoongArchExpandAtomicPseudoInsts.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. This pass should be run at the last possible moment,
- // avoiding the possibility for other passes to break the requirements for
- // forward progress in the LL/SC block.
- //
- //===----------------------------------------------------------------------===//
- #include "LoongArch.h"
- #include "LoongArchInstrInfo.h"
- #include "LoongArchTargetMachine.h"
- #include "llvm/CodeGen/LivePhysRegs.h"
- #include "llvm/CodeGen/MachineFunctionPass.h"
- #include "llvm/CodeGen/MachineInstrBuilder.h"
- using namespace llvm;
- #define LoongArch_EXPAND_ATOMIC_PSEUDO_NAME \
- "LoongArch atomic pseudo instruction expansion pass"
- namespace {
- class LoongArchExpandAtomicPseudo : public MachineFunctionPass {
- public:
- const LoongArchInstrInfo *TII;
- static char ID;
- LoongArchExpandAtomicPseudo() : MachineFunctionPass(ID) {
- initializeLoongArchExpandAtomicPseudoPass(*PassRegistry::getPassRegistry());
- }
- bool runOnMachineFunction(MachineFunction &MF) override;
- StringRef getPassName() const override {
- return LoongArch_EXPAND_ATOMIC_PSEUDO_NAME;
- }
- private:
- bool expandMBB(MachineBasicBlock &MBB);
- bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI);
- bool expandAtomicBinOp(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI, AtomicRMWInst::BinOp,
- bool IsMasked, int Width,
- MachineBasicBlock::iterator &NextMBBI);
- bool expandAtomicMinMaxOp(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- AtomicRMWInst::BinOp, bool IsMasked, int Width,
- MachineBasicBlock::iterator &NextMBBI);
- bool expandAtomicCmpXchg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI, bool IsMasked,
- int Width, MachineBasicBlock::iterator &NextMBBI);
- };
- char LoongArchExpandAtomicPseudo::ID = 0;
- bool LoongArchExpandAtomicPseudo::runOnMachineFunction(MachineFunction &MF) {
- TII =
- static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
- bool Modified = false;
- for (auto &MBB : MF)
- Modified |= expandMBB(MBB);
- return Modified;
- }
- bool LoongArchExpandAtomicPseudo::expandMBB(MachineBasicBlock &MBB) {
- bool Modified = false;
- MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
- while (MBBI != E) {
- MachineBasicBlock::iterator NMBBI = std::next(MBBI);
- Modified |= expandMI(MBB, MBBI, NMBBI);
- MBBI = NMBBI;
- }
- return Modified;
- }
- bool LoongArchExpandAtomicPseudo::expandMI(
- MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- MachineBasicBlock::iterator &NextMBBI) {
- switch (MBBI->getOpcode()) {
- case LoongArch::PseudoMaskedAtomicSwap32:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xchg, true, 32,
- NextMBBI);
- case LoongArch::PseudoAtomicSwap32:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xchg, false, 32,
- NextMBBI);
- case LoongArch::PseudoMaskedAtomicLoadAdd32:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Add, true, 32, NextMBBI);
- case LoongArch::PseudoMaskedAtomicLoadSub32:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Sub, true, 32, NextMBBI);
- case LoongArch::PseudoAtomicLoadNand32:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 32,
- NextMBBI);
- case LoongArch::PseudoAtomicLoadNand64:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 64,
- NextMBBI);
- case LoongArch::PseudoMaskedAtomicLoadNand32:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, true, 32,
- NextMBBI);
- case LoongArch::PseudoAtomicLoadAdd32:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Add, false, 32,
- NextMBBI);
- case LoongArch::PseudoAtomicLoadSub32:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Sub, false, 32,
- NextMBBI);
- case LoongArch::PseudoAtomicLoadAnd32:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::And, false, 32,
- NextMBBI);
- case LoongArch::PseudoAtomicLoadOr32:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Or, false, 32, NextMBBI);
- case LoongArch::PseudoAtomicLoadXor32:
- return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xor, false, 32,
- NextMBBI);
- case LoongArch::PseudoMaskedAtomicLoadUMax32:
- return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMax, true, 32,
- NextMBBI);
- case LoongArch::PseudoMaskedAtomicLoadUMin32:
- return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMin, true, 32,
- NextMBBI);
- case LoongArch::PseudoCmpXchg32:
- return expandAtomicCmpXchg(MBB, MBBI, false, 32, NextMBBI);
- case LoongArch::PseudoCmpXchg64:
- return expandAtomicCmpXchg(MBB, MBBI, false, 64, NextMBBI);
- case LoongArch::PseudoMaskedCmpXchg32:
- return expandAtomicCmpXchg(MBB, MBBI, true, 32, NextMBBI);
- case LoongArch::PseudoMaskedAtomicLoadMax32:
- return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Max, true, 32,
- NextMBBI);
- case LoongArch::PseudoMaskedAtomicLoadMin32:
- return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Min, true, 32,
- NextMBBI);
- }
- return false;
- }
- static void doAtomicBinOpExpansion(const LoongArchInstrInfo *TII,
- MachineInstr &MI, DebugLoc DL,
- MachineBasicBlock *ThisMBB,
- MachineBasicBlock *LoopMBB,
- MachineBasicBlock *DoneMBB,
- AtomicRMWInst::BinOp BinOp, int Width) {
- Register DestReg = MI.getOperand(0).getReg();
- Register ScratchReg = MI.getOperand(1).getReg();
- Register AddrReg = MI.getOperand(2).getReg();
- Register IncrReg = MI.getOperand(3).getReg();
- AtomicOrdering Ordering =
- static_cast<AtomicOrdering>(MI.getOperand(4).getImm());
- // .loop:
- // if(Ordering != AtomicOrdering::Monotonic)
- // dbar 0
- // ll.[w|d] dest, (addr)
- // binop scratch, dest, val
- // sc.[w|d] scratch, scratch, (addr)
- // beqz scratch, loop
- if (Ordering != AtomicOrdering::Monotonic)
- BuildMI(LoopMBB, DL, TII->get(LoongArch::DBAR)).addImm(0);
- BuildMI(LoopMBB, DL,
- TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)
- .addReg(AddrReg)
- .addImm(0);
- switch (BinOp) {
- default:
- llvm_unreachable("Unexpected AtomicRMW BinOp");
- case AtomicRMWInst::Xchg:
- BuildMI(LoopMBB, DL, TII->get(LoongArch::OR), ScratchReg)
- .addReg(IncrReg)
- .addReg(LoongArch::R0);
- break;
- case AtomicRMWInst::Nand:
- BuildMI(LoopMBB, DL, TII->get(LoongArch::AND), ScratchReg)
- .addReg(DestReg)
- .addReg(IncrReg);
- BuildMI(LoopMBB, DL, TII->get(LoongArch::NOR), ScratchReg)
- .addReg(ScratchReg)
- .addReg(LoongArch::R0);
- break;
- case AtomicRMWInst::Add:
- BuildMI(LoopMBB, DL, TII->get(LoongArch::ADD_W), ScratchReg)
- .addReg(DestReg)
- .addReg(IncrReg);
- break;
- case AtomicRMWInst::Sub:
- BuildMI(LoopMBB, DL, TII->get(LoongArch::SUB_W), ScratchReg)
- .addReg(DestReg)
- .addReg(IncrReg);
- break;
- case AtomicRMWInst::And:
- BuildMI(LoopMBB, DL, TII->get(LoongArch::AND), ScratchReg)
- .addReg(DestReg)
- .addReg(IncrReg);
- break;
- case AtomicRMWInst::Or:
- BuildMI(LoopMBB, DL, TII->get(LoongArch::OR), ScratchReg)
- .addReg(DestReg)
- .addReg(IncrReg);
- break;
- case AtomicRMWInst::Xor:
- BuildMI(LoopMBB, DL, TII->get(LoongArch::XOR), ScratchReg)
- .addReg(DestReg)
- .addReg(IncrReg);
- break;
- }
- BuildMI(LoopMBB, DL,
- TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D), ScratchReg)
- .addReg(ScratchReg)
- .addReg(AddrReg)
- .addImm(0);
- BuildMI(LoopMBB, DL, TII->get(LoongArch::BEQZ))
- .addReg(ScratchReg)
- .addMBB(LoopMBB);
- }
- static void insertMaskedMerge(const LoongArchInstrInfo *TII, DebugLoc DL,
- MachineBasicBlock *MBB, Register DestReg,
- Register OldValReg, Register NewValReg,
- Register MaskReg, Register ScratchReg) {
- assert(OldValReg != ScratchReg && "OldValReg and ScratchReg must be unique");
- assert(OldValReg != MaskReg && "OldValReg and MaskReg must be unique");
- assert(ScratchReg != MaskReg && "ScratchReg and MaskReg must be unique");
- // res = oldval ^ ((oldval ^ newval) & masktargetdata);
- BuildMI(MBB, DL, TII->get(LoongArch::XOR), ScratchReg)
- .addReg(OldValReg)
- .addReg(NewValReg);
- BuildMI(MBB, DL, TII->get(LoongArch::AND), ScratchReg)
- .addReg(ScratchReg)
- .addReg(MaskReg);
- BuildMI(MBB, DL, TII->get(LoongArch::XOR), DestReg)
- .addReg(OldValReg)
- .addReg(ScratchReg);
- }
- static void doMaskedAtomicBinOpExpansion(
- const LoongArchInstrInfo *TII, MachineInstr &MI, DebugLoc DL,
- MachineBasicBlock *ThisMBB, MachineBasicBlock *LoopMBB,
- MachineBasicBlock *DoneMBB, AtomicRMWInst::BinOp BinOp, int Width) {
- assert(Width == 32 && "Should never need to expand masked 64-bit operations");
- Register DestReg = MI.getOperand(0).getReg();
- Register ScratchReg = MI.getOperand(1).getReg();
- Register AddrReg = MI.getOperand(2).getReg();
- Register IncrReg = MI.getOperand(3).getReg();
- Register MaskReg = MI.getOperand(4).getReg();
- AtomicOrdering Ordering =
- static_cast<AtomicOrdering>(MI.getOperand(5).getImm());
- // .loop:
- // if(Ordering != AtomicOrdering::Monotonic)
- // dbar 0
- // ll.w destreg, (alignedaddr)
- // binop scratch, destreg, incr
- // xor scratch, destreg, scratch
- // and scratch, scratch, masktargetdata
- // xor scratch, destreg, scratch
- // sc.w scratch, scratch, (alignedaddr)
- // beqz scratch, loop
- if (Ordering != AtomicOrdering::Monotonic)
- BuildMI(LoopMBB, DL, TII->get(LoongArch::DBAR)).addImm(0);
- BuildMI(LoopMBB, DL, TII->get(LoongArch::LL_W), DestReg)
- .addReg(AddrReg)
- .addImm(0);
- switch (BinOp) {
- default:
- llvm_unreachable("Unexpected AtomicRMW BinOp");
- case AtomicRMWInst::Xchg:
- BuildMI(LoopMBB, DL, TII->get(LoongArch::ADDI_W), ScratchReg)
- .addReg(IncrReg)
- .addImm(0);
- break;
- case AtomicRMWInst::Add:
- BuildMI(LoopMBB, DL, TII->get(LoongArch::ADD_W), ScratchReg)
- .addReg(DestReg)
- .addReg(IncrReg);
- break;
- case AtomicRMWInst::Sub:
- BuildMI(LoopMBB, DL, TII->get(LoongArch::SUB_W), ScratchReg)
- .addReg(DestReg)
- .addReg(IncrReg);
- break;
- case AtomicRMWInst::Nand:
- BuildMI(LoopMBB, DL, TII->get(LoongArch::AND), ScratchReg)
- .addReg(DestReg)
- .addReg(IncrReg);
- BuildMI(LoopMBB, DL, TII->get(LoongArch::NOR), ScratchReg)
- .addReg(ScratchReg)
- .addReg(LoongArch::R0);
- // TODO: support other AtomicRMWInst.
- }
- insertMaskedMerge(TII, DL, LoopMBB, ScratchReg, DestReg, ScratchReg, MaskReg,
- ScratchReg);
- BuildMI(LoopMBB, DL, TII->get(LoongArch::SC_W), ScratchReg)
- .addReg(ScratchReg)
- .addReg(AddrReg)
- .addImm(0);
- BuildMI(LoopMBB, DL, TII->get(LoongArch::BEQZ))
- .addReg(ScratchReg)
- .addMBB(LoopMBB);
- }
- bool LoongArchExpandAtomicPseudo::expandAtomicBinOp(
- MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width,
- MachineBasicBlock::iterator &NextMBBI) {
- MachineInstr &MI = *MBBI;
- DebugLoc DL = MI.getDebugLoc();
- MachineFunction *MF = MBB.getParent();
- auto LoopMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- // Insert new MBBs.
- MF->insert(++MBB.getIterator(), LoopMBB);
- MF->insert(++LoopMBB->getIterator(), DoneMBB);
- // Set up successors and transfer remaining instructions to DoneMBB.
- LoopMBB->addSuccessor(LoopMBB);
- LoopMBB->addSuccessor(DoneMBB);
- DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
- DoneMBB->transferSuccessors(&MBB);
- MBB.addSuccessor(LoopMBB);
- if (IsMasked)
- doMaskedAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp,
- Width);
- else
- doAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp, Width);
- NextMBBI = MBB.end();
- MI.eraseFromParent();
- LivePhysRegs LiveRegs;
- computeAndAddLiveIns(LiveRegs, *LoopMBB);
- computeAndAddLiveIns(LiveRegs, *DoneMBB);
- return true;
- }
- static void insertSext(const LoongArchInstrInfo *TII, DebugLoc DL,
- MachineBasicBlock *MBB, Register ValReg,
- Register ShamtReg) {
- BuildMI(MBB, DL, TII->get(LoongArch::SLL_W), ValReg)
- .addReg(ValReg)
- .addReg(ShamtReg);
- BuildMI(MBB, DL, TII->get(LoongArch::SRA_W), ValReg)
- .addReg(ValReg)
- .addReg(ShamtReg);
- }
- bool LoongArchExpandAtomicPseudo::expandAtomicMinMaxOp(
- MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width,
- MachineBasicBlock::iterator &NextMBBI) {
- assert(IsMasked == true &&
- "Should only need to expand masked atomic max/min");
- assert(Width == 32 && "Should never need to expand masked 64-bit operations");
- MachineInstr &MI = *MBBI;
- DebugLoc DL = MI.getDebugLoc();
- MachineFunction *MF = MBB.getParent();
- auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- auto LoopIfBodyMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- auto TailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- // Insert new MBBs.
- MF->insert(++MBB.getIterator(), LoopHeadMBB);
- MF->insert(++LoopHeadMBB->getIterator(), LoopIfBodyMBB);
- MF->insert(++LoopIfBodyMBB->getIterator(), LoopTailMBB);
- MF->insert(++LoopTailMBB->getIterator(), TailMBB);
- MF->insert(++TailMBB->getIterator(), DoneMBB);
- // Set up successors and transfer remaining instructions to DoneMBB.
- LoopHeadMBB->addSuccessor(LoopIfBodyMBB);
- LoopHeadMBB->addSuccessor(LoopTailMBB);
- LoopIfBodyMBB->addSuccessor(LoopTailMBB);
- LoopTailMBB->addSuccessor(LoopHeadMBB);
- LoopTailMBB->addSuccessor(TailMBB);
- TailMBB->addSuccessor(DoneMBB);
- DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
- DoneMBB->transferSuccessors(&MBB);
- MBB.addSuccessor(LoopHeadMBB);
- Register DestReg = MI.getOperand(0).getReg();
- Register Scratch1Reg = MI.getOperand(1).getReg();
- Register Scratch2Reg = MI.getOperand(2).getReg();
- Register AddrReg = MI.getOperand(3).getReg();
- Register IncrReg = MI.getOperand(4).getReg();
- Register MaskReg = MI.getOperand(5).getReg();
- //
- // .loophead:
- // dbar 0
- // ll.w destreg, (alignedaddr)
- // and scratch2, destreg, mask
- // move scratch1, destreg
- BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::DBAR)).addImm(0);
- BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::LL_W), DestReg)
- .addReg(AddrReg)
- .addImm(0);
- BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::AND), Scratch2Reg)
- .addReg(DestReg)
- .addReg(MaskReg);
- BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::OR), Scratch1Reg)
- .addReg(DestReg)
- .addReg(LoongArch::R0);
- switch (BinOp) {
- default:
- llvm_unreachable("Unexpected AtomicRMW BinOp");
- // bgeu scratch2, incr, .looptail
- case AtomicRMWInst::UMax:
- BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGEU))
- .addReg(Scratch2Reg)
- .addReg(IncrReg)
- .addMBB(LoopTailMBB);
- break;
- // bgeu incr, scratch2, .looptail
- case AtomicRMWInst::UMin:
- BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGEU))
- .addReg(IncrReg)
- .addReg(Scratch2Reg)
- .addMBB(LoopTailMBB);
- break;
- case AtomicRMWInst::Max:
- insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg());
- // bge scratch2, incr, .looptail
- BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGE))
- .addReg(Scratch2Reg)
- .addReg(IncrReg)
- .addMBB(LoopTailMBB);
- break;
- case AtomicRMWInst::Min:
- insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg());
- // bge incr, scratch2, .looptail
- BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BGE))
- .addReg(IncrReg)
- .addReg(Scratch2Reg)
- .addMBB(LoopTailMBB);
- break;
- // TODO: support other AtomicRMWInst.
- }
- // .loopifbody:
- // xor scratch1, destreg, incr
- // and scratch1, scratch1, mask
- // xor scratch1, destreg, scratch1
- insertMaskedMerge(TII, DL, LoopIfBodyMBB, Scratch1Reg, DestReg, IncrReg,
- MaskReg, Scratch1Reg);
- // .looptail:
- // sc.w scratch1, scratch1, (addr)
- // beqz scratch1, loop
- // dbar 0x700
- BuildMI(LoopTailMBB, DL, TII->get(LoongArch::SC_W), Scratch1Reg)
- .addReg(Scratch1Reg)
- .addReg(AddrReg)
- .addImm(0);
- BuildMI(LoopTailMBB, DL, TII->get(LoongArch::BEQZ))
- .addReg(Scratch1Reg)
- .addMBB(LoopHeadMBB);
- // .tail:
- // dbar 0x700
- BuildMI(TailMBB, DL, TII->get(LoongArch::DBAR)).addImm(0x700);
- NextMBBI = MBB.end();
- MI.eraseFromParent();
- LivePhysRegs LiveRegs;
- computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);
- computeAndAddLiveIns(LiveRegs, *LoopIfBodyMBB);
- computeAndAddLiveIns(LiveRegs, *LoopTailMBB);
- computeAndAddLiveIns(LiveRegs, *TailMBB);
- computeAndAddLiveIns(LiveRegs, *DoneMBB);
- return true;
- }
- bool LoongArchExpandAtomicPseudo::expandAtomicCmpXchg(
- MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool IsMasked,
- int Width, MachineBasicBlock::iterator &NextMBBI) {
- MachineInstr &MI = *MBBI;
- DebugLoc DL = MI.getDebugLoc();
- MachineFunction *MF = MBB.getParent();
- auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- auto TailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
- // Insert new MBBs.
- MF->insert(++MBB.getIterator(), LoopHeadMBB);
- MF->insert(++LoopHeadMBB->getIterator(), LoopTailMBB);
- MF->insert(++LoopTailMBB->getIterator(), TailMBB);
- MF->insert(++TailMBB->getIterator(), DoneMBB);
- // Set up successors and transfer remaining instructions to DoneMBB.
- LoopHeadMBB->addSuccessor(LoopTailMBB);
- LoopHeadMBB->addSuccessor(TailMBB);
- LoopTailMBB->addSuccessor(DoneMBB);
- LoopTailMBB->addSuccessor(LoopHeadMBB);
- TailMBB->addSuccessor(DoneMBB);
- DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end());
- DoneMBB->transferSuccessors(&MBB);
- MBB.addSuccessor(LoopHeadMBB);
- Register DestReg = MI.getOperand(0).getReg();
- Register ScratchReg = MI.getOperand(1).getReg();
- Register AddrReg = MI.getOperand(2).getReg();
- Register CmpValReg = MI.getOperand(3).getReg();
- Register NewValReg = MI.getOperand(4).getReg();
- if (!IsMasked) {
- // .loophead:
- // ll.[w|d] dest, (addr)
- // bne dest, cmpval, tail
- BuildMI(LoopHeadMBB, DL,
- TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)
- .addReg(AddrReg)
- .addImm(0);
- BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BNE))
- .addReg(DestReg)
- .addReg(CmpValReg)
- .addMBB(TailMBB);
- // .looptail:
- // dbar 0
- // move scratch, newval
- // sc.[w|d] scratch, scratch, (addr)
- // beqz scratch, loophead
- // b done
- BuildMI(LoopTailMBB, DL, TII->get(LoongArch::DBAR)).addImm(0);
- BuildMI(LoopTailMBB, DL, TII->get(LoongArch::OR), ScratchReg)
- .addReg(NewValReg)
- .addReg(LoongArch::R0);
- BuildMI(LoopTailMBB, DL,
- TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D),
- ScratchReg)
- .addReg(ScratchReg)
- .addReg(AddrReg)
- .addImm(0);
- BuildMI(LoopTailMBB, DL, TII->get(LoongArch::BEQZ))
- .addReg(ScratchReg)
- .addMBB(LoopHeadMBB);
- BuildMI(LoopTailMBB, DL, TII->get(LoongArch::B)).addMBB(DoneMBB);
- } else {
- // .loophead:
- // ll.[w|d] dest, (addr)
- // and scratch, dest, mask
- // bne scratch, cmpval, tail
- Register MaskReg = MI.getOperand(5).getReg();
- BuildMI(LoopHeadMBB, DL,
- TII->get(Width == 32 ? LoongArch::LL_W : LoongArch::LL_D), DestReg)
- .addReg(AddrReg)
- .addImm(0);
- BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::AND), ScratchReg)
- .addReg(DestReg)
- .addReg(MaskReg);
- BuildMI(LoopHeadMBB, DL, TII->get(LoongArch::BNE))
- .addReg(ScratchReg)
- .addReg(CmpValReg)
- .addMBB(TailMBB);
- // .looptail:
- // dbar 0
- // andn scratch, dest, mask
- // or scratch, scratch, newval
- // sc.[w|d] scratch, scratch, (addr)
- // beqz scratch, loophead
- // b done
- BuildMI(LoopTailMBB, DL, TII->get(LoongArch::DBAR)).addImm(0);
- BuildMI(LoopTailMBB, DL, TII->get(LoongArch::ANDN), ScratchReg)
- .addReg(DestReg)
- .addReg(MaskReg);
- BuildMI(LoopTailMBB, DL, TII->get(LoongArch::OR), ScratchReg)
- .addReg(ScratchReg)
- .addReg(NewValReg);
- BuildMI(LoopTailMBB, DL,
- TII->get(Width == 32 ? LoongArch::SC_W : LoongArch::SC_D),
- ScratchReg)
- .addReg(ScratchReg)
- .addReg(AddrReg)
- .addImm(0);
- BuildMI(LoopTailMBB, DL, TII->get(LoongArch::BEQZ))
- .addReg(ScratchReg)
- .addMBB(LoopHeadMBB);
- BuildMI(LoopTailMBB, DL, TII->get(LoongArch::B)).addMBB(DoneMBB);
- }
- // .tail:
- // dbar 0x700
- BuildMI(TailMBB, DL, TII->get(LoongArch::DBAR)).addImm(0x700);
- NextMBBI = MBB.end();
- MI.eraseFromParent();
- LivePhysRegs LiveRegs;
- computeAndAddLiveIns(LiveRegs, *LoopHeadMBB);
- computeAndAddLiveIns(LiveRegs, *LoopTailMBB);
- computeAndAddLiveIns(LiveRegs, *TailMBB);
- computeAndAddLiveIns(LiveRegs, *DoneMBB);
- return true;
- }
- } // end namespace
- INITIALIZE_PASS(LoongArchExpandAtomicPseudo, "loongarch-expand-atomic-pseudo",
- LoongArch_EXPAND_ATOMIC_PSEUDO_NAME, false, false)
- namespace llvm {
- FunctionPass *createLoongArchExpandAtomicPseudoPass() {
- return new LoongArchExpandAtomicPseudo();
- }
- } // end namespace llvm
|