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 /// Saves virtual register \p Reg with lanemask \p Mask.
254 void saveReg(Register Reg, LaneBitmask Mask, const MachineRegisterInfo &MRI) {
255 RP.inc(Reg, PrevMask: Mask, NewMask: LaneBitmask::getNone(), MRI);
256 }
257
258 /// Returns the benefit towards achieving the RP target that saving \p SaveRP
259 /// represents, in total number of registers saved across all classes.
260 unsigned getNumRegsBenefit(const GCNRegPressure &SaveRP) const;
261
262 /// Saves a total pressure of \p SaveRP.
263 void saveRP(const GCNRegPressure &SaveRP) {
264 assert(!RP.less(MF, SaveRP) && "saving beyond current RP");
265 RP -= SaveRP;
266 }
267
268 /// Whether \p TestRP is at or below the defined pressure target.
269 bool satisfied(const GCNRegPressure &TestRP) const;
270 /// Whether the current RP is at or below the defined pressure target.
271 bool satisfied() const { return satisfied(TestRP: RP); }
272 bool hasVectorRegisterExcess() const;
273
274 unsigned getMaxSGPRs() const { return MaxSGPRs; }
275 unsigned getMaxVGPRs() const {
276 return UnifiedRF ? MaxUnifiedVGPRs : MaxVGPRs;
277 }
278
279#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
280 friend raw_ostream &operator<<(raw_ostream &OS, const GCNRPTarget &Target) {
281 OS << "Actual/Target: " << Target.RP.getSGPRNum() << '/' << Target.MaxSGPRs
282 << " SGPRs, " << Target.RP.getArchVGPRNum() << '/' << Target.MaxVGPRs
283 << " ArchVGPRs, " << Target.RP.getAGPRNum() << '/' << Target.MaxVGPRs
284 << " AGPRs";
285
286 if (Target.MaxUnifiedVGPRs) {
287 OS << ", " << Target.RP.getVGPRNum(true) << '/' << Target.MaxUnifiedVGPRs
288 << " VGPRs (unified)";
289 }
290 return OS;
291 }
292#endif
293
294private:
295 const MachineFunction &MF;
296 const bool UnifiedRF;
297
298 /// Current register pressure.
299 GCNRegPressure RP;
300
301 /// Target number of SGPRs.
302 unsigned MaxSGPRs;
303 /// Target number of ArchVGPRs and AGPRs.
304 unsigned MaxVGPRs;
305 /// Target number of overall VGPRs for subtargets with unified RFs. Always 0
306 /// for subtargets with non-unified RFs.
307 unsigned MaxUnifiedVGPRs;
308
309 GCNRPTarget(const GCNRegPressure &RP, const MachineFunction &MF)
310 : MF(MF), UnifiedRF(MF.getSubtarget<GCNSubtarget>().hasGFX90AInsts()),
311 RP(RP) {}
312};
313
314///////////////////////////////////////////////////////////////////////////////
315// GCNRPTracker
316
317class GCNRPTracker {
318public:
319 using LiveRegSet = DenseMap<unsigned, LaneBitmask>;
320
321protected:
322 const LiveIntervals &LIS;
323 LiveRegSet LiveRegs;
324 GCNRegPressure CurPressure, MaxPressure;
325 const MachineInstr *LastTrackedMI = nullptr;
326 mutable const MachineRegisterInfo *MRI = nullptr;
327
328 GCNRPTracker(const LiveIntervals &LIS_) : LIS(LIS_) {}
329
330 void reset(const MachineInstr &MI, const LiveRegSet *LiveRegsCopy,
331 bool After);
332
333 /// Mostly copy/paste from CodeGen/RegisterPressure.cpp
334 void bumpDeadDefs(ArrayRef<VRegMaskOrUnit> DeadDefs);
335
336 LaneBitmask getLastUsedLanes(Register Reg, SlotIndex Pos) const;
337
338public:
339 // reset tracker and set live register set to the specified value.
340 void reset(const MachineRegisterInfo &MRI_, const LiveRegSet &LiveRegs_);
341 // live regs for the current state
342 const decltype(LiveRegs) &getLiveRegs() const { return LiveRegs; }
343 const MachineInstr *getLastTrackedMI() const { return LastTrackedMI; }
344
345 void clearMaxPressure() { MaxPressure.clear(); }
346
347 GCNRegPressure getPressure() const { return CurPressure; }
348
349 decltype(LiveRegs) moveLiveRegs() {
350 return std::move(LiveRegs);
351 }
352};
353
354GCNRPTracker::LiveRegSet
355getLiveRegs(SlotIndex SI, const LiveIntervals &LIS,
356 const MachineRegisterInfo &MRI,
357 GCNRegPressure::RegKind RegKind = GCNRegPressure::TOTAL_KINDS);
358
359////////////////////////////////////////////////////////////////////////////////
360// GCNUpwardRPTracker
361
362class GCNUpwardRPTracker : public GCNRPTracker {
363public:
364 GCNUpwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
365
366 using GCNRPTracker::reset;
367
368 /// reset tracker at the specified slot index \p SI.
369 void reset(const MachineRegisterInfo &MRI, SlotIndex SI) {
370 GCNRPTracker::reset(MRI_: MRI, LiveRegs_: llvm::getLiveRegs(SI, LIS, MRI));
371 }
372
373 /// reset tracker to the end of the \p MBB.
374 void reset(const MachineBasicBlock &MBB) {
375 SlotIndex MBBLastSlot = LIS.getSlotIndexes()->getMBBLastIdx(MBB: &MBB);
376 reset(MRI: MBB.getParent()->getRegInfo(), SI: MBBLastSlot);
377 }
378
379 /// reset tracker to the point just after \p MI (in program order).
380 void reset(const MachineInstr &MI) {
381 reset(MRI: MI.getMF()->getRegInfo(), SI: LIS.getInstructionIndex(Instr: MI).getDeadSlot());
382 }
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
428 /// filling \p LiveRegs upon this point using LIS.
429 /// \p returns false if block is empty except debug values.
430 bool reset(const MachineInstr &MI, const LiveRegSet *LiveRegs = nullptr);
431
432 /// Move to the state right before the next MI or after the end of MBB.
433 /// \p returns false if reached end of the block.
434 /// If \p UseInternalIterator is true, then internal iterators are used and
435 /// set to process in program order. If \p UseInternalIterator is false, then
436 /// it is assumed that the tracker is using an externally managed iterator,
437 /// and advance* calls will not update the state of the iterator. In such
438 /// cases, the tracker will move to the state right before the provided \p MI
439 /// and use LIS for RP calculations.
440 bool advanceBeforeNext(MachineInstr *MI = nullptr,
441 bool UseInternalIterator = true);
442
443 /// Move to the state at the MI, advanceBeforeNext has to be called first.
444 /// If \p UseInternalIterator is true, then internal iterators are used and
445 /// set to process in program order. If \p UseInternalIterator is false, then
446 /// it is assumed that the tracker is using an externally managed iterator,
447 /// and advance* calls will not update the state of the iterator. In such
448 /// cases, the tracker will move to the state at the provided \p MI .
449 void advanceToNext(MachineInstr *MI = nullptr,
450 bool UseInternalIterator = true);
451
452 /// Move to the state at the next MI. \p returns false if reached end of
453 /// block. If \p UseInternalIterator is true, then internal iterators are used
454 /// and set to process in program order. If \p UseInternalIterator is false,
455 /// then it is assumed that the tracker is using an externally managed
456 /// iterator, and advance* calls will not update the state of the iterator. In
457 /// such cases, the tracker will move to the state right before the provided
458 /// \p MI and use LIS for RP calculations.
459 bool advance(MachineInstr *MI = nullptr, bool UseInternalIterator = true);
460
461 /// Advance instructions until before \p End.
462 bool advance(MachineBasicBlock::const_iterator End);
463
464 /// Reset to \p Begin and advance to \p End.
465 bool advance(MachineBasicBlock::const_iterator Begin,
466 MachineBasicBlock::const_iterator End,
467 const LiveRegSet *LiveRegsCopy = nullptr);
468
469 /// Mostly copy/paste from CodeGen/RegisterPressure.cpp
470 /// Calculate the impact \p MI will have on CurPressure and \return the
471 /// speculated pressure. In order to support RP Speculation, this does not
472 /// rely on the implicit program ordering in the LiveIntervals.
473 GCNRegPressure bumpDownwardPressure(const MachineInstr *MI,
474 const SIRegisterInfo *TRI) const;
475};
476
477/// \returns the LaneMask of live lanes of \p Reg at position \p SI. Only the
478/// active lanes of \p LaneMaskFilter will be set in the return value. This is
479/// used, for example, to limit the live lanes to a specific subreg when
480/// calculating use masks.
481LaneBitmask getLiveLaneMask(unsigned Reg, SlotIndex SI,
482 const LiveIntervals &LIS,
483 const MachineRegisterInfo &MRI,
484 LaneBitmask LaneMaskFilter = LaneBitmask::getAll());
485
486LaneBitmask getLiveLaneMask(const LiveInterval &LI, SlotIndex SI,
487 const MachineRegisterInfo &MRI,
488 LaneBitmask LaneMaskFilter = LaneBitmask::getAll());
489
490/// creates a map MachineInstr -> LiveRegSet
491/// R - range of iterators on instructions
492/// After - upon entry or exit of every instruction
493/// Note: there is no entry in the map for instructions with empty live reg set
494/// Complexity = O(NumVirtRegs * averageLiveRangeSegmentsPerReg * lg(R))
495template <typename Range>
496DenseMap<MachineInstr*, GCNRPTracker::LiveRegSet>
497getLiveRegMap(Range &&R, bool After, LiveIntervals &LIS) {
498 std::vector<SlotIndex> Indexes;
499 Indexes.reserve(n: llvm::size(R));
500 auto &SII = *LIS.getSlotIndexes();
501 for (MachineInstr *I : R) {
502 auto SI = SII.getInstructionIndex(MI: *I);
503 Indexes.push_back(x: After ? SI.getDeadSlot() : SI.getBaseIndex());
504 }
505 llvm::sort(C&: Indexes);
506
507 auto &MRI = (*R.begin())->getMF()->getRegInfo();
508 DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> LiveRegMap;
509 SmallVector<SlotIndex, 32> LiveIdxs, SRLiveIdxs;
510 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
511 auto Reg = Register::index2VirtReg(Index: I);
512 if (!LIS.hasInterval(Reg))
513 continue;
514 auto &LI = LIS.getInterval(Reg);
515 LiveIdxs.clear();
516 if (!LI.findIndexesLiveAt(R&: Indexes, O: std::back_inserter(x&: LiveIdxs)))
517 continue;
518 if (!LI.hasSubRanges()) {
519 for (auto SI : LiveIdxs)
520 LiveRegMap[SII.getInstructionFromIndex(index: SI)][Reg] =
521 MRI.getMaxLaneMaskForVReg(Reg);
522 } else
523 for (const auto &S : LI.subranges()) {
524 // constrain search for subranges by indexes live at main range
525 SRLiveIdxs.clear();
526 S.findIndexesLiveAt(R&: LiveIdxs, O: std::back_inserter(x&: SRLiveIdxs));
527 for (auto SI : SRLiveIdxs)
528 LiveRegMap[SII.getInstructionFromIndex(index: SI)][Reg] |= S.LaneMask;
529 }
530 }
531 return LiveRegMap;
532}
533
534inline GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI,
535 const LiveIntervals &LIS) {
536 return getLiveRegs(SI: LIS.getInstructionIndex(Instr: MI).getDeadSlot(), LIS,
537 MRI: MI.getMF()->getRegInfo());
538}
539
540inline GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI,
541 const LiveIntervals &LIS) {
542 return getLiveRegs(SI: LIS.getInstructionIndex(Instr: MI).getBaseIndex(), LIS,
543 MRI: MI.getMF()->getRegInfo());
544}
545
546template <typename Range>
547GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI,
548 Range &&LiveRegs) {
549 GCNRegPressure Res;
550 for (const auto &RM : LiveRegs)
551 Res.inc(Reg: RM.first, PrevMask: LaneBitmask::getNone(), NewMask: RM.second, MRI);
552 return Res;
553}
554
555bool isEqual(const GCNRPTracker::LiveRegSet &S1,
556 const GCNRPTracker::LiveRegSet &S2);
557
558Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST = nullptr,
559 unsigned DynamicVGPRBlockSize = 0);
560
561Printable print(const GCNRPTracker::LiveRegSet &LiveRegs,
562 const MachineRegisterInfo &MRI);
563
564Printable reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
565 const GCNRPTracker::LiveRegSet &TrackedL,
566 const TargetRegisterInfo *TRI, StringRef Pfx = " ");
567
568struct GCNRegPressurePrinter : public MachineFunctionPass {
569 static char ID;
570
571public:
572 GCNRegPressurePrinter() : MachineFunctionPass(ID) {}
573
574 bool runOnMachineFunction(MachineFunction &MF) override;
575
576 void getAnalysisUsage(AnalysisUsage &AU) const override {
577 AU.addRequired<LiveIntervalsWrapperPass>();
578 AU.setPreservesAll();
579 MachineFunctionPass::getAnalysisUsage(AU);
580 }
581};
582
583LLVM_ABI void dumpMaxRegPressure(MachineFunction &MF,
584 GCNRegPressure::RegKind Kind,
585 LiveIntervals &LIS,
586 const MachineLoopInfo *MLI);
587
588} // end namespace llvm
589
590#endif // LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
591