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