1 //===- GCNRegPressure.h -----------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file defines the GCNRegPressure class, which tracks registry pressure
11 /// by bookkeeping number of SGPR/VGPRs used, weights for large SGPR/VGPRs. It
12 /// also implements a compare function, which compares different register
13 /// pressures, and declares one with max occupance as winner.
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
18 #define LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
20 #include "GCNSubtarget.h"
21 #include "llvm/CodeGen/LiveIntervals.h"
26 class MachineRegisterInfo
;
30 struct GCNRegPressure
{
45 bool empty() const { return getSGPRNum() == 0 && getVGPRNum(false) == 0; }
47 void clear() { std::fill(&Value
[0], &Value
[TOTAL_KINDS
], 0); }
49 unsigned getSGPRNum() const { return Value
[SGPR32
]; }
50 unsigned getVGPRNum(bool UnifiedVGPRFile
) const {
51 if (UnifiedVGPRFile
) {
52 return Value
[AGPR32
] ? alignTo(Value
[VGPR32
], 4) + Value
[AGPR32
]
53 : Value
[VGPR32
] + Value
[AGPR32
];
55 return std::max(Value
[VGPR32
], Value
[AGPR32
]);
57 unsigned getAGPRNum() const { return Value
[AGPR32
]; }
59 unsigned getVGPRTuplesWeight() const { return std::max(Value
[VGPR_TUPLE
],
61 unsigned getSGPRTuplesWeight() const { return Value
[SGPR_TUPLE
]; }
63 unsigned getOccupancy(const GCNSubtarget
&ST
) const {
64 return std::min(ST
.getOccupancyWithNumSGPRs(getSGPRNum()),
65 ST
.getOccupancyWithNumVGPRs(getVGPRNum(ST
.hasGFX90AInsts())));
68 void inc(unsigned Reg
,
71 const MachineRegisterInfo
&MRI
);
73 bool higherOccupancy(const GCNSubtarget
&ST
, const GCNRegPressure
& O
) const {
74 return getOccupancy(ST
) > O
.getOccupancy(ST
);
77 bool less(const GCNSubtarget
&ST
, const GCNRegPressure
& O
,
78 unsigned MaxOccupancy
= std::numeric_limits
<unsigned>::max()) const;
80 bool operator==(const GCNRegPressure
&O
) const {
81 return std::equal(&Value
[0], &Value
[TOTAL_KINDS
], O
.Value
);
84 bool operator!=(const GCNRegPressure
&O
) const {
88 void print(raw_ostream
&OS
, const GCNSubtarget
*ST
= nullptr) const;
89 void dump() const { print(dbgs()); }
92 unsigned Value
[TOTAL_KINDS
];
94 static unsigned getRegKind(Register Reg
, const MachineRegisterInfo
&MRI
);
96 friend GCNRegPressure
max(const GCNRegPressure
&P1
,
97 const GCNRegPressure
&P2
);
100 inline GCNRegPressure
max(const GCNRegPressure
&P1
, const GCNRegPressure
&P2
) {
102 for (unsigned I
= 0; I
< GCNRegPressure::TOTAL_KINDS
; ++I
)
103 Res
.Value
[I
] = std::max(P1
.Value
[I
], P2
.Value
[I
]);
109 using LiveRegSet
= DenseMap
<unsigned, LaneBitmask
>;
112 const LiveIntervals
&LIS
;
114 GCNRegPressure CurPressure
, MaxPressure
;
115 const MachineInstr
*LastTrackedMI
= nullptr;
116 mutable const MachineRegisterInfo
*MRI
= nullptr;
118 GCNRPTracker(const LiveIntervals
&LIS_
) : LIS(LIS_
) {}
120 void reset(const MachineInstr
&MI
, const LiveRegSet
*LiveRegsCopy
,
124 // live regs for the current state
125 const decltype(LiveRegs
) &getLiveRegs() const { return LiveRegs
; }
126 const MachineInstr
*getLastTrackedMI() const { return LastTrackedMI
; }
128 void clearMaxPressure() { MaxPressure
.clear(); }
130 // returns MaxPressure, resetting it
131 decltype(MaxPressure
) moveMaxPressure() {
132 auto Res
= MaxPressure
;
137 decltype(LiveRegs
) moveLiveRegs() {
138 return std::move(LiveRegs
);
141 static void printLiveRegs(raw_ostream
&OS
, const LiveRegSet
& LiveRegs
,
142 const MachineRegisterInfo
&MRI
);
145 class GCNUpwardRPTracker
: public GCNRPTracker
{
147 GCNUpwardRPTracker(const LiveIntervals
&LIS_
) : GCNRPTracker(LIS_
) {}
149 // reset tracker to the point just below MI
150 // filling live regs upon this point using LIS
151 void reset(const MachineInstr
&MI
, const LiveRegSet
*LiveRegs
= nullptr);
153 // move to the state just above the MI
154 void recede(const MachineInstr
&MI
);
156 // checks whether the tracker's state after receding MI corresponds
157 // to reported by LIS
158 bool isValid() const;
161 class GCNDownwardRPTracker
: public GCNRPTracker
{
162 // Last position of reset or advanceBeforeNext
163 MachineBasicBlock::const_iterator NextMI
;
165 MachineBasicBlock::const_iterator MBBEnd
;
168 GCNDownwardRPTracker(const LiveIntervals
&LIS_
) : GCNRPTracker(LIS_
) {}
170 MachineBasicBlock::const_iterator
getNext() const { return NextMI
; }
172 // Reset tracker to the point before the MI
173 // filling live regs upon this point using LIS.
174 // Returns false if block is empty except debug values.
175 bool reset(const MachineInstr
&MI
, const LiveRegSet
*LiveRegs
= nullptr);
177 // Move to the state right before the next MI. Returns false if reached
179 bool advanceBeforeNext();
181 // Move to the state at the MI, advanceBeforeNext has to be called first.
182 void advanceToNext();
184 // Move to the state at the next MI. Returns false if reached end of block.
187 // Advance instructions until before End.
188 bool advance(MachineBasicBlock::const_iterator End
);
190 // Reset to Begin and advance to End.
191 bool advance(MachineBasicBlock::const_iterator Begin
,
192 MachineBasicBlock::const_iterator End
,
193 const LiveRegSet
*LiveRegsCopy
= nullptr);
196 LaneBitmask
getLiveLaneMask(unsigned Reg
,
198 const LiveIntervals
&LIS
,
199 const MachineRegisterInfo
&MRI
);
201 GCNRPTracker::LiveRegSet
getLiveRegs(SlotIndex SI
,
202 const LiveIntervals
&LIS
,
203 const MachineRegisterInfo
&MRI
);
205 /// creates a map MachineInstr -> LiveRegSet
206 /// R - range of iterators on instructions
207 /// After - upon entry or exit of every instruction
208 /// Note: there is no entry in the map for instructions with empty live reg set
209 /// Complexity = O(NumVirtRegs * averageLiveRangeSegmentsPerReg * lg(R))
210 template <typename Range
>
211 DenseMap
<MachineInstr
*, GCNRPTracker::LiveRegSet
>
212 getLiveRegMap(Range
&&R
, bool After
, LiveIntervals
&LIS
) {
213 std::vector
<SlotIndex
> Indexes
;
214 Indexes
.reserve(std::distance(R
.begin(), R
.end()));
215 auto &SII
= *LIS
.getSlotIndexes();
216 for (MachineInstr
*I
: R
) {
217 auto SI
= SII
.getInstructionIndex(*I
);
218 Indexes
.push_back(After
? SI
.getDeadSlot() : SI
.getBaseIndex());
222 auto &MRI
= (*R
.begin())->getParent()->getParent()->getRegInfo();
223 DenseMap
<MachineInstr
*, GCNRPTracker::LiveRegSet
> LiveRegMap
;
224 SmallVector
<SlotIndex
, 32> LiveIdxs
, SRLiveIdxs
;
225 for (unsigned I
= 0, E
= MRI
.getNumVirtRegs(); I
!= E
; ++I
) {
226 auto Reg
= Register::index2VirtReg(I
);
227 if (!LIS
.hasInterval(Reg
))
229 auto &LI
= LIS
.getInterval(Reg
);
231 if (!LI
.findIndexesLiveAt(Indexes
, std::back_inserter(LiveIdxs
)))
233 if (!LI
.hasSubRanges()) {
234 for (auto SI
: LiveIdxs
)
235 LiveRegMap
[SII
.getInstructionFromIndex(SI
)][Reg
] =
236 MRI
.getMaxLaneMaskForVReg(Reg
);
238 for (const auto &S
: LI
.subranges()) {
239 // constrain search for subranges by indexes live at main range
241 S
.findIndexesLiveAt(LiveIdxs
, std::back_inserter(SRLiveIdxs
));
242 for (auto SI
: SRLiveIdxs
)
243 LiveRegMap
[SII
.getInstructionFromIndex(SI
)][Reg
] |= S
.LaneMask
;
249 inline GCNRPTracker::LiveRegSet
getLiveRegsAfter(const MachineInstr
&MI
,
250 const LiveIntervals
&LIS
) {
251 return getLiveRegs(LIS
.getInstructionIndex(MI
).getDeadSlot(), LIS
,
252 MI
.getParent()->getParent()->getRegInfo());
255 inline GCNRPTracker::LiveRegSet
getLiveRegsBefore(const MachineInstr
&MI
,
256 const LiveIntervals
&LIS
) {
257 return getLiveRegs(LIS
.getInstructionIndex(MI
).getBaseIndex(), LIS
,
258 MI
.getParent()->getParent()->getRegInfo());
261 template <typename Range
>
262 GCNRegPressure
getRegPressure(const MachineRegisterInfo
&MRI
,
265 for (const auto &RM
: LiveRegs
)
266 Res
.inc(RM
.first
, LaneBitmask::getNone(), RM
.second
, MRI
);
270 bool isEqual(const GCNRPTracker::LiveRegSet
&S1
,
271 const GCNRPTracker::LiveRegSet
&S2
);
273 void printLivesAt(SlotIndex SI
,
274 const LiveIntervals
&LIS
,
275 const MachineRegisterInfo
&MRI
);
277 } // end namespace llvm
279 #endif // LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H