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