xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVExpandAtomicPseudoInsts.cpp (revision 1fd87a682ad7442327078e1eeb63edc4258f9815)
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