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 namespace { 51 class RegDefsUses { 52 public: 53 RegDefsUses(TargetMachine &TM); 54 void init(const MachineInstr &MI); 55 bool update(const MachineInstr &MI, unsigned Begin, unsigned End); 56 57 private: 58 bool checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, unsigned Reg, 59 bool IsDef) const; 60 61 /// Returns true if Reg or its alias is in RegSet. 62 bool isRegInSet(const BitVector &RegSet, unsigned Reg) const; 63 64 const TargetRegisterInfo &TRI; 65 BitVector Defs, Uses; 66 }; 67 68 /// This class maintains memory dependence information. 69 class MemDefsUses { 70 public: 71 MemDefsUses(const MachineFrameInfo *MFI); 72 73 /// Return true if MI cannot be moved to delay slot. 74 bool hasHazard(const MachineInstr &MI); 75 76 private: 77 /// Update Defs and Uses. Return true if there exist dependences that 78 /// disqualify the delay slot candidate between V and values in Uses and Defs. 79 bool updateDefsUses(const Value *V, bool MayStore); 80 81 /// Get the list of underlying objects of MI's memory operand. 82 bool getUnderlyingObjects(const MachineInstr &MI, 83 SmallVectorImpl<const Value *> &Objects) const; 84 85 const MachineFrameInfo *MFI; 86 SmallPtrSet<const Value*, 4> Uses, Defs; 87 88 /// Flags indicating whether loads or stores have been seen. 89 bool SeenLoad, SeenStore; 90 91 /// Flags indicating whether loads or stores with no underlying objects have 92 /// been seen. 93 bool SeenNoObjLoad, SeenNoObjStore; 94 95 /// Memory instructions are not allowed to move to delay slot if this flag 96 /// is true. 97 bool ForbidMemInstr; 98 }; 99 100 class Filler : public MachineFunctionPass { 101 public: 102 Filler(TargetMachine &tm) 103 : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } 104 105 virtual const char *getPassName() const { 106 return "Mips Delay Slot Filler"; 107 } 108 109 bool runOnMachineFunction(MachineFunction &F) { 110 if (SkipDelaySlotFiller) 111 return false; 112 113 bool Changed = false; 114 for (MachineFunction::iterator FI = F.begin(), FE = F.end(); 115 FI != FE; ++FI) 116 Changed |= runOnMachineBasicBlock(*FI); 117 return Changed; 118 } 119 120 private: 121 typedef MachineBasicBlock::iterator Iter; 122 typedef MachineBasicBlock::reverse_iterator ReverseIter; 123 124 bool runOnMachineBasicBlock(MachineBasicBlock &MBB); 125 126 /// This function checks if it is valid to move Candidate to the delay slot 127 /// and returns true if it isn't. It also updates memory and register 128 /// dependence information. 129 bool delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, 130 MemDefsUses &MemDU) const; 131 132 /// This function searches range [Begin, End) for an instruction that can be 133 /// moved to the delay slot. Returns true on success. 134 template<typename IterTy> 135 bool searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, 136 RegDefsUses &RegDU, MemDefsUses &MemDU, IterTy &Filler) const; 137 138 bool searchBackward(MachineBasicBlock &MBB, Iter Slot, Iter &Filler) const; 139 140 bool terminateSearch(const MachineInstr &Candidate) const; 141 142 TargetMachine &TM; 143 const TargetInstrInfo *TII; 144 145 static char ID; 146 }; 147 char Filler::ID = 0; 148 } // end of anonymous namespace 149 150 RegDefsUses::RegDefsUses(TargetMachine &TM) 151 : TRI(*TM.getRegisterInfo()), Defs(TRI.getNumRegs(), false), 152 Uses(TRI.getNumRegs(), false) {} 153 154 void RegDefsUses::init(const MachineInstr &MI) { 155 // Add all register operands which are explicit and non-variadic. 156 update(MI, 0, MI.getDesc().getNumOperands()); 157 158 // If MI is a call, add RA to Defs to prevent users of RA from going into 159 // delay slot. 160 if (MI.isCall()) 161 Defs.set(Mips::RA); 162 163 // Add all implicit register operands of branch instructions except 164 // register AT. 165 if (MI.isBranch()) { 166 update(MI, MI.getDesc().getNumOperands(), MI.getNumOperands()); 167 Defs.reset(Mips::AT); 168 } 169 } 170 171 bool RegDefsUses::update(const MachineInstr &MI, unsigned Begin, unsigned End) { 172 BitVector NewDefs(TRI.getNumRegs()), NewUses(TRI.getNumRegs()); 173 bool HasHazard = false; 174 175 for (unsigned I = Begin; I != End; ++I) { 176 const MachineOperand &MO = MI.getOperand(I); 177 178 if (MO.isReg() && MO.getReg()) 179 HasHazard |= checkRegDefsUses(NewDefs, NewUses, MO.getReg(), MO.isDef()); 180 } 181 182 Defs |= NewDefs; 183 Uses |= NewUses; 184 185 return HasHazard; 186 } 187 188 bool RegDefsUses::checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, 189 unsigned Reg, bool IsDef) const { 190 if (IsDef) { 191 NewDefs.set(Reg); 192 // check whether Reg has already been defined or used. 193 return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg)); 194 } 195 196 NewUses.set(Reg); 197 // check whether Reg has already been defined. 198 return isRegInSet(Defs, Reg); 199 } 200 201 bool RegDefsUses::isRegInSet(const BitVector &RegSet, unsigned Reg) const { 202 // Check Reg and all aliased Registers. 203 for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI) 204 if (RegSet.test(*AI)) 205 return true; 206 return false; 207 } 208 209 MemDefsUses::MemDefsUses(const MachineFrameInfo *MFI_) 210 : MFI(MFI_), SeenLoad(false), SeenStore(false), SeenNoObjLoad(false), 211 SeenNoObjStore(false), ForbidMemInstr(false) {} 212 213 bool MemDefsUses::hasHazard(const MachineInstr &MI) { 214 if (!MI.mayStore() && !MI.mayLoad()) 215 return false; 216 217 if (ForbidMemInstr) 218 return true; 219 220 bool OrigSeenLoad = SeenLoad, OrigSeenStore = SeenStore; 221 222 SeenLoad |= MI.mayLoad(); 223 SeenStore |= MI.mayStore(); 224 225 // If MI is an ordered or volatile memory reference, disallow moving 226 // subsequent loads and stores to delay slot. 227 if (MI.hasOrderedMemoryRef() && (OrigSeenLoad || OrigSeenStore)) { 228 ForbidMemInstr = true; 229 return true; 230 } 231 232 bool HasHazard = false; 233 SmallVector<const Value *, 4> Objs; 234 235 // Check underlying object list. 236 if (getUnderlyingObjects(MI, Objs)) { 237 for (SmallVector<const Value *, 4>::const_iterator I = Objs.begin(); 238 I != Objs.end(); ++I) 239 HasHazard |= updateDefsUses(*I, MI.mayStore()); 240 241 return HasHazard; 242 } 243 244 // No underlying objects found. 245 HasHazard = MI.mayStore() && (OrigSeenLoad || OrigSeenStore); 246 HasHazard |= MI.mayLoad() || OrigSeenStore; 247 248 SeenNoObjLoad |= MI.mayLoad(); 249 SeenNoObjStore |= MI.mayStore(); 250 251 return HasHazard; 252 } 253 254 bool MemDefsUses::updateDefsUses(const Value *V, bool MayStore) { 255 if (MayStore) 256 return !Defs.insert(V) || Uses.count(V) || SeenNoObjStore || SeenNoObjLoad; 257 258 Uses.insert(V); 259 return Defs.count(V) || SeenNoObjStore; 260 } 261 262 bool MemDefsUses:: 263 getUnderlyingObjects(const MachineInstr &MI, 264 SmallVectorImpl<const Value *> &Objects) const { 265 if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getValue()) 266 return false; 267 268 const Value *V = (*MI.memoperands_begin())->getValue(); 269 270 SmallVector<Value *, 4> Objs; 271 GetUnderlyingObjects(const_cast<Value *>(V), Objs); 272 273 for (SmallVector<Value*, 4>::iterator I = Objs.begin(), E = Objs.end(); 274 I != E; ++I) { 275 if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(*I)) { 276 if (PSV->isAliased(MFI)) 277 return false; 278 } else if (!isIdentifiedObject(V)) 279 return false; 280 281 Objects.push_back(*I); 282 } 283 284 return true; 285 } 286 287 /// runOnMachineBasicBlock - Fill in delay slots for the given basic block. 288 /// We assume there is only one delay slot per delayed instruction. 289 bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { 290 bool Changed = false; 291 292 for (Iter I = MBB.begin(); I != MBB.end(); ++I) { 293 if (!I->hasDelaySlot()) 294 continue; 295 296 ++FilledSlots; 297 Changed = true; 298 Iter D; 299 300 // Delay slot filling is disabled at -O0. 301 if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None) && 302 searchBackward(MBB, I, D)) { 303 MBB.splice(llvm::next(I), &MBB, D); 304 ++UsefulSlots; 305 } else 306 BuildMI(MBB, llvm::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); 307 308 // Bundle the delay slot filler to the instruction with the delay slot. 309 MIBundleBuilder(MBB, I, llvm::next(llvm::next(I))); 310 } 311 312 return Changed; 313 } 314 315 /// createMipsDelaySlotFillerPass - Returns a pass that fills in delay 316 /// slots in Mips MachineFunctions 317 FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) { 318 return new Filler(tm); 319 } 320 321 template<typename IterTy> 322 bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, 323 RegDefsUses &RegDU, MemDefsUses &MemDU, 324 IterTy &Filler) const { 325 for (IterTy I = Begin; I != End; ++I) { 326 // skip debug value 327 if (I->isDebugValue()) 328 continue; 329 330 if (terminateSearch(*I)) 331 break; 332 333 assert((!I->isCall() && !I->isReturn() && !I->isBranch()) && 334 "Cannot put calls, returns or branches in delay slot."); 335 336 if (delayHasHazard(*I, RegDU, MemDU)) 337 continue; 338 339 Filler = I; 340 return true; 341 } 342 343 return false; 344 } 345 346 bool Filler::searchBackward(MachineBasicBlock &MBB, Iter Slot, 347 Iter &Filler) const { 348 RegDefsUses RegDU(TM); 349 MemDefsUses MemDU(MBB.getParent()->getFrameInfo()); 350 ReverseIter FillerReverse; 351 352 RegDU.init(*Slot); 353 354 if (searchRange(MBB, ReverseIter(Slot), MBB.rend(), RegDU, MemDU, 355 FillerReverse)) { 356 Filler = llvm::next(FillerReverse).base(); 357 return true; 358 } 359 360 return false; 361 } 362 363 bool Filler::delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, 364 MemDefsUses &MemDU) const { 365 bool HasHazard = (Candidate.isImplicitDef() || Candidate.isKill()); 366 367 HasHazard |= MemDU.hasHazard(Candidate); 368 HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands()); 369 370 return HasHazard; 371 } 372 373 bool Filler::terminateSearch(const MachineInstr &Candidate) const { 374 return (Candidate.isTerminator() || Candidate.isCall() || 375 Candidate.isLabel() || Candidate.isInlineAsm() || 376 Candidate.hasUnmodeledSideEffects()); 377 } 378