1//===- GCNRegPressure.h -----------------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
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 occupancy as winner.
14///
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
18#define LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
19
20#include "GCNSubtarget.h"
21#include "llvm/CodeGen/LiveIntervals.h"
22#include "llvm/CodeGen/RegisterPressure.h"
23#include <algorithm>
24#include <array>
25
26namespace llvm {
27
28class MachineRegisterInfo;
29class raw_ostream;
30class SlotIndex;
31
32struct GCNRegPressure {
33 enum RegKind { SGPR, VGPR, AGPR, AVGPR, TOTAL_KINDS };
34
35 static constexpr const char *getName(RegKind Kind) {
36 const char *Names[] = {"SGPR", "VGPR", "AGPR", "AVGPR"};
37 assert(Kind < TOTAL_KINDS);
38 return Names[Kind];
39 }
40
41 GCNRegPressure() {
42 clear();
43 }
44
45 bool empty() const {
46 return !Value[SGPR] && !Value[VGPR] && !Value[AGPR] && !Value[AVGPR];
47 }
48
49 void clear() { Value.fill(u: 0); }
50
51 unsigned getNumRegs(RegKind Kind) const {
52 assert(Kind < TOTAL_KINDS);
53 return Value[Kind];
54 }
55
56 /// \returns the SGPR32 pressure
57 unsigned getSGPRNum() const { return Value[SGPR]; }
58 /// \returns the aggregated ArchVGPR32, AccVGPR32, and Pseudo AVGPR pressure
59 /// dependent upon \p UnifiedVGPRFile
60 unsigned getVGPRNum(bool UnifiedVGPRFile) const {
61 if (UnifiedVGPRFile) {
62 return Value[AGPR]
63 ? getUnifiedVGPRNum(NumArchVGPRs: Value[VGPR], NumAGPRs: Value[AGPR], NumAVGPRs: Value[AVGPR])
64 : Value[VGPR] + Value[AVGPR];
65 }
66 // AVGPR assignment priority is based on the width of the register. Account
67 // AVGPR pressure as VGPR.
68 return std::max(a: Value[VGPR] + Value[AVGPR], b: Value[AGPR]);
69 }
70
71 /// Returns the aggregated VGPR pressure, assuming \p NumArchVGPRs ArchVGPRs
72 /// \p NumAGPRs AGPRS, and \p NumAVGPRs AVGPRs for a target with a unified
73 /// VGPR file.
74 inline static unsigned getUnifiedVGPRNum(unsigned NumArchVGPRs,
75 unsigned NumAGPRs,
76 unsigned NumAVGPRs) {
77
78 // Assume AVGPRs will be assigned as VGPRs.
79 return alignTo(Value: NumArchVGPRs + NumAVGPRs,
80 Align: AMDGPU::IsaInfo::getArchVGPRAllocGranule()) +
81 NumAGPRs;
82 }
83
84 /// \returns the ArchVGPR32 pressure, plus the AVGPRS which we assume will be
85 /// allocated as VGPR
86 unsigned getArchVGPRNum() const { return Value[VGPR] + Value[AVGPR]; }
87 /// \returns the AccVGPR32 pressure
88 unsigned getAGPRNum() const { return Value[AGPR]; }
89 /// \returns the AVGPR32 pressure
90 unsigned getAVGPRNum() const { return Value[AVGPR]; }
91
92 unsigned getVGPRTuplesWeight() const {
93 return std::max(a: Value[TOTAL_KINDS + VGPR] + Value[TOTAL_KINDS + AVGPR],
94 b: Value[TOTAL_KINDS + AGPR]);
95 }
96 unsigned getSGPRTuplesWeight() const { return Value[TOTAL_KINDS + SGPR]; }
97
98 unsigned getOccupancy(const GCNSubtarget &ST,
99 unsigned DynamicVGPRBlockSize) const {
100 return std::min(a: ST.getOccupancyWithNumSGPRs(SGPRs: getSGPRNum()),
101 b: ST.getOccupancyWithNumVGPRs(VGPRs: getVGPRNum(UnifiedVGPRFile: ST.hasGFX90AInsts()),
102 DynamicVGPRBlockSize));
103 }
104
105 unsigned getVGPRSpills(MachineFunction &MF, unsigned ArchVGPRThreshold,
106 unsigned AGPRThreshold, unsigned CombinedThreshold) {
107 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
108 if (!ST.hasGFX90AInsts())
109 return 0;
110
111 unsigned ArchPressure = getArchVGPRNum();
112 unsigned AGPRPressure = getAGPRNum();
113
114 unsigned ArchSpill = ArchPressure > ArchVGPRThreshold
115 ? (ArchPressure - ArchVGPRThreshold)
116 : 0;
117 unsigned AGPRSpill =
118 AGPRPressure > AGPRThreshold ? (AGPRPressure - AGPRThreshold) : 0;
119
120 unsigned UnifiedPressure = getVGPRNum(/*UnifiedVGPRFile=*/UnifiedVGPRFile: true);
121 unsigned UnifiedSpill = UnifiedPressure > CombinedThreshold
122 ? (UnifiedPressure - CombinedThreshold)
123 : 0;
124
125 return std::max(a: UnifiedSpill, b: ArchSpill + AGPRSpill);
126 }
127
128 void inc(unsigned Reg,
129 LaneBitmask PrevMask,
130 LaneBitmask NewMask,
131 const MachineRegisterInfo &MRI);
132
133 bool higherOccupancy(const GCNSubtarget &ST, const GCNRegPressure &O,
134 unsigned DynamicVGPRBlockSize) const {
135 return getOccupancy(ST, DynamicVGPRBlockSize) >
136 O.getOccupancy(ST, DynamicVGPRBlockSize);
137 }
138
139 /// Compares \p this GCNRegpressure to \p O, returning true if \p this is
140 /// less. Since GCNRegpressure contains different types of pressures, and due
141 /// to target-specific pecularities (e.g. we care about occupancy rather than
142 /// raw register usage), we determine if \p this GCNRegPressure is less than
143 /// \p O based on the following tiered comparisons (in order order of
144 /// precedence):
145 /// 1. Better occupancy
146 /// 2. Less spilling (first preference to VGPR spills, then to SGPR spills)
147 /// 3. Less tuple register pressure (first preference to VGPR tuples if we
148 /// determine that SGPR pressure is not important)
149 /// 4. Less raw register pressure (first preference to VGPR tuples if we
150 /// determine that SGPR pressure is not important)
151 bool less(const MachineFunction &MF, const GCNRegPressure &O,
152 unsigned MaxOccupancy = std::numeric_limits<unsigned>::max()) const;
153
154 bool operator==(const GCNRegPressure &O) const { return Value == O.Value; }
155
156 bool operator!=(const GCNRegPressure &O) const {
157 return !(*this == O);
158 }
159
160 GCNRegPressure &operator+=(const GCNRegPressure &RHS) {
161 for (unsigned I = 0; I < ValueArraySize; ++I)
162 Value[I] += RHS.Value[I];
163 return *this;
164 }
165
166 GCNRegPressure &operator-=(const GCNRegPressure &RHS) {
167 for (unsigned I = 0; I < ValueArraySize; ++I)
168 Value[I] -= RHS.Value[I];
169 return *this;
170 }
171
172 void dump() const;
173
174 static RegKind getRegKind(unsigned Reg, const MachineRegisterInfo &MRI) {
175 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
176 const SIRegisterInfo *STI = static_cast<const SIRegisterInfo *>(TRI);
177 return (RegKind)getRegKind(RC: MRI.getRegClass(Reg), STI);
178 }
179
180private:
181 static constexpr unsigned ValueArraySize = TOTAL_KINDS * 2;
182
183 /// Pressure for all register kinds (first all regular registers kinds, then
184 /// all tuple register kinds).
185 std::array<unsigned, ValueArraySize> Value;
186
187 static unsigned getRegKind(const TargetRegisterClass *RC,
188 const SIRegisterInfo *STI);
189
190 friend GCNRegPressure max(const GCNRegPressure &P1,
191 const GCNRegPressure &P2);
192
193 friend Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST,
194 unsigned DynamicVGPRBlockSize);
195};
196
197inline GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2) {
198 GCNRegPressure Res;
199 for (unsigned I = 0; I < GCNRegPressure::ValueArraySize; ++I)
200 Res.Value[I] = std::max(a: P1.Value[I], b: P2.Value[I]);
201 return Res;
202}
203
204inline GCNRegPressure operator+(const GCNRegPressure &P1,
205 const GCNRegPressure &P2) {
206 GCNRegPressure Sum = P1;
207 Sum += P2;
208 return Sum;
209}
210
211inline GCNRegPressure operator-(const GCNRegPressure &P1,
212 const GCNRegPressure &P2) {
213 GCNRegPressure Diff = P1;
214 Diff -= P2;
215 return Diff;
216}
217
218////////////////////////////////////////////////////////////////////////////////
219// GCNRPTarget
220
221/// Models a register pressure target, allowing to evaluate and track register
222/// savings against that target from a starting \ref GCNRegPressure.
223class GCNRPTarget {
224public:
225 /// Sets up the target such that the register pressure starting at \p RP does
226 /// not show register spilling on function \p MF (w.r.t. the function's
227 /// mininum target occupancy).
228 GCNRPTarget(const MachineFunction &MF, const GCNRegPressure &RP);
229
230 /// Sets up the target such that the register pressure starting at \p RP does
231 /// not use more than \p NumSGPRs SGPRs and \p NumVGPRs VGPRs on function \p
232 /// MF.
233 GCNRPTarget(unsigned NumSGPRs, unsigned NumVGPRs, const MachineFunction &MF,
234 const GCNRegPressure &RP);
235
236 /// Sets up the target such that the register pressure starting at \p RP does
237 /// not prevent achieving an occupancy of at least \p Occupancy on function
238 /// \p MF.
239 GCNRPTarget(unsigned Occupancy, const MachineFunction &MF,
240 const GCNRegPressure &RP);
241
242 /// Changes the target (same semantics as constructor).
243 void setTarget(unsigned NumSGPRs, unsigned NumVGPRs);
244
245 const GCNRegPressure &getCurrentRP() const { return RP; }
246
247 void setRP(const GCNRegPressure &NewRP) { RP = NewRP; }
248
249 /// Determines whether saving virtual register \p Reg will be beneficial
250 /// towards achieving the RP target.
251 bool isSaveBeneficial(Register Reg) const;
252
253 /// Returns whether the benefit that saving \p SaveRP represents will be
254 /// beneficial towards achieving the RP target.
255 bool isSaveBeneficial(const GCNRegPressure &SaveRP) const;
256
257 /// Saves virtual register \p Reg with lanemask \p Mask.
258 void saveReg(Register Reg, LaneBitmask Mask, const MachineRegisterInfo &MRI) {
259 RP.inc(Reg, PrevMask: Mask, NewMask: LaneBitmask::getNone(), MRI);
260 }
261
262 /// Returns the benefit towards achieving the RP target that saving \p SaveRP
263 /// represents, in total number of registers saved across all classes.
264 unsigned getNumRegsBenefit(const GCNRegPressure &SaveRP) const;
265
266 /// Saves a total pressure of \p SaveRP.
267 void saveRP(const GCNRegPressure &SaveRP) {
268 assert(!RP.less(MF, SaveRP) && "saving beyond current RP");
269 RP -= SaveRP;
270 }
271
272 /// Whether \p TestRP is at or below the defined pressure target.
273 bool satisfied(const GCNRegPressure &TestRP) const;
274 /// Whether the current RP is at or below the defined pressure target.
275 bool satisfied() const { return satisfied(TestRP: RP); }
276 bool hasVectorRegisterExcess() const;
277
278 unsigned getMaxSGPRs() const { return MaxSGPRs; }
279 unsigned getMaxVGPRs() const {
280 return UnifiedRF ? MaxUnifiedVGPRs : MaxVGPRs;
281 }
282
283#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
284 friend raw_ostream &operator<<(raw_ostream &OS, const GCNRPTarget &Target) {
285 OS << "Actual/Target: " << Target.RP.getSGPRNum() << '/' << Target.MaxSGPRs
286 << " SGPRs, " << Target.RP.getArchVGPRNum() << '/' << Target.MaxVGPRs
287 << " ArchVGPRs, " << Target.RP.getAGPRNum() << '/' << Target.MaxVGPRs
288 << " AGPRs";
289
290 if (Target.MaxUnifiedVGPRs) {
291 OS << ", " << Target.RP.getVGPRNum(true) << '/' << Target.MaxUnifiedVGPRs
292 << " VGPRs (unified)";
293 }
294 return OS;
295 }
296#endif
297
298private:
299 const MachineFunction &MF;
300 const bool UnifiedRF;
301
302 /// Current register pressure.
303 GCNRegPressure RP;
304
305 /// Target number of SGPRs.
306 unsigned MaxSGPRs = 0;
307 /// Target number of ArchVGPRs and AGPRs.
308 unsigned MaxVGPRs = 0;
309 /// Target number of overall VGPRs for subtargets with unified RFs. Always 0
310 /// for subtargets with non-unified RFs.
311 unsigned MaxUnifiedVGPRs = 0;
312
313 GCNRPTarget(const GCNRegPressure &RP, const MachineFunction &MF)
314 : MF(MF), UnifiedRF(MF.getSubtarget<GCNSubtarget>().hasGFX90AInsts()),
315 RP(RP) {}
316};
317
318///////////////////////////////////////////////////////////////////////////////
319// GCNRPTracker
320
321class GCNRPTracker {
322public:
323 using LiveRegSet = DenseMap<unsigned, LaneBitmask>;
324
325protected:
326 const LiveIntervals &LIS;
327 LiveRegSet LiveRegs;
328 GCNRegPressure CurPressure, MaxPressure;
329 const MachineInstr *LastTrackedMI = nullptr;
330 mutable const MachineRegisterInfo *MRI = nullptr;
331
332 GCNRPTracker(const LiveIntervals &LIS_) : LIS(LIS_) {}
333
334 /// Resets tracker before or \p After the provided \p MI, which can be a debug
335 /// instruction.
336 void reset(const MachineInstr &MI, bool After);
337
338 /// Resets tracker at the start or \p End of the \p MBB.
339 void reset(const MachineBasicBlock &MBB, bool End);
340
341 /// Resets tracker at the specified slot index \p SI.
342 void reset(const MachineRegisterInfo &MRI, SlotIndex SI);
343
344 /// Mostly copy/paste from CodeGen/RegisterPressure.cpp
345 void bumpDeadDefs(ArrayRef<VRegMaskOrUnit> DeadDefs);
346
347 LaneBitmask getLastUsedLanes(Register Reg, SlotIndex Pos) const;
348
349public:
350 /// Resets tracker with the provided \p LiveRegs.
351 void reset(const MachineRegisterInfo &MRI, const LiveRegSet &LiveRegs);
352
353 // live regs for the current state
354 const decltype(LiveRegs) &getLiveRegs() const { return LiveRegs; }
355 const MachineInstr *getLastTrackedMI() const { return LastTrackedMI; }
356
357 void clearMaxPressure() { MaxPressure.clear(); }
358
359 GCNRegPressure getPressure() const { return CurPressure; }
360
361 decltype(LiveRegs) moveLiveRegs() {
362 return std::move(LiveRegs);
363 }
364};
365
366GCNRPTracker::LiveRegSet
367getLiveRegs(SlotIndex SI, const LiveIntervals &LIS,
368 const MachineRegisterInfo &MRI,
369 GCNRegPressure::RegKind RegKind = GCNRegPressure::TOTAL_KINDS);
370
371////////////////////////////////////////////////////////////////////////////////
372// GCNUpwardRPTracker
373
374class GCNUpwardRPTracker : public GCNRPTracker {
375public:
376 GCNUpwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
377
378 using GCNRPTracker::reset;
379
380 /// Resets tracker to the point just after \p MI (in program order), which can
381 /// be a debug instruction.
382 void reset(const MachineInstr &MI) { reset(MI, /*After=*/After: true); }
383
384 /// Move to the state of RP just before the \p MI . If \p UseInternalIterator
385 /// is set, also update the internal iterators. Setting \p UseInternalIterator
386 /// to false allows for an externally managed iterator / program order.
387 void recede(const MachineInstr &MI);
388
389 /// \p returns whether the tracker's state after receding MI corresponds
390 /// to reported by LIS.
391 bool isValid() const;
392
393 const GCNRegPressure &getMaxPressure() const { return MaxPressure; }
394
395 void resetMaxPressure() { MaxPressure = CurPressure; }
396
397 GCNRegPressure getMaxPressureAndReset() {
398 GCNRegPressure RP = MaxPressure;
399 resetMaxPressure();
400 return RP;
401 }
402};
403
404////////////////////////////////////////////////////////////////////////////////
405// GCNDownwardRPTracker
406
407class GCNDownwardRPTracker : public GCNRPTracker {
408 // Last position of reset or advanceBeforeNext
409 MachineBasicBlock::const_iterator NextMI;
410
411 MachineBasicBlock::const_iterator MBBEnd;
412
413public:
414 GCNDownwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
415
416 using GCNRPTracker::reset;
417
418 MachineBasicBlock::const_iterator getNext() const { return NextMI; }
419
420 /// \p return MaxPressure and clear it.
421 GCNRegPressure moveMaxPressure() {
422 auto Res = MaxPressure;
423 MaxPressure.clear();
424 return Res;
425 }
426
427 /// Reset tracker to the point before the \p MI filling \p LiveRegs upon this
428 /// point using LIS. \p End must be between the MI and the end of its parent
429 /// block (inclusive). \p returns false if the range [MI, End) is empty except
430 /// debug values.
431 bool reset(const MachineInstr &MI, MachineBasicBlock::const_iterator End,
432 const LiveRegSet *LiveRegs = nullptr);
433
434 /// Move to the state right before the next MI or after the end of MBB.
435 /// \p returns false if reached end of the block.
436 /// If \p UseInternalIterator is true, then internal iterators are used and
437 /// set to process in program order. If \p UseInternalIterator is false, then
438 /// it is assumed that the tracker is using an externally managed iterator,
439 /// and advance* calls will not update the state of the iterator. In such
440 /// cases, the tracker will move to the state right before the provided \p MI
441 /// and use LIS for RP calculations.
442 bool advanceBeforeNext(MachineInstr *MI = nullptr,
443 bool UseInternalIterator = true);
444
445 /// Move to the state at the MI, advanceBeforeNext has to be called first.
446 /// If \p UseInternalIterator is true, then internal iterators are used and
447 /// set to process in program order. If \p UseInternalIterator is false, then
448 /// it is assumed that the tracker is using an externally managed iterator,
449 /// and advance* calls will not update the state of the iterator. In such
450 /// cases, the tracker will move to the state at the provided \p MI .
451 void advanceToNext(MachineInstr *MI = nullptr,
452 bool UseInternalIterator = true);
453
454 /// Move to the state at the next MI. \p returns false if reached end of
455 /// block. If \p UseInternalIterator is true, then internal iterators are used
456 /// and set to process in program order. If \p UseInternalIterator is false,
457 /// then it is assumed that the tracker is using an externally managed
458 /// iterator, and advance* calls will not update the state of the iterator. In
459 /// such cases, the tracker will move to the state right before the provided
460 /// \p MI and use LIS for RP calculations.
461 bool advance(MachineInstr *MI = nullptr, bool UseInternalIterator = true);
462
463 /// Advance instructions until before \p End using internal iterators to
464 /// process instructions in program order. Returns whether iterators actually
465 /// had to advance to reach \p End.
466 bool advance(MachineBasicBlock::const_iterator End);
467
468 /// Reset tracker to \p Begin (filling \p LiveRegs upon this point using LIS)
469 /// and advance to \p End, which must be between \p Begin and the end of its
470 /// parent block (inclusive). \p returns false if the range [Begin, End) is
471 /// empty except debug values.
472 bool advance(MachineBasicBlock::const_iterator Begin,
473 MachineBasicBlock::const_iterator End,
474 const LiveRegSet *LiveRegsCopy = nullptr);
475
476 /// Mostly copy/paste from CodeGen/RegisterPressure.cpp
477 /// Calculate the impact \p MI will have on CurPressure and \return the
478 /// speculated pressure. In order to support RP Speculation, this does not
479 /// rely on the implicit program ordering in the LiveIntervals.
480 GCNRegPressure bumpDownwardPressure(const MachineInstr *MI,
481 const SIRegisterInfo *TRI) const;
482};
483
484/// \returns the LaneMask of live lanes of \p Reg at position \p SI. Only the
485/// active lanes of \p LaneMaskFilter will be set in the return value. This is
486/// used, for example, to limit the live lanes to a specific subreg when
487/// calculating use masks.
488LaneBitmask getLiveLaneMask(unsigned Reg, SlotIndex SI,
489 const LiveIntervals &LIS,
490 const MachineRegisterInfo &MRI,
491 LaneBitmask LaneMaskFilter = LaneBitmask::getAll());
492
493LaneBitmask getLiveLaneMask(const LiveInterval &LI, SlotIndex SI,
494 const MachineRegisterInfo &MRI,
495 LaneBitmask LaneMaskFilter = LaneBitmask::getAll());
496
497/// creates a map MachineInstr -> LiveRegSet
498/// R - range of iterators on instructions
499/// After - upon entry or exit of every instruction
500/// Note: there is no entry in the map for instructions with empty live reg set
501/// Complexity = O(NumVirtRegs * averageLiveRangeSegmentsPerReg * lg(R))
502template <typename Range>
503DenseMap<MachineInstr*, GCNRPTracker::LiveRegSet>
504getLiveRegMap(Range &&R, bool After, LiveIntervals &LIS) {
505 std::vector<SlotIndex> Indexes;
506 Indexes.reserve(n: llvm::size(R));
507 auto &SII = *LIS.getSlotIndexes();
508 for (MachineInstr *I : R) {
509 auto SI = SII.getInstructionIndex(MI: *I);
510 Indexes.push_back(x: After ? SI.getDeadSlot() : SI.getBaseIndex());
511 }
512 llvm::sort(C&: Indexes);
513
514 auto &MRI = (*R.begin())->getMF()->getRegInfo();
515 DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> LiveRegMap;
516 SmallVector<SlotIndex, 32> LiveIdxs, SRLiveIdxs;
517 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
518 auto Reg = Register::index2VirtReg(Index: I);
519 if (!LIS.hasInterval(Reg))
520 continue;
521 auto &LI = LIS.getInterval(Reg);
522 LiveIdxs.clear();
523 if (!LI.findIndexesLiveAt(R&: Indexes, O: std::back_inserter(x&: LiveIdxs)))
524 continue;
525 if (!LI.hasSubRanges()) {
526 for (auto SI : LiveIdxs)
527 LiveRegMap[SII.getInstructionFromIndex(index: SI)][Reg] =
528 MRI.getMaxLaneMaskForVReg(Reg);
529 } else
530 for (const auto &S : LI.subranges()) {
531 // constrain search for subranges by indexes live at main range
532 SRLiveIdxs.clear();
533 S.findIndexesLiveAt(R&: LiveIdxs, O: std::back_inserter(x&: SRLiveIdxs));
534 for (auto SI : SRLiveIdxs)
535 LiveRegMap[SII.getInstructionFromIndex(index: SI)][Reg] |= S.LaneMask;
536 }
537 }
538 return LiveRegMap;
539}
540
541inline GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI,
542 const LiveIntervals &LIS) {
543 return getLiveRegs(SI: LIS.getInstructionIndex(Instr: MI).getDeadSlot(), LIS,
544 MRI: MI.getMF()->getRegInfo());
545}
546
547inline GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI,
548 const LiveIntervals &LIS) {
549 return getLiveRegs(SI: LIS.getInstructionIndex(Instr: MI).getBaseIndex(), LIS,
550 MRI: MI.getMF()->getRegInfo());
551}
552
553template <typename Range>
554GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI,
555 Range &&LiveRegs) {
556 GCNRegPressure Res;
557 for (const auto &RM : LiveRegs)
558 Res.inc(Reg: RM.first, PrevMask: LaneBitmask::getNone(), NewMask: RM.second, MRI);
559 return Res;
560}
561
562bool isEqual(const GCNRPTracker::LiveRegSet &S1,
563 const GCNRPTracker::LiveRegSet &S2);
564
565Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST = nullptr,
566 unsigned DynamicVGPRBlockSize = 0);
567
568Printable print(const GCNRPTracker::LiveRegSet &LiveRegs,
569 const MachineRegisterInfo &MRI);
570
571Printable reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
572 const GCNRPTracker::LiveRegSet &TrackedL,
573 const TargetRegisterInfo *TRI, StringRef Pfx = " ");
574
575struct GCNRegPressurePrinter : public MachineFunctionPass {
576 static char ID;
577
578public:
579 GCNRegPressurePrinter() : MachineFunctionPass(ID) {}
580
581 bool runOnMachineFunction(MachineFunction &MF) override;
582
583 void getAnalysisUsage(AnalysisUsage &AU) const override {
584 AU.addRequired<LiveIntervalsWrapperPass>();
585 AU.setPreservesAll();
586 MachineFunctionPass::getAnalysisUsage(AU);
587 }
588};
589
590LLVM_ABI void dumpMaxRegPressure(MachineFunction &MF,
591 GCNRegPressure::RegKind Kind,
592 LiveIntervals &LIS,
593 const MachineLoopInfo *MLI);
594
595} // end namespace llvm
596
597#endif // LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
598