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