1 //===-- RegisterPressure.h - Dynamic Register Pressure -*- C++ -*-------===// 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 // This file defines the RegisterPressure class which can be used to track 11 // MachineInstr level register pressure. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CODEGEN_REGISTERPRESSURE_H 16 #define LLVM_CODEGEN_REGISTERPRESSURE_H 17 18 #include "llvm/ADT/SparseSet.h" 19 #include "llvm/CodeGen/SlotIndexes.h" 20 #include "llvm/Target/TargetRegisterInfo.h" 21 22 namespace llvm { 23 24 class LiveIntervals; 25 class LiveRange; 26 class RegisterClassInfo; 27 class MachineInstr; 28 29 /// Base class for register pressure results. 30 struct RegisterPressure { 31 /// Map of max reg pressure indexed by pressure set ID, not class ID. 32 std::vector<unsigned> MaxSetPressure; 33 34 /// List of live in virtual registers or physical register units. 35 SmallVector<unsigned,8> LiveInRegs; 36 SmallVector<unsigned,8> LiveOutRegs; 37 38 void dump(const TargetRegisterInfo *TRI) const; 39 }; 40 41 /// RegisterPressure computed within a region of instructions delimited by 42 /// TopIdx and BottomIdx. During pressure computation, the maximum pressure per 43 /// register pressure set is increased. Once pressure within a region is fully 44 /// computed, the live-in and live-out sets are recorded. 45 /// 46 /// This is preferable to RegionPressure when LiveIntervals are available, 47 /// because delimiting regions by SlotIndex is more robust and convenient than 48 /// holding block iterators. The block contents can change without invalidating 49 /// the pressure result. 50 struct IntervalPressure : RegisterPressure { 51 /// Record the boundary of the region being tracked. 52 SlotIndex TopIdx; 53 SlotIndex BottomIdx; 54 55 void reset(); 56 57 void openTop(SlotIndex NextTop); 58 59 void openBottom(SlotIndex PrevBottom); 60 }; 61 62 /// RegisterPressure computed within a region of instructions delimited by 63 /// TopPos and BottomPos. This is a less precise version of IntervalPressure for 64 /// use when LiveIntervals are unavailable. 65 struct RegionPressure : RegisterPressure { 66 /// Record the boundary of the region being tracked. 67 MachineBasicBlock::const_iterator TopPos; 68 MachineBasicBlock::const_iterator BottomPos; 69 70 void reset(); 71 72 void openTop(MachineBasicBlock::const_iterator PrevTop); 73 74 void openBottom(MachineBasicBlock::const_iterator PrevBottom); 75 }; 76 77 /// Capture a change in pressure for a single pressure set. UnitInc may be 78 /// expressed in terms of upward or downward pressure depending on the client 79 /// and will be dynamically adjusted for current liveness. 80 /// 81 /// Pressure increments are tiny, typically 1-2 units, and this is only for 82 /// heuristics, so we don't check UnitInc overflow. Instead, we may have a 83 /// higher level assert that pressure is consistent within a region. We also 84 /// effectively ignore dead defs which don't affect heuristics much. 85 class PressureChange { 86 uint16_t PSetID; // ID+1. 0=Invalid. 87 int16_t UnitInc; 88 public: PressureChange()89 PressureChange(): PSetID(0), UnitInc(0) {} PressureChange(unsigned id)90 PressureChange(unsigned id): PSetID(id+1), UnitInc(0) { 91 assert(id < UINT16_MAX && "PSetID overflow."); 92 } 93 isValid()94 bool isValid() const { return PSetID > 0; } 95 getPSet()96 unsigned getPSet() const { 97 assert(isValid() && "invalid PressureChange"); 98 return PSetID - 1; 99 } 100 // If PSetID is invalid, return UINT16_MAX to give it lowest priority. getPSetOrMax()101 unsigned getPSetOrMax() const { return (PSetID - 1) & UINT16_MAX; } 102 getUnitInc()103 int getUnitInc() const { return UnitInc; } 104 setUnitInc(int Inc)105 void setUnitInc(int Inc) { UnitInc = Inc; } 106 107 bool operator==(const PressureChange &RHS) const { 108 return PSetID == RHS.PSetID && UnitInc == RHS.UnitInc; 109 } 110 }; 111 112 template <> struct isPodLike<PressureChange> { 113 static const bool value = true; 114 }; 115 116 /// List of PressureChanges in order of increasing, unique PSetID. 117 /// 118 /// Use a small fixed number, because we can fit more PressureChanges in an 119 /// empty SmallVector than ever need to be tracked per register class. If more 120 /// PSets are affected, then we only track the most constrained. 121 class PressureDiff { 122 // The initial design was for MaxPSets=4, but that requires PSet partitions, 123 // which are not yet implemented. (PSet partitions are equivalent PSets given 124 // the register classes actually in use within the scheduling region.) 125 enum { MaxPSets = 16 }; 126 127 PressureChange PressureChanges[MaxPSets]; 128 129 typedef PressureChange* iterator; 130 iterator nonconst_begin() { return &PressureChanges[0]; } 131 iterator nonconst_end() { return &PressureChanges[MaxPSets]; } 132 133 public: 134 typedef const PressureChange* const_iterator; 135 const_iterator begin() const { return &PressureChanges[0]; } 136 const_iterator end() const { return &PressureChanges[MaxPSets]; } 137 138 void addPressureChange(unsigned RegUnit, bool IsDec, 139 const MachineRegisterInfo *MRI); 140 141 LLVM_DUMP_METHOD void dump(const TargetRegisterInfo &TRI) const; 142 }; 143 144 /// Array of PressureDiffs. 145 class PressureDiffs { 146 PressureDiff *PDiffArray; 147 unsigned Size; 148 unsigned Max; 149 public: 150 PressureDiffs(): PDiffArray(nullptr), Size(0), Max(0) {} 151 ~PressureDiffs() { free(PDiffArray); } 152 153 void clear() { Size = 0; } 154 155 void init(unsigned N); 156 157 PressureDiff &operator[](unsigned Idx) { 158 assert(Idx < Size && "PressureDiff index out of bounds"); 159 return PDiffArray[Idx]; 160 } 161 const PressureDiff &operator[](unsigned Idx) const { 162 return const_cast<PressureDiffs*>(this)->operator[](Idx); 163 } 164 }; 165 166 /// Store the effects of a change in pressure on things that MI scheduler cares 167 /// about. 168 /// 169 /// Excess records the value of the largest difference in register units beyond 170 /// the target's pressure limits across the affected pressure sets, where 171 /// largest is defined as the absolute value of the difference. Negative 172 /// ExcessUnits indicates a reduction in pressure that had already exceeded the 173 /// target's limits. 174 /// 175 /// CriticalMax records the largest increase in the tracker's max pressure that 176 /// exceeds the critical limit for some pressure set determined by the client. 177 /// 178 /// CurrentMax records the largest increase in the tracker's max pressure that 179 /// exceeds the current limit for some pressure set determined by the client. 180 struct RegPressureDelta { 181 PressureChange Excess; 182 PressureChange CriticalMax; 183 PressureChange CurrentMax; 184 185 RegPressureDelta() {} 186 187 bool operator==(const RegPressureDelta &RHS) const { 188 return Excess == RHS.Excess && CriticalMax == RHS.CriticalMax 189 && CurrentMax == RHS.CurrentMax; 190 } 191 bool operator!=(const RegPressureDelta &RHS) const { 192 return !operator==(RHS); 193 } 194 }; 195 196 /// A set of live virtual registers and physical register units. 197 /// 198 /// This is a wrapper around a SparseSet which deals with mapping register unit 199 /// and virtual register indexes to an index usable by the sparse set. 200 class LiveRegSet { 201 private: 202 SparseSet<unsigned> Regs; 203 unsigned NumRegUnits; 204 205 unsigned getSparseIndexFromReg(unsigned Reg) const { 206 if (TargetRegisterInfo::isVirtualRegister(Reg)) 207 return TargetRegisterInfo::virtReg2Index(Reg) + NumRegUnits; 208 assert(Reg < NumRegUnits); 209 return Reg; 210 } 211 unsigned getRegFromSparseIndex(unsigned SparseIndex) const { 212 if (SparseIndex >= NumRegUnits) 213 return TargetRegisterInfo::index2VirtReg(SparseIndex-NumRegUnits); 214 return SparseIndex; 215 } 216 217 public: 218 void clear(); 219 void init(const MachineRegisterInfo &MRI); 220 221 bool contains(unsigned Reg) const { 222 unsigned SparseIndex = getSparseIndexFromReg(Reg); 223 return Regs.count(SparseIndex); 224 } 225 226 bool insert(unsigned Reg) { 227 unsigned SparseIndex = getSparseIndexFromReg(Reg); 228 return Regs.insert(SparseIndex).second; 229 } 230 231 bool erase(unsigned Reg) { 232 unsigned SparseIndex = getSparseIndexFromReg(Reg); 233 return Regs.erase(SparseIndex); 234 } 235 236 size_t size() const { 237 return Regs.size(); 238 } 239 240 template<typename ContainerT> 241 void appendTo(ContainerT &To) const { 242 for (unsigned I : Regs) { 243 unsigned Reg = getRegFromSparseIndex(I); 244 To.push_back(Reg); 245 } 246 } 247 }; 248 249 /// Track the current register pressure at some position in the instruction 250 /// stream, and remember the high water mark within the region traversed. This 251 /// does not automatically consider live-through ranges. The client may 252 /// independently adjust for global liveness. 253 /// 254 /// Each RegPressureTracker only works within a MachineBasicBlock. Pressure can 255 /// be tracked across a larger region by storing a RegisterPressure result at 256 /// each block boundary and explicitly adjusting pressure to account for block 257 /// live-in and live-out register sets. 258 /// 259 /// RegPressureTracker holds a reference to a RegisterPressure result that it 260 /// computes incrementally. During downward tracking, P.BottomIdx or P.BottomPos 261 /// is invalid until it reaches the end of the block or closeRegion() is 262 /// explicitly called. Similarly, P.TopIdx is invalid during upward 263 /// tracking. Changing direction has the side effect of closing region, and 264 /// traversing past TopIdx or BottomIdx reopens it. 265 class RegPressureTracker { 266 const MachineFunction *MF; 267 const TargetRegisterInfo *TRI; 268 const RegisterClassInfo *RCI; 269 const MachineRegisterInfo *MRI; 270 const LiveIntervals *LIS; 271 272 /// We currently only allow pressure tracking within a block. 273 const MachineBasicBlock *MBB; 274 275 /// Track the max pressure within the region traversed so far. 276 RegisterPressure &P; 277 278 /// Run in two modes dependending on whether constructed with IntervalPressure 279 /// or RegisterPressure. If requireIntervals is false, LIS are ignored. 280 bool RequireIntervals; 281 282 /// True if UntiedDefs will be populated. 283 bool TrackUntiedDefs; 284 285 /// Register pressure corresponds to liveness before this instruction 286 /// iterator. It may point to the end of the block or a DebugValue rather than 287 /// an instruction. 288 MachineBasicBlock::const_iterator CurrPos; 289 290 /// Pressure map indexed by pressure set ID, not class ID. 291 std::vector<unsigned> CurrSetPressure; 292 293 /// Set of live registers. 294 LiveRegSet LiveRegs; 295 296 /// Set of vreg defs that start a live range. 297 SparseSet<unsigned, VirtReg2IndexFunctor> UntiedDefs; 298 /// Live-through pressure. 299 std::vector<unsigned> LiveThruPressure; 300 301 public: 302 RegPressureTracker(IntervalPressure &rp) : 303 MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp), 304 RequireIntervals(true), TrackUntiedDefs(false) {} 305 306 RegPressureTracker(RegionPressure &rp) : 307 MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp), 308 RequireIntervals(false), TrackUntiedDefs(false) {} 309 310 void reset(); 311 312 void init(const MachineFunction *mf, const RegisterClassInfo *rci, 313 const LiveIntervals *lis, const MachineBasicBlock *mbb, 314 MachineBasicBlock::const_iterator pos, 315 bool ShouldTrackUntiedDefs = false); 316 317 /// Force liveness of virtual registers or physical register 318 /// units. Particularly useful to initialize the livein/out state of the 319 /// tracker before the first call to advance/recede. 320 void addLiveRegs(ArrayRef<unsigned> Regs); 321 322 /// Get the MI position corresponding to this register pressure. 323 MachineBasicBlock::const_iterator getPos() const { return CurrPos; } 324 325 // Reset the MI position corresponding to the register pressure. This allows 326 // schedulers to move instructions above the RegPressureTracker's 327 // CurrPos. Since the pressure is computed before CurrPos, the iterator 328 // position changes while pressure does not. 329 void setPos(MachineBasicBlock::const_iterator Pos) { CurrPos = Pos; } 330 331 /// Recede across the previous instruction. 332 void recede(SmallVectorImpl<unsigned> *LiveUses = nullptr, 333 PressureDiff *PDiff = nullptr); 334 335 /// Advance across the current instruction. 336 void advance(); 337 338 /// Finalize the region boundaries and recored live ins and live outs. 339 void closeRegion(); 340 341 /// Initialize the LiveThru pressure set based on the untied defs found in 342 /// RPTracker. 343 void initLiveThru(const RegPressureTracker &RPTracker); 344 345 /// Copy an existing live thru pressure result. 346 void initLiveThru(ArrayRef<unsigned> PressureSet) { 347 LiveThruPressure.assign(PressureSet.begin(), PressureSet.end()); 348 } 349 350 ArrayRef<unsigned> getLiveThru() const { return LiveThruPressure; } 351 352 /// Get the resulting register pressure over the traversed region. 353 /// This result is complete if closeRegion() was explicitly invoked. 354 RegisterPressure &getPressure() { return P; } 355 const RegisterPressure &getPressure() const { return P; } 356 357 /// Get the register set pressure at the current position, which may be less 358 /// than the pressure across the traversed region. 359 const std::vector<unsigned> &getRegSetPressureAtPos() const { 360 return CurrSetPressure; 361 } 362 363 bool isTopClosed() const; 364 bool isBottomClosed() const; 365 366 void closeTop(); 367 void closeBottom(); 368 369 /// Consider the pressure increase caused by traversing this instruction 370 /// bottom-up. Find the pressure set with the most change beyond its pressure 371 /// limit based on the tracker's current pressure, and record the number of 372 /// excess register units of that pressure set introduced by this instruction. 373 void getMaxUpwardPressureDelta(const MachineInstr *MI, 374 PressureDiff *PDiff, 375 RegPressureDelta &Delta, 376 ArrayRef<PressureChange> CriticalPSets, 377 ArrayRef<unsigned> MaxPressureLimit); 378 379 void getUpwardPressureDelta(const MachineInstr *MI, 380 /*const*/ PressureDiff &PDiff, 381 RegPressureDelta &Delta, 382 ArrayRef<PressureChange> CriticalPSets, 383 ArrayRef<unsigned> MaxPressureLimit) const; 384 385 /// Consider the pressure increase caused by traversing this instruction 386 /// top-down. Find the pressure set with the most change beyond its pressure 387 /// limit based on the tracker's current pressure, and record the number of 388 /// excess register units of that pressure set introduced by this instruction. 389 void getMaxDownwardPressureDelta(const MachineInstr *MI, 390 RegPressureDelta &Delta, 391 ArrayRef<PressureChange> CriticalPSets, 392 ArrayRef<unsigned> MaxPressureLimit); 393 394 /// Find the pressure set with the most change beyond its pressure limit after 395 /// traversing this instruction either upward or downward depending on the 396 /// closed end of the current region. 397 void getMaxPressureDelta(const MachineInstr *MI, 398 RegPressureDelta &Delta, 399 ArrayRef<PressureChange> CriticalPSets, 400 ArrayRef<unsigned> MaxPressureLimit) { 401 if (isTopClosed()) 402 return getMaxDownwardPressureDelta(MI, Delta, CriticalPSets, 403 MaxPressureLimit); 404 405 assert(isBottomClosed() && "Uninitialized pressure tracker"); 406 return getMaxUpwardPressureDelta(MI, nullptr, Delta, CriticalPSets, 407 MaxPressureLimit); 408 } 409 410 /// Get the pressure of each PSet after traversing this instruction bottom-up. 411 void getUpwardPressure(const MachineInstr *MI, 412 std::vector<unsigned> &PressureResult, 413 std::vector<unsigned> &MaxPressureResult); 414 415 /// Get the pressure of each PSet after traversing this instruction top-down. 416 void getDownwardPressure(const MachineInstr *MI, 417 std::vector<unsigned> &PressureResult, 418 std::vector<unsigned> &MaxPressureResult); 419 420 void getPressureAfterInst(const MachineInstr *MI, 421 std::vector<unsigned> &PressureResult, 422 std::vector<unsigned> &MaxPressureResult) { 423 if (isTopClosed()) 424 return getUpwardPressure(MI, PressureResult, MaxPressureResult); 425 426 assert(isBottomClosed() && "Uninitialized pressure tracker"); 427 return getDownwardPressure(MI, PressureResult, MaxPressureResult); 428 } 429 430 bool hasUntiedDef(unsigned VirtReg) const { 431 return UntiedDefs.count(VirtReg); 432 } 433 434 void dump() const; 435 436 protected: 437 void discoverLiveOut(unsigned Reg); 438 void discoverLiveIn(unsigned Reg); 439 440 /// \brief Get the SlotIndex for the first nondebug instruction including or 441 /// after the current position. 442 SlotIndex getCurrSlot() const; 443 444 void increaseRegPressure(ArrayRef<unsigned> Regs); 445 void decreaseRegPressure(ArrayRef<unsigned> Regs); 446 447 void bumpUpwardPressure(const MachineInstr *MI); 448 void bumpDownwardPressure(const MachineInstr *MI); 449 }; 450 451 void dumpRegSetPressure(ArrayRef<unsigned> SetPressure, 452 const TargetRegisterInfo *TRI); 453 } // end namespace llvm 454 455 #endif 456