1249423Sdim//===-- MipsDelaySlotFiller.cpp - Mips Delay Slot Filler ------------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10249423Sdim// Simple pass to fill delay slots with useful instructions. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#define DEBUG_TYPE "delay-slot-filler" 15193323Sed 16193323Sed#include "Mips.h" 17249423Sdim#include "MipsInstrInfo.h" 18193323Sed#include "MipsTargetMachine.h" 19249423Sdim#include "llvm/ADT/BitVector.h" 20249423Sdim#include "llvm/ADT/SmallPtrSet.h" 21249423Sdim#include "llvm/ADT/Statistic.h" 22249423Sdim#include "llvm/Analysis/AliasAnalysis.h" 23249423Sdim#include "llvm/Analysis/ValueTracking.h" 24249423Sdim#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" 25193323Sed#include "llvm/CodeGen/MachineFunctionPass.h" 26193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 27249423Sdim#include "llvm/CodeGen/PseudoSourceValue.h" 28226633Sdim#include "llvm/Support/CommandLine.h" 29249423Sdim#include "llvm/Target/TargetInstrInfo.h" 30226633Sdim#include "llvm/Target/TargetMachine.h" 31226633Sdim#include "llvm/Target/TargetRegisterInfo.h" 32193323Sed 33193323Sedusing namespace llvm; 34193323Sed 35193323SedSTATISTIC(FilledSlots, "Number of delay slots filled"); 36226633SdimSTATISTIC(UsefulSlots, "Number of delay slots filled with instructions that" 37226633Sdim " are not NOP."); 38193323Sed 39243830Sdimstatic cl::opt<bool> DisableDelaySlotFiller( 40243830Sdim "disable-mips-delay-filler", 41226633Sdim cl::init(false), 42249423Sdim cl::desc("Fill all delay slots with NOPs."), 43226633Sdim cl::Hidden); 44226633Sdim 45249423Sdimstatic cl::opt<bool> DisableForwardSearch( 46249423Sdim "disable-mips-df-forward-search", 47249423Sdim cl::init(true), 48249423Sdim cl::desc("Disallow MIPS delay filler to search forward."), 49249423Sdim cl::Hidden); 50249423Sdim 51249423Sdimstatic cl::opt<bool> DisableSuccBBSearch( 52249423Sdim "disable-mips-df-succbb-search", 53249423Sdim cl::init(true), 54249423Sdim cl::desc("Disallow MIPS delay filler to search successor basic blocks."), 55249423Sdim cl::Hidden); 56249423Sdim 57249423Sdimstatic cl::opt<bool> DisableBackwardSearch( 58249423Sdim "disable-mips-df-backward-search", 59239462Sdim cl::init(false), 60249423Sdim cl::desc("Disallow MIPS delay filler to search backward."), 61239462Sdim cl::Hidden); 62239462Sdim 63193323Sednamespace { 64249423Sdim typedef MachineBasicBlock::iterator Iter; 65249423Sdim typedef MachineBasicBlock::reverse_iterator ReverseIter; 66249423Sdim typedef SmallDenseMap<MachineBasicBlock*, MachineInstr*, 2> BB2BrMap; 67193323Sed 68249423Sdim /// \brief A functor comparing edge weight of two blocks. 69249423Sdim struct CmpWeight { 70249423Sdim CmpWeight(const MachineBasicBlock &S, 71249423Sdim const MachineBranchProbabilityInfo &P) : Src(S), Prob(P) {} 72193323Sed 73249423Sdim bool operator()(const MachineBasicBlock *Dst0, 74249423Sdim const MachineBasicBlock *Dst1) const { 75249423Sdim return Prob.getEdgeWeight(&Src, Dst0) < Prob.getEdgeWeight(&Src, Dst1); 76249423Sdim } 77249423Sdim 78249423Sdim const MachineBasicBlock &Src; 79249423Sdim const MachineBranchProbabilityInfo &Prob; 80249423Sdim }; 81249423Sdim 82249423Sdim class RegDefsUses { 83249423Sdim public: 84249423Sdim RegDefsUses(TargetMachine &TM); 85249423Sdim void init(const MachineInstr &MI); 86249423Sdim 87249423Sdim /// This function sets all caller-saved registers in Defs. 88249423Sdim void setCallerSaved(const MachineInstr &MI); 89249423Sdim 90249423Sdim /// This function sets all unallocatable registers in Defs. 91249423Sdim void setUnallocatableRegs(const MachineFunction &MF); 92249423Sdim 93249423Sdim /// Set bits in Uses corresponding to MBB's live-out registers except for 94249423Sdim /// the registers that are live-in to SuccBB. 95249423Sdim void addLiveOut(const MachineBasicBlock &MBB, 96249423Sdim const MachineBasicBlock &SuccBB); 97249423Sdim 98249423Sdim bool update(const MachineInstr &MI, unsigned Begin, unsigned End); 99249423Sdim 100249423Sdim private: 101249423Sdim bool checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, unsigned Reg, 102249423Sdim bool IsDef) const; 103249423Sdim 104249423Sdim /// Returns true if Reg or its alias is in RegSet. 105249423Sdim bool isRegInSet(const BitVector &RegSet, unsigned Reg) const; 106249423Sdim 107249423Sdim const TargetRegisterInfo &TRI; 108249423Sdim BitVector Defs, Uses; 109249423Sdim }; 110249423Sdim 111249423Sdim /// Base class for inspecting loads and stores. 112249423Sdim class InspectMemInstr { 113249423Sdim public: 114249423Sdim InspectMemInstr(bool ForbidMemInstr_) 115249423Sdim : OrigSeenLoad(false), OrigSeenStore(false), SeenLoad(false), 116249423Sdim SeenStore(false), ForbidMemInstr(ForbidMemInstr_) {} 117249423Sdim 118249423Sdim /// Return true if MI cannot be moved to delay slot. 119249423Sdim bool hasHazard(const MachineInstr &MI); 120249423Sdim 121249423Sdim virtual ~InspectMemInstr() {} 122249423Sdim 123249423Sdim protected: 124249423Sdim /// Flags indicating whether loads or stores have been seen. 125249423Sdim bool OrigSeenLoad, OrigSeenStore, SeenLoad, SeenStore; 126249423Sdim 127249423Sdim /// Memory instructions are not allowed to move to delay slot if this flag 128249423Sdim /// is true. 129249423Sdim bool ForbidMemInstr; 130249423Sdim 131249423Sdim private: 132249423Sdim virtual bool hasHazard_(const MachineInstr &MI) = 0; 133249423Sdim }; 134249423Sdim 135249423Sdim /// This subclass rejects any memory instructions. 136249423Sdim class NoMemInstr : public InspectMemInstr { 137249423Sdim public: 138249423Sdim NoMemInstr() : InspectMemInstr(true) {} 139249423Sdim private: 140249423Sdim virtual bool hasHazard_(const MachineInstr &MI) { return true; } 141249423Sdim }; 142249423Sdim 143249423Sdim /// This subclass accepts loads from stacks and constant loads. 144249423Sdim class LoadFromStackOrConst : public InspectMemInstr { 145249423Sdim public: 146249423Sdim LoadFromStackOrConst() : InspectMemInstr(false) {} 147249423Sdim private: 148249423Sdim virtual bool hasHazard_(const MachineInstr &MI); 149249423Sdim }; 150249423Sdim 151249423Sdim /// This subclass uses memory dependence information to determine whether a 152249423Sdim /// memory instruction can be moved to a delay slot. 153249423Sdim class MemDefsUses : public InspectMemInstr { 154249423Sdim public: 155249423Sdim MemDefsUses(const MachineFrameInfo *MFI); 156249423Sdim 157249423Sdim private: 158249423Sdim virtual bool hasHazard_(const MachineInstr &MI); 159249423Sdim 160249423Sdim /// Update Defs and Uses. Return true if there exist dependences that 161249423Sdim /// disqualify the delay slot candidate between V and values in Uses and 162249423Sdim /// Defs. 163249423Sdim bool updateDefsUses(const Value *V, bool MayStore); 164249423Sdim 165249423Sdim /// Get the list of underlying objects of MI's memory operand. 166249423Sdim bool getUnderlyingObjects(const MachineInstr &MI, 167249423Sdim SmallVectorImpl<const Value *> &Objects) const; 168249423Sdim 169249423Sdim const MachineFrameInfo *MFI; 170249423Sdim SmallPtrSet<const Value*, 4> Uses, Defs; 171249423Sdim 172249423Sdim /// Flags indicating whether loads or stores with no underlying objects have 173249423Sdim /// been seen. 174249423Sdim bool SeenNoObjLoad, SeenNoObjStore; 175249423Sdim }; 176249423Sdim 177249423Sdim class Filler : public MachineFunctionPass { 178249423Sdim public: 179218893Sdim Filler(TargetMachine &tm) 180212904Sdim : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } 181193323Sed 182193323Sed virtual const char *getPassName() const { 183193323Sed return "Mips Delay Slot Filler"; 184193323Sed } 185193323Sed 186193323Sed bool runOnMachineFunction(MachineFunction &F) { 187193323Sed bool Changed = false; 188193323Sed for (MachineFunction::iterator FI = F.begin(), FE = F.end(); 189193323Sed FI != FE; ++FI) 190193323Sed Changed |= runOnMachineBasicBlock(*FI); 191193323Sed return Changed; 192193323Sed } 193193323Sed 194249423Sdim void getAnalysisUsage(AnalysisUsage &AU) const { 195249423Sdim AU.addRequired<MachineBranchProbabilityInfo>(); 196249423Sdim MachineFunctionPass::getAnalysisUsage(AU); 197249423Sdim } 198226633Sdim 199249423Sdim private: 200249423Sdim bool runOnMachineBasicBlock(MachineBasicBlock &MBB); 201226633Sdim 202249423Sdim /// This function checks if it is valid to move Candidate to the delay slot 203249423Sdim /// and returns true if it isn't. It also updates memory and register 204249423Sdim /// dependence information. 205249423Sdim bool delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, 206249423Sdim InspectMemInstr &IM) const; 207226633Sdim 208249423Sdim /// This function searches range [Begin, End) for an instruction that can be 209249423Sdim /// moved to the delay slot. Returns true on success. 210249423Sdim template<typename IterTy> 211249423Sdim bool searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, 212249423Sdim RegDefsUses &RegDU, InspectMemInstr &IM, 213249423Sdim IterTy &Filler) const; 214226633Sdim 215249423Sdim /// This function searches in the backward direction for an instruction that 216249423Sdim /// can be moved to the delay slot. Returns true on success. 217249423Sdim bool searchBackward(MachineBasicBlock &MBB, Iter Slot) const; 218226633Sdim 219249423Sdim /// This function searches MBB in the forward direction for an instruction 220249423Sdim /// that can be moved to the delay slot. Returns true on success. 221249423Sdim bool searchForward(MachineBasicBlock &MBB, Iter Slot) const; 222226633Sdim 223249423Sdim /// This function searches one of MBB's successor blocks for an instruction 224249423Sdim /// that can be moved to the delay slot and inserts clones of the 225249423Sdim /// instruction into the successor's predecessor blocks. 226249423Sdim bool searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const; 227226633Sdim 228249423Sdim /// Pick a successor block of MBB. Return NULL if MBB doesn't have a 229249423Sdim /// successor block that is not a landing pad. 230249423Sdim MachineBasicBlock *selectSuccBB(MachineBasicBlock &B) const; 231249423Sdim 232249423Sdim /// This function analyzes MBB and returns an instruction with an unoccupied 233249423Sdim /// slot that branches to Dst. 234249423Sdim std::pair<MipsInstrInfo::BranchType, MachineInstr *> 235249423Sdim getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const; 236249423Sdim 237249423Sdim /// Examine Pred and see if it is possible to insert an instruction into 238249423Sdim /// one of its branches delay slot or its end. 239249423Sdim bool examinePred(MachineBasicBlock &Pred, const MachineBasicBlock &Succ, 240249423Sdim RegDefsUses &RegDU, bool &HasMultipleSuccs, 241249423Sdim BB2BrMap &BrMap) const; 242249423Sdim 243249423Sdim bool terminateSearch(const MachineInstr &Candidate) const; 244249423Sdim 245249423Sdim TargetMachine &TM; 246249423Sdim const TargetInstrInfo *TII; 247249423Sdim 248249423Sdim static char ID; 249193323Sed }; 250193323Sed char Filler::ID = 0; 251193323Sed} // end of anonymous namespace 252193323Sed 253249423Sdimstatic bool hasUnoccupiedSlot(const MachineInstr *MI) { 254249423Sdim return MI->hasDelaySlot() && !MI->isBundledWithSucc(); 255249423Sdim} 256249423Sdim 257249423Sdim/// This function inserts clones of Filler into predecessor blocks. 258249423Sdimstatic void insertDelayFiller(Iter Filler, const BB2BrMap &BrMap) { 259249423Sdim MachineFunction *MF = Filler->getParent()->getParent(); 260249423Sdim 261249423Sdim for (BB2BrMap::const_iterator I = BrMap.begin(); I != BrMap.end(); ++I) { 262249423Sdim if (I->second) { 263249423Sdim MIBundleBuilder(I->second).append(MF->CloneMachineInstr(&*Filler)); 264249423Sdim ++UsefulSlots; 265249423Sdim } else { 266249423Sdim I->first->insert(I->first->end(), MF->CloneMachineInstr(&*Filler)); 267249423Sdim } 268249423Sdim } 269249423Sdim} 270249423Sdim 271249423Sdim/// This function adds registers Filler defines to MBB's live-in register list. 272249423Sdimstatic void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { 273249423Sdim for (unsigned I = 0, E = Filler->getNumOperands(); I != E; ++I) { 274249423Sdim const MachineOperand &MO = Filler->getOperand(I); 275249423Sdim unsigned R; 276249423Sdim 277249423Sdim if (!MO.isReg() || !MO.isDef() || !(R = MO.getReg())) 278249423Sdim continue; 279249423Sdim 280249423Sdim#ifndef NDEBUG 281249423Sdim const MachineFunction &MF = *MBB.getParent(); 282249423Sdim assert(MF.getTarget().getRegisterInfo()->getAllocatableSet(MF).test(R) && 283249423Sdim "Shouldn't move an instruction with unallocatable registers across " 284249423Sdim "basic block boundaries."); 285249423Sdim#endif 286249423Sdim 287249423Sdim if (!MBB.isLiveIn(R)) 288249423Sdim MBB.addLiveIn(R); 289249423Sdim } 290249423Sdim} 291249423Sdim 292249423SdimRegDefsUses::RegDefsUses(TargetMachine &TM) 293249423Sdim : TRI(*TM.getRegisterInfo()), Defs(TRI.getNumRegs(), false), 294249423Sdim Uses(TRI.getNumRegs(), false) {} 295249423Sdim 296249423Sdimvoid RegDefsUses::init(const MachineInstr &MI) { 297249423Sdim // Add all register operands which are explicit and non-variadic. 298249423Sdim update(MI, 0, MI.getDesc().getNumOperands()); 299249423Sdim 300249423Sdim // If MI is a call, add RA to Defs to prevent users of RA from going into 301249423Sdim // delay slot. 302249423Sdim if (MI.isCall()) 303249423Sdim Defs.set(Mips::RA); 304249423Sdim 305249423Sdim // Add all implicit register operands of branch instructions except 306249423Sdim // register AT. 307249423Sdim if (MI.isBranch()) { 308249423Sdim update(MI, MI.getDesc().getNumOperands(), MI.getNumOperands()); 309249423Sdim Defs.reset(Mips::AT); 310249423Sdim } 311249423Sdim} 312249423Sdim 313249423Sdimvoid RegDefsUses::setCallerSaved(const MachineInstr &MI) { 314249423Sdim assert(MI.isCall()); 315249423Sdim 316249423Sdim // If MI is a call, add all caller-saved registers to Defs. 317249423Sdim BitVector CallerSavedRegs(TRI.getNumRegs(), true); 318249423Sdim 319249423Sdim CallerSavedRegs.reset(Mips::ZERO); 320249423Sdim CallerSavedRegs.reset(Mips::ZERO_64); 321249423Sdim 322249423Sdim for (const MCPhysReg *R = TRI.getCalleeSavedRegs(); *R; ++R) 323249423Sdim for (MCRegAliasIterator AI(*R, &TRI, true); AI.isValid(); ++AI) 324249423Sdim CallerSavedRegs.reset(*AI); 325249423Sdim 326249423Sdim Defs |= CallerSavedRegs; 327249423Sdim} 328249423Sdim 329249423Sdimvoid RegDefsUses::setUnallocatableRegs(const MachineFunction &MF) { 330249423Sdim BitVector AllocSet = TRI.getAllocatableSet(MF); 331249423Sdim 332249423Sdim for (int R = AllocSet.find_first(); R != -1; R = AllocSet.find_next(R)) 333249423Sdim for (MCRegAliasIterator AI(R, &TRI, false); AI.isValid(); ++AI) 334249423Sdim AllocSet.set(*AI); 335249423Sdim 336249423Sdim AllocSet.set(Mips::ZERO); 337249423Sdim AllocSet.set(Mips::ZERO_64); 338249423Sdim 339249423Sdim Defs |= AllocSet.flip(); 340249423Sdim} 341249423Sdim 342249423Sdimvoid RegDefsUses::addLiveOut(const MachineBasicBlock &MBB, 343249423Sdim const MachineBasicBlock &SuccBB) { 344249423Sdim for (MachineBasicBlock::const_succ_iterator SI = MBB.succ_begin(), 345249423Sdim SE = MBB.succ_end(); SI != SE; ++SI) 346249423Sdim if (*SI != &SuccBB) 347249423Sdim for (MachineBasicBlock::livein_iterator LI = (*SI)->livein_begin(), 348249423Sdim LE = (*SI)->livein_end(); LI != LE; ++LI) 349249423Sdim Uses.set(*LI); 350249423Sdim} 351249423Sdim 352249423Sdimbool RegDefsUses::update(const MachineInstr &MI, unsigned Begin, unsigned End) { 353249423Sdim BitVector NewDefs(TRI.getNumRegs()), NewUses(TRI.getNumRegs()); 354249423Sdim bool HasHazard = false; 355249423Sdim 356249423Sdim for (unsigned I = Begin; I != End; ++I) { 357249423Sdim const MachineOperand &MO = MI.getOperand(I); 358249423Sdim 359249423Sdim if (MO.isReg() && MO.getReg()) 360249423Sdim HasHazard |= checkRegDefsUses(NewDefs, NewUses, MO.getReg(), MO.isDef()); 361249423Sdim } 362249423Sdim 363249423Sdim Defs |= NewDefs; 364249423Sdim Uses |= NewUses; 365249423Sdim 366249423Sdim return HasHazard; 367249423Sdim} 368249423Sdim 369249423Sdimbool RegDefsUses::checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, 370249423Sdim unsigned Reg, bool IsDef) const { 371249423Sdim if (IsDef) { 372249423Sdim NewDefs.set(Reg); 373249423Sdim // check whether Reg has already been defined or used. 374249423Sdim return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg)); 375249423Sdim } 376249423Sdim 377249423Sdim NewUses.set(Reg); 378249423Sdim // check whether Reg has already been defined. 379249423Sdim return isRegInSet(Defs, Reg); 380249423Sdim} 381249423Sdim 382249423Sdimbool RegDefsUses::isRegInSet(const BitVector &RegSet, unsigned Reg) const { 383249423Sdim // Check Reg and all aliased Registers. 384249423Sdim for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI) 385249423Sdim if (RegSet.test(*AI)) 386249423Sdim return true; 387249423Sdim return false; 388249423Sdim} 389249423Sdim 390249423Sdimbool InspectMemInstr::hasHazard(const MachineInstr &MI) { 391249423Sdim if (!MI.mayStore() && !MI.mayLoad()) 392249423Sdim return false; 393249423Sdim 394249423Sdim if (ForbidMemInstr) 395249423Sdim return true; 396249423Sdim 397249423Sdim OrigSeenLoad = SeenLoad; 398249423Sdim OrigSeenStore = SeenStore; 399249423Sdim SeenLoad |= MI.mayLoad(); 400249423Sdim SeenStore |= MI.mayStore(); 401249423Sdim 402249423Sdim // If MI is an ordered or volatile memory reference, disallow moving 403249423Sdim // subsequent loads and stores to delay slot. 404249423Sdim if (MI.hasOrderedMemoryRef() && (OrigSeenLoad || OrigSeenStore)) { 405249423Sdim ForbidMemInstr = true; 406249423Sdim return true; 407249423Sdim } 408249423Sdim 409249423Sdim return hasHazard_(MI); 410249423Sdim} 411249423Sdim 412249423Sdimbool LoadFromStackOrConst::hasHazard_(const MachineInstr &MI) { 413249423Sdim if (MI.mayStore()) 414249423Sdim return true; 415249423Sdim 416249423Sdim if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getValue()) 417249423Sdim return true; 418249423Sdim 419249423Sdim const Value *V = (*MI.memoperands_begin())->getValue(); 420249423Sdim 421249423Sdim if (isa<FixedStackPseudoSourceValue>(V)) 422249423Sdim return false; 423249423Sdim 424249423Sdim if (const PseudoSourceValue *PSV = dyn_cast<const PseudoSourceValue>(V)) 425249423Sdim return !PSV->PseudoSourceValue::isConstant(0) && 426249423Sdim (V != PseudoSourceValue::getStack()); 427249423Sdim 428249423Sdim return true; 429249423Sdim} 430249423Sdim 431249423SdimMemDefsUses::MemDefsUses(const MachineFrameInfo *MFI_) 432249423Sdim : InspectMemInstr(false), MFI(MFI_), SeenNoObjLoad(false), 433249423Sdim SeenNoObjStore(false) {} 434249423Sdim 435249423Sdimbool MemDefsUses::hasHazard_(const MachineInstr &MI) { 436249423Sdim bool HasHazard = false; 437249423Sdim SmallVector<const Value *, 4> Objs; 438249423Sdim 439249423Sdim // Check underlying object list. 440249423Sdim if (getUnderlyingObjects(MI, Objs)) { 441249423Sdim for (SmallVector<const Value *, 4>::const_iterator I = Objs.begin(); 442249423Sdim I != Objs.end(); ++I) 443249423Sdim HasHazard |= updateDefsUses(*I, MI.mayStore()); 444249423Sdim 445249423Sdim return HasHazard; 446249423Sdim } 447249423Sdim 448249423Sdim // No underlying objects found. 449249423Sdim HasHazard = MI.mayStore() && (OrigSeenLoad || OrigSeenStore); 450249423Sdim HasHazard |= MI.mayLoad() || OrigSeenStore; 451249423Sdim 452249423Sdim SeenNoObjLoad |= MI.mayLoad(); 453249423Sdim SeenNoObjStore |= MI.mayStore(); 454249423Sdim 455249423Sdim return HasHazard; 456249423Sdim} 457249423Sdim 458249423Sdimbool MemDefsUses::updateDefsUses(const Value *V, bool MayStore) { 459249423Sdim if (MayStore) 460249423Sdim return !Defs.insert(V) || Uses.count(V) || SeenNoObjStore || SeenNoObjLoad; 461249423Sdim 462249423Sdim Uses.insert(V); 463249423Sdim return Defs.count(V) || SeenNoObjStore; 464249423Sdim} 465249423Sdim 466249423Sdimbool MemDefsUses:: 467249423SdimgetUnderlyingObjects(const MachineInstr &MI, 468249423Sdim SmallVectorImpl<const Value *> &Objects) const { 469249423Sdim if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getValue()) 470249423Sdim return false; 471249423Sdim 472249423Sdim const Value *V = (*MI.memoperands_begin())->getValue(); 473249423Sdim 474249423Sdim SmallVector<Value *, 4> Objs; 475249423Sdim GetUnderlyingObjects(const_cast<Value *>(V), Objs); 476249423Sdim 477249423Sdim for (SmallVector<Value*, 4>::iterator I = Objs.begin(), E = Objs.end(); 478249423Sdim I != E; ++I) { 479249423Sdim if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(*I)) { 480249423Sdim if (PSV->isAliased(MFI)) 481249423Sdim return false; 482249423Sdim } else if (!isIdentifiedObject(V)) 483249423Sdim return false; 484249423Sdim 485249423Sdim Objects.push_back(*I); 486249423Sdim } 487249423Sdim 488249423Sdim return true; 489249423Sdim} 490249423Sdim 491193323Sed/// runOnMachineBasicBlock - Fill in delay slots for the given basic block. 492226633Sdim/// We assume there is only one delay slot per delayed instruction. 493249423Sdimbool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { 494193323Sed bool Changed = false; 495226633Sdim 496249423Sdim for (Iter I = MBB.begin(); I != MBB.end(); ++I) { 497249423Sdim if (!hasUnoccupiedSlot(&*I)) 498249423Sdim continue; 499218893Sdim 500249423Sdim ++FilledSlots; 501249423Sdim Changed = true; 502226633Sdim 503249423Sdim // Delay slot filling is disabled at -O0. 504249423Sdim if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) { 505249423Sdim if (searchBackward(MBB, I)) 506249423Sdim continue; 507226633Sdim 508249423Sdim if (I->isTerminator()) { 509249423Sdim if (searchSuccBBs(MBB, I)) 510249423Sdim continue; 511249423Sdim } else if (searchForward(MBB, I)) { 512249423Sdim continue; 513249423Sdim } 514249423Sdim } 515239462Sdim 516249423Sdim // Bundle the NOP to the instruction with the delay slot. 517249423Sdim BuildMI(MBB, llvm::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); 518249423Sdim MIBundleBuilder(MBB, I, llvm::next(llvm::next(I))); 519249423Sdim } 520249423Sdim 521193323Sed return Changed; 522193323Sed} 523193323Sed 524193323Sed/// createMipsDelaySlotFillerPass - Returns a pass that fills in delay 525193323Sed/// slots in Mips MachineFunctions 526193323SedFunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) { 527193323Sed return new Filler(tm); 528193323Sed} 529193323Sed 530249423Sdimtemplate<typename IterTy> 531249423Sdimbool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, 532249423Sdim RegDefsUses &RegDU, InspectMemInstr& IM, 533249423Sdim IterTy &Filler) const { 534249423Sdim for (IterTy I = Begin; I != End; ++I) { 535226633Sdim // skip debug value 536226633Sdim if (I->isDebugValue()) 537226633Sdim continue; 538226633Sdim 539249423Sdim if (terminateSearch(*I)) 540226633Sdim break; 541226633Sdim 542249423Sdim assert((!I->isCall() && !I->isReturn() && !I->isBranch()) && 543249423Sdim "Cannot put calls, returns or branches in delay slot."); 544249423Sdim 545249423Sdim if (delayHasHazard(*I, RegDU, IM)) 546226633Sdim continue; 547226633Sdim 548249423Sdim Filler = I; 549226633Sdim return true; 550226633Sdim } 551226633Sdim 552226633Sdim return false; 553226633Sdim} 554226633Sdim 555249423Sdimbool Filler::searchBackward(MachineBasicBlock &MBB, Iter Slot) const { 556249423Sdim if (DisableBackwardSearch) 557249423Sdim return false; 558226633Sdim 559249423Sdim RegDefsUses RegDU(TM); 560249423Sdim MemDefsUses MemDU(MBB.getParent()->getFrameInfo()); 561249423Sdim ReverseIter Filler; 562226633Sdim 563249423Sdim RegDU.init(*Slot); 564249423Sdim 565249423Sdim if (searchRange(MBB, ReverseIter(Slot), MBB.rend(), RegDU, MemDU, Filler)) { 566249423Sdim MBB.splice(llvm::next(Slot), &MBB, llvm::next(Filler).base()); 567249423Sdim MIBundleBuilder(MBB, Slot, llvm::next(llvm::next(Slot))); 568249423Sdim ++UsefulSlots; 569249423Sdim return true; 570226633Sdim } 571226633Sdim 572249423Sdim return false; 573249423Sdim} 574226633Sdim 575249423Sdimbool Filler::searchForward(MachineBasicBlock &MBB, Iter Slot) const { 576249423Sdim // Can handle only calls. 577249423Sdim if (DisableForwardSearch || !Slot->isCall()) 578249423Sdim return false; 579226633Sdim 580249423Sdim RegDefsUses RegDU(TM); 581249423Sdim NoMemInstr NM; 582249423Sdim Iter Filler; 583226633Sdim 584249423Sdim RegDU.setCallerSaved(*Slot); 585249423Sdim 586249423Sdim if (searchRange(MBB, llvm::next(Slot), MBB.end(), RegDU, NM, Filler)) { 587249423Sdim MBB.splice(llvm::next(Slot), &MBB, Filler); 588249423Sdim MIBundleBuilder(MBB, Slot, llvm::next(llvm::next(Slot))); 589249423Sdim ++UsefulSlots; 590249423Sdim return true; 591226633Sdim } 592249423Sdim 593226633Sdim return false; 594226633Sdim} 595226633Sdim 596249423Sdimbool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const { 597249423Sdim if (DisableSuccBBSearch) 598249423Sdim return false; 599234353Sdim 600249423Sdim MachineBasicBlock *SuccBB = selectSuccBB(MBB); 601226633Sdim 602249423Sdim if (!SuccBB) 603249423Sdim return false; 604226633Sdim 605249423Sdim RegDefsUses RegDU(TM); 606249423Sdim bool HasMultipleSuccs = false; 607249423Sdim BB2BrMap BrMap; 608249423Sdim OwningPtr<InspectMemInstr> IM; 609249423Sdim Iter Filler; 610226633Sdim 611249423Sdim // Iterate over SuccBB's predecessor list. 612249423Sdim for (MachineBasicBlock::pred_iterator PI = SuccBB->pred_begin(), 613249423Sdim PE = SuccBB->pred_end(); PI != PE; ++PI) 614249423Sdim if (!examinePred(**PI, *SuccBB, RegDU, HasMultipleSuccs, BrMap)) 615249423Sdim return false; 616249423Sdim 617249423Sdim // Do not allow moving instructions which have unallocatable register operands 618249423Sdim // across basic block boundaries. 619249423Sdim RegDU.setUnallocatableRegs(*MBB.getParent()); 620249423Sdim 621249423Sdim // Only allow moving loads from stack or constants if any of the SuccBB's 622249423Sdim // predecessors have multiple successors. 623249423Sdim if (HasMultipleSuccs) { 624249423Sdim IM.reset(new LoadFromStackOrConst()); 625249423Sdim } else { 626249423Sdim const MachineFrameInfo *MFI = MBB.getParent()->getFrameInfo(); 627249423Sdim IM.reset(new MemDefsUses(MFI)); 628226633Sdim } 629249423Sdim 630249423Sdim if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Filler)) 631249423Sdim return false; 632249423Sdim 633249423Sdim insertDelayFiller(Filler, BrMap); 634249423Sdim addLiveInRegs(Filler, *SuccBB); 635249423Sdim Filler->eraseFromParent(); 636249423Sdim 637249423Sdim return true; 638226633Sdim} 639226633Sdim 640249423SdimMachineBasicBlock *Filler::selectSuccBB(MachineBasicBlock &B) const { 641249423Sdim if (B.succ_empty()) 642249423Sdim return NULL; 643249423Sdim 644249423Sdim // Select the successor with the larget edge weight. 645249423Sdim CmpWeight Cmp(B, getAnalysis<MachineBranchProbabilityInfo>()); 646249423Sdim MachineBasicBlock *S = *std::max_element(B.succ_begin(), B.succ_end(), Cmp); 647249423Sdim return S->isLandingPad() ? NULL : S; 648226633Sdim} 649249423Sdim 650249423Sdimstd::pair<MipsInstrInfo::BranchType, MachineInstr *> 651249423SdimFiller::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const { 652249423Sdim const MipsInstrInfo *TII = 653249423Sdim static_cast<const MipsInstrInfo*>(TM.getInstrInfo()); 654249423Sdim MachineBasicBlock *TrueBB = 0, *FalseBB = 0; 655249423Sdim SmallVector<MachineInstr*, 2> BranchInstrs; 656249423Sdim SmallVector<MachineOperand, 2> Cond; 657249423Sdim 658249423Sdim MipsInstrInfo::BranchType R = 659249423Sdim TII->AnalyzeBranch(MBB, TrueBB, FalseBB, Cond, false, BranchInstrs); 660249423Sdim 661249423Sdim if ((R == MipsInstrInfo::BT_None) || (R == MipsInstrInfo::BT_NoBranch)) 662249423Sdim return std::make_pair(R, (MachineInstr*)NULL); 663249423Sdim 664249423Sdim if (R != MipsInstrInfo::BT_CondUncond) { 665249423Sdim if (!hasUnoccupiedSlot(BranchInstrs[0])) 666249423Sdim return std::make_pair(MipsInstrInfo::BT_None, (MachineInstr*)NULL); 667249423Sdim 668249423Sdim assert(((R != MipsInstrInfo::BT_Uncond) || (TrueBB == &Dst))); 669249423Sdim 670249423Sdim return std::make_pair(R, BranchInstrs[0]); 671249423Sdim } 672249423Sdim 673249423Sdim assert((TrueBB == &Dst) || (FalseBB == &Dst)); 674249423Sdim 675249423Sdim // Examine the conditional branch. See if its slot is occupied. 676249423Sdim if (hasUnoccupiedSlot(BranchInstrs[0])) 677249423Sdim return std::make_pair(MipsInstrInfo::BT_Cond, BranchInstrs[0]); 678249423Sdim 679249423Sdim // If that fails, try the unconditional branch. 680249423Sdim if (hasUnoccupiedSlot(BranchInstrs[1]) && (FalseBB == &Dst)) 681249423Sdim return std::make_pair(MipsInstrInfo::BT_Uncond, BranchInstrs[1]); 682249423Sdim 683249423Sdim return std::make_pair(MipsInstrInfo::BT_None, (MachineInstr*)NULL); 684249423Sdim} 685249423Sdim 686249423Sdimbool Filler::examinePred(MachineBasicBlock &Pred, const MachineBasicBlock &Succ, 687249423Sdim RegDefsUses &RegDU, bool &HasMultipleSuccs, 688249423Sdim BB2BrMap &BrMap) const { 689249423Sdim std::pair<MipsInstrInfo::BranchType, MachineInstr *> P = 690249423Sdim getBranch(Pred, Succ); 691249423Sdim 692249423Sdim // Return if either getBranch wasn't able to analyze the branches or there 693249423Sdim // were no branches with unoccupied slots. 694249423Sdim if (P.first == MipsInstrInfo::BT_None) 695249423Sdim return false; 696249423Sdim 697249423Sdim if ((P.first != MipsInstrInfo::BT_Uncond) && 698249423Sdim (P.first != MipsInstrInfo::BT_NoBranch)) { 699249423Sdim HasMultipleSuccs = true; 700249423Sdim RegDU.addLiveOut(Pred, Succ); 701249423Sdim } 702249423Sdim 703249423Sdim BrMap[&Pred] = P.second; 704249423Sdim return true; 705249423Sdim} 706249423Sdim 707249423Sdimbool Filler::delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, 708249423Sdim InspectMemInstr &IM) const { 709249423Sdim bool HasHazard = (Candidate.isImplicitDef() || Candidate.isKill()); 710249423Sdim 711249423Sdim HasHazard |= IM.hasHazard(Candidate); 712249423Sdim HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands()); 713249423Sdim 714249423Sdim return HasHazard; 715249423Sdim} 716249423Sdim 717249423Sdimbool Filler::terminateSearch(const MachineInstr &Candidate) const { 718249423Sdim return (Candidate.isTerminator() || Candidate.isCall() || 719249423Sdim Candidate.isLabel() || Candidate.isInlineAsm() || 720249423Sdim Candidate.hasUnmodeledSideEffects()); 721249423Sdim} 722