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