xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- GCNRegPressure.cpp -------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric ///
95ffd83dbSDimitry Andric /// \file
105ffd83dbSDimitry Andric /// This file implements the GCNRegPressure class.
115ffd83dbSDimitry Andric ///
125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "GCNRegPressure.h"
155f757f3fSDimitry Andric #include "AMDGPU.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterPressure.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric using namespace llvm;
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #define DEBUG_TYPE "machine-scheduler"
210b57cec5SDimitry Andric 
isEqual(const GCNRPTracker::LiveRegSet & S1,const GCNRPTracker::LiveRegSet & S2)220b57cec5SDimitry Andric bool llvm::isEqual(const GCNRPTracker::LiveRegSet &S1,
230b57cec5SDimitry Andric                    const GCNRPTracker::LiveRegSet &S2) {
240b57cec5SDimitry Andric   if (S1.size() != S2.size())
250b57cec5SDimitry Andric     return false;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric   for (const auto &P : S1) {
280b57cec5SDimitry Andric     auto I = S2.find(P.first);
290b57cec5SDimitry Andric     if (I == S2.end() || I->second != P.second)
300b57cec5SDimitry Andric       return false;
310b57cec5SDimitry Andric   }
320b57cec5SDimitry Andric   return true;
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric ///////////////////////////////////////////////////////////////////////////////
360b57cec5SDimitry Andric // GCNRegPressure
370b57cec5SDimitry Andric 
getRegKind(Register Reg,const MachineRegisterInfo & MRI)38e8d8bef9SDimitry Andric unsigned GCNRegPressure::getRegKind(Register Reg,
390b57cec5SDimitry Andric                                     const MachineRegisterInfo &MRI) {
40e8d8bef9SDimitry Andric   assert(Reg.isVirtual());
410b57cec5SDimitry Andric   const auto RC = MRI.getRegClass(Reg);
420b57cec5SDimitry Andric   auto STI = static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo());
434824e7fdSDimitry Andric   return STI->isSGPRClass(RC)
444824e7fdSDimitry Andric              ? (STI->getRegSizeInBits(*RC) == 32 ? SGPR32 : SGPR_TUPLE)
454824e7fdSDimitry Andric          : STI->isAGPRClass(RC)
464824e7fdSDimitry Andric              ? (STI->getRegSizeInBits(*RC) == 32 ? AGPR32 : AGPR_TUPLE)
474824e7fdSDimitry Andric              : (STI->getRegSizeInBits(*RC) == 32 ? VGPR32 : VGPR_TUPLE);
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
inc(unsigned Reg,LaneBitmask PrevMask,LaneBitmask NewMask,const MachineRegisterInfo & MRI)500b57cec5SDimitry Andric void GCNRegPressure::inc(unsigned Reg,
510b57cec5SDimitry Andric                          LaneBitmask PrevMask,
520b57cec5SDimitry Andric                          LaneBitmask NewMask,
530b57cec5SDimitry Andric                          const MachineRegisterInfo &MRI) {
545ffd83dbSDimitry Andric   if (SIRegisterInfo::getNumCoveredRegs(NewMask) ==
555ffd83dbSDimitry Andric       SIRegisterInfo::getNumCoveredRegs(PrevMask))
560b57cec5SDimitry Andric     return;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   int Sign = 1;
590b57cec5SDimitry Andric   if (NewMask < PrevMask) {
600b57cec5SDimitry Andric     std::swap(NewMask, PrevMask);
610b57cec5SDimitry Andric     Sign = -1;
620b57cec5SDimitry Andric   }
635ffd83dbSDimitry Andric 
640b57cec5SDimitry Andric   switch (auto Kind = getRegKind(Reg, MRI)) {
650b57cec5SDimitry Andric   case SGPR32:
660b57cec5SDimitry Andric   case VGPR32:
670b57cec5SDimitry Andric   case AGPR32:
680b57cec5SDimitry Andric     Value[Kind] += Sign;
690b57cec5SDimitry Andric     break;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   case SGPR_TUPLE:
720b57cec5SDimitry Andric   case VGPR_TUPLE:
730b57cec5SDimitry Andric   case AGPR_TUPLE:
740b57cec5SDimitry Andric     assert(PrevMask < NewMask);
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric     Value[Kind == SGPR_TUPLE ? SGPR32 : Kind == AGPR_TUPLE ? AGPR32 : VGPR32] +=
775ffd83dbSDimitry Andric       Sign * SIRegisterInfo::getNumCoveredRegs(~PrevMask & NewMask);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric     if (PrevMask.none()) {
800b57cec5SDimitry Andric       assert(NewMask.any());
815f757f3fSDimitry Andric       const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
825f757f3fSDimitry Andric       Value[Kind] +=
835f757f3fSDimitry Andric           Sign * TRI->getRegClassWeight(MRI.getRegClass(Reg)).RegWeight;
840b57cec5SDimitry Andric     }
850b57cec5SDimitry Andric     break;
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   default: llvm_unreachable("Unknown register kind");
880b57cec5SDimitry Andric   }
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
less(const MachineFunction & MF,const GCNRegPressure & O,unsigned MaxOccupancy) const91*0fca6ea1SDimitry Andric bool GCNRegPressure::less(const MachineFunction &MF, const GCNRegPressure &O,
920b57cec5SDimitry Andric                           unsigned MaxOccupancy) const {
93*0fca6ea1SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
94*0fca6ea1SDimitry Andric 
950b57cec5SDimitry Andric   const auto SGPROcc = std::min(MaxOccupancy,
960b57cec5SDimitry Andric                                 ST.getOccupancyWithNumSGPRs(getSGPRNum()));
97fe6060f1SDimitry Andric   const auto VGPROcc =
98fe6060f1SDimitry Andric     std::min(MaxOccupancy,
99fe6060f1SDimitry Andric              ST.getOccupancyWithNumVGPRs(getVGPRNum(ST.hasGFX90AInsts())));
1000b57cec5SDimitry Andric   const auto OtherSGPROcc = std::min(MaxOccupancy,
1010b57cec5SDimitry Andric                                 ST.getOccupancyWithNumSGPRs(O.getSGPRNum()));
102fe6060f1SDimitry Andric   const auto OtherVGPROcc =
103fe6060f1SDimitry Andric     std::min(MaxOccupancy,
104fe6060f1SDimitry Andric              ST.getOccupancyWithNumVGPRs(O.getVGPRNum(ST.hasGFX90AInsts())));
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   const auto Occ = std::min(SGPROcc, VGPROcc);
1070b57cec5SDimitry Andric   const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc);
108*0fca6ea1SDimitry Andric 
109*0fca6ea1SDimitry Andric   // Give first precedence to the better occupancy.
1100b57cec5SDimitry Andric   if (Occ != OtherOcc)
1110b57cec5SDimitry Andric     return Occ > OtherOcc;
1120b57cec5SDimitry Andric 
113*0fca6ea1SDimitry Andric   unsigned MaxVGPRs = ST.getMaxNumVGPRs(MF);
114*0fca6ea1SDimitry Andric   unsigned MaxSGPRs = ST.getMaxNumSGPRs(MF);
115*0fca6ea1SDimitry Andric 
116*0fca6ea1SDimitry Andric   // SGPR excess pressure conditions
117*0fca6ea1SDimitry Andric   unsigned ExcessSGPR = std::max(static_cast<int>(getSGPRNum() - MaxSGPRs), 0);
118*0fca6ea1SDimitry Andric   unsigned OtherExcessSGPR =
119*0fca6ea1SDimitry Andric       std::max(static_cast<int>(O.getSGPRNum() - MaxSGPRs), 0);
120*0fca6ea1SDimitry Andric 
121*0fca6ea1SDimitry Andric   auto WaveSize = ST.getWavefrontSize();
122*0fca6ea1SDimitry Andric   // The number of virtual VGPRs required to handle excess SGPR
123*0fca6ea1SDimitry Andric   unsigned VGPRForSGPRSpills = (ExcessSGPR + (WaveSize - 1)) / WaveSize;
124*0fca6ea1SDimitry Andric   unsigned OtherVGPRForSGPRSpills =
125*0fca6ea1SDimitry Andric       (OtherExcessSGPR + (WaveSize - 1)) / WaveSize;
126*0fca6ea1SDimitry Andric 
127*0fca6ea1SDimitry Andric   unsigned MaxArchVGPRs = ST.getAddressableNumArchVGPRs();
128*0fca6ea1SDimitry Andric 
129*0fca6ea1SDimitry Andric   // Unified excess pressure conditions, accounting for VGPRs used for SGPR
130*0fca6ea1SDimitry Andric   // spills
131*0fca6ea1SDimitry Andric   unsigned ExcessVGPR =
132*0fca6ea1SDimitry Andric       std::max(static_cast<int>(getVGPRNum(ST.hasGFX90AInsts()) +
133*0fca6ea1SDimitry Andric                                 VGPRForSGPRSpills - MaxVGPRs),
134*0fca6ea1SDimitry Andric                0);
135*0fca6ea1SDimitry Andric   unsigned OtherExcessVGPR =
136*0fca6ea1SDimitry Andric       std::max(static_cast<int>(O.getVGPRNum(ST.hasGFX90AInsts()) +
137*0fca6ea1SDimitry Andric                                 OtherVGPRForSGPRSpills - MaxVGPRs),
138*0fca6ea1SDimitry Andric                0);
139*0fca6ea1SDimitry Andric   // Arch VGPR excess pressure conditions, accounting for VGPRs used for SGPR
140*0fca6ea1SDimitry Andric   // spills
141*0fca6ea1SDimitry Andric   unsigned ExcessArchVGPR = std::max(
142*0fca6ea1SDimitry Andric       static_cast<int>(getVGPRNum(false) + VGPRForSGPRSpills - MaxArchVGPRs),
143*0fca6ea1SDimitry Andric       0);
144*0fca6ea1SDimitry Andric   unsigned OtherExcessArchVGPR =
145*0fca6ea1SDimitry Andric       std::max(static_cast<int>(O.getVGPRNum(false) + OtherVGPRForSGPRSpills -
146*0fca6ea1SDimitry Andric                                 MaxArchVGPRs),
147*0fca6ea1SDimitry Andric                0);
148*0fca6ea1SDimitry Andric   // AGPR excess pressure conditions
149*0fca6ea1SDimitry Andric   unsigned ExcessAGPR = std::max(
150*0fca6ea1SDimitry Andric       static_cast<int>(ST.hasGFX90AInsts() ? (getAGPRNum() - MaxArchVGPRs)
151*0fca6ea1SDimitry Andric                                            : (getAGPRNum() - MaxVGPRs)),
152*0fca6ea1SDimitry Andric       0);
153*0fca6ea1SDimitry Andric   unsigned OtherExcessAGPR = std::max(
154*0fca6ea1SDimitry Andric       static_cast<int>(ST.hasGFX90AInsts() ? (O.getAGPRNum() - MaxArchVGPRs)
155*0fca6ea1SDimitry Andric                                            : (O.getAGPRNum() - MaxVGPRs)),
156*0fca6ea1SDimitry Andric       0);
157*0fca6ea1SDimitry Andric 
158*0fca6ea1SDimitry Andric   bool ExcessRP = ExcessSGPR || ExcessVGPR || ExcessArchVGPR || ExcessAGPR;
159*0fca6ea1SDimitry Andric   bool OtherExcessRP = OtherExcessSGPR || OtherExcessVGPR ||
160*0fca6ea1SDimitry Andric                        OtherExcessArchVGPR || OtherExcessAGPR;
161*0fca6ea1SDimitry Andric 
162*0fca6ea1SDimitry Andric   // Give second precedence to the reduced number of spills to hold the register
163*0fca6ea1SDimitry Andric   // pressure.
164*0fca6ea1SDimitry Andric   if (ExcessRP || OtherExcessRP) {
165*0fca6ea1SDimitry Andric     // The difference in excess VGPR pressure, after including VGPRs used for
166*0fca6ea1SDimitry Andric     // SGPR spills
167*0fca6ea1SDimitry Andric     int VGPRDiff = ((OtherExcessVGPR + OtherExcessArchVGPR + OtherExcessAGPR) -
168*0fca6ea1SDimitry Andric                     (ExcessVGPR + ExcessArchVGPR + ExcessAGPR));
169*0fca6ea1SDimitry Andric 
170*0fca6ea1SDimitry Andric     int SGPRDiff = OtherExcessSGPR - ExcessSGPR;
171*0fca6ea1SDimitry Andric 
172*0fca6ea1SDimitry Andric     if (VGPRDiff != 0)
173*0fca6ea1SDimitry Andric       return VGPRDiff > 0;
174*0fca6ea1SDimitry Andric     if (SGPRDiff != 0) {
175*0fca6ea1SDimitry Andric       unsigned PureExcessVGPR =
176*0fca6ea1SDimitry Andric           std::max(static_cast<int>(getVGPRNum(ST.hasGFX90AInsts()) - MaxVGPRs),
177*0fca6ea1SDimitry Andric                    0) +
178*0fca6ea1SDimitry Andric           std::max(static_cast<int>(getVGPRNum(false) - MaxArchVGPRs), 0);
179*0fca6ea1SDimitry Andric       unsigned OtherPureExcessVGPR =
180*0fca6ea1SDimitry Andric           std::max(
181*0fca6ea1SDimitry Andric               static_cast<int>(O.getVGPRNum(ST.hasGFX90AInsts()) - MaxVGPRs),
182*0fca6ea1SDimitry Andric               0) +
183*0fca6ea1SDimitry Andric           std::max(static_cast<int>(O.getVGPRNum(false) - MaxArchVGPRs), 0);
184*0fca6ea1SDimitry Andric 
185*0fca6ea1SDimitry Andric       // If we have a special case where there is a tie in excess VGPR, but one
186*0fca6ea1SDimitry Andric       // of the pressures has VGPR usage from SGPR spills, prefer the pressure
187*0fca6ea1SDimitry Andric       // with SGPR spills.
188*0fca6ea1SDimitry Andric       if (PureExcessVGPR != OtherPureExcessVGPR)
189*0fca6ea1SDimitry Andric         return SGPRDiff < 0;
190*0fca6ea1SDimitry Andric       // If both pressures have the same excess pressure before and after
191*0fca6ea1SDimitry Andric       // accounting for SGPR spills, prefer fewer SGPR spills.
192*0fca6ea1SDimitry Andric       return SGPRDiff > 0;
193*0fca6ea1SDimitry Andric     }
194*0fca6ea1SDimitry Andric   }
195*0fca6ea1SDimitry Andric 
1960b57cec5SDimitry Andric   bool SGPRImportant = SGPROcc < VGPROcc;
1970b57cec5SDimitry Andric   const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc;
1980b57cec5SDimitry Andric 
199*0fca6ea1SDimitry Andric   // If both pressures disagree on what is more important compare vgprs.
2000b57cec5SDimitry Andric   if (SGPRImportant != OtherSGPRImportant) {
2010b57cec5SDimitry Andric     SGPRImportant = false;
2020b57cec5SDimitry Andric   }
2030b57cec5SDimitry Andric 
204*0fca6ea1SDimitry Andric   // Give third precedence to lower register tuple pressure.
2050b57cec5SDimitry Andric   bool SGPRFirst = SGPRImportant;
2060b57cec5SDimitry Andric   for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) {
2070b57cec5SDimitry Andric     if (SGPRFirst) {
2080b57cec5SDimitry Andric       auto SW = getSGPRTuplesWeight();
2090b57cec5SDimitry Andric       auto OtherSW = O.getSGPRTuplesWeight();
2100b57cec5SDimitry Andric       if (SW != OtherSW)
2110b57cec5SDimitry Andric         return SW < OtherSW;
2120b57cec5SDimitry Andric     } else {
2130b57cec5SDimitry Andric       auto VW = getVGPRTuplesWeight();
2140b57cec5SDimitry Andric       auto OtherVW = O.getVGPRTuplesWeight();
2150b57cec5SDimitry Andric       if (VW != OtherVW)
2160b57cec5SDimitry Andric         return VW < OtherVW;
2170b57cec5SDimitry Andric     }
2180b57cec5SDimitry Andric   }
219*0fca6ea1SDimitry Andric 
220*0fca6ea1SDimitry Andric   // Give final precedence to lower general RP.
2210b57cec5SDimitry Andric   return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()):
222fe6060f1SDimitry Andric                          (getVGPRNum(ST.hasGFX90AInsts()) <
223fe6060f1SDimitry Andric                           O.getVGPRNum(ST.hasGFX90AInsts()));
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric 
print(const GCNRegPressure & RP,const GCNSubtarget * ST)226bdd1243dSDimitry Andric Printable llvm::print(const GCNRegPressure &RP, const GCNSubtarget *ST) {
227bdd1243dSDimitry Andric   return Printable([&RP, ST](raw_ostream &OS) {
228bdd1243dSDimitry Andric     OS << "VGPRs: " << RP.Value[GCNRegPressure::VGPR32] << ' '
229bdd1243dSDimitry Andric        << "AGPRs: " << RP.getAGPRNum();
230bdd1243dSDimitry Andric     if (ST)
231bdd1243dSDimitry Andric       OS << "(O"
232bdd1243dSDimitry Andric          << ST->getOccupancyWithNumVGPRs(RP.getVGPRNum(ST->hasGFX90AInsts()))
233fe6060f1SDimitry Andric          << ')';
234bdd1243dSDimitry Andric     OS << ", SGPRs: " << RP.getSGPRNum();
235bdd1243dSDimitry Andric     if (ST)
236bdd1243dSDimitry Andric       OS << "(O" << ST->getOccupancyWithNumSGPRs(RP.getSGPRNum()) << ')';
237bdd1243dSDimitry Andric     OS << ", LVGPR WT: " << RP.getVGPRTuplesWeight()
238bdd1243dSDimitry Andric        << ", LSGPR WT: " << RP.getSGPRTuplesWeight();
239bdd1243dSDimitry Andric     if (ST)
240bdd1243dSDimitry Andric       OS << " -> Occ: " << RP.getOccupancy(*ST);
2410b57cec5SDimitry Andric     OS << '\n';
242bdd1243dSDimitry Andric   });
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
getDefRegMask(const MachineOperand & MO,const MachineRegisterInfo & MRI)2450b57cec5SDimitry Andric static LaneBitmask getDefRegMask(const MachineOperand &MO,
2460b57cec5SDimitry Andric                                  const MachineRegisterInfo &MRI) {
247e8d8bef9SDimitry Andric   assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual());
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   // We don't rely on read-undef flag because in case of tentative schedule
2500b57cec5SDimitry Andric   // tracking it isn't set correctly yet. This works correctly however since
2510b57cec5SDimitry Andric   // use mask has been tracked before using LIS.
2520b57cec5SDimitry Andric   return MO.getSubReg() == 0 ?
2530b57cec5SDimitry Andric     MRI.getMaxLaneMaskForVReg(MO.getReg()) :
2540b57cec5SDimitry Andric     MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric 
2575f757f3fSDimitry Andric static void
collectVirtualRegUses(SmallVectorImpl<RegisterMaskPair> & RegMaskPairs,const MachineInstr & MI,const LiveIntervals & LIS,const MachineRegisterInfo & MRI)2585f757f3fSDimitry Andric collectVirtualRegUses(SmallVectorImpl<RegisterMaskPair> &RegMaskPairs,
2595f757f3fSDimitry Andric                       const MachineInstr &MI, const LiveIntervals &LIS,
2600b57cec5SDimitry Andric                       const MachineRegisterInfo &MRI) {
2615f757f3fSDimitry Andric   SlotIndex InstrSI;
2620b57cec5SDimitry Andric   for (const auto &MO : MI.operands()) {
263e8d8bef9SDimitry Andric     if (!MO.isReg() || !MO.getReg().isVirtual())
2640b57cec5SDimitry Andric       continue;
2650b57cec5SDimitry Andric     if (!MO.isUse() || !MO.readsReg())
2660b57cec5SDimitry Andric       continue;
2670b57cec5SDimitry Andric 
2685f757f3fSDimitry Andric     Register Reg = MO.getReg();
2695f757f3fSDimitry Andric     if (llvm::any_of(RegMaskPairs, [Reg](const RegisterMaskPair &RM) {
2705f757f3fSDimitry Andric           return RM.RegUnit == Reg;
2715f757f3fSDimitry Andric         }))
2725f757f3fSDimitry Andric       continue;
2730b57cec5SDimitry Andric 
2745f757f3fSDimitry Andric     LaneBitmask UseMask;
2755f757f3fSDimitry Andric     auto &LI = LIS.getInterval(Reg);
2765f757f3fSDimitry Andric     if (!LI.hasSubRanges())
2775f757f3fSDimitry Andric       UseMask = MRI.getMaxLaneMaskForVReg(Reg);
2785f757f3fSDimitry Andric     else {
2795f757f3fSDimitry Andric       // For a tentative schedule LIS isn't updated yet but livemask should
2805f757f3fSDimitry Andric       // remain the same on any schedule. Subreg defs can be reordered but they
2815f757f3fSDimitry Andric       // all must dominate uses anyway.
2825f757f3fSDimitry Andric       if (!InstrSI)
2835f757f3fSDimitry Andric         InstrSI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex();
2845f757f3fSDimitry Andric       UseMask = getLiveLaneMask(LI, InstrSI, MRI);
2850b57cec5SDimitry Andric     }
2865f757f3fSDimitry Andric 
2875f757f3fSDimitry Andric     RegMaskPairs.emplace_back(Reg, UseMask);
2885f757f3fSDimitry Andric   }
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric ///////////////////////////////////////////////////////////////////////////////
2920b57cec5SDimitry Andric // GCNRPTracker
2930b57cec5SDimitry Andric 
getLiveLaneMask(unsigned Reg,SlotIndex SI,const LiveIntervals & LIS,const MachineRegisterInfo & MRI)2945f757f3fSDimitry Andric LaneBitmask llvm::getLiveLaneMask(unsigned Reg, SlotIndex SI,
2950b57cec5SDimitry Andric                                   const LiveIntervals &LIS,
2960b57cec5SDimitry Andric                                   const MachineRegisterInfo &MRI) {
2975f757f3fSDimitry Andric   return getLiveLaneMask(LIS.getInterval(Reg), SI, MRI);
2985f757f3fSDimitry Andric }
2995f757f3fSDimitry Andric 
getLiveLaneMask(const LiveInterval & LI,SlotIndex SI,const MachineRegisterInfo & MRI)3005f757f3fSDimitry Andric LaneBitmask llvm::getLiveLaneMask(const LiveInterval &LI, SlotIndex SI,
3015f757f3fSDimitry Andric                                   const MachineRegisterInfo &MRI) {
3020b57cec5SDimitry Andric   LaneBitmask LiveMask;
3030b57cec5SDimitry Andric   if (LI.hasSubRanges()) {
3040b57cec5SDimitry Andric     for (const auto &S : LI.subranges())
3050b57cec5SDimitry Andric       if (S.liveAt(SI)) {
3060b57cec5SDimitry Andric         LiveMask |= S.LaneMask;
3075f757f3fSDimitry Andric         assert(LiveMask == (LiveMask & MRI.getMaxLaneMaskForVReg(LI.reg())));
3080b57cec5SDimitry Andric       }
3090b57cec5SDimitry Andric   } else if (LI.liveAt(SI)) {
3105f757f3fSDimitry Andric     LiveMask = MRI.getMaxLaneMaskForVReg(LI.reg());
3110b57cec5SDimitry Andric   }
3120b57cec5SDimitry Andric   return LiveMask;
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric 
getLiveRegs(SlotIndex SI,const LiveIntervals & LIS,const MachineRegisterInfo & MRI)3150b57cec5SDimitry Andric GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
3160b57cec5SDimitry Andric                                            const LiveIntervals &LIS,
3170b57cec5SDimitry Andric                                            const MachineRegisterInfo &MRI) {
3180b57cec5SDimitry Andric   GCNRPTracker::LiveRegSet LiveRegs;
3190b57cec5SDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
3208bcb0991SDimitry Andric     auto Reg = Register::index2VirtReg(I);
3210b57cec5SDimitry Andric     if (!LIS.hasInterval(Reg))
3220b57cec5SDimitry Andric       continue;
3230b57cec5SDimitry Andric     auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI);
3240b57cec5SDimitry Andric     if (LiveMask.any())
3250b57cec5SDimitry Andric       LiveRegs[Reg] = LiveMask;
3260b57cec5SDimitry Andric   }
3270b57cec5SDimitry Andric   return LiveRegs;
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric 
reset(const MachineInstr & MI,const LiveRegSet * LiveRegsCopy,bool After)3300b57cec5SDimitry Andric void GCNRPTracker::reset(const MachineInstr &MI,
3310b57cec5SDimitry Andric                          const LiveRegSet *LiveRegsCopy,
3320b57cec5SDimitry Andric                          bool After) {
3330b57cec5SDimitry Andric   const MachineFunction &MF = *MI.getMF();
3340b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
3350b57cec5SDimitry Andric   if (LiveRegsCopy) {
3360b57cec5SDimitry Andric     if (&LiveRegs != LiveRegsCopy)
3370b57cec5SDimitry Andric       LiveRegs = *LiveRegsCopy;
3380b57cec5SDimitry Andric   } else {
3390b57cec5SDimitry Andric     LiveRegs = After ? getLiveRegsAfter(MI, LIS)
3400b57cec5SDimitry Andric                      : getLiveRegsBefore(MI, LIS);
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs);
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric 
3465f757f3fSDimitry Andric ////////////////////////////////////////////////////////////////////////////////
3475f757f3fSDimitry Andric // GCNUpwardRPTracker
3485f757f3fSDimitry Andric 
reset(const MachineRegisterInfo & MRI_,const LiveRegSet & LiveRegs_)3495f757f3fSDimitry Andric void GCNUpwardRPTracker::reset(const MachineRegisterInfo &MRI_,
3505f757f3fSDimitry Andric                                const LiveRegSet &LiveRegs_) {
3515f757f3fSDimitry Andric   MRI = &MRI_;
3525f757f3fSDimitry Andric   LiveRegs = LiveRegs_;
3535f757f3fSDimitry Andric   LastTrackedMI = nullptr;
3545f757f3fSDimitry Andric   MaxPressure = CurPressure = getRegPressure(MRI_, LiveRegs_);
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric 
recede(const MachineInstr & MI)3570b57cec5SDimitry Andric void GCNUpwardRPTracker::recede(const MachineInstr &MI) {
3580b57cec5SDimitry Andric   assert(MRI && "call reset first");
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   LastTrackedMI = &MI;
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   if (MI.isDebugInstr())
3630b57cec5SDimitry Andric     return;
3640b57cec5SDimitry Andric 
3655f757f3fSDimitry Andric   // Kill all defs.
3665f757f3fSDimitry Andric   GCNRegPressure DefPressure, ECDefPressure;
3675f757f3fSDimitry Andric   bool HasECDefs = false;
3685f757f3fSDimitry Andric   for (const MachineOperand &MO : MI.all_defs()) {
3695f757f3fSDimitry Andric     if (!MO.getReg().isVirtual())
3700b57cec5SDimitry Andric       continue;
3710b57cec5SDimitry Andric 
3725f757f3fSDimitry Andric     Register Reg = MO.getReg();
3735f757f3fSDimitry Andric     LaneBitmask DefMask = getDefRegMask(MO, *MRI);
3745f757f3fSDimitry Andric 
3755f757f3fSDimitry Andric     // Treat a def as fully live at the moment of definition: keep a record.
3765f757f3fSDimitry Andric     if (MO.isEarlyClobber()) {
3775f757f3fSDimitry Andric       ECDefPressure.inc(Reg, LaneBitmask::getNone(), DefMask, *MRI);
3785f757f3fSDimitry Andric       HasECDefs = true;
3795f757f3fSDimitry Andric     } else
3805f757f3fSDimitry Andric       DefPressure.inc(Reg, LaneBitmask::getNone(), DefMask, *MRI);
3815f757f3fSDimitry Andric 
3820b57cec5SDimitry Andric     auto I = LiveRegs.find(Reg);
3830b57cec5SDimitry Andric     if (I == LiveRegs.end())
3840b57cec5SDimitry Andric       continue;
3855f757f3fSDimitry Andric 
3865f757f3fSDimitry Andric     LaneBitmask &LiveMask = I->second;
3875f757f3fSDimitry Andric     LaneBitmask PrevMask = LiveMask;
3885f757f3fSDimitry Andric     LiveMask &= ~DefMask;
3890b57cec5SDimitry Andric     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
3900b57cec5SDimitry Andric     if (LiveMask.none())
3910b57cec5SDimitry Andric       LiveRegs.erase(I);
3920b57cec5SDimitry Andric   }
3935f757f3fSDimitry Andric 
3945f757f3fSDimitry Andric   // Update MaxPressure with defs pressure.
3955f757f3fSDimitry Andric   DefPressure += CurPressure;
3965f757f3fSDimitry Andric   if (HasECDefs)
3975f757f3fSDimitry Andric     DefPressure += ECDefPressure;
3985f757f3fSDimitry Andric   MaxPressure = max(DefPressure, MaxPressure);
3995f757f3fSDimitry Andric 
4005f757f3fSDimitry Andric   // Make uses alive.
4015f757f3fSDimitry Andric   SmallVector<RegisterMaskPair, 8> RegUses;
4025f757f3fSDimitry Andric   collectVirtualRegUses(RegUses, MI, LIS, *MRI);
4035f757f3fSDimitry Andric   for (const RegisterMaskPair &U : RegUses) {
4045f757f3fSDimitry Andric     LaneBitmask &LiveMask = LiveRegs[U.RegUnit];
4055f757f3fSDimitry Andric     LaneBitmask PrevMask = LiveMask;
4060b57cec5SDimitry Andric     LiveMask |= U.LaneMask;
4070b57cec5SDimitry Andric     CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI);
4080b57cec5SDimitry Andric   }
4095f757f3fSDimitry Andric 
4105f757f3fSDimitry Andric   // Update MaxPressure with uses plus early-clobber defs pressure.
4115f757f3fSDimitry Andric   MaxPressure = HasECDefs ? max(CurPressure + ECDefPressure, MaxPressure)
4125f757f3fSDimitry Andric                           : max(CurPressure, MaxPressure);
4135f757f3fSDimitry Andric 
4140b57cec5SDimitry Andric   assert(CurPressure == getRegPressure(*MRI, LiveRegs));
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric 
4175f757f3fSDimitry Andric ////////////////////////////////////////////////////////////////////////////////
4185f757f3fSDimitry Andric // GCNDownwardRPTracker
4195f757f3fSDimitry Andric 
reset(const MachineInstr & MI,const LiveRegSet * LiveRegsCopy)4200b57cec5SDimitry Andric bool GCNDownwardRPTracker::reset(const MachineInstr &MI,
4210b57cec5SDimitry Andric                                  const LiveRegSet *LiveRegsCopy) {
4220b57cec5SDimitry Andric   MRI = &MI.getParent()->getParent()->getRegInfo();
4230b57cec5SDimitry Andric   LastTrackedMI = nullptr;
4240b57cec5SDimitry Andric   MBBEnd = MI.getParent()->end();
4250b57cec5SDimitry Andric   NextMI = &MI;
4260b57cec5SDimitry Andric   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
4270b57cec5SDimitry Andric   if (NextMI == MBBEnd)
4280b57cec5SDimitry Andric     return false;
4290b57cec5SDimitry Andric   GCNRPTracker::reset(*NextMI, LiveRegsCopy, false);
4300b57cec5SDimitry Andric   return true;
4310b57cec5SDimitry Andric }
4320b57cec5SDimitry Andric 
advanceBeforeNext()4330b57cec5SDimitry Andric bool GCNDownwardRPTracker::advanceBeforeNext() {
4340b57cec5SDimitry Andric   assert(MRI && "call reset first");
435bdd1243dSDimitry Andric   if (!LastTrackedMI)
436bdd1243dSDimitry Andric     return NextMI == MBBEnd;
4370b57cec5SDimitry Andric 
438bdd1243dSDimitry Andric   assert(NextMI == MBBEnd || !NextMI->isDebugInstr());
4390b57cec5SDimitry Andric 
440bdd1243dSDimitry Andric   SlotIndex SI = NextMI == MBBEnd
441bdd1243dSDimitry Andric                      ? LIS.getInstructionIndex(*LastTrackedMI).getDeadSlot()
442bdd1243dSDimitry Andric                      : LIS.getInstructionIndex(*NextMI).getBaseIndex();
4430b57cec5SDimitry Andric   assert(SI.isValid());
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   // Remove dead registers or mask bits.
44606c3fb27SDimitry Andric   SmallSet<Register, 8> SeenRegs;
44706c3fb27SDimitry Andric   for (auto &MO : LastTrackedMI->operands()) {
44806c3fb27SDimitry Andric     if (!MO.isReg() || !MO.getReg().isVirtual())
44906c3fb27SDimitry Andric       continue;
45006c3fb27SDimitry Andric     if (MO.isUse() && !MO.readsReg())
45106c3fb27SDimitry Andric       continue;
45206c3fb27SDimitry Andric     if (!SeenRegs.insert(MO.getReg()).second)
45306c3fb27SDimitry Andric       continue;
45406c3fb27SDimitry Andric     const LiveInterval &LI = LIS.getInterval(MO.getReg());
4550b57cec5SDimitry Andric     if (LI.hasSubRanges()) {
45606c3fb27SDimitry Andric       auto It = LiveRegs.end();
4570b57cec5SDimitry Andric       for (const auto &S : LI.subranges()) {
4580b57cec5SDimitry Andric         if (!S.liveAt(SI)) {
45906c3fb27SDimitry Andric           if (It == LiveRegs.end()) {
46006c3fb27SDimitry Andric             It = LiveRegs.find(MO.getReg());
46106c3fb27SDimitry Andric             if (It == LiveRegs.end())
46206c3fb27SDimitry Andric               llvm_unreachable("register isn't live");
46306c3fb27SDimitry Andric           }
46406c3fb27SDimitry Andric           auto PrevMask = It->second;
46506c3fb27SDimitry Andric           It->second &= ~S.LaneMask;
46606c3fb27SDimitry Andric           CurPressure.inc(MO.getReg(), PrevMask, It->second, *MRI);
4670b57cec5SDimitry Andric         }
4680b57cec5SDimitry Andric       }
46906c3fb27SDimitry Andric       if (It != LiveRegs.end() && It->second.none())
47006c3fb27SDimitry Andric         LiveRegs.erase(It);
4710b57cec5SDimitry Andric     } else if (!LI.liveAt(SI)) {
47206c3fb27SDimitry Andric       auto It = LiveRegs.find(MO.getReg());
47306c3fb27SDimitry Andric       if (It == LiveRegs.end())
47406c3fb27SDimitry Andric         llvm_unreachable("register isn't live");
47506c3fb27SDimitry Andric       CurPressure.inc(MO.getReg(), It->second, LaneBitmask::getNone(), *MRI);
47606c3fb27SDimitry Andric       LiveRegs.erase(It);
4770b57cec5SDimitry Andric     }
4780b57cec5SDimitry Andric   }
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric   MaxPressure = max(MaxPressure, CurPressure);
4810b57cec5SDimitry Andric 
482bdd1243dSDimitry Andric   LastTrackedMI = nullptr;
483bdd1243dSDimitry Andric 
484bdd1243dSDimitry Andric   return NextMI == MBBEnd;
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric 
advanceToNext()4870b57cec5SDimitry Andric void GCNDownwardRPTracker::advanceToNext() {
4880b57cec5SDimitry Andric   LastTrackedMI = &*NextMI++;
489fe6060f1SDimitry Andric   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric   // Add new registers or mask bits.
49206c3fb27SDimitry Andric   for (const auto &MO : LastTrackedMI->all_defs()) {
4938bcb0991SDimitry Andric     Register Reg = MO.getReg();
494e8d8bef9SDimitry Andric     if (!Reg.isVirtual())
4950b57cec5SDimitry Andric       continue;
4960b57cec5SDimitry Andric     auto &LiveMask = LiveRegs[Reg];
4970b57cec5SDimitry Andric     auto PrevMask = LiveMask;
4980b57cec5SDimitry Andric     LiveMask |= getDefRegMask(MO, *MRI);
4990b57cec5SDimitry Andric     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
5000b57cec5SDimitry Andric   }
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   MaxPressure = max(MaxPressure, CurPressure);
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric 
advance()5050b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance() {
506bdd1243dSDimitry Andric   if (NextMI == MBBEnd)
5070b57cec5SDimitry Andric     return false;
508bdd1243dSDimitry Andric   advanceBeforeNext();
5090b57cec5SDimitry Andric   advanceToNext();
5100b57cec5SDimitry Andric   return true;
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric 
advance(MachineBasicBlock::const_iterator End)5130b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) {
5140b57cec5SDimitry Andric   while (NextMI != End)
5150b57cec5SDimitry Andric     if (!advance()) return false;
5160b57cec5SDimitry Andric   return true;
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric 
advance(MachineBasicBlock::const_iterator Begin,MachineBasicBlock::const_iterator End,const LiveRegSet * LiveRegsCopy)5190b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin,
5200b57cec5SDimitry Andric                                    MachineBasicBlock::const_iterator End,
5210b57cec5SDimitry Andric                                    const LiveRegSet *LiveRegsCopy) {
5220b57cec5SDimitry Andric   reset(*Begin, LiveRegsCopy);
5230b57cec5SDimitry Andric   return advance(End);
5240b57cec5SDimitry Andric }
5250b57cec5SDimitry Andric 
reportMismatch(const GCNRPTracker::LiveRegSet & LISLR,const GCNRPTracker::LiveRegSet & TrackedLR,const TargetRegisterInfo * TRI,StringRef Pfx)526bdd1243dSDimitry Andric Printable llvm::reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
5270b57cec5SDimitry Andric                                const GCNRPTracker::LiveRegSet &TrackedLR,
5285f757f3fSDimitry Andric                                const TargetRegisterInfo *TRI, StringRef Pfx) {
5295f757f3fSDimitry Andric   return Printable([&LISLR, &TrackedLR, TRI, Pfx](raw_ostream &OS) {
5300b57cec5SDimitry Andric     for (auto const &P : TrackedLR) {
5310b57cec5SDimitry Andric       auto I = LISLR.find(P.first);
5320b57cec5SDimitry Andric       if (I == LISLR.end()) {
5335f757f3fSDimitry Andric         OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
5340b57cec5SDimitry Andric            << " isn't found in LIS reported set\n";
535bdd1243dSDimitry Andric       } else if (I->second != P.second) {
5365f757f3fSDimitry Andric         OS << Pfx << printReg(P.first, TRI)
537bdd1243dSDimitry Andric            << " masks doesn't match: LIS reported " << PrintLaneMask(I->second)
538bdd1243dSDimitry Andric            << ", tracked " << PrintLaneMask(P.second) << '\n';
5390b57cec5SDimitry Andric       }
5400b57cec5SDimitry Andric     }
5410b57cec5SDimitry Andric     for (auto const &P : LISLR) {
5420b57cec5SDimitry Andric       auto I = TrackedLR.find(P.first);
5430b57cec5SDimitry Andric       if (I == TrackedLR.end()) {
5445f757f3fSDimitry Andric         OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
5450b57cec5SDimitry Andric            << " isn't found in tracked set\n";
5460b57cec5SDimitry Andric       }
5470b57cec5SDimitry Andric     }
548bdd1243dSDimitry Andric   });
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric 
isValid() const5510b57cec5SDimitry Andric bool GCNUpwardRPTracker::isValid() const {
5520b57cec5SDimitry Andric   const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
5530b57cec5SDimitry Andric   const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
5540b57cec5SDimitry Andric   const auto &TrackedLR = LiveRegs;
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   if (!isEqual(LISLR, TrackedLR)) {
5570b57cec5SDimitry Andric     dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
558bdd1243dSDimitry Andric               " LIS reported livesets mismatch:\n"
559bdd1243dSDimitry Andric            << print(LISLR, *MRI);
5600b57cec5SDimitry Andric     reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo());
5610b57cec5SDimitry Andric     return false;
5620b57cec5SDimitry Andric   }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric   auto LISPressure = getRegPressure(*MRI, LISLR);
5650b57cec5SDimitry Andric   if (LISPressure != CurPressure) {
566bdd1243dSDimitry Andric     dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: "
567bdd1243dSDimitry Andric            << print(CurPressure) << "LIS rpt: " << print(LISPressure);
5680b57cec5SDimitry Andric     return false;
5690b57cec5SDimitry Andric   }
5700b57cec5SDimitry Andric   return true;
5710b57cec5SDimitry Andric }
5720b57cec5SDimitry Andric 
print(const GCNRPTracker::LiveRegSet & LiveRegs,const MachineRegisterInfo & MRI)573bdd1243dSDimitry Andric Printable llvm::print(const GCNRPTracker::LiveRegSet &LiveRegs,
5740b57cec5SDimitry Andric                       const MachineRegisterInfo &MRI) {
575bdd1243dSDimitry Andric   return Printable([&LiveRegs, &MRI](raw_ostream &OS) {
5760b57cec5SDimitry Andric     const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
5770b57cec5SDimitry Andric     for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
57804eeddc0SDimitry Andric       Register Reg = Register::index2VirtReg(I);
5790b57cec5SDimitry Andric       auto It = LiveRegs.find(Reg);
5800b57cec5SDimitry Andric       if (It != LiveRegs.end() && It->second.any())
5810b57cec5SDimitry Andric         OS << ' ' << printVRegOrUnit(Reg, TRI) << ':'
5820b57cec5SDimitry Andric            << PrintLaneMask(It->second);
5830b57cec5SDimitry Andric     }
5840b57cec5SDimitry Andric     OS << '\n';
585bdd1243dSDimitry Andric   });
5860b57cec5SDimitry Andric }
587bdd1243dSDimitry Andric 
dump() const588bdd1243dSDimitry Andric void GCNRegPressure::dump() const { dbgs() << print(*this); }
589bdd1243dSDimitry Andric 
5905f757f3fSDimitry Andric static cl::opt<bool> UseDownwardTracker(
5915f757f3fSDimitry Andric     "amdgpu-print-rp-downward",
5925f757f3fSDimitry Andric     cl::desc("Use GCNDownwardRPTracker for GCNRegPressurePrinter pass"),
5935f757f3fSDimitry Andric     cl::init(false), cl::Hidden);
5945f757f3fSDimitry Andric 
5955f757f3fSDimitry Andric char llvm::GCNRegPressurePrinter::ID = 0;
5965f757f3fSDimitry Andric char &llvm::GCNRegPressurePrinterID = GCNRegPressurePrinter::ID;
5975f757f3fSDimitry Andric 
5985f757f3fSDimitry Andric INITIALIZE_PASS(GCNRegPressurePrinter, "amdgpu-print-rp", "", true, true)
5995f757f3fSDimitry Andric 
6005f757f3fSDimitry Andric // Return lanemask of Reg's subregs that are live-through at [Begin, End] and
6015f757f3fSDimitry Andric // are fully covered by Mask.
6025f757f3fSDimitry Andric static LaneBitmask
getRegLiveThroughMask(const MachineRegisterInfo & MRI,const LiveIntervals & LIS,Register Reg,SlotIndex Begin,SlotIndex End,LaneBitmask Mask=LaneBitmask::getAll ())6035f757f3fSDimitry Andric getRegLiveThroughMask(const MachineRegisterInfo &MRI, const LiveIntervals &LIS,
6045f757f3fSDimitry Andric                       Register Reg, SlotIndex Begin, SlotIndex End,
6055f757f3fSDimitry Andric                       LaneBitmask Mask = LaneBitmask::getAll()) {
6065f757f3fSDimitry Andric 
6075f757f3fSDimitry Andric   auto IsInOneSegment = [Begin, End](const LiveRange &LR) -> bool {
6085f757f3fSDimitry Andric     auto *Segment = LR.getSegmentContaining(Begin);
6095f757f3fSDimitry Andric     return Segment && Segment->contains(End);
6105f757f3fSDimitry Andric   };
6115f757f3fSDimitry Andric 
6125f757f3fSDimitry Andric   LaneBitmask LiveThroughMask;
6135f757f3fSDimitry Andric   const LiveInterval &LI = LIS.getInterval(Reg);
6145f757f3fSDimitry Andric   if (LI.hasSubRanges()) {
6155f757f3fSDimitry Andric     for (auto &SR : LI.subranges()) {
6165f757f3fSDimitry Andric       if ((SR.LaneMask & Mask) == SR.LaneMask && IsInOneSegment(SR))
6175f757f3fSDimitry Andric         LiveThroughMask |= SR.LaneMask;
6185f757f3fSDimitry Andric     }
6195f757f3fSDimitry Andric   } else {
6205f757f3fSDimitry Andric     LaneBitmask RegMask = MRI.getMaxLaneMaskForVReg(Reg);
6215f757f3fSDimitry Andric     if ((RegMask & Mask) == RegMask && IsInOneSegment(LI))
6225f757f3fSDimitry Andric       LiveThroughMask = RegMask;
6235f757f3fSDimitry Andric   }
6245f757f3fSDimitry Andric 
6255f757f3fSDimitry Andric   return LiveThroughMask;
6265f757f3fSDimitry Andric }
6275f757f3fSDimitry Andric 
runOnMachineFunction(MachineFunction & MF)6285f757f3fSDimitry Andric bool GCNRegPressurePrinter::runOnMachineFunction(MachineFunction &MF) {
6295f757f3fSDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
6305f757f3fSDimitry Andric   const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
631*0fca6ea1SDimitry Andric   const LiveIntervals &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
6325f757f3fSDimitry Andric 
6335f757f3fSDimitry Andric   auto &OS = dbgs();
6345f757f3fSDimitry Andric 
6355f757f3fSDimitry Andric // Leading spaces are important for YAML syntax.
6365f757f3fSDimitry Andric #define PFX "  "
6375f757f3fSDimitry Andric 
6385f757f3fSDimitry Andric   OS << "---\nname: " << MF.getName() << "\nbody:             |\n";
6395f757f3fSDimitry Andric 
6405f757f3fSDimitry Andric   auto printRP = [](const GCNRegPressure &RP) {
6415f757f3fSDimitry Andric     return Printable([&RP](raw_ostream &OS) {
6425f757f3fSDimitry Andric       OS << format(PFX "  %-5d", RP.getSGPRNum())
6435f757f3fSDimitry Andric          << format(" %-5d", RP.getVGPRNum(false));
6445f757f3fSDimitry Andric     });
6455f757f3fSDimitry Andric   };
6465f757f3fSDimitry Andric 
6475f757f3fSDimitry Andric   auto ReportLISMismatchIfAny = [&](const GCNRPTracker::LiveRegSet &TrackedLR,
6485f757f3fSDimitry Andric                                     const GCNRPTracker::LiveRegSet &LISLR) {
6495f757f3fSDimitry Andric     if (LISLR != TrackedLR) {
6505f757f3fSDimitry Andric       OS << PFX "  mis LIS: " << llvm::print(LISLR, MRI)
6515f757f3fSDimitry Andric          << reportMismatch(LISLR, TrackedLR, TRI, PFX "    ");
6525f757f3fSDimitry Andric     }
6535f757f3fSDimitry Andric   };
6545f757f3fSDimitry Andric 
6555f757f3fSDimitry Andric   // Register pressure before and at an instruction (in program order).
6565f757f3fSDimitry Andric   SmallVector<std::pair<GCNRegPressure, GCNRegPressure>, 16> RP;
6575f757f3fSDimitry Andric 
6585f757f3fSDimitry Andric   for (auto &MBB : MF) {
6595f757f3fSDimitry Andric     RP.clear();
6605f757f3fSDimitry Andric     RP.reserve(MBB.size());
6615f757f3fSDimitry Andric 
6625f757f3fSDimitry Andric     OS << PFX;
6635f757f3fSDimitry Andric     MBB.printName(OS);
6645f757f3fSDimitry Andric     OS << ":\n";
6655f757f3fSDimitry Andric 
6665f757f3fSDimitry Andric     SlotIndex MBBStartSlot = LIS.getSlotIndexes()->getMBBStartIdx(&MBB);
6675f757f3fSDimitry Andric     SlotIndex MBBEndSlot = LIS.getSlotIndexes()->getMBBEndIdx(&MBB);
6685f757f3fSDimitry Andric 
6695f757f3fSDimitry Andric     GCNRPTracker::LiveRegSet LiveIn, LiveOut;
6705f757f3fSDimitry Andric     GCNRegPressure RPAtMBBEnd;
6715f757f3fSDimitry Andric 
6725f757f3fSDimitry Andric     if (UseDownwardTracker) {
6735f757f3fSDimitry Andric       if (MBB.empty()) {
6745f757f3fSDimitry Andric         LiveIn = LiveOut = getLiveRegs(MBBStartSlot, LIS, MRI);
6755f757f3fSDimitry Andric         RPAtMBBEnd = getRegPressure(MRI, LiveIn);
6765f757f3fSDimitry Andric       } else {
6775f757f3fSDimitry Andric         GCNDownwardRPTracker RPT(LIS);
6785f757f3fSDimitry Andric         RPT.reset(MBB.front());
6795f757f3fSDimitry Andric 
6805f757f3fSDimitry Andric         LiveIn = RPT.getLiveRegs();
6815f757f3fSDimitry Andric 
6825f757f3fSDimitry Andric         while (!RPT.advanceBeforeNext()) {
6835f757f3fSDimitry Andric           GCNRegPressure RPBeforeMI = RPT.getPressure();
6845f757f3fSDimitry Andric           RPT.advanceToNext();
6855f757f3fSDimitry Andric           RP.emplace_back(RPBeforeMI, RPT.getPressure());
6865f757f3fSDimitry Andric         }
6875f757f3fSDimitry Andric 
6885f757f3fSDimitry Andric         LiveOut = RPT.getLiveRegs();
6895f757f3fSDimitry Andric         RPAtMBBEnd = RPT.getPressure();
6905f757f3fSDimitry Andric       }
6915f757f3fSDimitry Andric     } else {
6925f757f3fSDimitry Andric       GCNUpwardRPTracker RPT(LIS);
6935f757f3fSDimitry Andric       RPT.reset(MRI, MBBEndSlot);
6945f757f3fSDimitry Andric 
6955f757f3fSDimitry Andric       LiveOut = RPT.getLiveRegs();
6965f757f3fSDimitry Andric       RPAtMBBEnd = RPT.getPressure();
6975f757f3fSDimitry Andric 
6985f757f3fSDimitry Andric       for (auto &MI : reverse(MBB)) {
6995f757f3fSDimitry Andric         RPT.resetMaxPressure();
7005f757f3fSDimitry Andric         RPT.recede(MI);
7015f757f3fSDimitry Andric         if (!MI.isDebugInstr())
7025f757f3fSDimitry Andric           RP.emplace_back(RPT.getPressure(), RPT.getMaxPressure());
7035f757f3fSDimitry Andric       }
7045f757f3fSDimitry Andric 
7055f757f3fSDimitry Andric       LiveIn = RPT.getLiveRegs();
7065f757f3fSDimitry Andric     }
7075f757f3fSDimitry Andric 
7085f757f3fSDimitry Andric     OS << PFX "  Live-in: " << llvm::print(LiveIn, MRI);
7095f757f3fSDimitry Andric     if (!UseDownwardTracker)
7105f757f3fSDimitry Andric       ReportLISMismatchIfAny(LiveIn, getLiveRegs(MBBStartSlot, LIS, MRI));
7115f757f3fSDimitry Andric 
7125f757f3fSDimitry Andric     OS << PFX "  SGPR  VGPR\n";
7135f757f3fSDimitry Andric     int I = 0;
7145f757f3fSDimitry Andric     for (auto &MI : MBB) {
7155f757f3fSDimitry Andric       if (!MI.isDebugInstr()) {
7165f757f3fSDimitry Andric         auto &[RPBeforeInstr, RPAtInstr] =
7175f757f3fSDimitry Andric             RP[UseDownwardTracker ? I : (RP.size() - 1 - I)];
7185f757f3fSDimitry Andric         ++I;
7195f757f3fSDimitry Andric         OS << printRP(RPBeforeInstr) << '\n' << printRP(RPAtInstr) << "  ";
7205f757f3fSDimitry Andric       } else
7215f757f3fSDimitry Andric         OS << PFX "               ";
7225f757f3fSDimitry Andric       MI.print(OS);
7235f757f3fSDimitry Andric     }
7245f757f3fSDimitry Andric     OS << printRP(RPAtMBBEnd) << '\n';
7255f757f3fSDimitry Andric 
7265f757f3fSDimitry Andric     OS << PFX "  Live-out:" << llvm::print(LiveOut, MRI);
7275f757f3fSDimitry Andric     if (UseDownwardTracker)
7285f757f3fSDimitry Andric       ReportLISMismatchIfAny(LiveOut, getLiveRegs(MBBEndSlot, LIS, MRI));
7295f757f3fSDimitry Andric 
7305f757f3fSDimitry Andric     GCNRPTracker::LiveRegSet LiveThrough;
7315f757f3fSDimitry Andric     for (auto [Reg, Mask] : LiveIn) {
7325f757f3fSDimitry Andric       LaneBitmask MaskIntersection = Mask & LiveOut.lookup(Reg);
7335f757f3fSDimitry Andric       if (MaskIntersection.any()) {
7345f757f3fSDimitry Andric         LaneBitmask LTMask = getRegLiveThroughMask(
7355f757f3fSDimitry Andric             MRI, LIS, Reg, MBBStartSlot, MBBEndSlot, MaskIntersection);
7365f757f3fSDimitry Andric         if (LTMask.any())
7375f757f3fSDimitry Andric           LiveThrough[Reg] = LTMask;
7385f757f3fSDimitry Andric       }
7395f757f3fSDimitry Andric     }
7405f757f3fSDimitry Andric     OS << PFX "  Live-thr:" << llvm::print(LiveThrough, MRI);
7415f757f3fSDimitry Andric     OS << printRP(getRegPressure(MRI, LiveThrough)) << '\n';
7425f757f3fSDimitry Andric   }
7435f757f3fSDimitry Andric   OS << "...\n";
7445f757f3fSDimitry Andric   return false;
7455f757f3fSDimitry Andric 
7465f757f3fSDimitry Andric #undef PFX
7475f757f3fSDimitry Andric }