LLVM 22.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"
19
20using namespace llvm;
21
22#define DEBUG_TYPE "machine-scheduler"
23
25 const GCNRPTracker::LiveRegSet &S2) {
26 if (S1.size() != S2.size())
27 return false;
28
29 for (const auto &P : S1) {
30 auto I = S2.find(P.first);
31 if (I == S2.end() || I->second != P.second)
32 return false;
33 }
34 return true;
35}
36
37///////////////////////////////////////////////////////////////////////////////
38// GCNRegPressure
39
41 const SIRegisterInfo *STI) {
42 return STI->isSGPRClass(RC)
43 ? SGPR
44 : (STI->isAGPRClass(RC)
45 ? AGPR
46 : (STI->isVectorSuperClass(RC) ? AVGPR : VGPR));
47}
48
49void GCNRegPressure::inc(unsigned Reg,
50 LaneBitmask PrevMask,
51 LaneBitmask NewMask,
52 const MachineRegisterInfo &MRI) {
53 unsigned NewNumCoveredRegs = SIRegisterInfo::getNumCoveredRegs(NewMask);
54 unsigned PrevNumCoveredRegs = SIRegisterInfo::getNumCoveredRegs(PrevMask);
55 if (NewNumCoveredRegs == PrevNumCoveredRegs)
56 return;
57
58 int Sign = 1;
59 if (NewMask < PrevMask) {
60 std::swap(NewMask, PrevMask);
61 std::swap(NewNumCoveredRegs, PrevNumCoveredRegs);
62 Sign = -1;
63 }
64 assert(PrevMask < NewMask && PrevNumCoveredRegs < NewNumCoveredRegs &&
65 "prev mask should always be lesser than new");
66
67 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
68 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
69 const SIRegisterInfo *STI = static_cast<const SIRegisterInfo *>(TRI);
70 unsigned RegKind = getRegKind(RC, STI);
71 if (TRI->getRegSizeInBits(*RC) != 32) {
72 // Reg is from a tuple register class.
73 if (PrevMask.none()) {
74 unsigned TupleIdx = TOTAL_KINDS + RegKind;
75 Value[TupleIdx] += Sign * TRI->getRegClassWeight(RC).RegWeight;
76 }
77 // Pressure scales with number of new registers covered by the new mask.
78 // Note when true16 is enabled, we can no longer safely use the following
79 // approach to calculate the difference in the number of 32-bit registers
80 // between two masks:
81 //
82 // Sign *= SIRegisterInfo::getNumCoveredRegs(~PrevMask & NewMask);
83 //
84 // The issue is that the mask calculation `~PrevMask & NewMask` doesn't
85 // properly account for partial usage of a 32-bit register when dealing with
86 // 16-bit registers.
87 //
88 // Consider this example:
89 // Assume PrevMask = 0b0010 and NewMask = 0b1111. Here, the correct register
90 // usage difference should be 1, because even though PrevMask uses only half
91 // of a 32-bit register, it should still be counted as a full register use.
92 // However, the mask calculation yields `~PrevMask & NewMask = 0b1101`, and
93 // calling `getNumCoveredRegs` returns 2 instead of 1. This incorrect
94 // calculation can lead to integer overflow when Sign = -1.
95 Sign *= NewNumCoveredRegs - PrevNumCoveredRegs;
96 }
97 Value[RegKind] += Sign;
98}
99
101 unsigned MaxOccupancy) const {
102 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
103 unsigned DynamicVGPRBlockSize =
104 MF.getInfo<SIMachineFunctionInfo>()->getDynamicVGPRBlockSize();
105
106 const auto SGPROcc = std::min(MaxOccupancy,
107 ST.getOccupancyWithNumSGPRs(getSGPRNum()));
108 const auto VGPROcc = std::min(
109 MaxOccupancy, ST.getOccupancyWithNumVGPRs(getVGPRNum(ST.hasGFX90AInsts()),
110 DynamicVGPRBlockSize));
111 const auto OtherSGPROcc = std::min(MaxOccupancy,
112 ST.getOccupancyWithNumSGPRs(O.getSGPRNum()));
113 const auto OtherVGPROcc =
114 std::min(MaxOccupancy,
115 ST.getOccupancyWithNumVGPRs(O.getVGPRNum(ST.hasGFX90AInsts()),
116 DynamicVGPRBlockSize));
117
118 const auto Occ = std::min(SGPROcc, VGPROcc);
119 const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc);
120
121 // Give first precedence to the better occupancy.
122 if (Occ != OtherOcc)
123 return Occ > OtherOcc;
124
125 unsigned MaxVGPRs = ST.getMaxNumVGPRs(MF);
126 unsigned MaxSGPRs = ST.getMaxNumSGPRs(MF);
127
128 // SGPR excess pressure conditions
129 unsigned ExcessSGPR = std::max(static_cast<int>(getSGPRNum() - MaxSGPRs), 0);
130 unsigned OtherExcessSGPR =
131 std::max(static_cast<int>(O.getSGPRNum() - MaxSGPRs), 0);
132
133 auto WaveSize = ST.getWavefrontSize();
134 // The number of virtual VGPRs required to handle excess SGPR
135 unsigned VGPRForSGPRSpills = (ExcessSGPR + (WaveSize - 1)) / WaveSize;
136 unsigned OtherVGPRForSGPRSpills =
137 (OtherExcessSGPR + (WaveSize - 1)) / WaveSize;
138
139 unsigned MaxArchVGPRs = ST.getAddressableNumArchVGPRs();
140
141 // Unified excess pressure conditions, accounting for VGPRs used for SGPR
142 // spills
143 unsigned ExcessVGPR =
144 std::max(static_cast<int>(getVGPRNum(ST.hasGFX90AInsts()) +
145 VGPRForSGPRSpills - MaxVGPRs),
146 0);
147 unsigned OtherExcessVGPR =
148 std::max(static_cast<int>(O.getVGPRNum(ST.hasGFX90AInsts()) +
149 OtherVGPRForSGPRSpills - MaxVGPRs),
150 0);
151 // Arch VGPR excess pressure conditions, accounting for VGPRs used for SGPR
152 // spills
153 unsigned ExcessArchVGPR = std::max(
154 static_cast<int>(getVGPRNum(false) + VGPRForSGPRSpills - MaxArchVGPRs),
155 0);
156 unsigned OtherExcessArchVGPR =
157 std::max(static_cast<int>(O.getVGPRNum(false) + OtherVGPRForSGPRSpills -
158 MaxArchVGPRs),
159 0);
160 // AGPR excess pressure conditions
161 unsigned ExcessAGPR = std::max(
162 static_cast<int>(ST.hasGFX90AInsts() ? (getAGPRNum() - MaxArchVGPRs)
163 : (getAGPRNum() - MaxVGPRs)),
164 0);
165 unsigned OtherExcessAGPR = std::max(
166 static_cast<int>(ST.hasGFX90AInsts() ? (O.getAGPRNum() - MaxArchVGPRs)
167 : (O.getAGPRNum() - MaxVGPRs)),
168 0);
169
170 bool ExcessRP = ExcessSGPR || ExcessVGPR || ExcessArchVGPR || ExcessAGPR;
171 bool OtherExcessRP = OtherExcessSGPR || OtherExcessVGPR ||
172 OtherExcessArchVGPR || OtherExcessAGPR;
173
174 // Give second precedence to the reduced number of spills to hold the register
175 // pressure.
176 if (ExcessRP || OtherExcessRP) {
177 // The difference in excess VGPR pressure, after including VGPRs used for
178 // SGPR spills
179 int VGPRDiff = ((OtherExcessVGPR + OtherExcessArchVGPR + OtherExcessAGPR) -
180 (ExcessVGPR + ExcessArchVGPR + ExcessAGPR));
181
182 int SGPRDiff = OtherExcessSGPR - ExcessSGPR;
183
184 if (VGPRDiff != 0)
185 return VGPRDiff > 0;
186 if (SGPRDiff != 0) {
187 unsigned PureExcessVGPR =
188 std::max(static_cast<int>(getVGPRNum(ST.hasGFX90AInsts()) - MaxVGPRs),
189 0) +
190 std::max(static_cast<int>(getVGPRNum(false) - MaxArchVGPRs), 0);
191 unsigned OtherPureExcessVGPR =
192 std::max(
193 static_cast<int>(O.getVGPRNum(ST.hasGFX90AInsts()) - MaxVGPRs),
194 0) +
195 std::max(static_cast<int>(O.getVGPRNum(false) - MaxArchVGPRs), 0);
196
197 // If we have a special case where there is a tie in excess VGPR, but one
198 // of the pressures has VGPR usage from SGPR spills, prefer the pressure
199 // with SGPR spills.
200 if (PureExcessVGPR != OtherPureExcessVGPR)
201 return SGPRDiff < 0;
202 // If both pressures have the same excess pressure before and after
203 // accounting for SGPR spills, prefer fewer SGPR spills.
204 return SGPRDiff > 0;
205 }
206 }
207
208 bool SGPRImportant = SGPROcc < VGPROcc;
209 const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc;
210
211 // If both pressures disagree on what is more important compare vgprs.
212 if (SGPRImportant != OtherSGPRImportant) {
213 SGPRImportant = false;
214 }
215
216 // Give third precedence to lower register tuple pressure.
217 bool SGPRFirst = SGPRImportant;
218 for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) {
219 if (SGPRFirst) {
220 auto SW = getSGPRTuplesWeight();
221 auto OtherSW = O.getSGPRTuplesWeight();
222 if (SW != OtherSW)
223 return SW < OtherSW;
224 } else {
225 auto VW = getVGPRTuplesWeight();
226 auto OtherVW = O.getVGPRTuplesWeight();
227 if (VW != OtherVW)
228 return VW < OtherVW;
229 }
230 }
231
232 // Give final precedence to lower general RP.
233 return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()):
234 (getVGPRNum(ST.hasGFX90AInsts()) <
235 O.getVGPRNum(ST.hasGFX90AInsts()));
236}
237
239 unsigned DynamicVGPRBlockSize) {
240 return Printable([&RP, ST, DynamicVGPRBlockSize](raw_ostream &OS) {
241 OS << "VGPRs: " << RP.getArchVGPRNum() << ' '
242 << "AGPRs: " << RP.getAGPRNum();
243 if (ST)
244 OS << "(O"
245 << ST->getOccupancyWithNumVGPRs(RP.getVGPRNum(ST->hasGFX90AInsts()),
246 DynamicVGPRBlockSize)
247 << ')';
248 OS << ", SGPRs: " << RP.getSGPRNum();
249 if (ST)
250 OS << "(O" << ST->getOccupancyWithNumSGPRs(RP.getSGPRNum()) << ')';
251 OS << ", LVGPR WT: " << RP.getVGPRTuplesWeight()
252 << ", LSGPR WT: " << RP.getSGPRTuplesWeight();
253 if (ST)
254 OS << " -> Occ: " << RP.getOccupancy(*ST, DynamicVGPRBlockSize);
255 OS << '\n';
256 });
257}
258
260 const MachineRegisterInfo &MRI) {
261 assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual());
262
263 // We don't rely on read-undef flag because in case of tentative schedule
264 // tracking it isn't set correctly yet. This works correctly however since
265 // use mask has been tracked before using LIS.
266 return MO.getSubReg() == 0 ?
267 MRI.getMaxLaneMaskForVReg(MO.getReg()) :
268 MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
269}
270
271static void
273 const MachineInstr &MI, const LiveIntervals &LIS,
274 const MachineRegisterInfo &MRI) {
275
276 auto &TRI = *MRI.getTargetRegisterInfo();
277 for (const auto &MO : MI.operands()) {
278 if (!MO.isReg() || !MO.getReg().isVirtual())
279 continue;
280 if (!MO.isUse() || !MO.readsReg())
281 continue;
282
283 Register Reg = MO.getReg();
284 auto I = llvm::find_if(VRegMaskOrUnits, [Reg](const VRegMaskOrUnit &RM) {
285 return RM.RegUnit == Reg;
286 });
287
288 auto &P = I == VRegMaskOrUnits.end()
289 ? VRegMaskOrUnits.emplace_back(Reg, LaneBitmask::getNone())
290 : *I;
291
292 P.LaneMask |= MO.getSubReg() ? TRI.getSubRegIndexLaneMask(MO.getSubReg())
293 : MRI.getMaxLaneMaskForVReg(Reg);
294 }
295
296 SlotIndex InstrSI;
297 for (auto &P : VRegMaskOrUnits) {
298 auto &LI = LIS.getInterval(P.RegUnit);
299 if (!LI.hasSubRanges())
300 continue;
301
302 // For a tentative schedule LIS isn't updated yet but livemask should
303 // remain the same on any schedule. Subreg defs can be reordered but they
304 // all must dominate uses anyway.
305 if (!InstrSI)
306 InstrSI = LIS.getInstructionIndex(MI).getBaseIndex();
307
308 P.LaneMask = getLiveLaneMask(LI, InstrSI, MRI, P.LaneMask);
309 }
310}
311
312/// Mostly copy/paste from CodeGen/RegisterPressure.cpp
314 const LiveIntervals &LIS, const MachineRegisterInfo &MRI,
315 bool TrackLaneMasks, Register RegUnit, SlotIndex Pos,
316 LaneBitmask SafeDefault,
317 function_ref<bool(const LiveRange &LR, SlotIndex Pos)> Property) {
318 if (RegUnit.isVirtual()) {
319 const LiveInterval &LI = LIS.getInterval(RegUnit);
320 LaneBitmask Result;
321 if (TrackLaneMasks && LI.hasSubRanges()) {
322 for (const LiveInterval::SubRange &SR : LI.subranges()) {
323 if (Property(SR, Pos))
324 Result |= SR.LaneMask;
325 }
326 } else if (Property(LI, Pos)) {
327 Result = TrackLaneMasks ? MRI.getMaxLaneMaskForVReg(RegUnit)
329 }
330
331 return Result;
332 }
333
334 const LiveRange *LR = LIS.getCachedRegUnit(RegUnit);
335 if (LR == nullptr)
336 return SafeDefault;
337 return Property(*LR, Pos) ? LaneBitmask::getAll() : LaneBitmask::getNone();
338}
339
340/// Mostly copy/paste from CodeGen/RegisterPressure.cpp
341/// Helper to find a vreg use between two indices {PriorUseIdx, NextUseIdx}.
342/// The query starts with a lane bitmask which gets lanes/bits removed for every
343/// use we find.
344static LaneBitmask findUseBetween(unsigned Reg, LaneBitmask LastUseMask,
345 SlotIndex PriorUseIdx, SlotIndex NextUseIdx,
347 const SIRegisterInfo *TRI,
348 const LiveIntervals *LIS,
349 bool Upward = false) {
350 for (const MachineOperand &MO : MRI.use_nodbg_operands(Reg)) {
351 if (MO.isUndef())
352 continue;
353 const MachineInstr *MI = MO.getParent();
354 SlotIndex InstSlot = LIS->getInstructionIndex(*MI).getRegSlot();
355 bool InRange = Upward ? (InstSlot > PriorUseIdx && InstSlot <= NextUseIdx)
356 : (InstSlot >= PriorUseIdx && InstSlot < NextUseIdx);
357 if (!InRange)
358 continue;
359
360 unsigned SubRegIdx = MO.getSubReg();
361 LaneBitmask UseMask = TRI->getSubRegIndexLaneMask(SubRegIdx);
362 LastUseMask &= ~UseMask;
363 if (LastUseMask.none())
364 return LaneBitmask::getNone();
365 }
366 return LastUseMask;
367}
368
369////////////////////////////////////////////////////////////////////////////////
370// GCNRPTarget
371
373 : GCNRPTarget(RP, MF) {
374 const Function &F = MF.getFunction();
375 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
376 setTarget(ST.getMaxNumSGPRs(F), ST.getMaxNumVGPRs(F));
377}
378
379GCNRPTarget::GCNRPTarget(unsigned NumSGPRs, unsigned NumVGPRs,
380 const MachineFunction &MF, const GCNRegPressure &RP)
381 : GCNRPTarget(RP, MF) {
382 setTarget(NumSGPRs, NumVGPRs);
383}
384
385GCNRPTarget::GCNRPTarget(unsigned Occupancy, const MachineFunction &MF,
386 const GCNRegPressure &RP)
387 : GCNRPTarget(RP, MF) {
388 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
389 unsigned DynamicVGPRBlockSize =
391 setTarget(ST.getMaxNumSGPRs(Occupancy, /*Addressable=*/false),
392 ST.getMaxNumVGPRs(Occupancy, DynamicVGPRBlockSize));
393}
394
395void GCNRPTarget::setTarget(unsigned NumSGPRs, unsigned NumVGPRs) {
396 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
397 MaxSGPRs = std::min(ST.getAddressableNumSGPRs(), NumSGPRs);
398 MaxVGPRs = std::min(ST.getAddressableNumArchVGPRs(), NumVGPRs);
399 if (UnifiedRF) {
400 unsigned DynamicVGPRBlockSize =
401 MF.getInfo<SIMachineFunctionInfo>()->getDynamicVGPRBlockSize();
402 MaxUnifiedVGPRs =
403 std::min(ST.getAddressableNumVGPRs(DynamicVGPRBlockSize), NumVGPRs);
404 } else {
405 MaxUnifiedVGPRs = 0;
406 }
407}
408
410 const MachineRegisterInfo &MRI = MF.getRegInfo();
411 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
412 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
413 const SIRegisterInfo *SRI = static_cast<const SIRegisterInfo *>(TRI);
414
415 if (SRI->isSGPRClass(RC))
416 return RP.getSGPRNum() > MaxSGPRs;
417 unsigned NumVGPRs =
418 SRI->isAGPRClass(RC) ? RP.getAGPRNum() : RP.getArchVGPRNum();
419 // The addressable limit must always be respected.
420 if (NumVGPRs > MaxVGPRs)
421 return true;
422 // For unified RFs, combined VGPR usage limit must be respected as well.
423 return UnifiedRF && RP.getVGPRNum(true) > MaxUnifiedVGPRs;
424}
425
427 if (RP.getSGPRNum() > MaxSGPRs || RP.getVGPRNum(false) > MaxVGPRs)
428 return false;
429 if (UnifiedRF && RP.getVGPRNum(true) > MaxUnifiedVGPRs)
430 return false;
431 return true;
432}
433
434///////////////////////////////////////////////////////////////////////////////
435// GCNRPTracker
436
438 const LiveIntervals &LIS,
440 LaneBitmask LaneMaskFilter) {
441 return getLiveLaneMask(LIS.getInterval(Reg), SI, MRI, LaneMaskFilter);
442}
443
446 LaneBitmask LaneMaskFilter) {
447 LaneBitmask LiveMask;
448 if (LI.hasSubRanges()) {
449 for (const auto &S : LI.subranges())
450 if ((S.LaneMask & LaneMaskFilter).any() && S.liveAt(SI)) {
451 LiveMask |= S.LaneMask;
452 assert(LiveMask == (LiveMask & MRI.getMaxLaneMaskForVReg(LI.reg())));
453 }
454 } else if (LI.liveAt(SI)) {
455 LiveMask = MRI.getMaxLaneMaskForVReg(LI.reg());
456 }
457 LiveMask &= LaneMaskFilter;
458 return LiveMask;
459}
460
462 const LiveIntervals &LIS,
464 GCNRegPressure::RegKind RegKind) {
466 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
467 auto Reg = Register::index2VirtReg(I);
468 if (RegKind != GCNRegPressure::TOTAL_KINDS &&
469 GCNRegPressure::getRegKind(Reg, MRI) != RegKind)
470 continue;
471 if (!LIS.hasInterval(Reg))
472 continue;
473 auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI);
474 if (LiveMask.any())
475 LiveRegs[Reg] = LiveMask;
476 }
477 return LiveRegs;
478}
479
481 const LiveRegSet *LiveRegsCopy,
482 bool After) {
483 const MachineFunction &MF = *MI.getMF();
484 MRI = &MF.getRegInfo();
485 if (LiveRegsCopy) {
486 if (&LiveRegs != LiveRegsCopy)
487 LiveRegs = *LiveRegsCopy;
488 } else {
489 LiveRegs = After ? getLiveRegsAfter(MI, LIS)
491 }
492
494}
495
497 const LiveRegSet &LiveRegs_) {
498 MRI = &MRI_;
499 LiveRegs = LiveRegs_;
500 LastTrackedMI = nullptr;
501 MaxPressure = CurPressure = getRegPressure(MRI_, LiveRegs_);
502}
503
504/// Mostly copy/paste from CodeGen/RegisterPressure.cpp
506 SlotIndex Pos) const {
508 LIS, *MRI, true, RegUnit, Pos.getBaseIndex(), LaneBitmask::getNone(),
509 [](const LiveRange &LR, SlotIndex Pos) {
510 const LiveRange::Segment *S = LR.getSegmentContaining(Pos);
511 return S != nullptr && S->end == Pos.getRegSlot();
512 });
513}
514
515////////////////////////////////////////////////////////////////////////////////
516// GCNUpwardRPTracker
517
519 assert(MRI && "call reset first");
520
521 LastTrackedMI = &MI;
522
523 if (MI.isDebugInstr())
524 return;
525
526 // Kill all defs.
527 GCNRegPressure DefPressure, ECDefPressure;
528 bool HasECDefs = false;
529 for (const MachineOperand &MO : MI.all_defs()) {
530 if (!MO.getReg().isVirtual())
531 continue;
532
533 Register Reg = MO.getReg();
534 LaneBitmask DefMask = getDefRegMask(MO, *MRI);
535
536 // Treat a def as fully live at the moment of definition: keep a record.
537 if (MO.isEarlyClobber()) {
538 ECDefPressure.inc(Reg, LaneBitmask::getNone(), DefMask, *MRI);
539 HasECDefs = true;
540 } else
541 DefPressure.inc(Reg, LaneBitmask::getNone(), DefMask, *MRI);
542
543 auto I = LiveRegs.find(Reg);
544 if (I == LiveRegs.end())
545 continue;
546
547 LaneBitmask &LiveMask = I->second;
548 LaneBitmask PrevMask = LiveMask;
549 LiveMask &= ~DefMask;
550 CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
551 if (LiveMask.none())
552 LiveRegs.erase(I);
553 }
554
555 // Update MaxPressure with defs pressure.
556 DefPressure += CurPressure;
557 if (HasECDefs)
558 DefPressure += ECDefPressure;
559 MaxPressure = max(DefPressure, MaxPressure);
560
561 // Make uses alive.
563 collectVirtualRegUses(RegUses, MI, LIS, *MRI);
564 for (const VRegMaskOrUnit &U : RegUses) {
565 LaneBitmask &LiveMask = LiveRegs[U.RegUnit];
566 LaneBitmask PrevMask = LiveMask;
567 LiveMask |= U.LaneMask;
568 CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI);
569 }
570
571 // Update MaxPressure with uses plus early-clobber defs pressure.
572 MaxPressure = HasECDefs ? max(CurPressure + ECDefPressure, MaxPressure)
574
576}
577
578////////////////////////////////////////////////////////////////////////////////
579// GCNDownwardRPTracker
580
582 const LiveRegSet *LiveRegsCopy) {
583 MRI = &MI.getParent()->getParent()->getRegInfo();
584 LastTrackedMI = nullptr;
585 MBBEnd = MI.getParent()->end();
586 NextMI = &MI;
587 NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
588 if (NextMI == MBBEnd)
589 return false;
590 GCNRPTracker::reset(*NextMI, LiveRegsCopy, false);
591 return true;
592}
593
595 bool UseInternalIterator) {
596 assert(MRI && "call reset first");
598 const MachineInstr *CurrMI;
599 if (UseInternalIterator) {
600 if (!LastTrackedMI)
601 return NextMI == MBBEnd;
602
603 assert(NextMI == MBBEnd || !NextMI->isDebugInstr());
604 CurrMI = LastTrackedMI;
605
606 SI = NextMI == MBBEnd
607 ? LIS.getInstructionIndex(*LastTrackedMI).getDeadSlot()
608 : LIS.getInstructionIndex(*NextMI).getBaseIndex();
609 } else { //! UseInternalIterator
610 SI = LIS.getInstructionIndex(*MI).getBaseIndex();
611 CurrMI = MI;
612 }
613
614 assert(SI.isValid());
615
616 // Remove dead registers or mask bits.
617 SmallSet<Register, 8> SeenRegs;
618 for (auto &MO : CurrMI->operands()) {
619 if (!MO.isReg() || !MO.getReg().isVirtual())
620 continue;
621 if (MO.isUse() && !MO.readsReg())
622 continue;
623 if (!UseInternalIterator && MO.isDef())
624 continue;
625 if (!SeenRegs.insert(MO.getReg()).second)
626 continue;
627 const LiveInterval &LI = LIS.getInterval(MO.getReg());
628 if (LI.hasSubRanges()) {
629 auto It = LiveRegs.end();
630 for (const auto &S : LI.subranges()) {
631 if (!S.liveAt(SI)) {
632 if (It == LiveRegs.end()) {
633 It = LiveRegs.find(MO.getReg());
634 if (It == LiveRegs.end())
635 llvm_unreachable("register isn't live");
636 }
637 auto PrevMask = It->second;
638 It->second &= ~S.LaneMask;
639 CurPressure.inc(MO.getReg(), PrevMask, It->second, *MRI);
640 }
641 }
642 if (It != LiveRegs.end() && It->second.none())
643 LiveRegs.erase(It);
644 } else if (!LI.liveAt(SI)) {
645 auto It = LiveRegs.find(MO.getReg());
646 if (It == LiveRegs.end())
647 llvm_unreachable("register isn't live");
648 CurPressure.inc(MO.getReg(), It->second, LaneBitmask::getNone(), *MRI);
649 LiveRegs.erase(It);
650 }
651 }
652
654
655 LastTrackedMI = nullptr;
656
657 return UseInternalIterator && (NextMI == MBBEnd);
658}
659
661 bool UseInternalIterator) {
662 if (UseInternalIterator) {
663 LastTrackedMI = &*NextMI++;
664 NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
665 } else {
667 }
668
669 const MachineInstr *CurrMI = LastTrackedMI;
670
671 // Add new registers or mask bits.
672 for (const auto &MO : CurrMI->all_defs()) {
673 Register Reg = MO.getReg();
674 if (!Reg.isVirtual())
675 continue;
676 auto &LiveMask = LiveRegs[Reg];
677 auto PrevMask = LiveMask;
678 LiveMask |= getDefRegMask(MO, *MRI);
679 CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
680 }
681
683}
684
685bool GCNDownwardRPTracker::advance(MachineInstr *MI, bool UseInternalIterator) {
686 if (UseInternalIterator && NextMI == MBBEnd)
687 return false;
688
689 advanceBeforeNext(MI, UseInternalIterator);
690 advanceToNext(MI, UseInternalIterator);
691 if (!UseInternalIterator) {
692 // We must remove any dead def lanes from the current RP
693 advanceBeforeNext(MI, true);
694 }
695 return true;
696}
697
699 while (NextMI != End)
700 if (!advance()) return false;
701 return true;
702}
703
706 const LiveRegSet *LiveRegsCopy) {
707 reset(*Begin, LiveRegsCopy);
708 return advance(End);
709}
710
712 const GCNRPTracker::LiveRegSet &TrackedLR,
713 const TargetRegisterInfo *TRI, StringRef Pfx) {
714 return Printable([&LISLR, &TrackedLR, TRI, Pfx](raw_ostream &OS) {
715 for (auto const &P : TrackedLR) {
716 auto I = LISLR.find(P.first);
717 if (I == LISLR.end()) {
718 OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
719 << " isn't found in LIS reported set\n";
720 } else if (I->second != P.second) {
721 OS << Pfx << printReg(P.first, TRI)
722 << " masks doesn't match: LIS reported " << PrintLaneMask(I->second)
723 << ", tracked " << PrintLaneMask(P.second) << '\n';
724 }
725 }
726 for (auto const &P : LISLR) {
727 auto I = TrackedLR.find(P.first);
728 if (I == TrackedLR.end()) {
729 OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
730 << " isn't found in tracked set\n";
731 }
732 }
733 });
734}
735
738 const SIRegisterInfo *TRI) const {
739 assert(!MI->isDebugOrPseudoInstr() && "Expect a nondebug instruction.");
740
741 SlotIndex SlotIdx;
742 SlotIdx = LIS.getInstructionIndex(*MI).getRegSlot();
743
744 // Account for register pressure similar to RegPressureTracker::recede().
745 RegisterOperands RegOpers;
746 RegOpers.collect(*MI, *TRI, *MRI, true, /*IgnoreDead=*/false);
747 RegOpers.adjustLaneLiveness(LIS, *MRI, SlotIdx);
748 GCNRegPressure TempPressure = CurPressure;
749
750 for (const VRegMaskOrUnit &Use : RegOpers.Uses) {
751 Register Reg = Use.RegUnit;
752 if (!Reg.isVirtual())
753 continue;
754 LaneBitmask LastUseMask = getLastUsedLanes(Reg, SlotIdx);
755 if (LastUseMask.none())
756 continue;
757 // The LastUseMask is queried from the liveness information of instruction
758 // which may be further down the schedule. Some lanes may actually not be
759 // last uses for the current position.
760 // FIXME: allow the caller to pass in the list of vreg uses that remain
761 // to be bottom-scheduled to avoid searching uses at each query.
762 SlotIndex CurrIdx;
763 const MachineBasicBlock *MBB = MI->getParent();
765 LastTrackedMI ? LastTrackedMI : MBB->begin(), MBB->end());
766 if (IdxPos == MBB->end()) {
767 CurrIdx = LIS.getMBBEndIdx(MBB);
768 } else {
769 CurrIdx = LIS.getInstructionIndex(*IdxPos).getRegSlot();
770 }
771
772 LastUseMask =
773 findUseBetween(Reg, LastUseMask, CurrIdx, SlotIdx, *MRI, TRI, &LIS);
774 if (LastUseMask.none())
775 continue;
776
777 auto It = LiveRegs.find(Reg);
778 LaneBitmask LiveMask = It != LiveRegs.end() ? It->second : LaneBitmask(0);
779 LaneBitmask NewMask = LiveMask & ~LastUseMask;
780 TempPressure.inc(Reg, LiveMask, NewMask, *MRI);
781 }
782
783 // Generate liveness for defs.
784 for (const VRegMaskOrUnit &Def : RegOpers.Defs) {
785 Register Reg = Def.RegUnit;
786 if (!Reg.isVirtual())
787 continue;
788 auto It = LiveRegs.find(Reg);
789 LaneBitmask LiveMask = It != LiveRegs.end() ? It->second : LaneBitmask(0);
790 LaneBitmask NewMask = LiveMask | Def.LaneMask;
791 TempPressure.inc(Reg, LiveMask, NewMask, *MRI);
792 }
793
794 return TempPressure;
795}
796
798 const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
799 const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
800 const auto &TrackedLR = LiveRegs;
801
802 if (!isEqual(LISLR, TrackedLR)) {
803 dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
804 " LIS reported livesets mismatch:\n"
805 << print(LISLR, *MRI);
806 reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo());
807 return false;
808 }
809
810 auto LISPressure = getRegPressure(*MRI, LISLR);
811 if (LISPressure != CurPressure) {
812 dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: "
813 << print(CurPressure) << "LIS rpt: " << print(LISPressure);
814 return false;
815 }
816 return true;
817}
818
820 const MachineRegisterInfo &MRI) {
821 return Printable([&LiveRegs, &MRI](raw_ostream &OS) {
822 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
823 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
825 auto It = LiveRegs.find(Reg);
826 if (It != LiveRegs.end() && It->second.any())
827 OS << ' ' << printVRegOrUnit(Reg, TRI) << ':'
828 << PrintLaneMask(It->second);
829 }
830 OS << '\n';
831 });
832}
833
834void GCNRegPressure::dump() const { dbgs() << print(*this); }
835
837 "amdgpu-print-rp-downward",
838 cl::desc("Use GCNDownwardRPTracker for GCNRegPressurePrinter pass"),
839 cl::init(false), cl::Hidden);
840
843
844INITIALIZE_PASS(GCNRegPressurePrinter, "amdgpu-print-rp", "", true, true)
845
846// Return lanemask of Reg's subregs that are live-through at [Begin, End] and
847// are fully covered by Mask.
848static LaneBitmask
850 Register Reg, SlotIndex Begin, SlotIndex End,
851 LaneBitmask Mask = LaneBitmask::getAll()) {
852
853 auto IsInOneSegment = [Begin, End](const LiveRange &LR) -> bool {
854 auto *Segment = LR.getSegmentContaining(Begin);
855 return Segment && Segment->contains(End);
856 };
857
858 LaneBitmask LiveThroughMask;
859 const LiveInterval &LI = LIS.getInterval(Reg);
860 if (LI.hasSubRanges()) {
861 for (auto &SR : LI.subranges()) {
862 if ((SR.LaneMask & Mask) == SR.LaneMask && IsInOneSegment(SR))
863 LiveThroughMask |= SR.LaneMask;
864 }
865 } else {
866 LaneBitmask RegMask = MRI.getMaxLaneMaskForVReg(Reg);
867 if ((RegMask & Mask) == RegMask && IsInOneSegment(LI))
868 LiveThroughMask = RegMask;
869 }
870
871 return LiveThroughMask;
872}
873
875 const MachineRegisterInfo &MRI = MF.getRegInfo();
876 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
878
879 auto &OS = dbgs();
880
881// Leading spaces are important for YAML syntax.
882#define PFX " "
883
884 OS << "---\nname: " << MF.getName() << "\nbody: |\n";
885
886 auto printRP = [](const GCNRegPressure &RP) {
887 return Printable([&RP](raw_ostream &OS) {
888 OS << format(PFX " %-5d", RP.getSGPRNum())
889 << format(" %-5d", RP.getVGPRNum(false));
890 });
891 };
892
893 auto ReportLISMismatchIfAny = [&](const GCNRPTracker::LiveRegSet &TrackedLR,
894 const GCNRPTracker::LiveRegSet &LISLR) {
895 if (LISLR != TrackedLR) {
896 OS << PFX " mis LIS: " << llvm::print(LISLR, MRI)
897 << reportMismatch(LISLR, TrackedLR, TRI, PFX " ");
898 }
899 };
900
901 // Register pressure before and at an instruction (in program order).
903
904 for (auto &MBB : MF) {
905 RP.clear();
906 RP.reserve(MBB.size());
907
908 OS << PFX;
909 MBB.printName(OS);
910 OS << ":\n";
911
912 SlotIndex MBBStartSlot = LIS.getSlotIndexes()->getMBBStartIdx(&MBB);
913 SlotIndex MBBLastSlot = LIS.getSlotIndexes()->getMBBLastIdx(&MBB);
914
915 GCNRPTracker::LiveRegSet LiveIn, LiveOut;
916 GCNRegPressure RPAtMBBEnd;
917
918 if (UseDownwardTracker) {
919 if (MBB.empty()) {
920 LiveIn = LiveOut = getLiveRegs(MBBStartSlot, LIS, MRI);
921 RPAtMBBEnd = getRegPressure(MRI, LiveIn);
922 } else {
923 GCNDownwardRPTracker RPT(LIS);
924 RPT.reset(MBB.front());
925
926 LiveIn = RPT.getLiveRegs();
927
928 while (!RPT.advanceBeforeNext()) {
929 GCNRegPressure RPBeforeMI = RPT.getPressure();
930 RPT.advanceToNext();
931 RP.emplace_back(RPBeforeMI, RPT.getPressure());
932 }
933
934 LiveOut = RPT.getLiveRegs();
935 RPAtMBBEnd = RPT.getPressure();
936 }
937 } else {
938 GCNUpwardRPTracker RPT(LIS);
939 RPT.reset(MRI, MBBLastSlot);
940
941 LiveOut = RPT.getLiveRegs();
942 RPAtMBBEnd = RPT.getPressure();
943
944 for (auto &MI : reverse(MBB)) {
945 RPT.resetMaxPressure();
946 RPT.recede(MI);
947 if (!MI.isDebugInstr())
948 RP.emplace_back(RPT.getPressure(), RPT.getMaxPressure());
949 }
950
951 LiveIn = RPT.getLiveRegs();
952 }
953
954 OS << PFX " Live-in: " << llvm::print(LiveIn, MRI);
956 ReportLISMismatchIfAny(LiveIn, getLiveRegs(MBBStartSlot, LIS, MRI));
957
958 OS << PFX " SGPR VGPR\n";
959 int I = 0;
960 for (auto &MI : MBB) {
961 if (!MI.isDebugInstr()) {
962 auto &[RPBeforeInstr, RPAtInstr] =
963 RP[UseDownwardTracker ? I : (RP.size() - 1 - I)];
964 ++I;
965 OS << printRP(RPBeforeInstr) << '\n' << printRP(RPAtInstr) << " ";
966 } else
967 OS << PFX " ";
968 MI.print(OS);
969 }
970 OS << printRP(RPAtMBBEnd) << '\n';
971
972 OS << PFX " Live-out:" << llvm::print(LiveOut, MRI);
974 ReportLISMismatchIfAny(LiveOut, getLiveRegs(MBBLastSlot, LIS, MRI));
975
976 GCNRPTracker::LiveRegSet LiveThrough;
977 for (auto [Reg, Mask] : LiveIn) {
978 LaneBitmask MaskIntersection = Mask & LiveOut.lookup(Reg);
979 if (MaskIntersection.any()) {
981 MRI, LIS, Reg, MBBStartSlot, MBBLastSlot, MaskIntersection);
982 if (LTMask.any())
983 LiveThrough[Reg] = LTMask;
984 }
985 }
986 OS << PFX " Live-thr:" << llvm::print(LiveThrough, MRI);
987 OS << printRP(getRegPressure(MRI, LiveThrough)) << '\n';
988 }
989 OS << "...\n";
990 return false;
991
992#undef PFX
993}
994
995#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
998 LiveIntervals &LIS,
999 const MachineLoopInfo *MLI) {
1000
1001 const MachineRegisterInfo &MRI = MF.getRegInfo();
1002 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
1003 auto &OS = dbgs();
1004 const char *RegName = GCNRegPressure::getName(Kind);
1005
1006 unsigned MaxNumRegs = 0;
1007 const MachineInstr *MaxPressureMI = nullptr;
1008 GCNUpwardRPTracker RPT(LIS);
1009 for (const MachineBasicBlock &MBB : MF) {
1011 for (const MachineInstr &MI : reverse(MBB)) {
1012 RPT.recede(MI);
1013 unsigned NumRegs = RPT.getMaxPressure().getNumRegs(Kind);
1014 if (NumRegs > MaxNumRegs) {
1015 MaxNumRegs = NumRegs;
1016 MaxPressureMI = &MI;
1017 }
1018 }
1019 }
1020
1021 SlotIndex MISlot = LIS.getInstructionIndex(*MaxPressureMI);
1022
1023 // Max pressure can occur at either the early-clobber or register slot.
1024 // Choose the maximum liveset between both slots. This is ugly but this is
1025 // diagnostic code.
1026 SlotIndex ECSlot = MISlot.getRegSlot(true);
1027 SlotIndex RSlot = MISlot.getRegSlot(false);
1028 GCNRPTracker::LiveRegSet ECLiveSet = getLiveRegs(ECSlot, LIS, MRI, Kind);
1029 GCNRPTracker::LiveRegSet RLiveSet = getLiveRegs(RSlot, LIS, MRI, Kind);
1030 unsigned ECNumRegs = getRegPressure(MRI, ECLiveSet).getNumRegs(Kind);
1031 unsigned RNumRegs = getRegPressure(MRI, RLiveSet).getNumRegs(Kind);
1032 GCNRPTracker::LiveRegSet *LiveSet =
1033 ECNumRegs > RNumRegs ? &ECLiveSet : &RLiveSet;
1034 SlotIndex MaxPressureSlot = ECNumRegs > RNumRegs ? ECSlot : RSlot;
1035 assert(getRegPressure(MRI, *LiveSet).getNumRegs(Kind) == MaxNumRegs);
1036
1037 // Split live registers into single-def and multi-def sets.
1038 GCNRegPressure SDefPressure, MDefPressure;
1039 SmallVector<Register, 16> SDefRegs, MDefRegs;
1040 for (auto [Reg, LaneMask] : *LiveSet) {
1041 assert(GCNRegPressure::getRegKind(Reg, MRI) == Kind);
1042 LiveInterval &LI = LIS.getInterval(Reg);
1043 if (LI.getNumValNums() == 1 ||
1044 (LI.hasSubRanges() &&
1045 llvm::all_of(LI.subranges(), [](const LiveInterval::SubRange &SR) {
1046 return SR.getNumValNums() == 1;
1047 }))) {
1048 SDefPressure.inc(Reg, LaneBitmask::getNone(), LaneMask, MRI);
1049 SDefRegs.push_back(Reg);
1050 } else {
1051 MDefPressure.inc(Reg, LaneBitmask::getNone(), LaneMask, MRI);
1052 MDefRegs.push_back(Reg);
1053 }
1054 }
1055 unsigned SDefNumRegs = SDefPressure.getNumRegs(Kind);
1056 unsigned MDefNumRegs = MDefPressure.getNumRegs(Kind);
1057 assert(SDefNumRegs + MDefNumRegs == MaxNumRegs);
1058
1059 auto printLoc = [&](const MachineBasicBlock *MBB, SlotIndex SI) {
1060 return Printable([&, MBB, SI](raw_ostream &OS) {
1061 OS << SI << ':' << printMBBReference(*MBB);
1062 if (MLI)
1063 if (const MachineLoop *ML = MLI->getLoopFor(MBB))
1064 OS << " (LoopHdr " << printMBBReference(*ML->getHeader())
1065 << ", Depth " << ML->getLoopDepth() << ")";
1066 });
1067 };
1068
1069 auto PrintRegInfo = [&](Register Reg, LaneBitmask LiveMask) {
1070 GCNRegPressure RegPressure;
1071 RegPressure.inc(Reg, LaneBitmask::getNone(), LiveMask, MRI);
1072 OS << " " << printReg(Reg, TRI) << ':'
1073 << TRI->getRegClassName(MRI.getRegClass(Reg)) << ", LiveMask "
1074 << PrintLaneMask(LiveMask) << " (" << RegPressure.getNumRegs(Kind) << ' '
1075 << RegName << "s)\n";
1076
1077 // Use std::map to sort def/uses by SlotIndex.
1078 std::map<SlotIndex, const MachineInstr *> Instrs;
1079 for (const MachineInstr &MI : MRI.reg_nodbg_instructions(Reg)) {
1080 Instrs[LIS.getInstructionIndex(MI).getRegSlot()] = &MI;
1081 }
1082
1083 for (const auto &[SI, MI] : Instrs) {
1084 OS << " ";
1085 if (MI->definesRegister(Reg, TRI))
1086 OS << "def ";
1087 if (MI->readsRegister(Reg, TRI))
1088 OS << "use ";
1089 OS << printLoc(MI->getParent(), SI) << ": " << *MI;
1090 }
1091 };
1092
1093 OS << "\n*** Register pressure info (" << RegName << "s) for " << MF.getName()
1094 << " ***\n";
1095 OS << "Max pressure is " << MaxNumRegs << ' ' << RegName << "s at "
1096 << printLoc(MaxPressureMI->getParent(), MaxPressureSlot) << ": "
1097 << *MaxPressureMI;
1098
1099 OS << "\nLive registers with single definition (" << SDefNumRegs << ' '
1100 << RegName << "s):\n";
1101
1102 // Sort SDefRegs by number of uses (smallest first)
1103 llvm::sort(SDefRegs, [&](Register A, Register B) {
1104 return std::distance(MRI.use_nodbg_begin(A), MRI.use_nodbg_end()) <
1105 std::distance(MRI.use_nodbg_begin(B), MRI.use_nodbg_end());
1106 });
1107
1108 for (const Register Reg : SDefRegs) {
1109 PrintRegInfo(Reg, LiveSet->lookup(Reg));
1110 }
1111
1112 OS << "\nLive registers with multiple definitions (" << MDefNumRegs << ' '
1113 << RegName << "s):\n";
1114 for (const Register Reg : MDefRegs) {
1115 PrintRegInfo(Reg, LiveSet->lookup(Reg));
1116 }
1117}
1118#endif
unsigned const MachineRegisterInfo * MRI
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:638
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:55
#define I(x, y, z)
Definition MD5.cpp:58
Register Reg
Register const TargetRegisterInfo * TRI
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
static LaneBitmask findUseBetween(unsigned Reg, LaneBitmask LastUseMask, SlotIndex PriorUseIdx, SlotIndex NextUseIdx, const MachineRegisterInfo &MRI, const LiveIntervals *LIS)
Helper to find a vreg use between two indices [PriorUseIdx, NextUseIdx).
static LaneBitmask getLanesWithProperty(const LiveIntervals &LIS, const MachineRegisterInfo &MRI, bool TrackLaneMasks, Register RegUnit, SlotIndex Pos, LaneBitmask SafeDefault, bool(*Property)(const LiveRange &LR, SlotIndex Pos))
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition DenseMap.h:194
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:167
unsigned size() const
Definition DenseMap.h:110
iterator end()
Definition DenseMap.h:81
bool advanceBeforeNext(MachineInstr *MI=nullptr, bool UseInternalIterator=true)
Move to the state right before the next MI or after the end of MBB.
bool advance(MachineInstr *MI=nullptr, bool UseInternalIterator=true)
Move to the state at the next MI.
GCNRegPressure bumpDownwardPressure(const MachineInstr *MI, const SIRegisterInfo *TRI) const
Mostly copy/paste from CodeGen/RegisterPressure.cpp Calculate the impact MI will have on CurPressure ...
bool reset(const MachineInstr &MI, const LiveRegSet *LiveRegs=nullptr)
Reset tracker to the point before the MI filling LiveRegs upon this point using LIS.
void advanceToNext(MachineInstr *MI=nullptr, bool UseInternalIterator=true)
Move to the state at the MI, advanceBeforeNext has to be called first.
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 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).
GCNRegPressure getPressure() const
const decltype(LiveRegs) & getLiveRegs() const
const MachineInstr * LastTrackedMI
GCNRegPressure CurPressure
DenseMap< unsigned, LaneBitmask > LiveRegSet
GCNRegPressure MaxPressure
void reset(const MachineInstr &MI, const LiveRegSet *LiveRegsCopy, bool After)
LaneBitmask getLastUsedLanes(Register RegUnit, SlotIndex Pos) const
Mostly copy/paste from CodeGen/RegisterPressure.cpp.
const MachineRegisterInfo * MRI
const LiveIntervals & LIS
void reset(const MachineRegisterInfo &MRI, SlotIndex SI)
reset tracker at the specified slot index SI.
void recede(const MachineInstr &MI)
Move to the state of RP just before the MI .
const GCNRegPressure & getMaxPressure() const
bool isValid() const
returns whether the tracker's state after receding MI corresponds to reported by LIS.
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.
LiveRange * getCachedRegUnit(unsigned Unit)
Return the live range for register unit Unit if it has already been computed, or nullptr if it hasn't...
LiveInterval & getInterval(Register Reg)
This class represents the liveness of a register, stack slot, etc.
bool liveAt(SlotIndex index) const
unsigned getNumValNums() const
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
filtered_mop_range all_defs()
Returns an iterator range over all operands that are (explicit or implicit) register defs.
mop_range operands()
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,...
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 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...
LLVM_ABI void adjustLaneLiveness(const LiveIntervals &LIS, const MachineRegisterInfo &MRI, SlotIndex Pos, MachineInstr *AddFlagsMI=nullptr)
Use liveness information to find out which uses/defs are partially undefined/dead and adjust the VReg...
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:19
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition Register.h:67
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:74
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)
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:66
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(unsigned Num) const
Returns the index past the last valid index in the given basic block.
SlotIndex getMBBStartIdx(unsigned Num) const
Returns the first index in the given basic block number.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:133
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:183
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.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
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
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.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
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:1725
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.
GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI, const LiveIntervals &LIS)
auto reverse(ContainerTy &&C)
Definition STLExtras.h:406
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1622
LLVM_ABI Printable printVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *TRI)
Create Printable object to print virtual registers and physical registers on a raw_ostream.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:129
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:1758
GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI, const LiveIntervals &LIS)
LLVM_ABI void dumpMaxRegPressure(MachineFunction &MF, GCNRegPressure::RegKind Kind, LiveIntervals &LIS, const MachineLoopInfo *MLI)
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.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:869
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 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