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"
155f757f3fSDimitry Andric #include "AMDGPU.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterPressure.h"
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric using namespace llvm;
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric #define DEBUG_TYPE "machine-scheduler"
210b57cec5SDimitry Andric
isEqual(const GCNRPTracker::LiveRegSet & S1,const GCNRPTracker::LiveRegSet & S2)220b57cec5SDimitry Andric bool llvm::isEqual(const GCNRPTracker::LiveRegSet &S1,
230b57cec5SDimitry Andric const GCNRPTracker::LiveRegSet &S2) {
240b57cec5SDimitry Andric if (S1.size() != S2.size())
250b57cec5SDimitry Andric return false;
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric for (const auto &P : S1) {
280b57cec5SDimitry Andric auto I = S2.find(P.first);
290b57cec5SDimitry Andric if (I == S2.end() || I->second != P.second)
300b57cec5SDimitry Andric return false;
310b57cec5SDimitry Andric }
320b57cec5SDimitry Andric return true;
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric ///////////////////////////////////////////////////////////////////////////////
360b57cec5SDimitry Andric // GCNRegPressure
370b57cec5SDimitry Andric
getRegKind(Register Reg,const MachineRegisterInfo & MRI)38e8d8bef9SDimitry Andric unsigned GCNRegPressure::getRegKind(Register Reg,
390b57cec5SDimitry Andric const MachineRegisterInfo &MRI) {
40e8d8bef9SDimitry Andric assert(Reg.isVirtual());
410b57cec5SDimitry Andric const auto RC = MRI.getRegClass(Reg);
420b57cec5SDimitry Andric auto STI = static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo());
434824e7fdSDimitry Andric return STI->isSGPRClass(RC)
444824e7fdSDimitry Andric ? (STI->getRegSizeInBits(*RC) == 32 ? SGPR32 : SGPR_TUPLE)
454824e7fdSDimitry Andric : STI->isAGPRClass(RC)
464824e7fdSDimitry Andric ? (STI->getRegSizeInBits(*RC) == 32 ? AGPR32 : AGPR_TUPLE)
474824e7fdSDimitry Andric : (STI->getRegSizeInBits(*RC) == 32 ? VGPR32 : VGPR_TUPLE);
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric
inc(unsigned Reg,LaneBitmask PrevMask,LaneBitmask NewMask,const MachineRegisterInfo & MRI)500b57cec5SDimitry Andric void GCNRegPressure::inc(unsigned Reg,
510b57cec5SDimitry Andric LaneBitmask PrevMask,
520b57cec5SDimitry Andric LaneBitmask NewMask,
530b57cec5SDimitry Andric const MachineRegisterInfo &MRI) {
545ffd83dbSDimitry Andric if (SIRegisterInfo::getNumCoveredRegs(NewMask) ==
555ffd83dbSDimitry Andric SIRegisterInfo::getNumCoveredRegs(PrevMask))
560b57cec5SDimitry Andric return;
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric int Sign = 1;
590b57cec5SDimitry Andric if (NewMask < PrevMask) {
600b57cec5SDimitry Andric std::swap(NewMask, PrevMask);
610b57cec5SDimitry Andric Sign = -1;
620b57cec5SDimitry Andric }
635ffd83dbSDimitry Andric
640b57cec5SDimitry Andric switch (auto Kind = getRegKind(Reg, MRI)) {
650b57cec5SDimitry Andric case SGPR32:
660b57cec5SDimitry Andric case VGPR32:
670b57cec5SDimitry Andric case AGPR32:
680b57cec5SDimitry Andric Value[Kind] += Sign;
690b57cec5SDimitry Andric break;
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric case SGPR_TUPLE:
720b57cec5SDimitry Andric case VGPR_TUPLE:
730b57cec5SDimitry Andric case AGPR_TUPLE:
740b57cec5SDimitry Andric assert(PrevMask < NewMask);
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric Value[Kind == SGPR_TUPLE ? SGPR32 : Kind == AGPR_TUPLE ? AGPR32 : VGPR32] +=
775ffd83dbSDimitry Andric Sign * SIRegisterInfo::getNumCoveredRegs(~PrevMask & NewMask);
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric if (PrevMask.none()) {
800b57cec5SDimitry Andric assert(NewMask.any());
815f757f3fSDimitry Andric const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
825f757f3fSDimitry Andric Value[Kind] +=
835f757f3fSDimitry Andric Sign * TRI->getRegClassWeight(MRI.getRegClass(Reg)).RegWeight;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric break;
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric default: llvm_unreachable("Unknown register kind");
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric
less(const MachineFunction & MF,const GCNRegPressure & O,unsigned MaxOccupancy) const91*0fca6ea1SDimitry Andric bool GCNRegPressure::less(const MachineFunction &MF, const GCNRegPressure &O,
920b57cec5SDimitry Andric unsigned MaxOccupancy) const {
93*0fca6ea1SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
94*0fca6ea1SDimitry Andric
950b57cec5SDimitry Andric const auto SGPROcc = std::min(MaxOccupancy,
960b57cec5SDimitry Andric ST.getOccupancyWithNumSGPRs(getSGPRNum()));
97fe6060f1SDimitry Andric const auto VGPROcc =
98fe6060f1SDimitry Andric std::min(MaxOccupancy,
99fe6060f1SDimitry Andric ST.getOccupancyWithNumVGPRs(getVGPRNum(ST.hasGFX90AInsts())));
1000b57cec5SDimitry Andric const auto OtherSGPROcc = std::min(MaxOccupancy,
1010b57cec5SDimitry Andric ST.getOccupancyWithNumSGPRs(O.getSGPRNum()));
102fe6060f1SDimitry Andric const auto OtherVGPROcc =
103fe6060f1SDimitry Andric std::min(MaxOccupancy,
104fe6060f1SDimitry Andric ST.getOccupancyWithNumVGPRs(O.getVGPRNum(ST.hasGFX90AInsts())));
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric const auto Occ = std::min(SGPROcc, VGPROcc);
1070b57cec5SDimitry Andric const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc);
108*0fca6ea1SDimitry Andric
109*0fca6ea1SDimitry Andric // Give first precedence to the better occupancy.
1100b57cec5SDimitry Andric if (Occ != OtherOcc)
1110b57cec5SDimitry Andric return Occ > OtherOcc;
1120b57cec5SDimitry Andric
113*0fca6ea1SDimitry Andric unsigned MaxVGPRs = ST.getMaxNumVGPRs(MF);
114*0fca6ea1SDimitry Andric unsigned MaxSGPRs = ST.getMaxNumSGPRs(MF);
115*0fca6ea1SDimitry Andric
116*0fca6ea1SDimitry Andric // SGPR excess pressure conditions
117*0fca6ea1SDimitry Andric unsigned ExcessSGPR = std::max(static_cast<int>(getSGPRNum() - MaxSGPRs), 0);
118*0fca6ea1SDimitry Andric unsigned OtherExcessSGPR =
119*0fca6ea1SDimitry Andric std::max(static_cast<int>(O.getSGPRNum() - MaxSGPRs), 0);
120*0fca6ea1SDimitry Andric
121*0fca6ea1SDimitry Andric auto WaveSize = ST.getWavefrontSize();
122*0fca6ea1SDimitry Andric // The number of virtual VGPRs required to handle excess SGPR
123*0fca6ea1SDimitry Andric unsigned VGPRForSGPRSpills = (ExcessSGPR + (WaveSize - 1)) / WaveSize;
124*0fca6ea1SDimitry Andric unsigned OtherVGPRForSGPRSpills =
125*0fca6ea1SDimitry Andric (OtherExcessSGPR + (WaveSize - 1)) / WaveSize;
126*0fca6ea1SDimitry Andric
127*0fca6ea1SDimitry Andric unsigned MaxArchVGPRs = ST.getAddressableNumArchVGPRs();
128*0fca6ea1SDimitry Andric
129*0fca6ea1SDimitry Andric // Unified excess pressure conditions, accounting for VGPRs used for SGPR
130*0fca6ea1SDimitry Andric // spills
131*0fca6ea1SDimitry Andric unsigned ExcessVGPR =
132*0fca6ea1SDimitry Andric std::max(static_cast<int>(getVGPRNum(ST.hasGFX90AInsts()) +
133*0fca6ea1SDimitry Andric VGPRForSGPRSpills - MaxVGPRs),
134*0fca6ea1SDimitry Andric 0);
135*0fca6ea1SDimitry Andric unsigned OtherExcessVGPR =
136*0fca6ea1SDimitry Andric std::max(static_cast<int>(O.getVGPRNum(ST.hasGFX90AInsts()) +
137*0fca6ea1SDimitry Andric OtherVGPRForSGPRSpills - MaxVGPRs),
138*0fca6ea1SDimitry Andric 0);
139*0fca6ea1SDimitry Andric // Arch VGPR excess pressure conditions, accounting for VGPRs used for SGPR
140*0fca6ea1SDimitry Andric // spills
141*0fca6ea1SDimitry Andric unsigned ExcessArchVGPR = std::max(
142*0fca6ea1SDimitry Andric static_cast<int>(getVGPRNum(false) + VGPRForSGPRSpills - MaxArchVGPRs),
143*0fca6ea1SDimitry Andric 0);
144*0fca6ea1SDimitry Andric unsigned OtherExcessArchVGPR =
145*0fca6ea1SDimitry Andric std::max(static_cast<int>(O.getVGPRNum(false) + OtherVGPRForSGPRSpills -
146*0fca6ea1SDimitry Andric MaxArchVGPRs),
147*0fca6ea1SDimitry Andric 0);
148*0fca6ea1SDimitry Andric // AGPR excess pressure conditions
149*0fca6ea1SDimitry Andric unsigned ExcessAGPR = std::max(
150*0fca6ea1SDimitry Andric static_cast<int>(ST.hasGFX90AInsts() ? (getAGPRNum() - MaxArchVGPRs)
151*0fca6ea1SDimitry Andric : (getAGPRNum() - MaxVGPRs)),
152*0fca6ea1SDimitry Andric 0);
153*0fca6ea1SDimitry Andric unsigned OtherExcessAGPR = std::max(
154*0fca6ea1SDimitry Andric static_cast<int>(ST.hasGFX90AInsts() ? (O.getAGPRNum() - MaxArchVGPRs)
155*0fca6ea1SDimitry Andric : (O.getAGPRNum() - MaxVGPRs)),
156*0fca6ea1SDimitry Andric 0);
157*0fca6ea1SDimitry Andric
158*0fca6ea1SDimitry Andric bool ExcessRP = ExcessSGPR || ExcessVGPR || ExcessArchVGPR || ExcessAGPR;
159*0fca6ea1SDimitry Andric bool OtherExcessRP = OtherExcessSGPR || OtherExcessVGPR ||
160*0fca6ea1SDimitry Andric OtherExcessArchVGPR || OtherExcessAGPR;
161*0fca6ea1SDimitry Andric
162*0fca6ea1SDimitry Andric // Give second precedence to the reduced number of spills to hold the register
163*0fca6ea1SDimitry Andric // pressure.
164*0fca6ea1SDimitry Andric if (ExcessRP || OtherExcessRP) {
165*0fca6ea1SDimitry Andric // The difference in excess VGPR pressure, after including VGPRs used for
166*0fca6ea1SDimitry Andric // SGPR spills
167*0fca6ea1SDimitry Andric int VGPRDiff = ((OtherExcessVGPR + OtherExcessArchVGPR + OtherExcessAGPR) -
168*0fca6ea1SDimitry Andric (ExcessVGPR + ExcessArchVGPR + ExcessAGPR));
169*0fca6ea1SDimitry Andric
170*0fca6ea1SDimitry Andric int SGPRDiff = OtherExcessSGPR - ExcessSGPR;
171*0fca6ea1SDimitry Andric
172*0fca6ea1SDimitry Andric if (VGPRDiff != 0)
173*0fca6ea1SDimitry Andric return VGPRDiff > 0;
174*0fca6ea1SDimitry Andric if (SGPRDiff != 0) {
175*0fca6ea1SDimitry Andric unsigned PureExcessVGPR =
176*0fca6ea1SDimitry Andric std::max(static_cast<int>(getVGPRNum(ST.hasGFX90AInsts()) - MaxVGPRs),
177*0fca6ea1SDimitry Andric 0) +
178*0fca6ea1SDimitry Andric std::max(static_cast<int>(getVGPRNum(false) - MaxArchVGPRs), 0);
179*0fca6ea1SDimitry Andric unsigned OtherPureExcessVGPR =
180*0fca6ea1SDimitry Andric std::max(
181*0fca6ea1SDimitry Andric static_cast<int>(O.getVGPRNum(ST.hasGFX90AInsts()) - MaxVGPRs),
182*0fca6ea1SDimitry Andric 0) +
183*0fca6ea1SDimitry Andric std::max(static_cast<int>(O.getVGPRNum(false) - MaxArchVGPRs), 0);
184*0fca6ea1SDimitry Andric
185*0fca6ea1SDimitry Andric // If we have a special case where there is a tie in excess VGPR, but one
186*0fca6ea1SDimitry Andric // of the pressures has VGPR usage from SGPR spills, prefer the pressure
187*0fca6ea1SDimitry Andric // with SGPR spills.
188*0fca6ea1SDimitry Andric if (PureExcessVGPR != OtherPureExcessVGPR)
189*0fca6ea1SDimitry Andric return SGPRDiff < 0;
190*0fca6ea1SDimitry Andric // If both pressures have the same excess pressure before and after
191*0fca6ea1SDimitry Andric // accounting for SGPR spills, prefer fewer SGPR spills.
192*0fca6ea1SDimitry Andric return SGPRDiff > 0;
193*0fca6ea1SDimitry Andric }
194*0fca6ea1SDimitry Andric }
195*0fca6ea1SDimitry Andric
1960b57cec5SDimitry Andric bool SGPRImportant = SGPROcc < VGPROcc;
1970b57cec5SDimitry Andric const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc;
1980b57cec5SDimitry Andric
199*0fca6ea1SDimitry Andric // If both pressures disagree on what is more important compare vgprs.
2000b57cec5SDimitry Andric if (SGPRImportant != OtherSGPRImportant) {
2010b57cec5SDimitry Andric SGPRImportant = false;
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric
204*0fca6ea1SDimitry Andric // Give third precedence to lower register tuple pressure.
2050b57cec5SDimitry Andric bool SGPRFirst = SGPRImportant;
2060b57cec5SDimitry Andric for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) {
2070b57cec5SDimitry Andric if (SGPRFirst) {
2080b57cec5SDimitry Andric auto SW = getSGPRTuplesWeight();
2090b57cec5SDimitry Andric auto OtherSW = O.getSGPRTuplesWeight();
2100b57cec5SDimitry Andric if (SW != OtherSW)
2110b57cec5SDimitry Andric return SW < OtherSW;
2120b57cec5SDimitry Andric } else {
2130b57cec5SDimitry Andric auto VW = getVGPRTuplesWeight();
2140b57cec5SDimitry Andric auto OtherVW = O.getVGPRTuplesWeight();
2150b57cec5SDimitry Andric if (VW != OtherVW)
2160b57cec5SDimitry Andric return VW < OtherVW;
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric }
219*0fca6ea1SDimitry Andric
220*0fca6ea1SDimitry Andric // Give final precedence to lower general RP.
2210b57cec5SDimitry Andric return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()):
222fe6060f1SDimitry Andric (getVGPRNum(ST.hasGFX90AInsts()) <
223fe6060f1SDimitry Andric O.getVGPRNum(ST.hasGFX90AInsts()));
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric
print(const GCNRegPressure & RP,const GCNSubtarget * ST)226bdd1243dSDimitry Andric Printable llvm::print(const GCNRegPressure &RP, const GCNSubtarget *ST) {
227bdd1243dSDimitry Andric return Printable([&RP, ST](raw_ostream &OS) {
228bdd1243dSDimitry Andric OS << "VGPRs: " << RP.Value[GCNRegPressure::VGPR32] << ' '
229bdd1243dSDimitry Andric << "AGPRs: " << RP.getAGPRNum();
230bdd1243dSDimitry Andric if (ST)
231bdd1243dSDimitry Andric OS << "(O"
232bdd1243dSDimitry Andric << ST->getOccupancyWithNumVGPRs(RP.getVGPRNum(ST->hasGFX90AInsts()))
233fe6060f1SDimitry Andric << ')';
234bdd1243dSDimitry Andric OS << ", SGPRs: " << RP.getSGPRNum();
235bdd1243dSDimitry Andric if (ST)
236bdd1243dSDimitry Andric OS << "(O" << ST->getOccupancyWithNumSGPRs(RP.getSGPRNum()) << ')';
237bdd1243dSDimitry Andric OS << ", LVGPR WT: " << RP.getVGPRTuplesWeight()
238bdd1243dSDimitry Andric << ", LSGPR WT: " << RP.getSGPRTuplesWeight();
239bdd1243dSDimitry Andric if (ST)
240bdd1243dSDimitry Andric OS << " -> Occ: " << RP.getOccupancy(*ST);
2410b57cec5SDimitry Andric OS << '\n';
242bdd1243dSDimitry Andric });
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric
getDefRegMask(const MachineOperand & MO,const MachineRegisterInfo & MRI)2450b57cec5SDimitry Andric static LaneBitmask getDefRegMask(const MachineOperand &MO,
2460b57cec5SDimitry Andric const MachineRegisterInfo &MRI) {
247e8d8bef9SDimitry Andric assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual());
2480b57cec5SDimitry Andric
2490b57cec5SDimitry Andric // We don't rely on read-undef flag because in case of tentative schedule
2500b57cec5SDimitry Andric // tracking it isn't set correctly yet. This works correctly however since
2510b57cec5SDimitry Andric // use mask has been tracked before using LIS.
2520b57cec5SDimitry Andric return MO.getSubReg() == 0 ?
2530b57cec5SDimitry Andric MRI.getMaxLaneMaskForVReg(MO.getReg()) :
2540b57cec5SDimitry Andric MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric
2575f757f3fSDimitry Andric static void
collectVirtualRegUses(SmallVectorImpl<RegisterMaskPair> & RegMaskPairs,const MachineInstr & MI,const LiveIntervals & LIS,const MachineRegisterInfo & MRI)2585f757f3fSDimitry Andric collectVirtualRegUses(SmallVectorImpl<RegisterMaskPair> &RegMaskPairs,
2595f757f3fSDimitry Andric const MachineInstr &MI, const LiveIntervals &LIS,
2600b57cec5SDimitry Andric const MachineRegisterInfo &MRI) {
2615f757f3fSDimitry Andric SlotIndex InstrSI;
2620b57cec5SDimitry Andric for (const auto &MO : MI.operands()) {
263e8d8bef9SDimitry Andric if (!MO.isReg() || !MO.getReg().isVirtual())
2640b57cec5SDimitry Andric continue;
2650b57cec5SDimitry Andric if (!MO.isUse() || !MO.readsReg())
2660b57cec5SDimitry Andric continue;
2670b57cec5SDimitry Andric
2685f757f3fSDimitry Andric Register Reg = MO.getReg();
2695f757f3fSDimitry Andric if (llvm::any_of(RegMaskPairs, [Reg](const RegisterMaskPair &RM) {
2705f757f3fSDimitry Andric return RM.RegUnit == Reg;
2715f757f3fSDimitry Andric }))
2725f757f3fSDimitry Andric continue;
2730b57cec5SDimitry Andric
2745f757f3fSDimitry Andric LaneBitmask UseMask;
2755f757f3fSDimitry Andric auto &LI = LIS.getInterval(Reg);
2765f757f3fSDimitry Andric if (!LI.hasSubRanges())
2775f757f3fSDimitry Andric UseMask = MRI.getMaxLaneMaskForVReg(Reg);
2785f757f3fSDimitry Andric else {
2795f757f3fSDimitry Andric // For a tentative schedule LIS isn't updated yet but livemask should
2805f757f3fSDimitry Andric // remain the same on any schedule. Subreg defs can be reordered but they
2815f757f3fSDimitry Andric // all must dominate uses anyway.
2825f757f3fSDimitry Andric if (!InstrSI)
2835f757f3fSDimitry Andric InstrSI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex();
2845f757f3fSDimitry Andric UseMask = getLiveLaneMask(LI, InstrSI, MRI);
2850b57cec5SDimitry Andric }
2865f757f3fSDimitry Andric
2875f757f3fSDimitry Andric RegMaskPairs.emplace_back(Reg, UseMask);
2885f757f3fSDimitry Andric }
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric
2910b57cec5SDimitry Andric ///////////////////////////////////////////////////////////////////////////////
2920b57cec5SDimitry Andric // GCNRPTracker
2930b57cec5SDimitry Andric
getLiveLaneMask(unsigned Reg,SlotIndex SI,const LiveIntervals & LIS,const MachineRegisterInfo & MRI)2945f757f3fSDimitry Andric LaneBitmask llvm::getLiveLaneMask(unsigned Reg, SlotIndex SI,
2950b57cec5SDimitry Andric const LiveIntervals &LIS,
2960b57cec5SDimitry Andric const MachineRegisterInfo &MRI) {
2975f757f3fSDimitry Andric return getLiveLaneMask(LIS.getInterval(Reg), SI, MRI);
2985f757f3fSDimitry Andric }
2995f757f3fSDimitry Andric
getLiveLaneMask(const LiveInterval & LI,SlotIndex SI,const MachineRegisterInfo & MRI)3005f757f3fSDimitry Andric LaneBitmask llvm::getLiveLaneMask(const LiveInterval &LI, SlotIndex SI,
3015f757f3fSDimitry Andric const MachineRegisterInfo &MRI) {
3020b57cec5SDimitry Andric LaneBitmask LiveMask;
3030b57cec5SDimitry Andric if (LI.hasSubRanges()) {
3040b57cec5SDimitry Andric for (const auto &S : LI.subranges())
3050b57cec5SDimitry Andric if (S.liveAt(SI)) {
3060b57cec5SDimitry Andric LiveMask |= S.LaneMask;
3075f757f3fSDimitry Andric assert(LiveMask == (LiveMask & MRI.getMaxLaneMaskForVReg(LI.reg())));
3080b57cec5SDimitry Andric }
3090b57cec5SDimitry Andric } else if (LI.liveAt(SI)) {
3105f757f3fSDimitry Andric LiveMask = MRI.getMaxLaneMaskForVReg(LI.reg());
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric return LiveMask;
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric
getLiveRegs(SlotIndex SI,const LiveIntervals & LIS,const MachineRegisterInfo & MRI)3150b57cec5SDimitry Andric GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
3160b57cec5SDimitry Andric const LiveIntervals &LIS,
3170b57cec5SDimitry Andric const MachineRegisterInfo &MRI) {
3180b57cec5SDimitry Andric GCNRPTracker::LiveRegSet LiveRegs;
3190b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
3208bcb0991SDimitry Andric auto Reg = Register::index2VirtReg(I);
3210b57cec5SDimitry Andric if (!LIS.hasInterval(Reg))
3220b57cec5SDimitry Andric continue;
3230b57cec5SDimitry Andric auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI);
3240b57cec5SDimitry Andric if (LiveMask.any())
3250b57cec5SDimitry Andric LiveRegs[Reg] = LiveMask;
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric return LiveRegs;
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric
reset(const MachineInstr & MI,const LiveRegSet * LiveRegsCopy,bool After)3300b57cec5SDimitry Andric void GCNRPTracker::reset(const MachineInstr &MI,
3310b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy,
3320b57cec5SDimitry Andric bool After) {
3330b57cec5SDimitry Andric const MachineFunction &MF = *MI.getMF();
3340b57cec5SDimitry Andric MRI = &MF.getRegInfo();
3350b57cec5SDimitry Andric if (LiveRegsCopy) {
3360b57cec5SDimitry Andric if (&LiveRegs != LiveRegsCopy)
3370b57cec5SDimitry Andric LiveRegs = *LiveRegsCopy;
3380b57cec5SDimitry Andric } else {
3390b57cec5SDimitry Andric LiveRegs = After ? getLiveRegsAfter(MI, LIS)
3400b57cec5SDimitry Andric : getLiveRegsBefore(MI, LIS);
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andric MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs);
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric
3465f757f3fSDimitry Andric ////////////////////////////////////////////////////////////////////////////////
3475f757f3fSDimitry Andric // GCNUpwardRPTracker
3485f757f3fSDimitry Andric
reset(const MachineRegisterInfo & MRI_,const LiveRegSet & LiveRegs_)3495f757f3fSDimitry Andric void GCNUpwardRPTracker::reset(const MachineRegisterInfo &MRI_,
3505f757f3fSDimitry Andric const LiveRegSet &LiveRegs_) {
3515f757f3fSDimitry Andric MRI = &MRI_;
3525f757f3fSDimitry Andric LiveRegs = LiveRegs_;
3535f757f3fSDimitry Andric LastTrackedMI = nullptr;
3545f757f3fSDimitry Andric MaxPressure = CurPressure = getRegPressure(MRI_, LiveRegs_);
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric
recede(const MachineInstr & MI)3570b57cec5SDimitry Andric void GCNUpwardRPTracker::recede(const MachineInstr &MI) {
3580b57cec5SDimitry Andric assert(MRI && "call reset first");
3590b57cec5SDimitry Andric
3600b57cec5SDimitry Andric LastTrackedMI = &MI;
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric if (MI.isDebugInstr())
3630b57cec5SDimitry Andric return;
3640b57cec5SDimitry Andric
3655f757f3fSDimitry Andric // Kill all defs.
3665f757f3fSDimitry Andric GCNRegPressure DefPressure, ECDefPressure;
3675f757f3fSDimitry Andric bool HasECDefs = false;
3685f757f3fSDimitry Andric for (const MachineOperand &MO : MI.all_defs()) {
3695f757f3fSDimitry Andric if (!MO.getReg().isVirtual())
3700b57cec5SDimitry Andric continue;
3710b57cec5SDimitry Andric
3725f757f3fSDimitry Andric Register Reg = MO.getReg();
3735f757f3fSDimitry Andric LaneBitmask DefMask = getDefRegMask(MO, *MRI);
3745f757f3fSDimitry Andric
3755f757f3fSDimitry Andric // Treat a def as fully live at the moment of definition: keep a record.
3765f757f3fSDimitry Andric if (MO.isEarlyClobber()) {
3775f757f3fSDimitry Andric ECDefPressure.inc(Reg, LaneBitmask::getNone(), DefMask, *MRI);
3785f757f3fSDimitry Andric HasECDefs = true;
3795f757f3fSDimitry Andric } else
3805f757f3fSDimitry Andric DefPressure.inc(Reg, LaneBitmask::getNone(), DefMask, *MRI);
3815f757f3fSDimitry Andric
3820b57cec5SDimitry Andric auto I = LiveRegs.find(Reg);
3830b57cec5SDimitry Andric if (I == LiveRegs.end())
3840b57cec5SDimitry Andric continue;
3855f757f3fSDimitry Andric
3865f757f3fSDimitry Andric LaneBitmask &LiveMask = I->second;
3875f757f3fSDimitry Andric LaneBitmask PrevMask = LiveMask;
3885f757f3fSDimitry Andric LiveMask &= ~DefMask;
3890b57cec5SDimitry Andric CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
3900b57cec5SDimitry Andric if (LiveMask.none())
3910b57cec5SDimitry Andric LiveRegs.erase(I);
3920b57cec5SDimitry Andric }
3935f757f3fSDimitry Andric
3945f757f3fSDimitry Andric // Update MaxPressure with defs pressure.
3955f757f3fSDimitry Andric DefPressure += CurPressure;
3965f757f3fSDimitry Andric if (HasECDefs)
3975f757f3fSDimitry Andric DefPressure += ECDefPressure;
3985f757f3fSDimitry Andric MaxPressure = max(DefPressure, MaxPressure);
3995f757f3fSDimitry Andric
4005f757f3fSDimitry Andric // Make uses alive.
4015f757f3fSDimitry Andric SmallVector<RegisterMaskPair, 8> RegUses;
4025f757f3fSDimitry Andric collectVirtualRegUses(RegUses, MI, LIS, *MRI);
4035f757f3fSDimitry Andric for (const RegisterMaskPair &U : RegUses) {
4045f757f3fSDimitry Andric LaneBitmask &LiveMask = LiveRegs[U.RegUnit];
4055f757f3fSDimitry Andric LaneBitmask PrevMask = LiveMask;
4060b57cec5SDimitry Andric LiveMask |= U.LaneMask;
4070b57cec5SDimitry Andric CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI);
4080b57cec5SDimitry Andric }
4095f757f3fSDimitry Andric
4105f757f3fSDimitry Andric // Update MaxPressure with uses plus early-clobber defs pressure.
4115f757f3fSDimitry Andric MaxPressure = HasECDefs ? max(CurPressure + ECDefPressure, MaxPressure)
4125f757f3fSDimitry Andric : max(CurPressure, MaxPressure);
4135f757f3fSDimitry Andric
4140b57cec5SDimitry Andric assert(CurPressure == getRegPressure(*MRI, LiveRegs));
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric
4175f757f3fSDimitry Andric ////////////////////////////////////////////////////////////////////////////////
4185f757f3fSDimitry Andric // GCNDownwardRPTracker
4195f757f3fSDimitry Andric
reset(const MachineInstr & MI,const LiveRegSet * LiveRegsCopy)4200b57cec5SDimitry Andric bool GCNDownwardRPTracker::reset(const MachineInstr &MI,
4210b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) {
4220b57cec5SDimitry Andric MRI = &MI.getParent()->getParent()->getRegInfo();
4230b57cec5SDimitry Andric LastTrackedMI = nullptr;
4240b57cec5SDimitry Andric MBBEnd = MI.getParent()->end();
4250b57cec5SDimitry Andric NextMI = &MI;
4260b57cec5SDimitry Andric NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
4270b57cec5SDimitry Andric if (NextMI == MBBEnd)
4280b57cec5SDimitry Andric return false;
4290b57cec5SDimitry Andric GCNRPTracker::reset(*NextMI, LiveRegsCopy, false);
4300b57cec5SDimitry Andric return true;
4310b57cec5SDimitry Andric }
4320b57cec5SDimitry Andric
advanceBeforeNext()4330b57cec5SDimitry Andric bool GCNDownwardRPTracker::advanceBeforeNext() {
4340b57cec5SDimitry Andric assert(MRI && "call reset first");
435bdd1243dSDimitry Andric if (!LastTrackedMI)
436bdd1243dSDimitry Andric return NextMI == MBBEnd;
4370b57cec5SDimitry Andric
438bdd1243dSDimitry Andric assert(NextMI == MBBEnd || !NextMI->isDebugInstr());
4390b57cec5SDimitry Andric
440bdd1243dSDimitry Andric SlotIndex SI = NextMI == MBBEnd
441bdd1243dSDimitry Andric ? LIS.getInstructionIndex(*LastTrackedMI).getDeadSlot()
442bdd1243dSDimitry Andric : LIS.getInstructionIndex(*NextMI).getBaseIndex();
4430b57cec5SDimitry Andric assert(SI.isValid());
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andric // Remove dead registers or mask bits.
44606c3fb27SDimitry Andric SmallSet<Register, 8> SeenRegs;
44706c3fb27SDimitry Andric for (auto &MO : LastTrackedMI->operands()) {
44806c3fb27SDimitry Andric if (!MO.isReg() || !MO.getReg().isVirtual())
44906c3fb27SDimitry Andric continue;
45006c3fb27SDimitry Andric if (MO.isUse() && !MO.readsReg())
45106c3fb27SDimitry Andric continue;
45206c3fb27SDimitry Andric if (!SeenRegs.insert(MO.getReg()).second)
45306c3fb27SDimitry Andric continue;
45406c3fb27SDimitry Andric const LiveInterval &LI = LIS.getInterval(MO.getReg());
4550b57cec5SDimitry Andric if (LI.hasSubRanges()) {
45606c3fb27SDimitry Andric auto It = LiveRegs.end();
4570b57cec5SDimitry Andric for (const auto &S : LI.subranges()) {
4580b57cec5SDimitry Andric if (!S.liveAt(SI)) {
45906c3fb27SDimitry Andric if (It == LiveRegs.end()) {
46006c3fb27SDimitry Andric It = LiveRegs.find(MO.getReg());
46106c3fb27SDimitry Andric if (It == LiveRegs.end())
46206c3fb27SDimitry Andric llvm_unreachable("register isn't live");
46306c3fb27SDimitry Andric }
46406c3fb27SDimitry Andric auto PrevMask = It->second;
46506c3fb27SDimitry Andric It->second &= ~S.LaneMask;
46606c3fb27SDimitry Andric CurPressure.inc(MO.getReg(), PrevMask, It->second, *MRI);
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric }
46906c3fb27SDimitry Andric if (It != LiveRegs.end() && It->second.none())
47006c3fb27SDimitry Andric LiveRegs.erase(It);
4710b57cec5SDimitry Andric } else if (!LI.liveAt(SI)) {
47206c3fb27SDimitry Andric auto It = LiveRegs.find(MO.getReg());
47306c3fb27SDimitry Andric if (It == LiveRegs.end())
47406c3fb27SDimitry Andric llvm_unreachable("register isn't live");
47506c3fb27SDimitry Andric CurPressure.inc(MO.getReg(), It->second, LaneBitmask::getNone(), *MRI);
47606c3fb27SDimitry Andric LiveRegs.erase(It);
4770b57cec5SDimitry Andric }
4780b57cec5SDimitry Andric }
4790b57cec5SDimitry Andric
4800b57cec5SDimitry Andric MaxPressure = max(MaxPressure, CurPressure);
4810b57cec5SDimitry Andric
482bdd1243dSDimitry Andric LastTrackedMI = nullptr;
483bdd1243dSDimitry Andric
484bdd1243dSDimitry Andric return NextMI == MBBEnd;
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric
advanceToNext()4870b57cec5SDimitry Andric void GCNDownwardRPTracker::advanceToNext() {
4880b57cec5SDimitry Andric LastTrackedMI = &*NextMI++;
489fe6060f1SDimitry Andric NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
4900b57cec5SDimitry Andric
4910b57cec5SDimitry Andric // Add new registers or mask bits.
49206c3fb27SDimitry Andric for (const auto &MO : LastTrackedMI->all_defs()) {
4938bcb0991SDimitry Andric Register Reg = MO.getReg();
494e8d8bef9SDimitry Andric if (!Reg.isVirtual())
4950b57cec5SDimitry Andric continue;
4960b57cec5SDimitry Andric auto &LiveMask = LiveRegs[Reg];
4970b57cec5SDimitry Andric auto PrevMask = LiveMask;
4980b57cec5SDimitry Andric LiveMask |= getDefRegMask(MO, *MRI);
4990b57cec5SDimitry Andric CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
5000b57cec5SDimitry Andric }
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric MaxPressure = max(MaxPressure, CurPressure);
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric
advance()5050b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance() {
506bdd1243dSDimitry Andric if (NextMI == MBBEnd)
5070b57cec5SDimitry Andric return false;
508bdd1243dSDimitry Andric advanceBeforeNext();
5090b57cec5SDimitry Andric advanceToNext();
5100b57cec5SDimitry Andric return true;
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric
advance(MachineBasicBlock::const_iterator End)5130b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) {
5140b57cec5SDimitry Andric while (NextMI != End)
5150b57cec5SDimitry Andric if (!advance()) return false;
5160b57cec5SDimitry Andric return true;
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric
advance(MachineBasicBlock::const_iterator Begin,MachineBasicBlock::const_iterator End,const LiveRegSet * LiveRegsCopy)5190b57cec5SDimitry Andric bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin,
5200b57cec5SDimitry Andric MachineBasicBlock::const_iterator End,
5210b57cec5SDimitry Andric const LiveRegSet *LiveRegsCopy) {
5220b57cec5SDimitry Andric reset(*Begin, LiveRegsCopy);
5230b57cec5SDimitry Andric return advance(End);
5240b57cec5SDimitry Andric }
5250b57cec5SDimitry Andric
reportMismatch(const GCNRPTracker::LiveRegSet & LISLR,const GCNRPTracker::LiveRegSet & TrackedLR,const TargetRegisterInfo * TRI,StringRef Pfx)526bdd1243dSDimitry Andric Printable llvm::reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
5270b57cec5SDimitry Andric const GCNRPTracker::LiveRegSet &TrackedLR,
5285f757f3fSDimitry Andric const TargetRegisterInfo *TRI, StringRef Pfx) {
5295f757f3fSDimitry Andric return Printable([&LISLR, &TrackedLR, TRI, Pfx](raw_ostream &OS) {
5300b57cec5SDimitry Andric for (auto const &P : TrackedLR) {
5310b57cec5SDimitry Andric auto I = LISLR.find(P.first);
5320b57cec5SDimitry Andric if (I == LISLR.end()) {
5335f757f3fSDimitry Andric OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
5340b57cec5SDimitry Andric << " isn't found in LIS reported set\n";
535bdd1243dSDimitry Andric } else if (I->second != P.second) {
5365f757f3fSDimitry Andric OS << Pfx << printReg(P.first, TRI)
537bdd1243dSDimitry Andric << " masks doesn't match: LIS reported " << PrintLaneMask(I->second)
538bdd1243dSDimitry Andric << ", tracked " << PrintLaneMask(P.second) << '\n';
5390b57cec5SDimitry Andric }
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric for (auto const &P : LISLR) {
5420b57cec5SDimitry Andric auto I = TrackedLR.find(P.first);
5430b57cec5SDimitry Andric if (I == TrackedLR.end()) {
5445f757f3fSDimitry Andric OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second)
5450b57cec5SDimitry Andric << " isn't found in tracked set\n";
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric }
548bdd1243dSDimitry Andric });
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric
isValid() const5510b57cec5SDimitry Andric bool GCNUpwardRPTracker::isValid() const {
5520b57cec5SDimitry Andric const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
5530b57cec5SDimitry Andric const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
5540b57cec5SDimitry Andric const auto &TrackedLR = LiveRegs;
5550b57cec5SDimitry Andric
5560b57cec5SDimitry Andric if (!isEqual(LISLR, TrackedLR)) {
5570b57cec5SDimitry Andric dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
558bdd1243dSDimitry Andric " LIS reported livesets mismatch:\n"
559bdd1243dSDimitry Andric << print(LISLR, *MRI);
5600b57cec5SDimitry Andric reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo());
5610b57cec5SDimitry Andric return false;
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric
5640b57cec5SDimitry Andric auto LISPressure = getRegPressure(*MRI, LISLR);
5650b57cec5SDimitry Andric if (LISPressure != CurPressure) {
566bdd1243dSDimitry Andric dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: "
567bdd1243dSDimitry Andric << print(CurPressure) << "LIS rpt: " << print(LISPressure);
5680b57cec5SDimitry Andric return false;
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric return true;
5710b57cec5SDimitry Andric }
5720b57cec5SDimitry Andric
print(const GCNRPTracker::LiveRegSet & LiveRegs,const MachineRegisterInfo & MRI)573bdd1243dSDimitry Andric Printable llvm::print(const GCNRPTracker::LiveRegSet &LiveRegs,
5740b57cec5SDimitry Andric const MachineRegisterInfo &MRI) {
575bdd1243dSDimitry Andric return Printable([&LiveRegs, &MRI](raw_ostream &OS) {
5760b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
5770b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
57804eeddc0SDimitry Andric Register Reg = Register::index2VirtReg(I);
5790b57cec5SDimitry Andric auto It = LiveRegs.find(Reg);
5800b57cec5SDimitry Andric if (It != LiveRegs.end() && It->second.any())
5810b57cec5SDimitry Andric OS << ' ' << printVRegOrUnit(Reg, TRI) << ':'
5820b57cec5SDimitry Andric << PrintLaneMask(It->second);
5830b57cec5SDimitry Andric }
5840b57cec5SDimitry Andric OS << '\n';
585bdd1243dSDimitry Andric });
5860b57cec5SDimitry Andric }
587bdd1243dSDimitry Andric
dump() const588bdd1243dSDimitry Andric void GCNRegPressure::dump() const { dbgs() << print(*this); }
589bdd1243dSDimitry Andric
5905f757f3fSDimitry Andric static cl::opt<bool> UseDownwardTracker(
5915f757f3fSDimitry Andric "amdgpu-print-rp-downward",
5925f757f3fSDimitry Andric cl::desc("Use GCNDownwardRPTracker for GCNRegPressurePrinter pass"),
5935f757f3fSDimitry Andric cl::init(false), cl::Hidden);
5945f757f3fSDimitry Andric
5955f757f3fSDimitry Andric char llvm::GCNRegPressurePrinter::ID = 0;
5965f757f3fSDimitry Andric char &llvm::GCNRegPressurePrinterID = GCNRegPressurePrinter::ID;
5975f757f3fSDimitry Andric
5985f757f3fSDimitry Andric INITIALIZE_PASS(GCNRegPressurePrinter, "amdgpu-print-rp", "", true, true)
5995f757f3fSDimitry Andric
6005f757f3fSDimitry Andric // Return lanemask of Reg's subregs that are live-through at [Begin, End] and
6015f757f3fSDimitry Andric // are fully covered by Mask.
6025f757f3fSDimitry Andric static LaneBitmask
getRegLiveThroughMask(const MachineRegisterInfo & MRI,const LiveIntervals & LIS,Register Reg,SlotIndex Begin,SlotIndex End,LaneBitmask Mask=LaneBitmask::getAll ())6035f757f3fSDimitry Andric getRegLiveThroughMask(const MachineRegisterInfo &MRI, const LiveIntervals &LIS,
6045f757f3fSDimitry Andric Register Reg, SlotIndex Begin, SlotIndex End,
6055f757f3fSDimitry Andric LaneBitmask Mask = LaneBitmask::getAll()) {
6065f757f3fSDimitry Andric
6075f757f3fSDimitry Andric auto IsInOneSegment = [Begin, End](const LiveRange &LR) -> bool {
6085f757f3fSDimitry Andric auto *Segment = LR.getSegmentContaining(Begin);
6095f757f3fSDimitry Andric return Segment && Segment->contains(End);
6105f757f3fSDimitry Andric };
6115f757f3fSDimitry Andric
6125f757f3fSDimitry Andric LaneBitmask LiveThroughMask;
6135f757f3fSDimitry Andric const LiveInterval &LI = LIS.getInterval(Reg);
6145f757f3fSDimitry Andric if (LI.hasSubRanges()) {
6155f757f3fSDimitry Andric for (auto &SR : LI.subranges()) {
6165f757f3fSDimitry Andric if ((SR.LaneMask & Mask) == SR.LaneMask && IsInOneSegment(SR))
6175f757f3fSDimitry Andric LiveThroughMask |= SR.LaneMask;
6185f757f3fSDimitry Andric }
6195f757f3fSDimitry Andric } else {
6205f757f3fSDimitry Andric LaneBitmask RegMask = MRI.getMaxLaneMaskForVReg(Reg);
6215f757f3fSDimitry Andric if ((RegMask & Mask) == RegMask && IsInOneSegment(LI))
6225f757f3fSDimitry Andric LiveThroughMask = RegMask;
6235f757f3fSDimitry Andric }
6245f757f3fSDimitry Andric
6255f757f3fSDimitry Andric return LiveThroughMask;
6265f757f3fSDimitry Andric }
6275f757f3fSDimitry Andric
runOnMachineFunction(MachineFunction & MF)6285f757f3fSDimitry Andric bool GCNRegPressurePrinter::runOnMachineFunction(MachineFunction &MF) {
6295f757f3fSDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo();
6305f757f3fSDimitry Andric const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
631*0fca6ea1SDimitry Andric const LiveIntervals &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
6325f757f3fSDimitry Andric
6335f757f3fSDimitry Andric auto &OS = dbgs();
6345f757f3fSDimitry Andric
6355f757f3fSDimitry Andric // Leading spaces are important for YAML syntax.
6365f757f3fSDimitry Andric #define PFX " "
6375f757f3fSDimitry Andric
6385f757f3fSDimitry Andric OS << "---\nname: " << MF.getName() << "\nbody: |\n";
6395f757f3fSDimitry Andric
6405f757f3fSDimitry Andric auto printRP = [](const GCNRegPressure &RP) {
6415f757f3fSDimitry Andric return Printable([&RP](raw_ostream &OS) {
6425f757f3fSDimitry Andric OS << format(PFX " %-5d", RP.getSGPRNum())
6435f757f3fSDimitry Andric << format(" %-5d", RP.getVGPRNum(false));
6445f757f3fSDimitry Andric });
6455f757f3fSDimitry Andric };
6465f757f3fSDimitry Andric
6475f757f3fSDimitry Andric auto ReportLISMismatchIfAny = [&](const GCNRPTracker::LiveRegSet &TrackedLR,
6485f757f3fSDimitry Andric const GCNRPTracker::LiveRegSet &LISLR) {
6495f757f3fSDimitry Andric if (LISLR != TrackedLR) {
6505f757f3fSDimitry Andric OS << PFX " mis LIS: " << llvm::print(LISLR, MRI)
6515f757f3fSDimitry Andric << reportMismatch(LISLR, TrackedLR, TRI, PFX " ");
6525f757f3fSDimitry Andric }
6535f757f3fSDimitry Andric };
6545f757f3fSDimitry Andric
6555f757f3fSDimitry Andric // Register pressure before and at an instruction (in program order).
6565f757f3fSDimitry Andric SmallVector<std::pair<GCNRegPressure, GCNRegPressure>, 16> RP;
6575f757f3fSDimitry Andric
6585f757f3fSDimitry Andric for (auto &MBB : MF) {
6595f757f3fSDimitry Andric RP.clear();
6605f757f3fSDimitry Andric RP.reserve(MBB.size());
6615f757f3fSDimitry Andric
6625f757f3fSDimitry Andric OS << PFX;
6635f757f3fSDimitry Andric MBB.printName(OS);
6645f757f3fSDimitry Andric OS << ":\n";
6655f757f3fSDimitry Andric
6665f757f3fSDimitry Andric SlotIndex MBBStartSlot = LIS.getSlotIndexes()->getMBBStartIdx(&MBB);
6675f757f3fSDimitry Andric SlotIndex MBBEndSlot = LIS.getSlotIndexes()->getMBBEndIdx(&MBB);
6685f757f3fSDimitry Andric
6695f757f3fSDimitry Andric GCNRPTracker::LiveRegSet LiveIn, LiveOut;
6705f757f3fSDimitry Andric GCNRegPressure RPAtMBBEnd;
6715f757f3fSDimitry Andric
6725f757f3fSDimitry Andric if (UseDownwardTracker) {
6735f757f3fSDimitry Andric if (MBB.empty()) {
6745f757f3fSDimitry Andric LiveIn = LiveOut = getLiveRegs(MBBStartSlot, LIS, MRI);
6755f757f3fSDimitry Andric RPAtMBBEnd = getRegPressure(MRI, LiveIn);
6765f757f3fSDimitry Andric } else {
6775f757f3fSDimitry Andric GCNDownwardRPTracker RPT(LIS);
6785f757f3fSDimitry Andric RPT.reset(MBB.front());
6795f757f3fSDimitry Andric
6805f757f3fSDimitry Andric LiveIn = RPT.getLiveRegs();
6815f757f3fSDimitry Andric
6825f757f3fSDimitry Andric while (!RPT.advanceBeforeNext()) {
6835f757f3fSDimitry Andric GCNRegPressure RPBeforeMI = RPT.getPressure();
6845f757f3fSDimitry Andric RPT.advanceToNext();
6855f757f3fSDimitry Andric RP.emplace_back(RPBeforeMI, RPT.getPressure());
6865f757f3fSDimitry Andric }
6875f757f3fSDimitry Andric
6885f757f3fSDimitry Andric LiveOut = RPT.getLiveRegs();
6895f757f3fSDimitry Andric RPAtMBBEnd = RPT.getPressure();
6905f757f3fSDimitry Andric }
6915f757f3fSDimitry Andric } else {
6925f757f3fSDimitry Andric GCNUpwardRPTracker RPT(LIS);
6935f757f3fSDimitry Andric RPT.reset(MRI, MBBEndSlot);
6945f757f3fSDimitry Andric
6955f757f3fSDimitry Andric LiveOut = RPT.getLiveRegs();
6965f757f3fSDimitry Andric RPAtMBBEnd = RPT.getPressure();
6975f757f3fSDimitry Andric
6985f757f3fSDimitry Andric for (auto &MI : reverse(MBB)) {
6995f757f3fSDimitry Andric RPT.resetMaxPressure();
7005f757f3fSDimitry Andric RPT.recede(MI);
7015f757f3fSDimitry Andric if (!MI.isDebugInstr())
7025f757f3fSDimitry Andric RP.emplace_back(RPT.getPressure(), RPT.getMaxPressure());
7035f757f3fSDimitry Andric }
7045f757f3fSDimitry Andric
7055f757f3fSDimitry Andric LiveIn = RPT.getLiveRegs();
7065f757f3fSDimitry Andric }
7075f757f3fSDimitry Andric
7085f757f3fSDimitry Andric OS << PFX " Live-in: " << llvm::print(LiveIn, MRI);
7095f757f3fSDimitry Andric if (!UseDownwardTracker)
7105f757f3fSDimitry Andric ReportLISMismatchIfAny(LiveIn, getLiveRegs(MBBStartSlot, LIS, MRI));
7115f757f3fSDimitry Andric
7125f757f3fSDimitry Andric OS << PFX " SGPR VGPR\n";
7135f757f3fSDimitry Andric int I = 0;
7145f757f3fSDimitry Andric for (auto &MI : MBB) {
7155f757f3fSDimitry Andric if (!MI.isDebugInstr()) {
7165f757f3fSDimitry Andric auto &[RPBeforeInstr, RPAtInstr] =
7175f757f3fSDimitry Andric RP[UseDownwardTracker ? I : (RP.size() - 1 - I)];
7185f757f3fSDimitry Andric ++I;
7195f757f3fSDimitry Andric OS << printRP(RPBeforeInstr) << '\n' << printRP(RPAtInstr) << " ";
7205f757f3fSDimitry Andric } else
7215f757f3fSDimitry Andric OS << PFX " ";
7225f757f3fSDimitry Andric MI.print(OS);
7235f757f3fSDimitry Andric }
7245f757f3fSDimitry Andric OS << printRP(RPAtMBBEnd) << '\n';
7255f757f3fSDimitry Andric
7265f757f3fSDimitry Andric OS << PFX " Live-out:" << llvm::print(LiveOut, MRI);
7275f757f3fSDimitry Andric if (UseDownwardTracker)
7285f757f3fSDimitry Andric ReportLISMismatchIfAny(LiveOut, getLiveRegs(MBBEndSlot, LIS, MRI));
7295f757f3fSDimitry Andric
7305f757f3fSDimitry Andric GCNRPTracker::LiveRegSet LiveThrough;
7315f757f3fSDimitry Andric for (auto [Reg, Mask] : LiveIn) {
7325f757f3fSDimitry Andric LaneBitmask MaskIntersection = Mask & LiveOut.lookup(Reg);
7335f757f3fSDimitry Andric if (MaskIntersection.any()) {
7345f757f3fSDimitry Andric LaneBitmask LTMask = getRegLiveThroughMask(
7355f757f3fSDimitry Andric MRI, LIS, Reg, MBBStartSlot, MBBEndSlot, MaskIntersection);
7365f757f3fSDimitry Andric if (LTMask.any())
7375f757f3fSDimitry Andric LiveThrough[Reg] = LTMask;
7385f757f3fSDimitry Andric }
7395f757f3fSDimitry Andric }
7405f757f3fSDimitry Andric OS << PFX " Live-thr:" << llvm::print(LiveThrough, MRI);
7415f757f3fSDimitry Andric OS << printRP(getRegPressure(MRI, LiveThrough)) << '\n';
7425f757f3fSDimitry Andric }
7435f757f3fSDimitry Andric OS << "...\n";
7445f757f3fSDimitry Andric return false;
7455f757f3fSDimitry Andric
7465f757f3fSDimitry Andric #undef PFX
7475f757f3fSDimitry Andric }