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; 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 430b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 440b57cec5SDimitry Andric return MachineFunctionProperties().set( 450b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs); 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric 480b57cec5SDimitry 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 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 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 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 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 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 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 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. 9460b57cec5SDimitry Andric FunctionPass *llvm::createMipsExpandPseudoPass() { 9470b57cec5SDimitry Andric return new MipsExpandPseudo(); 9480b57cec5SDimitry Andric } 949