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