MipsDelaySlotFiller.cpp revision 261991
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) 180261991Sdim : MachineFunctionPass(ID), TM(tm) { } 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 247249423Sdim static char ID; 248193323Sed }; 249193323Sed char Filler::ID = 0; 250193323Sed} // end of anonymous namespace 251193323Sed 252249423Sdimstatic bool hasUnoccupiedSlot(const MachineInstr *MI) { 253249423Sdim return MI->hasDelaySlot() && !MI->isBundledWithSucc(); 254249423Sdim} 255249423Sdim 256249423Sdim/// This function inserts clones of Filler into predecessor blocks. 257249423Sdimstatic void insertDelayFiller(Iter Filler, const BB2BrMap &BrMap) { 258249423Sdim MachineFunction *MF = Filler->getParent()->getParent(); 259249423Sdim 260249423Sdim for (BB2BrMap::const_iterator I = BrMap.begin(); I != BrMap.end(); ++I) { 261249423Sdim if (I->second) { 262249423Sdim MIBundleBuilder(I->second).append(MF->CloneMachineInstr(&*Filler)); 263249423Sdim ++UsefulSlots; 264249423Sdim } else { 265249423Sdim I->first->insert(I->first->end(), MF->CloneMachineInstr(&*Filler)); 266249423Sdim } 267249423Sdim } 268249423Sdim} 269249423Sdim 270249423Sdim/// This function adds registers Filler defines to MBB's live-in register list. 271249423Sdimstatic void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { 272249423Sdim for (unsigned I = 0, E = Filler->getNumOperands(); I != E; ++I) { 273249423Sdim const MachineOperand &MO = Filler->getOperand(I); 274249423Sdim unsigned R; 275249423Sdim 276249423Sdim if (!MO.isReg() || !MO.isDef() || !(R = MO.getReg())) 277249423Sdim continue; 278249423Sdim 279249423Sdim#ifndef NDEBUG 280249423Sdim const MachineFunction &MF = *MBB.getParent(); 281249423Sdim assert(MF.getTarget().getRegisterInfo()->getAllocatableSet(MF).test(R) && 282249423Sdim "Shouldn't move an instruction with unallocatable registers across " 283249423Sdim "basic block boundaries."); 284249423Sdim#endif 285249423Sdim 286249423Sdim if (!MBB.isLiveIn(R)) 287249423Sdim MBB.addLiveIn(R); 288249423Sdim } 289249423Sdim} 290249423Sdim 291249423SdimRegDefsUses::RegDefsUses(TargetMachine &TM) 292249423Sdim : TRI(*TM.getRegisterInfo()), Defs(TRI.getNumRegs(), false), 293249423Sdim Uses(TRI.getNumRegs(), false) {} 294249423Sdim 295249423Sdimvoid RegDefsUses::init(const MachineInstr &MI) { 296249423Sdim // Add all register operands which are explicit and non-variadic. 297249423Sdim update(MI, 0, MI.getDesc().getNumOperands()); 298249423Sdim 299249423Sdim // If MI is a call, add RA to Defs to prevent users of RA from going into 300249423Sdim // delay slot. 301249423Sdim if (MI.isCall()) 302249423Sdim Defs.set(Mips::RA); 303249423Sdim 304249423Sdim // Add all implicit register operands of branch instructions except 305249423Sdim // register AT. 306249423Sdim if (MI.isBranch()) { 307249423Sdim update(MI, MI.getDesc().getNumOperands(), MI.getNumOperands()); 308249423Sdim Defs.reset(Mips::AT); 309249423Sdim } 310249423Sdim} 311249423Sdim 312249423Sdimvoid RegDefsUses::setCallerSaved(const MachineInstr &MI) { 313249423Sdim assert(MI.isCall()); 314249423Sdim 315249423Sdim // If MI is a call, add all caller-saved registers to Defs. 316249423Sdim BitVector CallerSavedRegs(TRI.getNumRegs(), true); 317249423Sdim 318249423Sdim CallerSavedRegs.reset(Mips::ZERO); 319249423Sdim CallerSavedRegs.reset(Mips::ZERO_64); 320249423Sdim 321249423Sdim for (const MCPhysReg *R = TRI.getCalleeSavedRegs(); *R; ++R) 322249423Sdim for (MCRegAliasIterator AI(*R, &TRI, true); AI.isValid(); ++AI) 323249423Sdim CallerSavedRegs.reset(*AI); 324249423Sdim 325249423Sdim Defs |= CallerSavedRegs; 326249423Sdim} 327249423Sdim 328249423Sdimvoid RegDefsUses::setUnallocatableRegs(const MachineFunction &MF) { 329249423Sdim BitVector AllocSet = TRI.getAllocatableSet(MF); 330249423Sdim 331249423Sdim for (int R = AllocSet.find_first(); R != -1; R = AllocSet.find_next(R)) 332249423Sdim for (MCRegAliasIterator AI(R, &TRI, false); AI.isValid(); ++AI) 333249423Sdim AllocSet.set(*AI); 334249423Sdim 335249423Sdim AllocSet.set(Mips::ZERO); 336249423Sdim AllocSet.set(Mips::ZERO_64); 337249423Sdim 338249423Sdim Defs |= AllocSet.flip(); 339249423Sdim} 340249423Sdim 341249423Sdimvoid RegDefsUses::addLiveOut(const MachineBasicBlock &MBB, 342249423Sdim const MachineBasicBlock &SuccBB) { 343249423Sdim for (MachineBasicBlock::const_succ_iterator SI = MBB.succ_begin(), 344249423Sdim SE = MBB.succ_end(); SI != SE; ++SI) 345249423Sdim if (*SI != &SuccBB) 346249423Sdim for (MachineBasicBlock::livein_iterator LI = (*SI)->livein_begin(), 347249423Sdim LE = (*SI)->livein_end(); LI != LE; ++LI) 348249423Sdim Uses.set(*LI); 349249423Sdim} 350249423Sdim 351249423Sdimbool RegDefsUses::update(const MachineInstr &MI, unsigned Begin, unsigned End) { 352249423Sdim BitVector NewDefs(TRI.getNumRegs()), NewUses(TRI.getNumRegs()); 353249423Sdim bool HasHazard = false; 354249423Sdim 355249423Sdim for (unsigned I = Begin; I != End; ++I) { 356249423Sdim const MachineOperand &MO = MI.getOperand(I); 357249423Sdim 358249423Sdim if (MO.isReg() && MO.getReg()) 359249423Sdim HasHazard |= checkRegDefsUses(NewDefs, NewUses, MO.getReg(), MO.isDef()); 360249423Sdim } 361249423Sdim 362249423Sdim Defs |= NewDefs; 363249423Sdim Uses |= NewUses; 364249423Sdim 365249423Sdim return HasHazard; 366249423Sdim} 367249423Sdim 368249423Sdimbool RegDefsUses::checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, 369249423Sdim unsigned Reg, bool IsDef) const { 370249423Sdim if (IsDef) { 371249423Sdim NewDefs.set(Reg); 372249423Sdim // check whether Reg has already been defined or used. 373249423Sdim return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg)); 374249423Sdim } 375249423Sdim 376249423Sdim NewUses.set(Reg); 377249423Sdim // check whether Reg has already been defined. 378249423Sdim return isRegInSet(Defs, Reg); 379249423Sdim} 380249423Sdim 381249423Sdimbool RegDefsUses::isRegInSet(const BitVector &RegSet, unsigned Reg) const { 382249423Sdim // Check Reg and all aliased Registers. 383249423Sdim for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI) 384249423Sdim if (RegSet.test(*AI)) 385249423Sdim return true; 386249423Sdim return false; 387249423Sdim} 388249423Sdim 389249423Sdimbool InspectMemInstr::hasHazard(const MachineInstr &MI) { 390249423Sdim if (!MI.mayStore() && !MI.mayLoad()) 391249423Sdim return false; 392249423Sdim 393249423Sdim if (ForbidMemInstr) 394249423Sdim return true; 395249423Sdim 396249423Sdim OrigSeenLoad = SeenLoad; 397249423Sdim OrigSeenStore = SeenStore; 398249423Sdim SeenLoad |= MI.mayLoad(); 399249423Sdim SeenStore |= MI.mayStore(); 400249423Sdim 401249423Sdim // If MI is an ordered or volatile memory reference, disallow moving 402249423Sdim // subsequent loads and stores to delay slot. 403249423Sdim if (MI.hasOrderedMemoryRef() && (OrigSeenLoad || OrigSeenStore)) { 404249423Sdim ForbidMemInstr = true; 405249423Sdim return true; 406249423Sdim } 407249423Sdim 408249423Sdim return hasHazard_(MI); 409249423Sdim} 410249423Sdim 411249423Sdimbool LoadFromStackOrConst::hasHazard_(const MachineInstr &MI) { 412249423Sdim if (MI.mayStore()) 413249423Sdim return true; 414249423Sdim 415249423Sdim if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getValue()) 416249423Sdim return true; 417249423Sdim 418249423Sdim const Value *V = (*MI.memoperands_begin())->getValue(); 419249423Sdim 420249423Sdim if (isa<FixedStackPseudoSourceValue>(V)) 421249423Sdim return false; 422249423Sdim 423249423Sdim if (const PseudoSourceValue *PSV = dyn_cast<const PseudoSourceValue>(V)) 424261991Sdim return !PSV->isConstant(0) && V != PseudoSourceValue::getStack(); 425249423Sdim 426249423Sdim return true; 427249423Sdim} 428249423Sdim 429249423SdimMemDefsUses::MemDefsUses(const MachineFrameInfo *MFI_) 430249423Sdim : InspectMemInstr(false), MFI(MFI_), SeenNoObjLoad(false), 431249423Sdim SeenNoObjStore(false) {} 432249423Sdim 433249423Sdimbool MemDefsUses::hasHazard_(const MachineInstr &MI) { 434249423Sdim bool HasHazard = false; 435249423Sdim SmallVector<const Value *, 4> Objs; 436249423Sdim 437249423Sdim // Check underlying object list. 438249423Sdim if (getUnderlyingObjects(MI, Objs)) { 439261991Sdim for (SmallVectorImpl<const Value *>::const_iterator I = Objs.begin(); 440249423Sdim I != Objs.end(); ++I) 441249423Sdim HasHazard |= updateDefsUses(*I, MI.mayStore()); 442249423Sdim 443249423Sdim return HasHazard; 444249423Sdim } 445249423Sdim 446249423Sdim // No underlying objects found. 447249423Sdim HasHazard = MI.mayStore() && (OrigSeenLoad || OrigSeenStore); 448249423Sdim HasHazard |= MI.mayLoad() || OrigSeenStore; 449249423Sdim 450249423Sdim SeenNoObjLoad |= MI.mayLoad(); 451249423Sdim SeenNoObjStore |= MI.mayStore(); 452249423Sdim 453249423Sdim return HasHazard; 454249423Sdim} 455249423Sdim 456249423Sdimbool MemDefsUses::updateDefsUses(const Value *V, bool MayStore) { 457249423Sdim if (MayStore) 458249423Sdim return !Defs.insert(V) || Uses.count(V) || SeenNoObjStore || SeenNoObjLoad; 459249423Sdim 460249423Sdim Uses.insert(V); 461249423Sdim return Defs.count(V) || SeenNoObjStore; 462249423Sdim} 463249423Sdim 464249423Sdimbool MemDefsUses:: 465249423SdimgetUnderlyingObjects(const MachineInstr &MI, 466249423Sdim SmallVectorImpl<const Value *> &Objects) const { 467249423Sdim if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getValue()) 468249423Sdim return false; 469249423Sdim 470249423Sdim const Value *V = (*MI.memoperands_begin())->getValue(); 471249423Sdim 472249423Sdim SmallVector<Value *, 4> Objs; 473249423Sdim GetUnderlyingObjects(const_cast<Value *>(V), Objs); 474249423Sdim 475261991Sdim for (SmallVectorImpl<Value *>::iterator I = Objs.begin(), E = Objs.end(); 476249423Sdim I != E; ++I) { 477249423Sdim if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(*I)) { 478249423Sdim if (PSV->isAliased(MFI)) 479249423Sdim return false; 480249423Sdim } else if (!isIdentifiedObject(V)) 481249423Sdim return false; 482249423Sdim 483249423Sdim Objects.push_back(*I); 484249423Sdim } 485249423Sdim 486249423Sdim return true; 487249423Sdim} 488249423Sdim 489193323Sed/// runOnMachineBasicBlock - Fill in delay slots for the given basic block. 490226633Sdim/// We assume there is only one delay slot per delayed instruction. 491249423Sdimbool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { 492193323Sed bool Changed = false; 493226633Sdim 494249423Sdim for (Iter I = MBB.begin(); I != MBB.end(); ++I) { 495249423Sdim if (!hasUnoccupiedSlot(&*I)) 496249423Sdim continue; 497218893Sdim 498249423Sdim ++FilledSlots; 499249423Sdim Changed = true; 500226633Sdim 501249423Sdim // Delay slot filling is disabled at -O0. 502249423Sdim if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) { 503249423Sdim if (searchBackward(MBB, I)) 504249423Sdim continue; 505226633Sdim 506249423Sdim if (I->isTerminator()) { 507249423Sdim if (searchSuccBBs(MBB, I)) 508249423Sdim continue; 509249423Sdim } else if (searchForward(MBB, I)) { 510249423Sdim continue; 511249423Sdim } 512249423Sdim } 513239462Sdim 514249423Sdim // Bundle the NOP to the instruction with the delay slot. 515261991Sdim const MipsInstrInfo *TII = 516261991Sdim static_cast<const MipsInstrInfo*>(TM.getInstrInfo()); 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 565261991Sdim if (!searchRange(MBB, ReverseIter(Slot), MBB.rend(), RegDU, MemDU, Filler)) 566261991Sdim return false; 567226633Sdim 568261991Sdim MBB.splice(llvm::next(Slot), &MBB, llvm::next(Filler).base()); 569261991Sdim MIBundleBuilder(MBB, Slot, llvm::next(llvm::next(Slot))); 570261991Sdim ++UsefulSlots; 571261991Sdim return true; 572249423Sdim} 573226633Sdim 574249423Sdimbool Filler::searchForward(MachineBasicBlock &MBB, Iter Slot) const { 575249423Sdim // Can handle only calls. 576249423Sdim if (DisableForwardSearch || !Slot->isCall()) 577249423Sdim return false; 578226633Sdim 579249423Sdim RegDefsUses RegDU(TM); 580249423Sdim NoMemInstr NM; 581249423Sdim Iter Filler; 582226633Sdim 583249423Sdim RegDU.setCallerSaved(*Slot); 584249423Sdim 585261991Sdim if (!searchRange(MBB, llvm::next(Slot), MBB.end(), RegDU, NM, Filler)) 586261991Sdim return false; 587249423Sdim 588261991Sdim MBB.splice(llvm::next(Slot), &MBB, Filler); 589261991Sdim MIBundleBuilder(MBB, Slot, llvm::next(llvm::next(Slot))); 590261991Sdim ++UsefulSlots; 591261991Sdim return true; 592226633Sdim} 593226633Sdim 594249423Sdimbool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const { 595249423Sdim if (DisableSuccBBSearch) 596249423Sdim return false; 597234353Sdim 598249423Sdim MachineBasicBlock *SuccBB = selectSuccBB(MBB); 599226633Sdim 600249423Sdim if (!SuccBB) 601249423Sdim return false; 602226633Sdim 603249423Sdim RegDefsUses RegDU(TM); 604249423Sdim bool HasMultipleSuccs = false; 605249423Sdim BB2BrMap BrMap; 606249423Sdim OwningPtr<InspectMemInstr> IM; 607249423Sdim Iter Filler; 608226633Sdim 609249423Sdim // Iterate over SuccBB's predecessor list. 610249423Sdim for (MachineBasicBlock::pred_iterator PI = SuccBB->pred_begin(), 611249423Sdim PE = SuccBB->pred_end(); PI != PE; ++PI) 612249423Sdim if (!examinePred(**PI, *SuccBB, RegDU, HasMultipleSuccs, BrMap)) 613249423Sdim return false; 614249423Sdim 615249423Sdim // Do not allow moving instructions which have unallocatable register operands 616249423Sdim // across basic block boundaries. 617249423Sdim RegDU.setUnallocatableRegs(*MBB.getParent()); 618249423Sdim 619249423Sdim // Only allow moving loads from stack or constants if any of the SuccBB's 620249423Sdim // predecessors have multiple successors. 621249423Sdim if (HasMultipleSuccs) { 622249423Sdim IM.reset(new LoadFromStackOrConst()); 623249423Sdim } else { 624249423Sdim const MachineFrameInfo *MFI = MBB.getParent()->getFrameInfo(); 625249423Sdim IM.reset(new MemDefsUses(MFI)); 626226633Sdim } 627249423Sdim 628249423Sdim if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Filler)) 629249423Sdim return false; 630249423Sdim 631249423Sdim insertDelayFiller(Filler, BrMap); 632249423Sdim addLiveInRegs(Filler, *SuccBB); 633249423Sdim Filler->eraseFromParent(); 634249423Sdim 635249423Sdim return true; 636226633Sdim} 637226633Sdim 638249423SdimMachineBasicBlock *Filler::selectSuccBB(MachineBasicBlock &B) const { 639249423Sdim if (B.succ_empty()) 640249423Sdim return NULL; 641249423Sdim 642249423Sdim // Select the successor with the larget edge weight. 643249423Sdim CmpWeight Cmp(B, getAnalysis<MachineBranchProbabilityInfo>()); 644249423Sdim MachineBasicBlock *S = *std::max_element(B.succ_begin(), B.succ_end(), Cmp); 645249423Sdim return S->isLandingPad() ? NULL : S; 646226633Sdim} 647249423Sdim 648249423Sdimstd::pair<MipsInstrInfo::BranchType, MachineInstr *> 649249423SdimFiller::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const { 650249423Sdim const MipsInstrInfo *TII = 651249423Sdim static_cast<const MipsInstrInfo*>(TM.getInstrInfo()); 652249423Sdim MachineBasicBlock *TrueBB = 0, *FalseBB = 0; 653249423Sdim SmallVector<MachineInstr*, 2> BranchInstrs; 654249423Sdim SmallVector<MachineOperand, 2> Cond; 655249423Sdim 656249423Sdim MipsInstrInfo::BranchType R = 657249423Sdim TII->AnalyzeBranch(MBB, TrueBB, FalseBB, Cond, false, BranchInstrs); 658249423Sdim 659249423Sdim if ((R == MipsInstrInfo::BT_None) || (R == MipsInstrInfo::BT_NoBranch)) 660249423Sdim return std::make_pair(R, (MachineInstr*)NULL); 661249423Sdim 662249423Sdim if (R != MipsInstrInfo::BT_CondUncond) { 663249423Sdim if (!hasUnoccupiedSlot(BranchInstrs[0])) 664249423Sdim return std::make_pair(MipsInstrInfo::BT_None, (MachineInstr*)NULL); 665249423Sdim 666249423Sdim assert(((R != MipsInstrInfo::BT_Uncond) || (TrueBB == &Dst))); 667249423Sdim 668249423Sdim return std::make_pair(R, BranchInstrs[0]); 669249423Sdim } 670249423Sdim 671249423Sdim assert((TrueBB == &Dst) || (FalseBB == &Dst)); 672249423Sdim 673249423Sdim // Examine the conditional branch. See if its slot is occupied. 674249423Sdim if (hasUnoccupiedSlot(BranchInstrs[0])) 675249423Sdim return std::make_pair(MipsInstrInfo::BT_Cond, BranchInstrs[0]); 676249423Sdim 677249423Sdim // If that fails, try the unconditional branch. 678249423Sdim if (hasUnoccupiedSlot(BranchInstrs[1]) && (FalseBB == &Dst)) 679249423Sdim return std::make_pair(MipsInstrInfo::BT_Uncond, BranchInstrs[1]); 680249423Sdim 681249423Sdim return std::make_pair(MipsInstrInfo::BT_None, (MachineInstr*)NULL); 682249423Sdim} 683249423Sdim 684249423Sdimbool Filler::examinePred(MachineBasicBlock &Pred, const MachineBasicBlock &Succ, 685249423Sdim RegDefsUses &RegDU, bool &HasMultipleSuccs, 686249423Sdim BB2BrMap &BrMap) const { 687249423Sdim std::pair<MipsInstrInfo::BranchType, MachineInstr *> P = 688249423Sdim getBranch(Pred, Succ); 689249423Sdim 690249423Sdim // Return if either getBranch wasn't able to analyze the branches or there 691249423Sdim // were no branches with unoccupied slots. 692249423Sdim if (P.first == MipsInstrInfo::BT_None) 693249423Sdim return false; 694249423Sdim 695249423Sdim if ((P.first != MipsInstrInfo::BT_Uncond) && 696249423Sdim (P.first != MipsInstrInfo::BT_NoBranch)) { 697249423Sdim HasMultipleSuccs = true; 698249423Sdim RegDU.addLiveOut(Pred, Succ); 699249423Sdim } 700249423Sdim 701249423Sdim BrMap[&Pred] = P.second; 702249423Sdim return true; 703249423Sdim} 704249423Sdim 705249423Sdimbool Filler::delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, 706249423Sdim InspectMemInstr &IM) const { 707249423Sdim bool HasHazard = (Candidate.isImplicitDef() || Candidate.isKill()); 708249423Sdim 709249423Sdim HasHazard |= IM.hasHazard(Candidate); 710249423Sdim HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands()); 711249423Sdim 712249423Sdim return HasHazard; 713249423Sdim} 714249423Sdim 715249423Sdimbool Filler::terminateSearch(const MachineInstr &Candidate) const { 716249423Sdim return (Candidate.isTerminator() || Candidate.isCall() || 717249423Sdim Candidate.isLabel() || Candidate.isInlineAsm() || 718249423Sdim Candidate.hasUnmodeledSideEffects()); 719249423Sdim} 720