xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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) {
308bcb0991SDimitry Andric     const unsigned 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 
72*e8d8bef9SDimitry Andric unsigned GCNRegPressure::getRegKind(Register Reg,
730b57cec5SDimitry Andric                                     const MachineRegisterInfo &MRI) {
74*e8d8bef9SDimitry Andric   assert(Reg.isVirtual());
750b57cec5SDimitry Andric   const auto RC = MRI.getRegClass(Reg);
760b57cec5SDimitry Andric   auto STI = static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo());
770b57cec5SDimitry Andric   return STI->isSGPRClass(RC) ?
780b57cec5SDimitry Andric     (STI->getRegSizeInBits(*RC) == 32 ? SGPR32 : SGPR_TUPLE) :
790b57cec5SDimitry Andric     STI->hasAGPRs(RC) ?
800b57cec5SDimitry Andric       (STI->getRegSizeInBits(*RC) == 32 ? AGPR32 : AGPR_TUPLE) :
810b57cec5SDimitry 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()));
1280b57cec5SDimitry Andric   const auto VGPROcc = std::min(MaxOccupancy,
1290b57cec5SDimitry Andric                                 ST.getOccupancyWithNumVGPRs(getVGPRNum()));
1300b57cec5SDimitry Andric   const auto OtherSGPROcc = std::min(MaxOccupancy,
1310b57cec5SDimitry Andric                                 ST.getOccupancyWithNumSGPRs(O.getSGPRNum()));
1320b57cec5SDimitry Andric   const auto OtherVGPROcc = std::min(MaxOccupancy,
1330b57cec5SDimitry Andric                                 ST.getOccupancyWithNumVGPRs(O.getVGPRNum()));
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   const auto Occ = std::min(SGPROcc, VGPROcc);
1360b57cec5SDimitry Andric   const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc);
1370b57cec5SDimitry Andric   if (Occ != OtherOcc)
1380b57cec5SDimitry Andric     return Occ > OtherOcc;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   bool SGPRImportant = SGPROcc < VGPROcc;
1410b57cec5SDimitry Andric   const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc;
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   // if both pressures disagree on what is more important compare vgprs
1440b57cec5SDimitry Andric   if (SGPRImportant != OtherSGPRImportant) {
1450b57cec5SDimitry Andric     SGPRImportant = false;
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   // compare large regs pressure
1490b57cec5SDimitry Andric   bool SGPRFirst = SGPRImportant;
1500b57cec5SDimitry Andric   for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) {
1510b57cec5SDimitry Andric     if (SGPRFirst) {
1520b57cec5SDimitry Andric       auto SW = getSGPRTuplesWeight();
1530b57cec5SDimitry Andric       auto OtherSW = O.getSGPRTuplesWeight();
1540b57cec5SDimitry Andric       if (SW != OtherSW)
1550b57cec5SDimitry Andric         return SW < OtherSW;
1560b57cec5SDimitry Andric     } else {
1570b57cec5SDimitry Andric       auto VW = getVGPRTuplesWeight();
1580b57cec5SDimitry Andric       auto OtherVW = O.getVGPRTuplesWeight();
1590b57cec5SDimitry Andric       if (VW != OtherVW)
1600b57cec5SDimitry Andric         return VW < OtherVW;
1610b57cec5SDimitry Andric     }
1620b57cec5SDimitry Andric   }
1630b57cec5SDimitry Andric   return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()):
1640b57cec5SDimitry Andric                          (getVGPRNum() < O.getVGPRNum());
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1680b57cec5SDimitry Andric LLVM_DUMP_METHOD
1690b57cec5SDimitry Andric void GCNRegPressure::print(raw_ostream &OS, const GCNSubtarget *ST) const {
1708bcb0991SDimitry Andric   OS << "VGPRs: " << Value[VGPR32] << ' ';
1718bcb0991SDimitry Andric   OS << "AGPRs: " << Value[AGPR32];
1720b57cec5SDimitry Andric   if (ST) OS << "(O" << ST->getOccupancyWithNumVGPRs(getVGPRNum()) << ')';
1730b57cec5SDimitry Andric   OS << ", SGPRs: " << getSGPRNum();
1740b57cec5SDimitry Andric   if (ST) OS << "(O" << ST->getOccupancyWithNumSGPRs(getSGPRNum()) << ')';
1750b57cec5SDimitry Andric   OS << ", LVGPR WT: " << getVGPRTuplesWeight()
1760b57cec5SDimitry Andric      << ", LSGPR WT: " << getSGPRTuplesWeight();
1770b57cec5SDimitry Andric   if (ST) OS << " -> Occ: " << getOccupancy(*ST);
1780b57cec5SDimitry Andric   OS << '\n';
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric #endif
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric static LaneBitmask getDefRegMask(const MachineOperand &MO,
1830b57cec5SDimitry Andric                                  const MachineRegisterInfo &MRI) {
184*e8d8bef9SDimitry Andric   assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual());
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   // We don't rely on read-undef flag because in case of tentative schedule
1870b57cec5SDimitry Andric   // tracking it isn't set correctly yet. This works correctly however since
1880b57cec5SDimitry Andric   // use mask has been tracked before using LIS.
1890b57cec5SDimitry Andric   return MO.getSubReg() == 0 ?
1900b57cec5SDimitry Andric     MRI.getMaxLaneMaskForVReg(MO.getReg()) :
1910b57cec5SDimitry Andric     MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric static LaneBitmask getUsedRegMask(const MachineOperand &MO,
1950b57cec5SDimitry Andric                                   const MachineRegisterInfo &MRI,
1960b57cec5SDimitry Andric                                   const LiveIntervals &LIS) {
197*e8d8bef9SDimitry Andric   assert(MO.isUse() && MO.isReg() && MO.getReg().isVirtual());
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   if (auto SubReg = MO.getSubReg())
2000b57cec5SDimitry Andric     return MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg);
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   auto MaxMask = MRI.getMaxLaneMaskForVReg(MO.getReg());
2035ffd83dbSDimitry Andric   if (SIRegisterInfo::getNumCoveredRegs(MaxMask) > 1) // cannot have subregs
2040b57cec5SDimitry Andric     return MaxMask;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   // For a tentative schedule LIS isn't updated yet but livemask should remain
2070b57cec5SDimitry Andric   // the same on any schedule. Subreg defs can be reordered but they all must
2080b57cec5SDimitry Andric   // dominate uses anyway.
2090b57cec5SDimitry Andric   auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex();
2100b57cec5SDimitry Andric   return getLiveLaneMask(MO.getReg(), SI, LIS, MRI);
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric static SmallVector<RegisterMaskPair, 8>
2140b57cec5SDimitry Andric collectVirtualRegUses(const MachineInstr &MI, const LiveIntervals &LIS,
2150b57cec5SDimitry Andric                       const MachineRegisterInfo &MRI) {
2160b57cec5SDimitry Andric   SmallVector<RegisterMaskPair, 8> Res;
2170b57cec5SDimitry Andric   for (const auto &MO : MI.operands()) {
218*e8d8bef9SDimitry Andric     if (!MO.isReg() || !MO.getReg().isVirtual())
2190b57cec5SDimitry Andric       continue;
2200b57cec5SDimitry Andric     if (!MO.isUse() || !MO.readsReg())
2210b57cec5SDimitry Andric       continue;
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric     auto const UsedMask = getUsedRegMask(MO, MRI, LIS);
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric     auto Reg = MO.getReg();
226*e8d8bef9SDimitry Andric     auto I = llvm::find_if(
227*e8d8bef9SDimitry Andric         Res, [Reg](const RegisterMaskPair &RM) { return RM.RegUnit == Reg; });
2280b57cec5SDimitry Andric     if (I != Res.end())
2290b57cec5SDimitry Andric       I->LaneMask |= UsedMask;
2300b57cec5SDimitry Andric     else
2310b57cec5SDimitry Andric       Res.push_back(RegisterMaskPair(Reg, UsedMask));
2320b57cec5SDimitry Andric   }
2330b57cec5SDimitry Andric   return Res;
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric ///////////////////////////////////////////////////////////////////////////////
2370b57cec5SDimitry Andric // GCNRPTracker
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric LaneBitmask llvm::getLiveLaneMask(unsigned Reg,
2400b57cec5SDimitry Andric                                   SlotIndex SI,
2410b57cec5SDimitry Andric                                   const LiveIntervals &LIS,
2420b57cec5SDimitry Andric                                   const MachineRegisterInfo &MRI) {
2430b57cec5SDimitry Andric   LaneBitmask LiveMask;
2440b57cec5SDimitry Andric   const auto &LI = LIS.getInterval(Reg);
2450b57cec5SDimitry Andric   if (LI.hasSubRanges()) {
2460b57cec5SDimitry Andric     for (const auto &S : LI.subranges())
2470b57cec5SDimitry Andric       if (S.liveAt(SI)) {
2480b57cec5SDimitry Andric         LiveMask |= S.LaneMask;
2490b57cec5SDimitry Andric         assert(LiveMask < MRI.getMaxLaneMaskForVReg(Reg) ||
2500b57cec5SDimitry Andric                LiveMask == MRI.getMaxLaneMaskForVReg(Reg));
2510b57cec5SDimitry Andric       }
2520b57cec5SDimitry Andric   } else if (LI.liveAt(SI)) {
2530b57cec5SDimitry Andric     LiveMask = MRI.getMaxLaneMaskForVReg(Reg);
2540b57cec5SDimitry Andric   }
2550b57cec5SDimitry Andric   return LiveMask;
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
2590b57cec5SDimitry Andric                                            const LiveIntervals &LIS,
2600b57cec5SDimitry Andric                                            const MachineRegisterInfo &MRI) {
2610b57cec5SDimitry Andric   GCNRPTracker::LiveRegSet LiveRegs;
2620b57cec5SDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
2638bcb0991SDimitry Andric     auto Reg = Register::index2VirtReg(I);
2640b57cec5SDimitry Andric     if (!LIS.hasInterval(Reg))
2650b57cec5SDimitry Andric       continue;
2660b57cec5SDimitry Andric     auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI);
2670b57cec5SDimitry Andric     if (LiveMask.any())
2680b57cec5SDimitry Andric       LiveRegs[Reg] = LiveMask;
2690b57cec5SDimitry Andric   }
2700b57cec5SDimitry Andric   return LiveRegs;
2710b57cec5SDimitry Andric }
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric void GCNRPTracker::reset(const MachineInstr &MI,
2740b57cec5SDimitry Andric                          const LiveRegSet *LiveRegsCopy,
2750b57cec5SDimitry Andric                          bool After) {
2760b57cec5SDimitry Andric   const MachineFunction &MF = *MI.getMF();
2770b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
2780b57cec5SDimitry Andric   if (LiveRegsCopy) {
2790b57cec5SDimitry Andric     if (&LiveRegs != LiveRegsCopy)
2800b57cec5SDimitry Andric       LiveRegs = *LiveRegsCopy;
2810b57cec5SDimitry Andric   } else {
2820b57cec5SDimitry Andric     LiveRegs = After ? getLiveRegsAfter(MI, LIS)
2830b57cec5SDimitry Andric                      : getLiveRegsBefore(MI, LIS);
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs);
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric void GCNUpwardRPTracker::reset(const MachineInstr &MI,
2900b57cec5SDimitry Andric                                const LiveRegSet *LiveRegsCopy) {
2910b57cec5SDimitry Andric   GCNRPTracker::reset(MI, LiveRegsCopy, true);
2920b57cec5SDimitry Andric }
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric void GCNUpwardRPTracker::recede(const MachineInstr &MI) {
2950b57cec5SDimitry Andric   assert(MRI && "call reset first");
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   LastTrackedMI = &MI;
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   if (MI.isDebugInstr())
3000b57cec5SDimitry Andric     return;
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   auto const RegUses = collectVirtualRegUses(MI, LIS, *MRI);
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   // calc pressure at the MI (defs + uses)
3050b57cec5SDimitry Andric   auto AtMIPressure = CurPressure;
3060b57cec5SDimitry Andric   for (const auto &U : RegUses) {
3070b57cec5SDimitry Andric     auto LiveMask = LiveRegs[U.RegUnit];
3080b57cec5SDimitry Andric     AtMIPressure.inc(U.RegUnit, LiveMask, LiveMask | U.LaneMask, *MRI);
3090b57cec5SDimitry Andric   }
3100b57cec5SDimitry Andric   // update max pressure
3110b57cec5SDimitry Andric   MaxPressure = max(AtMIPressure, MaxPressure);
3120b57cec5SDimitry Andric 
3135ffd83dbSDimitry Andric   for (const auto &MO : MI.operands()) {
314*e8d8bef9SDimitry Andric     if (!MO.isReg() || !MO.isDef() || !MO.getReg().isVirtual() || MO.isDead())
3150b57cec5SDimitry Andric       continue;
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric     auto Reg = MO.getReg();
3180b57cec5SDimitry Andric     auto I = LiveRegs.find(Reg);
3190b57cec5SDimitry Andric     if (I == LiveRegs.end())
3200b57cec5SDimitry Andric       continue;
3210b57cec5SDimitry Andric     auto &LiveMask = I->second;
3220b57cec5SDimitry Andric     auto PrevMask = LiveMask;
3230b57cec5SDimitry Andric     LiveMask &= ~getDefRegMask(MO, *MRI);
3240b57cec5SDimitry Andric     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
3250b57cec5SDimitry Andric     if (LiveMask.none())
3260b57cec5SDimitry Andric       LiveRegs.erase(I);
3270b57cec5SDimitry Andric   }
3280b57cec5SDimitry Andric   for (const auto &U : RegUses) {
3290b57cec5SDimitry Andric     auto &LiveMask = LiveRegs[U.RegUnit];
3300b57cec5SDimitry Andric     auto PrevMask = LiveMask;
3310b57cec5SDimitry Andric     LiveMask |= U.LaneMask;
3320b57cec5SDimitry Andric     CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI);
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric   assert(CurPressure == getRegPressure(*MRI, LiveRegs));
3350b57cec5SDimitry Andric }
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric bool GCNDownwardRPTracker::reset(const MachineInstr &MI,
3380b57cec5SDimitry Andric                                  const LiveRegSet *LiveRegsCopy) {
3390b57cec5SDimitry Andric   MRI = &MI.getParent()->getParent()->getRegInfo();
3400b57cec5SDimitry Andric   LastTrackedMI = nullptr;
3410b57cec5SDimitry Andric   MBBEnd = MI.getParent()->end();
3420b57cec5SDimitry Andric   NextMI = &MI;
3430b57cec5SDimitry Andric   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
3440b57cec5SDimitry Andric   if (NextMI == MBBEnd)
3450b57cec5SDimitry Andric     return false;
3460b57cec5SDimitry Andric   GCNRPTracker::reset(*NextMI, LiveRegsCopy, false);
3470b57cec5SDimitry Andric   return true;
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric bool GCNDownwardRPTracker::advanceBeforeNext() {
3510b57cec5SDimitry Andric   assert(MRI && "call reset first");
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
3540b57cec5SDimitry Andric   if (NextMI == MBBEnd)
3550b57cec5SDimitry Andric     return false;
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   SlotIndex SI = LIS.getInstructionIndex(*NextMI).getBaseIndex();
3580b57cec5SDimitry Andric   assert(SI.isValid());
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   // Remove dead registers or mask bits.
3610b57cec5SDimitry Andric   for (auto &It : LiveRegs) {
3620b57cec5SDimitry Andric     const LiveInterval &LI = LIS.getInterval(It.first);
3630b57cec5SDimitry Andric     if (LI.hasSubRanges()) {
3640b57cec5SDimitry Andric       for (const auto &S : LI.subranges()) {
3650b57cec5SDimitry Andric         if (!S.liveAt(SI)) {
3660b57cec5SDimitry Andric           auto PrevMask = It.second;
3670b57cec5SDimitry Andric           It.second &= ~S.LaneMask;
3680b57cec5SDimitry Andric           CurPressure.inc(It.first, PrevMask, It.second, *MRI);
3690b57cec5SDimitry Andric         }
3700b57cec5SDimitry Andric       }
3710b57cec5SDimitry Andric     } else if (!LI.liveAt(SI)) {
3720b57cec5SDimitry Andric       auto PrevMask = It.second;
3730b57cec5SDimitry Andric       It.second = LaneBitmask::getNone();
3740b57cec5SDimitry Andric       CurPressure.inc(It.first, PrevMask, It.second, *MRI);
3750b57cec5SDimitry Andric     }
3760b57cec5SDimitry Andric     if (It.second.none())
3770b57cec5SDimitry Andric       LiveRegs.erase(It.first);
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric   MaxPressure = max(MaxPressure, CurPressure);
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric   return true;
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric void GCNDownwardRPTracker::advanceToNext() {
3860b57cec5SDimitry Andric   LastTrackedMI = &*NextMI++;
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric   // Add new registers or mask bits.
3895ffd83dbSDimitry Andric   for (const auto &MO : LastTrackedMI->operands()) {
3905ffd83dbSDimitry Andric     if (!MO.isReg() || !MO.isDef())
3910b57cec5SDimitry Andric       continue;
3928bcb0991SDimitry Andric     Register Reg = MO.getReg();
393*e8d8bef9SDimitry Andric     if (!Reg.isVirtual())
3940b57cec5SDimitry Andric       continue;
3950b57cec5SDimitry Andric     auto &LiveMask = LiveRegs[Reg];
3960b57cec5SDimitry Andric     auto PrevMask = LiveMask;
3970b57cec5SDimitry Andric     LiveMask |= getDefRegMask(MO, *MRI);
3980b57cec5SDimitry Andric     CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
3990b57cec5SDimitry Andric   }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   MaxPressure = max(MaxPressure, CurPressure);
4020b57cec5SDimitry Andric }
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance() {
4050b57cec5SDimitry Andric   // If we have just called reset live set is actual.
4060b57cec5SDimitry Andric   if ((NextMI == MBBEnd) || (LastTrackedMI && !advanceBeforeNext()))
4070b57cec5SDimitry Andric     return false;
4080b57cec5SDimitry Andric   advanceToNext();
4090b57cec5SDimitry Andric   return true;
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) {
4130b57cec5SDimitry Andric   while (NextMI != End)
4140b57cec5SDimitry Andric     if (!advance()) return false;
4150b57cec5SDimitry Andric   return true;
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin,
4190b57cec5SDimitry Andric                                    MachineBasicBlock::const_iterator End,
4200b57cec5SDimitry Andric                                    const LiveRegSet *LiveRegsCopy) {
4210b57cec5SDimitry Andric   reset(*Begin, LiveRegsCopy);
4220b57cec5SDimitry Andric   return advance(End);
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4260b57cec5SDimitry Andric LLVM_DUMP_METHOD
4270b57cec5SDimitry Andric static void reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
4280b57cec5SDimitry Andric                            const GCNRPTracker::LiveRegSet &TrackedLR,
4290b57cec5SDimitry Andric                            const TargetRegisterInfo *TRI) {
4300b57cec5SDimitry Andric   for (auto const &P : TrackedLR) {
4310b57cec5SDimitry Andric     auto I = LISLR.find(P.first);
4320b57cec5SDimitry Andric     if (I == LISLR.end()) {
4330b57cec5SDimitry Andric       dbgs() << "  " << printReg(P.first, TRI)
4340b57cec5SDimitry Andric              << ":L" << PrintLaneMask(P.second)
4350b57cec5SDimitry Andric              << " isn't found in LIS reported set\n";
4360b57cec5SDimitry Andric     }
4370b57cec5SDimitry Andric     else if (I->second != P.second) {
4380b57cec5SDimitry Andric       dbgs() << "  " << printReg(P.first, TRI)
4390b57cec5SDimitry Andric         << " masks doesn't match: LIS reported "
4400b57cec5SDimitry Andric         << PrintLaneMask(I->second)
4410b57cec5SDimitry Andric         << ", tracked "
4420b57cec5SDimitry Andric         << PrintLaneMask(P.second)
4430b57cec5SDimitry Andric         << '\n';
4440b57cec5SDimitry Andric     }
4450b57cec5SDimitry Andric   }
4460b57cec5SDimitry Andric   for (auto const &P : LISLR) {
4470b57cec5SDimitry Andric     auto I = TrackedLR.find(P.first);
4480b57cec5SDimitry Andric     if (I == TrackedLR.end()) {
4490b57cec5SDimitry Andric       dbgs() << "  " << printReg(P.first, TRI)
4500b57cec5SDimitry Andric              << ":L" << PrintLaneMask(P.second)
4510b57cec5SDimitry Andric              << " isn't found in tracked set\n";
4520b57cec5SDimitry Andric     }
4530b57cec5SDimitry Andric   }
4540b57cec5SDimitry Andric }
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric bool GCNUpwardRPTracker::isValid() const {
4570b57cec5SDimitry Andric   const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
4580b57cec5SDimitry Andric   const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
4590b57cec5SDimitry Andric   const auto &TrackedLR = LiveRegs;
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   if (!isEqual(LISLR, TrackedLR)) {
4620b57cec5SDimitry Andric     dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
4630b57cec5SDimitry Andric               " LIS reported livesets mismatch:\n";
4640b57cec5SDimitry Andric     printLivesAt(SI, LIS, *MRI);
4650b57cec5SDimitry Andric     reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo());
4660b57cec5SDimitry Andric     return false;
4670b57cec5SDimitry Andric   }
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric   auto LISPressure = getRegPressure(*MRI, LISLR);
4700b57cec5SDimitry Andric   if (LISPressure != CurPressure) {
4710b57cec5SDimitry Andric     dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: ";
4720b57cec5SDimitry Andric     CurPressure.print(dbgs());
4730b57cec5SDimitry Andric     dbgs() << "LIS rpt: ";
4740b57cec5SDimitry Andric     LISPressure.print(dbgs());
4750b57cec5SDimitry Andric     return false;
4760b57cec5SDimitry Andric   }
4770b57cec5SDimitry Andric   return true;
4780b57cec5SDimitry Andric }
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric void GCNRPTracker::printLiveRegs(raw_ostream &OS, const LiveRegSet& LiveRegs,
4810b57cec5SDimitry Andric                                  const MachineRegisterInfo &MRI) {
4820b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
4830b57cec5SDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
4848bcb0991SDimitry Andric     unsigned Reg = Register::index2VirtReg(I);
4850b57cec5SDimitry Andric     auto It = LiveRegs.find(Reg);
4860b57cec5SDimitry Andric     if (It != LiveRegs.end() && It->second.any())
4870b57cec5SDimitry Andric       OS << ' ' << printVRegOrUnit(Reg, TRI) << ':'
4880b57cec5SDimitry Andric          << PrintLaneMask(It->second);
4890b57cec5SDimitry Andric   }
4900b57cec5SDimitry Andric   OS << '\n';
4910b57cec5SDimitry Andric }
4920b57cec5SDimitry Andric #endif
493