10b57cec5SDimitry Andric //===- GCNRegPressure.cpp -------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric /// 95ffd83dbSDimitry Andric /// \file 105ffd83dbSDimitry Andric /// This file implements the GCNRegPressure class. 115ffd83dbSDimitry Andric /// 125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "GCNRegPressure.h" 150b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterPressure.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric using namespace llvm; 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #define DEBUG_TYPE "machine-scheduler" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric bool llvm::isEqual(const GCNRPTracker::LiveRegSet &S1, 220b57cec5SDimitry Andric const GCNRPTracker::LiveRegSet &S2) { 230b57cec5SDimitry Andric if (S1.size() != S2.size()) 240b57cec5SDimitry Andric return false; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric for (const auto &P : S1) { 270b57cec5SDimitry Andric auto I = S2.find(P.first); 280b57cec5SDimitry Andric if (I == S2.end() || I->second != P.second) 290b57cec5SDimitry Andric return false; 300b57cec5SDimitry Andric } 310b57cec5SDimitry Andric return true; 320b57cec5SDimitry Andric } 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 360b57cec5SDimitry Andric // GCNRegPressure 370b57cec5SDimitry Andric 38e8d8bef9SDimitry Andric unsigned GCNRegPressure::getRegKind(Register Reg, 390b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 40e8d8bef9SDimitry Andric assert(Reg.isVirtual()); 410b57cec5SDimitry Andric const auto RC = MRI.getRegClass(Reg); 420b57cec5SDimitry Andric auto STI = static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo()); 434824e7fdSDimitry Andric return STI->isSGPRClass(RC) 444824e7fdSDimitry Andric ? (STI->getRegSizeInBits(*RC) == 32 ? SGPR32 : SGPR_TUPLE) 454824e7fdSDimitry Andric : STI->isAGPRClass(RC) 464824e7fdSDimitry Andric ? (STI->getRegSizeInBits(*RC) == 32 ? AGPR32 : AGPR_TUPLE) 474824e7fdSDimitry Andric : (STI->getRegSizeInBits(*RC) == 32 ? VGPR32 : VGPR_TUPLE); 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric void GCNRegPressure::inc(unsigned Reg, 510b57cec5SDimitry Andric LaneBitmask PrevMask, 520b57cec5SDimitry Andric LaneBitmask NewMask, 530b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 545ffd83dbSDimitry Andric if (SIRegisterInfo::getNumCoveredRegs(NewMask) == 555ffd83dbSDimitry Andric SIRegisterInfo::getNumCoveredRegs(PrevMask)) 560b57cec5SDimitry Andric return; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric int Sign = 1; 590b57cec5SDimitry Andric if (NewMask < PrevMask) { 600b57cec5SDimitry Andric std::swap(NewMask, PrevMask); 610b57cec5SDimitry Andric Sign = -1; 620b57cec5SDimitry Andric } 635ffd83dbSDimitry Andric 640b57cec5SDimitry Andric switch (auto Kind = getRegKind(Reg, MRI)) { 650b57cec5SDimitry Andric case SGPR32: 660b57cec5SDimitry Andric case VGPR32: 670b57cec5SDimitry Andric case AGPR32: 680b57cec5SDimitry Andric Value[Kind] += Sign; 690b57cec5SDimitry Andric break; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric case SGPR_TUPLE: 720b57cec5SDimitry Andric case VGPR_TUPLE: 730b57cec5SDimitry Andric case AGPR_TUPLE: 740b57cec5SDimitry Andric assert(PrevMask < NewMask); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric Value[Kind == SGPR_TUPLE ? SGPR32 : Kind == AGPR_TUPLE ? AGPR32 : VGPR32] += 775ffd83dbSDimitry Andric Sign * SIRegisterInfo::getNumCoveredRegs(~PrevMask & NewMask); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric if (PrevMask.none()) { 800b57cec5SDimitry Andric assert(NewMask.any()); 810b57cec5SDimitry Andric Value[Kind] += Sign * MRI.getPressureSets(Reg).getWeight(); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric break; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric default: llvm_unreachable("Unknown register kind"); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric bool GCNRegPressure::less(const GCNSubtarget &ST, 900b57cec5SDimitry Andric const GCNRegPressure& O, 910b57cec5SDimitry Andric unsigned MaxOccupancy) const { 920b57cec5SDimitry Andric const auto SGPROcc = std::min(MaxOccupancy, 930b57cec5SDimitry Andric ST.getOccupancyWithNumSGPRs(getSGPRNum())); 94fe6060f1SDimitry Andric const auto VGPROcc = 95fe6060f1SDimitry Andric std::min(MaxOccupancy, 96fe6060f1SDimitry Andric ST.getOccupancyWithNumVGPRs(getVGPRNum(ST.hasGFX90AInsts()))); 970b57cec5SDimitry Andric const auto OtherSGPROcc = std::min(MaxOccupancy, 980b57cec5SDimitry Andric ST.getOccupancyWithNumSGPRs(O.getSGPRNum())); 99fe6060f1SDimitry Andric const auto OtherVGPROcc = 100fe6060f1SDimitry Andric std::min(MaxOccupancy, 101fe6060f1SDimitry Andric ST.getOccupancyWithNumVGPRs(O.getVGPRNum(ST.hasGFX90AInsts()))); 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric const auto Occ = std::min(SGPROcc, VGPROcc); 1040b57cec5SDimitry Andric const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc); 1050b57cec5SDimitry Andric if (Occ != OtherOcc) 1060b57cec5SDimitry Andric return Occ > OtherOcc; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric bool SGPRImportant = SGPROcc < VGPROcc; 1090b57cec5SDimitry Andric const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc; 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric // if both pressures disagree on what is more important compare vgprs 1120b57cec5SDimitry Andric if (SGPRImportant != OtherSGPRImportant) { 1130b57cec5SDimitry Andric SGPRImportant = false; 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // compare large regs pressure 1170b57cec5SDimitry Andric bool SGPRFirst = SGPRImportant; 1180b57cec5SDimitry Andric for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) { 1190b57cec5SDimitry Andric if (SGPRFirst) { 1200b57cec5SDimitry Andric auto SW = getSGPRTuplesWeight(); 1210b57cec5SDimitry Andric auto OtherSW = O.getSGPRTuplesWeight(); 1220b57cec5SDimitry Andric if (SW != OtherSW) 1230b57cec5SDimitry Andric return SW < OtherSW; 1240b57cec5SDimitry Andric } else { 1250b57cec5SDimitry Andric auto VW = getVGPRTuplesWeight(); 1260b57cec5SDimitry Andric auto OtherVW = O.getVGPRTuplesWeight(); 1270b57cec5SDimitry Andric if (VW != OtherVW) 1280b57cec5SDimitry Andric return VW < OtherVW; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()): 132fe6060f1SDimitry Andric (getVGPRNum(ST.hasGFX90AInsts()) < 133fe6060f1SDimitry Andric O.getVGPRNum(ST.hasGFX90AInsts())); 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1370b57cec5SDimitry Andric LLVM_DUMP_METHOD 138bdd1243dSDimitry Andric Printable llvm::print(const GCNRegPressure &RP, const GCNSubtarget *ST) { 139bdd1243dSDimitry Andric return Printable([&RP, ST](raw_ostream &OS) { 140bdd1243dSDimitry Andric OS << "VGPRs: " << RP.Value[GCNRegPressure::VGPR32] << ' ' 141bdd1243dSDimitry Andric << "AGPRs: " << RP.getAGPRNum(); 142bdd1243dSDimitry Andric if (ST) 143bdd1243dSDimitry Andric OS << "(O" 144bdd1243dSDimitry Andric << ST->getOccupancyWithNumVGPRs(RP.getVGPRNum(ST->hasGFX90AInsts())) 145fe6060f1SDimitry Andric << ')'; 146bdd1243dSDimitry Andric OS << ", SGPRs: " << RP.getSGPRNum(); 147bdd1243dSDimitry Andric if (ST) 148bdd1243dSDimitry Andric OS << "(O" << ST->getOccupancyWithNumSGPRs(RP.getSGPRNum()) << ')'; 149bdd1243dSDimitry Andric OS << ", LVGPR WT: " << RP.getVGPRTuplesWeight() 150bdd1243dSDimitry Andric << ", LSGPR WT: " << RP.getSGPRTuplesWeight(); 151bdd1243dSDimitry Andric if (ST) 152bdd1243dSDimitry Andric OS << " -> Occ: " << RP.getOccupancy(*ST); 1530b57cec5SDimitry Andric OS << '\n'; 154bdd1243dSDimitry Andric }); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric #endif 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric static LaneBitmask getDefRegMask(const MachineOperand &MO, 1590b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 160e8d8bef9SDimitry Andric assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual()); 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric // We don't rely on read-undef flag because in case of tentative schedule 1630b57cec5SDimitry Andric // tracking it isn't set correctly yet. This works correctly however since 1640b57cec5SDimitry Andric // use mask has been tracked before using LIS. 1650b57cec5SDimitry Andric return MO.getSubReg() == 0 ? 1660b57cec5SDimitry Andric MRI.getMaxLaneMaskForVReg(MO.getReg()) : 1670b57cec5SDimitry Andric MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg()); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric static LaneBitmask getUsedRegMask(const MachineOperand &MO, 1710b57cec5SDimitry Andric const MachineRegisterInfo &MRI, 1720b57cec5SDimitry Andric const LiveIntervals &LIS) { 173e8d8bef9SDimitry Andric assert(MO.isUse() && MO.isReg() && MO.getReg().isVirtual()); 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric if (auto SubReg = MO.getSubReg()) 1760b57cec5SDimitry Andric return MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg); 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric auto MaxMask = MRI.getMaxLaneMaskForVReg(MO.getReg()); 1795ffd83dbSDimitry Andric if (SIRegisterInfo::getNumCoveredRegs(MaxMask) > 1) // cannot have subregs 1800b57cec5SDimitry Andric return MaxMask; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric // For a tentative schedule LIS isn't updated yet but livemask should remain 1830b57cec5SDimitry Andric // the same on any schedule. Subreg defs can be reordered but they all must 1840b57cec5SDimitry Andric // dominate uses anyway. 1850b57cec5SDimitry Andric auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex(); 1860b57cec5SDimitry Andric return getLiveLaneMask(MO.getReg(), SI, LIS, MRI); 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric static SmallVector<RegisterMaskPair, 8> 1900b57cec5SDimitry Andric collectVirtualRegUses(const MachineInstr &MI, const LiveIntervals &LIS, 1910b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 1920b57cec5SDimitry Andric SmallVector<RegisterMaskPair, 8> Res; 1930b57cec5SDimitry Andric for (const auto &MO : MI.operands()) { 194e8d8bef9SDimitry Andric if (!MO.isReg() || !MO.getReg().isVirtual()) 1950b57cec5SDimitry Andric continue; 1960b57cec5SDimitry Andric if (!MO.isUse() || !MO.readsReg()) 1970b57cec5SDimitry Andric continue; 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric auto const UsedMask = getUsedRegMask(MO, MRI, LIS); 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric auto Reg = MO.getReg(); 202e8d8bef9SDimitry Andric auto I = llvm::find_if( 203e8d8bef9SDimitry Andric Res, [Reg](const RegisterMaskPair &RM) { return RM.RegUnit == Reg; }); 2040b57cec5SDimitry Andric if (I != Res.end()) 2050b57cec5SDimitry Andric I->LaneMask |= UsedMask; 2060b57cec5SDimitry Andric else 2070b57cec5SDimitry Andric Res.push_back(RegisterMaskPair(Reg, UsedMask)); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric return Res; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 2130b57cec5SDimitry Andric // GCNRPTracker 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric LaneBitmask llvm::getLiveLaneMask(unsigned Reg, 2160b57cec5SDimitry Andric SlotIndex SI, 2170b57cec5SDimitry Andric const LiveIntervals &LIS, 2180b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 2190b57cec5SDimitry Andric LaneBitmask LiveMask; 2200b57cec5SDimitry Andric const auto &LI = LIS.getInterval(Reg); 2210b57cec5SDimitry Andric if (LI.hasSubRanges()) { 2220b57cec5SDimitry Andric for (const auto &S : LI.subranges()) 2230b57cec5SDimitry Andric if (S.liveAt(SI)) { 2240b57cec5SDimitry Andric LiveMask |= S.LaneMask; 2250b57cec5SDimitry Andric assert(LiveMask < MRI.getMaxLaneMaskForVReg(Reg) || 2260b57cec5SDimitry Andric LiveMask == MRI.getMaxLaneMaskForVReg(Reg)); 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric } else if (LI.liveAt(SI)) { 2290b57cec5SDimitry Andric LiveMask = MRI.getMaxLaneMaskForVReg(Reg); 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric return LiveMask; 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI, 2350b57cec5SDimitry Andric const LiveIntervals &LIS, 2360b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 2370b57cec5SDimitry Andric GCNRPTracker::LiveRegSet LiveRegs; 2380b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { 2398bcb0991SDimitry Andric auto Reg = Register::index2VirtReg(I); 2400b57cec5SDimitry Andric if (!LIS.hasInterval(Reg)) 2410b57cec5SDimitry Andric continue; 2420b57cec5SDimitry Andric auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI); 2430b57cec5SDimitry Andric if (LiveMask.any()) 2440b57cec5SDimitry Andric LiveRegs[Reg] = LiveMask; 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric return LiveRegs; 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric void GCNRPTracker::reset(const MachineInstr &MI, 2500b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy, 2510b57cec5SDimitry Andric bool After) { 2520b57cec5SDimitry Andric const MachineFunction &MF = *MI.getMF(); 2530b57cec5SDimitry Andric MRI = &MF.getRegInfo(); 2540b57cec5SDimitry Andric if (LiveRegsCopy) { 2550b57cec5SDimitry Andric if (&LiveRegs != LiveRegsCopy) 2560b57cec5SDimitry Andric LiveRegs = *LiveRegsCopy; 2570b57cec5SDimitry Andric } else { 2580b57cec5SDimitry Andric LiveRegs = After ? getLiveRegsAfter(MI, LIS) 2590b57cec5SDimitry Andric : getLiveRegsBefore(MI, LIS); 2600b57cec5SDimitry Andric } 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric void GCNUpwardRPTracker::reset(const MachineInstr &MI, 2660b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) { 2670b57cec5SDimitry Andric GCNRPTracker::reset(MI, LiveRegsCopy, true); 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric void GCNUpwardRPTracker::recede(const MachineInstr &MI) { 2710b57cec5SDimitry Andric assert(MRI && "call reset first"); 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric LastTrackedMI = &MI; 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric if (MI.isDebugInstr()) 2760b57cec5SDimitry Andric return; 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric auto const RegUses = collectVirtualRegUses(MI, LIS, *MRI); 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric // calc pressure at the MI (defs + uses) 2810b57cec5SDimitry Andric auto AtMIPressure = CurPressure; 2820b57cec5SDimitry Andric for (const auto &U : RegUses) { 2830b57cec5SDimitry Andric auto LiveMask = LiveRegs[U.RegUnit]; 2840b57cec5SDimitry Andric AtMIPressure.inc(U.RegUnit, LiveMask, LiveMask | U.LaneMask, *MRI); 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric // update max pressure 2870b57cec5SDimitry Andric MaxPressure = max(AtMIPressure, MaxPressure); 2880b57cec5SDimitry Andric 289*06c3fb27SDimitry Andric for (const auto &MO : MI.all_defs()) { 290*06c3fb27SDimitry Andric if (!MO.getReg().isVirtual() || MO.isDead()) 2910b57cec5SDimitry Andric continue; 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric auto Reg = MO.getReg(); 2940b57cec5SDimitry Andric auto I = LiveRegs.find(Reg); 2950b57cec5SDimitry Andric if (I == LiveRegs.end()) 2960b57cec5SDimitry Andric continue; 2970b57cec5SDimitry Andric auto &LiveMask = I->second; 2980b57cec5SDimitry Andric auto PrevMask = LiveMask; 2990b57cec5SDimitry Andric LiveMask &= ~getDefRegMask(MO, *MRI); 3000b57cec5SDimitry Andric CurPressure.inc(Reg, PrevMask, LiveMask, *MRI); 3010b57cec5SDimitry Andric if (LiveMask.none()) 3020b57cec5SDimitry Andric LiveRegs.erase(I); 3030b57cec5SDimitry Andric } 3040b57cec5SDimitry Andric for (const auto &U : RegUses) { 3050b57cec5SDimitry Andric auto &LiveMask = LiveRegs[U.RegUnit]; 3060b57cec5SDimitry Andric auto PrevMask = LiveMask; 3070b57cec5SDimitry Andric LiveMask |= U.LaneMask; 3080b57cec5SDimitry Andric CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI); 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric assert(CurPressure == getRegPressure(*MRI, LiveRegs)); 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric bool GCNDownwardRPTracker::reset(const MachineInstr &MI, 3140b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) { 3150b57cec5SDimitry Andric MRI = &MI.getParent()->getParent()->getRegInfo(); 3160b57cec5SDimitry Andric LastTrackedMI = nullptr; 3170b57cec5SDimitry Andric MBBEnd = MI.getParent()->end(); 3180b57cec5SDimitry Andric NextMI = &MI; 3190b57cec5SDimitry Andric NextMI = skipDebugInstructionsForward(NextMI, MBBEnd); 3200b57cec5SDimitry Andric if (NextMI == MBBEnd) 3210b57cec5SDimitry Andric return false; 3220b57cec5SDimitry Andric GCNRPTracker::reset(*NextMI, LiveRegsCopy, false); 3230b57cec5SDimitry Andric return true; 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric bool GCNDownwardRPTracker::advanceBeforeNext() { 3270b57cec5SDimitry Andric assert(MRI && "call reset first"); 328bdd1243dSDimitry Andric if (!LastTrackedMI) 329bdd1243dSDimitry Andric return NextMI == MBBEnd; 3300b57cec5SDimitry Andric 331bdd1243dSDimitry Andric assert(NextMI == MBBEnd || !NextMI->isDebugInstr()); 3320b57cec5SDimitry Andric 333bdd1243dSDimitry Andric SlotIndex SI = NextMI == MBBEnd 334bdd1243dSDimitry Andric ? LIS.getInstructionIndex(*LastTrackedMI).getDeadSlot() 335bdd1243dSDimitry Andric : LIS.getInstructionIndex(*NextMI).getBaseIndex(); 3360b57cec5SDimitry Andric assert(SI.isValid()); 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric // Remove dead registers or mask bits. 339*06c3fb27SDimitry Andric SmallSet<Register, 8> SeenRegs; 340*06c3fb27SDimitry Andric for (auto &MO : LastTrackedMI->operands()) { 341*06c3fb27SDimitry Andric if (!MO.isReg() || !MO.getReg().isVirtual()) 342*06c3fb27SDimitry Andric continue; 343*06c3fb27SDimitry Andric if (MO.isUse() && !MO.readsReg()) 344*06c3fb27SDimitry Andric continue; 345*06c3fb27SDimitry Andric if (!SeenRegs.insert(MO.getReg()).second) 346*06c3fb27SDimitry Andric continue; 347*06c3fb27SDimitry Andric const LiveInterval &LI = LIS.getInterval(MO.getReg()); 3480b57cec5SDimitry Andric if (LI.hasSubRanges()) { 349*06c3fb27SDimitry Andric auto It = LiveRegs.end(); 3500b57cec5SDimitry Andric for (const auto &S : LI.subranges()) { 3510b57cec5SDimitry Andric if (!S.liveAt(SI)) { 352*06c3fb27SDimitry Andric if (It == LiveRegs.end()) { 353*06c3fb27SDimitry Andric It = LiveRegs.find(MO.getReg()); 354*06c3fb27SDimitry Andric if (It == LiveRegs.end()) 355*06c3fb27SDimitry Andric llvm_unreachable("register isn't live"); 356*06c3fb27SDimitry Andric } 357*06c3fb27SDimitry Andric auto PrevMask = It->second; 358*06c3fb27SDimitry Andric It->second &= ~S.LaneMask; 359*06c3fb27SDimitry Andric CurPressure.inc(MO.getReg(), PrevMask, It->second, *MRI); 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric } 362*06c3fb27SDimitry Andric if (It != LiveRegs.end() && It->second.none()) 363*06c3fb27SDimitry Andric LiveRegs.erase(It); 3640b57cec5SDimitry Andric } else if (!LI.liveAt(SI)) { 365*06c3fb27SDimitry Andric auto It = LiveRegs.find(MO.getReg()); 366*06c3fb27SDimitry Andric if (It == LiveRegs.end()) 367*06c3fb27SDimitry Andric llvm_unreachable("register isn't live"); 368*06c3fb27SDimitry Andric CurPressure.inc(MO.getReg(), It->second, LaneBitmask::getNone(), *MRI); 369*06c3fb27SDimitry Andric LiveRegs.erase(It); 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric MaxPressure = max(MaxPressure, CurPressure); 3740b57cec5SDimitry Andric 375bdd1243dSDimitry Andric LastTrackedMI = nullptr; 376bdd1243dSDimitry Andric 377bdd1243dSDimitry Andric return NextMI == MBBEnd; 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric void GCNDownwardRPTracker::advanceToNext() { 3810b57cec5SDimitry Andric LastTrackedMI = &*NextMI++; 382fe6060f1SDimitry Andric NextMI = skipDebugInstructionsForward(NextMI, MBBEnd); 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric // Add new registers or mask bits. 385*06c3fb27SDimitry Andric for (const auto &MO : LastTrackedMI->all_defs()) { 3868bcb0991SDimitry Andric Register Reg = MO.getReg(); 387e8d8bef9SDimitry Andric if (!Reg.isVirtual()) 3880b57cec5SDimitry Andric continue; 3890b57cec5SDimitry Andric auto &LiveMask = LiveRegs[Reg]; 3900b57cec5SDimitry Andric auto PrevMask = LiveMask; 3910b57cec5SDimitry Andric LiveMask |= getDefRegMask(MO, *MRI); 3920b57cec5SDimitry Andric CurPressure.inc(Reg, PrevMask, LiveMask, *MRI); 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric MaxPressure = max(MaxPressure, CurPressure); 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance() { 399bdd1243dSDimitry Andric if (NextMI == MBBEnd) 4000b57cec5SDimitry Andric return false; 401bdd1243dSDimitry Andric advanceBeforeNext(); 4020b57cec5SDimitry Andric advanceToNext(); 4030b57cec5SDimitry Andric return true; 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) { 4070b57cec5SDimitry Andric while (NextMI != End) 4080b57cec5SDimitry Andric if (!advance()) return false; 4090b57cec5SDimitry Andric return true; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin, 4130b57cec5SDimitry Andric MachineBasicBlock::const_iterator End, 4140b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) { 4150b57cec5SDimitry Andric reset(*Begin, LiveRegsCopy); 4160b57cec5SDimitry Andric return advance(End); 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 4200b57cec5SDimitry Andric LLVM_DUMP_METHOD 421bdd1243dSDimitry Andric Printable llvm::reportMismatch(const GCNRPTracker::LiveRegSet &LISLR, 4220b57cec5SDimitry Andric const GCNRPTracker::LiveRegSet &TrackedLR, 4230b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 424bdd1243dSDimitry Andric return Printable([&LISLR, &TrackedLR, TRI](raw_ostream &OS) { 4250b57cec5SDimitry Andric for (auto const &P : TrackedLR) { 4260b57cec5SDimitry Andric auto I = LISLR.find(P.first); 4270b57cec5SDimitry Andric if (I == LISLR.end()) { 428bdd1243dSDimitry Andric OS << " " << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second) 4290b57cec5SDimitry Andric << " isn't found in LIS reported set\n"; 430bdd1243dSDimitry Andric } else if (I->second != P.second) { 431bdd1243dSDimitry Andric OS << " " << printReg(P.first, TRI) 432bdd1243dSDimitry Andric << " masks doesn't match: LIS reported " << PrintLaneMask(I->second) 433bdd1243dSDimitry Andric << ", tracked " << PrintLaneMask(P.second) << '\n'; 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric } 4360b57cec5SDimitry Andric for (auto const &P : LISLR) { 4370b57cec5SDimitry Andric auto I = TrackedLR.find(P.first); 4380b57cec5SDimitry Andric if (I == TrackedLR.end()) { 439bdd1243dSDimitry Andric OS << " " << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second) 4400b57cec5SDimitry Andric << " isn't found in tracked set\n"; 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric } 443bdd1243dSDimitry Andric }); 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric bool GCNUpwardRPTracker::isValid() const { 4470b57cec5SDimitry Andric const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex(); 4480b57cec5SDimitry Andric const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI); 4490b57cec5SDimitry Andric const auto &TrackedLR = LiveRegs; 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric if (!isEqual(LISLR, TrackedLR)) { 4520b57cec5SDimitry Andric dbgs() << "\nGCNUpwardRPTracker error: Tracked and" 453bdd1243dSDimitry Andric " LIS reported livesets mismatch:\n" 454bdd1243dSDimitry Andric << print(LISLR, *MRI); 4550b57cec5SDimitry Andric reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo()); 4560b57cec5SDimitry Andric return false; 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric auto LISPressure = getRegPressure(*MRI, LISLR); 4600b57cec5SDimitry Andric if (LISPressure != CurPressure) { 461bdd1243dSDimitry Andric dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: " 462bdd1243dSDimitry Andric << print(CurPressure) << "LIS rpt: " << print(LISPressure); 4630b57cec5SDimitry Andric return false; 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric return true; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 468bdd1243dSDimitry Andric LLVM_DUMP_METHOD 469bdd1243dSDimitry Andric Printable llvm::print(const GCNRPTracker::LiveRegSet &LiveRegs, 4700b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 471bdd1243dSDimitry Andric return Printable([&LiveRegs, &MRI](raw_ostream &OS) { 4720b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); 4730b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { 47404eeddc0SDimitry Andric Register Reg = Register::index2VirtReg(I); 4750b57cec5SDimitry Andric auto It = LiveRegs.find(Reg); 4760b57cec5SDimitry Andric if (It != LiveRegs.end() && It->second.any()) 4770b57cec5SDimitry Andric OS << ' ' << printVRegOrUnit(Reg, TRI) << ':' 4780b57cec5SDimitry Andric << PrintLaneMask(It->second); 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric OS << '\n'; 481bdd1243dSDimitry Andric }); 4820b57cec5SDimitry Andric } 483bdd1243dSDimitry Andric 484bdd1243dSDimitry Andric LLVM_DUMP_METHOD 485bdd1243dSDimitry Andric void GCNRegPressure::dump() const { dbgs() << print(*this); } 486bdd1243dSDimitry Andric 4870b57cec5SDimitry Andric #endif 488