blob: e2334f2681ab85641bd18939b8a63c37b916ded7 [file] [log] [blame]
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +00001//===------------------------- GCNRegPressure.cpp - -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10/// \file
11//
12//===----------------------------------------------------------------------===//
13
14#include "GCNRegPressure.h"
15
16using namespace llvm;
17
18#define DEBUG_TYPE "misched"
19
20#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
21LLVM_DUMP_METHOD
22void llvm::printLivesAt(SlotIndex SI,
23 const LiveIntervals &LIS,
24 const MachineRegisterInfo &MRI) {
25 dbgs() << "Live regs at " << SI << ": "
26 << *LIS.getInstructionFromIndex(SI);
27 unsigned Num = 0;
28 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
29 const unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
Stanislav Mekhanoshine61df312017-05-16 15:43:52 +000030 if (!LIS.hasInterval(Reg))
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +000031 continue;
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;
37 if (firstTime) {
38 dbgs() << " " << PrintReg(Reg, MRI.getTargetRegisterInfo())
39 << '\n';
40 firstTime = false;
41 }
42 dbgs() << " " << S << '\n';
43 ++Num;
44 }
45 } else if (LI.liveAt(SI)) {
46 dbgs() << " " << LI << '\n';
47 ++Num;
48 }
49 }
50 if (!Num) dbgs() << " <none>\n";
51}
52
53static bool isEqual(const GCNRPTracker::LiveRegSet &S1,
54 const GCNRPTracker::LiveRegSet &S2) {
55 if (S1.size() != S2.size())
56 return false;
57
58 for (const auto &P : S1) {
59 auto I = S2.find(P.first);
60 if (I == S2.end() || I->second != P.second)
61 return false;
62 }
63 return true;
64}
65
66static GCNRPTracker::LiveRegSet
67stripEmpty(const GCNRPTracker::LiveRegSet &LR) {
68 GCNRPTracker::LiveRegSet Res;
69 for (const auto &P : LR) {
70 if (P.second.any())
71 Res.insert(P);
72 }
73 return Res;
74}
75#endif
76
77///////////////////////////////////////////////////////////////////////////////
78// GCNRegPressure
79
80unsigned 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) ?
Krzysztof Parzyszek36d7c2b2017-04-24 18:55:33 +000086 (STI->getRegSizeInBits(*RC) == 32 ? SGPR32 : SGPR_TUPLE) :
87 (STI->getRegSizeInBits(*RC) == 32 ? VGPR32 : VGPR_TUPLE);
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +000088}
89
90void GCNRegPressure::inc(unsigned Reg,
91 LaneBitmask PrevMask,
92 LaneBitmask NewMask,
93 const MachineRegisterInfo &MRI) {
94 if (NewMask == PrevMask)
95 return;
96
97 int Sign = 1;
98 if (NewMask < PrevMask) {
99 std::swap(NewMask, PrevMask);
100 Sign = -1;
101 }
102#ifndef NDEBUG
103 const auto MaxMask = MRI.getMaxLaneMaskForVReg(Reg);
104#endif
105 switch (auto Kind = getRegKind(Reg, MRI)) {
106 case SGPR32:
107 case VGPR32:
108 assert(PrevMask.none() && NewMask == MaxMask);
109 Value[Kind] += Sign;
110 break;
111
112 case SGPR_TUPLE:
113 case VGPR_TUPLE:
114 assert(NewMask < MaxMask || NewMask == MaxMask);
115 assert(PrevMask < NewMask);
116
117 Value[Kind == SGPR_TUPLE ? SGPR32 : VGPR32] +=
118 Sign * countPopulation((~PrevMask & NewMask).getAsInteger());
119
120 if (PrevMask.none()) {
121 assert(NewMask.any());
122 Value[Kind] += Sign * MRI.getPressureSets(Reg).getWeight();
123 }
124 break;
125
126 default: llvm_unreachable("Unknown register kind");
127 }
128}
129
130bool GCNRegPressure::less(const SISubtarget &ST,
131 const GCNRegPressure& O,
132 unsigned MaxOccupancy) const {
133 const auto SGPROcc = std::min(MaxOccupancy,
Stanislav Mekhanoshinf7e31582017-05-09 20:50:04 +0000134 ST.getOccupancyWithNumSGPRs(getSGPRNum()));
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000135 const auto VGPROcc = std::min(MaxOccupancy,
Stanislav Mekhanoshinf7e31582017-05-09 20:50:04 +0000136 ST.getOccupancyWithNumVGPRs(getVGPRNum()));
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000137 const auto OtherSGPROcc = std::min(MaxOccupancy,
Stanislav Mekhanoshinf7e31582017-05-09 20:50:04 +0000138 ST.getOccupancyWithNumSGPRs(O.getSGPRNum()));
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000139 const auto OtherVGPROcc = std::min(MaxOccupancy,
Stanislav Mekhanoshinf7e31582017-05-09 20:50:04 +0000140 ST.getOccupancyWithNumVGPRs(O.getVGPRNum()));
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000141
142 const auto Occ = std::min(SGPROcc, VGPROcc);
143 const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc);
144 if (Occ != OtherOcc)
145 return Occ > OtherOcc;
146
147 bool SGPRImportant = SGPROcc < VGPROcc;
148 const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc;
149
150 // if both pressures disagree on what is more important compare vgprs
151 if (SGPRImportant != OtherSGPRImportant) {
152 SGPRImportant = false;
153 }
154
155 // compare large regs pressure
156 bool SGPRFirst = SGPRImportant;
157 for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) {
158 if (SGPRFirst) {
159 auto SW = getSGPRTuplesWeight();
160 auto OtherSW = O.getSGPRTuplesWeight();
161 if (SW != OtherSW)
162 return SW < OtherSW;
163 } else {
164 auto VW = getVGPRTuplesWeight();
165 auto OtherVW = O.getVGPRTuplesWeight();
166 if (VW != OtherVW)
167 return VW < OtherVW;
168 }
169 }
Stanislav Mekhanoshinf7e31582017-05-09 20:50:04 +0000170 return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()):
171 (getVGPRNum() < O.getVGPRNum());
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000172}
173
174#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
175LLVM_DUMP_METHOD
176void GCNRegPressure::print(raw_ostream &OS, const SISubtarget *ST) const {
Stanislav Mekhanoshinf7e31582017-05-09 20:50:04 +0000177 OS << "VGPRs: " << getVGPRNum();
178 if (ST) OS << "(O" << ST->getOccupancyWithNumVGPRs(getVGPRNum()) << ')';
179 OS << ", SGPRs: " << getSGPRNum();
180 if (ST) OS << "(O" << ST->getOccupancyWithNumSGPRs(getSGPRNum()) << ')';
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000181 OS << ", LVGPR WT: " << getVGPRTuplesWeight()
182 << ", LSGPR WT: " << getSGPRTuplesWeight();
183 if (ST) OS << " -> Occ: " << getOccupancy(*ST);
184 OS << '\n';
185}
186#endif
187
188///////////////////////////////////////////////////////////////////////////////
189// GCNRPTracker
190
191LaneBitmask llvm::getLiveLaneMask(unsigned Reg,
192 SlotIndex SI,
193 const LiveIntervals &LIS,
194 const MachineRegisterInfo &MRI) {
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000195 LaneBitmask LiveMask;
196 const auto &LI = LIS.getInterval(Reg);
197 if (LI.hasSubRanges()) {
198 for (const auto &S : LI.subranges())
199 if (S.liveAt(SI)) {
200 LiveMask |= S.LaneMask;
201 assert(LiveMask < MRI.getMaxLaneMaskForVReg(Reg) ||
202 LiveMask == MRI.getMaxLaneMaskForVReg(Reg));
203 }
204 } else if (LI.liveAt(SI)) {
205 LiveMask = MRI.getMaxLaneMaskForVReg(Reg);
206 }
207 return LiveMask;
208}
209
210GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
211 const LiveIntervals &LIS,
212 const MachineRegisterInfo &MRI) {
213 GCNRPTracker::LiveRegSet LiveRegs;
214 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
215 auto Reg = TargetRegisterInfo::index2VirtReg(I);
Stanislav Mekhanoshine61df312017-05-16 15:43:52 +0000216 if (!LIS.hasInterval(Reg))
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000217 continue;
218 auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI);
219 if (LiveMask.any())
220 LiveRegs[Reg] = LiveMask;
221 }
222 return LiveRegs;
223}
224
Stanislav Mekhanoshine61df312017-05-16 15:43:52 +0000225LaneBitmask GCNRPTracker::getDefRegMask(const MachineOperand &MO) const {
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000226 assert(MO.isDef() && MO.isReg() &&
227 TargetRegisterInfo::isVirtualRegister(MO.getReg()));
228
229 // We don't rely on read-undef flag because in case of tentative schedule
230 // tracking it isn't set correctly yet. This works correctly however since
231 // use mask has been tracked before using LIS.
232 return MO.getSubReg() == 0 ?
233 MRI->getMaxLaneMaskForVReg(MO.getReg()) :
234 MRI->getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg());
235}
236
Stanislav Mekhanoshine61df312017-05-16 15:43:52 +0000237LaneBitmask GCNRPTracker::getUsedRegMask(const MachineOperand &MO) const {
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000238 assert(MO.isUse() && MO.isReg() &&
239 TargetRegisterInfo::isVirtualRegister(MO.getReg()));
240
241 if (auto SubReg = MO.getSubReg())
242 return MRI->getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg);
243
244 auto MaxMask = MRI->getMaxLaneMaskForVReg(MO.getReg());
245 if (MaxMask.getAsInteger() == 1) // cannot have subregs
246 return MaxMask;
247
248 // For a tentative schedule LIS isn't updated yet but livemask should remain
249 // the same on any schedule. Subreg defs can be reordered but they all must
250 // dominate uses anyway.
251 auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex();
252 return getLiveLaneMask(MO.getReg(), SI, LIS, *MRI);
253}
254
Stanislav Mekhanoshine61df312017-05-16 15:43:52 +0000255void GCNUpwardRPTracker::reset(const MachineInstr &MI,
256 const LiveRegSet *LiveRegsCopy) {
257 MRI = &MI.getParent()->getParent()->getRegInfo();
258 if (LiveRegsCopy) {
259 if (&LiveRegs != LiveRegsCopy)
260 LiveRegs = *LiveRegsCopy;
261 } else {
262 LiveRegs = getLiveRegsAfter(MI, LIS);
263 }
264 MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs);
265}
266
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000267void GCNUpwardRPTracker::recede(const MachineInstr &MI) {
268 assert(MRI && "call reset first");
269
270 LastTrackedMI = &MI;
271
272 if (MI.isDebugValue())
273 return;
274
275 // process all defs first to ensure early clobbers are handled correctly
276 // iterating over operands() to catch implicit defs
277 for (const auto &MO : MI.operands()) {
278 if (!MO.isReg() || !MO.isDef() ||
279 !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
280 continue;
281
282 auto Reg = MO.getReg();
283 auto &LiveMask = LiveRegs[Reg];
284 auto PrevMask = LiveMask;
285 LiveMask &= ~getDefRegMask(MO);
286 CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
287 }
288
289 // then all uses
290 for (const auto &MO : MI.uses()) {
291 if (!MO.isReg() || !MO.readsReg() ||
292 !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
293 continue;
294
295 auto Reg = MO.getReg();
296 auto &LiveMask = LiveRegs[Reg];
297 auto PrevMask = LiveMask;
298 LiveMask |= getUsedRegMask(MO);
299 CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
300 }
301
302 MaxPressure = max(MaxPressure, CurPressure);
303}
304
Stanislav Mekhanoshine61df312017-05-16 15:43:52 +0000305bool GCNDownwardRPTracker::reset(const MachineInstr &MI,
306 const LiveRegSet *LiveRegsCopy) {
307 MRI = &MI.getParent()->getParent()->getRegInfo();
308 LastTrackedMI = nullptr;
309 MBBEnd = MI.getParent()->end();
310 NextMI = &MI;
311 NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
312 if (NextMI == MBBEnd)
313 return false;
314 if (LiveRegsCopy) {
315 if (&LiveRegs != LiveRegsCopy)
316 LiveRegs = *LiveRegsCopy;
317 } else {
318 LiveRegs = getLiveRegsBefore(*NextMI, LIS);
319 }
320 MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs);
321 return true;
322}
323
324bool GCNDownwardRPTracker::advanceBeforeNext() {
325 assert(MRI && "call reset first");
326
327 NextMI = skipDebugInstructionsForward(NextMI, MBBEnd);
328 if (NextMI == MBBEnd)
329 return false;
330
331 SlotIndex SI = LIS.getInstructionIndex(*NextMI).getBaseIndex();
332 assert(SI.isValid());
333
334 // Remove dead registers or mask bits.
335 for (auto &It : LiveRegs) {
336 const LiveInterval &LI = LIS.getInterval(It.first);
337 if (LI.hasSubRanges()) {
338 for (const auto &S : LI.subranges()) {
339 if (!S.liveAt(SI)) {
340 auto PrevMask = It.second;
341 It.second &= ~S.LaneMask;
342 CurPressure.inc(It.first, PrevMask, It.second, *MRI);
343 }
344 }
345 } else if (!LI.liveAt(SI)) {
346 auto PrevMask = It.second;
347 It.second = LaneBitmask::getNone();
348 CurPressure.inc(It.first, PrevMask, It.second, *MRI);
349 }
350 if (It.second.none())
351 LiveRegs.erase(It.first);
352 }
353
354 MaxPressure = max(MaxPressure, CurPressure);
355
356 return true;
357}
358
359void GCNDownwardRPTracker::advanceToNext() {
360 LastTrackedMI = &*NextMI++;
361
362 // Add new registers or mask bits.
363 for (const auto &MO : LastTrackedMI->defs()) {
364 if (!MO.isReg())
365 continue;
366 unsigned Reg = MO.getReg();
367 if (!TargetRegisterInfo::isVirtualRegister(Reg))
368 continue;
369 auto &LiveMask = LiveRegs[Reg];
370 auto PrevMask = LiveMask;
371 LiveMask |= getDefRegMask(MO);
372 CurPressure.inc(Reg, PrevMask, LiveMask, *MRI);
373 }
374
375 MaxPressure = max(MaxPressure, CurPressure);
376}
377
378bool GCNDownwardRPTracker::advance() {
379 // If we have just called reset live set is actual.
380 if ((NextMI == MBBEnd) || (LastTrackedMI && !advanceBeforeNext()))
381 return false;
382 advanceToNext();
383 return true;
384}
385
386bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) {
387 while (NextMI != End)
388 if (!advance()) return false;
389 return true;
390}
391
392bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin,
393 MachineBasicBlock::const_iterator End,
394 const LiveRegSet *LiveRegsCopy) {
395 reset(*Begin, LiveRegsCopy);
396 return advance(End);
397}
398
Valery Pykhtin4b7cf6c2017-03-21 13:15:46 +0000399#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
400LLVM_DUMP_METHOD
401static void reportMismatch(const GCNRPTracker::LiveRegSet &LISLR,
402 const GCNRPTracker::LiveRegSet &TrackedLR,
403 const TargetRegisterInfo *TRI) {
404 for (auto const &P : TrackedLR) {
405 auto I = LISLR.find(P.first);
406 if (I == LISLR.end()) {
407 dbgs() << " " << PrintReg(P.first, TRI)
408 << ":L" << PrintLaneMask(P.second)
409 << " isn't found in LIS reported set\n";
410 }
411 else if (I->second != P.second) {
412 dbgs() << " " << PrintReg(P.first, TRI)
413 << " masks doesn't match: LIS reported "
414 << PrintLaneMask(I->second)
415 << ", tracked "
416 << PrintLaneMask(P.second)
417 << '\n';
418 }
419 }
420 for (auto const &P : LISLR) {
421 auto I = TrackedLR.find(P.first);
422 if (I == TrackedLR.end()) {
423 dbgs() << " " << PrintReg(P.first, TRI)
424 << ":L" << PrintLaneMask(P.second)
425 << " isn't found in tracked set\n";
426 }
427 }
428}
429
430bool GCNUpwardRPTracker::isValid() const {
431 const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex();
432 const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI);
433 const auto TrackedLR = stripEmpty(LiveRegs);
434
435 if (!isEqual(LISLR, TrackedLR)) {
436 dbgs() << "\nGCNUpwardRPTracker error: Tracked and"
437 " LIS reported livesets mismatch:\n";
438 printLivesAt(SI, LIS, *MRI);
439 reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo());
440 return false;
441 }
442
443 auto LISPressure = getRegPressure(*MRI, LISLR);
444 if (LISPressure != CurPressure) {
445 dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: ";
446 CurPressure.print(dbgs());
447 dbgs() << "LIS rpt: ";
448 LISPressure.print(dbgs());
449 return false;
450 }
451 return true;
452}
453
454#endif