1 //===------------------------- GCNRegPressure.cpp - -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 //===----------------------------------------------------------------------===//
14 #include "GCNRegPressure.h"
18 #define DEBUG_TYPE "misched"
20 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
22 void llvm::printLivesAt(SlotIndex SI,
23 const LiveIntervals &LIS,
24 const MachineRegisterInfo &MRI) {
25 dbgs() << "Live regs at " << SI << ": "
26 << *LIS.getInstructionFromIndex(SI);
28 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
29 const unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
30 if (MRI.reg_nodbg_empty(Reg))
32 const auto &LI = LIS.getInterval(Reg);
33 if (LI.hasSubRanges()) {
34 bool firstTime = true;
35 for (const auto &S : LI.subranges()) {
36 if (!S.liveAt(SI)) continue;
38 dbgs() << " " << PrintReg(Reg, MRI.getTargetRegisterInfo())
42 dbgs() << " " << S << '\n';
45 } else if (LI.liveAt(SI)) {
46 dbgs() << " " << LI << '\n';
50 if (!Num) dbgs() << " <none>\n";
53 static bool isEqual(const GCNRPTracker::LiveRegSet &S1,
54 const GCNRPTracker::LiveRegSet &S2) {
55 if (S1.size() != S2.size())
58 for (const auto &P : S1) {
59 auto I = S2.find(P.first);
60 if (I == S2.end() || I->second != P.second)
66 static GCNRPTracker::LiveRegSet
67 stripEmpty(const GCNRPTracker::LiveRegSet &LR) {
68 GCNRPTracker::LiveRegSet Res;
69 for (const auto &P : LR) {
77 ///////////////////////////////////////////////////////////////////////////////
80 unsigned GCNRegPressure::getRegKind(unsigned Reg,
81 const MachineRegisterInfo &MRI) {
82 assert(TargetRegisterInfo::isVirtualRegister(Reg));
83 const auto RC = MRI.getRegClass(Reg);
84 auto STI = static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo());
85 return STI->isSGPRClass(RC) ?
86 (RC->getSize() == 4 ? SGPR32 : SGPR_TUPLE) :
87 (RC->getSize() == 4 ? VGPR32 : VGPR_TUPLE);
90 void GCNRegPressure::inc(unsigned Reg,
93 const MachineRegisterInfo &MRI) {
94 if (NewMask == PrevMask)
98 if (NewMask < PrevMask) {
99 std::swap(NewMask, PrevMask);
103 const auto MaxMask = MRI.getMaxLaneMaskForVReg(Reg);
105 switch (auto Kind = getRegKind(Reg, MRI)) {
108 assert(PrevMask.none() && NewMask == MaxMask);
114 assert(NewMask < MaxMask || NewMask == MaxMask);
115 assert(PrevMask < NewMask);
117 Value[Kind == SGPR_TUPLE ? SGPR32 : VGPR32] +=
118 Sign * countPopulation((~PrevMask & NewMask).getAsInteger());
120 if (PrevMask.none()) {
121 assert(NewMask.any());
122 Value[Kind] += Sign * MRI.getPressureSets(Reg).getWeight();
126 default: llvm_unreachable("Unknown register kind");
130 bool GCNRegPressure::less(const SISubtarget &ST,
131 const GCNRegPressure& O,
132 unsigned MaxOccupancy) const {
133 const auto SGPROcc = std::min(MaxOccupancy,
134 ST.getOccupancyWithNumSGPRs(getSGRPNum()));
135 const auto VGPROcc = std::min(MaxOccupancy,
136 ST.getOccupancyWithNumVGPRs(getVGRPNum()));
137 const auto OtherSGPROcc = std::min(MaxOccupancy,
138 ST.getOccupancyWithNumSGPRs(O.getSGRPNum()));
139 const auto OtherVGPROcc = std::min(MaxOccupancy,
140 ST.getOccupancyWithNumVGPRs(O.getVGRPNum()));
142 const auto Occ = std::min(SGPROcc, VGPROcc);
143 const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc);
145 return Occ > OtherOcc;
147 bool SGPRImportant = SGPROcc < VGPROcc;
148 const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc;
150 // if both pressures disagree on what is more important compare vgprs
151 if (SGPRImportant != OtherSGPRImportant) {
152 SGPRImportant = false;
155 // compare large regs pressure
156 bool SGPRFirst = SGPRImportant;
157 for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) {
159 auto SW = getSGPRTuplesWeight();
160 auto OtherSW = O.getSGPRTuplesWeight();
164 auto VW = getVGPRTuplesWeight();
165 auto OtherVW = O.getVGPRTuplesWeight();
170 return SGPRImportant ? (getSGRPNum() < O.getSGRPNum()):
171 (getVGRPNum() < O.getVGRPNum());
174 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
176 void GCNRegPressure::print(raw_ostream &OS, const SISubtarget *ST) const {
177 OS << "VGPRs: " << getVGRPNum();
178 if (ST) OS << "(O" << ST->getOccupancyWithNumVGPRs(getVGRPNum()) << ')';
179 OS << ", SGPRs: " << getSGRPNum();
180 if (ST) OS << "(O" << ST->getOccupancyWithNumSGPRs(getSGRPNum()) << ')';
181 OS << ", LVGPR WT: " << getVGPRTuplesWeight()
182 << ", LSGPR WT: " << getSGPRTuplesWeight();
183 if (ST) OS << " -> Occ: " << getOccupancy(*ST);
188 ///////////////////////////////////////////////////////////////////////////////
191 LaneBitmask llvm::getLiveLaneMask(unsigned Reg,
193 const LiveIntervals &LIS,
194 const MachineRegisterInfo &MRI) {
195 assert(!MRI.reg_nodbg_empty(Reg));
196 LaneBitmask LiveMask;
197 const auto &LI = LIS.getInterval(Reg);
198 if (LI.hasSubRanges()) {
199 for (const auto &S : LI.subranges())
201 LiveMask |= S.LaneMask;
202 assert(LiveMask < MRI.getMaxLaneMaskForVReg(Reg) ||
203 LiveMask == MRI.getMaxLaneMaskForVReg(Reg));
205 } else if (LI.liveAt(SI)) {
206 LiveMask = MRI.getMaxLaneMaskForVReg(Reg);
211 GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
212 const LiveIntervals &LIS,
213 const MachineRegisterInfo &MRI) {
214 GCNRPTracker::LiveRegSet LiveRegs;
215 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
216 auto Reg = TargetRegisterInfo::index2VirtReg(I);
217 if (MRI.reg_nodbg_empty(Reg))
219 auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI);
221 LiveRegs[Reg] = LiveMask;
226 void GCNUpwardRPTracker::reset(const MachineInstr &MI) {
227 MRI = &MI.getParent()->getParent()->getRegInfo();
228 LiveRegs = getLiveRegsAfter(MI, LIS);
229 MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs);
232 LaneBitmask GCNUpwardRPTracker::getDefRegMask(const MachineOperand &MO) const {
233 assert(MO.isDef() && MO.isReg() &&
234 TargetRegisterInfo::isVirtualRegister(MO.getReg()));
236 // We don't rely on read-undef flag because in case of tentative schedule
237 // tracking it isn't set correctly yet. This works correctly however since
238 // use mask has been tracked before using LIS.
239 return MO.getSubReg() == 0 ?
240 MRI->getMaxLaneMaskForVReg(MO.getReg()) :
241 MRI->getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
244 LaneBitmask GCNUpwardRPTracker::getUsedRegMask(const MachineOperand &MO) const {
245 assert(MO.isUse() && MO.isReg() &&
246 TargetRegisterInfo::isVirtualRegister(MO.getReg()));
248 if (auto SubReg = MO.getSubReg())
249 return MRI->getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg);
251 auto MaxMask = MRI->getMaxLaneMaskForVReg(MO.getReg());
252 if (MaxMask.getAsInteger() == 1) // cannot have subregs
255 // For a tentative schedule LIS isn't updated yet but livemask should remain
256 // the same on any schedule. Subreg defs can be reordered but they all must
257 // dominate uses anyway.
258 auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex();
259 return getLiveLaneMask(MO.getReg(), SI, LIS, *MRI);
262 void GCNUpwardRPTracker::recede(const MachineInstr &MI) {
263 assert(MRI && "call reset first");
267 if (MI.isDebugValue())
270 // process all defs first to ensure early clobbers are handled correctly
271 // iterating over operands() to catch implicit defs
272 for (const auto &MO : MI.operands()) {
273 if (!MO.isReg() || !MO.isDef() ||
274 !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
277 auto Reg = MO.getReg();
278 auto &LiveMask = LiveRegs[Reg];
279 auto PrevMask = LiveMask;
280 LiveMask &= ~getDefRegMask(MO);
281 CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
285 for (const auto &MO : MI.uses()) {
286 if (!MO.isReg() || !MO.readsReg() ||
287 !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
290 auto Reg = MO.getReg();
291 auto &LiveMask = LiveRegs[Reg];
292 auto PrevMask = LiveMask;
293 LiveMask |= getUsedRegMask(MO);
294 CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
297 MaxPressure = max(MaxPressure, CurPressure);
300 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
302 static void reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
303 const GCNRPTracker::LiveRegSet &TrackedLR,
304 const TargetRegisterInfo *TRI) {
305 for (auto const &P : TrackedLR) {
306 auto I = LISLR.find(P.first);
307 if (I == LISLR.end()) {
308 dbgs() << " " << PrintReg(P.first, TRI)
309 << ":L" << PrintLaneMask(P.second)
310 << " isn't found in LIS reported set\n";
312 else if (I->second != P.second) {
313 dbgs() << " " << PrintReg(P.first, TRI)
314 << " masks doesn't match: LIS reported "
315 << PrintLaneMask(I->second)
317 << PrintLaneMask(P.second)
321 for (auto const &P : LISLR) {
322 auto I = TrackedLR.find(P.first);
323 if (I == TrackedLR.end()) {
324 dbgs() << " " << PrintReg(P.first, TRI)
325 << ":L" << PrintLaneMask(P.second)
326 << " isn't found in tracked set\n";
331 bool GCNUpwardRPTracker::isValid() const {
332 const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
333 const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
334 const auto TrackedLR = stripEmpty(LiveRegs);
336 if (!isEqual(LISLR, TrackedLR)) {
337 dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
338 " LIS reported livesets mismatch:\n";
339 printLivesAt(SI, LIS, *MRI);
340 reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo());
344 auto LISPressure = getRegPressure(*MRI, LISLR);
345 if (LISPressure != CurPressure) {
346 dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: ";
347 CurPressure.print(dbgs());
348 dbgs() << "LIS rpt: ";
349 LISPressure.print(dbgs());