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