xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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"
150b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterPressure.h"
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric using namespace llvm;
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #define DEBUG_TYPE "machine-scheduler"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric bool llvm::isEqual(const GCNRPTracker::LiveRegSet &S1,
220b57cec5SDimitry Andric                    const GCNRPTracker::LiveRegSet &S2) {
230b57cec5SDimitry Andric   if (S1.size() != S2.size())
240b57cec5SDimitry Andric     return false;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric   for (const auto &P : S1) {
270b57cec5SDimitry Andric     auto I = S2.find(P.first);
280b57cec5SDimitry Andric     if (I == S2.end() || I->second != P.second)
290b57cec5SDimitry Andric       return false;
300b57cec5SDimitry Andric   }
310b57cec5SDimitry Andric   return true;
320b57cec5SDimitry Andric }
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());
810b57cec5SDimitry Andric       Value[Kind] += Sign * MRI.getPressureSets(Reg).getWeight();
820b57cec5SDimitry Andric     }
830b57cec5SDimitry Andric     break;
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   default: llvm_unreachable("Unknown register kind");
860b57cec5SDimitry Andric   }
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric bool GCNRegPressure::less(const GCNSubtarget &ST,
900b57cec5SDimitry Andric                           const GCNRegPressure& O,
910b57cec5SDimitry Andric                           unsigned MaxOccupancy) const {
920b57cec5SDimitry Andric   const auto SGPROcc = std::min(MaxOccupancy,
930b57cec5SDimitry Andric                                 ST.getOccupancyWithNumSGPRs(getSGPRNum()));
94fe6060f1SDimitry Andric   const auto VGPROcc =
95fe6060f1SDimitry Andric     std::min(MaxOccupancy,
96fe6060f1SDimitry Andric              ST.getOccupancyWithNumVGPRs(getVGPRNum(ST.hasGFX90AInsts())));
970b57cec5SDimitry Andric   const auto OtherSGPROcc = std::min(MaxOccupancy,
980b57cec5SDimitry Andric                                 ST.getOccupancyWithNumSGPRs(O.getSGPRNum()));
99fe6060f1SDimitry Andric   const auto OtherVGPROcc =
100fe6060f1SDimitry Andric     std::min(MaxOccupancy,
101fe6060f1SDimitry Andric              ST.getOccupancyWithNumVGPRs(O.getVGPRNum(ST.hasGFX90AInsts())));
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   const auto Occ = std::min(SGPROcc, VGPROcc);
1040b57cec5SDimitry Andric   const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc);
1050b57cec5SDimitry Andric   if (Occ != OtherOcc)
1060b57cec5SDimitry Andric     return Occ > OtherOcc;
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   bool SGPRImportant = SGPROcc < VGPROcc;
1090b57cec5SDimitry Andric   const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   // if both pressures disagree on what is more important compare vgprs
1120b57cec5SDimitry Andric   if (SGPRImportant != OtherSGPRImportant) {
1130b57cec5SDimitry Andric     SGPRImportant = false;
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   // compare large regs pressure
1170b57cec5SDimitry Andric   bool SGPRFirst = SGPRImportant;
1180b57cec5SDimitry Andric   for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) {
1190b57cec5SDimitry Andric     if (SGPRFirst) {
1200b57cec5SDimitry Andric       auto SW = getSGPRTuplesWeight();
1210b57cec5SDimitry Andric       auto OtherSW = O.getSGPRTuplesWeight();
1220b57cec5SDimitry Andric       if (SW != OtherSW)
1230b57cec5SDimitry Andric         return SW < OtherSW;
1240b57cec5SDimitry Andric     } else {
1250b57cec5SDimitry Andric       auto VW = getVGPRTuplesWeight();
1260b57cec5SDimitry Andric       auto OtherVW = O.getVGPRTuplesWeight();
1270b57cec5SDimitry Andric       if (VW != OtherVW)
1280b57cec5SDimitry Andric         return VW < OtherVW;
1290b57cec5SDimitry Andric     }
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric   return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()):
132fe6060f1SDimitry Andric                          (getVGPRNum(ST.hasGFX90AInsts()) <
133fe6060f1SDimitry Andric                           O.getVGPRNum(ST.hasGFX90AInsts()));
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1370b57cec5SDimitry Andric LLVM_DUMP_METHOD
138*bdd1243dSDimitry Andric Printable llvm::print(const GCNRegPressure &RP, const GCNSubtarget *ST) {
139*bdd1243dSDimitry Andric   return Printable([&RP, ST](raw_ostream &OS) {
140*bdd1243dSDimitry Andric     OS << "VGPRs: " << RP.Value[GCNRegPressure::VGPR32] << ' '
141*bdd1243dSDimitry Andric        << "AGPRs: " << RP.getAGPRNum();
142*bdd1243dSDimitry Andric     if (ST)
143*bdd1243dSDimitry Andric       OS << "(O"
144*bdd1243dSDimitry Andric          << ST->getOccupancyWithNumVGPRs(RP.getVGPRNum(ST->hasGFX90AInsts()))
145fe6060f1SDimitry Andric          << ')';
146*bdd1243dSDimitry Andric     OS << ", SGPRs: " << RP.getSGPRNum();
147*bdd1243dSDimitry Andric     if (ST)
148*bdd1243dSDimitry Andric       OS << "(O" << ST->getOccupancyWithNumSGPRs(RP.getSGPRNum()) << ')';
149*bdd1243dSDimitry Andric     OS << ", LVGPR WT: " << RP.getVGPRTuplesWeight()
150*bdd1243dSDimitry Andric        << ", LSGPR WT: " << RP.getSGPRTuplesWeight();
151*bdd1243dSDimitry Andric     if (ST)
152*bdd1243dSDimitry Andric       OS << " -> Occ: " << RP.getOccupancy(*ST);
1530b57cec5SDimitry Andric     OS << '\n';
154*bdd1243dSDimitry Andric   });
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric #endif
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric static LaneBitmask getDefRegMask(const MachineOperand &MO,
1590b57cec5SDimitry Andric                                  const MachineRegisterInfo &MRI) {
160e8d8bef9SDimitry Andric   assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual());
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   // We don't rely on read-undef flag because in case of tentative schedule
1630b57cec5SDimitry Andric   // tracking it isn't set correctly yet. This works correctly however since
1640b57cec5SDimitry Andric   // use mask has been tracked before using LIS.
1650b57cec5SDimitry Andric   return MO.getSubReg() == 0 ?
1660b57cec5SDimitry Andric     MRI.getMaxLaneMaskForVReg(MO.getReg()) :
1670b57cec5SDimitry Andric     MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric static LaneBitmask getUsedRegMask(const MachineOperand &MO,
1710b57cec5SDimitry Andric                                   const MachineRegisterInfo &MRI,
1720b57cec5SDimitry Andric                                   const LiveIntervals &LIS) {
173e8d8bef9SDimitry Andric   assert(MO.isUse() && MO.isReg() && MO.getReg().isVirtual());
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   if (auto SubReg = MO.getSubReg())
1760b57cec5SDimitry Andric     return MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg);
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   auto MaxMask = MRI.getMaxLaneMaskForVReg(MO.getReg());
1795ffd83dbSDimitry Andric   if (SIRegisterInfo::getNumCoveredRegs(MaxMask) > 1) // cannot have subregs
1800b57cec5SDimitry Andric     return MaxMask;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   // For a tentative schedule LIS isn't updated yet but livemask should remain
1830b57cec5SDimitry Andric   // the same on any schedule. Subreg defs can be reordered but they all must
1840b57cec5SDimitry Andric   // dominate uses anyway.
1850b57cec5SDimitry Andric   auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex();
1860b57cec5SDimitry Andric   return getLiveLaneMask(MO.getReg(), SI, LIS, MRI);
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric static SmallVector<RegisterMaskPair, 8>
1900b57cec5SDimitry Andric collectVirtualRegUses(const MachineInstr &MI, const LiveIntervals &LIS,
1910b57cec5SDimitry Andric                       const MachineRegisterInfo &MRI) {
1920b57cec5SDimitry Andric   SmallVector<RegisterMaskPair, 8> Res;
1930b57cec5SDimitry Andric   for (const auto &MO : MI.operands()) {
194e8d8bef9SDimitry Andric     if (!MO.isReg() || !MO.getReg().isVirtual())
1950b57cec5SDimitry Andric       continue;
1960b57cec5SDimitry Andric     if (!MO.isUse() || !MO.readsReg())
1970b57cec5SDimitry Andric       continue;
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric     auto const UsedMask = getUsedRegMask(MO, MRI, LIS);
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric     auto Reg = MO.getReg();
202e8d8bef9SDimitry Andric     auto I = llvm::find_if(
203e8d8bef9SDimitry Andric         Res, [Reg](const RegisterMaskPair &RM) { return RM.RegUnit == Reg; });
2040b57cec5SDimitry Andric     if (I != Res.end())
2050b57cec5SDimitry Andric       I->LaneMask |= UsedMask;
2060b57cec5SDimitry Andric     else
2070b57cec5SDimitry Andric       Res.push_back(RegisterMaskPair(Reg, UsedMask));
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric   return Res;
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric ///////////////////////////////////////////////////////////////////////////////
2130b57cec5SDimitry Andric // GCNRPTracker
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric LaneBitmask llvm::getLiveLaneMask(unsigned Reg,
2160b57cec5SDimitry Andric                                   SlotIndex SI,
2170b57cec5SDimitry Andric                                   const LiveIntervals &LIS,
2180b57cec5SDimitry Andric                                   const MachineRegisterInfo &MRI) {
2190b57cec5SDimitry Andric   LaneBitmask LiveMask;
2200b57cec5SDimitry Andric   const auto &LI = LIS.getInterval(Reg);
2210b57cec5SDimitry Andric   if (LI.hasSubRanges()) {
2220b57cec5SDimitry Andric     for (const auto &S : LI.subranges())
2230b57cec5SDimitry Andric       if (S.liveAt(SI)) {
2240b57cec5SDimitry Andric         LiveMask |= S.LaneMask;
2250b57cec5SDimitry Andric         assert(LiveMask < MRI.getMaxLaneMaskForVReg(Reg) ||
2260b57cec5SDimitry Andric                LiveMask == MRI.getMaxLaneMaskForVReg(Reg));
2270b57cec5SDimitry Andric       }
2280b57cec5SDimitry Andric   } else if (LI.liveAt(SI)) {
2290b57cec5SDimitry Andric     LiveMask = MRI.getMaxLaneMaskForVReg(Reg);
2300b57cec5SDimitry Andric   }
2310b57cec5SDimitry Andric   return LiveMask;
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
2350b57cec5SDimitry Andric                                            const LiveIntervals &LIS,
2360b57cec5SDimitry Andric                                            const MachineRegisterInfo &MRI) {
2370b57cec5SDimitry Andric   GCNRPTracker::LiveRegSet LiveRegs;
2380b57cec5SDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
2398bcb0991SDimitry Andric     auto Reg = Register::index2VirtReg(I);
2400b57cec5SDimitry Andric     if (!LIS.hasInterval(Reg))
2410b57cec5SDimitry Andric       continue;
2420b57cec5SDimitry Andric     auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI);
2430b57cec5SDimitry Andric     if (LiveMask.any())
2440b57cec5SDimitry Andric       LiveRegs[Reg] = LiveMask;
2450b57cec5SDimitry Andric   }
2460b57cec5SDimitry Andric   return LiveRegs;
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric void GCNRPTracker::reset(const MachineInstr &MI,
2500b57cec5SDimitry Andric                          const LiveRegSet *LiveRegsCopy,
2510b57cec5SDimitry Andric                          bool After) {
2520b57cec5SDimitry Andric   const MachineFunction &MF = *MI.getMF();
2530b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
2540b57cec5SDimitry Andric   if (LiveRegsCopy) {
2550b57cec5SDimitry Andric     if (&LiveRegs != LiveRegsCopy)
2560b57cec5SDimitry Andric       LiveRegs = *LiveRegsCopy;
2570b57cec5SDimitry Andric   } else {
2580b57cec5SDimitry Andric     LiveRegs = After ? getLiveRegsAfter(MI, LIS)
2590b57cec5SDimitry Andric                      : getLiveRegsBefore(MI, LIS);
2600b57cec5SDimitry Andric   }
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs);
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric void GCNUpwardRPTracker::reset(const MachineInstr &MI,
2660b57cec5SDimitry Andric                                const LiveRegSet *LiveRegsCopy) {
2670b57cec5SDimitry Andric   GCNRPTracker::reset(MI, LiveRegsCopy, true);
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric void GCNUpwardRPTracker::recede(const MachineInstr &MI) {
2710b57cec5SDimitry Andric   assert(MRI && "call reset first");
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric   LastTrackedMI = &MI;
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   if (MI.isDebugInstr())
2760b57cec5SDimitry Andric     return;
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   auto const RegUses = collectVirtualRegUses(MI, LIS, *MRI);
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   // calc pressure at the MI (defs + uses)
2810b57cec5SDimitry Andric   auto AtMIPressure = CurPressure;
2820b57cec5SDimitry Andric   for (const auto &U : RegUses) {
2830b57cec5SDimitry Andric     auto LiveMask = LiveRegs[U.RegUnit];
2840b57cec5SDimitry Andric     AtMIPressure.inc(U.RegUnit, LiveMask, LiveMask | U.LaneMask, *MRI);
2850b57cec5SDimitry Andric   }
2860b57cec5SDimitry Andric   // update max pressure
2870b57cec5SDimitry Andric   MaxPressure = max(AtMIPressure, MaxPressure);
2880b57cec5SDimitry Andric 
2895ffd83dbSDimitry Andric   for (const auto &MO : MI.operands()) {
290e8d8bef9SDimitry Andric     if (!MO.isReg() || !MO.isDef() || !MO.getReg().isVirtual() || MO.isDead())
2910b57cec5SDimitry Andric       continue;
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric     auto Reg = MO.getReg();
2940b57cec5SDimitry Andric     auto I = LiveRegs.find(Reg);
2950b57cec5SDimitry Andric     if (I == LiveRegs.end())
2960b57cec5SDimitry Andric       continue;
2970b57cec5SDimitry Andric     auto &LiveMask = I->second;
2980b57cec5SDimitry Andric     auto PrevMask = LiveMask;
2990b57cec5SDimitry Andric     LiveMask &= ~getDefRegMask(MO, *MRI);
3000b57cec5SDimitry Andric     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
3010b57cec5SDimitry Andric     if (LiveMask.none())
3020b57cec5SDimitry Andric       LiveRegs.erase(I);
3030b57cec5SDimitry Andric   }
3040b57cec5SDimitry Andric   for (const auto &U : RegUses) {
3050b57cec5SDimitry Andric     auto &LiveMask = LiveRegs[U.RegUnit];
3060b57cec5SDimitry Andric     auto PrevMask = LiveMask;
3070b57cec5SDimitry Andric     LiveMask |= U.LaneMask;
3080b57cec5SDimitry Andric     CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI);
3090b57cec5SDimitry Andric   }
3100b57cec5SDimitry Andric   assert(CurPressure == getRegPressure(*MRI, LiveRegs));
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric bool GCNDownwardRPTracker::reset(const MachineInstr &MI,
3140b57cec5SDimitry Andric                                  const LiveRegSet *LiveRegsCopy) {
3150b57cec5SDimitry Andric   MRI = &MI.getParent()->getParent()->getRegInfo();
3160b57cec5SDimitry Andric   LastTrackedMI = nullptr;
3170b57cec5SDimitry Andric   MBBEnd = MI.getParent()->end();
3180b57cec5SDimitry Andric   NextMI = &MI;
3190b57cec5SDimitry Andric   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
3200b57cec5SDimitry Andric   if (NextMI == MBBEnd)
3210b57cec5SDimitry Andric     return false;
3220b57cec5SDimitry Andric   GCNRPTracker::reset(*NextMI, LiveRegsCopy, false);
3230b57cec5SDimitry Andric   return true;
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric bool GCNDownwardRPTracker::advanceBeforeNext() {
3270b57cec5SDimitry Andric   assert(MRI && "call reset first");
328*bdd1243dSDimitry Andric   if (!LastTrackedMI)
329*bdd1243dSDimitry Andric     return NextMI == MBBEnd;
3300b57cec5SDimitry Andric 
331*bdd1243dSDimitry Andric   assert(NextMI == MBBEnd || !NextMI->isDebugInstr());
3320b57cec5SDimitry Andric 
333*bdd1243dSDimitry Andric   SlotIndex SI = NextMI == MBBEnd
334*bdd1243dSDimitry Andric                      ? LIS.getInstructionIndex(*LastTrackedMI).getDeadSlot()
335*bdd1243dSDimitry Andric                      : LIS.getInstructionIndex(*NextMI).getBaseIndex();
3360b57cec5SDimitry Andric   assert(SI.isValid());
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   // Remove dead registers or mask bits.
3390b57cec5SDimitry Andric   for (auto &It : LiveRegs) {
3400b57cec5SDimitry Andric     const LiveInterval &LI = LIS.getInterval(It.first);
3410b57cec5SDimitry Andric     if (LI.hasSubRanges()) {
3420b57cec5SDimitry Andric       for (const auto &S : LI.subranges()) {
3430b57cec5SDimitry Andric         if (!S.liveAt(SI)) {
3440b57cec5SDimitry Andric           auto PrevMask = It.second;
3450b57cec5SDimitry Andric           It.second &= ~S.LaneMask;
3460b57cec5SDimitry Andric           CurPressure.inc(It.first, PrevMask, It.second, *MRI);
3470b57cec5SDimitry Andric         }
3480b57cec5SDimitry Andric       }
3490b57cec5SDimitry Andric     } else if (!LI.liveAt(SI)) {
3500b57cec5SDimitry Andric       auto PrevMask = It.second;
3510b57cec5SDimitry Andric       It.second = LaneBitmask::getNone();
3520b57cec5SDimitry Andric       CurPressure.inc(It.first, PrevMask, It.second, *MRI);
3530b57cec5SDimitry Andric     }
3540b57cec5SDimitry Andric     if (It.second.none())
3550b57cec5SDimitry Andric       LiveRegs.erase(It.first);
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   MaxPressure = max(MaxPressure, CurPressure);
3590b57cec5SDimitry Andric 
360*bdd1243dSDimitry Andric   LastTrackedMI = nullptr;
361*bdd1243dSDimitry Andric 
362*bdd1243dSDimitry Andric   return NextMI == MBBEnd;
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric void GCNDownwardRPTracker::advanceToNext() {
3660b57cec5SDimitry Andric   LastTrackedMI = &*NextMI++;
367fe6060f1SDimitry Andric   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   // Add new registers or mask bits.
3705ffd83dbSDimitry Andric   for (const auto &MO : LastTrackedMI->operands()) {
3715ffd83dbSDimitry Andric     if (!MO.isReg() || !MO.isDef())
3720b57cec5SDimitry Andric       continue;
3738bcb0991SDimitry Andric     Register Reg = MO.getReg();
374e8d8bef9SDimitry Andric     if (!Reg.isVirtual())
3750b57cec5SDimitry Andric       continue;
3760b57cec5SDimitry Andric     auto &LiveMask = LiveRegs[Reg];
3770b57cec5SDimitry Andric     auto PrevMask = LiveMask;
3780b57cec5SDimitry Andric     LiveMask |= getDefRegMask(MO, *MRI);
3790b57cec5SDimitry Andric     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
3800b57cec5SDimitry Andric   }
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric   MaxPressure = max(MaxPressure, CurPressure);
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance() {
386*bdd1243dSDimitry Andric   if (NextMI == MBBEnd)
3870b57cec5SDimitry Andric     return false;
388*bdd1243dSDimitry Andric   advanceBeforeNext();
3890b57cec5SDimitry Andric   advanceToNext();
3900b57cec5SDimitry Andric   return true;
3910b57cec5SDimitry Andric }
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) {
3940b57cec5SDimitry Andric   while (NextMI != End)
3950b57cec5SDimitry Andric     if (!advance()) return false;
3960b57cec5SDimitry Andric   return true;
3970b57cec5SDimitry Andric }
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin,
4000b57cec5SDimitry Andric                                    MachineBasicBlock::const_iterator End,
4010b57cec5SDimitry Andric                                    const LiveRegSet *LiveRegsCopy) {
4020b57cec5SDimitry Andric   reset(*Begin, LiveRegsCopy);
4030b57cec5SDimitry Andric   return advance(End);
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4070b57cec5SDimitry Andric LLVM_DUMP_METHOD
408*bdd1243dSDimitry Andric Printable llvm::reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
4090b57cec5SDimitry Andric                                const GCNRPTracker::LiveRegSet &TrackedLR,
4100b57cec5SDimitry Andric                                const TargetRegisterInfo *TRI) {
411*bdd1243dSDimitry Andric   return Printable([&LISLR, &TrackedLR, TRI](raw_ostream &OS) {
4120b57cec5SDimitry Andric     for (auto const &P : TrackedLR) {
4130b57cec5SDimitry Andric       auto I = LISLR.find(P.first);
4140b57cec5SDimitry Andric       if (I == LISLR.end()) {
415*bdd1243dSDimitry Andric         OS << "  " << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
4160b57cec5SDimitry Andric            << " isn't found in LIS reported set\n";
417*bdd1243dSDimitry Andric       } else if (I->second != P.second) {
418*bdd1243dSDimitry Andric         OS << "  " << printReg(P.first, TRI)
419*bdd1243dSDimitry Andric            << " masks doesn't match: LIS reported " << PrintLaneMask(I->second)
420*bdd1243dSDimitry Andric            << ", tracked " << PrintLaneMask(P.second) << '\n';
4210b57cec5SDimitry Andric       }
4220b57cec5SDimitry Andric     }
4230b57cec5SDimitry Andric     for (auto const &P : LISLR) {
4240b57cec5SDimitry Andric       auto I = TrackedLR.find(P.first);
4250b57cec5SDimitry Andric       if (I == TrackedLR.end()) {
426*bdd1243dSDimitry Andric         OS << "  " << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
4270b57cec5SDimitry Andric            << " isn't found in tracked set\n";
4280b57cec5SDimitry Andric       }
4290b57cec5SDimitry Andric     }
430*bdd1243dSDimitry Andric   });
4310b57cec5SDimitry Andric }
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric bool GCNUpwardRPTracker::isValid() const {
4340b57cec5SDimitry Andric   const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
4350b57cec5SDimitry Andric   const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
4360b57cec5SDimitry Andric   const auto &TrackedLR = LiveRegs;
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   if (!isEqual(LISLR, TrackedLR)) {
4390b57cec5SDimitry Andric     dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
440*bdd1243dSDimitry Andric               " LIS reported livesets mismatch:\n"
441*bdd1243dSDimitry Andric            << print(LISLR, *MRI);
4420b57cec5SDimitry Andric     reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo());
4430b57cec5SDimitry Andric     return false;
4440b57cec5SDimitry Andric   }
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   auto LISPressure = getRegPressure(*MRI, LISLR);
4470b57cec5SDimitry Andric   if (LISPressure != CurPressure) {
448*bdd1243dSDimitry Andric     dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: "
449*bdd1243dSDimitry Andric            << print(CurPressure) << "LIS rpt: " << print(LISPressure);
4500b57cec5SDimitry Andric     return false;
4510b57cec5SDimitry Andric   }
4520b57cec5SDimitry Andric   return true;
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
455*bdd1243dSDimitry Andric LLVM_DUMP_METHOD
456*bdd1243dSDimitry Andric Printable llvm::print(const GCNRPTracker::LiveRegSet &LiveRegs,
4570b57cec5SDimitry Andric                       const MachineRegisterInfo &MRI) {
458*bdd1243dSDimitry Andric   return Printable([&LiveRegs, &MRI](raw_ostream &OS) {
4590b57cec5SDimitry Andric     const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
4600b57cec5SDimitry Andric     for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
46104eeddc0SDimitry Andric       Register Reg = Register::index2VirtReg(I);
4620b57cec5SDimitry Andric       auto It = LiveRegs.find(Reg);
4630b57cec5SDimitry Andric       if (It != LiveRegs.end() && It->second.any())
4640b57cec5SDimitry Andric         OS << ' ' << printVRegOrUnit(Reg, TRI) << ':'
4650b57cec5SDimitry Andric            << PrintLaneMask(It->second);
4660b57cec5SDimitry Andric     }
4670b57cec5SDimitry Andric     OS << '\n';
468*bdd1243dSDimitry Andric   });
4690b57cec5SDimitry Andric }
470*bdd1243dSDimitry Andric 
471*bdd1243dSDimitry Andric LLVM_DUMP_METHOD
472*bdd1243dSDimitry Andric void GCNRegPressure::dump() const { dbgs() << print(*this); }
473*bdd1243dSDimitry Andric 
4740b57cec5SDimitry Andric #endif
475