Line data Source code
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 1313317 : GCNRegPressure() {
39 : clear();
40 : }
41 :
42 : bool empty() const { return getSGPRNum() == 0 && getVGPRNum() == 0; }
43 :
44 105562 : void clear() { std::fill(&Value[0], &Value[TOTAL_KINDS], 0); }
45 :
46 0 : unsigned getSGPRNum() const { return Value[SGPR32]; }
47 0 : unsigned getVGPRNum() const { return Value[VGPR32]; }
48 :
49 0 : unsigned getVGPRTuplesWeight() const { return Value[VGPR_TUPLE]; }
50 0 : unsigned getSGPRTuplesWeight() const { return Value[SGPR_TUPLE]; }
51 :
52 1715 : unsigned getOccupancy(const GCNSubtarget &ST) const {
53 1715 : return std::min(ST.getOccupancyWithNumSGPRs(getSGPRNum()),
54 1715 : 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 6455585 : for (unsigned I = 0; I < GCNRegPressure::TOTAL_KINDS; ++I)
92 5660987 : Res.Value[I] = std::max(P1.Value[I], P2.Value[I]);
93 637629 : 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 42227 : 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 0 : const MachineInstr *getLastTrackedMI() const { return LastTrackedMI; }
116 :
117 : void clearMaxPressure() { MaxPressure.clear(); }
118 :
119 : // returns MaxPressure, resetting it
120 : decltype(MaxPressure) moveMaxPressure() {
121 42576 : 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 16 : 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 360 : 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 42211 : GCNDownwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
158 :
159 0 : 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 20 : inline GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI,
195 : const LiveIntervals &LIS) {
196 20 : return getLiveRegs(LIS.getInstructionIndex(MI).getDeadSlot(), LIS,
197 20 : MI.getParent()->getParent()->getRegInfo());
198 : }
199 :
200 20193 : inline GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI,
201 : const LiveIntervals &LIS) {
202 20193 : return getLiveRegs(LIS.getInstructionIndex(MI).getBaseIndex(), LIS,
203 20193 : MI.getParent()->getParent()->getRegInfo());
204 : }
205 :
206 : template <typename Range>
207 43106 : GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI,
208 : Range &&LiveRegs) {
209 : GCNRegPressure Res;
210 90957 : for (const auto &RM : LiveRegs)
211 47851 : Res.inc(RM.first, LaneBitmask::getNone(), RM.second, MRI);
212 43106 : 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
|