44#define DEBUG_TYPE "machine-scheduler"
51 return O.error(
"'" + Arg +
"' value invalid for uint argument!");
54 return O.error(
"'" + Arg +
"' value must be in the range [0, 100]!");
61 cl::desc(
"Percent of VGPR limits that we should use as RP threshold "
62 "during scheduling. We have two limits relevant to scheduling: "
63 "Critical (avoid decreasing occupancy), Excess (avoid spilling). "
64 "This flag scales both limits back by an equal percent: (0 = use "
65 " default calculation, 1-100 = use percentage), default: 0"),
88 Context->RegClassInfo->getNumAllocatableRegs(&AMDGPU::SGPR_32RegClass);
90 Context->RegClassInfo->getNumAllocatableRegs(&AMDGPU::VGPR_32RegClass);
92 Context->RegClassInfo->getNumAllocatableRegs(&AMDGPU::AGPR_32RegClass);
120 "VGPRCriticalLimit calculation method.\n");
124 unsigned Addressable =
127 VGPRBudget = std::max(VGPRBudget, Granule);
146 <<
". VGPRCriticalLimit: " << OriginalVGPRCriticalLimit
164 <<
", UnifiedVGPRCriticalLimit = "
197 if (!
Op.isReg() ||
Op.isImplicit())
199 if (
Op.getReg().isPhysical() ||
200 (
Op.isDef() &&
Op.getSubReg() != AMDGPU::NoSubRegister))
206std::pair<unsigned, unsigned>
208 if (!
CLOpts.avgpr_banking)
209 return {RP.getArchVGPRNum(), RP.getAGPRNum()};
243 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] = ArchNum;
244 Pressure[AMDGPU::RegisterPressureSets::AGPR_32] = AccNum;
253 unsigned SGPRPressure,
254 unsigned VGPRPressure,
255 unsigned AGPRPressure,
bool IsBottomUp) {
259 if (!
DAG->isTrackingPressure())
282 Pressure[AMDGPU::RegisterPressureSets::SReg_32] = SGPRPressure;
283 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] = VGPRPressure;
284 Pressure[AMDGPU::RegisterPressureSets::AGPR_32] = AGPRPressure;
286 for (
const auto &Diff :
DAG->getPressureDiff(SU)) {
292 (IsBottomUp ? Diff.getUnitInc() : -Diff.getUnitInc());
295#ifdef EXPENSIVE_CHECKS
296 std::vector<unsigned> CheckPressure, CheckMaxPressure;
299 if (
Pressure[AMDGPU::RegisterPressureSets::SReg_32] !=
300 CheckPressure[AMDGPU::RegisterPressureSets::SReg_32] ||
301 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] !=
302 CheckPressure[AMDGPU::RegisterPressureSets::VGPR_32] ||
303 Pressure[AMDGPU::RegisterPressureSets::AGPR_32] !=
304 CheckPressure[AMDGPU::RegisterPressureSets::AGPR_32]) {
305 errs() <<
"Register Pressure is inaccurate when calculated through "
307 <<
"SGPR got " <<
Pressure[AMDGPU::RegisterPressureSets::SReg_32]
309 << CheckPressure[AMDGPU::RegisterPressureSets::SReg_32] <<
"\n"
310 <<
"VGPR got " <<
Pressure[AMDGPU::RegisterPressureSets::VGPR_32]
312 << CheckPressure[AMDGPU::RegisterPressureSets::VGPR_32] <<
"\n"
313 <<
"AGPR got " <<
Pressure[AMDGPU::RegisterPressureSets::AGPR_32]
315 << CheckPressure[AMDGPU::RegisterPressureSets::AGPR_32] <<
"\n";
321 unsigned NewAGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::AGPR_32];
322 unsigned NewSGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::SReg_32];
323 unsigned NewVGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::VGPR_32];
333 const unsigned MaxVGPRPressureInc = 16;
334 bool ShouldTrackVGPRs = VGPRPressure + MaxVGPRPressureInc >=
VGPRExcessLimit;
337 bool ShouldTrackSGPRs =
338 !ShouldTrackVGPRs && !ShouldTrackAGPRs && SGPRPressure >=
SGPRExcessLimit;
375 Excess.
getPSet() != AMDGPU::RegisterPressureSets::SReg_32;
376 if (!HasBankExcess || UnifiedExcess > Excess.
getUnitInc()) {
390 bool UnifiedVGPRFile =
MF->getSubtarget<
GCNSubtarget>().hasGFX90AInsts();
392 if (UnifiedVGPRFile) {
400 int VGPRDelta = NewVGPRPressure - VectorCriticalLimit;
403 : std::numeric_limits<int>::min();
405 if (SGPRDelta >= 0 || VGPRDelta >= 0 || AGPRDelta >= 0) {
408 if (VGPRDelta >= SGPRDelta && VGPRDelta >= AGPRDelta) {
412 }
else if (AGPRDelta >= SGPRDelta) {
426 bool HasBufferedModel =
429 return Combined <= PendingQueueLimit && HasBufferedModel;
446 dbgs() <<
"Prefer:\t\t";
447 DAG->dumpNode(*Preferred.
SU);
451 DAG->dumpNode(*Current.
SU);
454 dbgs() <<
"Reason:\t\t";
468 unsigned SGPRPressure = 0;
469 unsigned VGPRPressure = 0;
470 unsigned AGPRPressure = 0;
472 if (
DAG->isTrackingPressure()) {
474 SGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::SReg_32];
475 VGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::VGPR_32];
476 AGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::AGPR_32];
481 SGPRPressure =
T->getPressure().getSGPRNum();
482 std::tie(VGPRPressure, AGPRPressure) =
488 for (
SUnit *SU : AQ) {
492 VGPRPressure, AGPRPressure, IsBottomUp);
513 for (
SUnit *SU : PQ) {
517 VGPRPressure, AGPRPressure, IsBottomUp);
537 bool &PickedPending) {
559 bool BotPending =
false;
579 "Last pick result should correspond to re-picking right now");
584 bool TopPending =
false;
604 "Last pick result should correspond to re-picking right now");
614 PickedPending = BotPending && TopPending;
617 if (BotPending || TopPending) {
624 Cand.setBest(TryCand);
629 IsTopNode = Cand.AtTop;
636 if (
DAG->top() ==
DAG->bottom()) {
638 Bot.Available.empty() &&
Bot.Pending.empty() &&
"ReadyQ garbage");
644 PickedPending =
false;
680 if (ReadyCycle > CurrentCycle)
745 if (
DAG->isTrackingPressure() &&
751 if (
DAG->isTrackingPressure() &&
756 bool SameBoundary = Zone !=
nullptr;
775 if (
CLOpts.rewrite_mfma_form_sched_stage)
780 if (IsLegacyScheduler)
799 if (
DAG->isTrackingPressure() &&
809 bool SameBoundary = Zone !=
nullptr;
844 bool CandIsClusterSucc =
846 bool TryCandIsClusterSucc =
848 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
853 if (
DAG->isTrackingPressure() &&
859 if (
DAG->isTrackingPressure() &&
905 if (
DAG->isTrackingPressure()) {
921 bool CandIsClusterSucc =
923 bool TryCandIsClusterSucc =
925 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
934 bool SameBoundary = Zone !=
nullptr;
951 if (TryMayLoad || CandMayLoad) {
952 bool TryLongLatency =
954 bool CandLongLatency =
958 Zone->
isTop() ? CandLongLatency : TryLongLatency, TryCand,
976 if (
DAG->isTrackingPressure() &&
995 !
Rem.IsAcyclicLatencyLimited &&
tryLatency(TryCand, Cand, *Zone))
1013 StartingOccupancy(MFI.getOccupancy()), MinOccupancy(StartingOccupancy),
1014 RegionLiveOuts(this,
true) {
1020 LLVM_DEBUG(
dbgs() <<
"Starting occupancy is " << StartingOccupancy <<
".\n");
1021 if (ST.getCLOpts().schedule_relaxed_occupancy) {
1022 MinOccupancy = std::min(MFI.getMinAllowedOccupancy(), StartingOccupancy);
1023 if (MinOccupancy != StartingOccupancy)
1024 LLVM_DEBUG(
dbgs() <<
"Allowing Occupancy drops to " << MinOccupancy
1029std::unique_ptr<GCNSchedStage>
1031 switch (SchedStageID) {
1033 return std::make_unique<OccInitialScheduleStage>(SchedStageID, *
this);
1035 return std::make_unique<RewriteMFMAFormStage>(SchedStageID, *
this);
1037 return std::make_unique<UnclusteredHighRPStage>(SchedStageID, *
this);
1039 return std::make_unique<ClusteredLowOccStage>(SchedStageID, *
this);
1041 return std::make_unique<PreRARematStage>(SchedStageID, *
this);
1043 return std::make_unique<ILPInitialScheduleStage>(SchedStageID, *
this);
1045 return std::make_unique<MemoryClauseInitialScheduleStage>(SchedStageID,
1048 return std::make_unique<LiveIntervalRPStage>(SchedStageID, *
this);
1062 std::function<
void(
const GCNRegPressure &)> PressureCallback)
const {
1063 if (Regions[RegionIdx].first == Regions[RegionIdx].second) {
1065 if (PressureCallback)
1066 PressureCallback(RP);
1071 RPTracker.
reset(*Regions[RegionIdx].first, Regions[RegionIdx].second,
1072 &LiveIns[RegionIdx]);
1074 if (PressureCallback) {
1076 RPTracker.setPressureCallback(std::move(PressureCallback));
1079 RPTracker.advance(Regions[RegionIdx].second);
1085 assert(RegionBegin != RegionEnd &&
"Region must not be empty");
1089void GCNScheduleDAGMILive::computeBlockPressure(
unsigned RegionIdx,
1101 const MachineBasicBlock *OnlySucc =
nullptr;
1104 if (!Candidate->empty() && Candidate->pred_size() == 1) {
1105 SlotIndexes *Ind =
LIS->getSlotIndexes();
1107 OnlySucc = Candidate;
1112 size_t CurRegion = RegionIdx;
1113 for (
size_t E = Regions.size(); CurRegion !=
E; ++CurRegion)
1114 if (Regions[CurRegion].first->getParent() !=
MBB)
1119 auto LiveInIt = MBBLiveIns.find(
MBB);
1120 auto &Rgn = Regions[CurRegion];
1122 if (LiveInIt != MBBLiveIns.end()) {
1123 auto LiveIn = std::move(LiveInIt->second);
1125 MBBLiveIns.erase(LiveInIt);
1128 auto LRS = BBLiveInMap.lookup(NonDbgMI);
1129#ifdef EXPENSIVE_CHECKS
1138 if (Regions[CurRegion].first ==
I || NonDbgMI ==
I) {
1139 LiveIns[CurRegion] =
RPTracker.getLiveRegs();
1143 if (Regions[CurRegion].second ==
I) {
1144 Pressure[CurRegion] =
RPTracker.moveMaxPressure();
1145 if (CurRegion-- == RegionIdx)
1147 auto &Rgn = Regions[CurRegion];
1160 MBBLiveIns[OnlySucc] =
RPTracker.moveLiveRegs();
1165GCNScheduleDAGMILive::getRegionLiveInMap()
const {
1166 assert(!Regions.empty());
1167 std::vector<MachineInstr *> RegionFirstMIs;
1168 RegionFirstMIs.reserve(Regions.size());
1170 RegionFirstMIs.push_back(
1177GCNScheduleDAGMILive::getRegionLiveOutMap()
const {
1178 assert(!Regions.empty());
1179 std::vector<MachineInstr *> RegionLastMIs;
1180 RegionLastMIs.reserve(Regions.size());
1191 IdxToInstruction.clear();
1194 IsLiveOut ? DAG->getRegionLiveOutMap() : DAG->getRegionLiveInMap();
1195 for (
unsigned I = 0;
I < DAG->Regions.size();
I++) {
1196 auto &[RegionBegin, RegionEnd] = DAG->Regions[
I];
1198 if (RegionBegin == RegionEnd)
1202 IdxToInstruction[
I] = RegionKey;
1210 LiveIns.resize(Regions.size());
1211 Pressure.resize(Regions.size());
1212 RegionsWithHighRP.resize(
static_cast<unsigned>(Regions.size()));
1213 RegionsWithExcessRP.resize(
static_cast<unsigned>(Regions.size()));
1214 RegionsWithIGLPInstrs.resize(
static_cast<unsigned>(Regions.size()));
1215 RegionsWithHighRP.reset();
1216 RegionsWithExcessRP.reset();
1217 RegionsWithIGLPInstrs.reset();
1222void GCNScheduleDAGMILive::runSchedStages() {
1223 LLVM_DEBUG(
dbgs() <<
"All regions recorded, starting actual scheduling.\n");
1226 if (!Regions.
empty()) {
1227 BBLiveInMap = getRegionLiveInMap();
1233 if (ST.
getCLOpts().print_max_reg_pressure_regusage_before_scheduler) {
1242 if (!Stage->initGCNSchedStage())
1245 for (
auto Region : Regions) {
1249 if (!Stage->initGCNRegion()) {
1250 Stage->advanceRegion();
1256 const unsigned RegionIdx = Stage->getRegionIdx();
1259 MRI, RegionLiveOuts.getLiveRegsForRegionIdx(RegionIdx));
1263 Stage->finalizeGCNRegion();
1264 Stage->advanceRegion();
1268 Stage->finalizeGCNSchedStage();
1272 if (ST.getCLOpts().print_max_reg_pressure_regusage_after_scheduler) {
1284 OS <<
"Max Occupancy Initial Schedule";
1287 OS <<
"Instruction Rewriting Reschedule";
1290 OS <<
"Unclustered High Register Pressure Reschedule";
1293 OS <<
"Clustered Low Occupancy Reschedule";
1296 OS <<
"Pre-RA Rematerialize";
1299 OS <<
"Max ILP Initial Schedule";
1302 OS <<
"Max memory clause Initial Schedule";
1305 OS <<
"Live Interval RP Reschedule";
1325void RewriteMFMAFormStage::findReachingDefs(
1347 while (!Worklist.
empty()) {
1362 for (MachineBasicBlock *PredMBB : DefMBB->
predecessors()) {
1363 if (Visited.
insert(PredMBB).second)
1369void RewriteMFMAFormStage::findReachingUses(
1373 for (MachineOperand &UseMO :
1376 findReachingDefs(UseMO, LIS, ReachingDefIndexes);
1380 if (
any_of(ReachingDefIndexes, [DefIdx](SlotIndex RDIdx) {
1392 if (!
ST.hasGFX90AInsts() ||
MFI.getMinWavesPerEU() > 1)
1395 RegionsWithExcessArchVGPR.resize(
static_cast<unsigned>(
DAG.Regions.size()));
1396 RegionsWithExcessArchVGPR.reset();
1400 RegionsWithExcessArchVGPR[
Region] =
true;
1403 if (RegionsWithExcessArchVGPR.none())
1406 TII =
ST.getInstrInfo();
1407 SRI =
ST.getRegisterInfo();
1409 std::vector<std::pair<MachineInstr *, unsigned>> RewriteCands;
1413 if (!initHeuristics(RewriteCands, CopyForUse, CopyForDef))
1416 int64_t
Cost = getRewriteCost(RewriteCands, CopyForUse, CopyForDef);
1423 return rewrite(RewriteCands);
1427 if (!
ST.getCLOpts().unclustered_high_rp_reschedule)
1433 if (
DAG.RegionsWithHighRP.none() &&
DAG.RegionsWithExcessRP.none())
1440 InitialOccupancy =
DAG.MinOccupancy;
1443 TempTargetOccupancy =
MFI.getMaxWavesPerEU() >
DAG.MinOccupancy
1444 ? InitialOccupancy + 1
1446 IsAnyRegionScheduled =
false;
1447 S.SGPRLimitBias =
S.HighRPSGPRBias;
1448 S.VGPRLimitBias =
S.HighRPVGPRBias;
1452 <<
"Retrying function scheduling without clustering. "
1453 "Aggressively try to reduce register pressure to achieve occupancy "
1454 << TempTargetOccupancy <<
".\n");
1460 if (!
ST.getCLOpts().clustered_low_occupancy_reschedule)
1469 if (
DAG.StartingOccupancy <=
DAG.MinOccupancy)
1473 dbgs() <<
"Retrying function scheduling with lowest recorded occupancy "
1474 <<
DAG.MinOccupancy <<
".\n");
1489 unsigned MaxSGPRs =
ST.getMaxNumSGPRs(
F);
1490 unsigned MaxVGPRs =
ST.getMaxNumVGPRs(
F);
1492 const unsigned VGPRBlockSize =
MFI.getDynamicVGPRBlockSize();
1493 bool HasVectorRegisterExcess =
false;
1495 if (
GCNRPTarget(MaxSGPRs, MaxVGPRs,
MF, RP).hasVectorRegisterExcess()) {
1496 HasVectorRegisterExcess =
true;
1500 if (HasVectorRegisterExcess ||
DAG.MinOccupancy >=
MFI.getMaxWavesPerEU()) {
1503 TargetOcc = std::nullopt;
1507 TargetOcc =
DAG.MinOccupancy + 1;
1508 MaxSGPRs =
ST.getMaxNumSGPRs(*TargetOcc,
false);
1509 MaxVGPRs =
ST.getMaxNumVGPRs(*TargetOcc, VGPRBlockSize);
1513 dbgs() <<
"In function ";
1514 MF.getFunction().printAsOperand(
dbgs(),
false);
1515 dbgs() <<
": rematerializing to ";
1517 dbgs() <<
"increase occupancy from " << *TargetOcc - 1 <<
'\n';
1519 dbgs() <<
"reduce spilling (minimum target occupancy is "
1520 <<
MFI.getMinWavesPerEU() <<
")\n";
1524 LiveOuts.reserve(
DAG.Regions.size());
1525 DAG.RegionLiveOuts.buildLiveRegMap();
1527 LiveOuts.push_back(
DAG.RegionLiveOuts.getLiveRegsForRegionIdx(
RegionIdx));
1529 Strategy = std::make_unique<GCNRematStrategy>(
MF,
DAG.Regions,
DAG.LiveIns,
1530 LiveOuts, *
DAG.LIS, *
DAG.MBFI);
1531 if (TargetOcc.has_value()) {
1538 Strategy->startRecordingRemats();
1541 RescheduleRegions.resize(
DAG.Regions.size());
1543 Strategy->rematerializeFor(MaxSGPRs, MaxVGPRs,
1544 !TargetOcc.has_value(),
1545 RescheduleRegions, &MaxPressure);
1546 if (RescheduleRegions.none())
1551 for (
unsigned RegionIdx : RescheduleRegions.set_bits()) {
1557 AchievedOcc =
MFI.getMaxWavesPerEU();
1559 AchievedOcc = std::min(AchievedOcc, RP.getOccupancy(
ST, VGPRBlockSize));
1562 dbgs() <<
"Retrying function scheduling with new min. occupancy of "
1563 << AchievedOcc <<
" from rematerializing (original was "
1564 <<
DAG.MinOccupancy;
1566 dbgs() <<
", target was " << *TargetOcc;
1570 DAG.setTargetOccupancy(getStageTargetOccupancy());
1581 S.SGPRLimitBias =
S.VGPRLimitBias = 0;
1582 if (
DAG.MinOccupancy > InitialOccupancy) {
1583 assert(IsAnyRegionScheduled);
1585 <<
" stage successfully increased occupancy to "
1586 <<
DAG.MinOccupancy <<
'\n');
1587 }
else if (!IsAnyRegionScheduled) {
1588 assert(
DAG.MinOccupancy == InitialOccupancy);
1590 <<
": No regions scheduled, min occupancy stays at "
1591 <<
DAG.MinOccupancy <<
", MFI occupancy stays at "
1592 <<
MFI.getOccupancy() <<
".\n");
1600 if (
DAG.begin() ==
DAG.end())
1607 unsigned NumRegionInstrs =
1608 static_cast<unsigned>(std::distance(
DAG.begin(),
DAG.end()));
1612 if (
DAG.begin() == std::prev(
DAG.end()))
1618 <<
"\n From: " << *
DAG.begin() <<
" To: ";
1620 else dbgs() <<
"End";
1621 dbgs() <<
" RegionInstrs: " << NumRegionInstrs <<
'\n');
1629 for (
auto &
I :
DAG) {
1642 dbgs() <<
"Pressure before scheduling:\nRegion live-ins:"
1644 <<
"Region live-in pressure: "
1648 S.HasHighPressure =
false;
1670 unsigned DynamicVGPRBlockSize =
DAG.MFI.getDynamicVGPRBlockSize();
1673 unsigned CurrentTargetOccupancy =
1674 IsAnyRegionScheduled ?
DAG.MinOccupancy : TempTargetOccupancy;
1676 (CurrentTargetOccupancy <= InitialOccupancy ||
1677 DAG.Pressure[
RegionIdx].getOccupancy(
ST, DynamicVGPRBlockSize) !=
1684 if (!IsAnyRegionScheduled && IsSchedulingThisRegion) {
1685 IsAnyRegionScheduled =
true;
1686 if (
MFI.getMaxWavesPerEU() >
DAG.MinOccupancy)
1687 DAG.setTargetOccupancy(TempTargetOccupancy);
1689 return IsSchedulingThisRegion;
1705 return !RevertAllRegions && RescheduleRegions[
RegionIdx] &&
1725 if (
S.HasHighPressure)
1746 if (
DAG.MinOccupancy < *TargetOcc) {
1748 <<
" cannot meet occupancy target, interrupting "
1749 "re-scheduling in all regions\n");
1750 RevertAllRegions =
true;
1757 unsigned MaxVGPRs =
ST.getMaxNumVGPRs(
MF);
1760 unsigned MaxArchVGPRs = std::min(MaxVGPRs,
ST.getAddressableNumArchVGPRs());
1765 bool AVGPRBanking =
ST.getCLOpts().avgpr_banking;
1766 unsigned ArchVGPRBankLimit, AGPRBankLimit;
1767 std::tie(ArchVGPRBankLimit, AGPRBankLimit) =
S.getBankLimits();
1768 unsigned BankedArchVGPRPeak = 0, BankedAGPRPeak = 0, BankedUnifiedPeak = 0;
1772 auto [ArchNum, AccNum] =
1773 RP.getBankedVGPRNum(ArchVGPRBankLimit, AGPRBankLimit);
1774 BankedArchVGPRPeak = std::max(BankedArchVGPRPeak, ArchNum);
1775 BankedAGPRPeak = std::max(BankedAGPRPeak, AccNum);
1777 std::max(BankedUnifiedPeak,
1788 unsigned DynamicVGPRBlockSize =
DAG.MFI.getDynamicVGPRBlockSize();
1790 bool UnifiedVGPRFile =
ST.hasGFX90AInsts();
1791 unsigned VectorCriticalLimit =
1792 UnifiedVGPRFile ?
S.UnifiedVGPRCriticalLimit :
S.VGPRCriticalLimit;
1796 PressureAfter.getVGPRNum(UnifiedVGPRFile) <= VectorCriticalLimit &&
1797 (!UnifiedVGPRFile ||
1807 unsigned TargetOccupancy = std::min(
1808 S.getTargetOccupancy(),
ST.getOccupancyWithWorkGroupSizes(
MF).second);
1809 unsigned WavesAfter = std::min(
1810 TargetOccupancy,
PressureAfter.getOccupancy(
ST, DynamicVGPRBlockSize));
1811 unsigned WavesBefore = std::min(
1813 LLVM_DEBUG(
dbgs() <<
"Occupancy before scheduling: " << WavesBefore
1814 <<
", after " << WavesAfter <<
".\n");
1820 unsigned NewOccupancy = std::max(WavesAfter, WavesBefore);
1824 if (WavesAfter < WavesBefore && WavesAfter <
DAG.MinOccupancy &&
1825 WavesAfter >=
MFI.getMinAllowedOccupancy()) {
1826 LLVM_DEBUG(
dbgs() <<
"Function is memory bound, allow occupancy drop up to "
1827 <<
MFI.getMinAllowedOccupancy() <<
" waves\n");
1828 NewOccupancy = WavesAfter;
1831 if (NewOccupancy <
DAG.MinOccupancy) {
1832 DAG.MinOccupancy = NewOccupancy;
1833 MFI.limitOccupancy(
DAG.MinOccupancy);
1835 <<
DAG.MinOccupancy <<
".\n");
1837 unsigned MaxSGPRs =
ST.getMaxNumSGPRs(
MF);
1839 bool BankExcess = AVGPRBanking
1840 ? BankedArchVGPRPeak > ArchVGPRBankLimit ||
1841 BankedAGPRPeak > AGPRBankLimit
1845 unsigned VGPRNum = AVGPRBanking && UnifiedVGPRFile
1848 if (VGPRNum > MaxVGPRs || BankExcess ||
1868 unsigned ReadyCycle = CurrCycle;
1869 for (
auto &
D : SU.
Preds) {
1870 if (
D.isAssignedRegDep()) {
1873 unsigned DefReady = ReadyCycles[
DAG.getSUnit(
DefMI)->NodeNum];
1874 ReadyCycle = std::max(ReadyCycle, DefReady +
Latency);
1877 ReadyCycles[SU.
NodeNum] = ReadyCycle;
1884 std::pair<MachineInstr *, unsigned>
B)
const {
1885 return A.second <
B.second;
1891 if (ReadyCycles.empty())
1893 unsigned BBNum = ReadyCycles.begin()->first->getParent()->getNumber();
1894 dbgs() <<
"\n################## Schedule time ReadyCycles for MBB : " << BBNum
1895 <<
" ##################\n# Cycle #\t\t\tInstruction "
1899 for (
auto &
I : ReadyCycles) {
1900 if (
I.second > IPrev + 1)
1901 dbgs() <<
"****************************** BUBBLE OF " <<
I.second - IPrev
1902 <<
" CYCLES DETECTED ******************************\n\n";
1903 dbgs() <<
"[ " <<
I.second <<
" ] : " << *
I.first <<
"\n";
1916 unsigned SumBubbles = 0;
1918 unsigned CurrCycle = 0;
1919 for (
auto &SU : InputSchedule) {
1920 unsigned ReadyCycle =
1922 SumBubbles += ReadyCycle - CurrCycle;
1924 ReadyCyclesSorted.insert(std::make_pair(SU.getInstr(), ReadyCycle));
1926 CurrCycle = ++ReadyCycle;
1949 unsigned SumBubbles = 0;
1951 unsigned CurrCycle = 0;
1952 for (
auto &
MI :
DAG) {
1956 unsigned ReadyCycle =
1958 SumBubbles += ReadyCycle - CurrCycle;
1960 ReadyCyclesSorted.insert(std::make_pair(SU->
getInstr(), ReadyCycle));
1962 CurrCycle = ++ReadyCycle;
1979 if (WavesAfter <
DAG.MinOccupancy)
1983 if (
DAG.MFI.isDynamicVGPREnabled()) {
1986 DAG.MFI.getDynamicVGPRBlockSize());
1989 if (BlocksAfter > BlocksBefore)
2026 <<
"\n\t *** In shouldRevertScheduling ***\n"
2027 <<
" *********** BEFORE UnclusteredHighRPStage ***********\n");
2031 <<
"\n *********** AFTER UnclusteredHighRPStage ***********\n");
2033 unsigned OldMetric = MBefore.
getMetric();
2034 unsigned NewMetric = MAfter.
getMetric();
2035 unsigned ScheduleMetricBias =
ST.getCLOpts().schedule_metric_bias;
2036 unsigned WavesBefore = std::min(
2037 S.getTargetOccupancy(),
2044 LLVM_DEBUG(
dbgs() <<
"\tMetric before " << MBefore <<
"\tMetric after "
2045 << MAfter <<
"Profit: " << Profit <<
"\n");
2075 unsigned WavesAfter) {
2080 if (!
ST.getCLOpts().lirp_reschedule)
2086 if (!
S.VGPRThresholdPercent) {
2087 LLVM_DEBUG(
dbgs() <<
"LIRP: expected VGPRThresholdPercent to be enabled, "
2088 "not using live interval RP reschedule stage\n");
2096 const AMDGPUOptions &CLOpts =
ST.getCLOpts();
2097 unsigned InstantRP =
DAG.Pressure[
RegionIdx].getArchVGPRNum();
2098 auto [RegionBegin, RegionEnd] =
DAG.Regions[
RegionIdx];
2099 if (RegionBegin == RegionEnd)
2106 unsigned NewVGPRThresholdPercent =
2107 (
S.VGPRThresholdPercent * CLOpts.lirp_vgpr_reduction + 99) / 100;
2110 <<
", VGPRThresholdPercent: " <<
S.VGPRThresholdPercent
2111 <<
" -> " << NewVGPRThresholdPercent
2112 <<
", VGPRExcessLimit=" <<
S.VGPRExcessLimit
2113 <<
", VGPRCriticalLimit=" <<
S.VGPRCriticalLimit
2114 <<
", InstantRP=" << InstantRP <<
", LIRP=" << LIRP);
2116 bool DoRescheduling =
false;
2118 unsigned InstantRPLowerBound =
2119 S.VGPRExcessLimit * CLOpts.lirp_instant_lower_bound / 100;
2120 if (LIRP >
S.VGPRExcessLimit) {
2121 LLVM_DEBUG(
dbgs() <<
" [LIRP exceeds the limit (" <<
S.VGPRExcessLimit
2122 <<
"), rescheduling]");
2123 DoRescheduling =
true;
2124 }
else if (LIRP > InstantRP && InstantRP > InstantRPLowerBound) {
2125 unsigned IncreasePercent = ((LIRP - InstantRP) * 100) / InstantRP;
2126 if (IncreasePercent > CLOpts.lirp_threshold) {
2128 << CLOpts.lirp_threshold <<
"%, rescheduling]");
2129 DoRescheduling =
true;
2135 SavedVGPRExcessLimit =
S.VGPRExcessLimit;
2136 SavedVGPRCriticalLimit =
S.VGPRCriticalLimit;
2137 SavedUnifiedVGPRCriticalLimit =
S.UnifiedVGPRCriticalLimit;
2138 SavedVGPRThresholdPercent =
S.VGPRThresholdPercent;
2139 S.VGPRThresholdPercent = NewVGPRThresholdPercent;
2147 S.VGPRExcessLimit = SavedVGPRExcessLimit;
2148 S.VGPRCriticalLimit = SavedVGPRCriticalLimit;
2149 S.UnifiedVGPRCriticalLimit = SavedUnifiedVGPRCriticalLimit;
2150 S.VGPRThresholdPercent = SavedVGPRThresholdPercent;
2157 LLVM_DEBUG(
dbgs() <<
"New pressure will result in more spilling.\n");
2169 "instruction number mismatch");
2170 if (MIOrder.
empty())
2183 if (MII != RegionEnd) {
2185 bool NonDebugReordered =
2186 !
MI->isDebugInstr() &&
2192 if (NonDebugReordered)
2193 DAG.LIS->handleMove(*
MI,
true);
2200 if (!
MI->isDebugInstr()) {
2202 SlotIndex PrevIdx =
DAG.LIS->getSlotIndexes()->getIndexBefore(*
MI);
2203 if (PrevIdx >= MIIdx)
2204 DAG.LIS->handleMove(*
MI,
true);
2208 if (
MI->isDebugInstr()) {
2215 DAG.ShouldTrackLaneMasks);
2234 if (RD->
getOpcode() == AMDGPU::AV_MOV_B32_IMM_PSEUDO ||
2235 RD->
getOpcode() == AMDGPU::AV_MOV_B64_IMM_PSEUDO)
2242bool RewriteMFMAFormStage::hasUseRequiringVGPR(
2245 for (SlotIndex RDIdx : Src2ReachingDefs) {
2246 const MachineInstr *RD =
DAG.LIS->getInstructionFromIndex(RDIdx);
2248 findReachingUses(RD,
DAG.LIS, ReachingUses);
2249 for (
const MachineOperand *UseMO : ReachingUses) {
2261void RewriteMFMAFormStage::resetRewriteCandsToVGPR(
2262 ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands) {
2263 for (
auto [
MI, OriginalOpcode] : RewriteCands) {
2266 DAG.MRI.getRegClass(
MI->getOperand(0).getReg());
2268 DAG.MRI.setRegClass(
MI->getOperand(0).getReg(), VDefRC);
2269 MI->setDesc(TII->get(OriginalOpcode));
2271 MachineOperand *
Src2 = TII->getNamedOperand(*
MI, AMDGPU::OpName::src2);
2280 DAG.MRI.setRegClass(
Src2->getReg(), VUseRC);
2284bool RewriteMFMAFormStage::isRewriteCandidate(
MachineInstr *
MI)
const {
2285 if (!
static_cast<const SIInstrInfo *
>(
DAG.TII)->isMAI(*
MI))
2290 Register DstReg =
MI->getOperand(0).getReg();
2291 for (
const MachineInstr &
UseMI :
DAG.MRI.use_nodbg_instructions(DstReg)) {
2298bool RewriteMFMAFormStage::initHeuristics(
2299 std::vector<std::pair<MachineInstr *, unsigned>> &RewriteCands,
2306 SmallPtrSet<MachineInstr *, 16> RewriteSet;
2307 DenseSet<Register> CandSrc2Regs;
2308 for (MachineBasicBlock &
MBB :
MF) {
2309 for (MachineInstr &
MI :
MBB) {
2310 if (!isRewriteCandidate(&
MI))
2313 MachineOperand *
Src2 = TII->getNamedOperand(
MI, AMDGPU::OpName::src2);
2314 if (Src2 &&
Src2->isReg())
2320 for (MachineBasicBlock &
MBB :
MF) {
2321 for (MachineInstr &
MI :
MBB) {
2322 if (!isRewriteCandidate(&
MI))
2326 assert(ReplacementOp != -1);
2328 RewriteCands.push_back({&
MI,
MI.getOpcode()});
2329 MI.setDesc(TII->get(ReplacementOp));
2331 MachineOperand *
Src2 = TII->getNamedOperand(
MI, AMDGPU::OpName::src2);
2332 if (
Src2->isReg()) {
2334 findReachingDefs(*Src2,
DAG.LIS, Src2ReachingDefs);
2338 bool Src2NeedsVGPR = hasUseRequiringVGPR(Src2ReachingDefs, RewriteSet);
2339 Src2NeedsVGPRCache[&
MI] = Src2NeedsVGPR;
2341 for (SlotIndex RDIdx : Src2ReachingDefs) {
2342 MachineInstr *RD =
DAG.LIS->getInstructionFromIndex(RDIdx);
2343 if (!Src2NeedsVGPR &&
2350 MachineOperand &Dst =
MI.getOperand(0);
2353 findReachingUses(&
MI,
DAG.LIS, DstReachingUses);
2355 for (MachineOperand *RUOp : DstReachingUses) {
2356 MachineInstr *UserMI = RUOp->getParent();
2358 if (TII->isMAI(*UserMI) && RewriteSet.
contains(UserMI))
2364 CopyForUse[UserMI->
getParent()].insert(RUOp->getReg());
2366 if (TII->isMAI(*UserMI))
2370 findReachingDefs(*RUOp,
DAG.LIS, DstUsesReachingDefs);
2372 for (SlotIndex RDIndex : DstUsesReachingDefs) {
2373 MachineInstr *RD =
DAG.LIS->getInstructionFromIndex(RDIndex);
2374 if (TII->isMAI(*RD))
2388 DAG.MRI.setRegClass(Dst.getReg(), ADefRC);
2389 if (
Src2->isReg()) {
2395 DAG.MRI.setRegClass(
Src2->getReg(), AUseRC);
2404int64_t RewriteMFMAFormStage::getRewriteCost(
2405 ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands,
2408 MachineBlockFrequencyInfo *MBFI =
DAG.MBFI;
2410 int64_t BestSpillCost = 0;
2414 std::pair<unsigned, unsigned> MaxVectorRegs =
2415 ST.getMaxNumVectorRegs(
MF.getFunction());
2416 unsigned ArchVGPRThreshold = MaxVectorRegs.first;
2417 unsigned AGPRThreshold = MaxVectorRegs.second;
2418 unsigned CombinedThreshold =
ST.getMaxNumVGPRs(
MF);
2421 if (!RegionsWithExcessArchVGPR[Region])
2426 MF, ArchVGPRThreshold, AGPRThreshold, CombinedThreshold);
2434 MF, ArchVGPRThreshold, AGPRThreshold, CombinedThreshold);
2440 bool RelativeFreqIsDenom = EntryFreq > BlockFreq;
2441 uint64_t RelativeFreq = EntryFreq && BlockFreq
2442 ? (RelativeFreqIsDenom ? EntryFreq / BlockFreq
2443 : BlockFreq / EntryFreq)
2448 int64_t SpillCost = ((int)SpillCostAfter - (int)SpillCostBefore) * 2;
2451 if (RelativeFreqIsDenom)
2452 SpillCost /= (int64_t)RelativeFreq;
2454 SpillCost *= (int64_t)RelativeFreq;
2457 if (SpillCost > 0) {
2458 resetRewriteCandsToVGPR(RewriteCands);
2462 if (SpillCost < BestSpillCost)
2463 BestSpillCost = SpillCost;
2468 Cost = BestSpillCost;
2471 unsigned CopyCost = 0;
2475 for (MachineInstr *
DefMI : CopyForDef) {
2483 CopyCost +=
static_cast<unsigned>(RC->
getCopyCost() * DefFreq);
2487 for (
auto &[UseBlock, UseRegs] : CopyForUse) {
2493 CopyCost +=
static_cast<unsigned>(RC->
getCopyCost() * UseFreq);
2501 resetRewriteCandsToVGPR(RewriteCands);
2503 return Cost + CopyCost;
2506bool RewriteMFMAFormStage::rewrite(
2507 ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands) {
2508 DenseMap<MachineInstr *, unsigned> FirstMIToRegion;
2509 DenseMap<MachineInstr *, unsigned> LastMIToRegion;
2517 if (
Entry.second !=
Entry.first->getParent()->end())
2560 DenseSet<Register> RewriteRegs;
2563 DenseMap<Register, Register> RedefMap;
2565 DenseMap<Register, DenseSet<MachineOperand *>>
ReplaceMap;
2567 DenseMap<Register, SmallPtrSet<MachineInstr *, 8>> ReachingDefCopyMap;
2570 DenseMap<unsigned, DenseMap<Register, SmallPtrSet<MachineOperand *, 8>>>
2575 SmallPtrSet<MachineInstr *, 16> RewriteCandsSet;
2576 DenseSet<Register> RewriteSrc2Regs;
2577 for (
auto &[
MI, OriginalOpcode] : RewriteCands) {
2579 MachineOperand *
Src2 = TII->getNamedOperand(*
MI, AMDGPU::OpName::src2);
2580 if (Src2 &&
Src2->isReg())
2584 for (
auto &[
MI, OriginalOpcode] : RewriteCands) {
2586 if (ReplacementOp == -1)
2588 MI->setDesc(TII->get(ReplacementOp));
2591 MachineOperand *
Src2 = TII->getNamedOperand(*
MI, AMDGPU::OpName::src2);
2592 if (
Src2->isReg()) {
2599 findReachingDefs(*Src2,
DAG.LIS, Src2ReachingDefs);
2600 SmallSetVector<MachineInstr *, 8> Src2DefsReplace;
2604 bool Src2NeedsVGPR = Src2NeedsVGPRCache.lookup(
MI);
2606 for (SlotIndex RDIndex : Src2ReachingDefs) {
2607 MachineInstr *RD =
DAG.LIS->getInstructionFromIndex(RDIndex);
2608 if (!Src2NeedsVGPR &&
2612 Src2DefsReplace.
insert(RD);
2615 if (!Src2DefsReplace.
empty()) {
2616 auto RI = RedefMap.
find(Src2Reg);
2617 if (RI != RedefMap.
end()) {
2618 MappedReg = RI->second;
2623 SRI->getEquivalentVGPRClass(Src2RC);
2626 MappedReg =
DAG.MRI.createVirtualRegister(VGPRRC);
2627 RedefMap[Src2Reg] = MappedReg;
2632 for (MachineInstr *RD : Src2DefsReplace) {
2634 if (ReachingDefCopyMap[Src2Reg].insert(RD).second) {
2635 MachineInstrBuilder VGPRCopy =
2638 .
addDef(MappedReg, {}, 0)
2639 .addUse(Src2Reg, {}, 0);
2640 DAG.LIS->InsertMachineInstrInMaps(*VGPRCopy);
2645 unsigned UpdateRegion = LastMIToRegion[RD];
2646 DAG.Regions[UpdateRegion].second = VGPRCopy;
2647 LastMIToRegion.
erase(RD);
2654 RewriteRegs.
insert(Src2Reg);
2664 MachineOperand *Dst = &
MI->getOperand(0);
2673 SmallVector<MachineInstr *, 8> DstUseDefsReplace;
2675 findReachingUses(
MI,
DAG.LIS, DstReachingUses);
2677 for (MachineOperand *RUOp : DstReachingUses) {
2678 MachineInstr *UserMI = RUOp->
getParent();
2680 if (TII->isMAI(*UserMI) && RewriteCandsSet.
contains(UserMI))
2684 if (
find(DstReachingUseCopies, RUOp) == DstReachingUseCopies.
end())
2688 if (TII->isMAI(*UserMI))
2692 findReachingDefs(*RUOp,
DAG.LIS, DstUsesReachingDefs);
2694 for (SlotIndex RDIndex : DstUsesReachingDefs) {
2695 MachineInstr *RD =
DAG.LIS->getInstructionFromIndex(RDIndex);
2696 if (TII->isMAI(*RD))
2701 if (
find(DstUseDefsReplace, RD) == DstUseDefsReplace.
end())
2706 if (!DstUseDefsReplace.
empty()) {
2707 auto RI = RedefMap.
find(DstReg);
2708 if (RI != RedefMap.
end()) {
2709 MappedReg = RI->second;
2716 MappedReg =
DAG.MRI.createVirtualRegister(VGPRRC);
2717 RedefMap[DstReg] = MappedReg;
2722 for (MachineInstr *RD : DstUseDefsReplace) {
2724 if (ReachingDefCopyMap[DstReg].insert(RD).second) {
2725 MachineInstrBuilder VGPRCopy =
2728 .
addDef(MappedReg, {}, 0)
2729 .addUse(DstReg, {}, 0);
2730 DAG.LIS->InsertMachineInstrInMaps(*VGPRCopy);
2734 auto LMI = LastMIToRegion.
find(RD);
2735 if (LMI != LastMIToRegion.
end()) {
2736 unsigned UpdateRegion = LMI->second;
2737 DAG.Regions[UpdateRegion].second = VGPRCopy;
2738 LastMIToRegion.
erase(RD);
2744 DenseSet<MachineOperand *> &DstRegSet =
ReplaceMap[DstReg];
2747 MachineInstr *EarliestSameBlockUse =
nullptr;
2748 for (MachineOperand *RU : DstReachingUseCopies) {
2749 MachineBasicBlock *RUBlock = RU->getParent()->getParent();
2752 if (RUBlock !=
MI->getParent()) {
2758 if (!SameBlockCopyReg.
isValid()) {
2761 SameBlockCopyReg =
DAG.MRI.createVirtualRegister(VGPRRC);
2765 MachineInstr *UseInst = RU->getParent();
2766 if (!EarliestSameBlockUse ||
2768 DAG.LIS->getInstructionIndex(*UseInst),
2769 DAG.LIS->getInstructionIndex(*EarliestSameBlockUse)))
2770 EarliestSameBlockUse = UseInst;
2771 RU->setReg(SameBlockCopyReg);
2775 if (SameBlockCopyReg.
isValid()) {
2776 MachineInstrBuilder VGPRCopy =
2779 TII->get(TargetOpcode::COPY), SameBlockCopyReg)
2781 DAG.LIS->InsertMachineInstrInMaps(*VGPRCopy);
2786 RewriteRegs.
insert(DstReg);
2796 std::pair<unsigned, DenseMap<Register, SmallPtrSet<MachineOperand *, 8>>>;
2797 for (RUBType RUBlockEntry : ReachingUseTracker) {
2798 using RUDType = std::pair<Register, SmallPtrSet<MachineOperand *, 8>>;
2799 for (RUDType RUDst : RUBlockEntry.second) {
2800 MachineOperand *OpBegin = *RUDst.second.begin();
2801 SlotIndex InstPt =
DAG.LIS->getInstructionIndex(*OpBegin->
getParent());
2804 for (MachineOperand *User : RUDst.second) {
2805 SlotIndex NewInstPt =
DAG.LIS->getInstructionIndex(*
User->getParent());
2812 Register NewUseReg =
DAG.MRI.createVirtualRegister(VGPRRC);
2813 MachineInstr *UseInst =
DAG.LIS->getInstructionFromIndex(InstPt);
2815 MachineInstrBuilder VGPRCopy =
2818 .
addDef(NewUseReg, {}, 0)
2819 .addUse(RUDst.first, {}, 0);
2820 DAG.LIS->InsertMachineInstrInMaps(*VGPRCopy);
2824 auto FI = FirstMIToRegion.
find(UseInst);
2825 if (FI != FirstMIToRegion.
end()) {
2826 unsigned UpdateRegion = FI->second;
2827 DAG.Regions[UpdateRegion].first = VGPRCopy;
2828 FirstMIToRegion.
erase(UseInst);
2832 for (MachineOperand *User : RUDst.second) {
2833 User->setReg(NewUseReg);
2844 for (std::pair<Register, Register> NewDef : RedefMap) {
2849 for (MachineOperand *ReplaceOp :
ReplaceMap[OldReg])
2850 ReplaceOp->setReg(NewReg);
2854 for (
Register RewriteReg : RewriteRegs) {
2855 Register RegToRewrite = RewriteReg;
2858 auto RI = RedefMap.find(RewriteReg);
2859 if (RI != RedefMap.end())
2860 RegToRewrite = RI->second;
2865 DAG.MRI.setRegClass(RegToRewrite, AGPRRC);
2869 DAG.LIS->reanalyze(
DAG.MF);
2871 RegionPressureMap LiveInUpdater(&
DAG,
false);
2872 LiveInUpdater.buildLiveRegMap();
2875 DAG.LiveIns[Region] = LiveInUpdater.getLiveRegsForRegionIdx(Region);
2882unsigned PreRARematStage::getStageTargetOccupancy()
const {
2883 return TargetOcc ? *TargetOcc :
MFI.getMinWavesPerEU();
2895 if (
DAG.MinOccupancy >= *TargetOcc)
2899 for (
const auto &[
RegionIdx, OrigMIOrder, MaxPressure] : RegionReverts) {
2909 if (AchievedOcc >= *TargetOcc) {
2910 DAG.setTargetOccupancy(AchievedOcc);
2915 DAG.setTargetOccupancy(*TargetOcc - 1);
2916 Strategy->rollbackRecordedRemats();
2917 for (
unsigned RegionIdx : RescheduleRegions.set_bits()) {
2922#ifdef EXPENSIVE_CHECKS
2931void GCNScheduleDAGMILive::setTargetOccupancy(
unsigned TargetOccupancy) {
2932 MinOccupancy = TargetOccupancy;
2933 if (MFI.getOccupancy() < TargetOccupancy)
2934 MFI.increaseOccupancy(
MF, MinOccupancy);
2936 MFI.limitOccupancy(MinOccupancy);
2953 if (HasIGLPInstrs) {
2954 SavedMutations.clear();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static SUnit * pickOnlyChoice(SchedBoundary &Zone)
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the GCNRegPressure class, which tracks registry pressure by bookkeeping number of S...
Rematerialization strategy, based on the target-independent rematerializer.
static MachineInstr * getLastMIForRegion(MachineBasicBlock::iterator RegionBegin, MachineBasicBlock::iterator RegionEnd)
static void printScheduleModel(std::set< std::pair< MachineInstr *, unsigned >, EarlierIssuingCycle > &ReadyCycles)
static bool isReachingDefAGPRForm(MachineInstr *RD, const SmallPtrSetImpl< MachineInstr * > &RewriteSet, const DenseSet< Register > &CandSrc2Regs, const SIInstrInfo &TII)
Returns true if reaching def RD will be in AGPR form after the rewrite and so needs no bridge copy: a...
static bool hasIGLPInstrs(ScheduleDAGInstrs *DAG)
static bool shouldCheckPending(unsigned PendingQueueLimit, SchedBoundary &Zone, const TargetSchedModel *SchedModel)
static bool canUsePressureDiffs(const SUnit &SU)
Checks whether SU can use the cached DAG pressure diffs to compute the current register pressure.
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
static constexpr std::pair< StringLiteral, StringLiteral > ReplaceMap[]
Promote Memory to Register
MachineRegisterInfo & MRI
const AMDGPUOptions & getCLOpts() const
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
uint64_t getFrequency() const
Returns the frequency as a fixpoint number scaled by the entry frequency.
bool initGCNSchedStage() override
bool shouldRevertScheduling(unsigned WavesAfter) override
bool initGCNRegion() override
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
Common behavior for downward RP trackers. Unconstructible directly.
Downward RP tracker that relies on program order to advance down the instruction stream.
GCNMaxILPSchedStrategy(const MachineSchedContext *C)
bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const override
Apply a set of heuristics to a new candidate.
bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const override
GCNMaxMemoryClauseSchedStrategy tries best to clause memory instructions as much as possible.
GCNMaxMemoryClauseSchedStrategy(const MachineSchedContext *C)
GCNMaxOccupancySchedStrategy(const MachineSchedContext *C, bool IsLegacyScheduler=false)
void finalizeSchedule() override
Allow targets to perform final scheduling actions at the level of the whole MachineFunction.
void schedule() override
Orders nodes according to selected style.
GCNPostScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S, bool RemoveKillFlags)
Models a register pressure target, allowing to evaluate and track register savings against that targe...
GCNRegPressure getPressure() const
void reset(const MachineInstr &MI, bool After)
Resets tracker before or After the provided MI, which can be a debug instruction.
virtual bool initGCNRegion()
GCNRegPressure PressureBefore
bool isRegionWithExcessRP() const
void modifyRegionSchedule(unsigned RegionIdx, ArrayRef< MachineInstr * > MIOrder)
Sets the schedule of region RegionIdx to MIOrder.
bool mayCauseSpilling(unsigned WavesAfter)
ScheduleMetrics getScheduleMetrics(const std::vector< SUnit > &InputSchedule)
GCNScheduleDAGMILive & DAG
const GCNSchedStageID StageID
std::vector< MachineInstr * > Unsched
GCNRegPressure PressureAfter
virtual void finalizeGCNRegion()
SIMachineFunctionInfo & MFI
unsigned computeSUnitReadyCycle(const SUnit &SU, unsigned CurrCycle, DenseMap< unsigned, unsigned > &ReadyCycles, const TargetSchedModel &SM)
virtual void finalizeGCNSchedStage()
virtual bool initGCNSchedStage()
virtual bool shouldRevertScheduling(unsigned WavesAfter)
std::vector< std::unique_ptr< ScheduleDAGMutation > > SavedMutations
GCNSchedStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
MachineBasicBlock * CurrentMBB
This is a minimal scheduler strategy.
bool useGCNTrackers() const
GCNSchedStrategy(const MachineSchedContext *C)
SmallVector< GCNSchedStageID, 4 > SchedStages
unsigned SGPRCriticalLimit
unsigned VGPRThresholdPercent
std::vector< unsigned > MaxPressure
bool hasNextStage() const
unsigned CandUnifiedVGPRPressure
Combined-file pressure of the candidate most recently passed to getRegisterPressures().
SUnit * pickNodeBidirectional(bool &IsTopNode, bool &PickedPending)
GCNSchedStageID getCurrentStage()
bool tryPendingCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const
Evaluates instructions in the pending queue using a subset of scheduling heuristics.
SmallVectorImpl< GCNSchedStageID >::iterator CurrentStage
std::pair< unsigned, unsigned > getBankedPressure(const GCNRegPressure &RP) const
unsigned VGPRCriticalLimit
void schedNode(SUnit *SU, bool IsTopNode) override
Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an instruction and updated scheduled/rem...
unsigned AGPRBankLimit
Capacity of the AGPR bank, captured before AGPRExcessLimit is cut down by ErrorMargin and VGPRLimitBi...
unsigned ArchVGPRBankLimit
Capacity of the ArchVGPR bank, captured before VGPRExcessLimit is cut down by ErrorMargin,...
std::optional< bool > GCNTrackersOverride
void getRegisterPressures(bool AtTop, const RegPressureTracker &RPTracker, SUnit *SU, std::vector< unsigned > &Pressure, std::vector< unsigned > &MaxPressure, const GCNDownwardRPTrackerBase &DownwardTracker, const GCNUpwardRPTracker &UpwardTracker, ScheduleDAGMI *DAG, const SIRegisterInfo *SRI)
unsigned AGPRCriticalLimit
std::vector< unsigned > Pressure
unsigned UnifiedVGPRCriticalLimit
void initialize(ScheduleDAGMI *DAG) override
Initialize the strategy after building the DAG for a new region.
GCNUpwardRPTracker UpwardTracker
void printCandidateDecision(const SchedCandidate &Current, const SchedCandidate &Preferred)
void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy, const RegPressureTracker &RPTracker, SchedCandidate &Cand, bool &IsPending, bool IsBottomUp)
GCNManualDownwardRPTracker DownwardTracker
GCNUpwardRPTracker & getUpwardTracker()
const AMDGPUOptions & CLOpts
void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop, const RegPressureTracker &RPTracker, const SIRegisterInfo *SRI, unsigned SGPRPressure, unsigned VGPRPressure, unsigned AGPRPressure, bool IsBottomUp)
GCNDownwardRPTrackerBase & getDownwardTracker()
SUnit * pickNode(bool &IsTopNode) override
Pick the next node to schedule, or return NULL.
unsigned UnifiedVGPRExcessLimit
Budget for the combined ArchVGPR + AGPR file, or zero on targets without one.
void finalizeSchedule() override
Allow targets to perform final scheduling actions at the level of the whole MachineFunction.
void schedule() override
Orders nodes according to selected style.
GCNScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S)
void recede(const MachineInstr &MI)
Move to the state of RP just before the MI.
void reset(const MachineInstr &MI)
Resets tracker to the point just after MI (in program order), which can be a debug instruction.
void traceCandidate(const SchedCandidate &Cand)
LLVM_ABI void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone, SchedBoundary *OtherZone)
Set the CandPolicy given a scheduling zone given the current resources and latencies inside and outsi...
MachineSchedPolicy RegionPolicy
const TargetSchedModel * SchedModel
const MachineSchedContext * Context
const TargetRegisterInfo * TRI
SchedCandidate BotCand
Candidate last picked from Bot boundary.
SchedCandidate TopCand
Candidate last picked from Top boundary.
virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const
Apply a set of heuristics to a new candidate.
void initialize(ScheduleDAGMI *dag) override
Initialize the strategy after building the DAG for a new region.
void schedNode(SUnit *SU, bool IsTopNode) override
Update the scheduler's state after scheduling a node.
GenericScheduler(const MachineSchedContext *C)
bool shouldRevertScheduling(unsigned WavesAfter) override
void finalizeGCNRegion() override
bool initGCNRegion() override
bool initGCNSchedStage() override
LiveInterval - This class represents the liveness of a register, or stack slot.
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const
Return the last index in the given basic block.
LiveInterval & getInterval(Register Reg)
LLVM_ABI void dump() const
MachineBasicBlock * getMBBFromIndex(SlotIndex index) const
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
uint8_t getCopyCost() const
getCopyCost - Return the cost of copying a value between two registers in this class.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
succ_iterator succ_begin()
unsigned succ_size() const
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI BlockFrequency getBlockFreq(const MachineBasicBlock *MBB) const
getblockFreq - Return block frequency.
LLVM_ABI BlockFrequency getEntryFreq() const
Divide a block's BlockFrequency::getFrequency() value by this value to obtain the entry block - relat...
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
Register getReg() const
getReg - Returns the register number.
bool shouldRevertScheduling(unsigned WavesAfter) override
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
bool shouldRevertScheduling(unsigned WavesAfter) override
bool shouldRevertScheduling(unsigned WavesAfter) override
void finalizeGCNRegion() override
bool initGCNRegion() override
bool initGCNSchedStage() override
Capture a change in pressure for a single pressure set.
Helpers for implementing custom MachineSchedStrategy classes.
Track the current register pressure at some position in the instruction stream, and remember the high...
RegisterPressure & getPressure()
Get the resulting register pressure over the traversed region.
LLVM_ABI void getDownwardPressure(const MachineInstr *MI, std::vector< unsigned > &PressureResult, std::vector< unsigned > &MaxPressureResult)
Get the pressure of each PSet after traversing this instruction top-down.
const std::vector< unsigned > & getRegSetPressureAtPos() const
Get the register set pressure at the current position, which may be less than the pressure across the...
LLVM_ABI void getUpwardPressure(const MachineInstr *MI, std::vector< unsigned > &PressureResult, std::vector< unsigned > &MaxPressureResult)
Get the pressure of each PSet after traversing this instruction bottom-up.
static LLVM_ABI void restoreLivenessFlags(MachineInstr &MI, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI, LiveIntervals &LIS, bool TrackLaneMasks=true, ArrayRef< Register > OnlyRegs={})
Clear potentially-stale read-undef flags on the defs of MI, then recompute them from LIS.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
bool isIGLPMutationOnly(unsigned Opcode) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
unsigned getOccupancy() const
unsigned getDynamicVGPRBlockSize() const
unsigned getMinAllowedOccupancy() const
Scheduling unit. This is a node in the scheduling DAG.
bool isInstr() const
Returns true if this SUnit refers to a machine instruction as opposed to an SDNode.
unsigned TopReadyCycle
Cycle relative to start when node is ready.
unsigned NodeNum
Entry # of node in the node vector.
unsigned short Latency
Node latency.
bool isScheduled
True once scheduled.
unsigned ParentClusterIdx
The parent cluster id.
unsigned BotReadyCycle
Cycle relative to end when node is ready.
bool isBottomReady() const
SmallVector< SDep, 4 > Preds
All sunit predecessors.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
Each Scheduling boundary is associated with ready queues.
LLVM_ABI void releasePending()
Release pending ready nodes in to the available queue.
LLVM_ABI unsigned getLatencyStallCycles(SUnit *SU)
Get the difference between the given SUnit's ready time and the current cycle.
LLVM_ABI SUnit * pickOnlyChoice()
Call this before applying any other heuristics to the Available queue.
LLVM_ABI void bumpCycle(unsigned NextCycle)
Move the boundary of scheduled code by one cycle.
unsigned getCurrMOps() const
Micro-ops issued in the current cycle.
unsigned getCurrCycle() const
Number of cycles to issue the instructions scheduled in this zone.
LLVM_ABI bool checkHazard(SUnit *SU)
Does this SU have a hazard within the current instruction group.
A ScheduleDAG for scheduling lists of MachineInstr.
bool ScheduleSingleMIRegions
True if regions with a single MI should be scheduled.
MachineBasicBlock::iterator RegionEnd
The end of the range to be scheduled.
virtual void finalizeSchedule()
Allow targets to perform final scheduling actions at the level of the whole MachineFunction.
const MachineLoopInfo * MLI
bool RemoveKillFlags
True if the DAG builder should remove kill flags (in preparation for rescheduling).
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
ScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S)
RegPressureTracker RPTracker
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
void exitRegion() override
Called when the scheduler has finished scheduling the current region.
void addMutation(std::unique_ptr< ScheduleDAGMutation > Mutation)
Add a postprocessing step to the DAG builder.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S, bool RemoveKillFlags)
std::vector< std::unique_ptr< ScheduleDAGMutation > > Mutations
Ordered list of DAG postprocessing steps.
MachineRegisterInfo & MRI
Virtual/real register map.
const TargetInstrInfo * TII
Target instruction information.
MachineFunction & MF
Machine function.
static const unsigned ScaleFactor
unsigned getMetric() const
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
SlotIndex - An opaque wrapper around machine indexes.
static bool isSameInstr(SlotIndex A, SlotIndex B)
isSameInstr - Return true if A and B refer to the same instruction.
static bool isEarlierInstr(SlotIndex A, SlotIndex B)
isEarlierInstr - Return true if A refers to an instruction earlier than B.
SlotIndex getPrevSlot() const
Returns the previous slot in the index list.
SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const
Returns the first index in the given basic block.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Provide an instruction scheduling machine model to CodeGen passes.
LLVM_ABI bool hasInstrSchedModel() const
Return true if this machine model includes an instruction-level scheduling model.
unsigned getMicroOpBufferSize() const
Number of micro-ops that may be buffered for OOO execution.
bool initGCNSchedStage() override
bool initGCNRegion() override
void finalizeGCNSchedStage() override
bool shouldRevertScheduling(unsigned WavesAfter) override
VNInfo - Value Number Information.
SlotIndex def
The index of the defining instruction.
bool isPHIDef() const
Returns true if this value is defined by a PHI instruction (or was, PHI instructions may have been el...
LLVM Value Representation.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getAddressableNumVGPRs(const MCSubtargetInfo &STI, unsigned DynamicVGPRBlockSize)
unsigned getAllocatedNumVGPRBlocks(const MCSubtargetInfo &STI, unsigned NumVGPRs, unsigned DynamicVGPRBlockSize, std::optional< bool > EnableWavefrontSize32)
unsigned getVGPRAllocGranule(const MCSubtargetInfo &STI, unsigned DynamicVGPRBlockSize, std::optional< bool > EnableWavefrontSize32)
LLVM_READONLY int32_t getAGPRFormOp(uint32_t Opcode)
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI int biasPhysReg(const SUnit *SU, bool isTop, bool BiasPRegsExtra=false)
Minimize physical register live ranges.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
LLVM_ABI unsigned getWeakLeft(const SUnit *SU, bool isTop)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI, Range &&LiveRegs)
std::unique_ptr< ScheduleDAGMutation > createIGroupLPDAGMutation(AMDGPU::SchedulingPhase Phase)
Phase specifes whether or not this is a reentry into the IGroupLPDAGMutation.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
std::pair< MachineBasicBlock::iterator, MachineBasicBlock::iterator > RegionBoundaries
A region's boundaries i.e.
IterT skipDebugInstructionsForward(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It until it points to a non-debug instruction or to End and return the resulting iterator.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool tryPressure(const PressureChange &TryP, const PressureChange &CandP, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason, const TargetRegisterInfo *TRI, const MachineFunction &MF)
@ UnclusteredHighRPReschedule
@ MemoryClauseInitialSchedule
@ LiveIntervalRPReschedule
@ ClusteredLowOccupancyReschedule
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
cl::opt< unsigned, false, VGPRThresholdParser > VGPRThresholdPercentOpt
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI bool shouldVerifyScheduling()
Returns whether -verify-misched is set.
iterator_range< ConstMIBundleOperands > const_mi_bundle_ops(const MachineInstr &MI)
LLVM_ABI bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, SchedBoundary &Zone)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
IterT skipDebugInstructionsBackward(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It until it points to a non-debug instruction or to Begin and return the resulting iterator...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
bool isTheSameCluster(unsigned A, unsigned B)
Return whether the input cluster ID's are the same and valid.
DWARFExpression::Operation Op
LLVM_ABI bool tryGreater(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
DenseMap< MachineInstr *, GCNRPTracker::LiveRegSet > getLiveRegMap(Range &&R, bool After, LiveIntervals &LIS)
creates a map MachineInstr -> LiveRegSet R - range of iterators on instructions After - upon entry or...
GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI, const LiveIntervals &LIS)
LLVM_ABI bool tryLess(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
Return true if this heuristic determines order.
LLVM_ABI void dumpMaxRegPressure(MachineFunction &MF, GCNRegPressure::RegKind Kind, LiveIntervals &LIS, const MachineLoopInfo *MLI)
unsigned estimateGreedyVGPRPressure(MachineBasicBlock::const_iterator RegionBegin, MachineBasicBlock::const_iterator RegionEnd, const GCNRPTracker::LiveRegSet &LiveIns, const LiveIntervals &LIS, const MachineRegisterInfo &MRI, const SIRegisterInfo &TRI)
Estimate VGPR pressure using greedy, non-splitting register allocation simulation,...
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
MCRegisterClass TargetRegisterClass
Implement std::hash so that hash_code can be used in STL containers.
bool operator()(std::pair< MachineInstr *, unsigned > A, std::pair< MachineInstr *, unsigned > B) const
static unsigned getBankedUnifiedVGPRNum(unsigned NumArchVGPRs, unsigned NumAGPRs)
Returns the aggregated VGPR pressure for NumArchVGPRs ArchVGPRs and NumAGPRs AGPRs,...
unsigned getSGPRNum() const
static unsigned getUnifiedVGPRNum(unsigned NumArchVGPRs, unsigned NumAGPRs, unsigned NumAVGPRs)
Returns the aggregated VGPR pressure, assuming NumArchVGPRs ArchVGPRs NumAGPRs AGPRS,...
Policy for scheduling the next instruction in the candidate's zone.
Store the state used by GenericScheduler heuristics, required for the lifetime of one invocation of p...
void setBest(SchedCandidate &Best)
void reset(const CandPolicy &NewPolicy)
LLVM_ABI void initResourceDelta(const ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel)
SchedResourceDelta ResDelta
Status of an instruction's critical resource consumption.
unsigned DemandedResources
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
PressureChange CriticalMax
PressureChange CurrentMax
bool parse(cl::Option &O, StringRef ArgName, StringRef Arg, unsigned &Value)