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 const MachineInstr *LastTrackedMI = nullptr;
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 { return LastTrackedMI; }
340
341 void clearMaxPressure() { MaxPressure.clear(); }
342
343 const GCNRegPressure &getMaxPressure() const { return MaxPressure; }
344
345 void resetMaxPressure() { MaxPressure = CurPressure; }
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(LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
365
366 using GCNRPTracker::reset;
367
368 /// Resets tracker to the point just after \p MI (in program order), which can
369 /// be a debug instruction.
370 void reset(const MachineInstr &MI) { reset(MI, /*After=*/After: true); }
371
372 /// Move to the state of RP just before the \p MI . If \p UseInternalIterator
373 /// is set, also update the internal iterators. Setting \p UseInternalIterator
374 /// to false allows for an externally managed iterator / program order.
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
391class GCNDownwardRPTracker : public GCNRPTracker {
392 // Last position of reset or advanceBeforeNext
393 MachineBasicBlock::const_iterator NextMI;
394
395 MachineBasicBlock::const_iterator MBBEnd;
396
397 /// Drop the lanes of \p Reg that are no longer live at \p SI, decreasing
398 /// CurPressure accordingly. \p Reg must be a virtual register that is
399 /// currently tracked as live.
400 void retireVirtReg(Register Reg, SlotIndex SI);
401
402public:
403 GCNDownwardRPTracker(LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
404
405 using GCNRPTracker::reset;
406
407 MachineBasicBlock::const_iterator getNext() const { return NextMI; }
408
409 /// \p return MaxPressure and clear it.
410 GCNRegPressure moveMaxPressure() {
411 auto Res = MaxPressure;
412 MaxPressure.clear();
413 return Res;
414 }
415
416 /// Reset tracker to the point before the \p MI filling \p LiveRegs upon this
417 /// point using LIS. \p End must be between the MI and the end of its parent
418 /// block (inclusive). \p returns false if the range [MI, End) is empty except
419 /// debug values.
420 bool reset(const MachineInstr &MI, MachineBasicBlock::const_iterator End,
421 const LiveRegSet *LiveRegs = nullptr);
422
423 /// Move to the state right before the next MI or after the end of MBB.
424 /// \p returns false if reached end of the block.
425 /// If \p UseInternalIterator is true, then internal iterators are used and
426 /// set to process in program order. If \p UseInternalIterator is false, then
427 /// it is assumed that the tracker is using an externally managed iterator,
428 /// and advance* calls will not update the state of the iterator. In such
429 /// cases, the tracker will move to the state right before the provided \p MI
430 /// and use LIS for RP calculations.
431 bool advanceBeforeNext(MachineInstr *MI = nullptr,
432 bool UseInternalIterator = true);
433
434 /// Move to the state at the MI, advanceBeforeNext has to be called first.
435 /// If \p UseInternalIterator is true, then internal iterators are used and
436 /// set to process in program order. If \p UseInternalIterator is false, then
437 /// it is assumed that the tracker is using an externally managed iterator,
438 /// and advance* calls will not update the state of the iterator. In such
439 /// cases, the tracker will move to the state at the provided \p MI .
440 void advanceToNext(MachineInstr *MI = nullptr,
441 bool UseInternalIterator = true);
442
443 /// Move to the state at the next MI. \p returns false if reached end of
444 /// block. If \p UseInternalIterator is true, then internal iterators are used
445 /// and set to process in program order. If \p UseInternalIterator is false,
446 /// then it is assumed that the tracker is using an externally managed
447 /// iterator, and advance* calls will not update the state of the iterator. In
448 /// such cases, the tracker will move to the state right before the provided
449 /// \p MI and use LIS for RP calculations.
450 bool advance(MachineInstr *MI = nullptr, bool UseInternalIterator = true);
451
452 /// Advance instructions until before \p End using internal iterators to
453 /// process instructions in program order. Returns whether iterators actually
454 /// had to advance to reach \p End.
455 bool advance(MachineBasicBlock::const_iterator End);
456
457 /// Reset tracker to \p Begin (filling \p LiveRegs upon this point using LIS)
458 /// and advance to \p End, which must be between \p Begin and the end of its
459 /// parent block (inclusive). \p returns false if the range [Begin, End) is
460 /// empty except debug values.
461 bool advance(MachineBasicBlock::const_iterator Begin,
462 MachineBasicBlock::const_iterator End,
463 const LiveRegSet *LiveRegsCopy = nullptr);
464
465 /// Mostly copy/paste from CodeGen/RegisterPressure.cpp
466 /// Calculate the impact \p MI will have on CurPressure and \return the
467 /// speculated pressure. In order to support RP Speculation, this does not
468 /// rely on the implicit program ordering in the LiveIntervals.
469 GCNRegPressure bumpDownwardPressure(const MachineInstr *MI,
470 const SIRegisterInfo *TRI) const;
471};
472
473/// \returns the LaneMask of live lanes of \p Reg at position \p SI. Only the
474/// active lanes of \p LaneMaskFilter will be set in the return value. This is
475/// used, for example, to limit the live lanes to a specific subreg when
476/// calculating use masks.
477LaneBitmask getLiveLaneMask(unsigned Reg, SlotIndex SI,
478 const LiveIntervals &LIS,
479 const MachineRegisterInfo &MRI,
480 LaneBitmask LaneMaskFilter = LaneBitmask::getAll());
481
482LaneBitmask getLiveLaneMask(const LiveInterval &LI, SlotIndex SI,
483 const MachineRegisterInfo &MRI,
484 LaneBitmask LaneMaskFilter = LaneBitmask::getAll());
485
486/// creates a map MachineInstr -> LiveRegSet
487/// R - range of iterators on instructions
488/// After - upon entry or exit of every instruction
489/// Note: there is no entry in the map for instructions with empty live reg set
490/// Complexity = O(NumVirtRegs * averageLiveRangeSegmentsPerReg * lg(R))
491template <typename Range>
492DenseMap<MachineInstr*, GCNRPTracker::LiveRegSet>
493getLiveRegMap(Range &&R, bool After, LiveIntervals &LIS) {
494 std::vector<SlotIndex> Indexes;
495 Indexes.reserve(n: llvm::size(R));
496 auto &SII = *LIS.getSlotIndexes();
497 for (MachineInstr *I : R) {
498 auto SI = SII.getInstructionIndex(MI: *I);
499 Indexes.push_back(x: After ? SI.getDeadSlot() : SI.getBaseIndex());
500 }
501 llvm::sort(C&: Indexes);
502
503 auto &MRI = (*R.begin())->getMF()->getRegInfo();
504 DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> LiveRegMap;
505 SmallVector<SlotIndex, 32> LiveIdxs, SRLiveIdxs;
506 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
507 auto Reg = Register::index2VirtReg(Index: I);
508 if (!LIS.hasInterval(Reg))
509 continue;
510 auto &LI = LIS.getInterval(Reg);
511 LiveIdxs.clear();
512 if (!LI.findIndexesLiveAt(R&: Indexes, O: std::back_inserter(x&: LiveIdxs)))
513 continue;
514 if (!LI.hasSubRanges()) {
515 for (auto SI : LiveIdxs)
516 LiveRegMap[SII.getInstructionFromIndex(index: SI)][Reg] =
517 MRI.getMaxLaneMaskForVReg(Reg);
518 } else
519 for (const auto &S : LI.subranges()) {
520 // constrain search for subranges by indexes live at main range
521 SRLiveIdxs.clear();
522 S.findIndexesLiveAt(R&: LiveIdxs, O: std::back_inserter(x&: SRLiveIdxs));
523 for (auto SI : SRLiveIdxs)
524 LiveRegMap[SII.getInstructionFromIndex(index: SI)][Reg] |= S.LaneMask;
525 }
526 }
527 return LiveRegMap;
528}
529
530inline GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI,
531 const LiveIntervals &LIS) {
532 return getLiveRegs(SI: LIS.getInstructionIndex(Instr: MI).getDeadSlot(), LIS,
533 MRI: MI.getMF()->getRegInfo());
534}
535
536inline GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI,
537 const LiveIntervals &LIS) {
538 return getLiveRegs(SI: LIS.getInstructionIndex(Instr: MI).getBaseIndex(), LIS,
539 MRI: MI.getMF()->getRegInfo());
540}
541
542template <typename Range>
543GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI,
544 Range &&LiveRegs) {
545 GCNRegPressure Res;
546 for (const auto &RM : LiveRegs)
547 Res.inc(Reg: RM.first, PrevMask: LaneBitmask::getNone(), NewMask: RM.second, MRI);
548 return Res;
549}
550
551bool isEqual(const GCNRPTracker::LiveRegSet &S1,
552 const GCNRPTracker::LiveRegSet &S2);
553
554Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST = nullptr,
555 unsigned DynamicVGPRBlockSize = 0);
556
557Printable print(const GCNRPTracker::LiveRegSet &LiveRegs,
558 const MachineRegisterInfo &MRI);
559
560Printable reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
561 const GCNRPTracker::LiveRegSet &TrackedL,
562 const TargetRegisterInfo *TRI, StringRef Pfx = " ");
563
564struct GCNRegPressurePrinter : public MachineFunctionPass {
565 static char ID;
566
567public:
568 GCNRegPressurePrinter() : MachineFunctionPass(ID) {}
569
570 bool runOnMachineFunction(MachineFunction &MF) override;
571
572 void getAnalysisUsage(AnalysisUsage &AU) const override {
573 AU.addRequired<LiveIntervalsWrapperPass>();
574 AU.setPreservesAll();
575 MachineFunctionPass::getAnalysisUsage(AU);
576 }
577};
578
579LLVM_ABI void dumpMaxRegPressure(MachineFunction &MF,
580 GCNRegPressure::RegKind Kind,
581 LiveIntervals &LIS,
582 const MachineLoopInfo *MLI);
583
584/// Estimate VGPR pressure using greedy, non-splitting register allocation
585/// simulation, accounting for live interval interference.
586/// \param RegionBegin Start iterator of the region
587/// \param RegionEnd End iterator of the region
588/// \param LiveIns Live-in registers for the region
589/// \returns estimated VGPR pressure
590unsigned estimateGreedyVGPRPressure(
591 MachineBasicBlock::const_iterator RegionBegin,
592 MachineBasicBlock::const_iterator RegionEnd,
593 const GCNRPTracker::LiveRegSet &LiveIns, const LiveIntervals &LIS,
594 const MachineRegisterInfo &MRI, const SIRegisterInfo &TRI);
595
596} // end namespace llvm
597
598#endif // LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
599