15ffd83dbSDimitry Andric //===-- RISCVExpandAtomicPseudoInsts.cpp - Expand atomic pseudo instrs. ---===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 95ffd83dbSDimitry Andric // This file contains a pass that expands atomic pseudo instructions into 105ffd83dbSDimitry Andric // target instructions. This pass should be run at the last possible moment, 115ffd83dbSDimitry Andric // avoiding the possibility for other passes to break the requirements for 125ffd83dbSDimitry Andric // forward progress in the LR/SC block. 135ffd83dbSDimitry Andric // 145ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 155ffd83dbSDimitry Andric 165ffd83dbSDimitry Andric #include "RISCV.h" 175ffd83dbSDimitry Andric #include "RISCVInstrInfo.h" 185ffd83dbSDimitry Andric #include "RISCVTargetMachine.h" 195ffd83dbSDimitry Andric 205ffd83dbSDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h" 215ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 225ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 235ffd83dbSDimitry Andric 245ffd83dbSDimitry Andric using namespace llvm; 255ffd83dbSDimitry Andric 265ffd83dbSDimitry Andric #define RISCV_EXPAND_ATOMIC_PSEUDO_NAME \ 275ffd83dbSDimitry Andric "RISCV atomic pseudo instruction expansion pass" 285ffd83dbSDimitry Andric 295ffd83dbSDimitry Andric namespace { 305ffd83dbSDimitry Andric 315ffd83dbSDimitry Andric class RISCVExpandAtomicPseudo : public MachineFunctionPass { 325ffd83dbSDimitry Andric public: 335ffd83dbSDimitry Andric const RISCVInstrInfo *TII; 345ffd83dbSDimitry Andric static char ID; 355ffd83dbSDimitry Andric 365ffd83dbSDimitry Andric RISCVExpandAtomicPseudo() : MachineFunctionPass(ID) { 375ffd83dbSDimitry Andric initializeRISCVExpandAtomicPseudoPass(*PassRegistry::getPassRegistry()); 385ffd83dbSDimitry Andric } 395ffd83dbSDimitry Andric 405ffd83dbSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 415ffd83dbSDimitry Andric 425ffd83dbSDimitry Andric StringRef getPassName() const override { 435ffd83dbSDimitry Andric return RISCV_EXPAND_ATOMIC_PSEUDO_NAME; 445ffd83dbSDimitry Andric } 455ffd83dbSDimitry Andric 465ffd83dbSDimitry Andric private: 475ffd83dbSDimitry Andric bool expandMBB(MachineBasicBlock &MBB); 485ffd83dbSDimitry Andric bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 495ffd83dbSDimitry Andric MachineBasicBlock::iterator &NextMBBI); 505ffd83dbSDimitry Andric bool expandAtomicBinOp(MachineBasicBlock &MBB, 515ffd83dbSDimitry Andric MachineBasicBlock::iterator MBBI, AtomicRMWInst::BinOp, 525ffd83dbSDimitry Andric bool IsMasked, int Width, 535ffd83dbSDimitry Andric MachineBasicBlock::iterator &NextMBBI); 545ffd83dbSDimitry Andric bool expandAtomicMinMaxOp(MachineBasicBlock &MBB, 555ffd83dbSDimitry Andric MachineBasicBlock::iterator MBBI, 565ffd83dbSDimitry Andric AtomicRMWInst::BinOp, bool IsMasked, int Width, 575ffd83dbSDimitry Andric MachineBasicBlock::iterator &NextMBBI); 585ffd83dbSDimitry Andric bool expandAtomicCmpXchg(MachineBasicBlock &MBB, 595ffd83dbSDimitry Andric MachineBasicBlock::iterator MBBI, bool IsMasked, 605ffd83dbSDimitry Andric int Width, MachineBasicBlock::iterator &NextMBBI); 615ffd83dbSDimitry Andric }; 625ffd83dbSDimitry Andric 635ffd83dbSDimitry Andric char RISCVExpandAtomicPseudo::ID = 0; 645ffd83dbSDimitry Andric 655ffd83dbSDimitry Andric bool RISCVExpandAtomicPseudo::runOnMachineFunction(MachineFunction &MF) { 665ffd83dbSDimitry Andric TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo()); 675ffd83dbSDimitry Andric bool Modified = false; 685ffd83dbSDimitry Andric for (auto &MBB : MF) 695ffd83dbSDimitry Andric Modified |= expandMBB(MBB); 705ffd83dbSDimitry Andric return Modified; 715ffd83dbSDimitry Andric } 725ffd83dbSDimitry Andric 735ffd83dbSDimitry Andric bool RISCVExpandAtomicPseudo::expandMBB(MachineBasicBlock &MBB) { 745ffd83dbSDimitry Andric bool Modified = false; 755ffd83dbSDimitry Andric 765ffd83dbSDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 775ffd83dbSDimitry Andric while (MBBI != E) { 785ffd83dbSDimitry Andric MachineBasicBlock::iterator NMBBI = std::next(MBBI); 795ffd83dbSDimitry Andric Modified |= expandMI(MBB, MBBI, NMBBI); 805ffd83dbSDimitry Andric MBBI = NMBBI; 815ffd83dbSDimitry Andric } 825ffd83dbSDimitry Andric 835ffd83dbSDimitry Andric return Modified; 845ffd83dbSDimitry Andric } 855ffd83dbSDimitry Andric 865ffd83dbSDimitry Andric bool RISCVExpandAtomicPseudo::expandMI(MachineBasicBlock &MBB, 875ffd83dbSDimitry Andric MachineBasicBlock::iterator MBBI, 885ffd83dbSDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 89*1fd87a68SDimitry Andric // RISCVInstrInfo::getInstSizeInBytes expects that the total size of the 90*1fd87a68SDimitry Andric // expanded instructions for each pseudo is correct in the Size field of the 91*1fd87a68SDimitry Andric // tablegen definition for the pseudo. 925ffd83dbSDimitry Andric switch (MBBI->getOpcode()) { 935ffd83dbSDimitry Andric case RISCV::PseudoAtomicLoadNand32: 945ffd83dbSDimitry Andric return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 32, 955ffd83dbSDimitry Andric NextMBBI); 965ffd83dbSDimitry Andric case RISCV::PseudoAtomicLoadNand64: 975ffd83dbSDimitry Andric return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, false, 64, 985ffd83dbSDimitry Andric NextMBBI); 995ffd83dbSDimitry Andric case RISCV::PseudoMaskedAtomicSwap32: 1005ffd83dbSDimitry Andric return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Xchg, true, 32, 1015ffd83dbSDimitry Andric NextMBBI); 1025ffd83dbSDimitry Andric case RISCV::PseudoMaskedAtomicLoadAdd32: 1035ffd83dbSDimitry Andric return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Add, true, 32, NextMBBI); 1045ffd83dbSDimitry Andric case RISCV::PseudoMaskedAtomicLoadSub32: 1055ffd83dbSDimitry Andric return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Sub, true, 32, NextMBBI); 1065ffd83dbSDimitry Andric case RISCV::PseudoMaskedAtomicLoadNand32: 1075ffd83dbSDimitry Andric return expandAtomicBinOp(MBB, MBBI, AtomicRMWInst::Nand, true, 32, 1085ffd83dbSDimitry Andric NextMBBI); 1095ffd83dbSDimitry Andric case RISCV::PseudoMaskedAtomicLoadMax32: 1105ffd83dbSDimitry Andric return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Max, true, 32, 1115ffd83dbSDimitry Andric NextMBBI); 1125ffd83dbSDimitry Andric case RISCV::PseudoMaskedAtomicLoadMin32: 1135ffd83dbSDimitry Andric return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::Min, true, 32, 1145ffd83dbSDimitry Andric NextMBBI); 1155ffd83dbSDimitry Andric case RISCV::PseudoMaskedAtomicLoadUMax32: 1165ffd83dbSDimitry Andric return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMax, true, 32, 1175ffd83dbSDimitry Andric NextMBBI); 1185ffd83dbSDimitry Andric case RISCV::PseudoMaskedAtomicLoadUMin32: 1195ffd83dbSDimitry Andric return expandAtomicMinMaxOp(MBB, MBBI, AtomicRMWInst::UMin, true, 32, 1205ffd83dbSDimitry Andric NextMBBI); 1215ffd83dbSDimitry Andric case RISCV::PseudoCmpXchg32: 1225ffd83dbSDimitry Andric return expandAtomicCmpXchg(MBB, MBBI, false, 32, NextMBBI); 1235ffd83dbSDimitry Andric case RISCV::PseudoCmpXchg64: 1245ffd83dbSDimitry Andric return expandAtomicCmpXchg(MBB, MBBI, false, 64, NextMBBI); 1255ffd83dbSDimitry Andric case RISCV::PseudoMaskedCmpXchg32: 1265ffd83dbSDimitry Andric return expandAtomicCmpXchg(MBB, MBBI, true, 32, NextMBBI); 1275ffd83dbSDimitry Andric } 1285ffd83dbSDimitry Andric 1295ffd83dbSDimitry Andric return false; 1305ffd83dbSDimitry Andric } 1315ffd83dbSDimitry Andric 1325ffd83dbSDimitry Andric static unsigned getLRForRMW32(AtomicOrdering Ordering) { 1335ffd83dbSDimitry Andric switch (Ordering) { 1345ffd83dbSDimitry Andric default: 1355ffd83dbSDimitry Andric llvm_unreachable("Unexpected AtomicOrdering"); 1365ffd83dbSDimitry Andric case AtomicOrdering::Monotonic: 1375ffd83dbSDimitry Andric return RISCV::LR_W; 1385ffd83dbSDimitry Andric case AtomicOrdering::Acquire: 1395ffd83dbSDimitry Andric return RISCV::LR_W_AQ; 1405ffd83dbSDimitry Andric case AtomicOrdering::Release: 1415ffd83dbSDimitry Andric return RISCV::LR_W; 1425ffd83dbSDimitry Andric case AtomicOrdering::AcquireRelease: 1435ffd83dbSDimitry Andric return RISCV::LR_W_AQ; 1445ffd83dbSDimitry Andric case AtomicOrdering::SequentiallyConsistent: 1455ffd83dbSDimitry Andric return RISCV::LR_W_AQ_RL; 1465ffd83dbSDimitry Andric } 1475ffd83dbSDimitry Andric } 1485ffd83dbSDimitry Andric 1495ffd83dbSDimitry Andric static unsigned getSCForRMW32(AtomicOrdering Ordering) { 1505ffd83dbSDimitry Andric switch (Ordering) { 1515ffd83dbSDimitry Andric default: 1525ffd83dbSDimitry Andric llvm_unreachable("Unexpected AtomicOrdering"); 1535ffd83dbSDimitry Andric case AtomicOrdering::Monotonic: 1545ffd83dbSDimitry Andric return RISCV::SC_W; 1555ffd83dbSDimitry Andric case AtomicOrdering::Acquire: 1565ffd83dbSDimitry Andric return RISCV::SC_W; 1575ffd83dbSDimitry Andric case AtomicOrdering::Release: 1585ffd83dbSDimitry Andric return RISCV::SC_W_RL; 1595ffd83dbSDimitry Andric case AtomicOrdering::AcquireRelease: 1605ffd83dbSDimitry Andric return RISCV::SC_W_RL; 1615ffd83dbSDimitry Andric case AtomicOrdering::SequentiallyConsistent: 1625ffd83dbSDimitry Andric return RISCV::SC_W_AQ_RL; 1635ffd83dbSDimitry Andric } 1645ffd83dbSDimitry Andric } 1655ffd83dbSDimitry Andric 1665ffd83dbSDimitry Andric static unsigned getLRForRMW64(AtomicOrdering Ordering) { 1675ffd83dbSDimitry Andric switch (Ordering) { 1685ffd83dbSDimitry Andric default: 1695ffd83dbSDimitry Andric llvm_unreachable("Unexpected AtomicOrdering"); 1705ffd83dbSDimitry Andric case AtomicOrdering::Monotonic: 1715ffd83dbSDimitry Andric return RISCV::LR_D; 1725ffd83dbSDimitry Andric case AtomicOrdering::Acquire: 1735ffd83dbSDimitry Andric return RISCV::LR_D_AQ; 1745ffd83dbSDimitry Andric case AtomicOrdering::Release: 1755ffd83dbSDimitry Andric return RISCV::LR_D; 1765ffd83dbSDimitry Andric case AtomicOrdering::AcquireRelease: 1775ffd83dbSDimitry Andric return RISCV::LR_D_AQ; 1785ffd83dbSDimitry Andric case AtomicOrdering::SequentiallyConsistent: 1795ffd83dbSDimitry Andric return RISCV::LR_D_AQ_RL; 1805ffd83dbSDimitry Andric } 1815ffd83dbSDimitry Andric } 1825ffd83dbSDimitry Andric 1835ffd83dbSDimitry Andric static unsigned getSCForRMW64(AtomicOrdering Ordering) { 1845ffd83dbSDimitry Andric switch (Ordering) { 1855ffd83dbSDimitry Andric default: 1865ffd83dbSDimitry Andric llvm_unreachable("Unexpected AtomicOrdering"); 1875ffd83dbSDimitry Andric case AtomicOrdering::Monotonic: 1885ffd83dbSDimitry Andric return RISCV::SC_D; 1895ffd83dbSDimitry Andric case AtomicOrdering::Acquire: 1905ffd83dbSDimitry Andric return RISCV::SC_D; 1915ffd83dbSDimitry Andric case AtomicOrdering::Release: 1925ffd83dbSDimitry Andric return RISCV::SC_D_RL; 1935ffd83dbSDimitry Andric case AtomicOrdering::AcquireRelease: 1945ffd83dbSDimitry Andric return RISCV::SC_D_RL; 1955ffd83dbSDimitry Andric case AtomicOrdering::SequentiallyConsistent: 1965ffd83dbSDimitry Andric return RISCV::SC_D_AQ_RL; 1975ffd83dbSDimitry Andric } 1985ffd83dbSDimitry Andric } 1995ffd83dbSDimitry Andric 2005ffd83dbSDimitry Andric static unsigned getLRForRMW(AtomicOrdering Ordering, int Width) { 2015ffd83dbSDimitry Andric if (Width == 32) 2025ffd83dbSDimitry Andric return getLRForRMW32(Ordering); 2035ffd83dbSDimitry Andric if (Width == 64) 2045ffd83dbSDimitry Andric return getLRForRMW64(Ordering); 2055ffd83dbSDimitry Andric llvm_unreachable("Unexpected LR width\n"); 2065ffd83dbSDimitry Andric } 2075ffd83dbSDimitry Andric 2085ffd83dbSDimitry Andric static unsigned getSCForRMW(AtomicOrdering Ordering, int Width) { 2095ffd83dbSDimitry Andric if (Width == 32) 2105ffd83dbSDimitry Andric return getSCForRMW32(Ordering); 2115ffd83dbSDimitry Andric if (Width == 64) 2125ffd83dbSDimitry Andric return getSCForRMW64(Ordering); 2135ffd83dbSDimitry Andric llvm_unreachable("Unexpected SC width\n"); 2145ffd83dbSDimitry Andric } 2155ffd83dbSDimitry Andric 2165ffd83dbSDimitry Andric static void doAtomicBinOpExpansion(const RISCVInstrInfo *TII, MachineInstr &MI, 2175ffd83dbSDimitry Andric DebugLoc DL, MachineBasicBlock *ThisMBB, 2185ffd83dbSDimitry Andric MachineBasicBlock *LoopMBB, 2195ffd83dbSDimitry Andric MachineBasicBlock *DoneMBB, 2205ffd83dbSDimitry Andric AtomicRMWInst::BinOp BinOp, int Width) { 2215ffd83dbSDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 2225ffd83dbSDimitry Andric Register ScratchReg = MI.getOperand(1).getReg(); 2235ffd83dbSDimitry Andric Register AddrReg = MI.getOperand(2).getReg(); 2245ffd83dbSDimitry Andric Register IncrReg = MI.getOperand(3).getReg(); 2255ffd83dbSDimitry Andric AtomicOrdering Ordering = 2265ffd83dbSDimitry Andric static_cast<AtomicOrdering>(MI.getOperand(4).getImm()); 2275ffd83dbSDimitry Andric 2285ffd83dbSDimitry Andric // .loop: 2295ffd83dbSDimitry Andric // lr.[w|d] dest, (addr) 2305ffd83dbSDimitry Andric // binop scratch, dest, val 2315ffd83dbSDimitry Andric // sc.[w|d] scratch, scratch, (addr) 2325ffd83dbSDimitry Andric // bnez scratch, loop 2335ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(getLRForRMW(Ordering, Width)), DestReg) 2345ffd83dbSDimitry Andric .addReg(AddrReg); 2355ffd83dbSDimitry Andric switch (BinOp) { 2365ffd83dbSDimitry Andric default: 2375ffd83dbSDimitry Andric llvm_unreachable("Unexpected AtomicRMW BinOp"); 2385ffd83dbSDimitry Andric case AtomicRMWInst::Nand: 2395ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(RISCV::AND), ScratchReg) 2405ffd83dbSDimitry Andric .addReg(DestReg) 2415ffd83dbSDimitry Andric .addReg(IncrReg); 2425ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(RISCV::XORI), ScratchReg) 2435ffd83dbSDimitry Andric .addReg(ScratchReg) 2445ffd83dbSDimitry Andric .addImm(-1); 2455ffd83dbSDimitry Andric break; 2465ffd83dbSDimitry Andric } 2475ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(getSCForRMW(Ordering, Width)), ScratchReg) 2485ffd83dbSDimitry Andric .addReg(AddrReg) 2495ffd83dbSDimitry Andric .addReg(ScratchReg); 2505ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(RISCV::BNE)) 2515ffd83dbSDimitry Andric .addReg(ScratchReg) 2525ffd83dbSDimitry Andric .addReg(RISCV::X0) 2535ffd83dbSDimitry Andric .addMBB(LoopMBB); 2545ffd83dbSDimitry Andric } 2555ffd83dbSDimitry Andric 2565ffd83dbSDimitry Andric static void insertMaskedMerge(const RISCVInstrInfo *TII, DebugLoc DL, 2575ffd83dbSDimitry Andric MachineBasicBlock *MBB, Register DestReg, 2585ffd83dbSDimitry Andric Register OldValReg, Register NewValReg, 2595ffd83dbSDimitry Andric Register MaskReg, Register ScratchReg) { 2605ffd83dbSDimitry Andric assert(OldValReg != ScratchReg && "OldValReg and ScratchReg must be unique"); 2615ffd83dbSDimitry Andric assert(OldValReg != MaskReg && "OldValReg and MaskReg must be unique"); 2625ffd83dbSDimitry Andric assert(ScratchReg != MaskReg && "ScratchReg and MaskReg must be unique"); 2635ffd83dbSDimitry Andric 2645ffd83dbSDimitry Andric // We select bits from newval and oldval using: 2655ffd83dbSDimitry Andric // https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge 2665ffd83dbSDimitry Andric // r = oldval ^ ((oldval ^ newval) & masktargetdata); 2675ffd83dbSDimitry Andric BuildMI(MBB, DL, TII->get(RISCV::XOR), ScratchReg) 2685ffd83dbSDimitry Andric .addReg(OldValReg) 2695ffd83dbSDimitry Andric .addReg(NewValReg); 2705ffd83dbSDimitry Andric BuildMI(MBB, DL, TII->get(RISCV::AND), ScratchReg) 2715ffd83dbSDimitry Andric .addReg(ScratchReg) 2725ffd83dbSDimitry Andric .addReg(MaskReg); 2735ffd83dbSDimitry Andric BuildMI(MBB, DL, TII->get(RISCV::XOR), DestReg) 2745ffd83dbSDimitry Andric .addReg(OldValReg) 2755ffd83dbSDimitry Andric .addReg(ScratchReg); 2765ffd83dbSDimitry Andric } 2775ffd83dbSDimitry Andric 2785ffd83dbSDimitry Andric static void doMaskedAtomicBinOpExpansion( 2795ffd83dbSDimitry Andric const RISCVInstrInfo *TII, MachineInstr &MI, DebugLoc DL, 2805ffd83dbSDimitry Andric MachineBasicBlock *ThisMBB, MachineBasicBlock *LoopMBB, 2815ffd83dbSDimitry Andric MachineBasicBlock *DoneMBB, AtomicRMWInst::BinOp BinOp, int Width) { 2825ffd83dbSDimitry Andric assert(Width == 32 && "Should never need to expand masked 64-bit operations"); 2835ffd83dbSDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 2845ffd83dbSDimitry Andric Register ScratchReg = MI.getOperand(1).getReg(); 2855ffd83dbSDimitry Andric Register AddrReg = MI.getOperand(2).getReg(); 2865ffd83dbSDimitry Andric Register IncrReg = MI.getOperand(3).getReg(); 2875ffd83dbSDimitry Andric Register MaskReg = MI.getOperand(4).getReg(); 2885ffd83dbSDimitry Andric AtomicOrdering Ordering = 2895ffd83dbSDimitry Andric static_cast<AtomicOrdering>(MI.getOperand(5).getImm()); 2905ffd83dbSDimitry Andric 2915ffd83dbSDimitry Andric // .loop: 2925ffd83dbSDimitry Andric // lr.w destreg, (alignedaddr) 2935ffd83dbSDimitry Andric // binop scratch, destreg, incr 2945ffd83dbSDimitry Andric // xor scratch, destreg, scratch 2955ffd83dbSDimitry Andric // and scratch, scratch, masktargetdata 2965ffd83dbSDimitry Andric // xor scratch, destreg, scratch 2975ffd83dbSDimitry Andric // sc.w scratch, scratch, (alignedaddr) 2985ffd83dbSDimitry Andric // bnez scratch, loop 2995ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(getLRForRMW32(Ordering)), DestReg) 3005ffd83dbSDimitry Andric .addReg(AddrReg); 3015ffd83dbSDimitry Andric switch (BinOp) { 3025ffd83dbSDimitry Andric default: 3035ffd83dbSDimitry Andric llvm_unreachable("Unexpected AtomicRMW BinOp"); 3045ffd83dbSDimitry Andric case AtomicRMWInst::Xchg: 3055ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(RISCV::ADDI), ScratchReg) 3065ffd83dbSDimitry Andric .addReg(IncrReg) 3075ffd83dbSDimitry Andric .addImm(0); 3085ffd83dbSDimitry Andric break; 3095ffd83dbSDimitry Andric case AtomicRMWInst::Add: 3105ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(RISCV::ADD), ScratchReg) 3115ffd83dbSDimitry Andric .addReg(DestReg) 3125ffd83dbSDimitry Andric .addReg(IncrReg); 3135ffd83dbSDimitry Andric break; 3145ffd83dbSDimitry Andric case AtomicRMWInst::Sub: 3155ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(RISCV::SUB), ScratchReg) 3165ffd83dbSDimitry Andric .addReg(DestReg) 3175ffd83dbSDimitry Andric .addReg(IncrReg); 3185ffd83dbSDimitry Andric break; 3195ffd83dbSDimitry Andric case AtomicRMWInst::Nand: 3205ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(RISCV::AND), ScratchReg) 3215ffd83dbSDimitry Andric .addReg(DestReg) 3225ffd83dbSDimitry Andric .addReg(IncrReg); 3235ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(RISCV::XORI), ScratchReg) 3245ffd83dbSDimitry Andric .addReg(ScratchReg) 3255ffd83dbSDimitry Andric .addImm(-1); 3265ffd83dbSDimitry Andric break; 3275ffd83dbSDimitry Andric } 3285ffd83dbSDimitry Andric 3295ffd83dbSDimitry Andric insertMaskedMerge(TII, DL, LoopMBB, ScratchReg, DestReg, ScratchReg, MaskReg, 3305ffd83dbSDimitry Andric ScratchReg); 3315ffd83dbSDimitry Andric 3325ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(getSCForRMW32(Ordering)), ScratchReg) 3335ffd83dbSDimitry Andric .addReg(AddrReg) 3345ffd83dbSDimitry Andric .addReg(ScratchReg); 3355ffd83dbSDimitry Andric BuildMI(LoopMBB, DL, TII->get(RISCV::BNE)) 3365ffd83dbSDimitry Andric .addReg(ScratchReg) 3375ffd83dbSDimitry Andric .addReg(RISCV::X0) 3385ffd83dbSDimitry Andric .addMBB(LoopMBB); 3395ffd83dbSDimitry Andric } 3405ffd83dbSDimitry Andric 3415ffd83dbSDimitry Andric bool RISCVExpandAtomicPseudo::expandAtomicBinOp( 3425ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 3435ffd83dbSDimitry Andric AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width, 3445ffd83dbSDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 3455ffd83dbSDimitry Andric MachineInstr &MI = *MBBI; 3465ffd83dbSDimitry Andric DebugLoc DL = MI.getDebugLoc(); 3475ffd83dbSDimitry Andric 3485ffd83dbSDimitry Andric MachineFunction *MF = MBB.getParent(); 3495ffd83dbSDimitry Andric auto LoopMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 3505ffd83dbSDimitry Andric auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 3515ffd83dbSDimitry Andric 3525ffd83dbSDimitry Andric // Insert new MBBs. 3535ffd83dbSDimitry Andric MF->insert(++MBB.getIterator(), LoopMBB); 3545ffd83dbSDimitry Andric MF->insert(++LoopMBB->getIterator(), DoneMBB); 3555ffd83dbSDimitry Andric 3565ffd83dbSDimitry Andric // Set up successors and transfer remaining instructions to DoneMBB. 3575ffd83dbSDimitry Andric LoopMBB->addSuccessor(LoopMBB); 3585ffd83dbSDimitry Andric LoopMBB->addSuccessor(DoneMBB); 3595ffd83dbSDimitry Andric DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end()); 3605ffd83dbSDimitry Andric DoneMBB->transferSuccessors(&MBB); 3615ffd83dbSDimitry Andric MBB.addSuccessor(LoopMBB); 3625ffd83dbSDimitry Andric 3635ffd83dbSDimitry Andric if (!IsMasked) 3645ffd83dbSDimitry Andric doAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp, Width); 3655ffd83dbSDimitry Andric else 3665ffd83dbSDimitry Andric doMaskedAtomicBinOpExpansion(TII, MI, DL, &MBB, LoopMBB, DoneMBB, BinOp, 3675ffd83dbSDimitry Andric Width); 3685ffd83dbSDimitry Andric 3695ffd83dbSDimitry Andric NextMBBI = MBB.end(); 3705ffd83dbSDimitry Andric MI.eraseFromParent(); 3715ffd83dbSDimitry Andric 3725ffd83dbSDimitry Andric LivePhysRegs LiveRegs; 3735ffd83dbSDimitry Andric computeAndAddLiveIns(LiveRegs, *LoopMBB); 3745ffd83dbSDimitry Andric computeAndAddLiveIns(LiveRegs, *DoneMBB); 3755ffd83dbSDimitry Andric 3765ffd83dbSDimitry Andric return true; 3775ffd83dbSDimitry Andric } 3785ffd83dbSDimitry Andric 3795ffd83dbSDimitry Andric static void insertSext(const RISCVInstrInfo *TII, DebugLoc DL, 3805ffd83dbSDimitry Andric MachineBasicBlock *MBB, Register ValReg, 3815ffd83dbSDimitry Andric Register ShamtReg) { 3825ffd83dbSDimitry Andric BuildMI(MBB, DL, TII->get(RISCV::SLL), ValReg) 3835ffd83dbSDimitry Andric .addReg(ValReg) 3845ffd83dbSDimitry Andric .addReg(ShamtReg); 3855ffd83dbSDimitry Andric BuildMI(MBB, DL, TII->get(RISCV::SRA), ValReg) 3865ffd83dbSDimitry Andric .addReg(ValReg) 3875ffd83dbSDimitry Andric .addReg(ShamtReg); 3885ffd83dbSDimitry Andric } 3895ffd83dbSDimitry Andric 3905ffd83dbSDimitry Andric bool RISCVExpandAtomicPseudo::expandAtomicMinMaxOp( 3915ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 3925ffd83dbSDimitry Andric AtomicRMWInst::BinOp BinOp, bool IsMasked, int Width, 3935ffd83dbSDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 3945ffd83dbSDimitry Andric assert(IsMasked == true && 3955ffd83dbSDimitry Andric "Should only need to expand masked atomic max/min"); 3965ffd83dbSDimitry Andric assert(Width == 32 && "Should never need to expand masked 64-bit operations"); 3975ffd83dbSDimitry Andric 3985ffd83dbSDimitry Andric MachineInstr &MI = *MBBI; 3995ffd83dbSDimitry Andric DebugLoc DL = MI.getDebugLoc(); 4005ffd83dbSDimitry Andric MachineFunction *MF = MBB.getParent(); 4015ffd83dbSDimitry Andric auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 4025ffd83dbSDimitry Andric auto LoopIfBodyMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 4035ffd83dbSDimitry Andric auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 4045ffd83dbSDimitry Andric auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 4055ffd83dbSDimitry Andric 4065ffd83dbSDimitry Andric // Insert new MBBs. 4075ffd83dbSDimitry Andric MF->insert(++MBB.getIterator(), LoopHeadMBB); 4085ffd83dbSDimitry Andric MF->insert(++LoopHeadMBB->getIterator(), LoopIfBodyMBB); 4095ffd83dbSDimitry Andric MF->insert(++LoopIfBodyMBB->getIterator(), LoopTailMBB); 4105ffd83dbSDimitry Andric MF->insert(++LoopTailMBB->getIterator(), DoneMBB); 4115ffd83dbSDimitry Andric 4125ffd83dbSDimitry Andric // Set up successors and transfer remaining instructions to DoneMBB. 4135ffd83dbSDimitry Andric LoopHeadMBB->addSuccessor(LoopIfBodyMBB); 4145ffd83dbSDimitry Andric LoopHeadMBB->addSuccessor(LoopTailMBB); 4155ffd83dbSDimitry Andric LoopIfBodyMBB->addSuccessor(LoopTailMBB); 4165ffd83dbSDimitry Andric LoopTailMBB->addSuccessor(LoopHeadMBB); 4175ffd83dbSDimitry Andric LoopTailMBB->addSuccessor(DoneMBB); 4185ffd83dbSDimitry Andric DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end()); 4195ffd83dbSDimitry Andric DoneMBB->transferSuccessors(&MBB); 4205ffd83dbSDimitry Andric MBB.addSuccessor(LoopHeadMBB); 4215ffd83dbSDimitry Andric 4225ffd83dbSDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 4235ffd83dbSDimitry Andric Register Scratch1Reg = MI.getOperand(1).getReg(); 4245ffd83dbSDimitry Andric Register Scratch2Reg = MI.getOperand(2).getReg(); 4255ffd83dbSDimitry Andric Register AddrReg = MI.getOperand(3).getReg(); 4265ffd83dbSDimitry Andric Register IncrReg = MI.getOperand(4).getReg(); 4275ffd83dbSDimitry Andric Register MaskReg = MI.getOperand(5).getReg(); 4285ffd83dbSDimitry Andric bool IsSigned = BinOp == AtomicRMWInst::Min || BinOp == AtomicRMWInst::Max; 4295ffd83dbSDimitry Andric AtomicOrdering Ordering = 4305ffd83dbSDimitry Andric static_cast<AtomicOrdering>(MI.getOperand(IsSigned ? 7 : 6).getImm()); 4315ffd83dbSDimitry Andric 4325ffd83dbSDimitry Andric // 4335ffd83dbSDimitry Andric // .loophead: 4345ffd83dbSDimitry Andric // lr.w destreg, (alignedaddr) 4355ffd83dbSDimitry Andric // and scratch2, destreg, mask 4365ffd83dbSDimitry Andric // mv scratch1, destreg 4375ffd83dbSDimitry Andric // [sext scratch2 if signed min/max] 4385ffd83dbSDimitry Andric // ifnochangeneeded scratch2, incr, .looptail 4395ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(getLRForRMW32(Ordering)), DestReg) 4405ffd83dbSDimitry Andric .addReg(AddrReg); 4415ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(RISCV::AND), Scratch2Reg) 4425ffd83dbSDimitry Andric .addReg(DestReg) 4435ffd83dbSDimitry Andric .addReg(MaskReg); 4445ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(RISCV::ADDI), Scratch1Reg) 4455ffd83dbSDimitry Andric .addReg(DestReg) 4465ffd83dbSDimitry Andric .addImm(0); 4475ffd83dbSDimitry Andric 4485ffd83dbSDimitry Andric switch (BinOp) { 4495ffd83dbSDimitry Andric default: 4505ffd83dbSDimitry Andric llvm_unreachable("Unexpected AtomicRMW BinOp"); 4515ffd83dbSDimitry Andric case AtomicRMWInst::Max: { 4525ffd83dbSDimitry Andric insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg()); 4535ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGE)) 4545ffd83dbSDimitry Andric .addReg(Scratch2Reg) 4555ffd83dbSDimitry Andric .addReg(IncrReg) 4565ffd83dbSDimitry Andric .addMBB(LoopTailMBB); 4575ffd83dbSDimitry Andric break; 4585ffd83dbSDimitry Andric } 4595ffd83dbSDimitry Andric case AtomicRMWInst::Min: { 4605ffd83dbSDimitry Andric insertSext(TII, DL, LoopHeadMBB, Scratch2Reg, MI.getOperand(6).getReg()); 4615ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGE)) 4625ffd83dbSDimitry Andric .addReg(IncrReg) 4635ffd83dbSDimitry Andric .addReg(Scratch2Reg) 4645ffd83dbSDimitry Andric .addMBB(LoopTailMBB); 4655ffd83dbSDimitry Andric break; 4665ffd83dbSDimitry Andric } 4675ffd83dbSDimitry Andric case AtomicRMWInst::UMax: 4685ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGEU)) 4695ffd83dbSDimitry Andric .addReg(Scratch2Reg) 4705ffd83dbSDimitry Andric .addReg(IncrReg) 4715ffd83dbSDimitry Andric .addMBB(LoopTailMBB); 4725ffd83dbSDimitry Andric break; 4735ffd83dbSDimitry Andric case AtomicRMWInst::UMin: 4745ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BGEU)) 4755ffd83dbSDimitry Andric .addReg(IncrReg) 4765ffd83dbSDimitry Andric .addReg(Scratch2Reg) 4775ffd83dbSDimitry Andric .addMBB(LoopTailMBB); 4785ffd83dbSDimitry Andric break; 4795ffd83dbSDimitry Andric } 4805ffd83dbSDimitry Andric 4815ffd83dbSDimitry Andric // .loopifbody: 4825ffd83dbSDimitry Andric // xor scratch1, destreg, incr 4835ffd83dbSDimitry Andric // and scratch1, scratch1, mask 4845ffd83dbSDimitry Andric // xor scratch1, destreg, scratch1 4855ffd83dbSDimitry Andric insertMaskedMerge(TII, DL, LoopIfBodyMBB, Scratch1Reg, DestReg, IncrReg, 4865ffd83dbSDimitry Andric MaskReg, Scratch1Reg); 4875ffd83dbSDimitry Andric 4885ffd83dbSDimitry Andric // .looptail: 4895ffd83dbSDimitry Andric // sc.w scratch1, scratch1, (addr) 4905ffd83dbSDimitry Andric // bnez scratch1, loop 4915ffd83dbSDimitry Andric BuildMI(LoopTailMBB, DL, TII->get(getSCForRMW32(Ordering)), Scratch1Reg) 4925ffd83dbSDimitry Andric .addReg(AddrReg) 4935ffd83dbSDimitry Andric .addReg(Scratch1Reg); 4945ffd83dbSDimitry Andric BuildMI(LoopTailMBB, DL, TII->get(RISCV::BNE)) 4955ffd83dbSDimitry Andric .addReg(Scratch1Reg) 4965ffd83dbSDimitry Andric .addReg(RISCV::X0) 4975ffd83dbSDimitry Andric .addMBB(LoopHeadMBB); 4985ffd83dbSDimitry Andric 4995ffd83dbSDimitry Andric NextMBBI = MBB.end(); 5005ffd83dbSDimitry Andric MI.eraseFromParent(); 5015ffd83dbSDimitry Andric 5025ffd83dbSDimitry Andric LivePhysRegs LiveRegs; 5035ffd83dbSDimitry Andric computeAndAddLiveIns(LiveRegs, *LoopHeadMBB); 5045ffd83dbSDimitry Andric computeAndAddLiveIns(LiveRegs, *LoopIfBodyMBB); 5055ffd83dbSDimitry Andric computeAndAddLiveIns(LiveRegs, *LoopTailMBB); 5065ffd83dbSDimitry Andric computeAndAddLiveIns(LiveRegs, *DoneMBB); 5075ffd83dbSDimitry Andric 5085ffd83dbSDimitry Andric return true; 5095ffd83dbSDimitry Andric } 5105ffd83dbSDimitry Andric 5115ffd83dbSDimitry Andric bool RISCVExpandAtomicPseudo::expandAtomicCmpXchg( 5125ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool IsMasked, 5135ffd83dbSDimitry Andric int Width, MachineBasicBlock::iterator &NextMBBI) { 5145ffd83dbSDimitry Andric MachineInstr &MI = *MBBI; 5155ffd83dbSDimitry Andric DebugLoc DL = MI.getDebugLoc(); 5165ffd83dbSDimitry Andric MachineFunction *MF = MBB.getParent(); 5175ffd83dbSDimitry Andric auto LoopHeadMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 5185ffd83dbSDimitry Andric auto LoopTailMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 5195ffd83dbSDimitry Andric auto DoneMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 5205ffd83dbSDimitry Andric 5215ffd83dbSDimitry Andric // Insert new MBBs. 5225ffd83dbSDimitry Andric MF->insert(++MBB.getIterator(), LoopHeadMBB); 5235ffd83dbSDimitry Andric MF->insert(++LoopHeadMBB->getIterator(), LoopTailMBB); 5245ffd83dbSDimitry Andric MF->insert(++LoopTailMBB->getIterator(), DoneMBB); 5255ffd83dbSDimitry Andric 5265ffd83dbSDimitry Andric // Set up successors and transfer remaining instructions to DoneMBB. 5275ffd83dbSDimitry Andric LoopHeadMBB->addSuccessor(LoopTailMBB); 5285ffd83dbSDimitry Andric LoopHeadMBB->addSuccessor(DoneMBB); 5295ffd83dbSDimitry Andric LoopTailMBB->addSuccessor(DoneMBB); 5305ffd83dbSDimitry Andric LoopTailMBB->addSuccessor(LoopHeadMBB); 5315ffd83dbSDimitry Andric DoneMBB->splice(DoneMBB->end(), &MBB, MI, MBB.end()); 5325ffd83dbSDimitry Andric DoneMBB->transferSuccessors(&MBB); 5335ffd83dbSDimitry Andric MBB.addSuccessor(LoopHeadMBB); 5345ffd83dbSDimitry Andric 5355ffd83dbSDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 5365ffd83dbSDimitry Andric Register ScratchReg = MI.getOperand(1).getReg(); 5375ffd83dbSDimitry Andric Register AddrReg = MI.getOperand(2).getReg(); 5385ffd83dbSDimitry Andric Register CmpValReg = MI.getOperand(3).getReg(); 5395ffd83dbSDimitry Andric Register NewValReg = MI.getOperand(4).getReg(); 5405ffd83dbSDimitry Andric AtomicOrdering Ordering = 5415ffd83dbSDimitry Andric static_cast<AtomicOrdering>(MI.getOperand(IsMasked ? 6 : 5).getImm()); 5425ffd83dbSDimitry Andric 5435ffd83dbSDimitry Andric if (!IsMasked) { 5445ffd83dbSDimitry Andric // .loophead: 5455ffd83dbSDimitry Andric // lr.[w|d] dest, (addr) 5465ffd83dbSDimitry Andric // bne dest, cmpval, done 5475ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(getLRForRMW(Ordering, Width)), DestReg) 5485ffd83dbSDimitry Andric .addReg(AddrReg); 5495ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BNE)) 5505ffd83dbSDimitry Andric .addReg(DestReg) 5515ffd83dbSDimitry Andric .addReg(CmpValReg) 5525ffd83dbSDimitry Andric .addMBB(DoneMBB); 5535ffd83dbSDimitry Andric // .looptail: 5545ffd83dbSDimitry Andric // sc.[w|d] scratch, newval, (addr) 5555ffd83dbSDimitry Andric // bnez scratch, loophead 5565ffd83dbSDimitry Andric BuildMI(LoopTailMBB, DL, TII->get(getSCForRMW(Ordering, Width)), ScratchReg) 5575ffd83dbSDimitry Andric .addReg(AddrReg) 5585ffd83dbSDimitry Andric .addReg(NewValReg); 5595ffd83dbSDimitry Andric BuildMI(LoopTailMBB, DL, TII->get(RISCV::BNE)) 5605ffd83dbSDimitry Andric .addReg(ScratchReg) 5615ffd83dbSDimitry Andric .addReg(RISCV::X0) 5625ffd83dbSDimitry Andric .addMBB(LoopHeadMBB); 5635ffd83dbSDimitry Andric } else { 5645ffd83dbSDimitry Andric // .loophead: 5655ffd83dbSDimitry Andric // lr.w dest, (addr) 5665ffd83dbSDimitry Andric // and scratch, dest, mask 5675ffd83dbSDimitry Andric // bne scratch, cmpval, done 5685ffd83dbSDimitry Andric Register MaskReg = MI.getOperand(5).getReg(); 5695ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(getLRForRMW(Ordering, Width)), DestReg) 5705ffd83dbSDimitry Andric .addReg(AddrReg); 5715ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(RISCV::AND), ScratchReg) 5725ffd83dbSDimitry Andric .addReg(DestReg) 5735ffd83dbSDimitry Andric .addReg(MaskReg); 5745ffd83dbSDimitry Andric BuildMI(LoopHeadMBB, DL, TII->get(RISCV::BNE)) 5755ffd83dbSDimitry Andric .addReg(ScratchReg) 5765ffd83dbSDimitry Andric .addReg(CmpValReg) 5775ffd83dbSDimitry Andric .addMBB(DoneMBB); 5785ffd83dbSDimitry Andric 5795ffd83dbSDimitry Andric // .looptail: 5805ffd83dbSDimitry Andric // xor scratch, dest, newval 5815ffd83dbSDimitry Andric // and scratch, scratch, mask 5825ffd83dbSDimitry Andric // xor scratch, dest, scratch 5835ffd83dbSDimitry Andric // sc.w scratch, scratch, (adrr) 5845ffd83dbSDimitry Andric // bnez scratch, loophead 5855ffd83dbSDimitry Andric insertMaskedMerge(TII, DL, LoopTailMBB, ScratchReg, DestReg, NewValReg, 5865ffd83dbSDimitry Andric MaskReg, ScratchReg); 5875ffd83dbSDimitry Andric BuildMI(LoopTailMBB, DL, TII->get(getSCForRMW(Ordering, Width)), ScratchReg) 5885ffd83dbSDimitry Andric .addReg(AddrReg) 5895ffd83dbSDimitry Andric .addReg(ScratchReg); 5905ffd83dbSDimitry Andric BuildMI(LoopTailMBB, DL, TII->get(RISCV::BNE)) 5915ffd83dbSDimitry Andric .addReg(ScratchReg) 5925ffd83dbSDimitry Andric .addReg(RISCV::X0) 5935ffd83dbSDimitry Andric .addMBB(LoopHeadMBB); 5945ffd83dbSDimitry Andric } 5955ffd83dbSDimitry Andric 5965ffd83dbSDimitry Andric NextMBBI = MBB.end(); 5975ffd83dbSDimitry Andric MI.eraseFromParent(); 5985ffd83dbSDimitry Andric 5995ffd83dbSDimitry Andric LivePhysRegs LiveRegs; 6005ffd83dbSDimitry Andric computeAndAddLiveIns(LiveRegs, *LoopHeadMBB); 6015ffd83dbSDimitry Andric computeAndAddLiveIns(LiveRegs, *LoopTailMBB); 6025ffd83dbSDimitry Andric computeAndAddLiveIns(LiveRegs, *DoneMBB); 6035ffd83dbSDimitry Andric 6045ffd83dbSDimitry Andric return true; 6055ffd83dbSDimitry Andric } 6065ffd83dbSDimitry Andric 6075ffd83dbSDimitry Andric } // end of anonymous namespace 6085ffd83dbSDimitry Andric 6095ffd83dbSDimitry Andric INITIALIZE_PASS(RISCVExpandAtomicPseudo, "riscv-expand-atomic-pseudo", 6105ffd83dbSDimitry Andric RISCV_EXPAND_ATOMIC_PSEUDO_NAME, false, false) 6115ffd83dbSDimitry Andric 6125ffd83dbSDimitry Andric namespace llvm { 6135ffd83dbSDimitry Andric 6145ffd83dbSDimitry Andric FunctionPass *createRISCVExpandAtomicPseudoPass() { 6155ffd83dbSDimitry Andric return new RISCVExpandAtomicPseudo(); 6165ffd83dbSDimitry Andric } 6175ffd83dbSDimitry Andric 6185ffd83dbSDimitry Andric } // end of namespace llvm 619