xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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