1 //===- GCNRegPressure.h -----------------------------------------*- 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 #ifndef LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H 11 #define LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H 12 13 #include "AMDGPUSubtarget.h" 14 #include "llvm/ADT/DenseMap.h" 15 #include "llvm/CodeGen/LiveIntervals.h" 16 #include "llvm/CodeGen/MachineBasicBlock.h" 17 #include "llvm/CodeGen/MachineInstr.h" 18 #include "llvm/CodeGen/SlotIndexes.h" 19 #include "llvm/MC/LaneBitmask.h" 20 #include "llvm/Support/Debug.h" 21 #include <algorithm> 22 #include <limits> 23 24 namespace llvm { 25 26 class MachineRegisterInfo; 27 class raw_ostream; 28 29 struct GCNRegPressure { 30 enum RegKind { 31 SGPR32, 32 SGPR_TUPLE, 33 VGPR32, 34 VGPR_TUPLE, 35 TOTAL_KINDS 36 }; 37 38 GCNRegPressure() { 39 clear(); 40 } 41 42 bool empty() const { return getSGPRNum() == 0 && getVGPRNum() == 0; } 43 44 void clear() { std::fill(&Value[0], &Value[TOTAL_KINDS], 0); } 45 46 unsigned getSGPRNum() const { return Value[SGPR32]; } 47 unsigned getVGPRNum() const { return Value[VGPR32]; } 48 49 unsigned getVGPRTuplesWeight() const { return Value[VGPR_TUPLE]; } 50 unsigned getSGPRTuplesWeight() const { return Value[SGPR_TUPLE]; } 51 52 unsigned getOccupancy(const GCNSubtarget &ST) const { 53 return std::min(ST.getOccupancyWithNumSGPRs(getSGPRNum()), 54 ST.getOccupancyWithNumVGPRs(getVGPRNum())); 55 } 56 57 void inc(unsigned Reg, 58 LaneBitmask PrevMask, 59 LaneBitmask NewMask, 60 const MachineRegisterInfo &MRI); 61 62 bool higherOccupancy(const GCNSubtarget &ST, const GCNRegPressure& O) const { 63 return getOccupancy(ST) > O.getOccupancy(ST); 64 } 65 66 bool less(const GCNSubtarget &ST, const GCNRegPressure& O, 67 unsigned MaxOccupancy = std::numeric_limits<unsigned>::max()) const; 68 69 bool operator==(const GCNRegPressure &O) const { 70 return std::equal(&Value[0], &Value[TOTAL_KINDS], O.Value); 71 } 72 73 bool operator!=(const GCNRegPressure &O) const { 74 return !(*this == O); 75 } 76 77 void print(raw_ostream &OS, const GCNSubtarget *ST = nullptr) const; 78 void dump() const { print(dbgs()); } 79 80 private: 81 unsigned Value[TOTAL_KINDS]; 82 83 static unsigned getRegKind(unsigned Reg, const MachineRegisterInfo &MRI); 84 85 friend GCNRegPressure max(const GCNRegPressure &P1, 86 const GCNRegPressure &P2); 87 }; 88 89 inline GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2) { 90 GCNRegPressure Res; 91 for (unsigned I = 0; I < GCNRegPressure::TOTAL_KINDS; ++I) 92 Res.Value[I] = std::max(P1.Value[I], P2.Value[I]); 93 return Res; 94 } 95 96 class GCNRPTracker { 97 public: 98 using LiveRegSet = DenseMap<unsigned, LaneBitmask>; 99 100 protected: 101 const LiveIntervals &LIS; 102 LiveRegSet LiveRegs; 103 GCNRegPressure CurPressure, MaxPressure; 104 const MachineInstr *LastTrackedMI = nullptr; 105 mutable const MachineRegisterInfo *MRI = nullptr; 106 107 GCNRPTracker(const LiveIntervals &LIS_) : LIS(LIS_) {} 108 109 void reset(const MachineInstr &MI, const LiveRegSet *LiveRegsCopy, 110 bool After); 111 112 public: 113 // live regs for the current state 114 const decltype(LiveRegs) &getLiveRegs() const { return LiveRegs; } 115 const MachineInstr *getLastTrackedMI() const { return LastTrackedMI; } 116 117 void clearMaxPressure() { MaxPressure.clear(); } 118 119 // returns MaxPressure, resetting it 120 decltype(MaxPressure) moveMaxPressure() { 121 auto Res = MaxPressure; 122 MaxPressure.clear(); 123 return Res; 124 } 125 126 decltype(LiveRegs) moveLiveRegs() { 127 return std::move(LiveRegs); 128 } 129 130 static void printLiveRegs(raw_ostream &OS, const LiveRegSet& LiveRegs, 131 const MachineRegisterInfo &MRI); 132 }; 133 134 class GCNUpwardRPTracker : public GCNRPTracker { 135 public: 136 GCNUpwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {} 137 138 // reset tracker to the point just below MI 139 // filling live regs upon this point using LIS 140 void reset(const MachineInstr &MI, const LiveRegSet *LiveRegs = nullptr); 141 142 // move to the state just above the MI 143 void recede(const MachineInstr &MI); 144 145 // checks whether the tracker's state after receding MI corresponds 146 // to reported by LIS 147 bool isValid() const; 148 }; 149 150 class GCNDownwardRPTracker : public GCNRPTracker { 151 // Last position of reset or advanceBeforeNext 152 MachineBasicBlock::const_iterator NextMI; 153 154 MachineBasicBlock::const_iterator MBBEnd; 155 156 public: 157 GCNDownwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {} 158 159 const MachineBasicBlock::const_iterator getNext() const { return NextMI; } 160 161 // Reset tracker to the point before the MI 162 // filling live regs upon this point using LIS. 163 // Returns false if block is empty except debug values. 164 bool reset(const MachineInstr &MI, const LiveRegSet *LiveRegs = nullptr); 165 166 // Move to the state right before the next MI. Returns false if reached 167 // end of the block. 168 bool advanceBeforeNext(); 169 170 // Move to the state at the MI, advanceBeforeNext has to be called first. 171 void advanceToNext(); 172 173 // Move to the state at the next MI. Returns false if reached end of block. 174 bool advance(); 175 176 // Advance instructions until before End. 177 bool advance(MachineBasicBlock::const_iterator End); 178 179 // Reset to Begin and advance to End. 180 bool advance(MachineBasicBlock::const_iterator Begin, 181 MachineBasicBlock::const_iterator End, 182 const LiveRegSet *LiveRegsCopy = nullptr); 183 }; 184 185 LaneBitmask getLiveLaneMask(unsigned Reg, 186 SlotIndex SI, 187 const LiveIntervals &LIS, 188 const MachineRegisterInfo &MRI); 189 190 GCNRPTracker::LiveRegSet getLiveRegs(SlotIndex SI, 191 const LiveIntervals &LIS, 192 const MachineRegisterInfo &MRI); 193 194 inline GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI, 195 const LiveIntervals &LIS) { 196 return getLiveRegs(LIS.getInstructionIndex(MI).getDeadSlot(), LIS, 197 MI.getParent()->getParent()->getRegInfo()); 198 } 199 200 inline GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI, 201 const LiveIntervals &LIS) { 202 return getLiveRegs(LIS.getInstructionIndex(MI).getBaseIndex(), LIS, 203 MI.getParent()->getParent()->getRegInfo()); 204 } 205 206 template <typename Range> 207 GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI, 208 Range &&LiveRegs) { 209 GCNRegPressure Res; 210 for (const auto &RM : LiveRegs) 211 Res.inc(RM.first, LaneBitmask::getNone(), RM.second, MRI); 212 return Res; 213 } 214 215 void printLivesAt(SlotIndex SI, 216 const LiveIntervals &LIS, 217 const MachineRegisterInfo &MRI); 218 219 } // end namespace llvm 220 221 #endif // LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H 222