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 138*bdd1243dSDimitry Andric Printable llvm::print(const GCNRegPressure &RP, const GCNSubtarget *ST) { 139*bdd1243dSDimitry Andric return Printable([&RP, ST](raw_ostream &OS) { 140*bdd1243dSDimitry Andric OS << "VGPRs: " << RP.Value[GCNRegPressure::VGPR32] << ' ' 141*bdd1243dSDimitry Andric << "AGPRs: " << RP.getAGPRNum(); 142*bdd1243dSDimitry Andric if (ST) 143*bdd1243dSDimitry Andric OS << "(O" 144*bdd1243dSDimitry Andric << ST->getOccupancyWithNumVGPRs(RP.getVGPRNum(ST->hasGFX90AInsts())) 145fe6060f1SDimitry Andric << ')'; 146*bdd1243dSDimitry Andric OS << ", SGPRs: " << RP.getSGPRNum(); 147*bdd1243dSDimitry Andric if (ST) 148*bdd1243dSDimitry Andric OS << "(O" << ST->getOccupancyWithNumSGPRs(RP.getSGPRNum()) << ')'; 149*bdd1243dSDimitry Andric OS << ", LVGPR WT: " << RP.getVGPRTuplesWeight() 150*bdd1243dSDimitry Andric << ", LSGPR WT: " << RP.getSGPRTuplesWeight(); 151*bdd1243dSDimitry Andric if (ST) 152*bdd1243dSDimitry Andric OS << " -> Occ: " << RP.getOccupancy(*ST); 1530b57cec5SDimitry Andric OS << '\n'; 154*bdd1243dSDimitry 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 2895ffd83dbSDimitry Andric for (const auto &MO : MI.operands()) { 290e8d8bef9SDimitry Andric if (!MO.isReg() || !MO.isDef() || !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"); 328*bdd1243dSDimitry Andric if (!LastTrackedMI) 329*bdd1243dSDimitry Andric return NextMI == MBBEnd; 3300b57cec5SDimitry Andric 331*bdd1243dSDimitry Andric assert(NextMI == MBBEnd || !NextMI->isDebugInstr()); 3320b57cec5SDimitry Andric 333*bdd1243dSDimitry Andric SlotIndex SI = NextMI == MBBEnd 334*bdd1243dSDimitry Andric ? LIS.getInstructionIndex(*LastTrackedMI).getDeadSlot() 335*bdd1243dSDimitry Andric : LIS.getInstructionIndex(*NextMI).getBaseIndex(); 3360b57cec5SDimitry Andric assert(SI.isValid()); 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric // Remove dead registers or mask bits. 3390b57cec5SDimitry Andric for (auto &It : LiveRegs) { 3400b57cec5SDimitry Andric const LiveInterval &LI = LIS.getInterval(It.first); 3410b57cec5SDimitry Andric if (LI.hasSubRanges()) { 3420b57cec5SDimitry Andric for (const auto &S : LI.subranges()) { 3430b57cec5SDimitry Andric if (!S.liveAt(SI)) { 3440b57cec5SDimitry Andric auto PrevMask = It.second; 3450b57cec5SDimitry Andric It.second &= ~S.LaneMask; 3460b57cec5SDimitry Andric CurPressure.inc(It.first, PrevMask, It.second, *MRI); 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric } else if (!LI.liveAt(SI)) { 3500b57cec5SDimitry Andric auto PrevMask = It.second; 3510b57cec5SDimitry Andric It.second = LaneBitmask::getNone(); 3520b57cec5SDimitry Andric CurPressure.inc(It.first, PrevMask, It.second, *MRI); 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric if (It.second.none()) 3550b57cec5SDimitry Andric LiveRegs.erase(It.first); 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric MaxPressure = max(MaxPressure, CurPressure); 3590b57cec5SDimitry Andric 360*bdd1243dSDimitry Andric LastTrackedMI = nullptr; 361*bdd1243dSDimitry Andric 362*bdd1243dSDimitry Andric return NextMI == MBBEnd; 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric void GCNDownwardRPTracker::advanceToNext() { 3660b57cec5SDimitry Andric LastTrackedMI = &*NextMI++; 367fe6060f1SDimitry Andric NextMI = skipDebugInstructionsForward(NextMI, MBBEnd); 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric // Add new registers or mask bits. 3705ffd83dbSDimitry Andric for (const auto &MO : LastTrackedMI->operands()) { 3715ffd83dbSDimitry Andric if (!MO.isReg() || !MO.isDef()) 3720b57cec5SDimitry Andric continue; 3738bcb0991SDimitry Andric Register Reg = MO.getReg(); 374e8d8bef9SDimitry Andric if (!Reg.isVirtual()) 3750b57cec5SDimitry Andric continue; 3760b57cec5SDimitry Andric auto &LiveMask = LiveRegs[Reg]; 3770b57cec5SDimitry Andric auto PrevMask = LiveMask; 3780b57cec5SDimitry Andric LiveMask |= getDefRegMask(MO, *MRI); 3790b57cec5SDimitry Andric CurPressure.inc(Reg, PrevMask, LiveMask, *MRI); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric MaxPressure = max(MaxPressure, CurPressure); 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance() { 386*bdd1243dSDimitry Andric if (NextMI == MBBEnd) 3870b57cec5SDimitry Andric return false; 388*bdd1243dSDimitry Andric advanceBeforeNext(); 3890b57cec5SDimitry Andric advanceToNext(); 3900b57cec5SDimitry Andric return true; 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) { 3940b57cec5SDimitry Andric while (NextMI != End) 3950b57cec5SDimitry Andric if (!advance()) return false; 3960b57cec5SDimitry Andric return true; 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin, 4000b57cec5SDimitry Andric MachineBasicBlock::const_iterator End, 4010b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) { 4020b57cec5SDimitry Andric reset(*Begin, LiveRegsCopy); 4030b57cec5SDimitry Andric return advance(End); 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 4070b57cec5SDimitry Andric LLVM_DUMP_METHOD 408*bdd1243dSDimitry Andric Printable llvm::reportMismatch(const GCNRPTracker::LiveRegSet &LISLR, 4090b57cec5SDimitry Andric const GCNRPTracker::LiveRegSet &TrackedLR, 4100b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 411*bdd1243dSDimitry Andric return Printable([&LISLR, &TrackedLR, TRI](raw_ostream &OS) { 4120b57cec5SDimitry Andric for (auto const &P : TrackedLR) { 4130b57cec5SDimitry Andric auto I = LISLR.find(P.first); 4140b57cec5SDimitry Andric if (I == LISLR.end()) { 415*bdd1243dSDimitry Andric OS << " " << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second) 4160b57cec5SDimitry Andric << " isn't found in LIS reported set\n"; 417*bdd1243dSDimitry Andric } else if (I->second != P.second) { 418*bdd1243dSDimitry Andric OS << " " << printReg(P.first, TRI) 419*bdd1243dSDimitry Andric << " masks doesn't match: LIS reported " << PrintLaneMask(I->second) 420*bdd1243dSDimitry Andric << ", tracked " << PrintLaneMask(P.second) << '\n'; 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric for (auto const &P : LISLR) { 4240b57cec5SDimitry Andric auto I = TrackedLR.find(P.first); 4250b57cec5SDimitry Andric if (I == TrackedLR.end()) { 426*bdd1243dSDimitry Andric OS << " " << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second) 4270b57cec5SDimitry Andric << " isn't found in tracked set\n"; 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric } 430*bdd1243dSDimitry Andric }); 4310b57cec5SDimitry Andric } 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric bool GCNUpwardRPTracker::isValid() const { 4340b57cec5SDimitry Andric const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex(); 4350b57cec5SDimitry Andric const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI); 4360b57cec5SDimitry Andric const auto &TrackedLR = LiveRegs; 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric if (!isEqual(LISLR, TrackedLR)) { 4390b57cec5SDimitry Andric dbgs() << "\nGCNUpwardRPTracker error: Tracked and" 440*bdd1243dSDimitry Andric " LIS reported livesets mismatch:\n" 441*bdd1243dSDimitry Andric << print(LISLR, *MRI); 4420b57cec5SDimitry Andric reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo()); 4430b57cec5SDimitry Andric return false; 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric auto LISPressure = getRegPressure(*MRI, LISLR); 4470b57cec5SDimitry Andric if (LISPressure != CurPressure) { 448*bdd1243dSDimitry Andric dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: " 449*bdd1243dSDimitry Andric << print(CurPressure) << "LIS rpt: " << print(LISPressure); 4500b57cec5SDimitry Andric return false; 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric return true; 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric 455*bdd1243dSDimitry Andric LLVM_DUMP_METHOD 456*bdd1243dSDimitry Andric Printable llvm::print(const GCNRPTracker::LiveRegSet &LiveRegs, 4570b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 458*bdd1243dSDimitry Andric return Printable([&LiveRegs, &MRI](raw_ostream &OS) { 4590b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); 4600b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { 46104eeddc0SDimitry Andric Register Reg = Register::index2VirtReg(I); 4620b57cec5SDimitry Andric auto It = LiveRegs.find(Reg); 4630b57cec5SDimitry Andric if (It != LiveRegs.end() && It->second.any()) 4640b57cec5SDimitry Andric OS << ' ' << printVRegOrUnit(Reg, TRI) << ':' 4650b57cec5SDimitry Andric << PrintLaneMask(It->second); 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric OS << '\n'; 468*bdd1243dSDimitry Andric }); 4690b57cec5SDimitry Andric } 470*bdd1243dSDimitry Andric 471*bdd1243dSDimitry Andric LLVM_DUMP_METHOD 472*bdd1243dSDimitry Andric void GCNRegPressure::dump() const { dbgs() << print(*this); } 473*bdd1243dSDimitry Andric 4740b57cec5SDimitry Andric #endif 475