1 //===- GCNRegPressure.cpp -------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file implements the GCNRegPressure class. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "GCNRegPressure.h" 15 #include "AMDGPU.h" 16 #include "llvm/CodeGen/RegisterPressure.h" 17 18 using namespace llvm; 19 20 #define DEBUG_TYPE "machine-scheduler" 21 22 bool llvm::isEqual(const GCNRPTracker::LiveRegSet &S1, 23 const GCNRPTracker::LiveRegSet &S2) { 24 if (S1.size() != S2.size()) 25 return false; 26 27 for (const auto &P : S1) { 28 auto I = S2.find(P.first); 29 if (I == S2.end() || I->second != P.second) 30 return false; 31 } 32 return true; 33 } 34 35 /////////////////////////////////////////////////////////////////////////////// 36 // GCNRegPressure 37 38 unsigned GCNRegPressure::getRegKind(Register Reg, 39 const MachineRegisterInfo &MRI) { 40 assert(Reg.isVirtual()); 41 const auto RC = MRI.getRegClass(Reg); 42 auto STI = static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo()); 43 return STI->isSGPRClass(RC) 44 ? (STI->getRegSizeInBits(*RC) == 32 ? SGPR32 : SGPR_TUPLE) 45 : STI->isAGPRClass(RC) 46 ? (STI->getRegSizeInBits(*RC) == 32 ? AGPR32 : AGPR_TUPLE) 47 : (STI->getRegSizeInBits(*RC) == 32 ? VGPR32 : VGPR_TUPLE); 48 } 49 50 void GCNRegPressure::inc(unsigned Reg, 51 LaneBitmask PrevMask, 52 LaneBitmask NewMask, 53 const MachineRegisterInfo &MRI) { 54 if (SIRegisterInfo::getNumCoveredRegs(NewMask) == 55 SIRegisterInfo::getNumCoveredRegs(PrevMask)) 56 return; 57 58 int Sign = 1; 59 if (NewMask < PrevMask) { 60 std::swap(NewMask, PrevMask); 61 Sign = -1; 62 } 63 64 switch (auto Kind = getRegKind(Reg, MRI)) { 65 case SGPR32: 66 case VGPR32: 67 case AGPR32: 68 Value[Kind] += Sign; 69 break; 70 71 case SGPR_TUPLE: 72 case VGPR_TUPLE: 73 case AGPR_TUPLE: 74 assert(PrevMask < NewMask); 75 76 Value[Kind == SGPR_TUPLE ? SGPR32 : Kind == AGPR_TUPLE ? AGPR32 : VGPR32] += 77 Sign * SIRegisterInfo::getNumCoveredRegs(~PrevMask & NewMask); 78 79 if (PrevMask.none()) { 80 assert(NewMask.any()); 81 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); 82 Value[Kind] += 83 Sign * TRI->getRegClassWeight(MRI.getRegClass(Reg)).RegWeight; 84 } 85 break; 86 87 default: llvm_unreachable("Unknown register kind"); 88 } 89 } 90 91 bool GCNRegPressure::less(const GCNSubtarget &ST, 92 const GCNRegPressure& O, 93 unsigned MaxOccupancy) const { 94 const auto SGPROcc = std::min(MaxOccupancy, 95 ST.getOccupancyWithNumSGPRs(getSGPRNum())); 96 const auto VGPROcc = 97 std::min(MaxOccupancy, 98 ST.getOccupancyWithNumVGPRs(getVGPRNum(ST.hasGFX90AInsts()))); 99 const auto OtherSGPROcc = std::min(MaxOccupancy, 100 ST.getOccupancyWithNumSGPRs(O.getSGPRNum())); 101 const auto OtherVGPROcc = 102 std::min(MaxOccupancy, 103 ST.getOccupancyWithNumVGPRs(O.getVGPRNum(ST.hasGFX90AInsts()))); 104 105 const auto Occ = std::min(SGPROcc, VGPROcc); 106 const auto OtherOcc = std::min(OtherSGPROcc, OtherVGPROcc); 107 if (Occ != OtherOcc) 108 return Occ > OtherOcc; 109 110 bool SGPRImportant = SGPROcc < VGPROcc; 111 const bool OtherSGPRImportant = OtherSGPROcc < OtherVGPROcc; 112 113 // if both pressures disagree on what is more important compare vgprs 114 if (SGPRImportant != OtherSGPRImportant) { 115 SGPRImportant = false; 116 } 117 118 // compare large regs pressure 119 bool SGPRFirst = SGPRImportant; 120 for (int I = 2; I > 0; --I, SGPRFirst = !SGPRFirst) { 121 if (SGPRFirst) { 122 auto SW = getSGPRTuplesWeight(); 123 auto OtherSW = O.getSGPRTuplesWeight(); 124 if (SW != OtherSW) 125 return SW < OtherSW; 126 } else { 127 auto VW = getVGPRTuplesWeight(); 128 auto OtherVW = O.getVGPRTuplesWeight(); 129 if (VW != OtherVW) 130 return VW < OtherVW; 131 } 132 } 133 return SGPRImportant ? (getSGPRNum() < O.getSGPRNum()): 134 (getVGPRNum(ST.hasGFX90AInsts()) < 135 O.getVGPRNum(ST.hasGFX90AInsts())); 136 } 137 138 Printable llvm::print(const GCNRegPressure &RP, const GCNSubtarget *ST) { 139 return Printable([&RP, ST](raw_ostream &OS) { 140 OS << "VGPRs: " << RP.Value[GCNRegPressure::VGPR32] << ' ' 141 << "AGPRs: " << RP.getAGPRNum(); 142 if (ST) 143 OS << "(O" 144 << ST->getOccupancyWithNumVGPRs(RP.getVGPRNum(ST->hasGFX90AInsts())) 145 << ')'; 146 OS << ", SGPRs: " << RP.getSGPRNum(); 147 if (ST) 148 OS << "(O" << ST->getOccupancyWithNumSGPRs(RP.getSGPRNum()) << ')'; 149 OS << ", LVGPR WT: " << RP.getVGPRTuplesWeight() 150 << ", LSGPR WT: " << RP.getSGPRTuplesWeight(); 151 if (ST) 152 OS << " -> Occ: " << RP.getOccupancy(*ST); 153 OS << '\n'; 154 }); 155 } 156 157 static LaneBitmask getDefRegMask(const MachineOperand &MO, 158 const MachineRegisterInfo &MRI) { 159 assert(MO.isDef() && MO.isReg() && MO.getReg().isVirtual()); 160 161 // We don't rely on read-undef flag because in case of tentative schedule 162 // tracking it isn't set correctly yet. This works correctly however since 163 // use mask has been tracked before using LIS. 164 return MO.getSubReg() == 0 ? 165 MRI.getMaxLaneMaskForVReg(MO.getReg()) : 166 MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg()); 167 } 168 169 static void 170 collectVirtualRegUses(SmallVectorImpl<RegisterMaskPair> &RegMaskPairs, 171 const MachineInstr &MI, const LiveIntervals &LIS, 172 const MachineRegisterInfo &MRI) { 173 SlotIndex InstrSI; 174 for (const auto &MO : MI.operands()) { 175 if (!MO.isReg() || !MO.getReg().isVirtual()) 176 continue; 177 if (!MO.isUse() || !MO.readsReg()) 178 continue; 179 180 Register Reg = MO.getReg(); 181 if (llvm::any_of(RegMaskPairs, [Reg](const RegisterMaskPair &RM) { 182 return RM.RegUnit == Reg; 183 })) 184 continue; 185 186 LaneBitmask UseMask; 187 auto &LI = LIS.getInterval(Reg); 188 if (!LI.hasSubRanges()) 189 UseMask = MRI.getMaxLaneMaskForVReg(Reg); 190 else { 191 // For a tentative schedule LIS isn't updated yet but livemask should 192 // remain the same on any schedule. Subreg defs can be reordered but they 193 // all must dominate uses anyway. 194 if (!InstrSI) 195 InstrSI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex(); 196 UseMask = getLiveLaneMask(LI, InstrSI, MRI); 197 } 198 199 RegMaskPairs.emplace_back(Reg, UseMask); 200 } 201 } 202 203 /////////////////////////////////////////////////////////////////////////////// 204 // GCNRPTracker 205 206 LaneBitmask llvm::getLiveLaneMask(unsigned Reg, SlotIndex SI, 207 const LiveIntervals &LIS, 208 const MachineRegisterInfo &MRI) { 209 return getLiveLaneMask(LIS.getInterval(Reg), SI, MRI); 210 } 211 212 LaneBitmask llvm::getLiveLaneMask(const LiveInterval &LI, SlotIndex SI, 213 const MachineRegisterInfo &MRI) { 214 LaneBitmask LiveMask; 215 if (LI.hasSubRanges()) { 216 for (const auto &S : LI.subranges()) 217 if (S.liveAt(SI)) { 218 LiveMask |= S.LaneMask; 219 assert(LiveMask == (LiveMask & MRI.getMaxLaneMaskForVReg(LI.reg()))); 220 } 221 } else if (LI.liveAt(SI)) { 222 LiveMask = MRI.getMaxLaneMaskForVReg(LI.reg()); 223 } 224 return LiveMask; 225 } 226 227 GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI, 228 const LiveIntervals &LIS, 229 const MachineRegisterInfo &MRI) { 230 GCNRPTracker::LiveRegSet LiveRegs; 231 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { 232 auto Reg = Register::index2VirtReg(I); 233 if (!LIS.hasInterval(Reg)) 234 continue; 235 auto LiveMask = getLiveLaneMask(Reg, SI, LIS, MRI); 236 if (LiveMask.any()) 237 LiveRegs[Reg] = LiveMask; 238 } 239 return LiveRegs; 240 } 241 242 void GCNRPTracker::reset(const MachineInstr &MI, 243 const LiveRegSet *LiveRegsCopy, 244 bool After) { 245 const MachineFunction &MF = *MI.getMF(); 246 MRI = &MF.getRegInfo(); 247 if (LiveRegsCopy) { 248 if (&LiveRegs != LiveRegsCopy) 249 LiveRegs = *LiveRegsCopy; 250 } else { 251 LiveRegs = After ? getLiveRegsAfter(MI, LIS) 252 : getLiveRegsBefore(MI, LIS); 253 } 254 255 MaxPressure = CurPressure = getRegPressure(*MRI, LiveRegs); 256 } 257 258 //////////////////////////////////////////////////////////////////////////////// 259 // GCNUpwardRPTracker 260 261 void GCNUpwardRPTracker::reset(const MachineRegisterInfo &MRI_, 262 const LiveRegSet &LiveRegs_) { 263 MRI = &MRI_; 264 LiveRegs = LiveRegs_; 265 LastTrackedMI = nullptr; 266 MaxPressure = CurPressure = getRegPressure(MRI_, LiveRegs_); 267 } 268 269 void GCNUpwardRPTracker::recede(const MachineInstr &MI) { 270 assert(MRI && "call reset first"); 271 272 LastTrackedMI = &MI; 273 274 if (MI.isDebugInstr()) 275 return; 276 277 auto DecrementDef = [this](const MachineOperand &MO) { 278 Register Reg = MO.getReg(); 279 auto I = LiveRegs.find(Reg); 280 if (I == LiveRegs.end()) 281 return; 282 283 LaneBitmask &LiveMask = I->second; 284 LaneBitmask PrevMask = LiveMask; 285 LiveMask &= ~getDefRegMask(MO, *MRI); 286 CurPressure.inc(Reg, PrevMask, LiveMask, *MRI); 287 if (LiveMask.none()) 288 LiveRegs.erase(I); 289 }; 290 291 // Decrement non-early-clobber defs. 292 SmallVector<const MachineOperand *, 2> EarlyClobberDefs; 293 for (const MachineOperand &MO : MI.all_defs()) { 294 if (!MO.getReg().isVirtual()) 295 continue; 296 if (!MO.isEarlyClobber()) 297 DecrementDef(MO); 298 else 299 EarlyClobberDefs.push_back(&MO); 300 } 301 302 // Increment uses. 303 SmallVector<RegisterMaskPair, 8> RegUses; 304 collectVirtualRegUses(RegUses, MI, LIS, *MRI); 305 for (const RegisterMaskPair &U : RegUses) { 306 LaneBitmask &LiveMask = LiveRegs[U.RegUnit]; 307 LaneBitmask PrevMask = LiveMask; 308 LiveMask |= U.LaneMask; 309 CurPressure.inc(U.RegUnit, PrevMask, LiveMask, *MRI); 310 } 311 312 // Point of maximum pressure: non-early-clobber defs are decremented and uses 313 // are incremented. 314 MaxPressure = max(CurPressure, MaxPressure); 315 316 // Now decrement early clobber defs. 317 for (const MachineOperand *MO : EarlyClobberDefs) 318 DecrementDef(*MO); 319 320 assert(CurPressure == getRegPressure(*MRI, LiveRegs)); 321 } 322 323 //////////////////////////////////////////////////////////////////////////////// 324 // GCNDownwardRPTracker 325 326 bool GCNDownwardRPTracker::reset(const MachineInstr &MI, 327 const LiveRegSet *LiveRegsCopy) { 328 MRI = &MI.getParent()->getParent()->getRegInfo(); 329 LastTrackedMI = nullptr; 330 MBBEnd = MI.getParent()->end(); 331 NextMI = &MI; 332 NextMI = skipDebugInstructionsForward(NextMI, MBBEnd); 333 if (NextMI == MBBEnd) 334 return false; 335 GCNRPTracker::reset(*NextMI, LiveRegsCopy, false); 336 return true; 337 } 338 339 bool GCNDownwardRPTracker::advanceBeforeNext() { 340 assert(MRI && "call reset first"); 341 if (!LastTrackedMI) 342 return NextMI == MBBEnd; 343 344 assert(NextMI == MBBEnd || !NextMI->isDebugInstr()); 345 346 SlotIndex SI = NextMI == MBBEnd 347 ? LIS.getInstructionIndex(*LastTrackedMI).getDeadSlot() 348 : LIS.getInstructionIndex(*NextMI).getBaseIndex(); 349 assert(SI.isValid()); 350 351 // Remove dead registers or mask bits. 352 SmallSet<Register, 8> SeenRegs; 353 for (auto &MO : LastTrackedMI->operands()) { 354 if (!MO.isReg() || !MO.getReg().isVirtual()) 355 continue; 356 if (MO.isUse() && !MO.readsReg()) 357 continue; 358 if (!SeenRegs.insert(MO.getReg()).second) 359 continue; 360 const LiveInterval &LI = LIS.getInterval(MO.getReg()); 361 if (LI.hasSubRanges()) { 362 auto It = LiveRegs.end(); 363 for (const auto &S : LI.subranges()) { 364 if (!S.liveAt(SI)) { 365 if (It == LiveRegs.end()) { 366 It = LiveRegs.find(MO.getReg()); 367 if (It == LiveRegs.end()) 368 llvm_unreachable("register isn't live"); 369 } 370 auto PrevMask = It->second; 371 It->second &= ~S.LaneMask; 372 CurPressure.inc(MO.getReg(), PrevMask, It->second, *MRI); 373 } 374 } 375 if (It != LiveRegs.end() && It->second.none()) 376 LiveRegs.erase(It); 377 } else if (!LI.liveAt(SI)) { 378 auto It = LiveRegs.find(MO.getReg()); 379 if (It == LiveRegs.end()) 380 llvm_unreachable("register isn't live"); 381 CurPressure.inc(MO.getReg(), It->second, LaneBitmask::getNone(), *MRI); 382 LiveRegs.erase(It); 383 } 384 } 385 386 MaxPressure = max(MaxPressure, CurPressure); 387 388 LastTrackedMI = nullptr; 389 390 return NextMI == MBBEnd; 391 } 392 393 void GCNDownwardRPTracker::advanceToNext() { 394 LastTrackedMI = &*NextMI++; 395 NextMI = skipDebugInstructionsForward(NextMI, MBBEnd); 396 397 // Add new registers or mask bits. 398 for (const auto &MO : LastTrackedMI->all_defs()) { 399 Register Reg = MO.getReg(); 400 if (!Reg.isVirtual()) 401 continue; 402 auto &LiveMask = LiveRegs[Reg]; 403 auto PrevMask = LiveMask; 404 LiveMask |= getDefRegMask(MO, *MRI); 405 CurPressure.inc(Reg, PrevMask, LiveMask, *MRI); 406 } 407 408 MaxPressure = max(MaxPressure, CurPressure); 409 } 410 411 bool GCNDownwardRPTracker::advance() { 412 if (NextMI == MBBEnd) 413 return false; 414 advanceBeforeNext(); 415 advanceToNext(); 416 return true; 417 } 418 419 bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator End) { 420 while (NextMI != End) 421 if (!advance()) return false; 422 return true; 423 } 424 425 bool GCNDownwardRPTracker::advance(MachineBasicBlock::const_iterator Begin, 426 MachineBasicBlock::const_iterator End, 427 const LiveRegSet *LiveRegsCopy) { 428 reset(*Begin, LiveRegsCopy); 429 return advance(End); 430 } 431 432 Printable llvm::reportMismatch(const GCNRPTracker::LiveRegSet &LISLR, 433 const GCNRPTracker::LiveRegSet &TrackedLR, 434 const TargetRegisterInfo *TRI, StringRef Pfx) { 435 return Printable([&LISLR, &TrackedLR, TRI, Pfx](raw_ostream &OS) { 436 for (auto const &P : TrackedLR) { 437 auto I = LISLR.find(P.first); 438 if (I == LISLR.end()) { 439 OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second) 440 << " isn't found in LIS reported set\n"; 441 } else if (I->second != P.second) { 442 OS << Pfx << printReg(P.first, TRI) 443 << " masks doesn't match: LIS reported " << PrintLaneMask(I->second) 444 << ", tracked " << PrintLaneMask(P.second) << '\n'; 445 } 446 } 447 for (auto const &P : LISLR) { 448 auto I = TrackedLR.find(P.first); 449 if (I == TrackedLR.end()) { 450 OS << Pfx << printReg(P.first, TRI) << ":L" << PrintLaneMask(P.second) 451 << " isn't found in tracked set\n"; 452 } 453 } 454 }); 455 } 456 457 bool GCNUpwardRPTracker::isValid() const { 458 const auto &SI = LIS.getInstructionIndex(*LastTrackedMI).getBaseIndex(); 459 const auto LISLR = llvm::getLiveRegs(SI, LIS, *MRI); 460 const auto &TrackedLR = LiveRegs; 461 462 if (!isEqual(LISLR, TrackedLR)) { 463 dbgs() << "\nGCNUpwardRPTracker error: Tracked and" 464 " LIS reported livesets mismatch:\n" 465 << print(LISLR, *MRI); 466 reportMismatch(LISLR, TrackedLR, MRI->getTargetRegisterInfo()); 467 return false; 468 } 469 470 auto LISPressure = getRegPressure(*MRI, LISLR); 471 if (LISPressure != CurPressure) { 472 dbgs() << "GCNUpwardRPTracker error: Pressure sets different\nTracked: " 473 << print(CurPressure) << "LIS rpt: " << print(LISPressure); 474 return false; 475 } 476 return true; 477 } 478 479 Printable llvm::print(const GCNRPTracker::LiveRegSet &LiveRegs, 480 const MachineRegisterInfo &MRI) { 481 return Printable([&LiveRegs, &MRI](raw_ostream &OS) { 482 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); 483 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { 484 Register Reg = Register::index2VirtReg(I); 485 auto It = LiveRegs.find(Reg); 486 if (It != LiveRegs.end() && It->second.any()) 487 OS << ' ' << printVRegOrUnit(Reg, TRI) << ':' 488 << PrintLaneMask(It->second); 489 } 490 OS << '\n'; 491 }); 492 } 493 494 void GCNRegPressure::dump() const { dbgs() << print(*this); } 495 496 static cl::opt<bool> UseDownwardTracker( 497 "amdgpu-print-rp-downward", 498 cl::desc("Use GCNDownwardRPTracker for GCNRegPressurePrinter pass"), 499 cl::init(false), cl::Hidden); 500 501 char llvm::GCNRegPressurePrinter::ID = 0; 502 char &llvm::GCNRegPressurePrinterID = GCNRegPressurePrinter::ID; 503 504 INITIALIZE_PASS(GCNRegPressurePrinter, "amdgpu-print-rp", "", true, true) 505 506 // Return lanemask of Reg's subregs that are live-through at [Begin, End] and 507 // are fully covered by Mask. 508 static LaneBitmask 509 getRegLiveThroughMask(const MachineRegisterInfo &MRI, const LiveIntervals &LIS, 510 Register Reg, SlotIndex Begin, SlotIndex End, 511 LaneBitmask Mask = LaneBitmask::getAll()) { 512 513 auto IsInOneSegment = [Begin, End](const LiveRange &LR) -> bool { 514 auto *Segment = LR.getSegmentContaining(Begin); 515 return Segment && Segment->contains(End); 516 }; 517 518 LaneBitmask LiveThroughMask; 519 const LiveInterval &LI = LIS.getInterval(Reg); 520 if (LI.hasSubRanges()) { 521 for (auto &SR : LI.subranges()) { 522 if ((SR.LaneMask & Mask) == SR.LaneMask && IsInOneSegment(SR)) 523 LiveThroughMask |= SR.LaneMask; 524 } 525 } else { 526 LaneBitmask RegMask = MRI.getMaxLaneMaskForVReg(Reg); 527 if ((RegMask & Mask) == RegMask && IsInOneSegment(LI)) 528 LiveThroughMask = RegMask; 529 } 530 531 return LiveThroughMask; 532 } 533 534 bool GCNRegPressurePrinter::runOnMachineFunction(MachineFunction &MF) { 535 const MachineRegisterInfo &MRI = MF.getRegInfo(); 536 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); 537 const LiveIntervals &LIS = getAnalysis<LiveIntervals>(); 538 539 auto &OS = dbgs(); 540 541 // Leading spaces are important for YAML syntax. 542 #define PFX " " 543 544 OS << "---\nname: " << MF.getName() << "\nbody: |\n"; 545 546 auto printRP = [](const GCNRegPressure &RP) { 547 return Printable([&RP](raw_ostream &OS) { 548 OS << format(PFX " %-5d", RP.getSGPRNum()) 549 << format(" %-5d", RP.getVGPRNum(false)); 550 }); 551 }; 552 553 auto ReportLISMismatchIfAny = [&](const GCNRPTracker::LiveRegSet &TrackedLR, 554 const GCNRPTracker::LiveRegSet &LISLR) { 555 if (LISLR != TrackedLR) { 556 OS << PFX " mis LIS: " << llvm::print(LISLR, MRI) 557 << reportMismatch(LISLR, TrackedLR, TRI, PFX " "); 558 } 559 }; 560 561 // Register pressure before and at an instruction (in program order). 562 SmallVector<std::pair<GCNRegPressure, GCNRegPressure>, 16> RP; 563 564 for (auto &MBB : MF) { 565 RP.clear(); 566 RP.reserve(MBB.size()); 567 568 OS << PFX; 569 MBB.printName(OS); 570 OS << ":\n"; 571 572 SlotIndex MBBStartSlot = LIS.getSlotIndexes()->getMBBStartIdx(&MBB); 573 SlotIndex MBBEndSlot = LIS.getSlotIndexes()->getMBBEndIdx(&MBB); 574 575 GCNRPTracker::LiveRegSet LiveIn, LiveOut; 576 GCNRegPressure RPAtMBBEnd; 577 578 if (UseDownwardTracker) { 579 if (MBB.empty()) { 580 LiveIn = LiveOut = getLiveRegs(MBBStartSlot, LIS, MRI); 581 RPAtMBBEnd = getRegPressure(MRI, LiveIn); 582 } else { 583 GCNDownwardRPTracker RPT(LIS); 584 RPT.reset(MBB.front()); 585 586 LiveIn = RPT.getLiveRegs(); 587 588 while (!RPT.advanceBeforeNext()) { 589 GCNRegPressure RPBeforeMI = RPT.getPressure(); 590 RPT.advanceToNext(); 591 RP.emplace_back(RPBeforeMI, RPT.getPressure()); 592 } 593 594 LiveOut = RPT.getLiveRegs(); 595 RPAtMBBEnd = RPT.getPressure(); 596 } 597 } else { 598 GCNUpwardRPTracker RPT(LIS); 599 RPT.reset(MRI, MBBEndSlot); 600 601 LiveOut = RPT.getLiveRegs(); 602 RPAtMBBEnd = RPT.getPressure(); 603 604 for (auto &MI : reverse(MBB)) { 605 RPT.resetMaxPressure(); 606 RPT.recede(MI); 607 if (!MI.isDebugInstr()) 608 RP.emplace_back(RPT.getPressure(), RPT.getMaxPressure()); 609 } 610 611 LiveIn = RPT.getLiveRegs(); 612 } 613 614 OS << PFX " Live-in: " << llvm::print(LiveIn, MRI); 615 if (!UseDownwardTracker) 616 ReportLISMismatchIfAny(LiveIn, getLiveRegs(MBBStartSlot, LIS, MRI)); 617 618 OS << PFX " SGPR VGPR\n"; 619 int I = 0; 620 for (auto &MI : MBB) { 621 if (!MI.isDebugInstr()) { 622 auto &[RPBeforeInstr, RPAtInstr] = 623 RP[UseDownwardTracker ? I : (RP.size() - 1 - I)]; 624 ++I; 625 OS << printRP(RPBeforeInstr) << '\n' << printRP(RPAtInstr) << " "; 626 } else 627 OS << PFX " "; 628 MI.print(OS); 629 } 630 OS << printRP(RPAtMBBEnd) << '\n'; 631 632 OS << PFX " Live-out:" << llvm::print(LiveOut, MRI); 633 if (UseDownwardTracker) 634 ReportLISMismatchIfAny(LiveOut, getLiveRegs(MBBEndSlot, LIS, MRI)); 635 636 GCNRPTracker::LiveRegSet LiveThrough; 637 for (auto [Reg, Mask] : LiveIn) { 638 LaneBitmask MaskIntersection = Mask & LiveOut.lookup(Reg); 639 if (MaskIntersection.any()) { 640 LaneBitmask LTMask = getRegLiveThroughMask( 641 MRI, LIS, Reg, MBBStartSlot, MBBEndSlot, MaskIntersection); 642 if (LTMask.any()) 643 LiveThrough[Reg] = LTMask; 644 } 645 } 646 OS << PFX " Live-thr:" << llvm::print(LiveThrough, MRI); 647 OS << printRP(getRegPressure(MRI, LiveThrough)) << '\n'; 648 } 649 OS << "...\n"; 650 return false; 651 652 #undef PFX 653 }