xref: /openbsd-src/gnu/llvm/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- GCNRegPressure.cpp -------------------------------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
8097a140dSpatrick ///
9097a140dSpatrick /// \file
10097a140dSpatrick /// This file implements the GCNRegPressure class.
11097a140dSpatrick ///
12097a140dSpatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
1409467b48Spatrick #include "GCNRegPressure.h"
1509467b48Spatrick #include "llvm/CodeGen/RegisterPressure.h"
1609467b48Spatrick 
1709467b48Spatrick using namespace llvm;
1809467b48Spatrick 
1909467b48Spatrick #define DEBUG_TYPE "machine-scheduler"
2009467b48Spatrick 
isEqual(const GCNRPTracker::LiveRegSet & S1,const GCNRPTracker::LiveRegSet & S2)2109467b48Spatrick bool llvm::isEqual(const GCNRPTracker::LiveRegSet &S1,
2209467b48Spatrick                    const GCNRPTracker::LiveRegSet &S2) {
2309467b48Spatrick   if (S1.size() != S2.size())
2409467b48Spatrick     return false;
2509467b48Spatrick 
2609467b48Spatrick   for (const auto &P : S1) {
2709467b48Spatrick     auto I = S2.find(P.first);
2809467b48Spatrick     if (I == S2.end() || I->second != P.second)
2909467b48Spatrick       return false;
3009467b48Spatrick   }
3109467b48Spatrick   return true;
3209467b48Spatrick }
3309467b48Spatrick 
3409467b48Spatrick 
3509467b48Spatrick ///////////////////////////////////////////////////////////////////////////////
3609467b48Spatrick // GCNRegPressure
3709467b48Spatrick 
getRegKind(Register Reg,const MachineRegisterInfo & MRI)3873471bf0Spatrick unsigned GCNRegPressure::getRegKind(Register Reg,
3909467b48Spatrick                                     const MachineRegisterInfo &MRI) {
4073471bf0Spatrick   assert(Reg.isVirtual());
4109467b48Spatrick   const auto RC = MRI.getRegClass(Reg);
4209467b48Spatrick   auto STI = static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo());
43*d415bd75Srobert   return STI->isSGPRClass(RC)
44*d415bd75Srobert              ? (STI->getRegSizeInBits(*RC) == 32 ? SGPR32 : SGPR_TUPLE)
45*d415bd75Srobert          : STI->isAGPRClass(RC)
46*d415bd75Srobert              ? (STI->getRegSizeInBits(*RC) == 32 ? AGPR32 : AGPR_TUPLE)
47*d415bd75Srobert              : (STI->getRegSizeInBits(*RC) == 32 ? VGPR32 : VGPR_TUPLE);
4809467b48Spatrick }
4909467b48Spatrick 
inc(unsigned Reg,LaneBitmask PrevMask,LaneBitmask NewMask,const MachineRegisterInfo & MRI)5009467b48Spatrick void GCNRegPressure::inc(unsigned Reg,
5109467b48Spatrick                          LaneBitmask PrevMask,
5209467b48Spatrick                          LaneBitmask NewMask,
5309467b48Spatrick                          const MachineRegisterInfo &MRI) {
54097a140dSpatrick   if (SIRegisterInfo::getNumCoveredRegs(NewMask) ==
55097a140dSpatrick       SIRegisterInfo::getNumCoveredRegs(PrevMask))
5609467b48Spatrick     return;
5709467b48Spatrick 
5809467b48Spatrick   int Sign = 1;
5909467b48Spatrick   if (NewMask < PrevMask) {
6009467b48Spatrick     std::swap(NewMask, PrevMask);
6109467b48Spatrick     Sign = -1;
6209467b48Spatrick   }
63097a140dSpatrick 
6409467b48Spatrick   switch (auto Kind = getRegKind(Reg, MRI)) {
6509467b48Spatrick   case SGPR32:
6609467b48Spatrick   case VGPR32:
6709467b48Spatrick   case AGPR32:
6809467b48Spatrick     Value[Kind] += Sign;
6909467b48Spatrick     break;
7009467b48Spatrick 
7109467b48Spatrick   case SGPR_TUPLE:
7209467b48Spatrick   case VGPR_TUPLE:
7309467b48Spatrick   case AGPR_TUPLE:
7409467b48Spatrick     assert(PrevMask < NewMask);
7509467b48Spatrick 
7609467b48Spatrick     Value[Kind == SGPR_TUPLE ? SGPR32 : Kind == AGPR_TUPLE ? AGPR32 : VGPR32] +=
77097a140dSpatrick       Sign * SIRegisterInfo::getNumCoveredRegs(~PrevMask & NewMask);
7809467b48Spatrick 
7909467b48Spatrick     if (PrevMask.none()) {
8009467b48Spatrick       assert(NewMask.any());
8109467b48Spatrick       Value[Kind] += Sign * MRI.getPressureSets(Reg).getWeight();
8209467b48Spatrick     }
8309467b48Spatrick     break;
8409467b48Spatrick 
8509467b48Spatrick   default: llvm_unreachable("Unknown register kind");
8609467b48Spatrick   }
8709467b48Spatrick }
8809467b48Spatrick 
less(const GCNSubtarget & ST,const GCNRegPressure & O,unsigned MaxOccupancy) const8909467b48Spatrick bool GCNRegPressure::less(const GCNSubtarget &ST,
9009467b48Spatrick                           const GCNRegPressure& O,
9109467b48Spatrick                           unsigned MaxOccupancy) const {
9209467b48Spatrick   const auto SGPROcc = std::min(MaxOccupancy,
9309467b48Spatrick                                 ST.getOccupancyWithNumSGPRs(getSGPRNum()));
9473471bf0Spatrick   const auto VGPROcc =
9573471bf0Spatrick     std::min(MaxOccupancy,
9673471bf0Spatrick              ST.getOccupancyWithNumVGPRs(getVGPRNum(ST.hasGFX90AInsts())));
9709467b48Spatrick   const auto OtherSGPROcc = std::min(MaxOccupancy,
9809467b48Spatrick                                 ST.getOccupancyWithNumSGPRs(O.getSGPRNum()));
9973471bf0Spatrick   const auto OtherVGPROcc =
10073471bf0Spatrick     std::min(MaxOccupancy,
10173471bf0Spatrick              ST.getOccupancyWithNumVGPRs(O.getVGPRNum(ST.hasGFX90AInsts())));
10209467b48Spatrick 
10309467b48Spatrick   const auto Occ = std::min(SGPROcc, VGPROcc);
10409467b48Spatrick   const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc);
10509467b48Spatrick   if (Occ != OtherOcc)
10609467b48Spatrick     return Occ > OtherOcc;
10709467b48Spatrick 
10809467b48Spatrick   bool SGPRImportant = SGPROcc < VGPROcc;
10909467b48Spatrick   const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc;
11009467b48Spatrick 
11109467b48Spatrick   // if both pressures disagree on what is more important compare vgprs
11209467b48Spatrick   if (SGPRImportant != OtherSGPRImportant) {
11309467b48Spatrick     SGPRImportant = false;
11409467b48Spatrick   }
11509467b48Spatrick 
11609467b48Spatrick   // compare large regs pressure
11709467b48Spatrick   bool SGPRFirst = SGPRImportant;
11809467b48Spatrick   for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) {
11909467b48Spatrick     if (SGPRFirst) {
12009467b48Spatrick       auto SW = getSGPRTuplesWeight();
12109467b48Spatrick       auto OtherSW = O.getSGPRTuplesWeight();
12209467b48Spatrick       if (SW != OtherSW)
12309467b48Spatrick         return SW < OtherSW;
12409467b48Spatrick     } else {
12509467b48Spatrick       auto VW = getVGPRTuplesWeight();
12609467b48Spatrick       auto OtherVW = O.getVGPRTuplesWeight();
12709467b48Spatrick       if (VW != OtherVW)
12809467b48Spatrick         return VW < OtherVW;
12909467b48Spatrick     }
13009467b48Spatrick   }
13109467b48Spatrick   return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()):
13273471bf0Spatrick                          (getVGPRNum(ST.hasGFX90AInsts()) <
13373471bf0Spatrick                           O.getVGPRNum(ST.hasGFX90AInsts()));
13409467b48Spatrick }
13509467b48Spatrick 
13609467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
13709467b48Spatrick LLVM_DUMP_METHOD
print(const GCNRegPressure & RP,const GCNSubtarget * ST)138*d415bd75Srobert Printable llvm::print(const GCNRegPressure &RP, const GCNSubtarget *ST) {
139*d415bd75Srobert   return Printable([&RP, ST](raw_ostream &OS) {
140*d415bd75Srobert     OS << "VGPRs: " << RP.Value[GCNRegPressure::VGPR32] << ' '
141*d415bd75Srobert        << "AGPRs: " << RP.getAGPRNum();
142*d415bd75Srobert     if (ST)
143*d415bd75Srobert       OS << "(O"
144*d415bd75Srobert          << ST->getOccupancyWithNumVGPRs(RP.getVGPRNum(ST->hasGFX90AInsts()))
14573471bf0Spatrick          << ')';
146*d415bd75Srobert     OS << ", SGPRs: " << RP.getSGPRNum();
147*d415bd75Srobert     if (ST)
148*d415bd75Srobert       OS << "(O" << ST->getOccupancyWithNumSGPRs(RP.getSGPRNum()) << ')';
149*d415bd75Srobert     OS << ", LVGPR WT: " << RP.getVGPRTuplesWeight()
150*d415bd75Srobert        << ", LSGPR WT: " << RP.getSGPRTuplesWeight();
151*d415bd75Srobert     if (ST)
152*d415bd75Srobert       OS << " -> Occ: " << RP.getOccupancy(*ST);
15309467b48Spatrick     OS << '\n';
154*d415bd75Srobert   });
15509467b48Spatrick }
15609467b48Spatrick #endif
15709467b48Spatrick 
getDefRegMask(const MachineOperand & MO,const MachineRegisterInfo & MRI)15809467b48Spatrick static LaneBitmask getDefRegMask(const MachineOperand &MO,
15909467b48Spatrick                                  const MachineRegisterInfo &MRI) {
16073471bf0Spatrick   assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual());
16109467b48Spatrick 
16209467b48Spatrick   // We don't rely on read-undef flag because in case of tentative schedule
16309467b48Spatrick   // tracking it isn't set correctly yet. This works correctly however since
16409467b48Spatrick   // use mask has been tracked before using LIS.
16509467b48Spatrick   return MO.getSubReg() == 0 ?
16609467b48Spatrick     MRI.getMaxLaneMaskForVReg(MO.getReg()) :
16709467b48Spatrick     MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
16809467b48Spatrick }
16909467b48Spatrick 
getUsedRegMask(const MachineOperand & MO,const MachineRegisterInfo & MRI,const LiveIntervals & LIS)17009467b48Spatrick static LaneBitmask getUsedRegMask(const MachineOperand &MO,
17109467b48Spatrick                                   const MachineRegisterInfo &MRI,
17209467b48Spatrick                                   const LiveIntervals &LIS) {
17373471bf0Spatrick   assert(MO.isUse() && MO.isReg() && MO.getReg().isVirtual());
17409467b48Spatrick 
17509467b48Spatrick   if (auto SubReg = MO.getSubReg())
17609467b48Spatrick     return MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg);
17709467b48Spatrick 
17809467b48Spatrick   auto MaxMask = MRI.getMaxLaneMaskForVReg(MO.getReg());
179097a140dSpatrick   if (SIRegisterInfo::getNumCoveredRegs(MaxMask) > 1) // cannot have subregs
18009467b48Spatrick     return MaxMask;
18109467b48Spatrick 
18209467b48Spatrick   // For a tentative schedule LIS isn't updated yet but livemask should remain
18309467b48Spatrick   // the same on any schedule. Subreg defs can be reordered but they all must
18409467b48Spatrick   // dominate uses anyway.
18509467b48Spatrick   auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex();
18609467b48Spatrick   return getLiveLaneMask(MO.getReg(), SI, LIS, MRI);
18709467b48Spatrick }
18809467b48Spatrick 
18909467b48Spatrick static SmallVector<RegisterMaskPair, 8>
collectVirtualRegUses(const MachineInstr & MI,const LiveIntervals & LIS,const MachineRegisterInfo & MRI)19009467b48Spatrick collectVirtualRegUses(const MachineInstr &MI, const LiveIntervals &LIS,
19109467b48Spatrick                       const MachineRegisterInfo &MRI) {
19209467b48Spatrick   SmallVector<RegisterMaskPair, 8> Res;
19309467b48Spatrick   for (const auto &MO : MI.operands()) {
19473471bf0Spatrick     if (!MO.isReg() || !MO.getReg().isVirtual())
19509467b48Spatrick       continue;
19609467b48Spatrick     if (!MO.isUse() || !MO.readsReg())
19709467b48Spatrick       continue;
19809467b48Spatrick 
19909467b48Spatrick     auto const UsedMask = getUsedRegMask(MO, MRI, LIS);
20009467b48Spatrick 
20109467b48Spatrick     auto Reg = MO.getReg();
20273471bf0Spatrick     auto I = llvm::find_if(
20373471bf0Spatrick         Res, [Reg](const RegisterMaskPair &RM) { return RM.RegUnit == Reg; });
20409467b48Spatrick     if (I != Res.end())
20509467b48Spatrick       I->LaneMask |= UsedMask;
20609467b48Spatrick     else
20709467b48Spatrick       Res.push_back(RegisterMaskPair(Reg, UsedMask));
20809467b48Spatrick   }
20909467b48Spatrick   return Res;
21009467b48Spatrick }
21109467b48Spatrick 
21209467b48Spatrick ///////////////////////////////////////////////////////////////////////////////
21309467b48Spatrick // GCNRPTracker
21409467b48Spatrick 
getLiveLaneMask(unsigned Reg,SlotIndex SI,const LiveIntervals & LIS,const MachineRegisterInfo & MRI)21509467b48Spatrick LaneBitmask llvm::getLiveLaneMask(unsigned Reg,
21609467b48Spatrick                                   SlotIndex SI,
21709467b48Spatrick                                   const LiveIntervals &LIS,
21809467b48Spatrick                                   const MachineRegisterInfo &MRI) {
21909467b48Spatrick   LaneBitmask LiveMask;
22009467b48Spatrick   const auto &LI = LIS.getInterval(Reg);
22109467b48Spatrick   if (LI.hasSubRanges()) {
22209467b48Spatrick     for (const auto &S : LI.subranges())
22309467b48Spatrick       if (S.liveAt(SI)) {
22409467b48Spatrick         LiveMask |= S.LaneMask;
22509467b48Spatrick         assert(LiveMask < MRI.getMaxLaneMaskForVReg(Reg) ||
22609467b48Spatrick                LiveMask == MRI.getMaxLaneMaskForVReg(Reg));
22709467b48Spatrick       }
22809467b48Spatrick   } else if (LI.liveAt(SI)) {
22909467b48Spatrick     LiveMask = MRI.getMaxLaneMaskForVReg(Reg);
23009467b48Spatrick   }
23109467b48Spatrick   return LiveMask;
23209467b48Spatrick }
23309467b48Spatrick 
getLiveRegs(SlotIndex SI,const LiveIntervals & LIS,const MachineRegisterInfo & MRI)23409467b48Spatrick GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
23509467b48Spatrick                                            const LiveIntervals &LIS,
23609467b48Spatrick                                            const MachineRegisterInfo &MRI) {
23709467b48Spatrick   GCNRPTracker::LiveRegSet LiveRegs;
23809467b48Spatrick   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
23909467b48Spatrick     auto Reg = Register::index2VirtReg(I);
24009467b48Spatrick     if (!LIS.hasInterval(Reg))
24109467b48Spatrick       continue;
24209467b48Spatrick     auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI);
24309467b48Spatrick     if (LiveMask.any())
24409467b48Spatrick       LiveRegs[Reg] = LiveMask;
24509467b48Spatrick   }
24609467b48Spatrick   return LiveRegs;
24709467b48Spatrick }
24809467b48Spatrick 
reset(const MachineInstr & MI,const LiveRegSet * LiveRegsCopy,bool After)24909467b48Spatrick void GCNRPTracker::reset(const MachineInstr &MI,
25009467b48Spatrick                          const LiveRegSet *LiveRegsCopy,
25109467b48Spatrick                          bool After) {
25209467b48Spatrick   const MachineFunction &MF = *MI.getMF();
25309467b48Spatrick   MRI = &MF.getRegInfo();
25409467b48Spatrick   if (LiveRegsCopy) {
25509467b48Spatrick     if (&LiveRegs != LiveRegsCopy)
25609467b48Spatrick       LiveRegs = *LiveRegsCopy;
25709467b48Spatrick   } else {
25809467b48Spatrick     LiveRegs = After ? getLiveRegsAfter(MI, LIS)
25909467b48Spatrick                      : getLiveRegsBefore(MI, LIS);
26009467b48Spatrick   }
26109467b48Spatrick 
26209467b48Spatrick   MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs);
26309467b48Spatrick }
26409467b48Spatrick 
reset(const MachineInstr & MI,const LiveRegSet * LiveRegsCopy)26509467b48Spatrick void GCNUpwardRPTracker::reset(const MachineInstr &MI,
26609467b48Spatrick                                const LiveRegSet *LiveRegsCopy) {
26709467b48Spatrick   GCNRPTracker::reset(MI, LiveRegsCopy, true);
26809467b48Spatrick }
26909467b48Spatrick 
recede(const MachineInstr & MI)27009467b48Spatrick void GCNUpwardRPTracker::recede(const MachineInstr &MI) {
27109467b48Spatrick   assert(MRI && "call reset first");
27209467b48Spatrick 
27309467b48Spatrick   LastTrackedMI = &MI;
27409467b48Spatrick 
27509467b48Spatrick   if (MI.isDebugInstr())
27609467b48Spatrick     return;
27709467b48Spatrick 
27809467b48Spatrick   auto const RegUses = collectVirtualRegUses(MI, LIS, *MRI);
27909467b48Spatrick 
28009467b48Spatrick   // calc pressure at the MI (defs + uses)
28109467b48Spatrick   auto AtMIPressure = CurPressure;
28209467b48Spatrick   for (const auto &U : RegUses) {
28309467b48Spatrick     auto LiveMask = LiveRegs[U.RegUnit];
28409467b48Spatrick     AtMIPressure.inc(U.RegUnit, LiveMask, LiveMask | U.LaneMask, *MRI);
28509467b48Spatrick   }
28609467b48Spatrick   // update max pressure
28709467b48Spatrick   MaxPressure = max(AtMIPressure, MaxPressure);
28809467b48Spatrick 
289097a140dSpatrick   for (const auto &MO : MI.operands()) {
29073471bf0Spatrick     if (!MO.isReg() || !MO.isDef() || !MO.getReg().isVirtual() || MO.isDead())
29109467b48Spatrick       continue;
29209467b48Spatrick 
29309467b48Spatrick     auto Reg = MO.getReg();
29409467b48Spatrick     auto I = LiveRegs.find(Reg);
29509467b48Spatrick     if (I == LiveRegs.end())
29609467b48Spatrick       continue;
29709467b48Spatrick     auto &LiveMask = I->second;
29809467b48Spatrick     auto PrevMask = LiveMask;
29909467b48Spatrick     LiveMask &= ~getDefRegMask(MO, *MRI);
30009467b48Spatrick     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
30109467b48Spatrick     if (LiveMask.none())
30209467b48Spatrick       LiveRegs.erase(I);
30309467b48Spatrick   }
30409467b48Spatrick   for (const auto &U : RegUses) {
30509467b48Spatrick     auto &LiveMask = LiveRegs[U.RegUnit];
30609467b48Spatrick     auto PrevMask = LiveMask;
30709467b48Spatrick     LiveMask |= U.LaneMask;
30809467b48Spatrick     CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI);
30909467b48Spatrick   }
31009467b48Spatrick   assert(CurPressure == getRegPressure(*MRI, LiveRegs));
31109467b48Spatrick }
31209467b48Spatrick 
reset(const MachineInstr & MI,const LiveRegSet * LiveRegsCopy)31309467b48Spatrick bool GCNDownwardRPTracker::reset(const MachineInstr &MI,
31409467b48Spatrick                                  const LiveRegSet *LiveRegsCopy) {
31509467b48Spatrick   MRI = &MI.getParent()->getParent()->getRegInfo();
31609467b48Spatrick   LastTrackedMI = nullptr;
31709467b48Spatrick   MBBEnd = MI.getParent()->end();
31809467b48Spatrick   NextMI = &MI;
31909467b48Spatrick   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
32009467b48Spatrick   if (NextMI == MBBEnd)
32109467b48Spatrick     return false;
32209467b48Spatrick   GCNRPTracker::reset(*NextMI, LiveRegsCopy, false);
32309467b48Spatrick   return true;
32409467b48Spatrick }
32509467b48Spatrick 
advanceBeforeNext()32609467b48Spatrick bool GCNDownwardRPTracker::advanceBeforeNext() {
32709467b48Spatrick   assert(MRI && "call reset first");
328*d415bd75Srobert   if (!LastTrackedMI)
329*d415bd75Srobert     return NextMI == MBBEnd;
33009467b48Spatrick 
331*d415bd75Srobert   assert(NextMI == MBBEnd || !NextMI->isDebugInstr());
33209467b48Spatrick 
333*d415bd75Srobert   SlotIndex SI = NextMI == MBBEnd
334*d415bd75Srobert                      ? LIS.getInstructionIndex(*LastTrackedMI).getDeadSlot()
335*d415bd75Srobert                      : LIS.getInstructionIndex(*NextMI).getBaseIndex();
33609467b48Spatrick   assert(SI.isValid());
33709467b48Spatrick 
33809467b48Spatrick   // Remove dead registers or mask bits.
33909467b48Spatrick   for (auto &It : LiveRegs) {
34009467b48Spatrick     const LiveInterval &LI = LIS.getInterval(It.first);
34109467b48Spatrick     if (LI.hasSubRanges()) {
34209467b48Spatrick       for (const auto &S : LI.subranges()) {
34309467b48Spatrick         if (!S.liveAt(SI)) {
34409467b48Spatrick           auto PrevMask = It.second;
34509467b48Spatrick           It.second &= ~S.LaneMask;
34609467b48Spatrick           CurPressure.inc(It.first, PrevMask, It.second, *MRI);
34709467b48Spatrick         }
34809467b48Spatrick       }
34909467b48Spatrick     } else if (!LI.liveAt(SI)) {
35009467b48Spatrick       auto PrevMask = It.second;
35109467b48Spatrick       It.second = LaneBitmask::getNone();
35209467b48Spatrick       CurPressure.inc(It.first, PrevMask, It.second, *MRI);
35309467b48Spatrick     }
35409467b48Spatrick     if (It.second.none())
35509467b48Spatrick       LiveRegs.erase(It.first);
35609467b48Spatrick   }
35709467b48Spatrick 
35809467b48Spatrick   MaxPressure = max(MaxPressure, CurPressure);
35909467b48Spatrick 
360*d415bd75Srobert   LastTrackedMI = nullptr;
361*d415bd75Srobert 
362*d415bd75Srobert   return NextMI == MBBEnd;
36309467b48Spatrick }
36409467b48Spatrick 
advanceToNext()36509467b48Spatrick void GCNDownwardRPTracker::advanceToNext() {
36609467b48Spatrick   LastTrackedMI = &*NextMI++;
36773471bf0Spatrick   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
36809467b48Spatrick 
36909467b48Spatrick   // Add new registers or mask bits.
370097a140dSpatrick   for (const auto &MO : LastTrackedMI->operands()) {
371097a140dSpatrick     if (!MO.isReg() || !MO.isDef())
37209467b48Spatrick       continue;
37309467b48Spatrick     Register Reg = MO.getReg();
37473471bf0Spatrick     if (!Reg.isVirtual())
37509467b48Spatrick       continue;
37609467b48Spatrick     auto &LiveMask = LiveRegs[Reg];
37709467b48Spatrick     auto PrevMask = LiveMask;
37809467b48Spatrick     LiveMask |= getDefRegMask(MO, *MRI);
37909467b48Spatrick     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
38009467b48Spatrick   }
38109467b48Spatrick 
38209467b48Spatrick   MaxPressure = max(MaxPressure, CurPressure);
38309467b48Spatrick }
38409467b48Spatrick 
advance()38509467b48Spatrick bool GCNDownwardRPTracker::advance() {
386*d415bd75Srobert   if (NextMI == MBBEnd)
38709467b48Spatrick     return false;
388*d415bd75Srobert   advanceBeforeNext();
38909467b48Spatrick   advanceToNext();
39009467b48Spatrick   return true;
39109467b48Spatrick }
39209467b48Spatrick 
advance(MachineBasicBlock::const_iterator End)39309467b48Spatrick bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) {
39409467b48Spatrick   while (NextMI != End)
39509467b48Spatrick     if (!advance()) return false;
39609467b48Spatrick   return true;
39709467b48Spatrick }
39809467b48Spatrick 
advance(MachineBasicBlock::const_iterator Begin,MachineBasicBlock::const_iterator End,const LiveRegSet * LiveRegsCopy)39909467b48Spatrick bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin,
40009467b48Spatrick                                    MachineBasicBlock::const_iterator End,
40109467b48Spatrick                                    const LiveRegSet *LiveRegsCopy) {
40209467b48Spatrick   reset(*Begin, LiveRegsCopy);
40309467b48Spatrick   return advance(End);
40409467b48Spatrick }
40509467b48Spatrick 
40609467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
40709467b48Spatrick LLVM_DUMP_METHOD
reportMismatch(const GCNRPTracker::LiveRegSet & LISLR,const GCNRPTracker::LiveRegSet & TrackedLR,const TargetRegisterInfo * TRI)408*d415bd75Srobert Printable llvm::reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
40909467b48Spatrick                                const GCNRPTracker::LiveRegSet &TrackedLR,
41009467b48Spatrick                                const TargetRegisterInfo *TRI) {
411*d415bd75Srobert   return Printable([&LISLR, &TrackedLR, TRI](raw_ostream &OS) {
41209467b48Spatrick     for (auto const &P : TrackedLR) {
41309467b48Spatrick       auto I = LISLR.find(P.first);
41409467b48Spatrick       if (I == LISLR.end()) {
415*d415bd75Srobert         OS << "  " << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
41609467b48Spatrick            << " isn't found in LIS reported set\n";
417*d415bd75Srobert       } else if (I->second != P.second) {
418*d415bd75Srobert         OS << "  " << printReg(P.first, TRI)
419*d415bd75Srobert            << " masks doesn't match: LIS reported " << PrintLaneMask(I->second)
420*d415bd75Srobert            << ", tracked " << PrintLaneMask(P.second) << '\n';
42109467b48Spatrick       }
42209467b48Spatrick     }
42309467b48Spatrick     for (auto const &P : LISLR) {
42409467b48Spatrick       auto I = TrackedLR.find(P.first);
42509467b48Spatrick       if (I == TrackedLR.end()) {
426*d415bd75Srobert         OS << "  " << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
42709467b48Spatrick            << " isn't found in tracked set\n";
42809467b48Spatrick       }
42909467b48Spatrick     }
430*d415bd75Srobert   });
43109467b48Spatrick }
43209467b48Spatrick 
isValid() const43309467b48Spatrick bool GCNUpwardRPTracker::isValid() const {
43409467b48Spatrick   const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
43509467b48Spatrick   const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
43609467b48Spatrick   const auto &TrackedLR = LiveRegs;
43709467b48Spatrick 
43809467b48Spatrick   if (!isEqual(LISLR, TrackedLR)) {
43909467b48Spatrick     dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
440*d415bd75Srobert               " LIS reported livesets mismatch:\n"
441*d415bd75Srobert            << print(LISLR, *MRI);
44209467b48Spatrick     reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo());
44309467b48Spatrick     return false;
44409467b48Spatrick   }
44509467b48Spatrick 
44609467b48Spatrick   auto LISPressure = getRegPressure(*MRI, LISLR);
44709467b48Spatrick   if (LISPressure != CurPressure) {
448*d415bd75Srobert     dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: "
449*d415bd75Srobert            << print(CurPressure) << "LIS rpt: " << print(LISPressure);
45009467b48Spatrick     return false;
45109467b48Spatrick   }
45209467b48Spatrick   return true;
45309467b48Spatrick }
45409467b48Spatrick 
455*d415bd75Srobert LLVM_DUMP_METHOD
print(const GCNRPTracker::LiveRegSet & LiveRegs,const MachineRegisterInfo & MRI)456*d415bd75Srobert Printable llvm::print(const GCNRPTracker::LiveRegSet &LiveRegs,
45709467b48Spatrick                       const MachineRegisterInfo &MRI) {
458*d415bd75Srobert   return Printable([&LiveRegs, &MRI](raw_ostream &OS) {
45909467b48Spatrick     const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
46009467b48Spatrick     for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
461*d415bd75Srobert       Register Reg = Register::index2VirtReg(I);
46209467b48Spatrick       auto It = LiveRegs.find(Reg);
46309467b48Spatrick       if (It != LiveRegs.end() && It->second.any())
46409467b48Spatrick         OS << ' ' << printVRegOrUnit(Reg, TRI) << ':'
46509467b48Spatrick            << PrintLaneMask(It->second);
46609467b48Spatrick     }
46709467b48Spatrick     OS << '\n';
468*d415bd75Srobert   });
46909467b48Spatrick }
470*d415bd75Srobert 
471*d415bd75Srobert LLVM_DUMP_METHOD
dump() const472*d415bd75Srobert void GCNRegPressure::dump() const { dbgs() << print(*this); }
473*d415bd75Srobert 
47409467b48Spatrick #endif
475