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 public: 129 typedef PressureChange* iterator; 130 typedef const PressureChange* const_iterator; 131 iterator begin() { return &PressureChanges[0]; } 132 iterator end() { return &PressureChanges[MaxPSets]; } 133 const_iterator begin() const { return &PressureChanges[0]; } 134 const_iterator end() const { return &PressureChanges[MaxPSets]; } 135 136 void addPressureChange(unsigned RegUnit, bool IsDec, 137 const MachineRegisterInfo *MRI); 138 }; 139 140 /// Array of PressureDiffs. 141 class PressureDiffs { 142 PressureDiff *PDiffArray; 143 unsigned Size; 144 unsigned Max; 145 public: 146 PressureDiffs(): PDiffArray(nullptr), Size(0), Max(0) {} 147 ~PressureDiffs() { free(PDiffArray); } 148 149 void clear() { Size = 0; } 150 151 void init(unsigned N); 152 153 PressureDiff &operator[](unsigned Idx) { 154 assert(Idx < Size && "PressureDiff index out of bounds"); 155 return PDiffArray[Idx]; 156 } 157 const PressureDiff &operator[](unsigned Idx) const { 158 return const_cast<PressureDiffs*>(this)->operator[](Idx); 159 } 160 }; 161 162 /// Store the effects of a change in pressure on things that MI scheduler cares 163 /// about. 164 /// 165 /// Excess records the value of the largest difference in register units beyond 166 /// the target's pressure limits across the affected pressure sets, where 167 /// largest is defined as the absolute value of the difference. Negative 168 /// ExcessUnits indicates a reduction in pressure that had already exceeded the 169 /// target's limits. 170 /// 171 /// CriticalMax records the largest increase in the tracker's max pressure that 172 /// exceeds the critical limit for some pressure set determined by the client. 173 /// 174 /// CurrentMax records the largest increase in the tracker's max pressure that 175 /// exceeds the current limit for some pressure set determined by the client. 176 struct RegPressureDelta { 177 PressureChange Excess; 178 PressureChange CriticalMax; 179 PressureChange CurrentMax; 180 181 RegPressureDelta() {} 182 183 bool operator==(const RegPressureDelta &RHS) const { 184 return Excess == RHS.Excess && CriticalMax == RHS.CriticalMax 185 && CurrentMax == RHS.CurrentMax; 186 } 187 bool operator!=(const RegPressureDelta &RHS) const { 188 return !operator==(RHS); 189 } 190 }; 191 192 /// \brief A set of live virtual registers and physical register units. 193 /// 194 /// Virtual and physical register numbers require separate sparse sets, but most 195 /// of the RegisterPressureTracker handles them uniformly. 196 struct LiveRegSet { 197 SparseSet<unsigned> PhysRegs; 198 SparseSet<unsigned, VirtReg2IndexFunctor> VirtRegs; 199 200 bool contains(unsigned Reg) const { 201 if (TargetRegisterInfo::isVirtualRegister(Reg)) 202 return VirtRegs.count(Reg); 203 return PhysRegs.count(Reg); 204 } 205 206 bool insert(unsigned Reg) { 207 if (TargetRegisterInfo::isVirtualRegister(Reg)) 208 return VirtRegs.insert(Reg).second; 209 return PhysRegs.insert(Reg).second; 210 } 211 212 bool erase(unsigned Reg) { 213 if (TargetRegisterInfo::isVirtualRegister(Reg)) 214 return VirtRegs.erase(Reg); 215 return PhysRegs.erase(Reg); 216 } 217 }; 218 219 /// Track the current register pressure at some position in the instruction 220 /// stream, and remember the high water mark within the region traversed. This 221 /// does not automatically consider live-through ranges. The client may 222 /// independently adjust for global liveness. 223 /// 224 /// Each RegPressureTracker only works within a MachineBasicBlock. Pressure can 225 /// be tracked across a larger region by storing a RegisterPressure result at 226 /// each block boundary and explicitly adjusting pressure to account for block 227 /// live-in and live-out register sets. 228 /// 229 /// RegPressureTracker holds a reference to a RegisterPressure result that it 230 /// computes incrementally. During downward tracking, P.BottomIdx or P.BottomPos 231 /// is invalid until it reaches the end of the block or closeRegion() is 232 /// explicitly called. Similarly, P.TopIdx is invalid during upward 233 /// tracking. Changing direction has the side effect of closing region, and 234 /// traversing past TopIdx or BottomIdx reopens it. 235 class RegPressureTracker { 236 const MachineFunction *MF; 237 const TargetRegisterInfo *TRI; 238 const RegisterClassInfo *RCI; 239 const MachineRegisterInfo *MRI; 240 const LiveIntervals *LIS; 241 242 /// We currently only allow pressure tracking within a block. 243 const MachineBasicBlock *MBB; 244 245 /// Track the max pressure within the region traversed so far. 246 RegisterPressure &P; 247 248 /// Run in two modes dependending on whether constructed with IntervalPressure 249 /// or RegisterPressure. If requireIntervals is false, LIS are ignored. 250 bool RequireIntervals; 251 252 /// True if UntiedDefs will be populated. 253 bool TrackUntiedDefs; 254 255 /// Register pressure corresponds to liveness before this instruction 256 /// iterator. It may point to the end of the block or a DebugValue rather than 257 /// an instruction. 258 MachineBasicBlock::const_iterator CurrPos; 259 260 /// Pressure map indexed by pressure set ID, not class ID. 261 std::vector<unsigned> CurrSetPressure; 262 263 /// Set of live registers. 264 LiveRegSet LiveRegs; 265 266 /// Set of vreg defs that start a live range. 267 SparseSet<unsigned, VirtReg2IndexFunctor> UntiedDefs; 268 /// Live-through pressure. 269 std::vector<unsigned> LiveThruPressure; 270 271 public: 272 RegPressureTracker(IntervalPressure &rp) : 273 MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp), 274 RequireIntervals(true), TrackUntiedDefs(false) {} 275 276 RegPressureTracker(RegionPressure &rp) : 277 MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp), 278 RequireIntervals(false), TrackUntiedDefs(false) {} 279 280 void reset(); 281 282 void init(const MachineFunction *mf, const RegisterClassInfo *rci, 283 const LiveIntervals *lis, const MachineBasicBlock *mbb, 284 MachineBasicBlock::const_iterator pos, 285 bool ShouldTrackUntiedDefs = false); 286 287 /// Force liveness of virtual registers or physical register 288 /// units. Particularly useful to initialize the livein/out state of the 289 /// tracker before the first call to advance/recede. 290 void addLiveRegs(ArrayRef<unsigned> Regs); 291 292 /// Get the MI position corresponding to this register pressure. 293 MachineBasicBlock::const_iterator getPos() const { return CurrPos; } 294 295 // Reset the MI position corresponding to the register pressure. This allows 296 // schedulers to move instructions above the RegPressureTracker's 297 // CurrPos. Since the pressure is computed before CurrPos, the iterator 298 // position changes while pressure does not. 299 void setPos(MachineBasicBlock::const_iterator Pos) { CurrPos = Pos; } 300 301 /// \brief Get the SlotIndex for the first nondebug instruction including or 302 /// after the current position. 303 SlotIndex getCurrSlot() const; 304 305 /// Recede across the previous instruction. 306 bool recede(SmallVectorImpl<unsigned> *LiveUses = nullptr, 307 PressureDiff *PDiff = nullptr); 308 309 /// Advance across the current instruction. 310 bool advance(); 311 312 /// Finalize the region boundaries and recored live ins and live outs. 313 void closeRegion(); 314 315 /// Initialize the LiveThru pressure set based on the untied defs found in 316 /// RPTracker. 317 void initLiveThru(const RegPressureTracker &RPTracker); 318 319 /// Copy an existing live thru pressure result. 320 void initLiveThru(ArrayRef<unsigned> PressureSet) { 321 LiveThruPressure.assign(PressureSet.begin(), PressureSet.end()); 322 } 323 324 ArrayRef<unsigned> getLiveThru() const { return LiveThruPressure; } 325 326 /// Get the resulting register pressure over the traversed region. 327 /// This result is complete if either advance() or recede() has returned true, 328 /// or if closeRegion() was explicitly invoked. 329 RegisterPressure &getPressure() { return P; } 330 const RegisterPressure &getPressure() const { return P; } 331 332 /// Get the register set pressure at the current position, which may be less 333 /// than the pressure across the traversed region. 334 std::vector<unsigned> &getRegSetPressureAtPos() { return CurrSetPressure; } 335 336 void discoverLiveOut(unsigned Reg); 337 void discoverLiveIn(unsigned Reg); 338 339 bool isTopClosed() const; 340 bool isBottomClosed() const; 341 342 void closeTop(); 343 void closeBottom(); 344 345 /// Consider the pressure increase caused by traversing this instruction 346 /// bottom-up. Find the pressure set with the most change beyond its pressure 347 /// limit based on the tracker's current pressure, and record the number of 348 /// excess register units of that pressure set introduced by this instruction. 349 void getMaxUpwardPressureDelta(const MachineInstr *MI, 350 PressureDiff *PDiff, 351 RegPressureDelta &Delta, 352 ArrayRef<PressureChange> CriticalPSets, 353 ArrayRef<unsigned> MaxPressureLimit); 354 355 void getUpwardPressureDelta(const MachineInstr *MI, 356 /*const*/ PressureDiff &PDiff, 357 RegPressureDelta &Delta, 358 ArrayRef<PressureChange> CriticalPSets, 359 ArrayRef<unsigned> MaxPressureLimit) const; 360 361 /// Consider the pressure increase caused by traversing this instruction 362 /// top-down. Find the pressure set with the most change beyond its pressure 363 /// limit based on the tracker's current pressure, and record the number of 364 /// excess register units of that pressure set introduced by this instruction. 365 void getMaxDownwardPressureDelta(const MachineInstr *MI, 366 RegPressureDelta &Delta, 367 ArrayRef<PressureChange> CriticalPSets, 368 ArrayRef<unsigned> MaxPressureLimit); 369 370 /// Find the pressure set with the most change beyond its pressure limit after 371 /// traversing this instruction either upward or downward depending on the 372 /// closed end of the current region. 373 void getMaxPressureDelta(const MachineInstr *MI, 374 RegPressureDelta &Delta, 375 ArrayRef<PressureChange> CriticalPSets, 376 ArrayRef<unsigned> MaxPressureLimit) { 377 if (isTopClosed()) 378 return getMaxDownwardPressureDelta(MI, Delta, CriticalPSets, 379 MaxPressureLimit); 380 381 assert(isBottomClosed() && "Uninitialized pressure tracker"); 382 return getMaxUpwardPressureDelta(MI, nullptr, Delta, CriticalPSets, 383 MaxPressureLimit); 384 } 385 386 /// Get the pressure of each PSet after traversing this instruction bottom-up. 387 void getUpwardPressure(const MachineInstr *MI, 388 std::vector<unsigned> &PressureResult, 389 std::vector<unsigned> &MaxPressureResult); 390 391 /// Get the pressure of each PSet after traversing this instruction top-down. 392 void getDownwardPressure(const MachineInstr *MI, 393 std::vector<unsigned> &PressureResult, 394 std::vector<unsigned> &MaxPressureResult); 395 396 void getPressureAfterInst(const MachineInstr *MI, 397 std::vector<unsigned> &PressureResult, 398 std::vector<unsigned> &MaxPressureResult) { 399 if (isTopClosed()) 400 return getUpwardPressure(MI, PressureResult, MaxPressureResult); 401 402 assert(isBottomClosed() && "Uninitialized pressure tracker"); 403 return getDownwardPressure(MI, PressureResult, MaxPressureResult); 404 } 405 406 bool hasUntiedDef(unsigned VirtReg) const { 407 return UntiedDefs.count(VirtReg); 408 } 409 410 void dump() const; 411 412 protected: 413 const LiveRange *getLiveRange(unsigned Reg) const; 414 415 void increaseRegPressure(ArrayRef<unsigned> Regs); 416 void decreaseRegPressure(ArrayRef<unsigned> Regs); 417 418 void bumpUpwardPressure(const MachineInstr *MI); 419 void bumpDownwardPressure(const MachineInstr *MI); 420 }; 421 422 void dumpRegSetPressure(ArrayRef<unsigned> SetPressure, 423 const TargetRegisterInfo *TRI); 424 } // end namespace llvm 425 426 #endif 427