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 LiveInterval; 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 /// Increase register pressure for each pressure set impacted by this register 39 /// class. Normally called by RegPressureTracker, but may be called manually 40 /// to account for live through (global liveness). 41 /// 42 /// \param Reg is either a virtual register number or register unit number. 43 void increase(unsigned Reg, const TargetRegisterInfo *TRI, 44 const MachineRegisterInfo *MRI); 45 46 /// Decrease register pressure for each pressure set impacted by this register 47 /// class. This is only useful to account for spilling or rematerialization. 48 /// 49 /// \param Reg is either a virtual register number or register unit number. 50 void decrease(unsigned Reg, const TargetRegisterInfo *TRI, 51 const MachineRegisterInfo *MRI); 52 53 void dump(const TargetRegisterInfo *TRI) const; 54 }; 55 56 /// RegisterPressure computed within a region of instructions delimited by 57 /// TopIdx and BottomIdx. During pressure computation, the maximum pressure per 58 /// register pressure set is increased. Once pressure within a region is fully 59 /// computed, the live-in and live-out sets are recorded. 60 /// 61 /// This is preferable to RegionPressure when LiveIntervals are available, 62 /// because delimiting regions by SlotIndex is more robust and convenient than 63 /// holding block iterators. The block contents can change without invalidating 64 /// the pressure result. 65 struct IntervalPressure : RegisterPressure { 66 /// Record the boundary of the region being tracked. 67 SlotIndex TopIdx; 68 SlotIndex BottomIdx; 69 70 void reset(); 71 72 void openTop(SlotIndex NextTop); 73 74 void openBottom(SlotIndex PrevBottom); 75 }; 76 77 /// RegisterPressure computed within a region of instructions delimited by 78 /// TopPos and BottomPos. This is a less precise version of IntervalPressure for 79 /// use when LiveIntervals are unavailable. 80 struct RegionPressure : RegisterPressure { 81 /// Record the boundary of the region being tracked. 82 MachineBasicBlock::const_iterator TopPos; 83 MachineBasicBlock::const_iterator BottomPos; 84 85 void reset(); 86 87 void openTop(MachineBasicBlock::const_iterator PrevTop); 88 89 void openBottom(MachineBasicBlock::const_iterator PrevBottom); 90 }; 91 92 /// An element of pressure difference that identifies the pressure set and 93 /// amount of increase or decrease in units of pressure. 94 struct PressureElement { 95 unsigned PSetID; 96 int UnitIncrease; 97 PressureElementPressureElement98 PressureElement(): PSetID(~0U), UnitIncrease(0) {} PressureElementPressureElement99 PressureElement(unsigned id, int inc): PSetID(id), UnitIncrease(inc) {} 100 isValidPressureElement101 bool isValid() const { return PSetID != ~0U; } 102 }; 103 104 /// Store the effects of a change in pressure on things that MI scheduler cares 105 /// about. 106 /// 107 /// Excess records the value of the largest difference in register units beyond 108 /// the target's pressure limits across the affected pressure sets, where 109 /// largest is defined as the absolute value of the difference. Negative 110 /// ExcessUnits indicates a reduction in pressure that had already exceeded the 111 /// target's limits. 112 /// 113 /// CriticalMax records the largest increase in the tracker's max pressure that 114 /// exceeds the critical limit for some pressure set determined by the client. 115 /// 116 /// CurrentMax records the largest increase in the tracker's max pressure that 117 /// exceeds the current limit for some pressure set determined by the client. 118 struct RegPressureDelta { 119 PressureElement Excess; 120 PressureElement CriticalMax; 121 PressureElement CurrentMax; 122 RegPressureDeltaRegPressureDelta123 RegPressureDelta() {} 124 }; 125 126 /// \brief A set of live virtual registers and physical register units. 127 /// 128 /// Virtual and physical register numbers require separate sparse sets, but most 129 /// of the RegisterPressureTracker handles them uniformly. 130 struct LiveRegSet { 131 SparseSet<unsigned> PhysRegs; 132 SparseSet<unsigned, VirtReg2IndexFunctor> VirtRegs; 133 containsLiveRegSet134 bool contains(unsigned Reg) { 135 if (TargetRegisterInfo::isVirtualRegister(Reg)) 136 return VirtRegs.count(Reg); 137 return PhysRegs.count(Reg); 138 } 139 insertLiveRegSet140 bool insert(unsigned Reg) { 141 if (TargetRegisterInfo::isVirtualRegister(Reg)) 142 return VirtRegs.insert(Reg).second; 143 return PhysRegs.insert(Reg).second; 144 } 145 eraseLiveRegSet146 bool erase(unsigned Reg) { 147 if (TargetRegisterInfo::isVirtualRegister(Reg)) 148 return VirtRegs.erase(Reg); 149 return PhysRegs.erase(Reg); 150 } 151 }; 152 153 /// Track the current register pressure at some position in the instruction 154 /// stream, and remember the high water mark within the region traversed. This 155 /// does not automatically consider live-through ranges. The client may 156 /// independently adjust for global liveness. 157 /// 158 /// Each RegPressureTracker only works within a MachineBasicBlock. Pressure can 159 /// be tracked across a larger region by storing a RegisterPressure result at 160 /// each block boundary and explicitly adjusting pressure to account for block 161 /// live-in and live-out register sets. 162 /// 163 /// RegPressureTracker holds a reference to a RegisterPressure result that it 164 /// computes incrementally. During downward tracking, P.BottomIdx or P.BottomPos 165 /// is invalid until it reaches the end of the block or closeRegion() is 166 /// explicitly called. Similarly, P.TopIdx is invalid during upward 167 /// tracking. Changing direction has the side effect of closing region, and 168 /// traversing past TopIdx or BottomIdx reopens it. 169 class RegPressureTracker { 170 const MachineFunction *MF; 171 const TargetRegisterInfo *TRI; 172 const RegisterClassInfo *RCI; 173 const MachineRegisterInfo *MRI; 174 const LiveIntervals *LIS; 175 176 /// We currently only allow pressure tracking within a block. 177 const MachineBasicBlock *MBB; 178 179 /// Track the max pressure within the region traversed so far. 180 RegisterPressure &P; 181 182 /// Run in two modes dependending on whether constructed with IntervalPressure 183 /// or RegisterPressure. If requireIntervals is false, LIS are ignored. 184 bool RequireIntervals; 185 186 /// Register pressure corresponds to liveness before this instruction 187 /// iterator. It may point to the end of the block or a DebugValue rather than 188 /// an instruction. 189 MachineBasicBlock::const_iterator CurrPos; 190 191 /// Pressure map indexed by pressure set ID, not class ID. 192 std::vector<unsigned> CurrSetPressure; 193 194 /// Set of live registers. 195 LiveRegSet LiveRegs; 196 197 public: RegPressureTracker(IntervalPressure & rp)198 RegPressureTracker(IntervalPressure &rp) : 199 MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(true) {} 200 RegPressureTracker(RegionPressure & rp)201 RegPressureTracker(RegionPressure &rp) : 202 MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false) {} 203 204 void init(const MachineFunction *mf, const RegisterClassInfo *rci, 205 const LiveIntervals *lis, const MachineBasicBlock *mbb, 206 MachineBasicBlock::const_iterator pos); 207 208 /// Force liveness of virtual registers or physical register 209 /// units. Particularly useful to initialize the livein/out state of the 210 /// tracker before the first call to advance/recede. 211 void addLiveRegs(ArrayRef<unsigned> Regs); 212 213 /// Get the MI position corresponding to this register pressure. getPos()214 MachineBasicBlock::const_iterator getPos() const { return CurrPos; } 215 216 // Reset the MI position corresponding to the register pressure. This allows 217 // schedulers to move instructions above the RegPressureTracker's 218 // CurrPos. Since the pressure is computed before CurrPos, the iterator 219 // position changes while pressure does not. setPos(MachineBasicBlock::const_iterator Pos)220 void setPos(MachineBasicBlock::const_iterator Pos) { CurrPos = Pos; } 221 222 /// \brief Get the SlotIndex for the first nondebug instruction including or 223 /// after the current position. 224 SlotIndex getCurrSlot() const; 225 226 /// Recede across the previous instruction. 227 bool recede(); 228 229 /// Advance across the current instruction. 230 bool advance(); 231 232 /// Finalize the region boundaries and recored live ins and live outs. 233 void closeRegion(); 234 235 /// Get the resulting register pressure over the traversed region. 236 /// This result is complete if either advance() or recede() has returned true, 237 /// or if closeRegion() was explicitly invoked. getPressure()238 RegisterPressure &getPressure() { return P; } getPressure()239 const RegisterPressure &getPressure() const { return P; } 240 241 /// Get the register set pressure at the current position, which may be less 242 /// than the pressure across the traversed region. getRegSetPressureAtPos()243 std::vector<unsigned> &getRegSetPressureAtPos() { return CurrSetPressure; } 244 245 void discoverLiveOut(unsigned Reg); 246 void discoverLiveIn(unsigned Reg); 247 248 bool isTopClosed() const; 249 bool isBottomClosed() const; 250 251 void closeTop(); 252 void closeBottom(); 253 254 /// Consider the pressure increase caused by traversing this instruction 255 /// bottom-up. Find the pressure set with the most change beyond its pressure 256 /// limit based on the tracker's current pressure, and record the number of 257 /// excess register units of that pressure set introduced by this instruction. 258 void getMaxUpwardPressureDelta(const MachineInstr *MI, 259 RegPressureDelta &Delta, 260 ArrayRef<PressureElement> CriticalPSets, 261 ArrayRef<unsigned> MaxPressureLimit); 262 263 /// Consider the pressure increase caused by traversing this instruction 264 /// top-down. Find the pressure set with the most change beyond its pressure 265 /// limit based on the tracker's current pressure, and record the number of 266 /// excess register units of that pressure set introduced by this instruction. 267 void getMaxDownwardPressureDelta(const MachineInstr *MI, 268 RegPressureDelta &Delta, 269 ArrayRef<PressureElement> CriticalPSets, 270 ArrayRef<unsigned> MaxPressureLimit); 271 272 /// Find the pressure set with the most change beyond its pressure limit after 273 /// traversing this instruction either upward or downward depending on the 274 /// closed end of the current region. getMaxPressureDelta(const MachineInstr * MI,RegPressureDelta & Delta,ArrayRef<PressureElement> CriticalPSets,ArrayRef<unsigned> MaxPressureLimit)275 void getMaxPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, 276 ArrayRef<PressureElement> CriticalPSets, 277 ArrayRef<unsigned> MaxPressureLimit) { 278 if (isTopClosed()) 279 return getMaxDownwardPressureDelta(MI, Delta, CriticalPSets, 280 MaxPressureLimit); 281 282 assert(isBottomClosed() && "Uninitialized pressure tracker"); 283 return getMaxUpwardPressureDelta(MI, Delta, CriticalPSets, 284 MaxPressureLimit); 285 } 286 287 /// Get the pressure of each PSet after traversing this instruction bottom-up. 288 void getUpwardPressure(const MachineInstr *MI, 289 std::vector<unsigned> &PressureResult, 290 std::vector<unsigned> &MaxPressureResult); 291 292 /// Get the pressure of each PSet after traversing this instruction top-down. 293 void getDownwardPressure(const MachineInstr *MI, 294 std::vector<unsigned> &PressureResult, 295 std::vector<unsigned> &MaxPressureResult); 296 getPressureAfterInst(const MachineInstr * MI,std::vector<unsigned> & PressureResult,std::vector<unsigned> & MaxPressureResult)297 void getPressureAfterInst(const MachineInstr *MI, 298 std::vector<unsigned> &PressureResult, 299 std::vector<unsigned> &MaxPressureResult) { 300 if (isTopClosed()) 301 return getUpwardPressure(MI, PressureResult, MaxPressureResult); 302 303 assert(isBottomClosed() && "Uninitialized pressure tracker"); 304 return getDownwardPressure(MI, PressureResult, MaxPressureResult); 305 } 306 307 void dump() const; 308 309 protected: 310 const LiveInterval *getInterval(unsigned Reg) const; 311 312 void increaseRegPressure(ArrayRef<unsigned> Regs); 313 void decreaseRegPressure(ArrayRef<unsigned> Regs); 314 315 void bumpUpwardPressure(const MachineInstr *MI); 316 void bumpDownwardPressure(const MachineInstr *MI); 317 }; 318 } // end namespace llvm 319 320 #endif 321