LLVM 24.0.0git
GCNRegPressure.cpp
Go to the documentation of this file.
1//===- GCNRegPressure.cpp -------------------------------------------------===//
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 implements the GCNRegPressure class.
11///
12//===----------------------------------------------------------------------===//
13
14#include "GCNRegPressure.h"
15#include "AMDGPU.h"
17#include "llvm/ADT/SetVector.h"
22
23using namespace llvm;
24
25#define DEBUG_TYPE "machine-scheduler"
26
28 const GCNRPTracker::LiveRegSet &S2) {
29 if (S1.size() != S2.size())
30 return false;
31
32 for (const auto &P : S1) {
33 auto I = S2.find(P.first);
34 if (I == S2.end() || I->second != P.second)
35 return false;
36 }
37 return true;
38}
39
40///////////////////////////////////////////////////////////////////////////////
41// GCNRegPressure
42
44 const SIRegisterInfo *STI) {
45 return STI->isSGPRClass(RC)
46 ? SGPR
47 : (STI->isAGPRClass(RC)
48 ? AGPR
49 : (STI->isVectorSuperClass(RC) ? AVGPR : VGPR));
50}
51
52void GCNRegPressure::inc(unsigned Reg,
53 LaneBitmask PrevMask,
54 LaneBitmask NewMask,
55 const MachineRegisterInfo &MRI) {
56 unsigned NewNumCoveredRegs = SIRegisterInfo::getNumCoveredRegs(NewMask);
57 unsigned PrevNumCoveredRegs = SIRegisterInfo::getNumCoveredRegs(PrevMask);
58 if (NewNumCoveredRegs == PrevNumCoveredRegs)
59 return;
60
61 int Sign = 1;
62 if (NewMask < PrevMask) {
63 std::swap(NewMask, PrevMask);
64 std::swap(NewNumCoveredRegs, PrevNumCoveredRegs);
65 Sign = -1;
66 }
67 assert(PrevMask < NewMask && PrevNumCoveredRegs < NewNumCoveredRegs &&
68 "prev mask should always be lesser than new");
69
70 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
71 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
72 const SIRegisterInfo *STI = static_cast<const SIRegisterInfo *>(TRI);
73 unsigned RegKind = getRegKind(RC, STI);
74 if (TRI->getRegSizeInBits(*RC) != 32) {
75 // Reg is from a tuple register class.
76 if (PrevMask.none()) {
77 unsigned TupleIdx = TOTAL_KINDS + RegKind;
78 Value[TupleIdx] += Sign * TRI->getRegClassWeight(RC).RegWeight;
79 }
80 // Pressure scales with number of new registers covered by the new mask.
81 // Note when true16 is enabled, we can no longer safely use the following
82 // approach to calculate the difference in the number of 32-bit registers
83 // between two masks:
84 //
85 // Sign *= SIRegisterInfo::getNumCoveredRegs(~PrevMask & NewMask);
86 //
87 // The issue is that the mask calculation `~PrevMask & NewMask` doesn't
88 // properly account for partial usage of a 32-bit register when dealing with
89 // 16-bit registers.
90 //
91 // Consider this example:
92 // Assume PrevMask = 0b0010 and NewMask = 0b1111. Here, the correct register
93 // usage difference should be 1, because even though PrevMask uses only half
94 // of a 32-bit register, it should still be counted as a full register use.
95 // However, the mask calculation yields `~PrevMask & NewMask = 0b1101`, and
96 // calling `getNumCoveredRegs` returns 2 instead of 1. This incorrect
97 // calculation can lead to integer overflow when Sign = -1.
98 Sign *= NewNumCoveredRegs - PrevNumCoveredRegs;
99 }
100 Value[RegKind] += Sign;
101}
102
103namespace {
104struct RegExcess {
105 unsigned SGPR = 0;
106 unsigned VGPR = 0;
107 unsigned ArchVGPR = 0;
108 unsigned AGPR = 0;
109
110 bool anyExcess() const { return SGPR || VGPR || ArchVGPR || AGPR; }
111 bool hasVectorRegisterExcess() const { return VGPR || ArchVGPR || AGPR; }
112
113 RegExcess(const MachineFunction &MF, const GCNRegPressure &RP)
114 : RegExcess(MF, RP, GCNRPTarget(MF, RP)) {}
115 RegExcess(const MachineFunction &MF, const GCNRegPressure &RP,
116 const GCNRPTarget &Target) {
117 unsigned MaxSGPRs = Target.getMaxSGPRs();
118 unsigned MaxVGPRs = Target.getMaxVGPRs();
119
120 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
121 SGPR = std::max(static_cast<int>(RP.getSGPRNum() - MaxSGPRs), 0);
122
123 // The number of virtual VGPRs required to handle excess SGPR
124 unsigned WaveSize = ST.getWavefrontSize();
125 unsigned VGPRForSGPRSpills = divideCeil(SGPR, WaveSize);
126
127 unsigned MaxArchVGPRs = ST.getAddressableNumArchVGPRs();
128
129 // Unified excess pressure conditions, accounting for VGPRs used for SGPR
130 // spills
131 VGPR = std::max(static_cast<int>(RP.getVGPRNum(ST.hasGFX90AInsts()) +
132 VGPRForSGPRSpills - MaxVGPRs),
133 0);
134
135 unsigned ArchVGPRLimit = ST.hasGFX90AInsts() ? MaxArchVGPRs : MaxVGPRs;
136 // Arch VGPR excess pressure conditions, accounting for VGPRs used for SGPR
137 // spills
138 ArchVGPR = std::max(static_cast<int>(RP.getArchVGPRNum() +
139 VGPRForSGPRSpills - ArchVGPRLimit),
140 0);
141
142 // AGPR excess pressure conditions
143 AGPR = std::max(static_cast<int>(RP.getAGPRNum() - ArchVGPRLimit), 0);
144 }
145};
146} // namespace
147
149 unsigned MaxOccupancy) const {
150 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
151 unsigned DynamicVGPRBlockSize =
152 MF.getInfo<SIMachineFunctionInfo>()->getDynamicVGPRBlockSize();
153
154 const auto SGPROcc = std::min(MaxOccupancy,
155 ST.getOccupancyWithNumSGPRs(getSGPRNum()));
156 const auto VGPROcc = std::min(
157 MaxOccupancy, ST.getOccupancyWithNumVGPRs(getVGPRNum(ST.hasGFX90AInsts()),
158 DynamicVGPRBlockSize));
159 const auto OtherSGPROcc = std::min(MaxOccupancy,
160 ST.getOccupancyWithNumSGPRs(O.getSGPRNum()));
161 const auto OtherVGPROcc =
162 std::min(MaxOccupancy,
163 ST.getOccupancyWithNumVGPRs(O.getVGPRNum(ST.hasGFX90AInsts()),
164 DynamicVGPRBlockSize));
165
166 const auto Occ = std::min(SGPROcc, VGPROcc);
167 const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc);
168
169 // Give first precedence to the better occupancy.
170 if (Occ != OtherOcc)
171 return Occ > OtherOcc;
172
173 unsigned MaxVGPRs = ST.getMaxNumVGPRs(MF);
174
175 RegExcess Excess(MF, *this);
176 RegExcess OtherExcess(MF, O);
177
178 unsigned MaxArchVGPRs = ST.getAddressableNumArchVGPRs();
179
180 bool ExcessRP = Excess.anyExcess();
181 bool OtherExcessRP = OtherExcess.anyExcess();
182
183 // Give second precedence to the reduced number of spills to hold the register
184 // pressure.
185 if (ExcessRP || OtherExcessRP) {
186 // The difference in excess VGPR pressure, after including VGPRs used for
187 // SGPR spills
188 int VGPRDiff =
189 ((OtherExcess.VGPR + OtherExcess.ArchVGPR + OtherExcess.AGPR) -
190 (Excess.VGPR + Excess.ArchVGPR + Excess.AGPR));
191
192 int SGPRDiff = OtherExcess.SGPR - Excess.SGPR;
193
194 if (VGPRDiff != 0)
195 return VGPRDiff > 0;
196 if (SGPRDiff != 0) {
197 unsigned PureExcessVGPR =
198 std::max(static_cast<int>(getVGPRNum(ST.hasGFX90AInsts()) - MaxVGPRs),
199 0) +
200 std::max(static_cast<int>(getVGPRNum(false) - MaxArchVGPRs), 0);
201 unsigned OtherPureExcessVGPR =
202 std::max(
203 static_cast<int>(O.getVGPRNum(ST.hasGFX90AInsts()) - MaxVGPRs),
204 0) +
205 std::max(static_cast<int>(O.getVGPRNum(false) - MaxArchVGPRs), 0);
206
207 // If we have a special case where there is a tie in excess VGPR, but one
208 // of the pressures has VGPR usage from SGPR spills, prefer the pressure
209 // with SGPR spills.
210 if (PureExcessVGPR != OtherPureExcessVGPR)
211 return SGPRDiff < 0;
212 // If both pressures have the same excess pressure before and after
213 // accounting for SGPR spills, prefer fewer SGPR spills.
214 return SGPRDiff > 0;
215 }
216 }
217
218 bool SGPRImportant = SGPROcc < VGPROcc;
219 const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc;
220
221 // If both pressures disagree on what is more important compare vgprs.
222 if (SGPRImportant != OtherSGPRImportant) {
223 SGPRImportant = false;
224 }
225
226 // Give third precedence to lower register tuple pressure.
227 bool SGPRFirst = SGPRImportant;
228 for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) {
229 if (SGPRFirst) {
230 auto SW = getSGPRTuplesWeight();
231 auto OtherSW = O.getSGPRTuplesWeight();
232 if (SW != OtherSW)
233 return SW < OtherSW;
234 } else {
235 auto VW = getVGPRTuplesWeight();
236 auto OtherVW = O.getVGPRTuplesWeight();
237 if (VW != OtherVW)
238 return VW < OtherVW;
239 }
240 }
241
242 // Give final precedence to lower general RP.
243 return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()):
244 (getVGPRNum(ST.hasGFX90AInsts()) <
245 O.getVGPRNum(ST.hasGFX90AInsts()));
246}
247
249 unsigned DynamicVGPRBlockSize) {
250 return Printable([&RP, ST, DynamicVGPRBlockSize](raw_ostream &OS) {
251 OS << "VGPRs: " << RP.getArchVGPRNum() << ' '
252 << "AGPRs: " << RP.getAGPRNum();
253 if (ST)
254 OS << "(O"
255 << ST->getOccupancyWithNumVGPRs(RP.getVGPRNum(ST->hasGFX90AInsts()),
256 DynamicVGPRBlockSize)
257 << ')';
258 OS << ", SGPRs: " << RP.getSGPRNum();
259 if (ST)
260 OS << "(O" << ST->getOccupancyWithNumSGPRs(RP.getSGPRNum()) << ')';
261 OS << ", LVGPR WT: " << RP.getVGPRTuplesWeight()
262 << ", LSGPR WT: " << RP.getSGPRTuplesWeight();
263 if (ST)
264 OS << " -> Occ: " << RP.getOccupancy(*ST, DynamicVGPRBlockSize);
265 OS << '\n';
266 });
267}
268
270 const MachineRegisterInfo &MRI) {
271 assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual());
272
273 // We don't rely on read-undef flag because in case of tentative schedule
274 // tracking it isn't set correctly yet. This works correctly however since
275 // use mask has been tracked before using LIS.
276 return MO.getSubReg() == 0 ?
277 MRI.getMaxLaneMaskForVReg(MO.getReg()) :
278 MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
279}
280
281static void
283 const MachineInstr &MI, const LiveIntervals &LIS,
284 const MachineRegisterInfo &MRI) {
285
286 auto &TRI = *MRI.getTargetRegisterInfo();
287 for (const auto &MO : MI.operands()) {
288 if (!MO.isReg() || !MO.getReg().isVirtual())
289 continue;
290 if (!MO.isUse() || !MO.readsReg())
291 continue;
292
293 Register Reg = MO.getReg();
294 auto I = llvm::find_if(VRegMaskOrUnits, [Reg](const VRegMaskOrUnit &RM) {
295 return RM.VRegOrUnit.asVirtualReg() == Reg;
296 });
297
298 auto &P = I == VRegMaskOrUnits.end()
299 ? VRegMaskOrUnits.emplace_back(VirtRegOrUnit(Reg),
301 : *I;
302
303 P.LaneMask |= MO.getSubReg() ? TRI.getSubRegIndexLaneMask(MO.getSubReg())
304 : MRI.getMaxLaneMaskForVReg(Reg);
305 }
306
307 SlotIndex InstrSI;
308 for (auto &P : VRegMaskOrUnits) {
309 auto &LI = LIS.getInterval(P.VRegOrUnit.asVirtualReg());
310 if (!LI.hasSubRanges())
311 continue;
312
313 // For a tentative schedule LIS isn't updated yet but livemask should
314 // remain the same on any schedule. Subreg defs can be reordered but they
315 // all must dominate uses anyway.
316 if (!InstrSI)
317 InstrSI = LIS.getInstructionIndex(MI).getBaseIndex();
318
319 P.LaneMask = getLiveLaneMask(LI, InstrSI, MRI, P.LaneMask);
320 }
321}
322
323/// Mostly copy/paste from CodeGen/RegisterPressure.cpp
325 const LiveIntervals &LIS, const MachineRegisterInfo &MRI,
326 bool TrackLaneMasks, Register Reg, SlotIndex Pos,
327 function_ref<bool(const LiveRange &LR, SlotIndex Pos)> Property) {
328 assert(Reg.isVirtual());
329 const LiveInterval &LI = LIS.getInterval(Reg);
330 LaneBitmask Result;
331 if (TrackLaneMasks && LI.hasSubRanges()) {
332 for (const LiveInterval::SubRange &SR : LI.subranges()) {
333 if (Property(SR, Pos))
334 Result |= SR.LaneMask;
335 }
336 } else if (Property(LI, Pos)) {
337 Result =
338 TrackLaneMasks ? MRI.getMaxLaneMaskForVReg(Reg) : LaneBitmask::getAll();
339 }
340
341 return Result;
342}
343
344/// Mostly copy/paste from CodeGen/RegisterPressure.cpp
345/// Helper to find a vreg use between two indices {PriorUseIdx, NextUseIdx}.
346/// The query starts with a lane bitmask which gets lanes/bits removed for every
347/// use we find.
348static LaneBitmask findUseBetween(unsigned Reg, LaneBitmask LastUseMask,
349 SlotIndex PriorUseIdx, SlotIndex NextUseIdx,
351 const SIRegisterInfo *TRI,
352 const LiveIntervals *LIS,
353 bool Upward = false) {
354 for (const MachineOperand &MO : MRI.use_nodbg_operands(Reg)) {
355 if (MO.isUndef())
356 continue;
357 const MachineInstr *MI = MO.getParent();
358 SlotIndex InstSlot = LIS->getInstructionIndex(*MI).getRegSlot();
359 bool InRange = Upward ? (InstSlot > PriorUseIdx && InstSlot <= NextUseIdx)
360 : (InstSlot >= PriorUseIdx && InstSlot < NextUseIdx);
361 if (!InRange)
362 continue;
363
364 unsigned SubRegIdx = MO.getSubReg();
365 LaneBitmask UseMask = TRI->getSubRegIndexLaneMask(SubRegIdx);
366 LastUseMask &= ~UseMask;
367 if (LastUseMask.none())
369 }
370 return LastUseMask;
371}
372
373////////////////////////////////////////////////////////////////////////////////
374// GCNRPTarget
375
377 : GCNRPTarget(RP, MF) {
378 const Function &F = MF.getFunction();
379 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
380 setTarget(ST.getMaxNumSGPRs(F), ST.getMaxNumVGPRs(F));
381}
382
383GCNRPTarget::GCNRPTarget(unsigned NumSGPRs, unsigned NumVGPRs,
384 const MachineFunction &MF, const GCNRegPressure &RP)
385 : GCNRPTarget(RP, MF) {
386 setTarget(NumSGPRs, NumVGPRs);
387}
388
389GCNRPTarget::GCNRPTarget(unsigned Occupancy, const MachineFunction &MF,
390 const GCNRegPressure &RP)
391 : GCNRPTarget(RP, MF) {
392 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
393 unsigned DynamicVGPRBlockSize =
395 setTarget(ST.getMaxNumSGPRs(Occupancy, /*Addressable=*/false),
396 ST.getMaxNumVGPRs(Occupancy, DynamicVGPRBlockSize));
397}
398
399void GCNRPTarget::setTarget(unsigned NumSGPRs, unsigned NumVGPRs) {
400 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
401 MaxSGPRs = std::min(ST.getAddressableNumSGPRs(), NumSGPRs);
402 MaxVGPRs = std::min(ST.getAddressableNumArchVGPRs(), NumVGPRs);
403 if (UnifiedRF) {
404 unsigned DynamicVGPRBlockSize =
405 MF.getInfo<SIMachineFunctionInfo>()->getDynamicVGPRBlockSize();
406 MaxUnifiedVGPRs =
407 std::min(ST.getAddressableNumVGPRs(DynamicVGPRBlockSize), NumVGPRs);
408 } else {
409 MaxUnifiedVGPRs = 0;
410 }
411}
412
414 const MachineRegisterInfo &MRI = MF.getRegInfo();
415 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
416 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
417 const SIRegisterInfo *SRI = static_cast<const SIRegisterInfo *>(TRI);
418
419 RegExcess Excess(MF, RP, *this);
420
421 if (SRI->isSGPRClass(RC))
422 return Excess.SGPR;
423
424 if (SRI->isAGPRClass(RC))
425 return (UnifiedRF && Excess.VGPR) || Excess.AGPR;
426
427 return (UnifiedRF && Excess.VGPR) || Excess.ArchVGPR;
428}
429
431 RegExcess Excess(MF, RP, *this);
432 if (SaveRP.getSGPRNum() != 0 && Excess.SGPR != 0)
433 return true;
434 if (SaveRP.getArchVGPRNum() != 0 && Excess.ArchVGPR != 0)
435 return true;
436 if (SaveRP.getAGPRNum() != 0 && Excess.AGPR != 0)
437 return true;
438 if (UnifiedRF && Excess.VGPR != 0)
439 return SaveRP.getArchVGPRNum() != 0 || SaveRP.getAGPRNum() != 0;
440 return false;
441}
442
443unsigned GCNRPTarget::getNumRegsBenefit(const GCNRegPressure &SaveRP) const {
444 RegExcess Excess(MF, RP, *this);
445 const unsigned NumVGPRAboveAddrLimit =
446 std::min(Excess.ArchVGPR, SaveRP.getArchVGPRNum()) +
447 std::min(Excess.AGPR, SaveRP.getAGPRNum());
448 unsigned NumRegsSaved =
449 std::min(Excess.SGPR, SaveRP.getSGPRNum()) + NumVGPRAboveAddrLimit;
450
451 if (UnifiedRF && Excess.VGPR) {
452 // We have already accounted for excess pressure above addressive limits for
453 // the individual VGPR classes. However for targets with unified RFs there
454 // is also a unified VGPR pressure (ArchVGPR + AGPR combination) limit to
455 // honor that may be more restrictive that the per-VGPR-class limits. We
456 // must also be careful not to double-count VGPR saves that may contribute
457 // to lowering pressure both above the addressable limit in their respective
458 // class as well as in the unified VGPR limit.
459 const unsigned VGPRSave = SaveRP.getArchVGPRNum() + SaveRP.getAGPRNum();
460 if (NumVGPRAboveAddrLimit < VGPRSave)
461 NumRegsSaved += std::min(Excess.VGPR, VGPRSave - NumVGPRAboveAddrLimit);
462 }
463
464 return NumRegsSaved;
465}
466
467bool GCNRPTarget::satisfied(const GCNRegPressure &TestRP) const {
468 if (TestRP.getSGPRNum() > MaxSGPRs || TestRP.getVGPRNum(false) > MaxVGPRs)
469 return false;
470 if (UnifiedRF && TestRP.getVGPRNum(true) > MaxUnifiedVGPRs)
471 return false;
472 return true;
473}
474
476 RegExcess Excess(MF, RP, *this);
477 return Excess.hasVectorRegisterExcess();
478}
479
480///////////////////////////////////////////////////////////////////////////////
481// GCNRPTracker
482
484 const LiveIntervals &LIS,
486 LaneBitmask LaneMaskFilter) {
487 return getLiveLaneMask(LIS.getInterval(Reg), SI, MRI, LaneMaskFilter);
488}
489
492 LaneBitmask LaneMaskFilter) {
493 LaneBitmask LiveMask;
494 if (LI.hasSubRanges()) {
495 for (const auto &S : LI.subranges())
496 if ((S.LaneMask & LaneMaskFilter).any() && S.liveAt(SI)) {
497 LiveMask |= S.LaneMask;
498 assert(LiveMask == (LiveMask & MRI.getMaxLaneMaskForVReg(LI.reg())));
499 }
500 } else if (LI.liveAt(SI)) {
501 LiveMask = MRI.getMaxLaneMaskForVReg(LI.reg());
502 }
503 LiveMask &= LaneMaskFilter;
504 return LiveMask;
505}
506
508 const LiveIntervals &LIS,
510 GCNRegPressure::RegKind RegKind) {
512 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
513 auto Reg = Register::index2VirtReg(I);
514 if (RegKind != GCNRegPressure::TOTAL_KINDS &&
515 GCNRegPressure::getRegKind(Reg, MRI) != RegKind)
516 continue;
517 if (!LIS.hasInterval(Reg))
518 continue;
519 auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI);
520 if (LiveMask.any())
521 LiveRegs[Reg] = LiveMask;
522 }
523 return LiveRegs;
524}
525
526void GCNRPTracker::reset(const MachineInstr &MI, bool After) {
527 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
528 if (!MI.isDebugInstr()) {
529 SlotIndex SI = LIS.getInstructionIndex(MI);
530 if (After)
531 SI = SI.getDeadSlot();
532 reset(MRI, SI);
533 return;
534 }
535
536 // Look for the first valid index after the provided debug MI.
537 MachineBasicBlock::const_iterator It = MI.getIterator(),
538 MBBEnd = MI.getParent()->end();
541 if (NonDbgMI == MBBEnd) {
542 // There are no non-debug instruction between MI and the end of the
543 // block, so we reset the tracker at the end of the block.
544 reset(*MI.getParent(), /*End=*/true);
545 return;
546 }
547 // MI is a debug instruction so register pressure before or after it is
548 // identical. Since we moved forward to finding a non-debug instruction
549 // in the block, we reset the tracker before that instruction i.e., at its
550 // base index.
551 reset(MRI, LIS.getInstructionIndex(*NonDbgMI));
552}
553
555 SlotIndex SI = End ? LIS.getSlotIndexes()->getMBBLastIdx(&MBB)
556 : LIS.getMBBStartIdx(&MBB);
557 reset(MBB.getParent()->getRegInfo(), SI);
558}
559
566
568 const LiveRegSet &LiveRegs) {
569 this->MRI = &MRI;
570 LastTrackedMI = nullptr;
571 if (&this->LiveRegs != &LiveRegs)
572 this->LiveRegs = LiveRegs;
574}
575
576/// Mostly copy/paste from CodeGen/RegisterPressure.cpp
579 LIS, *MRI, true, Reg, Pos.getBaseIndex(),
580 [](const LiveRange &LR, SlotIndex Pos) {
581 const LiveRange::Segment *S = LR.getSegmentContaining(Pos);
582 return S != nullptr && S->end == Pos.getRegSlot();
583 });
584}
585
586////////////////////////////////////////////////////////////////////////////////
587// GCNUpwardRPTracker
588
590 assert(MRI && "call reset first");
591
592 LastTrackedMI = &MI;
593
594 if (MI.isDebugInstr())
595 return;
596
597 // Kill all defs.
598 GCNRegPressure DefPressure, ECDefPressure;
599 bool HasECDefs = false;
600 for (const MachineOperand &MO : MI.all_defs()) {
601 if (!MO.getReg().isVirtual())
602 continue;
603
604 Register Reg = MO.getReg();
605 LaneBitmask DefMask = getDefRegMask(MO, *MRI);
606
607 // Treat a def as fully live at the moment of definition: keep a record.
608 if (MO.isEarlyClobber()) {
609 ECDefPressure.inc(Reg, LaneBitmask::getNone(), DefMask, *MRI);
610 HasECDefs = true;
611 } else
612 DefPressure.inc(Reg, LaneBitmask::getNone(), DefMask, *MRI);
613
614 auto I = LiveRegs.find(Reg);
615 if (I == LiveRegs.end())
616 continue;
617
618 LaneBitmask &LiveMask = I->second;
619 LaneBitmask PrevMask = LiveMask;
620 LiveMask &= ~DefMask;
621 CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
622 if (LiveMask.none())
623 LiveRegs.erase(I);
624 }
625
626 // Update MaxPressure with defs pressure.
627 DefPressure += CurPressure;
628 if (HasECDefs)
629 DefPressure += ECDefPressure;
630 updateMaxPressure(DefPressure);
631
632 // Make uses alive.
634 collectVirtualRegUses(RegUses, MI, LIS, *MRI);
635 for (const VRegMaskOrUnit &U : RegUses) {
636 LaneBitmask &LiveMask = LiveRegs[U.VRegOrUnit.asVirtualReg()];
637 LaneBitmask PrevMask = LiveMask;
638 LiveMask |= U.LaneMask;
639 CurPressure.inc(U.VRegOrUnit.asVirtualReg(), PrevMask, LiveMask, *MRI);
640 }
641
642 // Update MaxPressure with uses plus early-clobber defs pressure.
643 updateMaxPressure(HasECDefs ? CurPressure + ECDefPressure : CurPressure);
644
646}
647
648////////////////////////////////////////////////////////////////////////////////
649// GCNDownwardRPTracker
650
653 const LiveRegSet *LiveRegsCopy) {
654 MBBEnd = MI.getParent()->end();
655 assert((End == MBBEnd || End->getParent()->end() == MBBEnd) &&
656 "end unrelated to MI block");
657 NextMI = &MI;
658 NextMI = skipDebugInstructionsForward(NextMI, End);
659
660 // Do not use the MI to compute live registers when a set is provided.
661 // Otherwise the first non-debug instruction after the provided one (or the
662 // end of the block, if no such instruction exists) serves as the basis to
663 // compute a live register set.
664 if (LiveRegsCopy)
665 GCNRPTracker::reset(MI.getMF()->getRegInfo(), *LiveRegsCopy);
666 else if (NextMI != MBBEnd)
667 GCNRPTracker::reset(*NextMI, /*After=*/false);
668 else
669 GCNRPTracker::reset(*MI.getParent(), /*End=*/true);
670 return NextMI != End;
671}
672
673void GCNDownwardRPTrackerBase::retireVirtReg(Register Reg, SlotIndex SI) {
674 const LiveInterval &LI = LIS.getInterval(Reg);
675 if (LI.hasSubRanges()) {
676 auto It = LiveRegs.end();
677 for (const auto &S : LI.subranges()) {
678 if (!S.liveAt(SI)) {
679 if (It == LiveRegs.end()) {
680 It = LiveRegs.find(Reg);
681 if (It == LiveRegs.end())
682 llvm_unreachable("register isn't live");
683 }
684 auto PrevMask = It->second;
685 It->second &= ~S.LaneMask;
686 CurPressure.inc(Reg, PrevMask, It->second, *MRI);
687 }
688 }
689 if (It != LiveRegs.end() && It->second.none())
690 LiveRegs.erase(It);
691 } else if (!LI.liveAt(SI)) {
692 auto It = LiveRegs.find(Reg);
693 if (It == LiveRegs.end())
694 llvm_unreachable("register isn't live");
695 CurPressure.inc(Reg, It->second, LaneBitmask::getNone(), *MRI);
696 LiveRegs.erase(It);
697 }
698}
699
701 assert(MRI && "call reset first");
702
703 if (MI.isPHI())
704 return;
705
706 // Mirror ECDefPressure handling from GCNUpwardRPTracker::recede().
707 GCNRegPressure ECDefPressure;
708 for (const MachineOperand &MO : MI.all_defs()) {
709 Register Reg = MO.getReg();
710 if (Reg.isVirtual() && MO.isEarlyClobber())
711 ECDefPressure.inc(Reg, LaneBitmask::getNone(), getDefRegMask(MO, *MRI),
712 *MRI);
713 }
714
715 updateMaxPressure(CurPressure + ECDefPressure);
716
717 SlotIndex SI = LIS.getInstructionIndex(MI).getDeadSlot();
718 assert(SI.isValid());
719 SmallSet<Register, 8> SeenRegs;
720 for (const MachineOperand &MO : MI.all_uses()) {
721 Register Reg = MO.getReg();
722 if (MO.readsReg() && Reg.isVirtual() && SeenRegs.insert(Reg).second)
723 retireVirtReg(Reg, SI);
724 }
725}
726
728 SlotIndex SI) {
729 assert(MRI && "call reset first");
730
731 SmallSet<Register, 8> SeenRegs;
732 for (const MachineOperand &MO : MI.all_defs()) {
733 Register Reg = MO.getReg();
734 if (Reg.isVirtual() && SeenRegs.insert(Reg).second)
735 retireVirtReg(Reg, SI);
736 }
737
739}
740
742 assert(MRI && "call reset first");
743
744 // Add new registers or mask bits.
745 for (const MachineOperand &MO : MI.all_defs()) {
746 Register Reg = MO.getReg();
747 if (!Reg.isVirtual())
748 continue;
749 auto &LiveMask = LiveRegs[Reg];
750 auto PrevMask = LiveMask;
751 LiveMask |= getDefRegMask(MO, *MRI);
752 CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
753 }
755}
756
758 if (!LastTrackedMI.isValid())
759 return NextMI == MBBEnd;
760 assert(NextMI == MBBEnd || !NextMI->isDebugInstr());
761
762 SlotIndex SI = NextMI == MBBEnd
763 ? LIS.getInstructionIndex(*LastTrackedMI).getDeadSlot()
764 : LIS.getInstructionIndex(*NextMI).getBaseIndex();
765 assert(SI.isValid());
767 LastTrackedMI = nullptr;
768 return NextMI == MBBEnd;
769}
770
777
779 if (NextMI == MBBEnd)
780 return false;
781
784 return true;
785}
786
788 bool AnyAdvance = false;
789 while (NextMI != End && advance())
790 AnyAdvance = true;
791 return AnyAdvance;
792}
793
796 const LiveRegSet *LiveRegsCopy) {
797 if (!reset(*Begin, End, LiveRegsCopy))
798 return false;
800}
801
806 MI, LIS.getInstructionIndex(MI).getDeadSlot());
807
808 // Speculative queries (bumpDownwardPressure) must know the last scheduled
809 // instruction to correctly estimate pressure change.
810 LastTrackedMI = &MI;
811}
812
814 const GCNRPTracker::LiveRegSet &TrackedLR,
815 const TargetRegisterInfo *TRI, StringRef Pfx) {
816 return Printable([&LISLR, &TrackedLR, TRI, Pfx](raw_ostream &OS) {
817 for (auto const &P : TrackedLR) {
818 auto I = LISLR.find(P.first);
819 if (I == LISLR.end()) {
820 OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
821 << " isn't found in LIS reported set\n";
822 } else if (I->second != P.second) {
823 OS << Pfx << printReg(P.first, TRI)
824 << " masks doesn't match: LIS reported " << PrintLaneMask(I->second)
825 << ", tracked " << PrintLaneMask(P.second) << '\n';
826 }
827 }
828 for (auto const &P : LISLR) {
829 auto I = TrackedLR.find(P.first);
830 if (I == TrackedLR.end()) {
831 OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
832 << " isn't found in tracked set\n";
833 }
834 }
835 });
836}
837
839 const MachineInstr *MI, const SIRegisterInfo *TRI) const {
840 assert(!MI->isDebugOrPseudoInstr() && "Expect a nondebug instruction.");
841
842 SlotIndex SlotIdx;
843 SlotIdx = LIS.getInstructionIndex(*MI).getRegSlot();
844
845 SlotIndex CurrIdx;
846 const MachineBasicBlock *MBB = MI->getParent();
848 LastTrackedMI.isValid() ? std::next(LastTrackedMI) : MBB->begin();
850 skipDebugInstructionsForward(StartPos, MBB->end());
851 if (IdxPos == MBB->end()) {
852 CurrIdx = LIS.getMBBEndIdx(MBB);
853 } else {
854 CurrIdx = LIS.getInstructionIndex(*IdxPos).getRegSlot();
855 }
856
857 // Account for register pressure similar to RegPressureTracker::recede().
858 RegisterOperands RegOpers;
859 RegOpers.collect(*MI, *TRI, *MRI, true, /*IgnoreDead=*/false);
860 RegOpers.adjustLaneLiveness(LIS, *MRI, SlotIdx);
861 GCNRegPressure TempPressure = CurPressure;
862 // Tracks the live mask reported by the use loop for redefined registers.
864
865 for (const VRegMaskOrUnit &Use : RegOpers.Uses) {
866 if (!Use.VRegOrUnit.isVirtualReg())
867 continue;
868 Register Reg = Use.VRegOrUnit.asVirtualReg();
869 LaneBitmask LastUseMask = getLastUsedLanes(Reg, SlotIdx);
870 if (LastUseMask.none())
871 continue;
872 // The LastUseMask is queried from the liveness information of instruction
873 // which may be further down the schedule. Some lanes may actually not be
874 // last uses for the current position.
875 // FIXME: allow the caller to pass in the list of vreg uses that remain
876 // to be bottom-scheduled to avoid searching uses at each query.
877 LastUseMask =
878 findUseBetween(Reg, LastUseMask, CurrIdx, SlotIdx, *MRI, TRI, &LIS);
879 if (LastUseMask.none())
880 continue;
881
882 auto It = LiveRegs.find(Reg);
883 LaneBitmask LiveMask = It != LiveRegs.end() ? It->second : LaneBitmask(0);
884 LaneBitmask NewMask = LiveMask & ~LastUseMask;
885 PostUseMask[Reg] = NewMask;
886 TempPressure.inc(Reg, LiveMask, NewMask, *MRI);
887 }
888
889 // Generate liveness for defs.
890 for (const VRegMaskOrUnit &Def : RegOpers.Defs) {
891 if (!Def.VRegOrUnit.isVirtualReg())
892 continue;
893 Register Reg = Def.VRegOrUnit.asVirtualReg();
894 auto PostIt = PostUseMask.find(Reg);
895 LaneBitmask LiveMask;
896 if (PostIt != PostUseMask.end()) {
897 LiveMask = PostIt->second;
898 } else {
899 auto It = LiveRegs.find(Reg);
900 LiveMask = It != LiveRegs.end() ? It->second : LaneBitmask(0);
901 }
902
903 LaneBitmask NewMask = LiveMask | Def.LaneMask;
904 TempPressure.inc(Reg, LiveMask, NewMask, *MRI);
905 }
906
907 return TempPressure;
908}
909
911 const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
912 const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
913 const auto &TrackedLR = LiveRegs;
914
915 if (!isEqual(LISLR, TrackedLR)) {
916 dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
917 " LIS reported livesets mismatch:\n"
918 << print(LISLR, *MRI);
919 reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo());
920 return false;
921 }
922
923 auto LISPressure = getRegPressure(*MRI, LISLR);
924 if (LISPressure != CurPressure) {
925 dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: "
926 << print(CurPressure) << "LIS rpt: " << print(LISPressure);
927 return false;
928 }
929 return true;
930}
931
933 const MachineRegisterInfo &MRI) {
934 return Printable([&LiveRegs, &MRI](raw_ostream &OS) {
935 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
936 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
938 auto It = LiveRegs.find(Reg);
939 if (It != LiveRegs.end() && It->second.any())
940 OS << ' ' << printReg(Reg, TRI) << ':' << PrintLaneMask(It->second);
941 }
942 OS << '\n';
943 });
944}
945
946void GCNRegPressure::dump() const { dbgs() << print(*this); }
947
949 "amdgpu-print-rp-downward",
950 cl::desc("Use GCNDownwardRPTracker for GCNRegPressurePrinter pass"),
951 cl::init(false), cl::Hidden);
952
955
956INITIALIZE_PASS(GCNRegPressurePrinter, "amdgpu-print-rp", "", true, true)
957
958// Return lanemask of Reg's subregs that are live-through at [Begin, End] and
959// are fully covered by Mask.
960static LaneBitmask
963 LaneBitmask Mask = LaneBitmask::getAll()) {
964
965 auto IsInOneSegment = [Begin, End](const LiveRange &LR) -> bool {
966 auto *Segment = LR.getSegmentContaining(Begin);
967 return Segment && Segment->contains(End);
968 };
969
970 LaneBitmask LiveThroughMask;
971 const LiveInterval &LI = LIS.getInterval(Reg);
972 if (LI.hasSubRanges()) {
973 for (auto &SR : LI.subranges()) {
974 if ((SR.LaneMask & Mask) == SR.LaneMask && IsInOneSegment(SR))
975 LiveThroughMask |= SR.LaneMask;
976 }
977 } else {
979 if ((RegMask & Mask) == RegMask && IsInOneSegment(LI))
980 LiveThroughMask = RegMask;
981 }
982
983 return LiveThroughMask;
984}
985
987 const MachineRegisterInfo &MRI = MF.getRegInfo();
988 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
990
991 auto &OS = dbgs();
992
993// Leading spaces are important for YAML syntax.
994#define PFX " "
995
996 OS << "---\nname: " << MF.getName() << "\nbody: |\n";
997
998 auto printRP = [](const GCNRegPressure &RP) {
999 return Printable([&RP](raw_ostream &OS) {
1000 OS << format(PFX " %-5d", RP.getSGPRNum())
1001 << format(" %-5d", RP.getVGPRNum(false));
1002 });
1003 };
1004
1005 auto ReportLISMismatchIfAny = [&](const GCNRPTracker::LiveRegSet &TrackedLR,
1006 const GCNRPTracker::LiveRegSet &LISLR) {
1007 if (LISLR != TrackedLR) {
1008 OS << PFX " mis LIS: " << llvm::print(LISLR, MRI)
1009 << reportMismatch(LISLR, TrackedLR, TRI, PFX " ");
1010 }
1011 };
1012
1013 // Register pressure before and at an instruction (in program order).
1015
1016 for (auto &MBB : MF) {
1017 RP.clear();
1018 RP.reserve(MBB.size());
1019
1020 OS << PFX;
1021 MBB.printName(OS);
1022 OS << ":\n";
1023
1024 SlotIndex MBBStartSlot = LIS.getSlotIndexes()->getMBBStartIdx(&MBB);
1025 SlotIndex MBBLastSlot = LIS.getSlotIndexes()->getMBBLastIdx(&MBB);
1026
1027 GCNRPTracker::LiveRegSet LiveIn, LiveOut;
1028 GCNRegPressure RPAtMBBEnd;
1029
1030 if (UseDownwardTracker) {
1031 if (MBB.empty()) {
1032 LiveIn = LiveOut = getLiveRegs(MBBStartSlot, LIS, MRI);
1033 RPAtMBBEnd = getRegPressure(MRI, LiveIn);
1034 } else {
1035 GCNDownwardRPTracker RPT(LIS);
1036 RPT.reset(MBB.front(), MBB.end());
1037
1038 LiveIn = RPT.getLiveRegs();
1039
1040 while (!RPT.advanceBeforeNext()) {
1041 GCNRegPressure RPBeforeMI = RPT.getPressure();
1042 RPT.resetMaxPressure();
1043 RPT.advanceToNext();
1044 RP.emplace_back(RPBeforeMI, RPT.getMaxPressure());
1045 }
1046
1047 LiveOut = RPT.getLiveRegs();
1048 RPAtMBBEnd = RPT.getPressure();
1049 }
1050 } else {
1051 GCNUpwardRPTracker RPT(LIS);
1052 RPT.reset(MRI, MBBLastSlot);
1053
1054 LiveOut = RPT.getLiveRegs();
1055 RPAtMBBEnd = RPT.getPressure();
1056
1057 for (auto &MI : reverse(MBB)) {
1058 RPT.resetMaxPressure();
1059 RPT.recede(MI);
1060 if (!MI.isDebugInstr())
1061 RP.emplace_back(RPT.getPressure(), RPT.getMaxPressure());
1062 }
1063
1064 LiveIn = RPT.getLiveRegs();
1065 }
1066
1067 OS << PFX " Live-in: " << llvm::print(LiveIn, MRI);
1068 if (!UseDownwardTracker)
1069 ReportLISMismatchIfAny(LiveIn, getLiveRegs(MBBStartSlot, LIS, MRI));
1070
1071 OS << PFX " SGPR VGPR\n";
1072 int I = 0;
1073 for (auto &MI : MBB) {
1074 if (!MI.isDebugInstr()) {
1075 auto &[RPBeforeInstr, RPAtInstr] =
1076 RP[UseDownwardTracker ? I : (RP.size() - 1 - I)];
1077 ++I;
1078 OS << printRP(RPBeforeInstr) << '\n' << printRP(RPAtInstr) << " ";
1079 } else
1080 OS << PFX " ";
1081 MI.print(OS);
1082 }
1083 OS << printRP(RPAtMBBEnd) << '\n';
1084
1085 OS << PFX " Live-out:" << llvm::print(LiveOut, MRI);
1087 ReportLISMismatchIfAny(LiveOut, getLiveRegs(MBBLastSlot, LIS, MRI));
1088
1089 GCNRPTracker::LiveRegSet LiveThrough;
1090 for (auto [Reg, Mask] : LiveIn) {
1091 LaneBitmask MaskIntersection = Mask & LiveOut.lookup(Reg);
1092 if (MaskIntersection.any()) {
1094 MRI, LIS, Reg, MBBStartSlot, MBBLastSlot, MaskIntersection);
1095 if (LTMask.any())
1096 LiveThrough[Reg] = LTMask;
1097 }
1098 }
1099 OS << PFX " Live-thr:" << llvm::print(LiveThrough, MRI);
1100 OS << printRP(getRegPressure(MRI, LiveThrough)) << '\n';
1101 }
1102 OS << "...\n";
1103 return false;
1104
1105#undef PFX
1106}
1107
1108#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1111 LiveIntervals &LIS,
1112 const MachineLoopInfo *MLI) {
1113
1114 const MachineRegisterInfo &MRI = MF.getRegInfo();
1115 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
1116 auto &OS = dbgs();
1117 const char *RegName = GCNRegPressure::getName(Kind);
1118
1119 unsigned MaxNumRegs = 0;
1120 const MachineInstr *MaxPressureMI = nullptr;
1121 GCNUpwardRPTracker RPT(LIS);
1122 // The maximum pressure of the tracker pairs the VGPR and AVGPR components,
1123 // so take the maximum of Kind alone from each point.
1124 unsigned NumRegs = 0;
1125 RPT.setPressureCallback([&](const GCNRegPressure &RP) {
1126 NumRegs = std::max(NumRegs, RP.getNumRegs(Kind));
1127 });
1128 for (const MachineBasicBlock &MBB : MF) {
1130 NumRegs = RPT.getPressure().getNumRegs(Kind);
1131 for (const MachineInstr &MI : reverse(MBB)) {
1132 RPT.recede(MI);
1133 if (NumRegs > MaxNumRegs) {
1134 MaxNumRegs = NumRegs;
1135 MaxPressureMI = &MI;
1136 }
1137 }
1138 }
1139
1140 SlotIndex MISlot = LIS.getInstructionIndex(*MaxPressureMI);
1141
1142 // Max pressure can occur at either the early-clobber or register slot.
1143 // Choose the maximum liveset between both slots. This is ugly but this is
1144 // diagnostic code.
1145 SlotIndex ECSlot = MISlot.getRegSlot(true);
1146 SlotIndex RSlot = MISlot.getRegSlot(false);
1147 GCNRPTracker::LiveRegSet ECLiveSet = getLiveRegs(ECSlot, LIS, MRI, Kind);
1148 GCNRPTracker::LiveRegSet RLiveSet = getLiveRegs(RSlot, LIS, MRI, Kind);
1149 unsigned ECNumRegs = getRegPressure(MRI, ECLiveSet).getNumRegs(Kind);
1150 unsigned RNumRegs = getRegPressure(MRI, RLiveSet).getNumRegs(Kind);
1151 GCNRPTracker::LiveRegSet *LiveSet =
1152 ECNumRegs > RNumRegs ? &ECLiveSet : &RLiveSet;
1153 SlotIndex MaxPressureSlot = ECNumRegs > RNumRegs ? ECSlot : RSlot;
1154 assert(getRegPressure(MRI, *LiveSet).getNumRegs(Kind) == MaxNumRegs);
1155
1156 // Split live registers into single-def and multi-def sets.
1157 GCNRegPressure SDefPressure, MDefPressure;
1158 SmallVector<Register, 16> SDefRegs, MDefRegs;
1159 for (auto [Reg, LaneMask] : *LiveSet) {
1160 assert(GCNRegPressure::getRegKind(Reg, MRI) == Kind);
1161 LiveInterval &LI = LIS.getInterval(Reg);
1162 if (LI.getNumValNums() == 1 ||
1163 (LI.hasSubRanges() &&
1164 llvm::all_of(LI.subranges(), [](const LiveInterval::SubRange &SR) {
1165 return SR.getNumValNums() == 1;
1166 }))) {
1167 SDefPressure.inc(Reg, LaneBitmask::getNone(), LaneMask, MRI);
1168 SDefRegs.push_back(Reg);
1169 } else {
1170 MDefPressure.inc(Reg, LaneBitmask::getNone(), LaneMask, MRI);
1171 MDefRegs.push_back(Reg);
1172 }
1173 }
1174 unsigned SDefNumRegs = SDefPressure.getNumRegs(Kind);
1175 unsigned MDefNumRegs = MDefPressure.getNumRegs(Kind);
1176 assert(SDefNumRegs + MDefNumRegs == MaxNumRegs);
1177
1178 auto printLoc = [&](const MachineBasicBlock *MBB, SlotIndex SI) {
1179 return Printable([&, MBB, SI](raw_ostream &OS) {
1180 OS << SI << ':' << printMBBReference(*MBB);
1181 if (MLI)
1182 if (const MachineLoop *ML = MLI->getLoopFor(MBB))
1183 OS << " (LoopHdr " << printMBBReference(*ML->getHeader())
1184 << ", Depth " << ML->getLoopDepth() << ")";
1185 });
1186 };
1187
1188 auto PrintRegInfo = [&](Register Reg, LaneBitmask LiveMask) {
1189 GCNRegPressure RegPressure;
1190 RegPressure.inc(Reg, LaneBitmask::getNone(), LiveMask, MRI);
1191 OS << " " << printReg(Reg, TRI) << ':'
1192 << TRI->getRegClassName(MRI.getRegClass(Reg)) << ", LiveMask "
1193 << PrintLaneMask(LiveMask) << " (" << RegPressure.getNumRegs(Kind) << ' '
1194 << RegName << "s)\n";
1195
1196 // Use std::map to sort def/uses by SlotIndex.
1197 std::map<SlotIndex, const MachineInstr *> Instrs;
1198 for (const MachineInstr &MI : MRI.reg_nodbg_instructions(Reg)) {
1199 Instrs[LIS.getInstructionIndex(MI).getRegSlot()] = &MI;
1200 }
1201
1202 for (const auto &[SI, MI] : Instrs) {
1203 OS << " ";
1204 if (MI->definesRegister(Reg, TRI))
1205 OS << "def ";
1206 if (MI->readsRegister(Reg, TRI))
1207 OS << "use ";
1208 OS << printLoc(MI->getParent(), SI) << ": " << *MI;
1209 }
1210 };
1211
1212 OS << "\n*** Register pressure info (" << RegName << "s) for " << MF.getName()
1213 << " ***\n";
1214 OS << "Max pressure is " << MaxNumRegs << ' ' << RegName << "s at "
1215 << printLoc(MaxPressureMI->getParent(), MaxPressureSlot) << ": "
1216 << *MaxPressureMI;
1217
1218 OS << "\nLive registers with single definition (" << SDefNumRegs << ' '
1219 << RegName << "s):\n";
1220
1221 // Sort SDefRegs by number of uses (smallest first)
1222 llvm::sort(SDefRegs, [&](Register A, Register B) {
1223 return std::distance(MRI.use_nodbg_begin(A), MRI.use_nodbg_end()) <
1224 std::distance(MRI.use_nodbg_begin(B), MRI.use_nodbg_end());
1225 });
1226
1227 for (const Register Reg : SDefRegs) {
1228 PrintRegInfo(Reg, LiveSet->lookup(Reg));
1229 }
1230
1231 OS << "\nLive registers with multiple definitions (" << MDefNumRegs << ' '
1232 << RegName << "s):\n";
1233 for (const Register Reg : MDefRegs) {
1234 PrintRegInfo(Reg, LiveSet->lookup(Reg));
1235 }
1236}
1237#endif
1238
1242 const GCNRPTracker::LiveRegSet &LiveIns, const LiveIntervals &LIS,
1243 const MachineRegisterInfo &MRI, const SIRegisterInfo &TRI) {
1244
1246 IntervalSet.reserve(LiveIns.size());
1247
1248 auto checkAndCollect = [&](Register VReg) {
1249 if (!VReg.isVirtual() || !LIS.hasInterval(VReg))
1250 return;
1251
1252 const TargetRegisterClass *RC = MRI.getRegClass(VReg);
1253 if (!TRI.hasVGPRs(RC))
1254 return;
1255
1256 const LiveInterval &LI = LIS.getInterval(VReg);
1257 IntervalSet.insert(&LI);
1258 };
1259
1260 // Collect live-ins.
1261 for (const auto &[RegNum, LaneMask] : LiveIns) {
1262 checkAndCollect(Register(RegNum));
1263 }
1264
1265 // Collect defs in region.
1266 for (MachineBasicBlock::const_iterator I = RegionBegin; I != RegionEnd; ++I) {
1267 for (const MachineOperand &MO : I->operands()) {
1268 if (!MO.isReg() || !MO.isDef())
1269 continue;
1270 checkAndCollect(MO.getReg());
1271 }
1272 }
1273
1274 SmallVector<const LiveInterval *> Intervals = IntervalSet.takeVector();
1275 llvm::sort(Intervals, [](const LiveInterval *LHS, const LiveInterval *RHS) {
1276 return LHS->beginIndex() < RHS->beginIndex();
1277 });
1278
1280 std::vector<LiveIntervalUnion> RegFile;
1281 unsigned MaxRegsUsed = 0;
1282
1283 // Simulate greedy register allocation, assuming an unlimited number of
1284 // physical registers.
1285 for (const LiveInterval *LI : Intervals) {
1286 const TargetRegisterClass *RC = MRI.getRegClass(LI->reg());
1287 unsigned Width =
1288 std::max<unsigned>(1, TRI.getRegSizeInBits(*RC).getFixedValue() / 32);
1289 unsigned Alignment =
1290 std::max<unsigned>(1, TRI.getRegClassAlignmentNumBits(RC) / 32);
1291
1292 unsigned Start = 0;
1293 while (true) {
1294 unsigned End = Start + Width;
1295 if (RegFile.size() < End)
1296 RegFile.resize(End, LiveIntervalUnion(Alloc));
1297
1298 bool Fits = true;
1299 for (unsigned Idx = Start; Idx < End; Idx++) {
1300 LiveIntervalUnion::Query Q(*LI, RegFile[Idx]);
1301 if (Q.checkInterference()) {
1302 Start = alignTo(Idx + 1, Alignment);
1303 Fits = false;
1304 break;
1305 }
1306 }
1307
1308 if (Fits) {
1309 for (unsigned Idx = Start; Idx < End; Idx++)
1310 RegFile[Idx].unify(*LI, *LI);
1311 MaxRegsUsed = std::max(MaxRegsUsed, End);
1312 break;
1313 }
1314 }
1315 }
1316
1317 return MaxRegsUsed;
1318}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
constexpr LLT S1
MachineBasicBlock & MBB
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:690
static void collectVirtualRegUses(SmallVectorImpl< VRegMaskOrUnit > &VRegMaskOrUnits, const MachineInstr &MI, const LiveIntervals &LIS, const MachineRegisterInfo &MRI)
#define PFX
static cl::opt< bool > UseDownwardTracker("amdgpu-print-rp-downward", cl::desc("Use GCNDownwardRPTracker for GCNRegPressurePrinter pass"), cl::init(false), cl::Hidden)
static LaneBitmask getDefRegMask(const MachineOperand &MO, const MachineRegisterInfo &MRI)
static LaneBitmask getRegLiveThroughMask(const MachineRegisterInfo &MRI, const LiveIntervals &LIS, Register Reg, SlotIndex Begin, SlotIndex End, LaneBitmask Mask=LaneBitmask::getAll())
This file defines the GCNRegPressure class, which tracks registry pressure by bookkeeping number of S...
IRTranslator LLVM IR MI
#define RegName(no)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static bool InRange(int64_t Value, unsigned short Shift, int LBound, int HBound)
#define P(N)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
MachineRegisterInfo & MRI
static LaneBitmask getLanesWithProperty(LiveIntervals &LIS, const MachineRegisterInfo &MRI, bool TrackLaneMasks, VirtRegOrUnit VRegOrUnit, SlotIndex Pos, LaneBitmask SafeDefault, bool(*Property)(const LiveRange &LR, SlotIndex Pos), bool ComputePhysRegs=false)
static LaneBitmask findUseBetween(VirtRegOrUnit VRegOrUnit, LaneBitmask LastUseMask, SlotIndex PriorUseIdx, SlotIndex NextUseIdx, const MachineRegisterInfo &MRI, const LiveIntervals *LIS)
Helper to find a vreg use between two indices [PriorUseIdx, NextUseIdx).
This file implements a set that has insertion order iteration characteristics.
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:766
iterator end()
Definition DenseMap.h:686
unsigned size() const
Definition DenseMap.h:717
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:793
void retireDeadDefs(const MachineInstr &MI, SlotIndex SI)
Retires the lanes defined by MI that are dead at SI, according to LIS.
GCNRegPressure bumpDownwardPressure(const MachineInstr *MI, const SIRegisterInfo *TRI) const
Mostly copy/paste from CodeGen/RegisterPressure.cpp Calculate the impact MI will have on CurPressure ...
void retireDeadUses(const MachineInstr &MI)
Retires the lanes of MI's used registers that die at MI, mirroring RegPressureTracker::advance().
void addDefs(const MachineInstr &MI)
Adds all lanes (dead or not) defined by MI's register operands to CurPressure.
Downward RP tracker that relies on program order to advance down the instruction stream.
bool advance()
Advance to the state at the next MI in program order.
void advanceToNext()
Move to the state at NextMI.
bool advanceBeforeNext()
Move to the state right before NextMI or the end of the MBB.
bool reset(const MachineInstr &MI, MachineBasicBlock::const_iterator End, const LiveRegSet *LiveRegsCopy=nullptr)
Reset tracker to the point before the MI (filling LiveRegs upon this point using LiveRegsCopy if prov...
void advance(const MachineInstr &MI)
Advances to the state after MI.
GCNRPTarget(const MachineFunction &MF, const GCNRegPressure &RP)
Sets up the target such that the register pressure starting at RP does not show register spilling on ...
bool isSaveBeneficial(Register Reg) const
Determines whether saving virtual register Reg will be beneficial towards achieving the RP target.
bool hasVectorRegisterExcess() const
bool satisfied() const
Whether the current RP is at or below the defined pressure target.
void setTarget(unsigned NumSGPRs, unsigned NumVGPRs)
Changes the target (same semantics as constructor).
unsigned getNumRegsBenefit(const GCNRegPressure &SaveRP) const
Returns the benefit towards achieving the RP target that saving SaveRP represents,...
const GCNRegPressure & getMaxPressure() const
GCNRegPressure getPressure() const
const decltype(LiveRegs) & getLiveRegs() const
GCNRegPressure CurPressure
DenseMap< unsigned, LaneBitmask > LiveRegSet
LiveIntervals & LIS
MachineBasicBlock::const_iterator LastTrackedMI
LaneBitmask getLastUsedLanes(Register Reg, SlotIndex Pos) const
Mostly copy/paste from CodeGen/RegisterPressure.cpp.
void updateMaxPressure(const GCNRegPressure &RP)
Folds the pressure RP of one program point into MaxPressure and passes it to the pressure callback.
GCNRegPressure MaxPressure
const MachineRegisterInfo * MRI
void setPressureCallback(std::function< void(const GCNRegPressure &)> CB)
Sets a function that the tracker calls with the pressure of every program point that it folds into th...
void reset(const MachineInstr &MI, bool After)
Resets tracker before or After the provided MI, which can be a debug instruction.
void recede(const MachineInstr &MI)
Move to the state of RP just before the MI.
bool isValid() const
returns whether the tracker's state after receding MI corresponds to reported by LIS.
void reset(const MachineInstr &MI)
Resets tracker to the point just after MI (in program order), which can be a debug instruction.
Query interferences between a single live virtual register and a live interval union.
Union of live intervals that are strong candidates for coalescing into a single register (either phys...
LiveSegments::Allocator Allocator
A live range for subregisters.
LiveInterval - This class represents the liveness of a register, or stack slot.
Register reg() const
bool hasSubRanges() const
Returns true if subregister liveness information is available.
iterator_range< subrange_iterator > subranges()
bool hasInterval(Register Reg) const
SlotIndexes * getSlotIndexes() const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
This class represents the liveness of a register, stack slot, etc.
bool liveAt(SlotIndex index) const
unsigned getNumValNums() const
A set of live virtual registers and physical register units.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
MachineInstrBundleIterator< const MachineInstr > const_iterator
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI LaneBitmask getMaxLaneMaskForVReg(Register Reg) const
Returns a mask covering all bits that can appear in lane masks of subregisters of the virtual registe...
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
Simple wrapper around std::function<void(raw_ostream&)>.
Definition Printable.h:38
List of registers defined and used by a machine instruction.
SmallVector< VRegMaskOrUnit, 8 > Defs
List of virtual registers and register units defined by the instruction which are not dead.
LLVM_ABI void adjustLaneLiveness(LiveIntervals &LIS, const MachineRegisterInfo &MRI, SlotIndex Pos)
Use liveness information to find out which uses/defs are partially undefined/dead at Pos and adjust t...
LLVM_ABI void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI, bool TrackLaneMasks, bool IgnoreDead)
Analyze the given instruction MI and fill in the Uses, Defs and DeadDefs list based on the MachineOpe...
SmallVector< VRegMaskOrUnit, 8 > Uses
List of virtual registers and register units read by the instruction.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition Register.h:72
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
static unsigned getNumCoveredRegs(LaneBitmask LM)
bool isVectorSuperClass(const TargetRegisterClass *RC) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
A vector that has set insertion semantics.
Definition SetVector.h:57
void reserve(size_type Size)
Reserve space in the SetVector if supported by the underlying containers.
Definition SetVector.h:106
Vector takeVector()
Clear the SetVector and return the underlying vector.
Definition SetVector.h:94
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:70
SlotIndex getBaseIndex() const
Returns the base index for associated with this index.
SlotIndex getPrevSlot() const
Returns the previous slot in the index list.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndex getMBBLastIdx(const MachineBasicBlock *MBB) const
Returns the last valid index in the given basic block.
SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const
Returns the index past the last valid index in the given basic block.
SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const
Returns the first index in the given basic block.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
Wrapper class representing a virtual register or register unit.
Definition Register.h:175
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ VGPR
Address space for VGPRs.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LaneBitmask getLiveLaneMask(unsigned Reg, SlotIndex SI, const LiveIntervals &LIS, const MachineRegisterInfo &MRI, LaneBitmask LaneMaskFilter=LaneBitmask::getAll())
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
GCNRPTracker::LiveRegSet getLiveRegs(SlotIndex SI, const LiveIntervals &LIS, const MachineRegisterInfo &MRI, GCNRegPressure::RegKind RegKind=GCNRegPressure::TOTAL_KINDS)
GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI, Range &&LiveRegs)
Printable PrintLaneMask(LaneBitmask LaneMask)
Create Printable object to print LaneBitmasks on a raw_ostream.
Definition LaneBitmask.h:92
IterT skipDebugInstructionsForward(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It until it points to a non-debug instruction or to End and return the resulting iterator.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:102
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
char & GCNRegPressurePrinterID
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
LLVM_ABI void dumpMaxRegPressure(MachineFunction &MF, GCNRegPressure::RegKind Kind, LiveIntervals &LIS, const MachineLoopInfo *MLI)
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320
unsigned estimateGreedyVGPRPressure(MachineBasicBlock::const_iterator RegionBegin, MachineBasicBlock::const_iterator RegionEnd, const GCNRPTracker::LiveRegSet &LiveIns, const LiveIntervals &LIS, const MachineRegisterInfo &MRI, const SIRegisterInfo &TRI)
Estimate VGPR pressure using greedy, non-splitting register allocation simulation,...
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
Printable reportMismatch(const GCNRPTracker::LiveRegSet &LISLR, const GCNRPTracker::LiveRegSet &TrackedL, const TargetRegisterInfo *TRI, StringRef Pfx=" ")
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
static RegKind getRegKind(unsigned Reg, const MachineRegisterInfo &MRI)
static constexpr const char * getName(RegKind Kind)
unsigned getNumRegs(RegKind Kind) const
unsigned getVGPRTuplesWeight() const
unsigned getVGPRNum(bool UnifiedVGPRFile) const
friend Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST, unsigned DynamicVGPRBlockSize)
void inc(unsigned Reg, LaneBitmask PrevMask, LaneBitmask NewMask, const MachineRegisterInfo &MRI)
unsigned getArchVGPRNum() const
unsigned getAGPRNum() const
unsigned getSGPRNum() const
unsigned getSGPRTuplesWeight() const
bool less(const MachineFunction &MF, const GCNRegPressure &O, unsigned MaxOccupancy=std::numeric_limits< unsigned >::max()) const
Compares this GCNRegpressure to O, returning true if this is less.
static constexpr LaneBitmask getAll()
Definition LaneBitmask.h:82
constexpr bool none() const
Definition LaneBitmask.h:52
constexpr bool any() const
Definition LaneBitmask.h:53
static constexpr LaneBitmask getNone()
Definition LaneBitmask.h:81