1*0b57cec5SDimitry Andric //===- GCNRegPressure.cpp -------------------------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "GCNRegPressure.h" 10*0b57cec5SDimitry Andric #include "AMDGPUSubtarget.h" 11*0b57cec5SDimitry Andric #include "SIRegisterInfo.h" 12*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 13*0b57cec5SDimitry Andric #include "llvm/CodeGen/LiveInterval.h" 14*0b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h" 15*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 16*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 17*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 18*0b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterPressure.h" 19*0b57cec5SDimitry Andric #include "llvm/CodeGen/SlotIndexes.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 21*0b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 22*0b57cec5SDimitry Andric #include "llvm/MC/LaneBitmask.h" 23*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 24*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 25*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 26*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 27*0b57cec5SDimitry Andric #include <algorithm> 28*0b57cec5SDimitry Andric #include <cassert> 29*0b57cec5SDimitry Andric 30*0b57cec5SDimitry Andric using namespace llvm; 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric #define DEBUG_TYPE "machine-scheduler" 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 35*0b57cec5SDimitry Andric LLVM_DUMP_METHOD 36*0b57cec5SDimitry Andric void llvm::printLivesAt(SlotIndex SI, 37*0b57cec5SDimitry Andric const LiveIntervals &LIS, 38*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 39*0b57cec5SDimitry Andric dbgs() << "Live regs at " << SI << ": " 40*0b57cec5SDimitry Andric << *LIS.getInstructionFromIndex(SI); 41*0b57cec5SDimitry Andric unsigned Num = 0; 42*0b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { 43*0b57cec5SDimitry Andric const unsigned Reg = TargetRegisterInfo::index2VirtReg(I); 44*0b57cec5SDimitry Andric if (!LIS.hasInterval(Reg)) 45*0b57cec5SDimitry Andric continue; 46*0b57cec5SDimitry Andric const auto &LI = LIS.getInterval(Reg); 47*0b57cec5SDimitry Andric if (LI.hasSubRanges()) { 48*0b57cec5SDimitry Andric bool firstTime = true; 49*0b57cec5SDimitry Andric for (const auto &S : LI.subranges()) { 50*0b57cec5SDimitry Andric if (!S.liveAt(SI)) continue; 51*0b57cec5SDimitry Andric if (firstTime) { 52*0b57cec5SDimitry Andric dbgs() << " " << printReg(Reg, MRI.getTargetRegisterInfo()) 53*0b57cec5SDimitry Andric << '\n'; 54*0b57cec5SDimitry Andric firstTime = false; 55*0b57cec5SDimitry Andric } 56*0b57cec5SDimitry Andric dbgs() << " " << S << '\n'; 57*0b57cec5SDimitry Andric ++Num; 58*0b57cec5SDimitry Andric } 59*0b57cec5SDimitry Andric } else if (LI.liveAt(SI)) { 60*0b57cec5SDimitry Andric dbgs() << " " << LI << '\n'; 61*0b57cec5SDimitry Andric ++Num; 62*0b57cec5SDimitry Andric } 63*0b57cec5SDimitry Andric } 64*0b57cec5SDimitry Andric if (!Num) dbgs() << " <none>\n"; 65*0b57cec5SDimitry Andric } 66*0b57cec5SDimitry Andric #endif 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric bool llvm::isEqual(const GCNRPTracker::LiveRegSet &S1, 69*0b57cec5SDimitry Andric const GCNRPTracker::LiveRegSet &S2) { 70*0b57cec5SDimitry Andric if (S1.size() != S2.size()) 71*0b57cec5SDimitry Andric return false; 72*0b57cec5SDimitry Andric 73*0b57cec5SDimitry Andric for (const auto &P : S1) { 74*0b57cec5SDimitry Andric auto I = S2.find(P.first); 75*0b57cec5SDimitry Andric if (I == S2.end() || I->second != P.second) 76*0b57cec5SDimitry Andric return false; 77*0b57cec5SDimitry Andric } 78*0b57cec5SDimitry Andric return true; 79*0b57cec5SDimitry Andric } 80*0b57cec5SDimitry Andric 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 83*0b57cec5SDimitry Andric // GCNRegPressure 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric unsigned GCNRegPressure::getRegKind(unsigned Reg, 86*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 87*0b57cec5SDimitry Andric assert(TargetRegisterInfo::isVirtualRegister(Reg)); 88*0b57cec5SDimitry Andric const auto RC = MRI.getRegClass(Reg); 89*0b57cec5SDimitry Andric auto STI = static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo()); 90*0b57cec5SDimitry Andric return STI->isSGPRClass(RC) ? 91*0b57cec5SDimitry Andric (STI->getRegSizeInBits(*RC) == 32 ? SGPR32 : SGPR_TUPLE) : 92*0b57cec5SDimitry Andric STI->hasAGPRs(RC) ? 93*0b57cec5SDimitry Andric (STI->getRegSizeInBits(*RC) == 32 ? AGPR32 : AGPR_TUPLE) : 94*0b57cec5SDimitry Andric (STI->getRegSizeInBits(*RC) == 32 ? VGPR32 : VGPR_TUPLE); 95*0b57cec5SDimitry Andric } 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric void GCNRegPressure::inc(unsigned Reg, 98*0b57cec5SDimitry Andric LaneBitmask PrevMask, 99*0b57cec5SDimitry Andric LaneBitmask NewMask, 100*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 101*0b57cec5SDimitry Andric if (NewMask == PrevMask) 102*0b57cec5SDimitry Andric return; 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric int Sign = 1; 105*0b57cec5SDimitry Andric if (NewMask < PrevMask) { 106*0b57cec5SDimitry Andric std::swap(NewMask, PrevMask); 107*0b57cec5SDimitry Andric Sign = -1; 108*0b57cec5SDimitry Andric } 109*0b57cec5SDimitry Andric #ifndef NDEBUG 110*0b57cec5SDimitry Andric const auto MaxMask = MRI.getMaxLaneMaskForVReg(Reg); 111*0b57cec5SDimitry Andric #endif 112*0b57cec5SDimitry Andric switch (auto Kind = getRegKind(Reg, MRI)) { 113*0b57cec5SDimitry Andric case SGPR32: 114*0b57cec5SDimitry Andric case VGPR32: 115*0b57cec5SDimitry Andric case AGPR32: 116*0b57cec5SDimitry Andric assert(PrevMask.none() && NewMask == MaxMask); 117*0b57cec5SDimitry Andric Value[Kind] += Sign; 118*0b57cec5SDimitry Andric break; 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric case SGPR_TUPLE: 121*0b57cec5SDimitry Andric case VGPR_TUPLE: 122*0b57cec5SDimitry Andric case AGPR_TUPLE: 123*0b57cec5SDimitry Andric assert(NewMask < MaxMask || NewMask == MaxMask); 124*0b57cec5SDimitry Andric assert(PrevMask < NewMask); 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric Value[Kind == SGPR_TUPLE ? SGPR32 : Kind == AGPR_TUPLE ? AGPR32 : VGPR32] += 127*0b57cec5SDimitry Andric Sign * (~PrevMask & NewMask).getNumLanes(); 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric if (PrevMask.none()) { 130*0b57cec5SDimitry Andric assert(NewMask.any()); 131*0b57cec5SDimitry Andric Value[Kind] += Sign * MRI.getPressureSets(Reg).getWeight(); 132*0b57cec5SDimitry Andric } 133*0b57cec5SDimitry Andric break; 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric default: llvm_unreachable("Unknown register kind"); 136*0b57cec5SDimitry Andric } 137*0b57cec5SDimitry Andric } 138*0b57cec5SDimitry Andric 139*0b57cec5SDimitry Andric bool GCNRegPressure::less(const GCNSubtarget &ST, 140*0b57cec5SDimitry Andric const GCNRegPressure& O, 141*0b57cec5SDimitry Andric unsigned MaxOccupancy) const { 142*0b57cec5SDimitry Andric const auto SGPROcc = std::min(MaxOccupancy, 143*0b57cec5SDimitry Andric ST.getOccupancyWithNumSGPRs(getSGPRNum())); 144*0b57cec5SDimitry Andric const auto VGPROcc = std::min(MaxOccupancy, 145*0b57cec5SDimitry Andric ST.getOccupancyWithNumVGPRs(getVGPRNum())); 146*0b57cec5SDimitry Andric const auto OtherSGPROcc = std::min(MaxOccupancy, 147*0b57cec5SDimitry Andric ST.getOccupancyWithNumSGPRs(O.getSGPRNum())); 148*0b57cec5SDimitry Andric const auto OtherVGPROcc = std::min(MaxOccupancy, 149*0b57cec5SDimitry Andric ST.getOccupancyWithNumVGPRs(O.getVGPRNum())); 150*0b57cec5SDimitry Andric 151*0b57cec5SDimitry Andric const auto Occ = std::min(SGPROcc, VGPROcc); 152*0b57cec5SDimitry Andric const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc); 153*0b57cec5SDimitry Andric if (Occ != OtherOcc) 154*0b57cec5SDimitry Andric return Occ > OtherOcc; 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric bool SGPRImportant = SGPROcc < VGPROcc; 157*0b57cec5SDimitry Andric const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc; 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric // if both pressures disagree on what is more important compare vgprs 160*0b57cec5SDimitry Andric if (SGPRImportant != OtherSGPRImportant) { 161*0b57cec5SDimitry Andric SGPRImportant = false; 162*0b57cec5SDimitry Andric } 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric // compare large regs pressure 165*0b57cec5SDimitry Andric bool SGPRFirst = SGPRImportant; 166*0b57cec5SDimitry Andric for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) { 167*0b57cec5SDimitry Andric if (SGPRFirst) { 168*0b57cec5SDimitry Andric auto SW = getSGPRTuplesWeight(); 169*0b57cec5SDimitry Andric auto OtherSW = O.getSGPRTuplesWeight(); 170*0b57cec5SDimitry Andric if (SW != OtherSW) 171*0b57cec5SDimitry Andric return SW < OtherSW; 172*0b57cec5SDimitry Andric } else { 173*0b57cec5SDimitry Andric auto VW = getVGPRTuplesWeight(); 174*0b57cec5SDimitry Andric auto OtherVW = O.getVGPRTuplesWeight(); 175*0b57cec5SDimitry Andric if (VW != OtherVW) 176*0b57cec5SDimitry Andric return VW < OtherVW; 177*0b57cec5SDimitry Andric } 178*0b57cec5SDimitry Andric } 179*0b57cec5SDimitry Andric return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()): 180*0b57cec5SDimitry Andric (getVGPRNum() < O.getVGPRNum()); 181*0b57cec5SDimitry Andric } 182*0b57cec5SDimitry Andric 183*0b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 184*0b57cec5SDimitry Andric LLVM_DUMP_METHOD 185*0b57cec5SDimitry Andric void GCNRegPressure::print(raw_ostream &OS, const GCNSubtarget *ST) const { 186*0b57cec5SDimitry Andric OS << "VGPRs: " << getVGPRNum(); 187*0b57cec5SDimitry Andric if (ST) OS << "(O" << ST->getOccupancyWithNumVGPRs(getVGPRNum()) << ')'; 188*0b57cec5SDimitry Andric OS << ", SGPRs: " << getSGPRNum(); 189*0b57cec5SDimitry Andric if (ST) OS << "(O" << ST->getOccupancyWithNumSGPRs(getSGPRNum()) << ')'; 190*0b57cec5SDimitry Andric OS << ", LVGPR WT: " << getVGPRTuplesWeight() 191*0b57cec5SDimitry Andric << ", LSGPR WT: " << getSGPRTuplesWeight(); 192*0b57cec5SDimitry Andric if (ST) OS << " -> Occ: " << getOccupancy(*ST); 193*0b57cec5SDimitry Andric OS << '\n'; 194*0b57cec5SDimitry Andric } 195*0b57cec5SDimitry Andric #endif 196*0b57cec5SDimitry Andric 197*0b57cec5SDimitry Andric static LaneBitmask getDefRegMask(const MachineOperand &MO, 198*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 199*0b57cec5SDimitry Andric assert(MO.isDef() && MO.isReg() && 200*0b57cec5SDimitry Andric TargetRegisterInfo::isVirtualRegister(MO.getReg())); 201*0b57cec5SDimitry Andric 202*0b57cec5SDimitry Andric // We don't rely on read-undef flag because in case of tentative schedule 203*0b57cec5SDimitry Andric // tracking it isn't set correctly yet. This works correctly however since 204*0b57cec5SDimitry Andric // use mask has been tracked before using LIS. 205*0b57cec5SDimitry Andric return MO.getSubReg() == 0 ? 206*0b57cec5SDimitry Andric MRI.getMaxLaneMaskForVReg(MO.getReg()) : 207*0b57cec5SDimitry Andric MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg()); 208*0b57cec5SDimitry Andric } 209*0b57cec5SDimitry Andric 210*0b57cec5SDimitry Andric static LaneBitmask getUsedRegMask(const MachineOperand &MO, 211*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI, 212*0b57cec5SDimitry Andric const LiveIntervals &LIS) { 213*0b57cec5SDimitry Andric assert(MO.isUse() && MO.isReg() && 214*0b57cec5SDimitry Andric TargetRegisterInfo::isVirtualRegister(MO.getReg())); 215*0b57cec5SDimitry Andric 216*0b57cec5SDimitry Andric if (auto SubReg = MO.getSubReg()) 217*0b57cec5SDimitry Andric return MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg); 218*0b57cec5SDimitry Andric 219*0b57cec5SDimitry Andric auto MaxMask = MRI.getMaxLaneMaskForVReg(MO.getReg()); 220*0b57cec5SDimitry Andric if (MaxMask == LaneBitmask::getLane(0)) // cannot have subregs 221*0b57cec5SDimitry Andric return MaxMask; 222*0b57cec5SDimitry Andric 223*0b57cec5SDimitry Andric // For a tentative schedule LIS isn't updated yet but livemask should remain 224*0b57cec5SDimitry Andric // the same on any schedule. Subreg defs can be reordered but they all must 225*0b57cec5SDimitry Andric // dominate uses anyway. 226*0b57cec5SDimitry Andric auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex(); 227*0b57cec5SDimitry Andric return getLiveLaneMask(MO.getReg(), SI, LIS, MRI); 228*0b57cec5SDimitry Andric } 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric static SmallVector<RegisterMaskPair, 8> 231*0b57cec5SDimitry Andric collectVirtualRegUses(const MachineInstr &MI, const LiveIntervals &LIS, 232*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 233*0b57cec5SDimitry Andric SmallVector<RegisterMaskPair, 8> Res; 234*0b57cec5SDimitry Andric for (const auto &MO : MI.operands()) { 235*0b57cec5SDimitry Andric if (!MO.isReg() || !TargetRegisterInfo::isVirtualRegister(MO.getReg())) 236*0b57cec5SDimitry Andric continue; 237*0b57cec5SDimitry Andric if (!MO.isUse() || !MO.readsReg()) 238*0b57cec5SDimitry Andric continue; 239*0b57cec5SDimitry Andric 240*0b57cec5SDimitry Andric auto const UsedMask = getUsedRegMask(MO, MRI, LIS); 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric auto Reg = MO.getReg(); 243*0b57cec5SDimitry Andric auto I = std::find_if(Res.begin(), Res.end(), [Reg](const RegisterMaskPair &RM) { 244*0b57cec5SDimitry Andric return RM.RegUnit == Reg; 245*0b57cec5SDimitry Andric }); 246*0b57cec5SDimitry Andric if (I != Res.end()) 247*0b57cec5SDimitry Andric I->LaneMask |= UsedMask; 248*0b57cec5SDimitry Andric else 249*0b57cec5SDimitry Andric Res.push_back(RegisterMaskPair(Reg, UsedMask)); 250*0b57cec5SDimitry Andric } 251*0b57cec5SDimitry Andric return Res; 252*0b57cec5SDimitry Andric } 253*0b57cec5SDimitry Andric 254*0b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 255*0b57cec5SDimitry Andric // GCNRPTracker 256*0b57cec5SDimitry Andric 257*0b57cec5SDimitry Andric LaneBitmask llvm::getLiveLaneMask(unsigned Reg, 258*0b57cec5SDimitry Andric SlotIndex SI, 259*0b57cec5SDimitry Andric const LiveIntervals &LIS, 260*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 261*0b57cec5SDimitry Andric LaneBitmask LiveMask; 262*0b57cec5SDimitry Andric const auto &LI = LIS.getInterval(Reg); 263*0b57cec5SDimitry Andric if (LI.hasSubRanges()) { 264*0b57cec5SDimitry Andric for (const auto &S : LI.subranges()) 265*0b57cec5SDimitry Andric if (S.liveAt(SI)) { 266*0b57cec5SDimitry Andric LiveMask |= S.LaneMask; 267*0b57cec5SDimitry Andric assert(LiveMask < MRI.getMaxLaneMaskForVReg(Reg) || 268*0b57cec5SDimitry Andric LiveMask == MRI.getMaxLaneMaskForVReg(Reg)); 269*0b57cec5SDimitry Andric } 270*0b57cec5SDimitry Andric } else if (LI.liveAt(SI)) { 271*0b57cec5SDimitry Andric LiveMask = MRI.getMaxLaneMaskForVReg(Reg); 272*0b57cec5SDimitry Andric } 273*0b57cec5SDimitry Andric return LiveMask; 274*0b57cec5SDimitry Andric } 275*0b57cec5SDimitry Andric 276*0b57cec5SDimitry Andric GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI, 277*0b57cec5SDimitry Andric const LiveIntervals &LIS, 278*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 279*0b57cec5SDimitry Andric GCNRPTracker::LiveRegSet LiveRegs; 280*0b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { 281*0b57cec5SDimitry Andric auto Reg = TargetRegisterInfo::index2VirtReg(I); 282*0b57cec5SDimitry Andric if (!LIS.hasInterval(Reg)) 283*0b57cec5SDimitry Andric continue; 284*0b57cec5SDimitry Andric auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI); 285*0b57cec5SDimitry Andric if (LiveMask.any()) 286*0b57cec5SDimitry Andric LiveRegs[Reg] = LiveMask; 287*0b57cec5SDimitry Andric } 288*0b57cec5SDimitry Andric return LiveRegs; 289*0b57cec5SDimitry Andric } 290*0b57cec5SDimitry Andric 291*0b57cec5SDimitry Andric void GCNRPTracker::reset(const MachineInstr &MI, 292*0b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy, 293*0b57cec5SDimitry Andric bool After) { 294*0b57cec5SDimitry Andric const MachineFunction &MF = *MI.getMF(); 295*0b57cec5SDimitry Andric MRI = &MF.getRegInfo(); 296*0b57cec5SDimitry Andric if (LiveRegsCopy) { 297*0b57cec5SDimitry Andric if (&LiveRegs != LiveRegsCopy) 298*0b57cec5SDimitry Andric LiveRegs = *LiveRegsCopy; 299*0b57cec5SDimitry Andric } else { 300*0b57cec5SDimitry Andric LiveRegs = After ? getLiveRegsAfter(MI, LIS) 301*0b57cec5SDimitry Andric : getLiveRegsBefore(MI, LIS); 302*0b57cec5SDimitry Andric } 303*0b57cec5SDimitry Andric 304*0b57cec5SDimitry Andric MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs); 305*0b57cec5SDimitry Andric } 306*0b57cec5SDimitry Andric 307*0b57cec5SDimitry Andric void GCNUpwardRPTracker::reset(const MachineInstr &MI, 308*0b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) { 309*0b57cec5SDimitry Andric GCNRPTracker::reset(MI, LiveRegsCopy, true); 310*0b57cec5SDimitry Andric } 311*0b57cec5SDimitry Andric 312*0b57cec5SDimitry Andric void GCNUpwardRPTracker::recede(const MachineInstr &MI) { 313*0b57cec5SDimitry Andric assert(MRI && "call reset first"); 314*0b57cec5SDimitry Andric 315*0b57cec5SDimitry Andric LastTrackedMI = &MI; 316*0b57cec5SDimitry Andric 317*0b57cec5SDimitry Andric if (MI.isDebugInstr()) 318*0b57cec5SDimitry Andric return; 319*0b57cec5SDimitry Andric 320*0b57cec5SDimitry Andric auto const RegUses = collectVirtualRegUses(MI, LIS, *MRI); 321*0b57cec5SDimitry Andric 322*0b57cec5SDimitry Andric // calc pressure at the MI (defs + uses) 323*0b57cec5SDimitry Andric auto AtMIPressure = CurPressure; 324*0b57cec5SDimitry Andric for (const auto &U : RegUses) { 325*0b57cec5SDimitry Andric auto LiveMask = LiveRegs[U.RegUnit]; 326*0b57cec5SDimitry Andric AtMIPressure.inc(U.RegUnit, LiveMask, LiveMask | U.LaneMask, *MRI); 327*0b57cec5SDimitry Andric } 328*0b57cec5SDimitry Andric // update max pressure 329*0b57cec5SDimitry Andric MaxPressure = max(AtMIPressure, MaxPressure); 330*0b57cec5SDimitry Andric 331*0b57cec5SDimitry Andric for (const auto &MO : MI.defs()) { 332*0b57cec5SDimitry Andric if (!MO.isReg() || !TargetRegisterInfo::isVirtualRegister(MO.getReg()) || 333*0b57cec5SDimitry Andric MO.isDead()) 334*0b57cec5SDimitry Andric continue; 335*0b57cec5SDimitry Andric 336*0b57cec5SDimitry Andric auto Reg = MO.getReg(); 337*0b57cec5SDimitry Andric auto I = LiveRegs.find(Reg); 338*0b57cec5SDimitry Andric if (I == LiveRegs.end()) 339*0b57cec5SDimitry Andric continue; 340*0b57cec5SDimitry Andric auto &LiveMask = I->second; 341*0b57cec5SDimitry Andric auto PrevMask = LiveMask; 342*0b57cec5SDimitry Andric LiveMask &= ~getDefRegMask(MO, *MRI); 343*0b57cec5SDimitry Andric CurPressure.inc(Reg, PrevMask, LiveMask, *MRI); 344*0b57cec5SDimitry Andric if (LiveMask.none()) 345*0b57cec5SDimitry Andric LiveRegs.erase(I); 346*0b57cec5SDimitry Andric } 347*0b57cec5SDimitry Andric for (const auto &U : RegUses) { 348*0b57cec5SDimitry Andric auto &LiveMask = LiveRegs[U.RegUnit]; 349*0b57cec5SDimitry Andric auto PrevMask = LiveMask; 350*0b57cec5SDimitry Andric LiveMask |= U.LaneMask; 351*0b57cec5SDimitry Andric CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI); 352*0b57cec5SDimitry Andric } 353*0b57cec5SDimitry Andric assert(CurPressure == getRegPressure(*MRI, LiveRegs)); 354*0b57cec5SDimitry Andric } 355*0b57cec5SDimitry Andric 356*0b57cec5SDimitry Andric bool GCNDownwardRPTracker::reset(const MachineInstr &MI, 357*0b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) { 358*0b57cec5SDimitry Andric MRI = &MI.getParent()->getParent()->getRegInfo(); 359*0b57cec5SDimitry Andric LastTrackedMI = nullptr; 360*0b57cec5SDimitry Andric MBBEnd = MI.getParent()->end(); 361*0b57cec5SDimitry Andric NextMI = &MI; 362*0b57cec5SDimitry Andric NextMI = skipDebugInstructionsForward(NextMI, MBBEnd); 363*0b57cec5SDimitry Andric if (NextMI == MBBEnd) 364*0b57cec5SDimitry Andric return false; 365*0b57cec5SDimitry Andric GCNRPTracker::reset(*NextMI, LiveRegsCopy, false); 366*0b57cec5SDimitry Andric return true; 367*0b57cec5SDimitry Andric } 368*0b57cec5SDimitry Andric 369*0b57cec5SDimitry Andric bool GCNDownwardRPTracker::advanceBeforeNext() { 370*0b57cec5SDimitry Andric assert(MRI && "call reset first"); 371*0b57cec5SDimitry Andric 372*0b57cec5SDimitry Andric NextMI = skipDebugInstructionsForward(NextMI, MBBEnd); 373*0b57cec5SDimitry Andric if (NextMI == MBBEnd) 374*0b57cec5SDimitry Andric return false; 375*0b57cec5SDimitry Andric 376*0b57cec5SDimitry Andric SlotIndex SI = LIS.getInstructionIndex(*NextMI).getBaseIndex(); 377*0b57cec5SDimitry Andric assert(SI.isValid()); 378*0b57cec5SDimitry Andric 379*0b57cec5SDimitry Andric // Remove dead registers or mask bits. 380*0b57cec5SDimitry Andric for (auto &It : LiveRegs) { 381*0b57cec5SDimitry Andric const LiveInterval &LI = LIS.getInterval(It.first); 382*0b57cec5SDimitry Andric if (LI.hasSubRanges()) { 383*0b57cec5SDimitry Andric for (const auto &S : LI.subranges()) { 384*0b57cec5SDimitry Andric if (!S.liveAt(SI)) { 385*0b57cec5SDimitry Andric auto PrevMask = It.second; 386*0b57cec5SDimitry Andric It.second &= ~S.LaneMask; 387*0b57cec5SDimitry Andric CurPressure.inc(It.first, PrevMask, It.second, *MRI); 388*0b57cec5SDimitry Andric } 389*0b57cec5SDimitry Andric } 390*0b57cec5SDimitry Andric } else if (!LI.liveAt(SI)) { 391*0b57cec5SDimitry Andric auto PrevMask = It.second; 392*0b57cec5SDimitry Andric It.second = LaneBitmask::getNone(); 393*0b57cec5SDimitry Andric CurPressure.inc(It.first, PrevMask, It.second, *MRI); 394*0b57cec5SDimitry Andric } 395*0b57cec5SDimitry Andric if (It.second.none()) 396*0b57cec5SDimitry Andric LiveRegs.erase(It.first); 397*0b57cec5SDimitry Andric } 398*0b57cec5SDimitry Andric 399*0b57cec5SDimitry Andric MaxPressure = max(MaxPressure, CurPressure); 400*0b57cec5SDimitry Andric 401*0b57cec5SDimitry Andric return true; 402*0b57cec5SDimitry Andric } 403*0b57cec5SDimitry Andric 404*0b57cec5SDimitry Andric void GCNDownwardRPTracker::advanceToNext() { 405*0b57cec5SDimitry Andric LastTrackedMI = &*NextMI++; 406*0b57cec5SDimitry Andric 407*0b57cec5SDimitry Andric // Add new registers or mask bits. 408*0b57cec5SDimitry Andric for (const auto &MO : LastTrackedMI->defs()) { 409*0b57cec5SDimitry Andric if (!MO.isReg()) 410*0b57cec5SDimitry Andric continue; 411*0b57cec5SDimitry Andric unsigned Reg = MO.getReg(); 412*0b57cec5SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(Reg)) 413*0b57cec5SDimitry Andric continue; 414*0b57cec5SDimitry Andric auto &LiveMask = LiveRegs[Reg]; 415*0b57cec5SDimitry Andric auto PrevMask = LiveMask; 416*0b57cec5SDimitry Andric LiveMask |= getDefRegMask(MO, *MRI); 417*0b57cec5SDimitry Andric CurPressure.inc(Reg, PrevMask, LiveMask, *MRI); 418*0b57cec5SDimitry Andric } 419*0b57cec5SDimitry Andric 420*0b57cec5SDimitry Andric MaxPressure = max(MaxPressure, CurPressure); 421*0b57cec5SDimitry Andric } 422*0b57cec5SDimitry Andric 423*0b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance() { 424*0b57cec5SDimitry Andric // If we have just called reset live set is actual. 425*0b57cec5SDimitry Andric if ((NextMI == MBBEnd) || (LastTrackedMI && !advanceBeforeNext())) 426*0b57cec5SDimitry Andric return false; 427*0b57cec5SDimitry Andric advanceToNext(); 428*0b57cec5SDimitry Andric return true; 429*0b57cec5SDimitry Andric } 430*0b57cec5SDimitry Andric 431*0b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) { 432*0b57cec5SDimitry Andric while (NextMI != End) 433*0b57cec5SDimitry Andric if (!advance()) return false; 434*0b57cec5SDimitry Andric return true; 435*0b57cec5SDimitry Andric } 436*0b57cec5SDimitry Andric 437*0b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin, 438*0b57cec5SDimitry Andric MachineBasicBlock::const_iterator End, 439*0b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) { 440*0b57cec5SDimitry Andric reset(*Begin, LiveRegsCopy); 441*0b57cec5SDimitry Andric return advance(End); 442*0b57cec5SDimitry Andric } 443*0b57cec5SDimitry Andric 444*0b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 445*0b57cec5SDimitry Andric LLVM_DUMP_METHOD 446*0b57cec5SDimitry Andric static void reportMismatch(const GCNRPTracker::LiveRegSet &LISLR, 447*0b57cec5SDimitry Andric const GCNRPTracker::LiveRegSet &TrackedLR, 448*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 449*0b57cec5SDimitry Andric for (auto const &P : TrackedLR) { 450*0b57cec5SDimitry Andric auto I = LISLR.find(P.first); 451*0b57cec5SDimitry Andric if (I == LISLR.end()) { 452*0b57cec5SDimitry Andric dbgs() << " " << printReg(P.first, TRI) 453*0b57cec5SDimitry Andric << ":L" << PrintLaneMask(P.second) 454*0b57cec5SDimitry Andric << " isn't found in LIS reported set\n"; 455*0b57cec5SDimitry Andric } 456*0b57cec5SDimitry Andric else if (I->second != P.second) { 457*0b57cec5SDimitry Andric dbgs() << " " << printReg(P.first, TRI) 458*0b57cec5SDimitry Andric << " masks doesn't match: LIS reported " 459*0b57cec5SDimitry Andric << PrintLaneMask(I->second) 460*0b57cec5SDimitry Andric << ", tracked " 461*0b57cec5SDimitry Andric << PrintLaneMask(P.second) 462*0b57cec5SDimitry Andric << '\n'; 463*0b57cec5SDimitry Andric } 464*0b57cec5SDimitry Andric } 465*0b57cec5SDimitry Andric for (auto const &P : LISLR) { 466*0b57cec5SDimitry Andric auto I = TrackedLR.find(P.first); 467*0b57cec5SDimitry Andric if (I == TrackedLR.end()) { 468*0b57cec5SDimitry Andric dbgs() << " " << printReg(P.first, TRI) 469*0b57cec5SDimitry Andric << ":L" << PrintLaneMask(P.second) 470*0b57cec5SDimitry Andric << " isn't found in tracked set\n"; 471*0b57cec5SDimitry Andric } 472*0b57cec5SDimitry Andric } 473*0b57cec5SDimitry Andric } 474*0b57cec5SDimitry Andric 475*0b57cec5SDimitry Andric bool GCNUpwardRPTracker::isValid() const { 476*0b57cec5SDimitry Andric const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex(); 477*0b57cec5SDimitry Andric const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI); 478*0b57cec5SDimitry Andric const auto &TrackedLR = LiveRegs; 479*0b57cec5SDimitry Andric 480*0b57cec5SDimitry Andric if (!isEqual(LISLR, TrackedLR)) { 481*0b57cec5SDimitry Andric dbgs() << "\nGCNUpwardRPTracker error: Tracked and" 482*0b57cec5SDimitry Andric " LIS reported livesets mismatch:\n"; 483*0b57cec5SDimitry Andric printLivesAt(SI, LIS, *MRI); 484*0b57cec5SDimitry Andric reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo()); 485*0b57cec5SDimitry Andric return false; 486*0b57cec5SDimitry Andric } 487*0b57cec5SDimitry Andric 488*0b57cec5SDimitry Andric auto LISPressure = getRegPressure(*MRI, LISLR); 489*0b57cec5SDimitry Andric if (LISPressure != CurPressure) { 490*0b57cec5SDimitry Andric dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: "; 491*0b57cec5SDimitry Andric CurPressure.print(dbgs()); 492*0b57cec5SDimitry Andric dbgs() << "LIS rpt: "; 493*0b57cec5SDimitry Andric LISPressure.print(dbgs()); 494*0b57cec5SDimitry Andric return false; 495*0b57cec5SDimitry Andric } 496*0b57cec5SDimitry Andric return true; 497*0b57cec5SDimitry Andric } 498*0b57cec5SDimitry Andric 499*0b57cec5SDimitry Andric void GCNRPTracker::printLiveRegs(raw_ostream &OS, const LiveRegSet& LiveRegs, 500*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI) { 501*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); 502*0b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { 503*0b57cec5SDimitry Andric unsigned Reg = TargetRegisterInfo::index2VirtReg(I); 504*0b57cec5SDimitry Andric auto It = LiveRegs.find(Reg); 505*0b57cec5SDimitry Andric if (It != LiveRegs.end() && It->second.any()) 506*0b57cec5SDimitry Andric OS << ' ' << printVRegOrUnit(Reg, TRI) << ':' 507*0b57cec5SDimitry Andric << PrintLaneMask(It->second); 508*0b57cec5SDimitry Andric } 509*0b57cec5SDimitry Andric OS << '\n'; 510*0b57cec5SDimitry Andric } 511*0b57cec5SDimitry Andric #endif 512