xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
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 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
220b57cec5SDimitry Andric LLVM_DUMP_METHOD
230b57cec5SDimitry Andric void llvm::printLivesAt(SlotIndex SI,
240b57cec5SDimitry Andric                         const LiveIntervals &LIS,
250b57cec5SDimitry Andric                         const MachineRegisterInfo &MRI) {
260b57cec5SDimitry Andric   dbgs() << "Live regs at " << SI << ": "
270b57cec5SDimitry Andric          << *LIS.getInstructionFromIndex(SI);
280b57cec5SDimitry Andric   unsigned Num = 0;
290b57cec5SDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
30*04eeddc0SDimitry Andric     const Register Reg = Register::index2VirtReg(I);
310b57cec5SDimitry Andric     if (!LIS.hasInterval(Reg))
320b57cec5SDimitry Andric       continue;
330b57cec5SDimitry Andric     const auto &LI = LIS.getInterval(Reg);
340b57cec5SDimitry Andric     if (LI.hasSubRanges()) {
350b57cec5SDimitry Andric       bool firstTime = true;
360b57cec5SDimitry Andric       for (const auto &S : LI.subranges()) {
370b57cec5SDimitry Andric         if (!S.liveAt(SI)) continue;
380b57cec5SDimitry Andric         if (firstTime) {
390b57cec5SDimitry Andric           dbgs() << "  " << printReg(Reg, MRI.getTargetRegisterInfo())
400b57cec5SDimitry Andric                  << '\n';
410b57cec5SDimitry Andric           firstTime = false;
420b57cec5SDimitry Andric         }
430b57cec5SDimitry Andric         dbgs() << "  " << S << '\n';
440b57cec5SDimitry Andric         ++Num;
450b57cec5SDimitry Andric       }
460b57cec5SDimitry Andric     } else if (LI.liveAt(SI)) {
470b57cec5SDimitry Andric       dbgs() << "  " << LI << '\n';
480b57cec5SDimitry Andric       ++Num;
490b57cec5SDimitry Andric     }
500b57cec5SDimitry Andric   }
510b57cec5SDimitry Andric   if (!Num) dbgs() << "  <none>\n";
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric #endif
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric bool llvm::isEqual(const GCNRPTracker::LiveRegSet &S1,
560b57cec5SDimitry Andric                    const GCNRPTracker::LiveRegSet &S2) {
570b57cec5SDimitry Andric   if (S1.size() != S2.size())
580b57cec5SDimitry Andric     return false;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   for (const auto &P : S1) {
610b57cec5SDimitry Andric     auto I = S2.find(P.first);
620b57cec5SDimitry Andric     if (I == S2.end() || I->second != P.second)
630b57cec5SDimitry Andric       return false;
640b57cec5SDimitry Andric   }
650b57cec5SDimitry Andric   return true;
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric ///////////////////////////////////////////////////////////////////////////////
700b57cec5SDimitry Andric // GCNRegPressure
710b57cec5SDimitry Andric 
72e8d8bef9SDimitry Andric unsigned GCNRegPressure::getRegKind(Register Reg,
730b57cec5SDimitry Andric                                     const MachineRegisterInfo &MRI) {
74e8d8bef9SDimitry Andric   assert(Reg.isVirtual());
750b57cec5SDimitry Andric   const auto RC = MRI.getRegClass(Reg);
760b57cec5SDimitry Andric   auto STI = static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo());
774824e7fdSDimitry Andric   return STI->isSGPRClass(RC)
784824e7fdSDimitry Andric              ? (STI->getRegSizeInBits(*RC) == 32 ? SGPR32 : SGPR_TUPLE)
794824e7fdSDimitry Andric          : STI->isAGPRClass(RC)
804824e7fdSDimitry Andric              ? (STI->getRegSizeInBits(*RC) == 32 ? AGPR32 : AGPR_TUPLE)
814824e7fdSDimitry Andric              : (STI->getRegSizeInBits(*RC) == 32 ? VGPR32 : VGPR_TUPLE);
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric void GCNRegPressure::inc(unsigned Reg,
850b57cec5SDimitry Andric                          LaneBitmask PrevMask,
860b57cec5SDimitry Andric                          LaneBitmask NewMask,
870b57cec5SDimitry Andric                          const MachineRegisterInfo &MRI) {
885ffd83dbSDimitry Andric   if (SIRegisterInfo::getNumCoveredRegs(NewMask) ==
895ffd83dbSDimitry Andric       SIRegisterInfo::getNumCoveredRegs(PrevMask))
900b57cec5SDimitry Andric     return;
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   int Sign = 1;
930b57cec5SDimitry Andric   if (NewMask < PrevMask) {
940b57cec5SDimitry Andric     std::swap(NewMask, PrevMask);
950b57cec5SDimitry Andric     Sign = -1;
960b57cec5SDimitry Andric   }
975ffd83dbSDimitry Andric 
980b57cec5SDimitry Andric   switch (auto Kind = getRegKind(Reg, MRI)) {
990b57cec5SDimitry Andric   case SGPR32:
1000b57cec5SDimitry Andric   case VGPR32:
1010b57cec5SDimitry Andric   case AGPR32:
1020b57cec5SDimitry Andric     Value[Kind] += Sign;
1030b57cec5SDimitry Andric     break;
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   case SGPR_TUPLE:
1060b57cec5SDimitry Andric   case VGPR_TUPLE:
1070b57cec5SDimitry Andric   case AGPR_TUPLE:
1080b57cec5SDimitry Andric     assert(PrevMask < NewMask);
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric     Value[Kind == SGPR_TUPLE ? SGPR32 : Kind == AGPR_TUPLE ? AGPR32 : VGPR32] +=
1115ffd83dbSDimitry Andric       Sign * SIRegisterInfo::getNumCoveredRegs(~PrevMask & NewMask);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric     if (PrevMask.none()) {
1140b57cec5SDimitry Andric       assert(NewMask.any());
1150b57cec5SDimitry Andric       Value[Kind] += Sign * MRI.getPressureSets(Reg).getWeight();
1160b57cec5SDimitry Andric     }
1170b57cec5SDimitry Andric     break;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   default: llvm_unreachable("Unknown register kind");
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric bool GCNRegPressure::less(const GCNSubtarget &ST,
1240b57cec5SDimitry Andric                           const GCNRegPressure& O,
1250b57cec5SDimitry Andric                           unsigned MaxOccupancy) const {
1260b57cec5SDimitry Andric   const auto SGPROcc = std::min(MaxOccupancy,
1270b57cec5SDimitry Andric                                 ST.getOccupancyWithNumSGPRs(getSGPRNum()));
128fe6060f1SDimitry Andric   const auto VGPROcc =
129fe6060f1SDimitry Andric     std::min(MaxOccupancy,
130fe6060f1SDimitry Andric              ST.getOccupancyWithNumVGPRs(getVGPRNum(ST.hasGFX90AInsts())));
1310b57cec5SDimitry Andric   const auto OtherSGPROcc = std::min(MaxOccupancy,
1320b57cec5SDimitry Andric                                 ST.getOccupancyWithNumSGPRs(O.getSGPRNum()));
133fe6060f1SDimitry Andric   const auto OtherVGPROcc =
134fe6060f1SDimitry Andric     std::min(MaxOccupancy,
135fe6060f1SDimitry Andric              ST.getOccupancyWithNumVGPRs(O.getVGPRNum(ST.hasGFX90AInsts())));
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   const auto Occ = std::min(SGPROcc, VGPROcc);
1380b57cec5SDimitry Andric   const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc);
1390b57cec5SDimitry Andric   if (Occ != OtherOcc)
1400b57cec5SDimitry Andric     return Occ > OtherOcc;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   bool SGPRImportant = SGPROcc < VGPROcc;
1430b57cec5SDimitry Andric   const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   // if both pressures disagree on what is more important compare vgprs
1460b57cec5SDimitry Andric   if (SGPRImportant != OtherSGPRImportant) {
1470b57cec5SDimitry Andric     SGPRImportant = false;
1480b57cec5SDimitry Andric   }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   // compare large regs pressure
1510b57cec5SDimitry Andric   bool SGPRFirst = SGPRImportant;
1520b57cec5SDimitry Andric   for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) {
1530b57cec5SDimitry Andric     if (SGPRFirst) {
1540b57cec5SDimitry Andric       auto SW = getSGPRTuplesWeight();
1550b57cec5SDimitry Andric       auto OtherSW = O.getSGPRTuplesWeight();
1560b57cec5SDimitry Andric       if (SW != OtherSW)
1570b57cec5SDimitry Andric         return SW < OtherSW;
1580b57cec5SDimitry Andric     } else {
1590b57cec5SDimitry Andric       auto VW = getVGPRTuplesWeight();
1600b57cec5SDimitry Andric       auto OtherVW = O.getVGPRTuplesWeight();
1610b57cec5SDimitry Andric       if (VW != OtherVW)
1620b57cec5SDimitry Andric         return VW < OtherVW;
1630b57cec5SDimitry Andric     }
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric   return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()):
166fe6060f1SDimitry Andric                          (getVGPRNum(ST.hasGFX90AInsts()) <
167fe6060f1SDimitry Andric                           O.getVGPRNum(ST.hasGFX90AInsts()));
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1710b57cec5SDimitry Andric LLVM_DUMP_METHOD
1720b57cec5SDimitry Andric void GCNRegPressure::print(raw_ostream &OS, const GCNSubtarget *ST) const {
1738bcb0991SDimitry Andric   OS << "VGPRs: " << Value[VGPR32] << ' ';
1748bcb0991SDimitry Andric   OS << "AGPRs: " << Value[AGPR32];
175fe6060f1SDimitry Andric   if (ST) OS << "(O"
176fe6060f1SDimitry Andric              << ST->getOccupancyWithNumVGPRs(getVGPRNum(ST->hasGFX90AInsts()))
177fe6060f1SDimitry Andric              << ')';
1780b57cec5SDimitry Andric   OS << ", SGPRs: " << getSGPRNum();
1790b57cec5SDimitry Andric   if (ST) OS << "(O" << ST->getOccupancyWithNumSGPRs(getSGPRNum()) << ')';
1800b57cec5SDimitry Andric   OS << ", LVGPR WT: " << getVGPRTuplesWeight()
1810b57cec5SDimitry Andric      << ", LSGPR WT: " << getSGPRTuplesWeight();
1820b57cec5SDimitry Andric   if (ST) OS << " -> Occ: " << getOccupancy(*ST);
1830b57cec5SDimitry Andric   OS << '\n';
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric #endif
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric static LaneBitmask getDefRegMask(const MachineOperand &MO,
1880b57cec5SDimitry Andric                                  const MachineRegisterInfo &MRI) {
189e8d8bef9SDimitry Andric   assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual());
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   // We don't rely on read-undef flag because in case of tentative schedule
1920b57cec5SDimitry Andric   // tracking it isn't set correctly yet. This works correctly however since
1930b57cec5SDimitry Andric   // use mask has been tracked before using LIS.
1940b57cec5SDimitry Andric   return MO.getSubReg() == 0 ?
1950b57cec5SDimitry Andric     MRI.getMaxLaneMaskForVReg(MO.getReg()) :
1960b57cec5SDimitry Andric     MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric static LaneBitmask getUsedRegMask(const MachineOperand &MO,
2000b57cec5SDimitry Andric                                   const MachineRegisterInfo &MRI,
2010b57cec5SDimitry Andric                                   const LiveIntervals &LIS) {
202e8d8bef9SDimitry Andric   assert(MO.isUse() && MO.isReg() && MO.getReg().isVirtual());
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   if (auto SubReg = MO.getSubReg())
2050b57cec5SDimitry Andric     return MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg);
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   auto MaxMask = MRI.getMaxLaneMaskForVReg(MO.getReg());
2085ffd83dbSDimitry Andric   if (SIRegisterInfo::getNumCoveredRegs(MaxMask) > 1) // cannot have subregs
2090b57cec5SDimitry Andric     return MaxMask;
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   // For a tentative schedule LIS isn't updated yet but livemask should remain
2120b57cec5SDimitry Andric   // the same on any schedule. Subreg defs can be reordered but they all must
2130b57cec5SDimitry Andric   // dominate uses anyway.
2140b57cec5SDimitry Andric   auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex();
2150b57cec5SDimitry Andric   return getLiveLaneMask(MO.getReg(), SI, LIS, MRI);
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric static SmallVector<RegisterMaskPair, 8>
2190b57cec5SDimitry Andric collectVirtualRegUses(const MachineInstr &MI, const LiveIntervals &LIS,
2200b57cec5SDimitry Andric                       const MachineRegisterInfo &MRI) {
2210b57cec5SDimitry Andric   SmallVector<RegisterMaskPair, 8> Res;
2220b57cec5SDimitry Andric   for (const auto &MO : MI.operands()) {
223e8d8bef9SDimitry Andric     if (!MO.isReg() || !MO.getReg().isVirtual())
2240b57cec5SDimitry Andric       continue;
2250b57cec5SDimitry Andric     if (!MO.isUse() || !MO.readsReg())
2260b57cec5SDimitry Andric       continue;
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric     auto const UsedMask = getUsedRegMask(MO, MRI, LIS);
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric     auto Reg = MO.getReg();
231e8d8bef9SDimitry Andric     auto I = llvm::find_if(
232e8d8bef9SDimitry Andric         Res, [Reg](const RegisterMaskPair &RM) { return RM.RegUnit == Reg; });
2330b57cec5SDimitry Andric     if (I != Res.end())
2340b57cec5SDimitry Andric       I->LaneMask |= UsedMask;
2350b57cec5SDimitry Andric     else
2360b57cec5SDimitry Andric       Res.push_back(RegisterMaskPair(Reg, UsedMask));
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric   return Res;
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric ///////////////////////////////////////////////////////////////////////////////
2420b57cec5SDimitry Andric // GCNRPTracker
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric LaneBitmask llvm::getLiveLaneMask(unsigned Reg,
2450b57cec5SDimitry Andric                                   SlotIndex SI,
2460b57cec5SDimitry Andric                                   const LiveIntervals &LIS,
2470b57cec5SDimitry Andric                                   const MachineRegisterInfo &MRI) {
2480b57cec5SDimitry Andric   LaneBitmask LiveMask;
2490b57cec5SDimitry Andric   const auto &LI = LIS.getInterval(Reg);
2500b57cec5SDimitry Andric   if (LI.hasSubRanges()) {
2510b57cec5SDimitry Andric     for (const auto &S : LI.subranges())
2520b57cec5SDimitry Andric       if (S.liveAt(SI)) {
2530b57cec5SDimitry Andric         LiveMask |= S.LaneMask;
2540b57cec5SDimitry Andric         assert(LiveMask < MRI.getMaxLaneMaskForVReg(Reg) ||
2550b57cec5SDimitry Andric                LiveMask == MRI.getMaxLaneMaskForVReg(Reg));
2560b57cec5SDimitry Andric       }
2570b57cec5SDimitry Andric   } else if (LI.liveAt(SI)) {
2580b57cec5SDimitry Andric     LiveMask = MRI.getMaxLaneMaskForVReg(Reg);
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric   return LiveMask;
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
2640b57cec5SDimitry Andric                                            const LiveIntervals &LIS,
2650b57cec5SDimitry Andric                                            const MachineRegisterInfo &MRI) {
2660b57cec5SDimitry Andric   GCNRPTracker::LiveRegSet LiveRegs;
2670b57cec5SDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
2688bcb0991SDimitry Andric     auto Reg = Register::index2VirtReg(I);
2690b57cec5SDimitry Andric     if (!LIS.hasInterval(Reg))
2700b57cec5SDimitry Andric       continue;
2710b57cec5SDimitry Andric     auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI);
2720b57cec5SDimitry Andric     if (LiveMask.any())
2730b57cec5SDimitry Andric       LiveRegs[Reg] = LiveMask;
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric   return LiveRegs;
2760b57cec5SDimitry Andric }
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric void GCNRPTracker::reset(const MachineInstr &MI,
2790b57cec5SDimitry Andric                          const LiveRegSet *LiveRegsCopy,
2800b57cec5SDimitry Andric                          bool After) {
2810b57cec5SDimitry Andric   const MachineFunction &MF = *MI.getMF();
2820b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
2830b57cec5SDimitry Andric   if (LiveRegsCopy) {
2840b57cec5SDimitry Andric     if (&LiveRegs != LiveRegsCopy)
2850b57cec5SDimitry Andric       LiveRegs = *LiveRegsCopy;
2860b57cec5SDimitry Andric   } else {
2870b57cec5SDimitry Andric     LiveRegs = After ? getLiveRegsAfter(MI, LIS)
2880b57cec5SDimitry Andric                      : getLiveRegsBefore(MI, LIS);
2890b57cec5SDimitry Andric   }
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs);
2920b57cec5SDimitry Andric }
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric void GCNUpwardRPTracker::reset(const MachineInstr &MI,
2950b57cec5SDimitry Andric                                const LiveRegSet *LiveRegsCopy) {
2960b57cec5SDimitry Andric   GCNRPTracker::reset(MI, LiveRegsCopy, true);
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric void GCNUpwardRPTracker::recede(const MachineInstr &MI) {
3000b57cec5SDimitry Andric   assert(MRI && "call reset first");
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   LastTrackedMI = &MI;
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   if (MI.isDebugInstr())
3050b57cec5SDimitry Andric     return;
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   auto const RegUses = collectVirtualRegUses(MI, LIS, *MRI);
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   // calc pressure at the MI (defs + uses)
3100b57cec5SDimitry Andric   auto AtMIPressure = CurPressure;
3110b57cec5SDimitry Andric   for (const auto &U : RegUses) {
3120b57cec5SDimitry Andric     auto LiveMask = LiveRegs[U.RegUnit];
3130b57cec5SDimitry Andric     AtMIPressure.inc(U.RegUnit, LiveMask, LiveMask | U.LaneMask, *MRI);
3140b57cec5SDimitry Andric   }
3150b57cec5SDimitry Andric   // update max pressure
3160b57cec5SDimitry Andric   MaxPressure = max(AtMIPressure, MaxPressure);
3170b57cec5SDimitry Andric 
3185ffd83dbSDimitry Andric   for (const auto &MO : MI.operands()) {
319e8d8bef9SDimitry Andric     if (!MO.isReg() || !MO.isDef() || !MO.getReg().isVirtual() || MO.isDead())
3200b57cec5SDimitry Andric       continue;
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric     auto Reg = MO.getReg();
3230b57cec5SDimitry Andric     auto I = LiveRegs.find(Reg);
3240b57cec5SDimitry Andric     if (I == LiveRegs.end())
3250b57cec5SDimitry Andric       continue;
3260b57cec5SDimitry Andric     auto &LiveMask = I->second;
3270b57cec5SDimitry Andric     auto PrevMask = LiveMask;
3280b57cec5SDimitry Andric     LiveMask &= ~getDefRegMask(MO, *MRI);
3290b57cec5SDimitry Andric     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
3300b57cec5SDimitry Andric     if (LiveMask.none())
3310b57cec5SDimitry Andric       LiveRegs.erase(I);
3320b57cec5SDimitry Andric   }
3330b57cec5SDimitry Andric   for (const auto &U : RegUses) {
3340b57cec5SDimitry Andric     auto &LiveMask = LiveRegs[U.RegUnit];
3350b57cec5SDimitry Andric     auto PrevMask = LiveMask;
3360b57cec5SDimitry Andric     LiveMask |= U.LaneMask;
3370b57cec5SDimitry Andric     CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI);
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric   assert(CurPressure == getRegPressure(*MRI, LiveRegs));
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric bool GCNDownwardRPTracker::reset(const MachineInstr &MI,
3430b57cec5SDimitry Andric                                  const LiveRegSet *LiveRegsCopy) {
3440b57cec5SDimitry Andric   MRI = &MI.getParent()->getParent()->getRegInfo();
3450b57cec5SDimitry Andric   LastTrackedMI = nullptr;
3460b57cec5SDimitry Andric   MBBEnd = MI.getParent()->end();
3470b57cec5SDimitry Andric   NextMI = &MI;
3480b57cec5SDimitry Andric   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
3490b57cec5SDimitry Andric   if (NextMI == MBBEnd)
3500b57cec5SDimitry Andric     return false;
3510b57cec5SDimitry Andric   GCNRPTracker::reset(*NextMI, LiveRegsCopy, false);
3520b57cec5SDimitry Andric   return true;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric bool GCNDownwardRPTracker::advanceBeforeNext() {
3560b57cec5SDimitry Andric   assert(MRI && "call reset first");
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
3590b57cec5SDimitry Andric   if (NextMI == MBBEnd)
3600b57cec5SDimitry Andric     return false;
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   SlotIndex SI = LIS.getInstructionIndex(*NextMI).getBaseIndex();
3630b57cec5SDimitry Andric   assert(SI.isValid());
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   // Remove dead registers or mask bits.
3660b57cec5SDimitry Andric   for (auto &It : LiveRegs) {
3670b57cec5SDimitry Andric     const LiveInterval &LI = LIS.getInterval(It.first);
3680b57cec5SDimitry Andric     if (LI.hasSubRanges()) {
3690b57cec5SDimitry Andric       for (const auto &S : LI.subranges()) {
3700b57cec5SDimitry Andric         if (!S.liveAt(SI)) {
3710b57cec5SDimitry Andric           auto PrevMask = It.second;
3720b57cec5SDimitry Andric           It.second &= ~S.LaneMask;
3730b57cec5SDimitry Andric           CurPressure.inc(It.first, PrevMask, It.second, *MRI);
3740b57cec5SDimitry Andric         }
3750b57cec5SDimitry Andric       }
3760b57cec5SDimitry Andric     } else if (!LI.liveAt(SI)) {
3770b57cec5SDimitry Andric       auto PrevMask = It.second;
3780b57cec5SDimitry Andric       It.second = LaneBitmask::getNone();
3790b57cec5SDimitry Andric       CurPressure.inc(It.first, PrevMask, It.second, *MRI);
3800b57cec5SDimitry Andric     }
3810b57cec5SDimitry Andric     if (It.second.none())
3820b57cec5SDimitry Andric       LiveRegs.erase(It.first);
3830b57cec5SDimitry Andric   }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric   MaxPressure = max(MaxPressure, CurPressure);
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   return true;
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric void GCNDownwardRPTracker::advanceToNext() {
3910b57cec5SDimitry Andric   LastTrackedMI = &*NextMI++;
392fe6060f1SDimitry Andric   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   // Add new registers or mask bits.
3955ffd83dbSDimitry Andric   for (const auto &MO : LastTrackedMI->operands()) {
3965ffd83dbSDimitry Andric     if (!MO.isReg() || !MO.isDef())
3970b57cec5SDimitry Andric       continue;
3988bcb0991SDimitry Andric     Register Reg = MO.getReg();
399e8d8bef9SDimitry Andric     if (!Reg.isVirtual())
4000b57cec5SDimitry Andric       continue;
4010b57cec5SDimitry Andric     auto &LiveMask = LiveRegs[Reg];
4020b57cec5SDimitry Andric     auto PrevMask = LiveMask;
4030b57cec5SDimitry Andric     LiveMask |= getDefRegMask(MO, *MRI);
4040b57cec5SDimitry Andric     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
4050b57cec5SDimitry Andric   }
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   MaxPressure = max(MaxPressure, CurPressure);
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance() {
4110b57cec5SDimitry Andric   // If we have just called reset live set is actual.
4120b57cec5SDimitry Andric   if ((NextMI == MBBEnd) || (LastTrackedMI && !advanceBeforeNext()))
4130b57cec5SDimitry Andric     return false;
4140b57cec5SDimitry Andric   advanceToNext();
4150b57cec5SDimitry Andric   return true;
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) {
4190b57cec5SDimitry Andric   while (NextMI != End)
4200b57cec5SDimitry Andric     if (!advance()) return false;
4210b57cec5SDimitry Andric   return true;
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin,
4250b57cec5SDimitry Andric                                    MachineBasicBlock::const_iterator End,
4260b57cec5SDimitry Andric                                    const LiveRegSet *LiveRegsCopy) {
4270b57cec5SDimitry Andric   reset(*Begin, LiveRegsCopy);
4280b57cec5SDimitry Andric   return advance(End);
4290b57cec5SDimitry Andric }
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4320b57cec5SDimitry Andric LLVM_DUMP_METHOD
4330b57cec5SDimitry Andric static void reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
4340b57cec5SDimitry Andric                            const GCNRPTracker::LiveRegSet &TrackedLR,
4350b57cec5SDimitry Andric                            const TargetRegisterInfo *TRI) {
4360b57cec5SDimitry Andric   for (auto const &P : TrackedLR) {
4370b57cec5SDimitry Andric     auto I = LISLR.find(P.first);
4380b57cec5SDimitry Andric     if (I == LISLR.end()) {
4390b57cec5SDimitry Andric       dbgs() << "  " << printReg(P.first, TRI)
4400b57cec5SDimitry Andric              << ":L" << PrintLaneMask(P.second)
4410b57cec5SDimitry Andric              << " isn't found in LIS reported set\n";
4420b57cec5SDimitry Andric     }
4430b57cec5SDimitry Andric     else if (I->second != P.second) {
4440b57cec5SDimitry Andric       dbgs() << "  " << printReg(P.first, TRI)
4450b57cec5SDimitry Andric         << " masks doesn't match: LIS reported "
4460b57cec5SDimitry Andric         << PrintLaneMask(I->second)
4470b57cec5SDimitry Andric         << ", tracked "
4480b57cec5SDimitry Andric         << PrintLaneMask(P.second)
4490b57cec5SDimitry Andric         << '\n';
4500b57cec5SDimitry Andric     }
4510b57cec5SDimitry Andric   }
4520b57cec5SDimitry Andric   for (auto const &P : LISLR) {
4530b57cec5SDimitry Andric     auto I = TrackedLR.find(P.first);
4540b57cec5SDimitry Andric     if (I == TrackedLR.end()) {
4550b57cec5SDimitry Andric       dbgs() << "  " << printReg(P.first, TRI)
4560b57cec5SDimitry Andric              << ":L" << PrintLaneMask(P.second)
4570b57cec5SDimitry Andric              << " isn't found in tracked set\n";
4580b57cec5SDimitry Andric     }
4590b57cec5SDimitry Andric   }
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric bool GCNUpwardRPTracker::isValid() const {
4630b57cec5SDimitry Andric   const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
4640b57cec5SDimitry Andric   const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
4650b57cec5SDimitry Andric   const auto &TrackedLR = LiveRegs;
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric   if (!isEqual(LISLR, TrackedLR)) {
4680b57cec5SDimitry Andric     dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
4690b57cec5SDimitry Andric               " LIS reported livesets mismatch:\n";
4700b57cec5SDimitry Andric     printLivesAt(SI, LIS, *MRI);
4710b57cec5SDimitry Andric     reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo());
4720b57cec5SDimitry Andric     return false;
4730b57cec5SDimitry Andric   }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric   auto LISPressure = getRegPressure(*MRI, LISLR);
4760b57cec5SDimitry Andric   if (LISPressure != CurPressure) {
4770b57cec5SDimitry Andric     dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: ";
4780b57cec5SDimitry Andric     CurPressure.print(dbgs());
4790b57cec5SDimitry Andric     dbgs() << "LIS rpt: ";
4800b57cec5SDimitry Andric     LISPressure.print(dbgs());
4810b57cec5SDimitry Andric     return false;
4820b57cec5SDimitry Andric   }
4830b57cec5SDimitry Andric   return true;
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric void GCNRPTracker::printLiveRegs(raw_ostream &OS, const LiveRegSet& LiveRegs,
4870b57cec5SDimitry Andric                                  const MachineRegisterInfo &MRI) {
4880b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
4890b57cec5SDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
490*04eeddc0SDimitry 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';
4970b57cec5SDimitry Andric }
4980b57cec5SDimitry Andric #endif
499