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) { 308bcb0991SDimitry Andric const unsigned 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 72*e8d8bef9SDimitry Andric unsigned GCNRegPressure::getRegKind(Register Reg, 730b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 74*e8d8bef9SDimitry Andric assert(Reg.isVirtual()); 750b57cec5SDimitry Andric const auto RC = MRI.getRegClass(Reg); 760b57cec5SDimitry Andric auto STI = static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo()); 770b57cec5SDimitry Andric return STI->isSGPRClass(RC) ? 780b57cec5SDimitry Andric (STI->getRegSizeInBits(*RC) == 32 ? SGPR32 : SGPR_TUPLE) : 790b57cec5SDimitry Andric STI->hasAGPRs(RC) ? 800b57cec5SDimitry Andric (STI->getRegSizeInBits(*RC) == 32 ? AGPR32 : AGPR_TUPLE) : 810b57cec5SDimitry 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())); 1280b57cec5SDimitry Andric const auto VGPROcc = std::min(MaxOccupancy, 1290b57cec5SDimitry Andric ST.getOccupancyWithNumVGPRs(getVGPRNum())); 1300b57cec5SDimitry Andric const auto OtherSGPROcc = std::min(MaxOccupancy, 1310b57cec5SDimitry Andric ST.getOccupancyWithNumSGPRs(O.getSGPRNum())); 1320b57cec5SDimitry Andric const auto OtherVGPROcc = std::min(MaxOccupancy, 1330b57cec5SDimitry Andric ST.getOccupancyWithNumVGPRs(O.getVGPRNum())); 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric const auto Occ = std::min(SGPROcc, VGPROcc); 1360b57cec5SDimitry Andric const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc); 1370b57cec5SDimitry Andric if (Occ != OtherOcc) 1380b57cec5SDimitry Andric return Occ > OtherOcc; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric bool SGPRImportant = SGPROcc < VGPROcc; 1410b57cec5SDimitry Andric const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric // if both pressures disagree on what is more important compare vgprs 1440b57cec5SDimitry Andric if (SGPRImportant != OtherSGPRImportant) { 1450b57cec5SDimitry Andric SGPRImportant = false; 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric // compare large regs pressure 1490b57cec5SDimitry Andric bool SGPRFirst = SGPRImportant; 1500b57cec5SDimitry Andric for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) { 1510b57cec5SDimitry Andric if (SGPRFirst) { 1520b57cec5SDimitry Andric auto SW = getSGPRTuplesWeight(); 1530b57cec5SDimitry Andric auto OtherSW = O.getSGPRTuplesWeight(); 1540b57cec5SDimitry Andric if (SW != OtherSW) 1550b57cec5SDimitry Andric return SW < OtherSW; 1560b57cec5SDimitry Andric } else { 1570b57cec5SDimitry Andric auto VW = getVGPRTuplesWeight(); 1580b57cec5SDimitry Andric auto OtherVW = O.getVGPRTuplesWeight(); 1590b57cec5SDimitry Andric if (VW != OtherVW) 1600b57cec5SDimitry Andric return VW < OtherVW; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()): 1640b57cec5SDimitry Andric (getVGPRNum() < O.getVGPRNum()); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1680b57cec5SDimitry Andric LLVM_DUMP_METHOD 1690b57cec5SDimitry Andric void GCNRegPressure::print(raw_ostream &OS, const GCNSubtarget *ST) const { 1708bcb0991SDimitry Andric OS << "VGPRs: " << Value[VGPR32] << ' '; 1718bcb0991SDimitry Andric OS << "AGPRs: " << Value[AGPR32]; 1720b57cec5SDimitry Andric if (ST) OS << "(O" << ST->getOccupancyWithNumVGPRs(getVGPRNum()) << ')'; 1730b57cec5SDimitry Andric OS << ", SGPRs: " << getSGPRNum(); 1740b57cec5SDimitry Andric if (ST) OS << "(O" << ST->getOccupancyWithNumSGPRs(getSGPRNum()) << ')'; 1750b57cec5SDimitry Andric OS << ", LVGPR WT: " << getVGPRTuplesWeight() 1760b57cec5SDimitry Andric << ", LSGPR WT: " << getSGPRTuplesWeight(); 1770b57cec5SDimitry Andric if (ST) OS << " -> Occ: " << getOccupancy(*ST); 1780b57cec5SDimitry Andric OS << '\n'; 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric #endif 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric static LaneBitmask getDefRegMask(const MachineOperand &MO, 1830b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 184*e8d8bef9SDimitry Andric assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual()); 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric // We don't rely on read-undef flag because in case of tentative schedule 1870b57cec5SDimitry Andric // tracking it isn't set correctly yet. This works correctly however since 1880b57cec5SDimitry Andric // use mask has been tracked before using LIS. 1890b57cec5SDimitry Andric return MO.getSubReg() == 0 ? 1900b57cec5SDimitry Andric MRI.getMaxLaneMaskForVReg(MO.getReg()) : 1910b57cec5SDimitry Andric MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg()); 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric static LaneBitmask getUsedRegMask(const MachineOperand &MO, 1950b57cec5SDimitry Andric const MachineRegisterInfo &MRI, 1960b57cec5SDimitry Andric const LiveIntervals &LIS) { 197*e8d8bef9SDimitry Andric assert(MO.isUse() && MO.isReg() && MO.getReg().isVirtual()); 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric if (auto SubReg = MO.getSubReg()) 2000b57cec5SDimitry Andric return MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg); 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric auto MaxMask = MRI.getMaxLaneMaskForVReg(MO.getReg()); 2035ffd83dbSDimitry Andric if (SIRegisterInfo::getNumCoveredRegs(MaxMask) > 1) // cannot have subregs 2040b57cec5SDimitry Andric return MaxMask; 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric // For a tentative schedule LIS isn't updated yet but livemask should remain 2070b57cec5SDimitry Andric // the same on any schedule. Subreg defs can be reordered but they all must 2080b57cec5SDimitry Andric // dominate uses anyway. 2090b57cec5SDimitry Andric auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex(); 2100b57cec5SDimitry Andric return getLiveLaneMask(MO.getReg(), SI, LIS, MRI); 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric static SmallVector<RegisterMaskPair, 8> 2140b57cec5SDimitry Andric collectVirtualRegUses(const MachineInstr &MI, const LiveIntervals &LIS, 2150b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 2160b57cec5SDimitry Andric SmallVector<RegisterMaskPair, 8> Res; 2170b57cec5SDimitry Andric for (const auto &MO : MI.operands()) { 218*e8d8bef9SDimitry Andric if (!MO.isReg() || !MO.getReg().isVirtual()) 2190b57cec5SDimitry Andric continue; 2200b57cec5SDimitry Andric if (!MO.isUse() || !MO.readsReg()) 2210b57cec5SDimitry Andric continue; 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric auto const UsedMask = getUsedRegMask(MO, MRI, LIS); 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric auto Reg = MO.getReg(); 226*e8d8bef9SDimitry Andric auto I = llvm::find_if( 227*e8d8bef9SDimitry Andric Res, [Reg](const RegisterMaskPair &RM) { return RM.RegUnit == Reg; }); 2280b57cec5SDimitry Andric if (I != Res.end()) 2290b57cec5SDimitry Andric I->LaneMask |= UsedMask; 2300b57cec5SDimitry Andric else 2310b57cec5SDimitry Andric Res.push_back(RegisterMaskPair(Reg, UsedMask)); 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric return Res; 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 2370b57cec5SDimitry Andric // GCNRPTracker 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric LaneBitmask llvm::getLiveLaneMask(unsigned Reg, 2400b57cec5SDimitry Andric SlotIndex SI, 2410b57cec5SDimitry Andric const LiveIntervals &LIS, 2420b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 2430b57cec5SDimitry Andric LaneBitmask LiveMask; 2440b57cec5SDimitry Andric const auto &LI = LIS.getInterval(Reg); 2450b57cec5SDimitry Andric if (LI.hasSubRanges()) { 2460b57cec5SDimitry Andric for (const auto &S : LI.subranges()) 2470b57cec5SDimitry Andric if (S.liveAt(SI)) { 2480b57cec5SDimitry Andric LiveMask |= S.LaneMask; 2490b57cec5SDimitry Andric assert(LiveMask < MRI.getMaxLaneMaskForVReg(Reg) || 2500b57cec5SDimitry Andric LiveMask == MRI.getMaxLaneMaskForVReg(Reg)); 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric } else if (LI.liveAt(SI)) { 2530b57cec5SDimitry Andric LiveMask = MRI.getMaxLaneMaskForVReg(Reg); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric return LiveMask; 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI, 2590b57cec5SDimitry Andric const LiveIntervals &LIS, 2600b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 2610b57cec5SDimitry Andric GCNRPTracker::LiveRegSet LiveRegs; 2620b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { 2638bcb0991SDimitry Andric auto Reg = Register::index2VirtReg(I); 2640b57cec5SDimitry Andric if (!LIS.hasInterval(Reg)) 2650b57cec5SDimitry Andric continue; 2660b57cec5SDimitry Andric auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI); 2670b57cec5SDimitry Andric if (LiveMask.any()) 2680b57cec5SDimitry Andric LiveRegs[Reg] = LiveMask; 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric return LiveRegs; 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric void GCNRPTracker::reset(const MachineInstr &MI, 2740b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy, 2750b57cec5SDimitry Andric bool After) { 2760b57cec5SDimitry Andric const MachineFunction &MF = *MI.getMF(); 2770b57cec5SDimitry Andric MRI = &MF.getRegInfo(); 2780b57cec5SDimitry Andric if (LiveRegsCopy) { 2790b57cec5SDimitry Andric if (&LiveRegs != LiveRegsCopy) 2800b57cec5SDimitry Andric LiveRegs = *LiveRegsCopy; 2810b57cec5SDimitry Andric } else { 2820b57cec5SDimitry Andric LiveRegs = After ? getLiveRegsAfter(MI, LIS) 2830b57cec5SDimitry Andric : getLiveRegsBefore(MI, LIS); 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs); 2870b57cec5SDimitry Andric } 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric void GCNUpwardRPTracker::reset(const MachineInstr &MI, 2900b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) { 2910b57cec5SDimitry Andric GCNRPTracker::reset(MI, LiveRegsCopy, true); 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric void GCNUpwardRPTracker::recede(const MachineInstr &MI) { 2950b57cec5SDimitry Andric assert(MRI && "call reset first"); 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric LastTrackedMI = &MI; 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric if (MI.isDebugInstr()) 3000b57cec5SDimitry Andric return; 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric auto const RegUses = collectVirtualRegUses(MI, LIS, *MRI); 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric // calc pressure at the MI (defs + uses) 3050b57cec5SDimitry Andric auto AtMIPressure = CurPressure; 3060b57cec5SDimitry Andric for (const auto &U : RegUses) { 3070b57cec5SDimitry Andric auto LiveMask = LiveRegs[U.RegUnit]; 3080b57cec5SDimitry Andric AtMIPressure.inc(U.RegUnit, LiveMask, LiveMask | U.LaneMask, *MRI); 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric // update max pressure 3110b57cec5SDimitry Andric MaxPressure = max(AtMIPressure, MaxPressure); 3120b57cec5SDimitry Andric 3135ffd83dbSDimitry Andric for (const auto &MO : MI.operands()) { 314*e8d8bef9SDimitry Andric if (!MO.isReg() || !MO.isDef() || !MO.getReg().isVirtual() || MO.isDead()) 3150b57cec5SDimitry Andric continue; 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric auto Reg = MO.getReg(); 3180b57cec5SDimitry Andric auto I = LiveRegs.find(Reg); 3190b57cec5SDimitry Andric if (I == LiveRegs.end()) 3200b57cec5SDimitry Andric continue; 3210b57cec5SDimitry Andric auto &LiveMask = I->second; 3220b57cec5SDimitry Andric auto PrevMask = LiveMask; 3230b57cec5SDimitry Andric LiveMask &= ~getDefRegMask(MO, *MRI); 3240b57cec5SDimitry Andric CurPressure.inc(Reg, PrevMask, LiveMask, *MRI); 3250b57cec5SDimitry Andric if (LiveMask.none()) 3260b57cec5SDimitry Andric LiveRegs.erase(I); 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric for (const auto &U : RegUses) { 3290b57cec5SDimitry Andric auto &LiveMask = LiveRegs[U.RegUnit]; 3300b57cec5SDimitry Andric auto PrevMask = LiveMask; 3310b57cec5SDimitry Andric LiveMask |= U.LaneMask; 3320b57cec5SDimitry Andric CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI); 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric assert(CurPressure == getRegPressure(*MRI, LiveRegs)); 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric bool GCNDownwardRPTracker::reset(const MachineInstr &MI, 3380b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) { 3390b57cec5SDimitry Andric MRI = &MI.getParent()->getParent()->getRegInfo(); 3400b57cec5SDimitry Andric LastTrackedMI = nullptr; 3410b57cec5SDimitry Andric MBBEnd = MI.getParent()->end(); 3420b57cec5SDimitry Andric NextMI = &MI; 3430b57cec5SDimitry Andric NextMI = skipDebugInstructionsForward(NextMI, MBBEnd); 3440b57cec5SDimitry Andric if (NextMI == MBBEnd) 3450b57cec5SDimitry Andric return false; 3460b57cec5SDimitry Andric GCNRPTracker::reset(*NextMI, LiveRegsCopy, false); 3470b57cec5SDimitry Andric return true; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric bool GCNDownwardRPTracker::advanceBeforeNext() { 3510b57cec5SDimitry Andric assert(MRI && "call reset first"); 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric NextMI = skipDebugInstructionsForward(NextMI, MBBEnd); 3540b57cec5SDimitry Andric if (NextMI == MBBEnd) 3550b57cec5SDimitry Andric return false; 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric SlotIndex SI = LIS.getInstructionIndex(*NextMI).getBaseIndex(); 3580b57cec5SDimitry Andric assert(SI.isValid()); 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric // Remove dead registers or mask bits. 3610b57cec5SDimitry Andric for (auto &It : LiveRegs) { 3620b57cec5SDimitry Andric const LiveInterval &LI = LIS.getInterval(It.first); 3630b57cec5SDimitry Andric if (LI.hasSubRanges()) { 3640b57cec5SDimitry Andric for (const auto &S : LI.subranges()) { 3650b57cec5SDimitry Andric if (!S.liveAt(SI)) { 3660b57cec5SDimitry Andric auto PrevMask = It.second; 3670b57cec5SDimitry Andric It.second &= ~S.LaneMask; 3680b57cec5SDimitry Andric CurPressure.inc(It.first, PrevMask, It.second, *MRI); 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric } else if (!LI.liveAt(SI)) { 3720b57cec5SDimitry Andric auto PrevMask = It.second; 3730b57cec5SDimitry Andric It.second = LaneBitmask::getNone(); 3740b57cec5SDimitry Andric CurPressure.inc(It.first, PrevMask, It.second, *MRI); 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric if (It.second.none()) 3770b57cec5SDimitry Andric LiveRegs.erase(It.first); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric MaxPressure = max(MaxPressure, CurPressure); 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric return true; 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric void GCNDownwardRPTracker::advanceToNext() { 3860b57cec5SDimitry Andric LastTrackedMI = &*NextMI++; 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric // Add new registers or mask bits. 3895ffd83dbSDimitry Andric for (const auto &MO : LastTrackedMI->operands()) { 3905ffd83dbSDimitry Andric if (!MO.isReg() || !MO.isDef()) 3910b57cec5SDimitry Andric continue; 3928bcb0991SDimitry Andric Register Reg = MO.getReg(); 393*e8d8bef9SDimitry Andric if (!Reg.isVirtual()) 3940b57cec5SDimitry Andric continue; 3950b57cec5SDimitry Andric auto &LiveMask = LiveRegs[Reg]; 3960b57cec5SDimitry Andric auto PrevMask = LiveMask; 3970b57cec5SDimitry Andric LiveMask |= getDefRegMask(MO, *MRI); 3980b57cec5SDimitry Andric CurPressure.inc(Reg, PrevMask, LiveMask, *MRI); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric MaxPressure = max(MaxPressure, CurPressure); 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance() { 4050b57cec5SDimitry Andric // If we have just called reset live set is actual. 4060b57cec5SDimitry Andric if ((NextMI == MBBEnd) || (LastTrackedMI && !advanceBeforeNext())) 4070b57cec5SDimitry Andric return false; 4080b57cec5SDimitry Andric advanceToNext(); 4090b57cec5SDimitry Andric return true; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) { 4130b57cec5SDimitry Andric while (NextMI != End) 4140b57cec5SDimitry Andric if (!advance()) return false; 4150b57cec5SDimitry Andric return true; 4160b57cec5SDimitry Andric } 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin, 4190b57cec5SDimitry Andric MachineBasicBlock::const_iterator End, 4200b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) { 4210b57cec5SDimitry Andric reset(*Begin, LiveRegsCopy); 4220b57cec5SDimitry Andric return advance(End); 4230b57cec5SDimitry Andric } 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 4260b57cec5SDimitry Andric LLVM_DUMP_METHOD 4270b57cec5SDimitry Andric static void reportMismatch(const GCNRPTracker::LiveRegSet &LISLR, 4280b57cec5SDimitry Andric const GCNRPTracker::LiveRegSet &TrackedLR, 4290b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 4300b57cec5SDimitry Andric for (auto const &P : TrackedLR) { 4310b57cec5SDimitry Andric auto I = LISLR.find(P.first); 4320b57cec5SDimitry Andric if (I == LISLR.end()) { 4330b57cec5SDimitry Andric dbgs() << " " << printReg(P.first, TRI) 4340b57cec5SDimitry Andric << ":L" << PrintLaneMask(P.second) 4350b57cec5SDimitry Andric << " isn't found in LIS reported set\n"; 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric else if (I->second != P.second) { 4380b57cec5SDimitry Andric dbgs() << " " << printReg(P.first, TRI) 4390b57cec5SDimitry Andric << " masks doesn't match: LIS reported " 4400b57cec5SDimitry Andric << PrintLaneMask(I->second) 4410b57cec5SDimitry Andric << ", tracked " 4420b57cec5SDimitry Andric << PrintLaneMask(P.second) 4430b57cec5SDimitry Andric << '\n'; 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric for (auto const &P : LISLR) { 4470b57cec5SDimitry Andric auto I = TrackedLR.find(P.first); 4480b57cec5SDimitry Andric if (I == TrackedLR.end()) { 4490b57cec5SDimitry Andric dbgs() << " " << printReg(P.first, TRI) 4500b57cec5SDimitry Andric << ":L" << PrintLaneMask(P.second) 4510b57cec5SDimitry Andric << " isn't found in tracked set\n"; 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric bool GCNUpwardRPTracker::isValid() const { 4570b57cec5SDimitry Andric const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex(); 4580b57cec5SDimitry Andric const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI); 4590b57cec5SDimitry Andric const auto &TrackedLR = LiveRegs; 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric if (!isEqual(LISLR, TrackedLR)) { 4620b57cec5SDimitry Andric dbgs() << "\nGCNUpwardRPTracker error: Tracked and" 4630b57cec5SDimitry Andric " LIS reported livesets mismatch:\n"; 4640b57cec5SDimitry Andric printLivesAt(SI, LIS, *MRI); 4650b57cec5SDimitry Andric reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo()); 4660b57cec5SDimitry Andric return false; 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric auto LISPressure = getRegPressure(*MRI, LISLR); 4700b57cec5SDimitry Andric if (LISPressure != CurPressure) { 4710b57cec5SDimitry Andric dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: "; 4720b57cec5SDimitry Andric CurPressure.print(dbgs()); 4730b57cec5SDimitry Andric dbgs() << "LIS rpt: "; 4740b57cec5SDimitry Andric LISPressure.print(dbgs()); 4750b57cec5SDimitry Andric return false; 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric return true; 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric void GCNRPTracker::printLiveRegs(raw_ostream &OS, const LiveRegSet& LiveRegs, 4810b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 4820b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); 4830b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { 4848bcb0991SDimitry Andric unsigned Reg = Register::index2VirtReg(I); 4850b57cec5SDimitry Andric auto It = LiveRegs.find(Reg); 4860b57cec5SDimitry Andric if (It != LiveRegs.end() && It->second.any()) 4870b57cec5SDimitry Andric OS << ' ' << printVRegOrUnit(Reg, TRI) << ':' 4880b57cec5SDimitry Andric << PrintLaneMask(It->second); 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric OS << '\n'; 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric #endif 493