xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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"
15*5f757f3fSDimitry 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 
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 
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 
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());
81*5f757f3fSDimitry Andric       const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
82*5f757f3fSDimitry Andric       Value[Kind] +=
83*5f757f3fSDimitry 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 
910b57cec5SDimitry Andric bool GCNRegPressure::less(const GCNSubtarget &ST,
920b57cec5SDimitry Andric                           const GCNRegPressure& O,
930b57cec5SDimitry Andric                           unsigned MaxOccupancy) const {
940b57cec5SDimitry Andric   const auto SGPROcc = std::min(MaxOccupancy,
950b57cec5SDimitry Andric                                 ST.getOccupancyWithNumSGPRs(getSGPRNum()));
96fe6060f1SDimitry Andric   const auto VGPROcc =
97fe6060f1SDimitry Andric     std::min(MaxOccupancy,
98fe6060f1SDimitry Andric              ST.getOccupancyWithNumVGPRs(getVGPRNum(ST.hasGFX90AInsts())));
990b57cec5SDimitry Andric   const auto OtherSGPROcc = std::min(MaxOccupancy,
1000b57cec5SDimitry Andric                                 ST.getOccupancyWithNumSGPRs(O.getSGPRNum()));
101fe6060f1SDimitry Andric   const auto OtherVGPROcc =
102fe6060f1SDimitry Andric     std::min(MaxOccupancy,
103fe6060f1SDimitry Andric              ST.getOccupancyWithNumVGPRs(O.getVGPRNum(ST.hasGFX90AInsts())));
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   const auto Occ = std::min(SGPROcc, VGPROcc);
1060b57cec5SDimitry Andric   const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc);
1070b57cec5SDimitry Andric   if (Occ != OtherOcc)
1080b57cec5SDimitry Andric     return Occ > OtherOcc;
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   bool SGPRImportant = SGPROcc < VGPROcc;
1110b57cec5SDimitry Andric   const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   // if both pressures disagree on what is more important compare vgprs
1140b57cec5SDimitry Andric   if (SGPRImportant != OtherSGPRImportant) {
1150b57cec5SDimitry Andric     SGPRImportant = false;
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   // compare large regs pressure
1190b57cec5SDimitry Andric   bool SGPRFirst = SGPRImportant;
1200b57cec5SDimitry Andric   for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) {
1210b57cec5SDimitry Andric     if (SGPRFirst) {
1220b57cec5SDimitry Andric       auto SW = getSGPRTuplesWeight();
1230b57cec5SDimitry Andric       auto OtherSW = O.getSGPRTuplesWeight();
1240b57cec5SDimitry Andric       if (SW != OtherSW)
1250b57cec5SDimitry Andric         return SW < OtherSW;
1260b57cec5SDimitry Andric     } else {
1270b57cec5SDimitry Andric       auto VW = getVGPRTuplesWeight();
1280b57cec5SDimitry Andric       auto OtherVW = O.getVGPRTuplesWeight();
1290b57cec5SDimitry Andric       if (VW != OtherVW)
1300b57cec5SDimitry Andric         return VW < OtherVW;
1310b57cec5SDimitry Andric     }
1320b57cec5SDimitry Andric   }
1330b57cec5SDimitry Andric   return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()):
134fe6060f1SDimitry Andric                          (getVGPRNum(ST.hasGFX90AInsts()) <
135fe6060f1SDimitry Andric                           O.getVGPRNum(ST.hasGFX90AInsts()));
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
138bdd1243dSDimitry Andric Printable llvm::print(const GCNRegPressure &RP, const GCNSubtarget *ST) {
139bdd1243dSDimitry Andric   return Printable([&RP, ST](raw_ostream &OS) {
140bdd1243dSDimitry Andric     OS << "VGPRs: " << RP.Value[GCNRegPressure::VGPR32] << ' '
141bdd1243dSDimitry Andric        << "AGPRs: " << RP.getAGPRNum();
142bdd1243dSDimitry Andric     if (ST)
143bdd1243dSDimitry Andric       OS << "(O"
144bdd1243dSDimitry Andric          << ST->getOccupancyWithNumVGPRs(RP.getVGPRNum(ST->hasGFX90AInsts()))
145fe6060f1SDimitry Andric          << ')';
146bdd1243dSDimitry Andric     OS << ", SGPRs: " << RP.getSGPRNum();
147bdd1243dSDimitry Andric     if (ST)
148bdd1243dSDimitry Andric       OS << "(O" << ST->getOccupancyWithNumSGPRs(RP.getSGPRNum()) << ')';
149bdd1243dSDimitry Andric     OS << ", LVGPR WT: " << RP.getVGPRTuplesWeight()
150bdd1243dSDimitry Andric        << ", LSGPR WT: " << RP.getSGPRTuplesWeight();
151bdd1243dSDimitry Andric     if (ST)
152bdd1243dSDimitry Andric       OS << " -> Occ: " << RP.getOccupancy(*ST);
1530b57cec5SDimitry Andric     OS << '\n';
154bdd1243dSDimitry Andric   });
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric static LaneBitmask getDefRegMask(const MachineOperand &MO,
1580b57cec5SDimitry Andric                                  const MachineRegisterInfo &MRI) {
159e8d8bef9SDimitry Andric   assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual());
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   // We don't rely on read-undef flag because in case of tentative schedule
1620b57cec5SDimitry Andric   // tracking it isn't set correctly yet. This works correctly however since
1630b57cec5SDimitry Andric   // use mask has been tracked before using LIS.
1640b57cec5SDimitry Andric   return MO.getSubReg() == 0 ?
1650b57cec5SDimitry Andric     MRI.getMaxLaneMaskForVReg(MO.getReg()) :
1660b57cec5SDimitry Andric     MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric 
169*5f757f3fSDimitry Andric static void
170*5f757f3fSDimitry Andric collectVirtualRegUses(SmallVectorImpl<RegisterMaskPair> &RegMaskPairs,
171*5f757f3fSDimitry Andric                       const MachineInstr &MI, const LiveIntervals &LIS,
1720b57cec5SDimitry Andric                       const MachineRegisterInfo &MRI) {
173*5f757f3fSDimitry Andric   SlotIndex InstrSI;
1740b57cec5SDimitry Andric   for (const auto &MO : MI.operands()) {
175e8d8bef9SDimitry Andric     if (!MO.isReg() || !MO.getReg().isVirtual())
1760b57cec5SDimitry Andric       continue;
1770b57cec5SDimitry Andric     if (!MO.isUse() || !MO.readsReg())
1780b57cec5SDimitry Andric       continue;
1790b57cec5SDimitry Andric 
180*5f757f3fSDimitry Andric     Register Reg = MO.getReg();
181*5f757f3fSDimitry Andric     if (llvm::any_of(RegMaskPairs, [Reg](const RegisterMaskPair &RM) {
182*5f757f3fSDimitry Andric           return RM.RegUnit == Reg;
183*5f757f3fSDimitry Andric         }))
184*5f757f3fSDimitry Andric       continue;
1850b57cec5SDimitry Andric 
186*5f757f3fSDimitry Andric     LaneBitmask UseMask;
187*5f757f3fSDimitry Andric     auto &LI = LIS.getInterval(Reg);
188*5f757f3fSDimitry Andric     if (!LI.hasSubRanges())
189*5f757f3fSDimitry Andric       UseMask = MRI.getMaxLaneMaskForVReg(Reg);
190*5f757f3fSDimitry Andric     else {
191*5f757f3fSDimitry Andric       // For a tentative schedule LIS isn't updated yet but livemask should
192*5f757f3fSDimitry Andric       // remain the same on any schedule. Subreg defs can be reordered but they
193*5f757f3fSDimitry Andric       // all must dominate uses anyway.
194*5f757f3fSDimitry Andric       if (!InstrSI)
195*5f757f3fSDimitry Andric         InstrSI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex();
196*5f757f3fSDimitry Andric       UseMask = getLiveLaneMask(LI, InstrSI, MRI);
1970b57cec5SDimitry Andric     }
198*5f757f3fSDimitry Andric 
199*5f757f3fSDimitry Andric     RegMaskPairs.emplace_back(Reg, UseMask);
200*5f757f3fSDimitry Andric   }
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric ///////////////////////////////////////////////////////////////////////////////
2040b57cec5SDimitry Andric // GCNRPTracker
2050b57cec5SDimitry Andric 
206*5f757f3fSDimitry Andric LaneBitmask llvm::getLiveLaneMask(unsigned Reg, SlotIndex SI,
2070b57cec5SDimitry Andric                                   const LiveIntervals &LIS,
2080b57cec5SDimitry Andric                                   const MachineRegisterInfo &MRI) {
209*5f757f3fSDimitry Andric   return getLiveLaneMask(LIS.getInterval(Reg), SI, MRI);
210*5f757f3fSDimitry Andric }
211*5f757f3fSDimitry Andric 
212*5f757f3fSDimitry Andric LaneBitmask llvm::getLiveLaneMask(const LiveInterval &LI, SlotIndex SI,
213*5f757f3fSDimitry Andric                                   const MachineRegisterInfo &MRI) {
2140b57cec5SDimitry Andric   LaneBitmask LiveMask;
2150b57cec5SDimitry Andric   if (LI.hasSubRanges()) {
2160b57cec5SDimitry Andric     for (const auto &S : LI.subranges())
2170b57cec5SDimitry Andric       if (S.liveAt(SI)) {
2180b57cec5SDimitry Andric         LiveMask |= S.LaneMask;
219*5f757f3fSDimitry Andric         assert(LiveMask == (LiveMask & MRI.getMaxLaneMaskForVReg(LI.reg())));
2200b57cec5SDimitry Andric       }
2210b57cec5SDimitry Andric   } else if (LI.liveAt(SI)) {
222*5f757f3fSDimitry Andric     LiveMask = MRI.getMaxLaneMaskForVReg(LI.reg());
2230b57cec5SDimitry Andric   }
2240b57cec5SDimitry Andric   return LiveMask;
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
2280b57cec5SDimitry Andric                                            const LiveIntervals &LIS,
2290b57cec5SDimitry Andric                                            const MachineRegisterInfo &MRI) {
2300b57cec5SDimitry Andric   GCNRPTracker::LiveRegSet LiveRegs;
2310b57cec5SDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
2328bcb0991SDimitry Andric     auto Reg = Register::index2VirtReg(I);
2330b57cec5SDimitry Andric     if (!LIS.hasInterval(Reg))
2340b57cec5SDimitry Andric       continue;
2350b57cec5SDimitry Andric     auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI);
2360b57cec5SDimitry Andric     if (LiveMask.any())
2370b57cec5SDimitry Andric       LiveRegs[Reg] = LiveMask;
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric   return LiveRegs;
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric void GCNRPTracker::reset(const MachineInstr &MI,
2430b57cec5SDimitry Andric                          const LiveRegSet *LiveRegsCopy,
2440b57cec5SDimitry Andric                          bool After) {
2450b57cec5SDimitry Andric   const MachineFunction &MF = *MI.getMF();
2460b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
2470b57cec5SDimitry Andric   if (LiveRegsCopy) {
2480b57cec5SDimitry Andric     if (&LiveRegs != LiveRegsCopy)
2490b57cec5SDimitry Andric       LiveRegs = *LiveRegsCopy;
2500b57cec5SDimitry Andric   } else {
2510b57cec5SDimitry Andric     LiveRegs = After ? getLiveRegsAfter(MI, LIS)
2520b57cec5SDimitry Andric                      : getLiveRegsBefore(MI, LIS);
2530b57cec5SDimitry Andric   }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs);
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
258*5f757f3fSDimitry Andric ////////////////////////////////////////////////////////////////////////////////
259*5f757f3fSDimitry Andric // GCNUpwardRPTracker
260*5f757f3fSDimitry Andric 
261*5f757f3fSDimitry Andric void GCNUpwardRPTracker::reset(const MachineRegisterInfo &MRI_,
262*5f757f3fSDimitry Andric                                const LiveRegSet &LiveRegs_) {
263*5f757f3fSDimitry Andric   MRI = &MRI_;
264*5f757f3fSDimitry Andric   LiveRegs = LiveRegs_;
265*5f757f3fSDimitry Andric   LastTrackedMI = nullptr;
266*5f757f3fSDimitry Andric   MaxPressure = CurPressure = getRegPressure(MRI_, LiveRegs_);
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric void GCNUpwardRPTracker::recede(const MachineInstr &MI) {
2700b57cec5SDimitry Andric   assert(MRI && "call reset first");
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   LastTrackedMI = &MI;
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   if (MI.isDebugInstr())
2750b57cec5SDimitry Andric     return;
2760b57cec5SDimitry Andric 
277*5f757f3fSDimitry Andric   // Kill all defs.
278*5f757f3fSDimitry Andric   GCNRegPressure DefPressure, ECDefPressure;
279*5f757f3fSDimitry Andric   bool HasECDefs = false;
280*5f757f3fSDimitry Andric   for (const MachineOperand &MO : MI.all_defs()) {
281*5f757f3fSDimitry Andric     if (!MO.getReg().isVirtual())
2820b57cec5SDimitry Andric       continue;
2830b57cec5SDimitry Andric 
284*5f757f3fSDimitry Andric     Register Reg = MO.getReg();
285*5f757f3fSDimitry Andric     LaneBitmask DefMask = getDefRegMask(MO, *MRI);
286*5f757f3fSDimitry Andric 
287*5f757f3fSDimitry Andric     // Treat a def as fully live at the moment of definition: keep a record.
288*5f757f3fSDimitry Andric     if (MO.isEarlyClobber()) {
289*5f757f3fSDimitry Andric       ECDefPressure.inc(Reg, LaneBitmask::getNone(), DefMask, *MRI);
290*5f757f3fSDimitry Andric       HasECDefs = true;
291*5f757f3fSDimitry Andric     } else
292*5f757f3fSDimitry Andric       DefPressure.inc(Reg, LaneBitmask::getNone(), DefMask, *MRI);
293*5f757f3fSDimitry Andric 
2940b57cec5SDimitry Andric     auto I = LiveRegs.find(Reg);
2950b57cec5SDimitry Andric     if (I == LiveRegs.end())
2960b57cec5SDimitry Andric       continue;
297*5f757f3fSDimitry Andric 
298*5f757f3fSDimitry Andric     LaneBitmask &LiveMask = I->second;
299*5f757f3fSDimitry Andric     LaneBitmask PrevMask = LiveMask;
300*5f757f3fSDimitry Andric     LiveMask &= ~DefMask;
3010b57cec5SDimitry Andric     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
3020b57cec5SDimitry Andric     if (LiveMask.none())
3030b57cec5SDimitry Andric       LiveRegs.erase(I);
3040b57cec5SDimitry Andric   }
305*5f757f3fSDimitry Andric 
306*5f757f3fSDimitry Andric   // Update MaxPressure with defs pressure.
307*5f757f3fSDimitry Andric   DefPressure += CurPressure;
308*5f757f3fSDimitry Andric   if (HasECDefs)
309*5f757f3fSDimitry Andric     DefPressure += ECDefPressure;
310*5f757f3fSDimitry Andric   MaxPressure = max(DefPressure, MaxPressure);
311*5f757f3fSDimitry Andric 
312*5f757f3fSDimitry Andric   // Make uses alive.
313*5f757f3fSDimitry Andric   SmallVector<RegisterMaskPair, 8> RegUses;
314*5f757f3fSDimitry Andric   collectVirtualRegUses(RegUses, MI, LIS, *MRI);
315*5f757f3fSDimitry Andric   for (const RegisterMaskPair &U : RegUses) {
316*5f757f3fSDimitry Andric     LaneBitmask &LiveMask = LiveRegs[U.RegUnit];
317*5f757f3fSDimitry Andric     LaneBitmask PrevMask = LiveMask;
3180b57cec5SDimitry Andric     LiveMask |= U.LaneMask;
3190b57cec5SDimitry Andric     CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI);
3200b57cec5SDimitry Andric   }
321*5f757f3fSDimitry Andric 
322*5f757f3fSDimitry Andric   // Update MaxPressure with uses plus early-clobber defs pressure.
323*5f757f3fSDimitry Andric   MaxPressure = HasECDefs ? max(CurPressure + ECDefPressure, MaxPressure)
324*5f757f3fSDimitry Andric                           : max(CurPressure, MaxPressure);
325*5f757f3fSDimitry Andric 
3260b57cec5SDimitry Andric   assert(CurPressure == getRegPressure(*MRI, LiveRegs));
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric 
329*5f757f3fSDimitry Andric ////////////////////////////////////////////////////////////////////////////////
330*5f757f3fSDimitry Andric // GCNDownwardRPTracker
331*5f757f3fSDimitry Andric 
3320b57cec5SDimitry Andric bool GCNDownwardRPTracker::reset(const MachineInstr &MI,
3330b57cec5SDimitry Andric                                  const LiveRegSet *LiveRegsCopy) {
3340b57cec5SDimitry Andric   MRI = &MI.getParent()->getParent()->getRegInfo();
3350b57cec5SDimitry Andric   LastTrackedMI = nullptr;
3360b57cec5SDimitry Andric   MBBEnd = MI.getParent()->end();
3370b57cec5SDimitry Andric   NextMI = &MI;
3380b57cec5SDimitry Andric   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
3390b57cec5SDimitry Andric   if (NextMI == MBBEnd)
3400b57cec5SDimitry Andric     return false;
3410b57cec5SDimitry Andric   GCNRPTracker::reset(*NextMI, LiveRegsCopy, false);
3420b57cec5SDimitry Andric   return true;
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric bool GCNDownwardRPTracker::advanceBeforeNext() {
3460b57cec5SDimitry Andric   assert(MRI && "call reset first");
347bdd1243dSDimitry Andric   if (!LastTrackedMI)
348bdd1243dSDimitry Andric     return NextMI == MBBEnd;
3490b57cec5SDimitry Andric 
350bdd1243dSDimitry Andric   assert(NextMI == MBBEnd || !NextMI->isDebugInstr());
3510b57cec5SDimitry Andric 
352bdd1243dSDimitry Andric   SlotIndex SI = NextMI == MBBEnd
353bdd1243dSDimitry Andric                      ? LIS.getInstructionIndex(*LastTrackedMI).getDeadSlot()
354bdd1243dSDimitry Andric                      : LIS.getInstructionIndex(*NextMI).getBaseIndex();
3550b57cec5SDimitry Andric   assert(SI.isValid());
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   // Remove dead registers or mask bits.
35806c3fb27SDimitry Andric   SmallSet<Register, 8> SeenRegs;
35906c3fb27SDimitry Andric   for (auto &MO : LastTrackedMI->operands()) {
36006c3fb27SDimitry Andric     if (!MO.isReg() || !MO.getReg().isVirtual())
36106c3fb27SDimitry Andric       continue;
36206c3fb27SDimitry Andric     if (MO.isUse() && !MO.readsReg())
36306c3fb27SDimitry Andric       continue;
36406c3fb27SDimitry Andric     if (!SeenRegs.insert(MO.getReg()).second)
36506c3fb27SDimitry Andric       continue;
36606c3fb27SDimitry Andric     const LiveInterval &LI = LIS.getInterval(MO.getReg());
3670b57cec5SDimitry Andric     if (LI.hasSubRanges()) {
36806c3fb27SDimitry Andric       auto It = LiveRegs.end();
3690b57cec5SDimitry Andric       for (const auto &S : LI.subranges()) {
3700b57cec5SDimitry Andric         if (!S.liveAt(SI)) {
37106c3fb27SDimitry Andric           if (It == LiveRegs.end()) {
37206c3fb27SDimitry Andric             It = LiveRegs.find(MO.getReg());
37306c3fb27SDimitry Andric             if (It == LiveRegs.end())
37406c3fb27SDimitry Andric               llvm_unreachable("register isn't live");
37506c3fb27SDimitry Andric           }
37606c3fb27SDimitry Andric           auto PrevMask = It->second;
37706c3fb27SDimitry Andric           It->second &= ~S.LaneMask;
37806c3fb27SDimitry Andric           CurPressure.inc(MO.getReg(), PrevMask, It->second, *MRI);
3790b57cec5SDimitry Andric         }
3800b57cec5SDimitry Andric       }
38106c3fb27SDimitry Andric       if (It != LiveRegs.end() && It->second.none())
38206c3fb27SDimitry Andric         LiveRegs.erase(It);
3830b57cec5SDimitry Andric     } else if (!LI.liveAt(SI)) {
38406c3fb27SDimitry Andric       auto It = LiveRegs.find(MO.getReg());
38506c3fb27SDimitry Andric       if (It == LiveRegs.end())
38606c3fb27SDimitry Andric         llvm_unreachable("register isn't live");
38706c3fb27SDimitry Andric       CurPressure.inc(MO.getReg(), It->second, LaneBitmask::getNone(), *MRI);
38806c3fb27SDimitry Andric       LiveRegs.erase(It);
3890b57cec5SDimitry Andric     }
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   MaxPressure = max(MaxPressure, CurPressure);
3930b57cec5SDimitry Andric 
394bdd1243dSDimitry Andric   LastTrackedMI = nullptr;
395bdd1243dSDimitry Andric 
396bdd1243dSDimitry Andric   return NextMI == MBBEnd;
3970b57cec5SDimitry Andric }
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric void GCNDownwardRPTracker::advanceToNext() {
4000b57cec5SDimitry Andric   LastTrackedMI = &*NextMI++;
401fe6060f1SDimitry Andric   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   // Add new registers or mask bits.
40406c3fb27SDimitry Andric   for (const auto &MO : LastTrackedMI->all_defs()) {
4058bcb0991SDimitry Andric     Register Reg = MO.getReg();
406e8d8bef9SDimitry Andric     if (!Reg.isVirtual())
4070b57cec5SDimitry Andric       continue;
4080b57cec5SDimitry Andric     auto &LiveMask = LiveRegs[Reg];
4090b57cec5SDimitry Andric     auto PrevMask = LiveMask;
4100b57cec5SDimitry Andric     LiveMask |= getDefRegMask(MO, *MRI);
4110b57cec5SDimitry Andric     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
4120b57cec5SDimitry Andric   }
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   MaxPressure = max(MaxPressure, CurPressure);
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance() {
418bdd1243dSDimitry Andric   if (NextMI == MBBEnd)
4190b57cec5SDimitry Andric     return false;
420bdd1243dSDimitry Andric   advanceBeforeNext();
4210b57cec5SDimitry Andric   advanceToNext();
4220b57cec5SDimitry Andric   return true;
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) {
4260b57cec5SDimitry Andric   while (NextMI != End)
4270b57cec5SDimitry Andric     if (!advance()) return false;
4280b57cec5SDimitry Andric   return true;
4290b57cec5SDimitry Andric }
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin,
4320b57cec5SDimitry Andric                                    MachineBasicBlock::const_iterator End,
4330b57cec5SDimitry Andric                                    const LiveRegSet *LiveRegsCopy) {
4340b57cec5SDimitry Andric   reset(*Begin, LiveRegsCopy);
4350b57cec5SDimitry Andric   return advance(End);
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric 
438bdd1243dSDimitry Andric Printable llvm::reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
4390b57cec5SDimitry Andric                                const GCNRPTracker::LiveRegSet &TrackedLR,
440*5f757f3fSDimitry Andric                                const TargetRegisterInfo *TRI, StringRef Pfx) {
441*5f757f3fSDimitry Andric   return Printable([&LISLR, &TrackedLR, TRI, Pfx](raw_ostream &OS) {
4420b57cec5SDimitry Andric     for (auto const &P : TrackedLR) {
4430b57cec5SDimitry Andric       auto I = LISLR.find(P.first);
4440b57cec5SDimitry Andric       if (I == LISLR.end()) {
445*5f757f3fSDimitry Andric         OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
4460b57cec5SDimitry Andric            << " isn't found in LIS reported set\n";
447bdd1243dSDimitry Andric       } else if (I->second != P.second) {
448*5f757f3fSDimitry Andric         OS << Pfx << printReg(P.first, TRI)
449bdd1243dSDimitry Andric            << " masks doesn't match: LIS reported " << PrintLaneMask(I->second)
450bdd1243dSDimitry Andric            << ", tracked " << PrintLaneMask(P.second) << '\n';
4510b57cec5SDimitry Andric       }
4520b57cec5SDimitry Andric     }
4530b57cec5SDimitry Andric     for (auto const &P : LISLR) {
4540b57cec5SDimitry Andric       auto I = TrackedLR.find(P.first);
4550b57cec5SDimitry Andric       if (I == TrackedLR.end()) {
456*5f757f3fSDimitry Andric         OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
4570b57cec5SDimitry Andric            << " isn't found in tracked set\n";
4580b57cec5SDimitry Andric       }
4590b57cec5SDimitry Andric     }
460bdd1243dSDimitry Andric   });
4610b57cec5SDimitry Andric }
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric bool GCNUpwardRPTracker::isValid() const {
4640b57cec5SDimitry Andric   const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
4650b57cec5SDimitry Andric   const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
4660b57cec5SDimitry Andric   const auto &TrackedLR = LiveRegs;
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   if (!isEqual(LISLR, TrackedLR)) {
4690b57cec5SDimitry Andric     dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
470bdd1243dSDimitry Andric               " LIS reported livesets mismatch:\n"
471bdd1243dSDimitry Andric            << print(LISLR, *MRI);
4720b57cec5SDimitry Andric     reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo());
4730b57cec5SDimitry Andric     return false;
4740b57cec5SDimitry Andric   }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   auto LISPressure = getRegPressure(*MRI, LISLR);
4770b57cec5SDimitry Andric   if (LISPressure != CurPressure) {
478bdd1243dSDimitry Andric     dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: "
479bdd1243dSDimitry Andric            << print(CurPressure) << "LIS rpt: " << print(LISPressure);
4800b57cec5SDimitry Andric     return false;
4810b57cec5SDimitry Andric   }
4820b57cec5SDimitry Andric   return true;
4830b57cec5SDimitry Andric }
4840b57cec5SDimitry Andric 
485bdd1243dSDimitry Andric Printable llvm::print(const GCNRPTracker::LiveRegSet &LiveRegs,
4860b57cec5SDimitry Andric                       const MachineRegisterInfo &MRI) {
487bdd1243dSDimitry Andric   return Printable([&LiveRegs, &MRI](raw_ostream &OS) {
4880b57cec5SDimitry Andric     const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
4890b57cec5SDimitry Andric     for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
49004eeddc0SDimitry Andric       Register Reg = Register::index2VirtReg(I);
4910b57cec5SDimitry Andric       auto It = LiveRegs.find(Reg);
4920b57cec5SDimitry Andric       if (It != LiveRegs.end() && It->second.any())
4930b57cec5SDimitry Andric         OS << ' ' << printVRegOrUnit(Reg, TRI) << ':'
4940b57cec5SDimitry Andric            << PrintLaneMask(It->second);
4950b57cec5SDimitry Andric     }
4960b57cec5SDimitry Andric     OS << '\n';
497bdd1243dSDimitry Andric   });
4980b57cec5SDimitry Andric }
499bdd1243dSDimitry Andric 
500bdd1243dSDimitry Andric void GCNRegPressure::dump() const { dbgs() << print(*this); }
501bdd1243dSDimitry Andric 
502*5f757f3fSDimitry Andric static cl::opt<bool> UseDownwardTracker(
503*5f757f3fSDimitry Andric     "amdgpu-print-rp-downward",
504*5f757f3fSDimitry Andric     cl::desc("Use GCNDownwardRPTracker for GCNRegPressurePrinter pass"),
505*5f757f3fSDimitry Andric     cl::init(false), cl::Hidden);
506*5f757f3fSDimitry Andric 
507*5f757f3fSDimitry Andric char llvm::GCNRegPressurePrinter::ID = 0;
508*5f757f3fSDimitry Andric char &llvm::GCNRegPressurePrinterID = GCNRegPressurePrinter::ID;
509*5f757f3fSDimitry Andric 
510*5f757f3fSDimitry Andric INITIALIZE_PASS(GCNRegPressurePrinter, "amdgpu-print-rp", "", true, true)
511*5f757f3fSDimitry Andric 
512*5f757f3fSDimitry Andric // Return lanemask of Reg's subregs that are live-through at [Begin, End] and
513*5f757f3fSDimitry Andric // are fully covered by Mask.
514*5f757f3fSDimitry Andric static LaneBitmask
515*5f757f3fSDimitry Andric getRegLiveThroughMask(const MachineRegisterInfo &MRI, const LiveIntervals &LIS,
516*5f757f3fSDimitry Andric                       Register Reg, SlotIndex Begin, SlotIndex End,
517*5f757f3fSDimitry Andric                       LaneBitmask Mask = LaneBitmask::getAll()) {
518*5f757f3fSDimitry Andric 
519*5f757f3fSDimitry Andric   auto IsInOneSegment = [Begin, End](const LiveRange &LR) -> bool {
520*5f757f3fSDimitry Andric     auto *Segment = LR.getSegmentContaining(Begin);
521*5f757f3fSDimitry Andric     return Segment && Segment->contains(End);
522*5f757f3fSDimitry Andric   };
523*5f757f3fSDimitry Andric 
524*5f757f3fSDimitry Andric   LaneBitmask LiveThroughMask;
525*5f757f3fSDimitry Andric   const LiveInterval &LI = LIS.getInterval(Reg);
526*5f757f3fSDimitry Andric   if (LI.hasSubRanges()) {
527*5f757f3fSDimitry Andric     for (auto &SR : LI.subranges()) {
528*5f757f3fSDimitry Andric       if ((SR.LaneMask & Mask) == SR.LaneMask && IsInOneSegment(SR))
529*5f757f3fSDimitry Andric         LiveThroughMask |= SR.LaneMask;
530*5f757f3fSDimitry Andric     }
531*5f757f3fSDimitry Andric   } else {
532*5f757f3fSDimitry Andric     LaneBitmask RegMask = MRI.getMaxLaneMaskForVReg(Reg);
533*5f757f3fSDimitry Andric     if ((RegMask & Mask) == RegMask && IsInOneSegment(LI))
534*5f757f3fSDimitry Andric       LiveThroughMask = RegMask;
535*5f757f3fSDimitry Andric   }
536*5f757f3fSDimitry Andric 
537*5f757f3fSDimitry Andric   return LiveThroughMask;
538*5f757f3fSDimitry Andric }
539*5f757f3fSDimitry Andric 
540*5f757f3fSDimitry Andric bool GCNRegPressurePrinter::runOnMachineFunction(MachineFunction &MF) {
541*5f757f3fSDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
542*5f757f3fSDimitry Andric   const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
543*5f757f3fSDimitry Andric   const LiveIntervals &LIS = getAnalysis<LiveIntervals>();
544*5f757f3fSDimitry Andric 
545*5f757f3fSDimitry Andric   auto &OS = dbgs();
546*5f757f3fSDimitry Andric 
547*5f757f3fSDimitry Andric // Leading spaces are important for YAML syntax.
548*5f757f3fSDimitry Andric #define PFX "  "
549*5f757f3fSDimitry Andric 
550*5f757f3fSDimitry Andric   OS << "---\nname: " << MF.getName() << "\nbody:             |\n";
551*5f757f3fSDimitry Andric 
552*5f757f3fSDimitry Andric   auto printRP = [](const GCNRegPressure &RP) {
553*5f757f3fSDimitry Andric     return Printable([&RP](raw_ostream &OS) {
554*5f757f3fSDimitry Andric       OS << format(PFX "  %-5d", RP.getSGPRNum())
555*5f757f3fSDimitry Andric          << format(" %-5d", RP.getVGPRNum(false));
556*5f757f3fSDimitry Andric     });
557*5f757f3fSDimitry Andric   };
558*5f757f3fSDimitry Andric 
559*5f757f3fSDimitry Andric   auto ReportLISMismatchIfAny = [&](const GCNRPTracker::LiveRegSet &TrackedLR,
560*5f757f3fSDimitry Andric                                     const GCNRPTracker::LiveRegSet &LISLR) {
561*5f757f3fSDimitry Andric     if (LISLR != TrackedLR) {
562*5f757f3fSDimitry Andric       OS << PFX "  mis LIS: " << llvm::print(LISLR, MRI)
563*5f757f3fSDimitry Andric          << reportMismatch(LISLR, TrackedLR, TRI, PFX "    ");
564*5f757f3fSDimitry Andric     }
565*5f757f3fSDimitry Andric   };
566*5f757f3fSDimitry Andric 
567*5f757f3fSDimitry Andric   // Register pressure before and at an instruction (in program order).
568*5f757f3fSDimitry Andric   SmallVector<std::pair<GCNRegPressure, GCNRegPressure>, 16> RP;
569*5f757f3fSDimitry Andric 
570*5f757f3fSDimitry Andric   for (auto &MBB : MF) {
571*5f757f3fSDimitry Andric     RP.clear();
572*5f757f3fSDimitry Andric     RP.reserve(MBB.size());
573*5f757f3fSDimitry Andric 
574*5f757f3fSDimitry Andric     OS << PFX;
575*5f757f3fSDimitry Andric     MBB.printName(OS);
576*5f757f3fSDimitry Andric     OS << ":\n";
577*5f757f3fSDimitry Andric 
578*5f757f3fSDimitry Andric     SlotIndex MBBStartSlot = LIS.getSlotIndexes()->getMBBStartIdx(&MBB);
579*5f757f3fSDimitry Andric     SlotIndex MBBEndSlot = LIS.getSlotIndexes()->getMBBEndIdx(&MBB);
580*5f757f3fSDimitry Andric 
581*5f757f3fSDimitry Andric     GCNRPTracker::LiveRegSet LiveIn, LiveOut;
582*5f757f3fSDimitry Andric     GCNRegPressure RPAtMBBEnd;
583*5f757f3fSDimitry Andric 
584*5f757f3fSDimitry Andric     if (UseDownwardTracker) {
585*5f757f3fSDimitry Andric       if (MBB.empty()) {
586*5f757f3fSDimitry Andric         LiveIn = LiveOut = getLiveRegs(MBBStartSlot, LIS, MRI);
587*5f757f3fSDimitry Andric         RPAtMBBEnd = getRegPressure(MRI, LiveIn);
588*5f757f3fSDimitry Andric       } else {
589*5f757f3fSDimitry Andric         GCNDownwardRPTracker RPT(LIS);
590*5f757f3fSDimitry Andric         RPT.reset(MBB.front());
591*5f757f3fSDimitry Andric 
592*5f757f3fSDimitry Andric         LiveIn = RPT.getLiveRegs();
593*5f757f3fSDimitry Andric 
594*5f757f3fSDimitry Andric         while (!RPT.advanceBeforeNext()) {
595*5f757f3fSDimitry Andric           GCNRegPressure RPBeforeMI = RPT.getPressure();
596*5f757f3fSDimitry Andric           RPT.advanceToNext();
597*5f757f3fSDimitry Andric           RP.emplace_back(RPBeforeMI, RPT.getPressure());
598*5f757f3fSDimitry Andric         }
599*5f757f3fSDimitry Andric 
600*5f757f3fSDimitry Andric         LiveOut = RPT.getLiveRegs();
601*5f757f3fSDimitry Andric         RPAtMBBEnd = RPT.getPressure();
602*5f757f3fSDimitry Andric       }
603*5f757f3fSDimitry Andric     } else {
604*5f757f3fSDimitry Andric       GCNUpwardRPTracker RPT(LIS);
605*5f757f3fSDimitry Andric       RPT.reset(MRI, MBBEndSlot);
606*5f757f3fSDimitry Andric 
607*5f757f3fSDimitry Andric       LiveOut = RPT.getLiveRegs();
608*5f757f3fSDimitry Andric       RPAtMBBEnd = RPT.getPressure();
609*5f757f3fSDimitry Andric 
610*5f757f3fSDimitry Andric       for (auto &MI : reverse(MBB)) {
611*5f757f3fSDimitry Andric         RPT.resetMaxPressure();
612*5f757f3fSDimitry Andric         RPT.recede(MI);
613*5f757f3fSDimitry Andric         if (!MI.isDebugInstr())
614*5f757f3fSDimitry Andric           RP.emplace_back(RPT.getPressure(), RPT.getMaxPressure());
615*5f757f3fSDimitry Andric       }
616*5f757f3fSDimitry Andric 
617*5f757f3fSDimitry Andric       LiveIn = RPT.getLiveRegs();
618*5f757f3fSDimitry Andric     }
619*5f757f3fSDimitry Andric 
620*5f757f3fSDimitry Andric     OS << PFX "  Live-in: " << llvm::print(LiveIn, MRI);
621*5f757f3fSDimitry Andric     if (!UseDownwardTracker)
622*5f757f3fSDimitry Andric       ReportLISMismatchIfAny(LiveIn, getLiveRegs(MBBStartSlot, LIS, MRI));
623*5f757f3fSDimitry Andric 
624*5f757f3fSDimitry Andric     OS << PFX "  SGPR  VGPR\n";
625*5f757f3fSDimitry Andric     int I = 0;
626*5f757f3fSDimitry Andric     for (auto &MI : MBB) {
627*5f757f3fSDimitry Andric       if (!MI.isDebugInstr()) {
628*5f757f3fSDimitry Andric         auto &[RPBeforeInstr, RPAtInstr] =
629*5f757f3fSDimitry Andric             RP[UseDownwardTracker ? I : (RP.size() - 1 - I)];
630*5f757f3fSDimitry Andric         ++I;
631*5f757f3fSDimitry Andric         OS << printRP(RPBeforeInstr) << '\n' << printRP(RPAtInstr) << "  ";
632*5f757f3fSDimitry Andric       } else
633*5f757f3fSDimitry Andric         OS << PFX "               ";
634*5f757f3fSDimitry Andric       MI.print(OS);
635*5f757f3fSDimitry Andric     }
636*5f757f3fSDimitry Andric     OS << printRP(RPAtMBBEnd) << '\n';
637*5f757f3fSDimitry Andric 
638*5f757f3fSDimitry Andric     OS << PFX "  Live-out:" << llvm::print(LiveOut, MRI);
639*5f757f3fSDimitry Andric     if (UseDownwardTracker)
640*5f757f3fSDimitry Andric       ReportLISMismatchIfAny(LiveOut, getLiveRegs(MBBEndSlot, LIS, MRI));
641*5f757f3fSDimitry Andric 
642*5f757f3fSDimitry Andric     GCNRPTracker::LiveRegSet LiveThrough;
643*5f757f3fSDimitry Andric     for (auto [Reg, Mask] : LiveIn) {
644*5f757f3fSDimitry Andric       LaneBitmask MaskIntersection = Mask & LiveOut.lookup(Reg);
645*5f757f3fSDimitry Andric       if (MaskIntersection.any()) {
646*5f757f3fSDimitry Andric         LaneBitmask LTMask = getRegLiveThroughMask(
647*5f757f3fSDimitry Andric             MRI, LIS, Reg, MBBStartSlot, MBBEndSlot, MaskIntersection);
648*5f757f3fSDimitry Andric         if (LTMask.any())
649*5f757f3fSDimitry Andric           LiveThrough[Reg] = LTMask;
650*5f757f3fSDimitry Andric       }
651*5f757f3fSDimitry Andric     }
652*5f757f3fSDimitry Andric     OS << PFX "  Live-thr:" << llvm::print(LiveThrough, MRI);
653*5f757f3fSDimitry Andric     OS << printRP(getRegPressure(MRI, LiveThrough)) << '\n';
654*5f757f3fSDimitry Andric   }
655*5f757f3fSDimitry Andric   OS << "...\n";
656*5f757f3fSDimitry Andric   return false;
657*5f757f3fSDimitry Andric 
658*5f757f3fSDimitry Andric #undef PFX
659*5f757f3fSDimitry Andric }