10b57cec5SDimitry Andric //===- MipsDelaySlotFiller.cpp - Mips Delay Slot Filler -------------------===// 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 // Simple pass to fill delay slots with useful instructions. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCNaCl.h" 140b57cec5SDimitry Andric #include "Mips.h" 150b57cec5SDimitry Andric #include "MipsInstrInfo.h" 160b57cec5SDimitry Andric #include "MipsRegisterInfo.h" 170b57cec5SDimitry Andric #include "MipsSubtarget.h" 180b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 190b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 200b57cec5SDimitry Andric #include "llvm/ADT/PointerUnion.h" 210b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 220b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 230b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 240b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 250b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 260b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 350b57cec5SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h" 360b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 370b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 380b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 390b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 400b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 410b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 420b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 430b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 440b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 450b57cec5SDimitry Andric #include <algorithm> 460b57cec5SDimitry Andric #include <cassert> 470b57cec5SDimitry Andric #include <iterator> 480b57cec5SDimitry Andric #include <memory> 490b57cec5SDimitry Andric #include <utility> 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric using namespace llvm; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric #define DEBUG_TYPE "mips-delay-slot-filler" 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric STATISTIC(FilledSlots, "Number of delay slots filled"); 560b57cec5SDimitry Andric STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that" 570b57cec5SDimitry Andric " are not NOP."); 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric static cl::opt<bool> DisableDelaySlotFiller( 600b57cec5SDimitry Andric "disable-mips-delay-filler", 610b57cec5SDimitry Andric cl::init(false), 620b57cec5SDimitry Andric cl::desc("Fill all delay slots with NOPs."), 630b57cec5SDimitry Andric cl::Hidden); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric static cl::opt<bool> DisableForwardSearch( 660b57cec5SDimitry Andric "disable-mips-df-forward-search", 670b57cec5SDimitry Andric cl::init(true), 680b57cec5SDimitry Andric cl::desc("Disallow MIPS delay filler to search forward."), 690b57cec5SDimitry Andric cl::Hidden); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric static cl::opt<bool> DisableSuccBBSearch( 720b57cec5SDimitry Andric "disable-mips-df-succbb-search", 730b57cec5SDimitry Andric cl::init(true), 740b57cec5SDimitry Andric cl::desc("Disallow MIPS delay filler to search successor basic blocks."), 750b57cec5SDimitry Andric cl::Hidden); 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric static cl::opt<bool> DisableBackwardSearch( 780b57cec5SDimitry Andric "disable-mips-df-backward-search", 790b57cec5SDimitry Andric cl::init(false), 800b57cec5SDimitry Andric cl::desc("Disallow MIPS delay filler to search backward."), 810b57cec5SDimitry Andric cl::Hidden); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric enum CompactBranchPolicy { 840b57cec5SDimitry Andric CB_Never, ///< The policy 'never' may in some circumstances or for some 850b57cec5SDimitry Andric ///< ISAs not be absolutely adhered to. 860b57cec5SDimitry Andric CB_Optimal, ///< Optimal is the default and will produce compact branches 870b57cec5SDimitry Andric ///< when delay slots cannot be filled. 880b57cec5SDimitry Andric CB_Always ///< 'always' may in some circumstances may not be 890b57cec5SDimitry Andric ///< absolutely adhered to there may not be a corresponding 900b57cec5SDimitry Andric ///< compact form of a branch. 910b57cec5SDimitry Andric }; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric static cl::opt<CompactBranchPolicy> MipsCompactBranchPolicy( 94480093f4SDimitry Andric "mips-compact-branches", cl::Optional, cl::init(CB_Optimal), 950b57cec5SDimitry Andric cl::desc("MIPS Specific: Compact branch policy."), 96480093f4SDimitry Andric cl::values(clEnumValN(CB_Never, "never", 97480093f4SDimitry Andric "Do not use compact branches if possible."), 98480093f4SDimitry Andric clEnumValN(CB_Optimal, "optimal", 995ffd83dbSDimitry Andric "Use compact branches where appropriate (default)."), 100480093f4SDimitry Andric clEnumValN(CB_Always, "always", 101480093f4SDimitry Andric "Always use compact branches if possible."))); 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric namespace { 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric using Iter = MachineBasicBlock::iterator; 1060b57cec5SDimitry Andric using ReverseIter = MachineBasicBlock::reverse_iterator; 1070b57cec5SDimitry Andric using BB2BrMap = SmallDenseMap<MachineBasicBlock *, MachineInstr *, 2>; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric class RegDefsUses { 1100b57cec5SDimitry Andric public: 1110b57cec5SDimitry Andric RegDefsUses(const TargetRegisterInfo &TRI); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric void init(const MachineInstr &MI); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric /// This function sets all caller-saved registers in Defs. 1160b57cec5SDimitry Andric void setCallerSaved(const MachineInstr &MI); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric /// This function sets all unallocatable registers in Defs. 1190b57cec5SDimitry Andric void setUnallocatableRegs(const MachineFunction &MF); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric /// Set bits in Uses corresponding to MBB's live-out registers except for 1220b57cec5SDimitry Andric /// the registers that are live-in to SuccBB. 1230b57cec5SDimitry Andric void addLiveOut(const MachineBasicBlock &MBB, 1240b57cec5SDimitry Andric const MachineBasicBlock &SuccBB); 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric bool update(const MachineInstr &MI, unsigned Begin, unsigned End); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric private: 1290b57cec5SDimitry Andric bool checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, unsigned Reg, 1300b57cec5SDimitry Andric bool IsDef) const; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric /// Returns true if Reg or its alias is in RegSet. 1330b57cec5SDimitry Andric bool isRegInSet(const BitVector &RegSet, unsigned Reg) const; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric const TargetRegisterInfo &TRI; 1360b57cec5SDimitry Andric BitVector Defs, Uses; 1370b57cec5SDimitry Andric }; 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric /// Base class for inspecting loads and stores. 1400b57cec5SDimitry Andric class InspectMemInstr { 1410b57cec5SDimitry Andric public: 1420b57cec5SDimitry Andric InspectMemInstr(bool ForbidMemInstr_) : ForbidMemInstr(ForbidMemInstr_) {} 1430b57cec5SDimitry Andric virtual ~InspectMemInstr() = default; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric /// Return true if MI cannot be moved to delay slot. 1460b57cec5SDimitry Andric bool hasHazard(const MachineInstr &MI); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric protected: 1490b57cec5SDimitry Andric /// Flags indicating whether loads or stores have been seen. 1500b57cec5SDimitry Andric bool OrigSeenLoad = false; 1510b57cec5SDimitry Andric bool OrigSeenStore = false; 1520b57cec5SDimitry Andric bool SeenLoad = false; 1530b57cec5SDimitry Andric bool SeenStore = false; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric /// Memory instructions are not allowed to move to delay slot if this flag 1560b57cec5SDimitry Andric /// is true. 1570b57cec5SDimitry Andric bool ForbidMemInstr; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric private: 1600b57cec5SDimitry Andric virtual bool hasHazard_(const MachineInstr &MI) = 0; 1610b57cec5SDimitry Andric }; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric /// This subclass rejects any memory instructions. 1640b57cec5SDimitry Andric class NoMemInstr : public InspectMemInstr { 1650b57cec5SDimitry Andric public: 1660b57cec5SDimitry Andric NoMemInstr() : InspectMemInstr(true) {} 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric private: 1690b57cec5SDimitry Andric bool hasHazard_(const MachineInstr &MI) override { return true; } 1700b57cec5SDimitry Andric }; 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric /// This subclass accepts loads from stacks and constant loads. 1730b57cec5SDimitry Andric class LoadFromStackOrConst : public InspectMemInstr { 1740b57cec5SDimitry Andric public: 1750b57cec5SDimitry Andric LoadFromStackOrConst() : InspectMemInstr(false) {} 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric private: 1780b57cec5SDimitry Andric bool hasHazard_(const MachineInstr &MI) override; 1790b57cec5SDimitry Andric }; 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric /// This subclass uses memory dependence information to determine whether a 1820b57cec5SDimitry Andric /// memory instruction can be moved to a delay slot. 1830b57cec5SDimitry Andric class MemDefsUses : public InspectMemInstr { 1840b57cec5SDimitry Andric public: 185e8d8bef9SDimitry Andric explicit MemDefsUses(const MachineFrameInfo *MFI); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric private: 1880b57cec5SDimitry Andric using ValueType = PointerUnion<const Value *, const PseudoSourceValue *>; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric bool hasHazard_(const MachineInstr &MI) override; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric /// Update Defs and Uses. Return true if there exist dependences that 1930b57cec5SDimitry Andric /// disqualify the delay slot candidate between V and values in Uses and 1940b57cec5SDimitry Andric /// Defs. 1950b57cec5SDimitry Andric bool updateDefsUses(ValueType V, bool MayStore); 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric /// Get the list of underlying objects of MI's memory operand. 1980b57cec5SDimitry Andric bool getUnderlyingObjects(const MachineInstr &MI, 1990b57cec5SDimitry Andric SmallVectorImpl<ValueType> &Objects) const; 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric const MachineFrameInfo *MFI; 2020b57cec5SDimitry Andric SmallPtrSet<ValueType, 4> Uses, Defs; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric /// Flags indicating whether loads or stores with no underlying objects have 2050b57cec5SDimitry Andric /// been seen. 2060b57cec5SDimitry Andric bool SeenNoObjLoad = false; 2070b57cec5SDimitry Andric bool SeenNoObjStore = false; 2080b57cec5SDimitry Andric }; 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric class MipsDelaySlotFiller : public MachineFunctionPass { 2110b57cec5SDimitry Andric public: 2120b57cec5SDimitry Andric MipsDelaySlotFiller() : MachineFunctionPass(ID) { 2130b57cec5SDimitry Andric initializeMipsDelaySlotFillerPass(*PassRegistry::getPassRegistry()); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric StringRef getPassName() const override { return "Mips Delay Slot Filler"; } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &F) override { 2190b57cec5SDimitry Andric TM = &F.getTarget(); 2200b57cec5SDimitry Andric bool Changed = false; 2214824e7fdSDimitry Andric for (MachineBasicBlock &MBB : F) 2224824e7fdSDimitry Andric Changed |= runOnMachineBasicBlock(MBB); 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric // This pass invalidates liveness information when it reorders 2250b57cec5SDimitry Andric // instructions to fill delay slot. Without this, -verify-machineinstrs 2260b57cec5SDimitry Andric // will fail. 2270b57cec5SDimitry Andric if (Changed) 2280b57cec5SDimitry Andric F.getRegInfo().invalidateLiveness(); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric return Changed; 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 2340b57cec5SDimitry Andric return MachineFunctionProperties().set( 2350b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs); 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 239*0fca6ea1SDimitry Andric AU.addRequired<MachineBranchProbabilityInfoWrapperPass>(); 2400b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric static char ID; 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric private: 2460b57cec5SDimitry Andric bool runOnMachineBasicBlock(MachineBasicBlock &MBB); 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric Iter replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, 2490b57cec5SDimitry Andric const DebugLoc &DL); 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric /// This function checks if it is valid to move Candidate to the delay slot 2520b57cec5SDimitry Andric /// and returns true if it isn't. It also updates memory and register 2530b57cec5SDimitry Andric /// dependence information. 2540b57cec5SDimitry Andric bool delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, 2550b57cec5SDimitry Andric InspectMemInstr &IM) const; 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric /// This function searches range [Begin, End) for an instruction that can be 2580b57cec5SDimitry Andric /// moved to the delay slot. Returns true on success. 2590b57cec5SDimitry Andric template<typename IterTy> 2600b57cec5SDimitry Andric bool searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, 2610b57cec5SDimitry Andric RegDefsUses &RegDU, InspectMemInstr &IM, Iter Slot, 2620b57cec5SDimitry Andric IterTy &Filler) const; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric /// This function searches in the backward direction for an instruction that 2650b57cec5SDimitry Andric /// can be moved to the delay slot. Returns true on success. 2660b57cec5SDimitry Andric bool searchBackward(MachineBasicBlock &MBB, MachineInstr &Slot) const; 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric /// This function searches MBB in the forward direction for an instruction 2690b57cec5SDimitry Andric /// that can be moved to the delay slot. Returns true on success. 2700b57cec5SDimitry Andric bool searchForward(MachineBasicBlock &MBB, Iter Slot) const; 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric /// This function searches one of MBB's successor blocks for an instruction 2730b57cec5SDimitry Andric /// that can be moved to the delay slot and inserts clones of the 2740b57cec5SDimitry Andric /// instruction into the successor's predecessor blocks. 2750b57cec5SDimitry Andric bool searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const; 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric /// Pick a successor block of MBB. Return NULL if MBB doesn't have a 2780b57cec5SDimitry Andric /// successor block that is not a landing pad. 2790b57cec5SDimitry Andric MachineBasicBlock *selectSuccBB(MachineBasicBlock &B) const; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric /// This function analyzes MBB and returns an instruction with an unoccupied 2820b57cec5SDimitry Andric /// slot that branches to Dst. 2830b57cec5SDimitry Andric std::pair<MipsInstrInfo::BranchType, MachineInstr *> 2840b57cec5SDimitry Andric getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const; 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric /// Examine Pred and see if it is possible to insert an instruction into 2870b57cec5SDimitry Andric /// one of its branches delay slot or its end. 2880b57cec5SDimitry Andric bool examinePred(MachineBasicBlock &Pred, const MachineBasicBlock &Succ, 2890b57cec5SDimitry Andric RegDefsUses &RegDU, bool &HasMultipleSuccs, 2900b57cec5SDimitry Andric BB2BrMap &BrMap) const; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric bool terminateSearch(const MachineInstr &Candidate) const; 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric const TargetMachine *TM = nullptr; 2950b57cec5SDimitry Andric }; 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric } // end anonymous namespace 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric char MipsDelaySlotFiller::ID = 0; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric static bool hasUnoccupiedSlot(const MachineInstr *MI) { 3020b57cec5SDimitry Andric return MI->hasDelaySlot() && !MI->isBundledWithSucc(); 3030b57cec5SDimitry Andric } 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric INITIALIZE_PASS(MipsDelaySlotFiller, DEBUG_TYPE, 3060b57cec5SDimitry Andric "Fill delay slot for MIPS", false, false) 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric /// This function inserts clones of Filler into predecessor blocks. 3090b57cec5SDimitry Andric static void insertDelayFiller(Iter Filler, const BB2BrMap &BrMap) { 3100b57cec5SDimitry Andric MachineFunction *MF = Filler->getParent()->getParent(); 3110b57cec5SDimitry Andric 31204eeddc0SDimitry Andric for (const auto &I : BrMap) { 31304eeddc0SDimitry Andric if (I.second) { 31404eeddc0SDimitry Andric MIBundleBuilder(I.second).append(MF->CloneMachineInstr(&*Filler)); 3150b57cec5SDimitry Andric ++UsefulSlots; 3160b57cec5SDimitry Andric } else { 31704eeddc0SDimitry Andric I.first->push_back(MF->CloneMachineInstr(&*Filler)); 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric /// This function adds registers Filler defines to MBB's live-in register list. 3230b57cec5SDimitry Andric static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { 32406c3fb27SDimitry Andric for (const MachineOperand &MO : Filler->operands()) { 3250b57cec5SDimitry Andric unsigned R; 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef() || !(R = MO.getReg())) 3280b57cec5SDimitry Andric continue; 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric #ifndef NDEBUG 3310b57cec5SDimitry Andric const MachineFunction &MF = *MBB.getParent(); 3320b57cec5SDimitry Andric assert(MF.getSubtarget().getRegisterInfo()->getAllocatableSet(MF).test(R) && 3330b57cec5SDimitry Andric "Shouldn't move an instruction with unallocatable registers across " 3340b57cec5SDimitry Andric "basic block boundaries."); 3350b57cec5SDimitry Andric #endif 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric if (!MBB.isLiveIn(R)) 3380b57cec5SDimitry Andric MBB.addLiveIn(R); 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric RegDefsUses::RegDefsUses(const TargetRegisterInfo &TRI) 3430b57cec5SDimitry Andric : TRI(TRI), Defs(TRI.getNumRegs(), false), Uses(TRI.getNumRegs(), false) {} 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric void RegDefsUses::init(const MachineInstr &MI) { 3460b57cec5SDimitry Andric // Add all register operands which are explicit and non-variadic. 3470b57cec5SDimitry Andric update(MI, 0, MI.getDesc().getNumOperands()); 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric // If MI is a call, add RA to Defs to prevent users of RA from going into 3500b57cec5SDimitry Andric // delay slot. 3510b57cec5SDimitry Andric if (MI.isCall()) 3520b57cec5SDimitry Andric Defs.set(Mips::RA); 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric // Add all implicit register operands of branch instructions except 3550b57cec5SDimitry Andric // register AT. 3560b57cec5SDimitry Andric if (MI.isBranch()) { 3570b57cec5SDimitry Andric update(MI, MI.getDesc().getNumOperands(), MI.getNumOperands()); 3580b57cec5SDimitry Andric Defs.reset(Mips::AT); 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric void RegDefsUses::setCallerSaved(const MachineInstr &MI) { 3630b57cec5SDimitry Andric assert(MI.isCall()); 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric // Add RA/RA_64 to Defs to prevent users of RA/RA_64 from going into 3660b57cec5SDimitry Andric // the delay slot. The reason is that RA/RA_64 must not be changed 3670b57cec5SDimitry Andric // in the delay slot so that the callee can return to the caller. 368*0fca6ea1SDimitry Andric if (MI.definesRegister(Mips::RA, /*TRI=*/nullptr) || 369*0fca6ea1SDimitry Andric MI.definesRegister(Mips::RA_64, /*TRI=*/nullptr)) { 3700b57cec5SDimitry Andric Defs.set(Mips::RA); 3710b57cec5SDimitry Andric Defs.set(Mips::RA_64); 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric // If MI is a call, add all caller-saved registers to Defs. 3750b57cec5SDimitry Andric BitVector CallerSavedRegs(TRI.getNumRegs(), true); 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric CallerSavedRegs.reset(Mips::ZERO); 3780b57cec5SDimitry Andric CallerSavedRegs.reset(Mips::ZERO_64); 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric for (const MCPhysReg *R = TRI.getCalleeSavedRegs(MI.getParent()->getParent()); 3810b57cec5SDimitry Andric *R; ++R) 3820b57cec5SDimitry Andric for (MCRegAliasIterator AI(*R, &TRI, true); AI.isValid(); ++AI) 3830b57cec5SDimitry Andric CallerSavedRegs.reset(*AI); 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric Defs |= CallerSavedRegs; 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric void RegDefsUses::setUnallocatableRegs(const MachineFunction &MF) { 3890b57cec5SDimitry Andric BitVector AllocSet = TRI.getAllocatableSet(MF); 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric for (unsigned R : AllocSet.set_bits()) 3920b57cec5SDimitry Andric for (MCRegAliasIterator AI(R, &TRI, false); AI.isValid(); ++AI) 3930b57cec5SDimitry Andric AllocSet.set(*AI); 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric AllocSet.set(Mips::ZERO); 3960b57cec5SDimitry Andric AllocSet.set(Mips::ZERO_64); 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric Defs |= AllocSet.flip(); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric void RegDefsUses::addLiveOut(const MachineBasicBlock &MBB, 4020b57cec5SDimitry Andric const MachineBasicBlock &SuccBB) { 403349cc55cSDimitry Andric for (const MachineBasicBlock *S : MBB.successors()) 404349cc55cSDimitry Andric if (S != &SuccBB) 405349cc55cSDimitry Andric for (const auto &LI : S->liveins()) 4060b57cec5SDimitry Andric Uses.set(LI.PhysReg); 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric bool RegDefsUses::update(const MachineInstr &MI, unsigned Begin, unsigned End) { 4100b57cec5SDimitry Andric BitVector NewDefs(TRI.getNumRegs()), NewUses(TRI.getNumRegs()); 4110b57cec5SDimitry Andric bool HasHazard = false; 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric for (unsigned I = Begin; I != End; ++I) { 4140b57cec5SDimitry Andric const MachineOperand &MO = MI.getOperand(I); 4150b57cec5SDimitry Andric 416480093f4SDimitry Andric if (MO.isReg() && MO.getReg()) { 417480093f4SDimitry Andric if (checkRegDefsUses(NewDefs, NewUses, MO.getReg(), MO.isDef())) { 418480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found register hazard for operand " 419480093f4SDimitry Andric << I << ": "; 420480093f4SDimitry Andric MO.dump()); 421480093f4SDimitry Andric HasHazard = true; 422480093f4SDimitry Andric } 423480093f4SDimitry Andric } 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric Defs |= NewDefs; 4270b57cec5SDimitry Andric Uses |= NewUses; 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric return HasHazard; 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric bool RegDefsUses::checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, 4330b57cec5SDimitry Andric unsigned Reg, bool IsDef) const { 4340b57cec5SDimitry Andric if (IsDef) { 4350b57cec5SDimitry Andric NewDefs.set(Reg); 4360b57cec5SDimitry Andric // check whether Reg has already been defined or used. 4370b57cec5SDimitry Andric return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg)); 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric NewUses.set(Reg); 4410b57cec5SDimitry Andric // check whether Reg has already been defined. 4420b57cec5SDimitry Andric return isRegInSet(Defs, Reg); 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric bool RegDefsUses::isRegInSet(const BitVector &RegSet, unsigned Reg) const { 4460b57cec5SDimitry Andric // Check Reg and all aliased Registers. 4470b57cec5SDimitry Andric for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI) 4480b57cec5SDimitry Andric if (RegSet.test(*AI)) 4490b57cec5SDimitry Andric return true; 4500b57cec5SDimitry Andric return false; 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric bool InspectMemInstr::hasHazard(const MachineInstr &MI) { 4540b57cec5SDimitry Andric if (!MI.mayStore() && !MI.mayLoad()) 4550b57cec5SDimitry Andric return false; 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric if (ForbidMemInstr) 4580b57cec5SDimitry Andric return true; 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric OrigSeenLoad = SeenLoad; 4610b57cec5SDimitry Andric OrigSeenStore = SeenStore; 4620b57cec5SDimitry Andric SeenLoad |= MI.mayLoad(); 4630b57cec5SDimitry Andric SeenStore |= MI.mayStore(); 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric // If MI is an ordered or volatile memory reference, disallow moving 4660b57cec5SDimitry Andric // subsequent loads and stores to delay slot. 4670b57cec5SDimitry Andric if (MI.hasOrderedMemoryRef() && (OrigSeenLoad || OrigSeenStore)) { 4680b57cec5SDimitry Andric ForbidMemInstr = true; 4690b57cec5SDimitry Andric return true; 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric return hasHazard_(MI); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric bool LoadFromStackOrConst::hasHazard_(const MachineInstr &MI) { 4760b57cec5SDimitry Andric if (MI.mayStore()) 4770b57cec5SDimitry Andric return true; 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getPseudoValue()) 4800b57cec5SDimitry Andric return true; 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric if (const PseudoSourceValue *PSV = 4830b57cec5SDimitry Andric (*MI.memoperands_begin())->getPseudoValue()) { 4840b57cec5SDimitry Andric if (isa<FixedStackPseudoSourceValue>(PSV)) 4850b57cec5SDimitry Andric return false; 4860b57cec5SDimitry Andric return !PSV->isConstant(nullptr) && !PSV->isStack(); 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric return true; 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric 492e8d8bef9SDimitry Andric MemDefsUses::MemDefsUses(const MachineFrameInfo *MFI_) 493e8d8bef9SDimitry Andric : InspectMemInstr(false), MFI(MFI_) {} 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric bool MemDefsUses::hasHazard_(const MachineInstr &MI) { 4960b57cec5SDimitry Andric bool HasHazard = false; 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric // Check underlying object list. 4990b57cec5SDimitry Andric SmallVector<ValueType, 4> Objs; 5000b57cec5SDimitry Andric if (getUnderlyingObjects(MI, Objs)) { 5010b57cec5SDimitry Andric for (ValueType VT : Objs) 5020b57cec5SDimitry Andric HasHazard |= updateDefsUses(VT, MI.mayStore()); 5030b57cec5SDimitry Andric return HasHazard; 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric // No underlying objects found. 5070b57cec5SDimitry Andric HasHazard = MI.mayStore() && (OrigSeenLoad || OrigSeenStore); 5080b57cec5SDimitry Andric HasHazard |= MI.mayLoad() || OrigSeenStore; 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric SeenNoObjLoad |= MI.mayLoad(); 5110b57cec5SDimitry Andric SeenNoObjStore |= MI.mayStore(); 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric return HasHazard; 5140b57cec5SDimitry Andric } 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric bool MemDefsUses::updateDefsUses(ValueType V, bool MayStore) { 5170b57cec5SDimitry Andric if (MayStore) 5180b57cec5SDimitry Andric return !Defs.insert(V).second || Uses.count(V) || SeenNoObjStore || 5190b57cec5SDimitry Andric SeenNoObjLoad; 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric Uses.insert(V); 5220b57cec5SDimitry Andric return Defs.count(V) || SeenNoObjStore; 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric bool MemDefsUses:: 5260b57cec5SDimitry Andric getUnderlyingObjects(const MachineInstr &MI, 5270b57cec5SDimitry Andric SmallVectorImpl<ValueType> &Objects) const { 5280b57cec5SDimitry Andric if (!MI.hasOneMemOperand()) 5290b57cec5SDimitry Andric return false; 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric auto & MMO = **MI.memoperands_begin(); 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric if (const PseudoSourceValue *PSV = MMO.getPseudoValue()) { 5340b57cec5SDimitry Andric if (!PSV->isAliased(MFI)) 5350b57cec5SDimitry Andric return false; 5360b57cec5SDimitry Andric Objects.push_back(PSV); 5370b57cec5SDimitry Andric return true; 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric if (const Value *V = MMO.getValue()) { 5410b57cec5SDimitry Andric SmallVector<const Value *, 4> Objs; 542e8d8bef9SDimitry Andric ::getUnderlyingObjects(V, Objs); 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric for (const Value *UValue : Objs) { 5450b57cec5SDimitry Andric if (!isIdentifiedObject(V)) 5460b57cec5SDimitry Andric return false; 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric Objects.push_back(UValue); 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric return true; 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric return false; 5540b57cec5SDimitry Andric } 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric // Replace Branch with the compact branch instruction. 5570b57cec5SDimitry Andric Iter MipsDelaySlotFiller::replaceWithCompactBranch(MachineBasicBlock &MBB, 5580b57cec5SDimitry Andric Iter Branch, 5590b57cec5SDimitry Andric const DebugLoc &DL) { 5600b57cec5SDimitry Andric const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); 5610b57cec5SDimitry Andric const MipsInstrInfo *TII = STI.getInstrInfo(); 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric unsigned NewOpcode = TII->getEquivalentCompactForm(Branch); 5640b57cec5SDimitry Andric Branch = TII->genInstrWithNewOpc(NewOpcode, Branch); 5650b57cec5SDimitry Andric 566e8d8bef9SDimitry Andric auto *ToErase = cast<MachineInstr>(&*std::next(Branch)); 567e8d8bef9SDimitry Andric // Update call site info for the Branch. 568e8d8bef9SDimitry Andric if (ToErase->shouldUpdateCallSiteInfo()) 569e8d8bef9SDimitry Andric ToErase->getMF()->moveCallSiteInfo(ToErase, cast<MachineInstr>(&*Branch)); 570e8d8bef9SDimitry Andric ToErase->eraseFromParent(); 5710b57cec5SDimitry Andric return Branch; 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric // For given opcode returns opcode of corresponding instruction with short 5750b57cec5SDimitry Andric // delay slot. 5760b57cec5SDimitry Andric // For the pseudo TAILCALL*_MM instructions return the short delay slot 5770b57cec5SDimitry Andric // form. Unfortunately, TAILCALL<->b16 is denied as b16 has a limited range 5780b57cec5SDimitry Andric // that is too short to make use of for tail calls. 5790b57cec5SDimitry Andric static int getEquivalentCallShort(int Opcode) { 5800b57cec5SDimitry Andric switch (Opcode) { 5810b57cec5SDimitry Andric case Mips::BGEZAL: 5820b57cec5SDimitry Andric return Mips::BGEZALS_MM; 5830b57cec5SDimitry Andric case Mips::BLTZAL: 5840b57cec5SDimitry Andric return Mips::BLTZALS_MM; 5850b57cec5SDimitry Andric case Mips::JAL: 5860b57cec5SDimitry Andric case Mips::JAL_MM: 5870b57cec5SDimitry Andric return Mips::JALS_MM; 5880b57cec5SDimitry Andric case Mips::JALR: 5890b57cec5SDimitry Andric return Mips::JALRS_MM; 5900b57cec5SDimitry Andric case Mips::JALR16_MM: 5910b57cec5SDimitry Andric return Mips::JALRS16_MM; 5920b57cec5SDimitry Andric case Mips::TAILCALL_MM: 5930b57cec5SDimitry Andric llvm_unreachable("Attempting to shorten the TAILCALL_MM pseudo!"); 5940b57cec5SDimitry Andric case Mips::TAILCALLREG: 5950b57cec5SDimitry Andric return Mips::JR16_MM; 5960b57cec5SDimitry Andric default: 5970b57cec5SDimitry Andric llvm_unreachable("Unexpected call instruction for microMIPS."); 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric } 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric /// runOnMachineBasicBlock - Fill in delay slots for the given basic block. 6020b57cec5SDimitry Andric /// We assume there is only one delay slot per delayed instruction. 6030b57cec5SDimitry Andric bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) { 6040b57cec5SDimitry Andric bool Changed = false; 6050b57cec5SDimitry Andric const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); 6060b57cec5SDimitry Andric bool InMicroMipsMode = STI.inMicroMipsMode(); 6070b57cec5SDimitry Andric const MipsInstrInfo *TII = STI.getInstrInfo(); 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric for (Iter I = MBB.begin(); I != MBB.end(); ++I) { 6100b57cec5SDimitry Andric if (!hasUnoccupiedSlot(&*I)) 6110b57cec5SDimitry Andric continue; 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric // Delay slot filling is disabled at -O0, or in microMIPS32R6. 6145f757f3fSDimitry Andric if (!DisableDelaySlotFiller && 6155f757f3fSDimitry Andric (TM->getOptLevel() != CodeGenOptLevel::None) && 6160b57cec5SDimitry Andric !(InMicroMipsMode && STI.hasMips32r6())) { 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric bool Filled = false; 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric if (MipsCompactBranchPolicy.getValue() != CB_Always || 6210b57cec5SDimitry Andric !TII->getEquivalentCompactForm(I)) { 6220b57cec5SDimitry Andric if (searchBackward(MBB, *I)) { 623480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot" 624480093f4SDimitry Andric " in backwards search.\n"); 6250b57cec5SDimitry Andric Filled = true; 6260b57cec5SDimitry Andric } else if (I->isTerminator()) { 6270b57cec5SDimitry Andric if (searchSuccBBs(MBB, I)) { 6280b57cec5SDimitry Andric Filled = true; 629480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot" 630480093f4SDimitry Andric " in successor BB search.\n"); 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric } else if (searchForward(MBB, I)) { 633480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot" 634480093f4SDimitry Andric " in forwards search.\n"); 6350b57cec5SDimitry Andric Filled = true; 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric } 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric if (Filled) { 6400b57cec5SDimitry Andric // Get instruction with delay slot. 6410b57cec5SDimitry Andric MachineBasicBlock::instr_iterator DSI = I.getInstrIterator(); 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric if (InMicroMipsMode && TII->getInstSizeInBytes(*std::next(DSI)) == 2 && 6440b57cec5SDimitry Andric DSI->isCall()) { 6450b57cec5SDimitry Andric // If instruction in delay slot is 16b change opcode to 6460b57cec5SDimitry Andric // corresponding instruction with short delay slot. 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric // TODO: Implement an instruction mapping table of 16bit opcodes to 6490b57cec5SDimitry Andric // 32bit opcodes so that an instruction can be expanded. This would 6500b57cec5SDimitry Andric // save 16 bits as a TAILCALL_MM pseudo requires a fullsized nop. 6510b57cec5SDimitry Andric // TODO: Permit b16 when branching backwards to the same function 6520b57cec5SDimitry Andric // if it is in range. 6530b57cec5SDimitry Andric DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode()))); 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric ++FilledSlots; 6560b57cec5SDimitry Andric Changed = true; 6570b57cec5SDimitry Andric continue; 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric // For microMIPS if instruction is BEQ or BNE with one ZERO register, then 6620b57cec5SDimitry Andric // instead of adding NOP replace this instruction with the corresponding 6630b57cec5SDimitry Andric // compact branch instruction, i.e. BEQZC or BNEZC. Additionally 6640b57cec5SDimitry Andric // PseudoReturn and PseudoIndirectBranch are expanded to JR_MM, so they can 6650b57cec5SDimitry Andric // be replaced with JRC16_MM. 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric // For MIPSR6 attempt to produce the corresponding compact (no delay slot) 6680b57cec5SDimitry Andric // form of the CTI. For indirect jumps this will not require inserting a 6690b57cec5SDimitry Andric // NOP and for branches will hopefully avoid requiring a NOP. 6700b57cec5SDimitry Andric if ((InMicroMipsMode || 6710b57cec5SDimitry Andric (STI.hasMips32r6() && MipsCompactBranchPolicy != CB_Never)) && 6720b57cec5SDimitry Andric TII->getEquivalentCompactForm(I)) { 6730b57cec5SDimitry Andric I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); 6740b57cec5SDimitry Andric Changed = true; 6750b57cec5SDimitry Andric continue; 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric // Bundle the NOP to the instruction with the delay slot. 679480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE << ": could not fill delay slot for "; 680480093f4SDimitry Andric I->dump()); 68181ad6265SDimitry Andric TII->insertNop(MBB, std::next(I), I->getDebugLoc()); 6820b57cec5SDimitry Andric MIBundleBuilder(MBB, I, std::next(I, 2)); 6830b57cec5SDimitry Andric ++FilledSlots; 6840b57cec5SDimitry Andric Changed = true; 6850b57cec5SDimitry Andric } 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric return Changed; 6880b57cec5SDimitry Andric } 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric template <typename IterTy> 6910b57cec5SDimitry Andric bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin, 6920b57cec5SDimitry Andric IterTy End, RegDefsUses &RegDU, 6930b57cec5SDimitry Andric InspectMemInstr &IM, Iter Slot, 6940b57cec5SDimitry Andric IterTy &Filler) const { 6950b57cec5SDimitry Andric for (IterTy I = Begin; I != End;) { 6960b57cec5SDimitry Andric IterTy CurrI = I; 6970b57cec5SDimitry Andric ++I; 698480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE ": checking instruction: "; CurrI->dump()); 6990b57cec5SDimitry Andric // skip debug value 700480093f4SDimitry Andric if (CurrI->isDebugInstr()) { 701480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE ": ignoring debug instruction: "; 702480093f4SDimitry Andric CurrI->dump()); 7030b57cec5SDimitry Andric continue; 704480093f4SDimitry Andric } 7050b57cec5SDimitry Andric 706480093f4SDimitry Andric if (CurrI->isBundle()) { 707480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE ": ignoring BUNDLE instruction: "; 708480093f4SDimitry Andric CurrI->dump()); 709480093f4SDimitry Andric // However, we still need to update the register def-use information. 710480093f4SDimitry Andric RegDU.update(*CurrI, 0, CurrI->getNumOperands()); 711480093f4SDimitry Andric continue; 712480093f4SDimitry Andric } 713480093f4SDimitry Andric 714480093f4SDimitry Andric if (terminateSearch(*CurrI)) { 715480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE ": should terminate search: "; 716480093f4SDimitry Andric CurrI->dump()); 7170b57cec5SDimitry Andric break; 718480093f4SDimitry Andric } 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric assert((!CurrI->isCall() && !CurrI->isReturn() && !CurrI->isBranch()) && 7210b57cec5SDimitry Andric "Cannot put calls, returns or branches in delay slot."); 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric if (CurrI->isKill()) { 7240b57cec5SDimitry Andric CurrI->eraseFromParent(); 7250b57cec5SDimitry Andric continue; 7260b57cec5SDimitry Andric } 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric if (delayHasHazard(*CurrI, RegDU, IM)) 7290b57cec5SDimitry Andric continue; 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); 7320b57cec5SDimitry Andric if (STI.isTargetNaCl()) { 7330b57cec5SDimitry Andric // In NaCl, instructions that must be masked are forbidden in delay slots. 7340b57cec5SDimitry Andric // We only check for loads, stores and SP changes. Calls, returns and 7350b57cec5SDimitry Andric // branches are not checked because non-NaCl targets never put them in 7360b57cec5SDimitry Andric // delay slots. 7370b57cec5SDimitry Andric unsigned AddrIdx; 7380b57cec5SDimitry Andric if ((isBasePlusOffsetMemoryAccess(CurrI->getOpcode(), &AddrIdx) && 7390b57cec5SDimitry Andric baseRegNeedsLoadStoreMask(CurrI->getOperand(AddrIdx).getReg())) || 7400b57cec5SDimitry Andric CurrI->modifiesRegister(Mips::SP, STI.getRegisterInfo())) 7410b57cec5SDimitry Andric continue; 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric bool InMicroMipsMode = STI.inMicroMipsMode(); 7450b57cec5SDimitry Andric const MipsInstrInfo *TII = STI.getInstrInfo(); 7460b57cec5SDimitry Andric unsigned Opcode = (*Slot).getOpcode(); 7470b57cec5SDimitry Andric // This is complicated by the tail call optimization. For non-PIC code 7480b57cec5SDimitry Andric // there is only a 32bit sized unconditional branch which can be assumed 7490b57cec5SDimitry Andric // to be able to reach the target. b16 only has a range of +/- 1 KB. 7500b57cec5SDimitry Andric // It's entirely possible that the target function is reachable with b16 7510b57cec5SDimitry Andric // but we don't have enough information to make that decision. 7520b57cec5SDimitry Andric if (InMicroMipsMode && TII->getInstSizeInBytes(*CurrI) == 2 && 7530b57cec5SDimitry Andric (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch || 7540b57cec5SDimitry Andric Opcode == Mips::PseudoIndirectBranch_MM || 7550b57cec5SDimitry Andric Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL)) 7560b57cec5SDimitry Andric continue; 7570b57cec5SDimitry Andric // Instructions LWP/SWP and MOVEP should not be in a delay slot as that 7580b57cec5SDimitry Andric // results in unpredictable behaviour 7590b57cec5SDimitry Andric if (InMicroMipsMode && (Opcode == Mips::LWP_MM || Opcode == Mips::SWP_MM || 7600b57cec5SDimitry Andric Opcode == Mips::MOVEP_MM)) 7610b57cec5SDimitry Andric continue; 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric Filler = CurrI; 764480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot: "; 765480093f4SDimitry Andric CurrI->dump()); 766480093f4SDimitry Andric 7670b57cec5SDimitry Andric return true; 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric return false; 7710b57cec5SDimitry Andric } 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric bool MipsDelaySlotFiller::searchBackward(MachineBasicBlock &MBB, 7740b57cec5SDimitry Andric MachineInstr &Slot) const { 7750b57cec5SDimitry Andric if (DisableBackwardSearch) 7760b57cec5SDimitry Andric return false; 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric auto *Fn = MBB.getParent(); 7790b57cec5SDimitry Andric RegDefsUses RegDU(*Fn->getSubtarget().getRegisterInfo()); 780e8d8bef9SDimitry Andric MemDefsUses MemDU(&Fn->getFrameInfo()); 7810b57cec5SDimitry Andric ReverseIter Filler; 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric RegDU.init(Slot); 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric MachineBasicBlock::iterator SlotI = Slot; 7860b57cec5SDimitry Andric if (!searchRange(MBB, ++SlotI.getReverse(), MBB.rend(), RegDU, MemDU, Slot, 787480093f4SDimitry Andric Filler)) { 788480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE ": could not find instruction for delay " 789480093f4SDimitry Andric "slot using backwards search.\n"); 7900b57cec5SDimitry Andric return false; 791480093f4SDimitry Andric } 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric MBB.splice(std::next(SlotI), &MBB, Filler.getReverse()); 7940b57cec5SDimitry Andric MIBundleBuilder(MBB, SlotI, std::next(SlotI, 2)); 7950b57cec5SDimitry Andric ++UsefulSlots; 7960b57cec5SDimitry Andric return true; 7970b57cec5SDimitry Andric } 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric bool MipsDelaySlotFiller::searchForward(MachineBasicBlock &MBB, 8000b57cec5SDimitry Andric Iter Slot) const { 8010b57cec5SDimitry Andric // Can handle only calls. 8020b57cec5SDimitry Andric if (DisableForwardSearch || !Slot->isCall()) 8030b57cec5SDimitry Andric return false; 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); 8060b57cec5SDimitry Andric NoMemInstr NM; 8070b57cec5SDimitry Andric Iter Filler; 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric RegDU.setCallerSaved(*Slot); 8100b57cec5SDimitry Andric 811480093f4SDimitry Andric if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Slot, Filler)) { 812480093f4SDimitry Andric LLVM_DEBUG(dbgs() << DEBUG_TYPE ": could not find instruction for delay " 813480093f4SDimitry Andric "slot using forwards search.\n"); 8140b57cec5SDimitry Andric return false; 815480093f4SDimitry Andric } 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric MBB.splice(std::next(Slot), &MBB, Filler); 8180b57cec5SDimitry Andric MIBundleBuilder(MBB, Slot, std::next(Slot, 2)); 8190b57cec5SDimitry Andric ++UsefulSlots; 8200b57cec5SDimitry Andric return true; 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric bool MipsDelaySlotFiller::searchSuccBBs(MachineBasicBlock &MBB, 8240b57cec5SDimitry Andric Iter Slot) const { 8250b57cec5SDimitry Andric if (DisableSuccBBSearch) 8260b57cec5SDimitry Andric return false; 8270b57cec5SDimitry Andric 8280b57cec5SDimitry Andric MachineBasicBlock *SuccBB = selectSuccBB(MBB); 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric if (!SuccBB) 8310b57cec5SDimitry Andric return false; 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); 8340b57cec5SDimitry Andric bool HasMultipleSuccs = false; 8350b57cec5SDimitry Andric BB2BrMap BrMap; 8360b57cec5SDimitry Andric std::unique_ptr<InspectMemInstr> IM; 8370b57cec5SDimitry Andric Iter Filler; 8380b57cec5SDimitry Andric auto *Fn = MBB.getParent(); 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric // Iterate over SuccBB's predecessor list. 841349cc55cSDimitry Andric for (MachineBasicBlock *Pred : SuccBB->predecessors()) 842349cc55cSDimitry Andric if (!examinePred(*Pred, *SuccBB, RegDU, HasMultipleSuccs, BrMap)) 8430b57cec5SDimitry Andric return false; 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric // Do not allow moving instructions which have unallocatable register operands 8460b57cec5SDimitry Andric // across basic block boundaries. 8470b57cec5SDimitry Andric RegDU.setUnallocatableRegs(*Fn); 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric // Only allow moving loads from stack or constants if any of the SuccBB's 8500b57cec5SDimitry Andric // predecessors have multiple successors. 8510b57cec5SDimitry Andric if (HasMultipleSuccs) { 8520b57cec5SDimitry Andric IM.reset(new LoadFromStackOrConst()); 8530b57cec5SDimitry Andric } else { 8540b57cec5SDimitry Andric const MachineFrameInfo &MFI = Fn->getFrameInfo(); 855e8d8bef9SDimitry Andric IM.reset(new MemDefsUses(&MFI)); 8560b57cec5SDimitry Andric } 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Slot, 8590b57cec5SDimitry Andric Filler)) 8600b57cec5SDimitry Andric return false; 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric insertDelayFiller(Filler, BrMap); 8630b57cec5SDimitry Andric addLiveInRegs(Filler, *SuccBB); 8640b57cec5SDimitry Andric Filler->eraseFromParent(); 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric return true; 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric MachineBasicBlock * 8700b57cec5SDimitry Andric MipsDelaySlotFiller::selectSuccBB(MachineBasicBlock &B) const { 8710b57cec5SDimitry Andric if (B.succ_empty()) 8720b57cec5SDimitry Andric return nullptr; 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric // Select the successor with the larget edge weight. 875*0fca6ea1SDimitry Andric auto &Prob = getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI(); 8760b57cec5SDimitry Andric MachineBasicBlock *S = *std::max_element( 8770b57cec5SDimitry Andric B.succ_begin(), B.succ_end(), 8780b57cec5SDimitry Andric [&](const MachineBasicBlock *Dst0, const MachineBasicBlock *Dst1) { 8790b57cec5SDimitry Andric return Prob.getEdgeProbability(&B, Dst0) < 8800b57cec5SDimitry Andric Prob.getEdgeProbability(&B, Dst1); 8810b57cec5SDimitry Andric }); 8820b57cec5SDimitry Andric return S->isEHPad() ? nullptr : S; 8830b57cec5SDimitry Andric } 8840b57cec5SDimitry Andric 8850b57cec5SDimitry Andric std::pair<MipsInstrInfo::BranchType, MachineInstr *> 8860b57cec5SDimitry Andric MipsDelaySlotFiller::getBranch(MachineBasicBlock &MBB, 8870b57cec5SDimitry Andric const MachineBasicBlock &Dst) const { 8880b57cec5SDimitry Andric const MipsInstrInfo *TII = 8890b57cec5SDimitry Andric MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); 8900b57cec5SDimitry Andric MachineBasicBlock *TrueBB = nullptr, *FalseBB = nullptr; 8910b57cec5SDimitry Andric SmallVector<MachineInstr*, 2> BranchInstrs; 8920b57cec5SDimitry Andric SmallVector<MachineOperand, 2> Cond; 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric MipsInstrInfo::BranchType R = 8950b57cec5SDimitry Andric TII->analyzeBranch(MBB, TrueBB, FalseBB, Cond, false, BranchInstrs); 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric if ((R == MipsInstrInfo::BT_None) || (R == MipsInstrInfo::BT_NoBranch)) 8980b57cec5SDimitry Andric return std::make_pair(R, nullptr); 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric if (R != MipsInstrInfo::BT_CondUncond) { 9010b57cec5SDimitry Andric if (!hasUnoccupiedSlot(BranchInstrs[0])) 9020b57cec5SDimitry Andric return std::make_pair(MipsInstrInfo::BT_None, nullptr); 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric assert(((R != MipsInstrInfo::BT_Uncond) || (TrueBB == &Dst))); 9050b57cec5SDimitry Andric 9060b57cec5SDimitry Andric return std::make_pair(R, BranchInstrs[0]); 9070b57cec5SDimitry Andric } 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric assert((TrueBB == &Dst) || (FalseBB == &Dst)); 9100b57cec5SDimitry Andric 9110b57cec5SDimitry Andric // Examine the conditional branch. See if its slot is occupied. 9120b57cec5SDimitry Andric if (hasUnoccupiedSlot(BranchInstrs[0])) 9130b57cec5SDimitry Andric return std::make_pair(MipsInstrInfo::BT_Cond, BranchInstrs[0]); 9140b57cec5SDimitry Andric 9150b57cec5SDimitry Andric // If that fails, try the unconditional branch. 9160b57cec5SDimitry Andric if (hasUnoccupiedSlot(BranchInstrs[1]) && (FalseBB == &Dst)) 9170b57cec5SDimitry Andric return std::make_pair(MipsInstrInfo::BT_Uncond, BranchInstrs[1]); 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric return std::make_pair(MipsInstrInfo::BT_None, nullptr); 9200b57cec5SDimitry Andric } 9210b57cec5SDimitry Andric 9220b57cec5SDimitry Andric bool MipsDelaySlotFiller::examinePred(MachineBasicBlock &Pred, 9230b57cec5SDimitry Andric const MachineBasicBlock &Succ, 9240b57cec5SDimitry Andric RegDefsUses &RegDU, 9250b57cec5SDimitry Andric bool &HasMultipleSuccs, 9260b57cec5SDimitry Andric BB2BrMap &BrMap) const { 9270b57cec5SDimitry Andric std::pair<MipsInstrInfo::BranchType, MachineInstr *> P = 9280b57cec5SDimitry Andric getBranch(Pred, Succ); 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric // Return if either getBranch wasn't able to analyze the branches or there 9310b57cec5SDimitry Andric // were no branches with unoccupied slots. 9320b57cec5SDimitry Andric if (P.first == MipsInstrInfo::BT_None) 9330b57cec5SDimitry Andric return false; 9340b57cec5SDimitry Andric 9350b57cec5SDimitry Andric if ((P.first != MipsInstrInfo::BT_Uncond) && 9360b57cec5SDimitry Andric (P.first != MipsInstrInfo::BT_NoBranch)) { 9370b57cec5SDimitry Andric HasMultipleSuccs = true; 9380b57cec5SDimitry Andric RegDU.addLiveOut(Pred, Succ); 9390b57cec5SDimitry Andric } 9400b57cec5SDimitry Andric 9410b57cec5SDimitry Andric BrMap[&Pred] = P.second; 9420b57cec5SDimitry Andric return true; 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric bool MipsDelaySlotFiller::delayHasHazard(const MachineInstr &Candidate, 9460b57cec5SDimitry Andric RegDefsUses &RegDU, 9470b57cec5SDimitry Andric InspectMemInstr &IM) const { 9480b57cec5SDimitry Andric assert(!Candidate.isKill() && 9490b57cec5SDimitry Andric "KILL instructions should have been eliminated at this point."); 9500b57cec5SDimitry Andric 9510b57cec5SDimitry Andric bool HasHazard = Candidate.isImplicitDef(); 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric HasHazard |= IM.hasHazard(Candidate); 9540b57cec5SDimitry Andric HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands()); 9550b57cec5SDimitry Andric 9560b57cec5SDimitry Andric return HasHazard; 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric 9590b57cec5SDimitry Andric bool MipsDelaySlotFiller::terminateSearch(const MachineInstr &Candidate) const { 9600b57cec5SDimitry Andric return (Candidate.isTerminator() || Candidate.isCall() || 9610b57cec5SDimitry Andric Candidate.isPosition() || Candidate.isInlineAsm() || 9620b57cec5SDimitry Andric Candidate.hasUnmodeledSideEffects()); 9630b57cec5SDimitry Andric } 9640b57cec5SDimitry Andric 9650b57cec5SDimitry Andric /// createMipsDelaySlotFillerPass - Returns a pass that fills in delay 9660b57cec5SDimitry Andric /// slots in Mips MachineFunctions 967480093f4SDimitry Andric FunctionPass *llvm::createMipsDelaySlotFillerPass() { 968480093f4SDimitry Andric return new MipsDelaySlotFiller(); 969480093f4SDimitry Andric } 970