xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsExpandPseudo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- MipsExpandPseudoInsts.cpp - Expand pseudo instructions ------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains a pass that expands pseudo instructions into target
100b57cec5SDimitry Andric // instructions to allow proper scheduling, if-conversion, and other late
110b57cec5SDimitry Andric // optimizations. This pass should be run after register allocation but before
120b57cec5SDimitry Andric // the post-regalloc scheduling pass.
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric // This is currently only used for expanding atomic pseudos after register
150b57cec5SDimitry Andric // allocation. We do this to avoid the fast register allocator introducing
160b57cec5SDimitry Andric // spills between ll and sc. These stores cause some MIPS implementations to
170b57cec5SDimitry Andric // abort the atomic RMW sequence.
180b57cec5SDimitry Andric //
190b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #include "Mips.h"
220b57cec5SDimitry Andric #include "MipsInstrInfo.h"
230b57cec5SDimitry Andric #include "MipsSubtarget.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric using namespace llvm;
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric #define DEBUG_TYPE "mips-pseudo"
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric namespace {
330b57cec5SDimitry Andric   class MipsExpandPseudo : public MachineFunctionPass {
340b57cec5SDimitry Andric   public:
350b57cec5SDimitry Andric     static char ID;
MipsExpandPseudo()360b57cec5SDimitry Andric     MipsExpandPseudo() : MachineFunctionPass(ID) {}
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric     const MipsInstrInfo *TII;
390b57cec5SDimitry Andric     const MipsSubtarget *STI;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &Fn) override;
420b57cec5SDimitry Andric 
getRequiredProperties() const430b57cec5SDimitry Andric     MachineFunctionProperties getRequiredProperties() const override {
440b57cec5SDimitry Andric       return MachineFunctionProperties().set(
450b57cec5SDimitry Andric           MachineFunctionProperties::Property::NoVRegs);
460b57cec5SDimitry Andric     }
470b57cec5SDimitry Andric 
getPassName() const480b57cec5SDimitry Andric     StringRef getPassName() const override {
490b57cec5SDimitry Andric       return "Mips pseudo instruction expansion pass";
500b57cec5SDimitry Andric     }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   private:
530b57cec5SDimitry Andric     bool expandAtomicCmpSwap(MachineBasicBlock &MBB,
540b57cec5SDimitry Andric                              MachineBasicBlock::iterator MBBI,
550b57cec5SDimitry Andric                              MachineBasicBlock::iterator &NextMBBI);
560b57cec5SDimitry Andric     bool expandAtomicCmpSwapSubword(MachineBasicBlock &MBB,
570b57cec5SDimitry Andric                                     MachineBasicBlock::iterator MBBI,
580b57cec5SDimitry Andric                                     MachineBasicBlock::iterator &NextMBBI);
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric     bool expandAtomicBinOp(MachineBasicBlock &BB,
610b57cec5SDimitry Andric                            MachineBasicBlock::iterator I,
620b57cec5SDimitry Andric                            MachineBasicBlock::iterator &NMBBI, unsigned Size);
630b57cec5SDimitry Andric     bool expandAtomicBinOpSubword(MachineBasicBlock &BB,
640b57cec5SDimitry Andric                                   MachineBasicBlock::iterator I,
650b57cec5SDimitry Andric                                   MachineBasicBlock::iterator &NMBBI);
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric     bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
680b57cec5SDimitry Andric                   MachineBasicBlock::iterator &NMBB);
690b57cec5SDimitry Andric     bool expandMBB(MachineBasicBlock &MBB);
700b57cec5SDimitry Andric    };
710b57cec5SDimitry Andric   char MipsExpandPseudo::ID = 0;
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
expandAtomicCmpSwapSubword(MachineBasicBlock & BB,MachineBasicBlock::iterator I,MachineBasicBlock::iterator & NMBBI)740b57cec5SDimitry Andric bool MipsExpandPseudo::expandAtomicCmpSwapSubword(
750b57cec5SDimitry Andric     MachineBasicBlock &BB, MachineBasicBlock::iterator I,
760b57cec5SDimitry Andric     MachineBasicBlock::iterator &NMBBI) {
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   MachineFunction *MF = BB.getParent();
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   const bool ArePtrs64bit = STI->getABI().ArePtrs64bit();
810b57cec5SDimitry Andric   DebugLoc DL = I->getDebugLoc();
820b57cec5SDimitry Andric   unsigned LL, SC;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   unsigned ZERO = Mips::ZERO;
850b57cec5SDimitry Andric   unsigned BNE = Mips::BNE;
860b57cec5SDimitry Andric   unsigned BEQ = Mips::BEQ;
870b57cec5SDimitry Andric   unsigned SEOp =
880b57cec5SDimitry Andric       I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I8_POSTRA ? Mips::SEB : Mips::SEH;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   if (STI->inMicroMipsMode()) {
910b57cec5SDimitry Andric       LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM;
920b57cec5SDimitry Andric       SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM;
930b57cec5SDimitry Andric       BNE = STI->hasMips32r6() ? Mips::BNEC_MMR6 : Mips::BNE_MM;
940b57cec5SDimitry Andric       BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM;
950b57cec5SDimitry Andric   } else {
960b57cec5SDimitry Andric     LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
970b57cec5SDimitry Andric                             : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
980b57cec5SDimitry Andric     SC = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
990b57cec5SDimitry Andric                             : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric 
1028bcb0991SDimitry Andric   Register Dest = I->getOperand(0).getReg();
1038bcb0991SDimitry Andric   Register Ptr = I->getOperand(1).getReg();
1048bcb0991SDimitry Andric   Register Mask = I->getOperand(2).getReg();
1058bcb0991SDimitry Andric   Register ShiftCmpVal = I->getOperand(3).getReg();
1068bcb0991SDimitry Andric   Register Mask2 = I->getOperand(4).getReg();
1078bcb0991SDimitry Andric   Register ShiftNewVal = I->getOperand(5).getReg();
1088bcb0991SDimitry Andric   Register ShiftAmnt = I->getOperand(6).getReg();
1098bcb0991SDimitry Andric   Register Scratch = I->getOperand(7).getReg();
1108bcb0991SDimitry Andric   Register Scratch2 = I->getOperand(8).getReg();
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   // insert new blocks after the current block
1130b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = BB.getBasicBlock();
1140b57cec5SDimitry Andric   MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB);
1150b57cec5SDimitry Andric   MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB);
1160b57cec5SDimitry Andric   MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB);
1170b57cec5SDimitry Andric   MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
1180b57cec5SDimitry Andric   MachineFunction::iterator It = ++BB.getIterator();
1190b57cec5SDimitry Andric   MF->insert(It, loop1MBB);
1200b57cec5SDimitry Andric   MF->insert(It, loop2MBB);
1210b57cec5SDimitry Andric   MF->insert(It, sinkMBB);
1220b57cec5SDimitry Andric   MF->insert(It, exitMBB);
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   // Transfer the remainder of BB and its successor edges to exitMBB.
1250b57cec5SDimitry Andric   exitMBB->splice(exitMBB->begin(), &BB,
1260b57cec5SDimitry Andric                   std::next(MachineBasicBlock::iterator(I)), BB.end());
1270b57cec5SDimitry Andric   exitMBB->transferSuccessorsAndUpdatePHIs(&BB);
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   //  thisMBB:
1300b57cec5SDimitry Andric   //    ...
1310b57cec5SDimitry Andric   //    fallthrough --> loop1MBB
1320b57cec5SDimitry Andric   BB.addSuccessor(loop1MBB, BranchProbability::getOne());
1330b57cec5SDimitry Andric   loop1MBB->addSuccessor(sinkMBB);
1340b57cec5SDimitry Andric   loop1MBB->addSuccessor(loop2MBB);
1350b57cec5SDimitry Andric   loop1MBB->normalizeSuccProbs();
1360b57cec5SDimitry Andric   loop2MBB->addSuccessor(loop1MBB);
1370b57cec5SDimitry Andric   loop2MBB->addSuccessor(sinkMBB);
1380b57cec5SDimitry Andric   loop2MBB->normalizeSuccProbs();
1390b57cec5SDimitry Andric   sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne());
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   // loop1MBB:
1420b57cec5SDimitry Andric   //   ll dest, 0(ptr)
1430b57cec5SDimitry Andric   //   and Mask', dest, Mask
1440b57cec5SDimitry Andric   //   bne Mask', ShiftCmpVal, exitMBB
1450b57cec5SDimitry Andric   BuildMI(loop1MBB, DL, TII->get(LL), Scratch).addReg(Ptr).addImm(0);
1460b57cec5SDimitry Andric   BuildMI(loop1MBB, DL, TII->get(Mips::AND), Scratch2)
1470b57cec5SDimitry Andric       .addReg(Scratch)
1480b57cec5SDimitry Andric       .addReg(Mask);
1490b57cec5SDimitry Andric   BuildMI(loop1MBB, DL, TII->get(BNE))
1500b57cec5SDimitry Andric     .addReg(Scratch2).addReg(ShiftCmpVal).addMBB(sinkMBB);
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   // loop2MBB:
1530b57cec5SDimitry Andric   //   and dest, dest, mask2
1540b57cec5SDimitry Andric   //   or dest, dest, ShiftNewVal
1550b57cec5SDimitry Andric   //   sc dest, dest, 0(ptr)
1560b57cec5SDimitry Andric   //   beq dest, $0, loop1MBB
1570b57cec5SDimitry Andric   BuildMI(loop2MBB, DL, TII->get(Mips::AND), Scratch)
1580b57cec5SDimitry Andric       .addReg(Scratch, RegState::Kill)
1590b57cec5SDimitry Andric       .addReg(Mask2);
1600b57cec5SDimitry Andric   BuildMI(loop2MBB, DL, TII->get(Mips::OR), Scratch)
1610b57cec5SDimitry Andric       .addReg(Scratch, RegState::Kill)
1620b57cec5SDimitry Andric       .addReg(ShiftNewVal);
1630b57cec5SDimitry Andric   BuildMI(loop2MBB, DL, TII->get(SC), Scratch)
1640b57cec5SDimitry Andric       .addReg(Scratch, RegState::Kill)
1650b57cec5SDimitry Andric       .addReg(Ptr)
1660b57cec5SDimitry Andric       .addImm(0);
1670b57cec5SDimitry Andric   BuildMI(loop2MBB, DL, TII->get(BEQ))
1680b57cec5SDimitry Andric       .addReg(Scratch, RegState::Kill)
1690b57cec5SDimitry Andric       .addReg(ZERO)
1700b57cec5SDimitry Andric       .addMBB(loop1MBB);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   //  sinkMBB:
1730b57cec5SDimitry Andric   //    srl     srlres, Mask', shiftamt
1740b57cec5SDimitry Andric   //    sign_extend dest,srlres
1750b57cec5SDimitry Andric   BuildMI(sinkMBB, DL, TII->get(Mips::SRLV), Dest)
1760b57cec5SDimitry Andric       .addReg(Scratch2)
1770b57cec5SDimitry Andric       .addReg(ShiftAmnt);
1780b57cec5SDimitry Andric   if (STI->hasMips32r2()) {
1790b57cec5SDimitry Andric     BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest);
1800b57cec5SDimitry Andric   } else {
1810b57cec5SDimitry Andric     const unsigned ShiftImm =
1820b57cec5SDimitry Andric         I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I16_POSTRA ? 16 : 24;
1830b57cec5SDimitry Andric     BuildMI(sinkMBB, DL, TII->get(Mips::SLL), Dest)
1840b57cec5SDimitry Andric         .addReg(Dest, RegState::Kill)
1850b57cec5SDimitry Andric         .addImm(ShiftImm);
1860b57cec5SDimitry Andric     BuildMI(sinkMBB, DL, TII->get(Mips::SRA), Dest)
1870b57cec5SDimitry Andric         .addReg(Dest, RegState::Kill)
1880b57cec5SDimitry Andric         .addImm(ShiftImm);
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   LivePhysRegs LiveRegs;
1920b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *loop1MBB);
1930b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *loop2MBB);
1940b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *sinkMBB);
1950b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *exitMBB);
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   NMBBI = BB.end();
1980b57cec5SDimitry Andric   I->eraseFromParent();
1990b57cec5SDimitry Andric   return true;
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
expandAtomicCmpSwap(MachineBasicBlock & BB,MachineBasicBlock::iterator I,MachineBasicBlock::iterator & NMBBI)2020b57cec5SDimitry Andric bool MipsExpandPseudo::expandAtomicCmpSwap(MachineBasicBlock &BB,
2030b57cec5SDimitry Andric                                            MachineBasicBlock::iterator I,
2040b57cec5SDimitry Andric                                            MachineBasicBlock::iterator &NMBBI) {
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   const unsigned Size =
2070b57cec5SDimitry Andric       I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I32_POSTRA ? 4 : 8;
2080b57cec5SDimitry Andric   MachineFunction *MF = BB.getParent();
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   const bool ArePtrs64bit = STI->getABI().ArePtrs64bit();
2110b57cec5SDimitry Andric   DebugLoc DL = I->getDebugLoc();
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   unsigned LL, SC, ZERO, BNE, BEQ, MOVE;
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   if (Size == 4) {
2160b57cec5SDimitry Andric     if (STI->inMicroMipsMode()) {
2170b57cec5SDimitry Andric       LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM;
2180b57cec5SDimitry Andric       SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM;
2190b57cec5SDimitry Andric       BNE = STI->hasMips32r6() ? Mips::BNEC_MMR6 : Mips::BNE_MM;
2200b57cec5SDimitry Andric       BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM;
2210b57cec5SDimitry Andric     } else {
2220b57cec5SDimitry Andric       LL = STI->hasMips32r6()
2230b57cec5SDimitry Andric                ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
2240b57cec5SDimitry Andric                : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
2250b57cec5SDimitry Andric       SC = STI->hasMips32r6()
2260b57cec5SDimitry Andric                ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
2270b57cec5SDimitry Andric                : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
2280b57cec5SDimitry Andric       BNE = Mips::BNE;
2290b57cec5SDimitry Andric       BEQ = Mips::BEQ;
2300b57cec5SDimitry Andric     }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric     ZERO = Mips::ZERO;
2330b57cec5SDimitry Andric     MOVE = Mips::OR;
2340b57cec5SDimitry Andric   } else {
2350b57cec5SDimitry Andric     LL = STI->hasMips64r6() ? Mips::LLD_R6 : Mips::LLD;
2360b57cec5SDimitry Andric     SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD;
2370b57cec5SDimitry Andric     ZERO = Mips::ZERO_64;
2380b57cec5SDimitry Andric     BNE = Mips::BNE64;
2390b57cec5SDimitry Andric     BEQ = Mips::BEQ64;
2400b57cec5SDimitry Andric     MOVE = Mips::OR64;
2410b57cec5SDimitry Andric   }
2420b57cec5SDimitry Andric 
2438bcb0991SDimitry Andric   Register Dest = I->getOperand(0).getReg();
2448bcb0991SDimitry Andric   Register Ptr = I->getOperand(1).getReg();
2458bcb0991SDimitry Andric   Register OldVal = I->getOperand(2).getReg();
2468bcb0991SDimitry Andric   Register NewVal = I->getOperand(3).getReg();
2478bcb0991SDimitry Andric   Register Scratch = I->getOperand(4).getReg();
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   // insert new blocks after the current block
2500b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = BB.getBasicBlock();
2510b57cec5SDimitry Andric   MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB);
2520b57cec5SDimitry Andric   MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB);
2530b57cec5SDimitry Andric   MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
2540b57cec5SDimitry Andric   MachineFunction::iterator It = ++BB.getIterator();
2550b57cec5SDimitry Andric   MF->insert(It, loop1MBB);
2560b57cec5SDimitry Andric   MF->insert(It, loop2MBB);
2570b57cec5SDimitry Andric   MF->insert(It, exitMBB);
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   // Transfer the remainder of BB and its successor edges to exitMBB.
2600b57cec5SDimitry Andric   exitMBB->splice(exitMBB->begin(), &BB,
2610b57cec5SDimitry Andric                   std::next(MachineBasicBlock::iterator(I)), BB.end());
2620b57cec5SDimitry Andric   exitMBB->transferSuccessorsAndUpdatePHIs(&BB);
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   //  thisMBB:
2650b57cec5SDimitry Andric   //    ...
2660b57cec5SDimitry Andric   //    fallthrough --> loop1MBB
2670b57cec5SDimitry Andric   BB.addSuccessor(loop1MBB, BranchProbability::getOne());
2680b57cec5SDimitry Andric   loop1MBB->addSuccessor(exitMBB);
2690b57cec5SDimitry Andric   loop1MBB->addSuccessor(loop2MBB);
2700b57cec5SDimitry Andric   loop1MBB->normalizeSuccProbs();
2710b57cec5SDimitry Andric   loop2MBB->addSuccessor(loop1MBB);
2720b57cec5SDimitry Andric   loop2MBB->addSuccessor(exitMBB);
2730b57cec5SDimitry Andric   loop2MBB->normalizeSuccProbs();
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   // loop1MBB:
2760b57cec5SDimitry Andric   //   ll dest, 0(ptr)
2770b57cec5SDimitry Andric   //   bne dest, oldval, exitMBB
2780b57cec5SDimitry Andric   BuildMI(loop1MBB, DL, TII->get(LL), Dest).addReg(Ptr).addImm(0);
2790b57cec5SDimitry Andric   BuildMI(loop1MBB, DL, TII->get(BNE))
2800b57cec5SDimitry Andric     .addReg(Dest, RegState::Kill).addReg(OldVal).addMBB(exitMBB);
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   // loop2MBB:
2830b57cec5SDimitry Andric   //   move scratch, NewVal
2840b57cec5SDimitry Andric   //   sc Scratch, Scratch, 0(ptr)
2850b57cec5SDimitry Andric   //   beq Scratch, $0, loop1MBB
2860b57cec5SDimitry Andric   BuildMI(loop2MBB, DL, TII->get(MOVE), Scratch).addReg(NewVal).addReg(ZERO);
2870b57cec5SDimitry Andric   BuildMI(loop2MBB, DL, TII->get(SC), Scratch)
2880b57cec5SDimitry Andric     .addReg(Scratch).addReg(Ptr).addImm(0);
2890b57cec5SDimitry Andric   BuildMI(loop2MBB, DL, TII->get(BEQ))
2900b57cec5SDimitry Andric     .addReg(Scratch, RegState::Kill).addReg(ZERO).addMBB(loop1MBB);
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   LivePhysRegs LiveRegs;
2930b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *loop1MBB);
2940b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *loop2MBB);
2950b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *exitMBB);
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   NMBBI = BB.end();
2980b57cec5SDimitry Andric   I->eraseFromParent();
2990b57cec5SDimitry Andric   return true;
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric 
expandAtomicBinOpSubword(MachineBasicBlock & BB,MachineBasicBlock::iterator I,MachineBasicBlock::iterator & NMBBI)3020b57cec5SDimitry Andric bool MipsExpandPseudo::expandAtomicBinOpSubword(
3030b57cec5SDimitry Andric     MachineBasicBlock &BB, MachineBasicBlock::iterator I,
3040b57cec5SDimitry Andric     MachineBasicBlock::iterator &NMBBI) {
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   MachineFunction *MF = BB.getParent();
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   const bool ArePtrs64bit = STI->getABI().ArePtrs64bit();
3090b57cec5SDimitry Andric   DebugLoc DL = I->getDebugLoc();
3100b57cec5SDimitry Andric 
311480093f4SDimitry Andric   unsigned LL, SC, SLT, SLTu, OR, MOVN, MOVZ, SELNEZ, SELEQZ;
3120b57cec5SDimitry Andric   unsigned BEQ = Mips::BEQ;
3130b57cec5SDimitry Andric   unsigned SEOp = Mips::SEH;
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   if (STI->inMicroMipsMode()) {
3160b57cec5SDimitry Andric       LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM;
3170b57cec5SDimitry Andric       SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM;
3180b57cec5SDimitry Andric       BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM;
319480093f4SDimitry Andric       SLT = Mips::SLT_MM;
320480093f4SDimitry Andric       SLTu = Mips::SLTu_MM;
321480093f4SDimitry Andric       OR = STI->hasMips32r6() ? Mips::OR_MMR6 : Mips::OR_MM;
322480093f4SDimitry Andric       MOVN = Mips::MOVN_I_MM;
323480093f4SDimitry Andric       MOVZ = Mips::MOVZ_I_MM;
324480093f4SDimitry Andric       SELNEZ = STI->hasMips32r6() ? Mips::SELNEZ_MMR6 : Mips::SELNEZ;
325480093f4SDimitry Andric       SELEQZ = STI->hasMips32r6() ? Mips::SELEQZ_MMR6 : Mips::SELEQZ;
3260b57cec5SDimitry Andric   } else {
3270b57cec5SDimitry Andric     LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
3280b57cec5SDimitry Andric                             : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
3290b57cec5SDimitry Andric     SC = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
3300b57cec5SDimitry Andric                             : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
331480093f4SDimitry Andric     SLT = Mips::SLT;
332480093f4SDimitry Andric     SLTu = Mips::SLTu;
333480093f4SDimitry Andric     OR = Mips::OR;
334480093f4SDimitry Andric     MOVN = Mips::MOVN_I_I;
335480093f4SDimitry Andric     MOVZ = Mips::MOVZ_I_I;
336480093f4SDimitry Andric     SELNEZ = Mips::SELNEZ;
337480093f4SDimitry Andric     SELEQZ = Mips::SELEQZ;
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   bool IsSwap = false;
3410b57cec5SDimitry Andric   bool IsNand = false;
342480093f4SDimitry Andric   bool IsMin = false;
343480093f4SDimitry Andric   bool IsMax = false;
344480093f4SDimitry Andric   bool IsUnsigned = false;
345*0fca6ea1SDimitry Andric   bool DestOK = false;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   unsigned Opcode = 0;
3480b57cec5SDimitry Andric   switch (I->getOpcode()) {
3490b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_NAND_I8_POSTRA:
3500b57cec5SDimitry Andric     SEOp = Mips::SEB;
351bdd1243dSDimitry Andric     [[fallthrough]];
3520b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_NAND_I16_POSTRA:
3530b57cec5SDimitry Andric     IsNand = true;
3540b57cec5SDimitry Andric     break;
3550b57cec5SDimitry Andric   case Mips::ATOMIC_SWAP_I8_POSTRA:
3560b57cec5SDimitry Andric     SEOp = Mips::SEB;
357bdd1243dSDimitry Andric     [[fallthrough]];
3580b57cec5SDimitry Andric   case Mips::ATOMIC_SWAP_I16_POSTRA:
3590b57cec5SDimitry Andric     IsSwap = true;
3600b57cec5SDimitry Andric     break;
3610b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_ADD_I8_POSTRA:
3620b57cec5SDimitry Andric     SEOp = Mips::SEB;
363bdd1243dSDimitry Andric     [[fallthrough]];
3640b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_ADD_I16_POSTRA:
3650b57cec5SDimitry Andric     Opcode = Mips::ADDu;
3660b57cec5SDimitry Andric     break;
3670b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_SUB_I8_POSTRA:
3680b57cec5SDimitry Andric     SEOp = Mips::SEB;
369bdd1243dSDimitry Andric     [[fallthrough]];
3700b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_SUB_I16_POSTRA:
3710b57cec5SDimitry Andric     Opcode = Mips::SUBu;
3720b57cec5SDimitry Andric     break;
3730b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_AND_I8_POSTRA:
3740b57cec5SDimitry Andric     SEOp = Mips::SEB;
375bdd1243dSDimitry Andric     [[fallthrough]];
3760b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_AND_I16_POSTRA:
3770b57cec5SDimitry Andric     Opcode = Mips::AND;
3780b57cec5SDimitry Andric     break;
3790b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_OR_I8_POSTRA:
3800b57cec5SDimitry Andric     SEOp = Mips::SEB;
381bdd1243dSDimitry Andric     [[fallthrough]];
3820b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_OR_I16_POSTRA:
3830b57cec5SDimitry Andric     Opcode = Mips::OR;
3840b57cec5SDimitry Andric     break;
3850b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_XOR_I8_POSTRA:
3860b57cec5SDimitry Andric     SEOp = Mips::SEB;
387bdd1243dSDimitry Andric     [[fallthrough]];
3880b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_XOR_I16_POSTRA:
3890b57cec5SDimitry Andric     Opcode = Mips::XOR;
3900b57cec5SDimitry Andric     break;
391480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMIN_I8_POSTRA:
392*0fca6ea1SDimitry Andric     SEOp = Mips::SEB;
393*0fca6ea1SDimitry Andric     IsUnsigned = true;
394*0fca6ea1SDimitry Andric     IsMin = true;
395*0fca6ea1SDimitry Andric     break;
396480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMIN_I16_POSTRA:
397480093f4SDimitry Andric     IsUnsigned = true;
398*0fca6ea1SDimitry Andric     IsMin = true;
399*0fca6ea1SDimitry Andric     break;
400480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MIN_I8_POSTRA:
401*0fca6ea1SDimitry Andric     SEOp = Mips::SEB;
402*0fca6ea1SDimitry Andric     IsMin = true;
403*0fca6ea1SDimitry Andric     break;
404480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MIN_I16_POSTRA:
405480093f4SDimitry Andric     IsMin = true;
406480093f4SDimitry Andric     break;
407480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMAX_I8_POSTRA:
408*0fca6ea1SDimitry Andric     SEOp = Mips::SEB;
409*0fca6ea1SDimitry Andric     IsUnsigned = true;
410*0fca6ea1SDimitry Andric     IsMax = true;
411*0fca6ea1SDimitry Andric     break;
412480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMAX_I16_POSTRA:
413480093f4SDimitry Andric     IsUnsigned = true;
414*0fca6ea1SDimitry Andric     IsMax = true;
415*0fca6ea1SDimitry Andric     break;
416480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MAX_I8_POSTRA:
417*0fca6ea1SDimitry Andric     SEOp = Mips::SEB;
418*0fca6ea1SDimitry Andric     IsMax = true;
419*0fca6ea1SDimitry Andric     break;
420480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MAX_I16_POSTRA:
421480093f4SDimitry Andric     IsMax = true;
422480093f4SDimitry Andric     break;
4230b57cec5SDimitry Andric   default:
4240b57cec5SDimitry Andric     llvm_unreachable("Unknown subword atomic pseudo for expansion!");
4250b57cec5SDimitry Andric   }
4260b57cec5SDimitry Andric 
4278bcb0991SDimitry Andric   Register Dest = I->getOperand(0).getReg();
4288bcb0991SDimitry Andric   Register Ptr = I->getOperand(1).getReg();
4298bcb0991SDimitry Andric   Register Incr = I->getOperand(2).getReg();
4308bcb0991SDimitry Andric   Register Mask = I->getOperand(3).getReg();
4318bcb0991SDimitry Andric   Register Mask2 = I->getOperand(4).getReg();
4328bcb0991SDimitry Andric   Register ShiftAmnt = I->getOperand(5).getReg();
4338bcb0991SDimitry Andric   Register OldVal = I->getOperand(6).getReg();
4348bcb0991SDimitry Andric   Register BinOpRes = I->getOperand(7).getReg();
4358bcb0991SDimitry Andric   Register StoreVal = I->getOperand(8).getReg();
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = BB.getBasicBlock();
4380b57cec5SDimitry Andric   MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
4390b57cec5SDimitry Andric   MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB);
4400b57cec5SDimitry Andric   MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
4410b57cec5SDimitry Andric   MachineFunction::iterator It = ++BB.getIterator();
4420b57cec5SDimitry Andric   MF->insert(It, loopMBB);
4430b57cec5SDimitry Andric   MF->insert(It, sinkMBB);
4440b57cec5SDimitry Andric   MF->insert(It, exitMBB);
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end());
4470b57cec5SDimitry Andric   exitMBB->transferSuccessorsAndUpdatePHIs(&BB);
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   BB.addSuccessor(loopMBB, BranchProbability::getOne());
4500b57cec5SDimitry Andric   loopMBB->addSuccessor(sinkMBB);
4510b57cec5SDimitry Andric   loopMBB->addSuccessor(loopMBB);
4520b57cec5SDimitry Andric   loopMBB->normalizeSuccProbs();
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric   BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0);
4550b57cec5SDimitry Andric   if (IsNand) {
4560b57cec5SDimitry Andric     //  and andres, oldval, incr2
4570b57cec5SDimitry Andric     //  nor binopres, $0, andres
4580b57cec5SDimitry Andric     //  and newval, binopres, mask
4590b57cec5SDimitry Andric     BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes)
4600b57cec5SDimitry Andric         .addReg(OldVal)
4610b57cec5SDimitry Andric         .addReg(Incr);
4620b57cec5SDimitry Andric     BuildMI(loopMBB, DL, TII->get(Mips::NOR), BinOpRes)
4630b57cec5SDimitry Andric         .addReg(Mips::ZERO)
4640b57cec5SDimitry Andric         .addReg(BinOpRes);
4650b57cec5SDimitry Andric     BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes)
4660b57cec5SDimitry Andric         .addReg(BinOpRes)
4670b57cec5SDimitry Andric         .addReg(Mask);
468480093f4SDimitry Andric   } else if (IsMin || IsMax) {
469480093f4SDimitry Andric 
470480093f4SDimitry Andric     assert(I->getNumOperands() == 10 &&
471480093f4SDimitry Andric            "Atomics min|max|umin|umax use an additional register");
472480093f4SDimitry Andric     Register Scratch4 = I->getOperand(9).getReg();
473480093f4SDimitry Andric 
474480093f4SDimitry Andric     unsigned SLTScratch4 = IsUnsigned ? SLTu : SLT;
475480093f4SDimitry Andric     unsigned SELIncr = IsMax ? SELNEZ : SELEQZ;
476480093f4SDimitry Andric     unsigned SELOldVal = IsMax ? SELEQZ : SELNEZ;
477480093f4SDimitry Andric     unsigned MOVIncr = IsMax ? MOVN : MOVZ;
478480093f4SDimitry Andric 
479*0fca6ea1SDimitry Andric     BuildMI(loopMBB, DL, TII->get(Mips::SRAV), StoreVal)
480480093f4SDimitry Andric         .addReg(OldVal)
481*0fca6ea1SDimitry Andric         .addReg(ShiftAmnt);
482*0fca6ea1SDimitry Andric     if (IsUnsigned) {
483*0fca6ea1SDimitry Andric       const unsigned OpMask = SEOp == Mips::SEH ? 0xffff : 0xff;
484*0fca6ea1SDimitry Andric       BuildMI(loopMBB, DL, TII->get(Mips::ANDi), StoreVal)
485*0fca6ea1SDimitry Andric           .addReg(StoreVal)
486*0fca6ea1SDimitry Andric           .addImm(OpMask);
487*0fca6ea1SDimitry Andric     } else if (STI->hasMips32r2()) {
488*0fca6ea1SDimitry Andric       BuildMI(loopMBB, DL, TII->get(SEOp), StoreVal).addReg(StoreVal);
489*0fca6ea1SDimitry Andric     } else {
490*0fca6ea1SDimitry Andric       const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24;
491*0fca6ea1SDimitry Andric       const unsigned SROp = IsUnsigned ? Mips::SRL : Mips::SRA;
492*0fca6ea1SDimitry Andric       BuildMI(loopMBB, DL, TII->get(Mips::SLL), StoreVal)
493*0fca6ea1SDimitry Andric           .addReg(StoreVal, RegState::Kill)
494*0fca6ea1SDimitry Andric           .addImm(ShiftImm);
495*0fca6ea1SDimitry Andric       BuildMI(loopMBB, DL, TII->get(SROp), StoreVal)
496*0fca6ea1SDimitry Andric           .addReg(StoreVal, RegState::Kill)
497*0fca6ea1SDimitry Andric           .addImm(ShiftImm);
498480093f4SDimitry Andric     }
499*0fca6ea1SDimitry Andric     BuildMI(loopMBB, DL, TII->get(Mips::OR), Dest)
500*0fca6ea1SDimitry Andric         .addReg(Mips::ZERO)
501*0fca6ea1SDimitry Andric         .addReg(StoreVal);
502*0fca6ea1SDimitry Andric     DestOK = true;
503*0fca6ea1SDimitry Andric     BuildMI(loopMBB, DL, TII->get(Mips::SLLV), StoreVal)
504*0fca6ea1SDimitry Andric         .addReg(StoreVal)
505*0fca6ea1SDimitry Andric         .addReg(ShiftAmnt);
506dfa39133SDimitry Andric 
507*0fca6ea1SDimitry Andric     // unsigned: sltu Scratch4, StoreVal, Incr
508*0fca6ea1SDimitry Andric     // signed:   slt Scratch4, StoreVal, Incr
509480093f4SDimitry Andric     BuildMI(loopMBB, DL, TII->get(SLTScratch4), Scratch4)
510*0fca6ea1SDimitry Andric         .addReg(StoreVal)
511480093f4SDimitry Andric         .addReg(Incr);
512480093f4SDimitry Andric 
513480093f4SDimitry Andric     if (STI->hasMips64r6() || STI->hasMips32r6()) {
514480093f4SDimitry Andric       // max: seleqz BinOpRes, OldVal, Scratch4
515480093f4SDimitry Andric       //      selnez Scratch4, Incr, Scratch4
516480093f4SDimitry Andric       //      or BinOpRes, BinOpRes, Scratch4
517480093f4SDimitry Andric       // min: selnqz BinOpRes, OldVal, Scratch4
518480093f4SDimitry Andric       //      seleqz Scratch4, Incr, Scratch4
519480093f4SDimitry Andric       //      or BinOpRes, BinOpRes, Scratch4
520480093f4SDimitry Andric       BuildMI(loopMBB, DL, TII->get(SELOldVal), BinOpRes)
521*0fca6ea1SDimitry Andric           .addReg(StoreVal)
522480093f4SDimitry Andric           .addReg(Scratch4);
523480093f4SDimitry Andric       BuildMI(loopMBB, DL, TII->get(SELIncr), Scratch4)
524480093f4SDimitry Andric           .addReg(Incr)
525480093f4SDimitry Andric           .addReg(Scratch4);
526480093f4SDimitry Andric       BuildMI(loopMBB, DL, TII->get(OR), BinOpRes)
527480093f4SDimitry Andric           .addReg(BinOpRes)
528480093f4SDimitry Andric           .addReg(Scratch4);
529480093f4SDimitry Andric     } else {
530*0fca6ea1SDimitry Andric       // max: move BinOpRes, StoreVal
531480093f4SDimitry Andric       //      movn BinOpRes, Incr, Scratch4, BinOpRes
532*0fca6ea1SDimitry Andric       // min: move BinOpRes, StoreVal
533480093f4SDimitry Andric       //      movz BinOpRes, Incr, Scratch4, BinOpRes
534480093f4SDimitry Andric       BuildMI(loopMBB, DL, TII->get(OR), BinOpRes)
535*0fca6ea1SDimitry Andric           .addReg(StoreVal)
536480093f4SDimitry Andric           .addReg(Mips::ZERO);
537480093f4SDimitry Andric       BuildMI(loopMBB, DL, TII->get(MOVIncr), BinOpRes)
538480093f4SDimitry Andric           .addReg(Incr)
539480093f4SDimitry Andric           .addReg(Scratch4)
540480093f4SDimitry Andric           .addReg(BinOpRes);
541480093f4SDimitry Andric     }
542480093f4SDimitry Andric 
543480093f4SDimitry Andric     //  and BinOpRes, BinOpRes, Mask
544480093f4SDimitry Andric     BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes)
545480093f4SDimitry Andric         .addReg(BinOpRes)
546480093f4SDimitry Andric         .addReg(Mask);
547480093f4SDimitry Andric 
5480b57cec5SDimitry Andric   } else if (!IsSwap) {
5490b57cec5SDimitry Andric     //  <binop> binopres, oldval, incr2
5500b57cec5SDimitry Andric     //  and newval, binopres, mask
5510b57cec5SDimitry Andric     BuildMI(loopMBB, DL, TII->get(Opcode), BinOpRes)
5520b57cec5SDimitry Andric         .addReg(OldVal)
5530b57cec5SDimitry Andric         .addReg(Incr);
5540b57cec5SDimitry Andric     BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes)
5550b57cec5SDimitry Andric         .addReg(BinOpRes)
5560b57cec5SDimitry Andric         .addReg(Mask);
5570b57cec5SDimitry Andric   } else { // atomic.swap
5580b57cec5SDimitry Andric     //  and newval, incr2, mask
5590b57cec5SDimitry Andric     BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes)
5600b57cec5SDimitry Andric         .addReg(Incr)
5610b57cec5SDimitry Andric         .addReg(Mask);
5620b57cec5SDimitry Andric   }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric   // and StoreVal, OlddVal, Mask2
5650b57cec5SDimitry Andric   // or StoreVal, StoreVal, BinOpRes
5660b57cec5SDimitry Andric   // StoreVal<tied1> = sc StoreVal, 0(Ptr)
5670b57cec5SDimitry Andric   // beq StoreVal, zero, loopMBB
5680b57cec5SDimitry Andric   BuildMI(loopMBB, DL, TII->get(Mips::AND), StoreVal)
5690b57cec5SDimitry Andric     .addReg(OldVal).addReg(Mask2);
5700b57cec5SDimitry Andric   BuildMI(loopMBB, DL, TII->get(Mips::OR), StoreVal)
5710b57cec5SDimitry Andric     .addReg(StoreVal).addReg(BinOpRes);
5720b57cec5SDimitry Andric   BuildMI(loopMBB, DL, TII->get(SC), StoreVal)
5730b57cec5SDimitry Andric     .addReg(StoreVal).addReg(Ptr).addImm(0);
5740b57cec5SDimitry Andric   BuildMI(loopMBB, DL, TII->get(BEQ))
5750b57cec5SDimitry Andric     .addReg(StoreVal).addReg(Mips::ZERO).addMBB(loopMBB);
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric   //  sinkMBB:
5780b57cec5SDimitry Andric   //    and     maskedoldval1,oldval,mask
5790b57cec5SDimitry Andric   //    srl     srlres,maskedoldval1,shiftamt
5800b57cec5SDimitry Andric   //    sign_extend dest,srlres
5810b57cec5SDimitry Andric 
582*0fca6ea1SDimitry Andric   if (!DestOK) {
5830b57cec5SDimitry Andric     sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne());
584*0fca6ea1SDimitry Andric     BuildMI(sinkMBB, DL, TII->get(Mips::AND), Dest).addReg(OldVal).addReg(Mask);
5850b57cec5SDimitry Andric     BuildMI(sinkMBB, DL, TII->get(Mips::SRLV), Dest)
586*0fca6ea1SDimitry Andric         .addReg(Dest)
587*0fca6ea1SDimitry Andric         .addReg(ShiftAmnt);
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric     if (STI->hasMips32r2()) {
5900b57cec5SDimitry Andric       BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest);
5910b57cec5SDimitry Andric     } else {
5920b57cec5SDimitry Andric       const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24;
5930b57cec5SDimitry Andric       BuildMI(sinkMBB, DL, TII->get(Mips::SLL), Dest)
5940b57cec5SDimitry Andric           .addReg(Dest, RegState::Kill)
5950b57cec5SDimitry Andric           .addImm(ShiftImm);
5960b57cec5SDimitry Andric       BuildMI(sinkMBB, DL, TII->get(Mips::SRA), Dest)
5970b57cec5SDimitry Andric           .addReg(Dest, RegState::Kill)
5980b57cec5SDimitry Andric           .addImm(ShiftImm);
5990b57cec5SDimitry Andric     }
600*0fca6ea1SDimitry Andric   }
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric   LivePhysRegs LiveRegs;
6030b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *loopMBB);
6040b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *sinkMBB);
6050b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *exitMBB);
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric   NMBBI = BB.end();
6080b57cec5SDimitry Andric   I->eraseFromParent();
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   return true;
6110b57cec5SDimitry Andric }
6120b57cec5SDimitry Andric 
expandAtomicBinOp(MachineBasicBlock & BB,MachineBasicBlock::iterator I,MachineBasicBlock::iterator & NMBBI,unsigned Size)6130b57cec5SDimitry Andric bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB,
6140b57cec5SDimitry Andric                                          MachineBasicBlock::iterator I,
6150b57cec5SDimitry Andric                                          MachineBasicBlock::iterator &NMBBI,
6160b57cec5SDimitry Andric                                          unsigned Size) {
6170b57cec5SDimitry Andric   MachineFunction *MF = BB.getParent();
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric   const bool ArePtrs64bit = STI->getABI().ArePtrs64bit();
6200b57cec5SDimitry Andric   DebugLoc DL = I->getDebugLoc();
6210b57cec5SDimitry Andric 
622480093f4SDimitry Andric   unsigned LL, SC, ZERO, BEQ, SLT, SLTu, OR, MOVN, MOVZ, SELNEZ, SELEQZ;
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric   if (Size == 4) {
6250b57cec5SDimitry Andric     if (STI->inMicroMipsMode()) {
6260b57cec5SDimitry Andric       LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM;
6270b57cec5SDimitry Andric       SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM;
6280b57cec5SDimitry Andric       BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM;
629480093f4SDimitry Andric       SLT = Mips::SLT_MM;
630480093f4SDimitry Andric       SLTu = Mips::SLTu_MM;
631480093f4SDimitry Andric       OR = STI->hasMips32r6() ? Mips::OR_MMR6 : Mips::OR_MM;
632480093f4SDimitry Andric       MOVN = Mips::MOVN_I_MM;
633480093f4SDimitry Andric       MOVZ = Mips::MOVZ_I_MM;
634480093f4SDimitry Andric       SELNEZ = STI->hasMips32r6() ? Mips::SELNEZ_MMR6 : Mips::SELNEZ;
635480093f4SDimitry Andric       SELEQZ = STI->hasMips32r6() ? Mips::SELEQZ_MMR6 : Mips::SELEQZ;
6360b57cec5SDimitry Andric     } else {
6370b57cec5SDimitry Andric       LL = STI->hasMips32r6()
6380b57cec5SDimitry Andric                ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
6390b57cec5SDimitry Andric                : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
6400b57cec5SDimitry Andric       SC = STI->hasMips32r6()
6410b57cec5SDimitry Andric                ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
6420b57cec5SDimitry Andric                : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
6430b57cec5SDimitry Andric       BEQ = Mips::BEQ;
644480093f4SDimitry Andric       SLT = Mips::SLT;
645480093f4SDimitry Andric       SLTu = Mips::SLTu;
646480093f4SDimitry Andric       OR = Mips::OR;
647480093f4SDimitry Andric       MOVN = Mips::MOVN_I_I;
648480093f4SDimitry Andric       MOVZ = Mips::MOVZ_I_I;
649480093f4SDimitry Andric       SELNEZ = Mips::SELNEZ;
650480093f4SDimitry Andric       SELEQZ = Mips::SELEQZ;
6510b57cec5SDimitry Andric     }
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric     ZERO = Mips::ZERO;
6540b57cec5SDimitry Andric   } else {
6550b57cec5SDimitry Andric     LL = STI->hasMips64r6() ? Mips::LLD_R6 : Mips::LLD;
6560b57cec5SDimitry Andric     SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD;
6570b57cec5SDimitry Andric     ZERO = Mips::ZERO_64;
6580b57cec5SDimitry Andric     BEQ = Mips::BEQ64;
659480093f4SDimitry Andric     SLT = Mips::SLT64;
660480093f4SDimitry Andric     SLTu = Mips::SLTu64;
661480093f4SDimitry Andric     OR = Mips::OR64;
662480093f4SDimitry Andric     MOVN = Mips::MOVN_I64_I64;
663480093f4SDimitry Andric     MOVZ = Mips::MOVZ_I64_I64;
664480093f4SDimitry Andric     SELNEZ = Mips::SELNEZ64;
665480093f4SDimitry Andric     SELEQZ = Mips::SELEQZ64;
6660b57cec5SDimitry Andric   }
6670b57cec5SDimitry Andric 
6688bcb0991SDimitry Andric   Register OldVal = I->getOperand(0).getReg();
6698bcb0991SDimitry Andric   Register Ptr = I->getOperand(1).getReg();
6708bcb0991SDimitry Andric   Register Incr = I->getOperand(2).getReg();
6718bcb0991SDimitry Andric   Register Scratch = I->getOperand(3).getReg();
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric   unsigned Opcode = 0;
6740b57cec5SDimitry Andric   unsigned AND = 0;
6750b57cec5SDimitry Andric   unsigned NOR = 0;
676480093f4SDimitry Andric 
677480093f4SDimitry Andric   bool IsOr = false;
6780b57cec5SDimitry Andric   bool IsNand = false;
679480093f4SDimitry Andric   bool IsMin = false;
680480093f4SDimitry Andric   bool IsMax = false;
681480093f4SDimitry Andric   bool IsUnsigned = false;
682480093f4SDimitry Andric 
6830b57cec5SDimitry Andric   switch (I->getOpcode()) {
6840b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_ADD_I32_POSTRA:
6850b57cec5SDimitry Andric     Opcode = Mips::ADDu;
6860b57cec5SDimitry Andric     break;
6870b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_SUB_I32_POSTRA:
6880b57cec5SDimitry Andric     Opcode = Mips::SUBu;
6890b57cec5SDimitry Andric     break;
6900b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_AND_I32_POSTRA:
6910b57cec5SDimitry Andric     Opcode = Mips::AND;
6920b57cec5SDimitry Andric     break;
6930b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_OR_I32_POSTRA:
6940b57cec5SDimitry Andric     Opcode = Mips::OR;
6950b57cec5SDimitry Andric     break;
6960b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_XOR_I32_POSTRA:
6970b57cec5SDimitry Andric     Opcode = Mips::XOR;
6980b57cec5SDimitry Andric     break;
6990b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_NAND_I32_POSTRA:
7000b57cec5SDimitry Andric     IsNand = true;
7010b57cec5SDimitry Andric     AND = Mips::AND;
7020b57cec5SDimitry Andric     NOR = Mips::NOR;
7030b57cec5SDimitry Andric     break;
7040b57cec5SDimitry Andric   case Mips::ATOMIC_SWAP_I32_POSTRA:
705480093f4SDimitry Andric     IsOr = true;
7060b57cec5SDimitry Andric     break;
7070b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_ADD_I64_POSTRA:
7080b57cec5SDimitry Andric     Opcode = Mips::DADDu;
7090b57cec5SDimitry Andric     break;
7100b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_SUB_I64_POSTRA:
7110b57cec5SDimitry Andric     Opcode = Mips::DSUBu;
7120b57cec5SDimitry Andric     break;
7130b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_AND_I64_POSTRA:
7140b57cec5SDimitry Andric     Opcode = Mips::AND64;
7150b57cec5SDimitry Andric     break;
7160b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_OR_I64_POSTRA:
7170b57cec5SDimitry Andric     Opcode = Mips::OR64;
7180b57cec5SDimitry Andric     break;
7190b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_XOR_I64_POSTRA:
7200b57cec5SDimitry Andric     Opcode = Mips::XOR64;
7210b57cec5SDimitry Andric     break;
7220b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_NAND_I64_POSTRA:
7230b57cec5SDimitry Andric     IsNand = true;
7240b57cec5SDimitry Andric     AND = Mips::AND64;
7250b57cec5SDimitry Andric     NOR = Mips::NOR64;
7260b57cec5SDimitry Andric     break;
7270b57cec5SDimitry Andric   case Mips::ATOMIC_SWAP_I64_POSTRA:
728480093f4SDimitry Andric     IsOr = true;
729480093f4SDimitry Andric     break;
730480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMIN_I32_POSTRA:
731480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMIN_I64_POSTRA:
732480093f4SDimitry Andric     IsUnsigned = true;
733bdd1243dSDimitry Andric     [[fallthrough]];
734480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MIN_I32_POSTRA:
735480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MIN_I64_POSTRA:
736480093f4SDimitry Andric     IsMin = true;
737480093f4SDimitry Andric     break;
738480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMAX_I32_POSTRA:
739480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMAX_I64_POSTRA:
740480093f4SDimitry Andric     IsUnsigned = true;
741bdd1243dSDimitry Andric     [[fallthrough]];
742480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MAX_I32_POSTRA:
743480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MAX_I64_POSTRA:
744480093f4SDimitry Andric     IsMax = true;
7450b57cec5SDimitry Andric     break;
7460b57cec5SDimitry Andric   default:
7470b57cec5SDimitry Andric     llvm_unreachable("Unknown pseudo atomic!");
7480b57cec5SDimitry Andric   }
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = BB.getBasicBlock();
7510b57cec5SDimitry Andric   MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
7520b57cec5SDimitry Andric   MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
7530b57cec5SDimitry Andric   MachineFunction::iterator It = ++BB.getIterator();
7540b57cec5SDimitry Andric   MF->insert(It, loopMBB);
7550b57cec5SDimitry Andric   MF->insert(It, exitMBB);
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric   exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end());
7580b57cec5SDimitry Andric   exitMBB->transferSuccessorsAndUpdatePHIs(&BB);
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric   BB.addSuccessor(loopMBB, BranchProbability::getOne());
7610b57cec5SDimitry Andric   loopMBB->addSuccessor(exitMBB);
7620b57cec5SDimitry Andric   loopMBB->addSuccessor(loopMBB);
7630b57cec5SDimitry Andric   loopMBB->normalizeSuccProbs();
7640b57cec5SDimitry Andric 
7650b57cec5SDimitry Andric   BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0);
7660b57cec5SDimitry Andric   assert((OldVal != Ptr) && "Clobbered the wrong ptr reg!");
7670b57cec5SDimitry Andric   assert((OldVal != Incr) && "Clobbered the wrong reg!");
768480093f4SDimitry Andric   if (IsMin || IsMax) {
769480093f4SDimitry Andric 
770480093f4SDimitry Andric     assert(I->getNumOperands() == 5 &&
771480093f4SDimitry Andric            "Atomics min|max|umin|umax use an additional register");
772e8d8bef9SDimitry Andric     MCRegister Scratch2 = I->getOperand(4).getReg().asMCReg();
773480093f4SDimitry Andric 
774480093f4SDimitry Andric     // On Mips64 result of slt is GPR32.
775e8d8bef9SDimitry Andric     MCRegister Scratch2_32 =
776480093f4SDimitry Andric         (Size == 8) ? STI->getRegisterInfo()->getSubReg(Scratch2, Mips::sub_32)
777480093f4SDimitry Andric                     : Scratch2;
778480093f4SDimitry Andric 
779480093f4SDimitry Andric     unsigned SLTScratch2 = IsUnsigned ? SLTu : SLT;
780480093f4SDimitry Andric     unsigned SELIncr = IsMax ? SELNEZ : SELEQZ;
781480093f4SDimitry Andric     unsigned SELOldVal = IsMax ? SELEQZ : SELNEZ;
782480093f4SDimitry Andric     unsigned MOVIncr = IsMax ? MOVN : MOVZ;
783480093f4SDimitry Andric 
784480093f4SDimitry Andric     // unsigned: sltu Scratch2, oldVal, Incr
785480093f4SDimitry Andric     // signed:   slt Scratch2, oldVal, Incr
786480093f4SDimitry Andric     BuildMI(loopMBB, DL, TII->get(SLTScratch2), Scratch2_32)
787480093f4SDimitry Andric         .addReg(OldVal)
788480093f4SDimitry Andric         .addReg(Incr);
789480093f4SDimitry Andric 
790480093f4SDimitry Andric     if (STI->hasMips64r6() || STI->hasMips32r6()) {
791480093f4SDimitry Andric       // max: seleqz Scratch, OldVal, Scratch2
792480093f4SDimitry Andric       //      selnez Scratch2, Incr, Scratch2
793480093f4SDimitry Andric       //      or Scratch, Scratch, Scratch2
794480093f4SDimitry Andric       // min: selnez Scratch, OldVal, Scratch2
795480093f4SDimitry Andric       //      seleqz Scratch2, Incr, Scratch2
796480093f4SDimitry Andric       //      or Scratch, Scratch, Scratch2
797480093f4SDimitry Andric       BuildMI(loopMBB, DL, TII->get(SELOldVal), Scratch)
798480093f4SDimitry Andric           .addReg(OldVal)
799480093f4SDimitry Andric           .addReg(Scratch2);
800480093f4SDimitry Andric       BuildMI(loopMBB, DL, TII->get(SELIncr), Scratch2)
801480093f4SDimitry Andric           .addReg(Incr)
802480093f4SDimitry Andric           .addReg(Scratch2);
803480093f4SDimitry Andric       BuildMI(loopMBB, DL, TII->get(OR), Scratch)
804480093f4SDimitry Andric           .addReg(Scratch)
805480093f4SDimitry Andric           .addReg(Scratch2);
806480093f4SDimitry Andric     } else {
807480093f4SDimitry Andric       // max: move Scratch, OldVal
808480093f4SDimitry Andric       //      movn Scratch, Incr, Scratch2, Scratch
809480093f4SDimitry Andric       // min: move Scratch, OldVal
810480093f4SDimitry Andric       //      movz Scratch, Incr, Scratch2, Scratch
811480093f4SDimitry Andric       BuildMI(loopMBB, DL, TII->get(OR), Scratch)
812480093f4SDimitry Andric           .addReg(OldVal)
813480093f4SDimitry Andric           .addReg(ZERO);
814480093f4SDimitry Andric       BuildMI(loopMBB, DL, TII->get(MOVIncr), Scratch)
815480093f4SDimitry Andric           .addReg(Incr)
816480093f4SDimitry Andric           .addReg(Scratch2)
817480093f4SDimitry Andric           .addReg(Scratch);
818480093f4SDimitry Andric     }
819480093f4SDimitry Andric 
820480093f4SDimitry Andric   } else if (Opcode) {
8210b57cec5SDimitry Andric     BuildMI(loopMBB, DL, TII->get(Opcode), Scratch).addReg(OldVal).addReg(Incr);
8220b57cec5SDimitry Andric   } else if (IsNand) {
8230b57cec5SDimitry Andric     assert(AND && NOR &&
8240b57cec5SDimitry Andric            "Unknown nand instruction for atomic pseudo expansion");
8250b57cec5SDimitry Andric     BuildMI(loopMBB, DL, TII->get(AND), Scratch).addReg(OldVal).addReg(Incr);
8260b57cec5SDimitry Andric     BuildMI(loopMBB, DL, TII->get(NOR), Scratch).addReg(ZERO).addReg(Scratch);
8270b57cec5SDimitry Andric   } else {
828480093f4SDimitry Andric     assert(IsOr && OR && "Unknown instruction for atomic pseudo expansion!");
829480093f4SDimitry Andric     (void)IsOr;
8300b57cec5SDimitry Andric     BuildMI(loopMBB, DL, TII->get(OR), Scratch).addReg(Incr).addReg(ZERO);
8310b57cec5SDimitry Andric   }
8320b57cec5SDimitry Andric 
833480093f4SDimitry Andric   BuildMI(loopMBB, DL, TII->get(SC), Scratch)
834480093f4SDimitry Andric       .addReg(Scratch)
835480093f4SDimitry Andric       .addReg(Ptr)
836480093f4SDimitry Andric       .addImm(0);
837480093f4SDimitry Andric   BuildMI(loopMBB, DL, TII->get(BEQ))
838480093f4SDimitry Andric       .addReg(Scratch)
839480093f4SDimitry Andric       .addReg(ZERO)
840480093f4SDimitry Andric       .addMBB(loopMBB);
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric   NMBBI = BB.end();
8430b57cec5SDimitry Andric   I->eraseFromParent();
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric   LivePhysRegs LiveRegs;
8460b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *loopMBB);
8470b57cec5SDimitry Andric   computeAndAddLiveIns(LiveRegs, *exitMBB);
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric   return true;
8500b57cec5SDimitry Andric }
8510b57cec5SDimitry Andric 
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NMBB)8520b57cec5SDimitry Andric bool MipsExpandPseudo::expandMI(MachineBasicBlock &MBB,
8530b57cec5SDimitry Andric                                 MachineBasicBlock::iterator MBBI,
8540b57cec5SDimitry Andric                                 MachineBasicBlock::iterator &NMBB) {
8550b57cec5SDimitry Andric 
8560b57cec5SDimitry Andric   bool Modified = false;
8570b57cec5SDimitry Andric 
8580b57cec5SDimitry Andric   switch (MBBI->getOpcode()) {
8590b57cec5SDimitry Andric   case Mips::ATOMIC_CMP_SWAP_I32_POSTRA:
8600b57cec5SDimitry Andric   case Mips::ATOMIC_CMP_SWAP_I64_POSTRA:
8610b57cec5SDimitry Andric     return expandAtomicCmpSwap(MBB, MBBI, NMBB);
8620b57cec5SDimitry Andric   case Mips::ATOMIC_CMP_SWAP_I8_POSTRA:
8630b57cec5SDimitry Andric   case Mips::ATOMIC_CMP_SWAP_I16_POSTRA:
8640b57cec5SDimitry Andric     return expandAtomicCmpSwapSubword(MBB, MBBI, NMBB);
8650b57cec5SDimitry Andric   case Mips::ATOMIC_SWAP_I8_POSTRA:
8660b57cec5SDimitry Andric   case Mips::ATOMIC_SWAP_I16_POSTRA:
8670b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_NAND_I8_POSTRA:
8680b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_NAND_I16_POSTRA:
8690b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_ADD_I8_POSTRA:
8700b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_ADD_I16_POSTRA:
8710b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_SUB_I8_POSTRA:
8720b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_SUB_I16_POSTRA:
8730b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_AND_I8_POSTRA:
8740b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_AND_I16_POSTRA:
8750b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_OR_I8_POSTRA:
8760b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_OR_I16_POSTRA:
8770b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_XOR_I8_POSTRA:
8780b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_XOR_I16_POSTRA:
879480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MIN_I8_POSTRA:
880480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MIN_I16_POSTRA:
881480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MAX_I8_POSTRA:
882480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MAX_I16_POSTRA:
883480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMIN_I8_POSTRA:
884480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMIN_I16_POSTRA:
885480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMAX_I8_POSTRA:
886480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMAX_I16_POSTRA:
8870b57cec5SDimitry Andric     return expandAtomicBinOpSubword(MBB, MBBI, NMBB);
8880b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_ADD_I32_POSTRA:
8890b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_SUB_I32_POSTRA:
8900b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_AND_I32_POSTRA:
8910b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_OR_I32_POSTRA:
8920b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_XOR_I32_POSTRA:
8930b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_NAND_I32_POSTRA:
8940b57cec5SDimitry Andric   case Mips::ATOMIC_SWAP_I32_POSTRA:
895480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MIN_I32_POSTRA:
896480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MAX_I32_POSTRA:
897480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMIN_I32_POSTRA:
898480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMAX_I32_POSTRA:
8990b57cec5SDimitry Andric     return expandAtomicBinOp(MBB, MBBI, NMBB, 4);
9000b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_ADD_I64_POSTRA:
9010b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_SUB_I64_POSTRA:
9020b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_AND_I64_POSTRA:
9030b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_OR_I64_POSTRA:
9040b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_XOR_I64_POSTRA:
9050b57cec5SDimitry Andric   case Mips::ATOMIC_LOAD_NAND_I64_POSTRA:
9060b57cec5SDimitry Andric   case Mips::ATOMIC_SWAP_I64_POSTRA:
907480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MIN_I64_POSTRA:
908480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_MAX_I64_POSTRA:
909480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMIN_I64_POSTRA:
910480093f4SDimitry Andric   case Mips::ATOMIC_LOAD_UMAX_I64_POSTRA:
9110b57cec5SDimitry Andric     return expandAtomicBinOp(MBB, MBBI, NMBB, 8);
9120b57cec5SDimitry Andric   default:
9130b57cec5SDimitry Andric     return Modified;
9140b57cec5SDimitry Andric   }
9150b57cec5SDimitry Andric }
9160b57cec5SDimitry Andric 
expandMBB(MachineBasicBlock & MBB)9170b57cec5SDimitry Andric bool MipsExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
9180b57cec5SDimitry Andric   bool Modified = false;
9190b57cec5SDimitry Andric 
9200b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
9210b57cec5SDimitry Andric   while (MBBI != E) {
9220b57cec5SDimitry Andric     MachineBasicBlock::iterator NMBBI = std::next(MBBI);
9230b57cec5SDimitry Andric     Modified |= expandMI(MBB, MBBI, NMBBI);
9240b57cec5SDimitry Andric     MBBI = NMBBI;
9250b57cec5SDimitry Andric   }
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric   return Modified;
9280b57cec5SDimitry Andric }
9290b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)9300b57cec5SDimitry Andric bool MipsExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
93181ad6265SDimitry Andric   STI = &MF.getSubtarget<MipsSubtarget>();
9320b57cec5SDimitry Andric   TII = STI->getInstrInfo();
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric   bool Modified = false;
9354824e7fdSDimitry Andric   for (MachineBasicBlock &MBB : MF)
9364824e7fdSDimitry Andric     Modified |= expandMBB(MBB);
9370b57cec5SDimitry Andric 
9380b57cec5SDimitry Andric   if (Modified)
9390b57cec5SDimitry Andric     MF.RenumberBlocks();
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric   return Modified;
9420b57cec5SDimitry Andric }
9430b57cec5SDimitry Andric 
9440b57cec5SDimitry Andric /// createMipsExpandPseudoPass - returns an instance of the pseudo instruction
9450b57cec5SDimitry Andric /// expansion pass.
createMipsExpandPseudoPass()9460b57cec5SDimitry Andric FunctionPass *llvm::createMipsExpandPseudoPass() {
9470b57cec5SDimitry Andric   return new MipsExpandPseudo();
9480b57cec5SDimitry Andric }
949