1 //===-- MipsDelaySlotFiller.cpp - Mips Delay Slot Filler ------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Simple pass to fill delay slots with useful instructions. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #define DEBUG_TYPE "delay-slot-filler" 15 16 #include "Mips.h" 17 #include "MipsTargetMachine.h" 18 #include "llvm/ADT/BitVector.h" 19 #include "llvm/ADT/SmallPtrSet.h" 20 #include "llvm/ADT/Statistic.h" 21 #include "llvm/Analysis/AliasAnalysis.h" 22 #include "llvm/Analysis/ValueTracking.h" 23 #include "llvm/CodeGen/MachineFunctionPass.h" 24 #include "llvm/CodeGen/MachineInstrBuilder.h" 25 #include "llvm/CodeGen/PseudoSourceValue.h" 26 #include "llvm/Support/CommandLine.h" 27 #include "llvm/Target/TargetInstrInfo.h" 28 #include "llvm/Target/TargetMachine.h" 29 #include "llvm/Target/TargetRegisterInfo.h" 30 31 using namespace llvm; 32 33 STATISTIC(FilledSlots, "Number of delay slots filled"); 34 STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that" 35 " are not NOP."); 36 37 static cl::opt<bool> DisableDelaySlotFiller( 38 "disable-mips-delay-filler", 39 cl::init(false), 40 cl::desc("Fill all delay slots with NOPs."), 41 cl::Hidden); 42 43 // This option can be used to silence complaints by machine verifier passes. 44 static cl::opt<bool> SkipDelaySlotFiller( 45 "skip-mips-delay-filler", 46 cl::init(false), 47 cl::desc("Skip MIPS' delay slot filling pass."), 48 cl::Hidden); 49 50 static cl::opt<bool> DisableForwardSearch( 51 "disable-mips-df-forward-search", 52 cl::init(true), 53 cl::desc("Disallow MIPS delay filler to search forward."), 54 cl::Hidden); 55 56 static cl::opt<bool> DisableSuccBBSearch( 57 "disable-mips-df-succbb-search", 58 cl::init(true), 59 cl::desc("Disallow MIPS delay filler to search successor basic blocks."), 60 cl::Hidden); 61 62 static cl::opt<bool> DisableBackwardSearch( 63 "disable-mips-df-backward-search", 64 cl::init(false), 65 cl::desc("Disallow MIPS delay filler to search backward."), 66 cl::Hidden); 67 68 namespace { 69 class RegDefsUses { 70 public: 71 RegDefsUses(TargetMachine &TM); 72 void init(const MachineInstr &MI); 73 74 /// This function sets all caller-saved registers in Defs. 75 void setCallerSaved(const MachineInstr &MI); 76 77 bool update(const MachineInstr &MI, unsigned Begin, unsigned End); 78 79 private: 80 bool checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, unsigned Reg, 81 bool IsDef) const; 82 83 /// Returns true if Reg or its alias is in RegSet. 84 bool isRegInSet(const BitVector &RegSet, unsigned Reg) const; 85 86 const TargetRegisterInfo &TRI; 87 BitVector Defs, Uses; 88 }; 89 90 /// Base class for inspecting loads and stores. 91 class InspectMemInstr { 92 public: 93 virtual bool hasHazard(const MachineInstr &MI) = 0; 94 virtual ~InspectMemInstr() {} 95 }; 96 97 /// This subclass rejects any memory instructions. 98 class NoMemInstr : public InspectMemInstr { 99 public: 100 virtual bool hasHazard(const MachineInstr &MI); 101 }; 102 103 /// This subclass uses memory dependence information to determine whether a 104 /// memory instruction can be moved to a delay slot. 105 class MemDefsUses : public InspectMemInstr { 106 public: 107 MemDefsUses(const MachineFrameInfo *MFI); 108 109 /// Return true if MI cannot be moved to delay slot. 110 virtual bool hasHazard(const MachineInstr &MI); 111 112 private: 113 /// Update Defs and Uses. Return true if there exist dependences that 114 /// disqualify the delay slot candidate between V and values in Uses and Defs. 115 bool updateDefsUses(const Value *V, bool MayStore); 116 117 /// Get the list of underlying objects of MI's memory operand. 118 bool getUnderlyingObjects(const MachineInstr &MI, 119 SmallVectorImpl<const Value *> &Objects) const; 120 121 const MachineFrameInfo *MFI; 122 SmallPtrSet<const Value*, 4> Uses, Defs; 123 124 /// Flags indicating whether loads or stores have been seen. 125 bool SeenLoad, SeenStore; 126 127 /// Flags indicating whether loads or stores with no underlying objects have 128 /// been seen. 129 bool SeenNoObjLoad, SeenNoObjStore; 130 131 /// Memory instructions are not allowed to move to delay slot if this flag 132 /// is true. 133 bool ForbidMemInstr; 134 }; 135 136 class Filler : public MachineFunctionPass { 137 public: 138 Filler(TargetMachine &tm) 139 : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } 140 141 virtual const char *getPassName() const { 142 return "Mips Delay Slot Filler"; 143 } 144 145 bool runOnMachineFunction(MachineFunction &F) { 146 if (SkipDelaySlotFiller) 147 return false; 148 149 bool Changed = false; 150 for (MachineFunction::iterator FI = F.begin(), FE = F.end(); 151 FI != FE; ++FI) 152 Changed |= runOnMachineBasicBlock(*FI); 153 return Changed; 154 } 155 156 private: 157 typedef MachineBasicBlock::iterator Iter; 158 typedef MachineBasicBlock::reverse_iterator ReverseIter; 159 160 bool runOnMachineBasicBlock(MachineBasicBlock &MBB); 161 162 /// This function checks if it is valid to move Candidate to the delay slot 163 /// and returns true if it isn't. It also updates memory and register 164 /// dependence information. 165 bool delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, 166 InspectMemInstr &IM) const; 167 168 /// This function searches range [Begin, End) for an instruction that can be 169 /// moved to the delay slot. Returns true on success. 170 template<typename IterTy> 171 bool searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, 172 RegDefsUses &RegDU, InspectMemInstr &IM, IterTy &Filler) const; 173 174 /// This function searches in the backward direction for an instruction that 175 /// can be moved to the delay slot. Returns true on success. 176 bool searchBackward(MachineBasicBlock &MBB, Iter Slot) const; 177 178 /// This function searches MBB in the forward direction for an instruction 179 /// that can be moved to the delay slot. Returns true on success. 180 bool searchForward(MachineBasicBlock &MBB, Iter Slot) const; 181 182 bool terminateSearch(const MachineInstr &Candidate) const; 183 184 TargetMachine &TM; 185 const TargetInstrInfo *TII; 186 187 static char ID; 188 }; 189 char Filler::ID = 0; 190 } // end of anonymous namespace 191 192 RegDefsUses::RegDefsUses(TargetMachine &TM) 193 : TRI(*TM.getRegisterInfo()), Defs(TRI.getNumRegs(), false), 194 Uses(TRI.getNumRegs(), false) {} 195 196 void RegDefsUses::init(const MachineInstr &MI) { 197 // Add all register operands which are explicit and non-variadic. 198 update(MI, 0, MI.getDesc().getNumOperands()); 199 200 // If MI is a call, add RA to Defs to prevent users of RA from going into 201 // delay slot. 202 if (MI.isCall()) 203 Defs.set(Mips::RA); 204 205 // Add all implicit register operands of branch instructions except 206 // register AT. 207 if (MI.isBranch()) { 208 update(MI, MI.getDesc().getNumOperands(), MI.getNumOperands()); 209 Defs.reset(Mips::AT); 210 } 211 } 212 213 void RegDefsUses::setCallerSaved(const MachineInstr &MI) { 214 assert(MI.isCall()); 215 216 // If MI is a call, add all caller-saved registers to Defs. 217 BitVector CallerSavedRegs(TRI.getNumRegs(), true); 218 219 CallerSavedRegs.reset(Mips::ZERO); 220 CallerSavedRegs.reset(Mips::ZERO_64); 221 222 for (const MCPhysReg *R = TRI.getCalleeSavedRegs(); *R; ++R) 223 for (MCRegAliasIterator AI(*R, &TRI, true); AI.isValid(); ++AI) 224 CallerSavedRegs.reset(*AI); 225 226 Defs |= CallerSavedRegs; 227 } 228 229 bool RegDefsUses::update(const MachineInstr &MI, unsigned Begin, unsigned End) { 230 BitVector NewDefs(TRI.getNumRegs()), NewUses(TRI.getNumRegs()); 231 bool HasHazard = false; 232 233 for (unsigned I = Begin; I != End; ++I) { 234 const MachineOperand &MO = MI.getOperand(I); 235 236 if (MO.isReg() && MO.getReg()) 237 HasHazard |= checkRegDefsUses(NewDefs, NewUses, MO.getReg(), MO.isDef()); 238 } 239 240 Defs |= NewDefs; 241 Uses |= NewUses; 242 243 return HasHazard; 244 } 245 246 bool RegDefsUses::checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, 247 unsigned Reg, bool IsDef) const { 248 if (IsDef) { 249 NewDefs.set(Reg); 250 // check whether Reg has already been defined or used. 251 return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg)); 252 } 253 254 NewUses.set(Reg); 255 // check whether Reg has already been defined. 256 return isRegInSet(Defs, Reg); 257 } 258 259 bool RegDefsUses::isRegInSet(const BitVector &RegSet, unsigned Reg) const { 260 // Check Reg and all aliased Registers. 261 for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI) 262 if (RegSet.test(*AI)) 263 return true; 264 return false; 265 } 266 267 bool NoMemInstr::hasHazard(const MachineInstr &MI) { 268 // Return true if MI accesses memory. 269 return (MI.mayStore() || MI.mayLoad()); 270 } 271 272 MemDefsUses::MemDefsUses(const MachineFrameInfo *MFI_) 273 : MFI(MFI_), SeenLoad(false), SeenStore(false), SeenNoObjLoad(false), 274 SeenNoObjStore(false), ForbidMemInstr(false) {} 275 276 bool MemDefsUses::hasHazard(const MachineInstr &MI) { 277 if (!MI.mayStore() && !MI.mayLoad()) 278 return false; 279 280 if (ForbidMemInstr) 281 return true; 282 283 bool OrigSeenLoad = SeenLoad, OrigSeenStore = SeenStore; 284 285 SeenLoad |= MI.mayLoad(); 286 SeenStore |= MI.mayStore(); 287 288 // If MI is an ordered or volatile memory reference, disallow moving 289 // subsequent loads and stores to delay slot. 290 if (MI.hasOrderedMemoryRef() && (OrigSeenLoad || OrigSeenStore)) { 291 ForbidMemInstr = true; 292 return true; 293 } 294 295 bool HasHazard = false; 296 SmallVector<const Value *, 4> Objs; 297 298 // Check underlying object list. 299 if (getUnderlyingObjects(MI, Objs)) { 300 for (SmallVector<const Value *, 4>::const_iterator I = Objs.begin(); 301 I != Objs.end(); ++I) 302 HasHazard |= updateDefsUses(*I, MI.mayStore()); 303 304 return HasHazard; 305 } 306 307 // No underlying objects found. 308 HasHazard = MI.mayStore() && (OrigSeenLoad || OrigSeenStore); 309 HasHazard |= MI.mayLoad() || OrigSeenStore; 310 311 SeenNoObjLoad |= MI.mayLoad(); 312 SeenNoObjStore |= MI.mayStore(); 313 314 return HasHazard; 315 } 316 317 bool MemDefsUses::updateDefsUses(const Value *V, bool MayStore) { 318 if (MayStore) 319 return !Defs.insert(V) || Uses.count(V) || SeenNoObjStore || SeenNoObjLoad; 320 321 Uses.insert(V); 322 return Defs.count(V) || SeenNoObjStore; 323 } 324 325 bool MemDefsUses:: 326 getUnderlyingObjects(const MachineInstr &MI, 327 SmallVectorImpl<const Value *> &Objects) const { 328 if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getValue()) 329 return false; 330 331 const Value *V = (*MI.memoperands_begin())->getValue(); 332 333 SmallVector<Value *, 4> Objs; 334 GetUnderlyingObjects(const_cast<Value *>(V), Objs); 335 336 for (SmallVector<Value*, 4>::iterator I = Objs.begin(), E = Objs.end(); 337 I != E; ++I) { 338 if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(*I)) { 339 if (PSV->isAliased(MFI)) 340 return false; 341 } else if (!isIdentifiedObject(V)) 342 return false; 343 344 Objects.push_back(*I); 345 } 346 347 return true; 348 } 349 350 /// runOnMachineBasicBlock - Fill in delay slots for the given basic block. 351 /// We assume there is only one delay slot per delayed instruction. 352 bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { 353 bool Changed = false; 354 355 for (Iter I = MBB.begin(); I != MBB.end(); ++I) { 356 if (!I->hasDelaySlot()) 357 continue; 358 359 ++FilledSlots; 360 Changed = true; 361 362 // Delay slot filling is disabled at -O0. 363 if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None) && 364 (searchBackward(MBB, I) || searchForward(MBB, I))) 365 continue; 366 367 // Bundle the NOP to the instruction with the delay slot. 368 BuildMI(MBB, llvm::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); 369 MIBundleBuilder(MBB, I, llvm::next(llvm::next(I))); 370 } 371 372 return Changed; 373 } 374 375 /// createMipsDelaySlotFillerPass - Returns a pass that fills in delay 376 /// slots in Mips MachineFunctions 377 FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) { 378 return new Filler(tm); 379 } 380 381 template<typename IterTy> 382 bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, 383 RegDefsUses &RegDU, InspectMemInstr& IM, 384 IterTy &Filler) const { 385 for (IterTy I = Begin; I != End; ++I) { 386 // skip debug value 387 if (I->isDebugValue()) 388 continue; 389 390 if (terminateSearch(*I)) 391 break; 392 393 assert((!I->isCall() && !I->isReturn() && !I->isBranch()) && 394 "Cannot put calls, returns or branches in delay slot."); 395 396 if (delayHasHazard(*I, RegDU, IM)) 397 continue; 398 399 Filler = I; 400 return true; 401 } 402 403 return false; 404 } 405 406 bool Filler::searchBackward(MachineBasicBlock &MBB, Iter Slot) const { 407 RegDefsUses RegDU(TM); 408 MemDefsUses MemDU(MBB.getParent()->getFrameInfo()); 409 ReverseIter Filler; 410 411 RegDU.init(*Slot); 412 413 if (searchRange(MBB, ReverseIter(Slot), MBB.rend(), RegDU, MemDU, Filler)) { 414 MBB.splice(llvm::next(Slot), &MBB, llvm::next(Filler).base()); 415 MIBundleBuilder(MBB, Slot, llvm::next(llvm::next(Slot))); 416 ++UsefulSlots; 417 return true; 418 } 419 420 return false; 421 } 422 423 bool Filler::searchForward(MachineBasicBlock &MBB, Iter Slot) const { 424 // Can handle only calls. 425 if (!Slot->isCall()) 426 return false; 427 428 RegDefsUses RegDU(TM); 429 NoMemInstr NM; 430 Iter Filler; 431 432 RegDU.setCallerSaved(*Slot); 433 434 if (searchRange(MBB, llvm::next(Slot), MBB.end(), RegDU, NM, Filler)) { 435 MBB.splice(llvm::next(Slot), &MBB, Filler); 436 MIBundleBuilder(MBB, Slot, llvm::next(llvm::next(Slot))); 437 ++UsefulSlots; 438 return true; 439 } 440 441 return false; 442 } 443 444 bool Filler::delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, 445 InspectMemInstr &IM) const { 446 bool HasHazard = (Candidate.isImplicitDef() || Candidate.isKill()); 447 448 HasHazard |= IM.hasHazard(Candidate); 449 HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands()); 450 451 return HasHazard; 452 } 453 454 bool Filler::terminateSearch(const MachineInstr &Candidate) const { 455 return (Candidate.isTerminator() || Candidate.isCall() || 456 Candidate.isLabel() || Candidate.isInlineAsm() || 457 Candidate.hasUnmodeledSideEffects()); 458 } 459