44#define DEBUG_TYPE "machine-scheduler"
49 "amdgpu-disable-unclustered-high-rp-reschedule",
cl::Hidden,
50 cl::desc(
"Disable unclustered high register pressure "
51 "reduction scheduling stage."),
55 "amdgpu-disable-clustered-low-occupancy-reschedule",
cl::Hidden,
56 cl::desc(
"Disable clustered low occupancy "
57 "rescheduling for ILP scheduling stage."),
63 "Sets the bias which adds weight to occupancy vs latency. Set it to "
64 "100 to chase the occupancy only."),
69 cl::desc(
"Relax occupancy targets for kernels which are memory "
70 "bound (amdgpu-membound-threshold), or "
71 "Wave Limited (amdgpu-limit-wave-threshold)."),
76 cl::desc(
"Use the AMDGPU specific RPTrackers during scheduling"),
80 "amdgpu-scheduler-pending-queue-limit",
cl::Hidden,
82 "Max (Available+Pending) size to inspect pending queue (0 disables)"),
85#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
86#define DUMP_MAX_REG_PRESSURE
88 "amdgpu-print-max-reg-pressure-regusage-before-scheduler",
cl::Hidden,
89 cl::desc(
"Print a list of live registers along with their def/uses at the "
90 "point of maximum register pressure before scheduling."),
94 "amdgpu-print-max-reg-pressure-regusage-after-scheduler",
cl::Hidden,
95 cl::desc(
"Print a list of live registers along with their def/uses at the "
96 "point of maximum register pressure after scheduling."),
101 "amdgpu-disable-rewrite-mfma-form-sched-stage",
cl::Hidden,
107 return O.error(
"'" + Arg +
"' value invalid for uint argument!");
110 return O.error(
"'" + Arg +
"' value must be in the range [0, 100]!");
117 cl::desc(
"Percent of VGPR limits that we should use as RP threshold "
118 "during scheduling. We have two limits relevant to scheduling: "
119 "Critical (avoid decreasing occupancy), Excess (avoid spilling). "
120 "This flag scales both limits back by an equal percent: (0 = use "
121 " default calculation, 1-100 = use percentage), default: 0"),
142 Context->RegClassInfo->getNumAllocatableRegs(&AMDGPU::SGPR_32RegClass);
144 Context->RegClassInfo->getNumAllocatableRegs(&AMDGPU::VGPR_32RegClass);
146 Context->RegClassInfo->getNumAllocatableRegs(&AMDGPU::AGPR_32RegClass);
169 "VGPRCriticalLimit calculation method.\n");
173 unsigned Addressable =
176 VGPRBudget = std::max(VGPRBudget, Granule);
195 <<
". VGPRCriticalLimit: " << OriginalVGPRCriticalLimit
213 <<
", UnifiedVGPRCriticalLimit = "
246 if (!
Op.isReg() ||
Op.isImplicit())
248 if (
Op.getReg().isPhysical() ||
249 (
Op.isDef() &&
Op.getSubReg() != AMDGPU::NoSubRegister))
284 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] =
293 unsigned SGPRPressure,
294 unsigned VGPRPressure,
295 unsigned AGPRPressure,
bool IsBottomUp) {
299 if (!
DAG->isTrackingPressure())
322 Pressure[AMDGPU::RegisterPressureSets::SReg_32] = SGPRPressure;
323 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] = VGPRPressure;
324 Pressure[AMDGPU::RegisterPressureSets::AGPR_32] = AGPRPressure;
326 for (
const auto &Diff :
DAG->getPressureDiff(SU)) {
332 (IsBottomUp ? Diff.getUnitInc() : -Diff.getUnitInc());
335#ifdef EXPENSIVE_CHECKS
336 std::vector<unsigned> CheckPressure, CheckMaxPressure;
339 if (
Pressure[AMDGPU::RegisterPressureSets::SReg_32] !=
340 CheckPressure[AMDGPU::RegisterPressureSets::SReg_32] ||
341 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] !=
342 CheckPressure[AMDGPU::RegisterPressureSets::VGPR_32] ||
343 Pressure[AMDGPU::RegisterPressureSets::AGPR_32] !=
344 CheckPressure[AMDGPU::RegisterPressureSets::AGPR_32]) {
345 errs() <<
"Register Pressure is inaccurate when calculated through "
347 <<
"SGPR got " <<
Pressure[AMDGPU::RegisterPressureSets::SReg_32]
349 << CheckPressure[AMDGPU::RegisterPressureSets::SReg_32] <<
"\n"
350 <<
"VGPR got " <<
Pressure[AMDGPU::RegisterPressureSets::VGPR_32]
352 << CheckPressure[AMDGPU::RegisterPressureSets::VGPR_32] <<
"\n"
353 <<
"AGPR got " <<
Pressure[AMDGPU::RegisterPressureSets::AGPR_32]
355 << CheckPressure[AMDGPU::RegisterPressureSets::AGPR_32] <<
"\n";
361 unsigned NewAGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::AGPR_32];
362 unsigned NewSGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::SReg_32];
363 unsigned NewVGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::VGPR_32];
373 const unsigned MaxVGPRPressureInc = 16;
374 bool ShouldTrackVGPRs = VGPRPressure + MaxVGPRPressureInc >=
VGPRExcessLimit;
377 bool ShouldTrackSGPRs =
378 !ShouldTrackVGPRs && !ShouldTrackAGPRs && SGPRPressure >=
SGPRExcessLimit;
413 bool UnifiedVGPRFile =
MF->getSubtarget<
GCNSubtarget>().hasGFX90AInsts();
415 if (UnifiedVGPRFile) {
423 int VGPRDelta = NewVGPRPressure - VectorCriticalLimit;
426 : std::numeric_limits<int>::min();
428 if (SGPRDelta >= 0 || VGPRDelta >= 0 || AGPRDelta >= 0) {
431 if (VGPRDelta >= SGPRDelta && VGPRDelta >= AGPRDelta) {
435 }
else if (AGPRDelta >= SGPRDelta) {
449 bool HasBufferedModel =
468 dbgs() <<
"Prefer:\t\t";
469 DAG->dumpNode(*Preferred.
SU);
473 DAG->dumpNode(*Current.
SU);
476 dbgs() <<
"Reason:\t\t";
490 unsigned SGPRPressure = 0;
491 unsigned VGPRPressure = 0;
492 unsigned AGPRPressure = 0;
494 if (
DAG->isTrackingPressure()) {
496 SGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::SReg_32];
497 VGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::VGPR_32];
498 AGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::AGPR_32];
503 SGPRPressure =
T->getPressure().getSGPRNum();
504 VGPRPressure =
T->getPressure().getArchVGPRNum();
505 AGPRPressure =
T->getPressure().getAGPRNum();
510 for (
SUnit *SU : AQ) {
514 VGPRPressure, AGPRPressure, IsBottomUp);
534 for (
SUnit *SU : PQ) {
538 VGPRPressure, AGPRPressure, IsBottomUp);
558 bool &PickedPending) {
578 bool BotPending =
false;
598 "Last pick result should correspond to re-picking right now");
603 bool TopPending =
false;
623 "Last pick result should correspond to re-picking right now");
633 PickedPending = BotPending && TopPending;
636 if (BotPending || TopPending) {
643 Cand.setBest(TryCand);
648 IsTopNode = Cand.AtTop;
655 if (
DAG->top() ==
DAG->bottom()) {
657 Bot.Available.empty() &&
Bot.Pending.empty() &&
"ReadyQ garbage");
663 PickedPending =
false;
697 if (ReadyCycle > CurrentCycle)
762 if (
DAG->isTrackingPressure() &&
768 if (
DAG->isTrackingPressure() &&
773 bool SameBoundary = Zone !=
nullptr;
797 if (IsLegacyScheduler)
816 if (
DAG->isTrackingPressure() &&
826 bool SameBoundary = Zone !=
nullptr;
861 bool CandIsClusterSucc =
863 bool TryCandIsClusterSucc =
865 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
870 if (
DAG->isTrackingPressure() &&
876 if (
DAG->isTrackingPressure() &&
922 if (
DAG->isTrackingPressure()) {
938 bool CandIsClusterSucc =
940 bool TryCandIsClusterSucc =
942 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
951 bool SameBoundary = Zone !=
nullptr;
968 if (TryMayLoad || CandMayLoad) {
969 bool TryLongLatency =
971 bool CandLongLatency =
975 Zone->
isTop() ? CandLongLatency : TryLongLatency, TryCand,
993 if (
DAG->isTrackingPressure() &&
1012 !
Rem.IsAcyclicLatencyLimited &&
tryLatency(TryCand, Cand, *Zone))
1030 StartingOccupancy(MFI.getOccupancy()), MinOccupancy(StartingOccupancy),
1031 RegionLiveOuts(this,
true) {
1037 LLVM_DEBUG(
dbgs() <<
"Starting occupancy is " << StartingOccupancy <<
".\n");
1039 MinOccupancy = std::min(MFI.getMinAllowedOccupancy(), StartingOccupancy);
1040 if (MinOccupancy != StartingOccupancy)
1041 LLVM_DEBUG(
dbgs() <<
"Allowing Occupancy drops to " << MinOccupancy
1046std::unique_ptr<GCNSchedStage>
1048 switch (SchedStageID) {
1050 return std::make_unique<OccInitialScheduleStage>(SchedStageID, *
this);
1052 return std::make_unique<RewriteMFMAFormStage>(SchedStageID, *
this);
1054 return std::make_unique<UnclusteredHighRPStage>(SchedStageID, *
this);
1056 return std::make_unique<ClusteredLowOccStage>(SchedStageID, *
this);
1058 return std::make_unique<PreRARematStage>(SchedStageID, *
this);
1060 return std::make_unique<ILPInitialScheduleStage>(SchedStageID, *
this);
1062 return std::make_unique<MemoryClauseInitialScheduleStage>(SchedStageID,
1065 return std::make_unique<LiveIntervalRPStage>(SchedStageID, *
this);
1078GCNScheduleDAGMILive::getRealRegPressure(
unsigned RegionIdx)
const {
1079 if (Regions[RegionIdx].first == Regions[RegionIdx].second)
1083 &LiveIns[RegionIdx]);
1089 assert(RegionBegin != RegionEnd &&
"Region must not be empty");
1093void GCNScheduleDAGMILive::computeBlockPressure(
unsigned RegionIdx,
1105 const MachineBasicBlock *OnlySucc =
nullptr;
1108 if (!Candidate->empty() && Candidate->pred_size() == 1) {
1109 SlotIndexes *Ind =
LIS->getSlotIndexes();
1111 OnlySucc = Candidate;
1116 size_t CurRegion = RegionIdx;
1117 for (
size_t E = Regions.size(); CurRegion !=
E; ++CurRegion)
1118 if (Regions[CurRegion].first->getParent() !=
MBB)
1123 auto LiveInIt = MBBLiveIns.find(
MBB);
1124 auto &Rgn = Regions[CurRegion];
1126 if (LiveInIt != MBBLiveIns.end()) {
1127 auto LiveIn = std::move(LiveInIt->second);
1129 MBBLiveIns.erase(LiveInIt);
1132 auto LRS = BBLiveInMap.lookup(NonDbgMI);
1133#ifdef EXPENSIVE_CHECKS
1142 if (Regions[CurRegion].first ==
I || NonDbgMI ==
I) {
1143 LiveIns[CurRegion] =
RPTracker.getLiveRegs();
1147 if (Regions[CurRegion].second ==
I) {
1148 Pressure[CurRegion] =
RPTracker.moveMaxPressure();
1149 if (CurRegion-- == RegionIdx)
1151 auto &Rgn = Regions[CurRegion];
1164 MBBLiveIns[OnlySucc] =
RPTracker.moveLiveRegs();
1169GCNScheduleDAGMILive::getRegionLiveInMap()
const {
1170 assert(!Regions.empty());
1171 std::vector<MachineInstr *> RegionFirstMIs;
1172 RegionFirstMIs.reserve(Regions.size());
1174 RegionFirstMIs.push_back(
1181GCNScheduleDAGMILive::getRegionLiveOutMap()
const {
1182 assert(!Regions.empty());
1183 std::vector<MachineInstr *> RegionLastMIs;
1184 RegionLastMIs.reserve(Regions.size());
1195 IdxToInstruction.clear();
1198 IsLiveOut ? DAG->getRegionLiveOutMap() : DAG->getRegionLiveInMap();
1199 for (
unsigned I = 0;
I < DAG->Regions.size();
I++) {
1200 auto &[RegionBegin, RegionEnd] = DAG->Regions[
I];
1202 if (RegionBegin == RegionEnd)
1206 IdxToInstruction[
I] = RegionKey;
1214 LiveIns.resize(Regions.size());
1215 Pressure.resize(Regions.size());
1216 RegionsWithHighRP.resize(
static_cast<unsigned>(Regions.size()));
1217 RegionsWithExcessRP.resize(
static_cast<unsigned>(Regions.size()));
1218 RegionsWithIGLPInstrs.resize(
static_cast<unsigned>(Regions.size()));
1219 RegionsWithHighRP.reset();
1220 RegionsWithExcessRP.reset();
1221 RegionsWithIGLPInstrs.reset();
1226void GCNScheduleDAGMILive::runSchedStages() {
1227 LLVM_DEBUG(
dbgs() <<
"All regions recorded, starting actual scheduling.\n");
1230 if (!Regions.
empty()) {
1231 BBLiveInMap = getRegionLiveInMap();
1236#ifdef DUMP_MAX_REG_PRESSURE
1246 if (!Stage->initGCNSchedStage())
1249 for (
auto Region : Regions) {
1253 if (!Stage->initGCNRegion()) {
1254 Stage->advanceRegion();
1260 const unsigned RegionIdx = Stage->getRegionIdx();
1263 MRI, RegionLiveOuts.getLiveRegsForRegionIdx(RegionIdx));
1267 Stage->finalizeGCNRegion();
1268 Stage->advanceRegion();
1272 Stage->finalizeGCNSchedStage();
1275#ifdef DUMP_MAX_REG_PRESSURE
1288 OS <<
"Max Occupancy Initial Schedule";
1291 OS <<
"Instruction Rewriting Reschedule";
1294 OS <<
"Unclustered High Register Pressure Reschedule";
1297 OS <<
"Clustered Low Occupancy Reschedule";
1300 OS <<
"Pre-RA Rematerialize";
1303 OS <<
"Max ILP Initial Schedule";
1306 OS <<
"Max memory clause Initial Schedule";
1309 OS <<
"Live Interval RP Reschedule";
1329void RewriteMFMAFormStage::findReachingDefs(
1351 while (!Worklist.
empty()) {
1366 for (MachineBasicBlock *PredMBB : DefMBB->
predecessors()) {
1367 if (Visited.
insert(PredMBB).second)
1373void RewriteMFMAFormStage::findReachingUses(
1377 for (MachineOperand &UseMO :
1380 findReachingDefs(UseMO, LIS, ReachingDefIndexes);
1384 if (
any_of(ReachingDefIndexes, [DefIdx](SlotIndex RDIdx) {
1396 if (!
ST.hasGFX90AInsts() ||
MFI.getMinWavesPerEU() > 1)
1399 RegionsWithExcessArchVGPR.resize(
static_cast<unsigned>(
DAG.Regions.size()));
1400 RegionsWithExcessArchVGPR.reset();
1404 RegionsWithExcessArchVGPR[
Region] =
true;
1407 if (RegionsWithExcessArchVGPR.none())
1410 TII =
ST.getInstrInfo();
1411 SRI =
ST.getRegisterInfo();
1413 std::vector<std::pair<MachineInstr *, unsigned>> RewriteCands;
1417 if (!initHeuristics(RewriteCands, CopyForUse, CopyForDef))
1420 int64_t
Cost = getRewriteCost(RewriteCands, CopyForUse, CopyForDef);
1427 return rewrite(RewriteCands);
1437 if (
DAG.RegionsWithHighRP.none() &&
DAG.RegionsWithExcessRP.none())
1444 InitialOccupancy =
DAG.MinOccupancy;
1447 TempTargetOccupancy =
MFI.getMaxWavesPerEU() >
DAG.MinOccupancy
1448 ? InitialOccupancy + 1
1450 IsAnyRegionScheduled =
false;
1451 S.SGPRLimitBias =
S.HighRPSGPRBias;
1452 S.VGPRLimitBias =
S.HighRPVGPRBias;
1456 <<
"Retrying function scheduling without clustering. "
1457 "Aggressively try to reduce register pressure to achieve occupancy "
1458 << TempTargetOccupancy <<
".\n");
1473 if (
DAG.StartingOccupancy <=
DAG.MinOccupancy)
1477 dbgs() <<
"Retrying function scheduling with lowest recorded occupancy "
1478 <<
DAG.MinOccupancy <<
".\n");
1493 unsigned MaxSGPRs =
ST.getMaxNumSGPRs(
F);
1494 unsigned MaxVGPRs =
ST.getMaxNumVGPRs(
F);
1496 const unsigned VGPRBlockSize =
MFI.getDynamicVGPRBlockSize();
1497 bool HasVectorRegisterExcess =
false;
1499 if (
GCNRPTarget(MaxSGPRs, MaxVGPRs,
MF, RP).hasVectorRegisterExcess()) {
1500 HasVectorRegisterExcess =
true;
1504 if (HasVectorRegisterExcess ||
DAG.MinOccupancy >=
MFI.getMaxWavesPerEU()) {
1507 TargetOcc = std::nullopt;
1511 TargetOcc =
DAG.MinOccupancy + 1;
1512 MaxSGPRs =
ST.getMaxNumSGPRs(*TargetOcc,
false);
1513 MaxVGPRs =
ST.getMaxNumVGPRs(*TargetOcc, VGPRBlockSize);
1517 dbgs() <<
"In function ";
1518 MF.getFunction().printAsOperand(
dbgs(),
false);
1519 dbgs() <<
": rematerializing to ";
1521 dbgs() <<
"increase occupancy from " << *TargetOcc - 1 <<
'\n';
1523 dbgs() <<
"reduce spilling (minimum target occupancy is "
1524 <<
MFI.getMinWavesPerEU() <<
")\n";
1528 LiveOuts.reserve(
DAG.Regions.size());
1529 DAG.RegionLiveOuts.buildLiveRegMap();
1531 LiveOuts.push_back(
DAG.RegionLiveOuts.getLiveRegsForRegionIdx(
RegionIdx));
1533 Strategy = std::make_unique<GCNRematStrategy>(
MF,
DAG.Regions,
DAG.LiveIns,
1534 LiveOuts, *
DAG.LIS, *
DAG.MBFI);
1535 if (TargetOcc.has_value()) {
1542 Strategy->startRecordingRemats();
1545 RescheduleRegions.resize(
DAG.Regions.size());
1547 Strategy->rematerializeFor(MaxSGPRs, MaxVGPRs,
1548 !TargetOcc.has_value(),
1549 RescheduleRegions, &MaxPressure);
1550 if (RescheduleRegions.none())
1555 for (
unsigned RegionIdx : RescheduleRegions.set_bits()) {
1561 AchievedOcc =
MFI.getMaxWavesPerEU();
1563 AchievedOcc = std::min(AchievedOcc, RP.getOccupancy(
ST, VGPRBlockSize));
1566 dbgs() <<
"Retrying function scheduling with new min. occupancy of "
1567 << AchievedOcc <<
" from rematerializing (original was "
1568 <<
DAG.MinOccupancy;
1570 dbgs() <<
", target was " << *TargetOcc;
1574 DAG.setTargetOccupancy(getStageTargetOccupancy());
1585 S.SGPRLimitBias =
S.VGPRLimitBias = 0;
1586 if (
DAG.MinOccupancy > InitialOccupancy) {
1587 assert(IsAnyRegionScheduled);
1589 <<
" stage successfully increased occupancy to "
1590 <<
DAG.MinOccupancy <<
'\n');
1591 }
else if (!IsAnyRegionScheduled) {
1592 assert(
DAG.MinOccupancy == InitialOccupancy);
1594 <<
": No regions scheduled, min occupancy stays at "
1595 <<
DAG.MinOccupancy <<
", MFI occupancy stays at "
1596 <<
MFI.getOccupancy() <<
".\n");
1604 if (
DAG.begin() ==
DAG.end())
1611 unsigned NumRegionInstrs =
1612 static_cast<unsigned>(std::distance(
DAG.begin(),
DAG.end()));
1616 if (
DAG.begin() == std::prev(
DAG.end()))
1622 <<
"\n From: " << *
DAG.begin() <<
" To: ";
1624 else dbgs() <<
"End";
1625 dbgs() <<
" RegionInstrs: " << NumRegionInstrs <<
'\n');
1633 for (
auto &
I :
DAG) {
1646 dbgs() <<
"Pressure before scheduling:\nRegion live-ins:"
1648 <<
"Region live-in pressure: "
1652 S.HasHighPressure =
false;
1674 unsigned DynamicVGPRBlockSize =
DAG.MFI.getDynamicVGPRBlockSize();
1677 unsigned CurrentTargetOccupancy =
1678 IsAnyRegionScheduled ?
DAG.MinOccupancy : TempTargetOccupancy;
1680 (CurrentTargetOccupancy <= InitialOccupancy ||
1681 DAG.Pressure[
RegionIdx].getOccupancy(
ST, DynamicVGPRBlockSize) !=
1688 if (!IsAnyRegionScheduled && IsSchedulingThisRegion) {
1689 IsAnyRegionScheduled =
true;
1690 if (
MFI.getMaxWavesPerEU() >
DAG.MinOccupancy)
1691 DAG.setTargetOccupancy(TempTargetOccupancy);
1693 return IsSchedulingThisRegion;
1709 return !RevertAllRegions && RescheduleRegions[
RegionIdx] &&
1729 if (
S.HasHighPressure)
1750 if (
DAG.MinOccupancy < *TargetOcc) {
1752 <<
" cannot meet occupancy target, interrupting "
1753 "re-scheduling in all regions\n");
1754 RevertAllRegions =
true;
1765 unsigned DynamicVGPRBlockSize =
DAG.MFI.getDynamicVGPRBlockSize();
1767 bool UnifiedVGPRFile =
ST.hasGFX90AInsts();
1768 unsigned VectorCriticalLimit =
1769 UnifiedVGPRFile ?
S.UnifiedVGPRCriticalLimit :
S.VGPRCriticalLimit;
1773 PressureAfter.getVGPRNum(UnifiedVGPRFile) <= VectorCriticalLimit &&
1774 (!UnifiedVGPRFile ||
1784 unsigned TargetOccupancy = std::min(
1785 S.getTargetOccupancy(),
ST.getOccupancyWithWorkGroupSizes(
MF).second);
1786 unsigned WavesAfter = std::min(
1787 TargetOccupancy,
PressureAfter.getOccupancy(
ST, DynamicVGPRBlockSize));
1788 unsigned WavesBefore = std::min(
1790 LLVM_DEBUG(
dbgs() <<
"Occupancy before scheduling: " << WavesBefore
1791 <<
", after " << WavesAfter <<
".\n");
1797 unsigned NewOccupancy = std::max(WavesAfter, WavesBefore);
1801 if (WavesAfter < WavesBefore && WavesAfter <
DAG.MinOccupancy &&
1802 WavesAfter >=
MFI.getMinAllowedOccupancy()) {
1803 LLVM_DEBUG(
dbgs() <<
"Function is memory bound, allow occupancy drop up to "
1804 <<
MFI.getMinAllowedOccupancy() <<
" waves\n");
1805 NewOccupancy = WavesAfter;
1808 if (NewOccupancy <
DAG.MinOccupancy) {
1809 DAG.MinOccupancy = NewOccupancy;
1810 MFI.limitOccupancy(
DAG.MinOccupancy);
1812 <<
DAG.MinOccupancy <<
".\n");
1816 unsigned MaxVGPRs =
ST.getMaxNumVGPRs(
MF);
1819 unsigned MaxArchVGPRs = std::min(MaxVGPRs,
ST.getAddressableNumArchVGPRs());
1820 unsigned MaxSGPRs =
ST.getMaxNumSGPRs(
MF);
1844 unsigned ReadyCycle = CurrCycle;
1845 for (
auto &
D : SU.
Preds) {
1846 if (
D.isAssignedRegDep()) {
1849 unsigned DefReady = ReadyCycles[
DAG.getSUnit(
DefMI)->NodeNum];
1850 ReadyCycle = std::max(ReadyCycle, DefReady +
Latency);
1853 ReadyCycles[SU.
NodeNum] = ReadyCycle;
1860 std::pair<MachineInstr *, unsigned>
B)
const {
1861 return A.second <
B.second;
1867 if (ReadyCycles.empty())
1869 unsigned BBNum = ReadyCycles.begin()->first->getParent()->getNumber();
1870 dbgs() <<
"\n################## Schedule time ReadyCycles for MBB : " << BBNum
1871 <<
" ##################\n# Cycle #\t\t\tInstruction "
1875 for (
auto &
I : ReadyCycles) {
1876 if (
I.second > IPrev + 1)
1877 dbgs() <<
"****************************** BUBBLE OF " <<
I.second - IPrev
1878 <<
" CYCLES DETECTED ******************************\n\n";
1879 dbgs() <<
"[ " <<
I.second <<
" ] : " << *
I.first <<
"\n";
1892 unsigned SumBubbles = 0;
1894 unsigned CurrCycle = 0;
1895 for (
auto &SU : InputSchedule) {
1896 unsigned ReadyCycle =
1898 SumBubbles += ReadyCycle - CurrCycle;
1900 ReadyCyclesSorted.insert(std::make_pair(SU.getInstr(), ReadyCycle));
1902 CurrCycle = ++ReadyCycle;
1925 unsigned SumBubbles = 0;
1927 unsigned CurrCycle = 0;
1928 for (
auto &
MI :
DAG) {
1932 unsigned ReadyCycle =
1934 SumBubbles += ReadyCycle - CurrCycle;
1936 ReadyCyclesSorted.insert(std::make_pair(SU->
getInstr(), ReadyCycle));
1938 CurrCycle = ++ReadyCycle;
1955 if (WavesAfter <
DAG.MinOccupancy)
1959 if (
DAG.MFI.isDynamicVGPREnabled()) {
1962 DAG.MFI.getDynamicVGPRBlockSize());
1965 if (BlocksAfter > BlocksBefore)
2002 <<
"\n\t *** In shouldRevertScheduling ***\n"
2003 <<
" *********** BEFORE UnclusteredHighRPStage ***********\n");
2007 <<
"\n *********** AFTER UnclusteredHighRPStage ***********\n");
2009 unsigned OldMetric = MBefore.
getMetric();
2010 unsigned NewMetric = MAfter.
getMetric();
2011 unsigned WavesBefore = std::min(
2012 S.getTargetOccupancy(),
2019 LLVM_DEBUG(
dbgs() <<
"\tMetric before " << MBefore <<
"\tMetric after "
2020 << MAfter <<
"Profit: " << Profit <<
"\n");
2050 unsigned WavesAfter) {
2060 cl::desc(
"Percent increase of live interval RP over instant pressure to "
2061 "trigger rescheduling"),
2067 "Reduction factor (percent) for VGPR threshold during live interval RP "
2068 "reschedule stage"),
2072 "amdgpu-lirp-instant-lower-bound",
cl::Hidden,
2073 cl::desc(
"Lower bound (percent of the VGPR excess limit) on instant RP, "
2074 "below which a region is skipped"),
2084 if (!
S.VGPRThresholdPercent) {
2085 LLVM_DEBUG(
dbgs() <<
"LIRP: expected VGPRThresholdPercent to be enabled, "
2086 "not using live interval RP reschedule stage\n");
2094 unsigned InstantRP =
DAG.Pressure[
RegionIdx].getArchVGPRNum();
2095 auto [RegionBegin, RegionEnd] =
DAG.Regions[
RegionIdx];
2096 if (RegionBegin == RegionEnd)
2103 unsigned NewVGPRThresholdPercent =
2107 <<
", VGPRThresholdPercent: " <<
S.VGPRThresholdPercent
2108 <<
" -> " << NewVGPRThresholdPercent
2109 <<
", VGPRExcessLimit=" <<
S.VGPRExcessLimit
2110 <<
", VGPRCriticalLimit=" <<
S.VGPRCriticalLimit
2111 <<
", InstantRP=" << InstantRP <<
", LIRP=" << LIRP);
2113 bool DoRescheduling =
false;
2115 unsigned InstantRPLowerBound =
2117 if (LIRP >
S.VGPRExcessLimit) {
2118 LLVM_DEBUG(
dbgs() <<
" [LIRP exceeds the limit (" <<
S.VGPRExcessLimit
2119 <<
"), rescheduling]");
2120 DoRescheduling =
true;
2121 }
else if (LIRP > InstantRP && InstantRP > InstantRPLowerBound) {
2122 unsigned IncreasePercent = ((LIRP - InstantRP) * 100) / InstantRP;
2126 DoRescheduling =
true;
2132 SavedVGPRExcessLimit =
S.VGPRExcessLimit;
2133 SavedVGPRCriticalLimit =
S.VGPRCriticalLimit;
2134 SavedUnifiedVGPRCriticalLimit =
S.UnifiedVGPRCriticalLimit;
2135 SavedVGPRThresholdPercent =
S.VGPRThresholdPercent;
2136 S.VGPRThresholdPercent = NewVGPRThresholdPercent;
2144 S.VGPRExcessLimit = SavedVGPRExcessLimit;
2145 S.VGPRCriticalLimit = SavedVGPRCriticalLimit;
2146 S.UnifiedVGPRCriticalLimit = SavedUnifiedVGPRCriticalLimit;
2147 S.VGPRThresholdPercent = SavedVGPRThresholdPercent;
2154 LLVM_DEBUG(
dbgs() <<
"New pressure will result in more spilling.\n");
2166 "instruction number mismatch");
2167 if (MIOrder.
empty())
2180 if (MII != RegionEnd) {
2182 bool NonDebugReordered =
2183 !
MI->isDebugInstr() &&
2189 if (NonDebugReordered)
2190 DAG.LIS->handleMove(*
MI,
true);
2197 if (!
MI->isDebugInstr()) {
2199 SlotIndex PrevIdx =
DAG.LIS->getSlotIndexes()->getIndexBefore(*
MI);
2200 if (PrevIdx >= MIIdx)
2201 DAG.LIS->handleMove(*
MI,
true);
2205 if (
MI->isDebugInstr()) {
2212 DAG.ShouldTrackLaneMasks);
2231 if (RD->
getOpcode() == AMDGPU::AV_MOV_B32_IMM_PSEUDO ||
2232 RD->
getOpcode() == AMDGPU::AV_MOV_B64_IMM_PSEUDO)
2239bool RewriteMFMAFormStage::hasUseRequiringVGPR(
2242 for (SlotIndex RDIdx : Src2ReachingDefs) {
2243 const MachineInstr *RD =
DAG.LIS->getInstructionFromIndex(RDIdx);
2245 findReachingUses(RD,
DAG.LIS, ReachingUses);
2246 for (
const MachineOperand *UseMO : ReachingUses) {
2258void RewriteMFMAFormStage::resetRewriteCandsToVGPR(
2259 ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands) {
2260 for (
auto [
MI, OriginalOpcode] : RewriteCands) {
2263 DAG.MRI.getRegClass(
MI->getOperand(0).getReg());
2265 DAG.MRI.setRegClass(
MI->getOperand(0).getReg(), VDefRC);
2266 MI->setDesc(TII->get(OriginalOpcode));
2268 MachineOperand *
Src2 = TII->getNamedOperand(*
MI, AMDGPU::OpName::src2);
2277 DAG.MRI.setRegClass(
Src2->getReg(), VUseRC);
2281bool RewriteMFMAFormStage::isRewriteCandidate(
MachineInstr *
MI)
const {
2282 if (!
static_cast<const SIInstrInfo *
>(
DAG.TII)->isMAI(*
MI))
2287 Register DstReg =
MI->getOperand(0).getReg();
2288 for (
const MachineInstr &
UseMI :
DAG.MRI.use_nodbg_instructions(DstReg)) {
2295bool RewriteMFMAFormStage::initHeuristics(
2296 std::vector<std::pair<MachineInstr *, unsigned>> &RewriteCands,
2303 SmallPtrSet<MachineInstr *, 16> RewriteSet;
2304 DenseSet<Register> CandSrc2Regs;
2305 for (MachineBasicBlock &
MBB :
MF) {
2306 for (MachineInstr &
MI :
MBB) {
2307 if (!isRewriteCandidate(&
MI))
2310 MachineOperand *
Src2 = TII->getNamedOperand(
MI, AMDGPU::OpName::src2);
2311 if (Src2 &&
Src2->isReg())
2317 for (MachineBasicBlock &
MBB :
MF) {
2318 for (MachineInstr &
MI :
MBB) {
2319 if (!isRewriteCandidate(&
MI))
2323 assert(ReplacementOp != -1);
2325 RewriteCands.push_back({&
MI,
MI.getOpcode()});
2326 MI.setDesc(TII->get(ReplacementOp));
2328 MachineOperand *
Src2 = TII->getNamedOperand(
MI, AMDGPU::OpName::src2);
2329 if (
Src2->isReg()) {
2331 findReachingDefs(*Src2,
DAG.LIS, Src2ReachingDefs);
2335 bool Src2NeedsVGPR = hasUseRequiringVGPR(Src2ReachingDefs, RewriteSet);
2336 Src2NeedsVGPRCache[&
MI] = Src2NeedsVGPR;
2338 for (SlotIndex RDIdx : Src2ReachingDefs) {
2339 MachineInstr *RD =
DAG.LIS->getInstructionFromIndex(RDIdx);
2340 if (!Src2NeedsVGPR &&
2347 MachineOperand &Dst =
MI.getOperand(0);
2350 findReachingUses(&
MI,
DAG.LIS, DstReachingUses);
2352 for (MachineOperand *RUOp : DstReachingUses) {
2353 MachineInstr *UserMI = RUOp->getParent();
2355 if (TII->isMAI(*UserMI) && RewriteSet.
contains(UserMI))
2361 CopyForUse[UserMI->
getParent()].insert(RUOp->getReg());
2363 if (TII->isMAI(*UserMI))
2367 findReachingDefs(*RUOp,
DAG.LIS, DstUsesReachingDefs);
2369 for (SlotIndex RDIndex : DstUsesReachingDefs) {
2370 MachineInstr *RD =
DAG.LIS->getInstructionFromIndex(RDIndex);
2371 if (TII->isMAI(*RD))
2385 DAG.MRI.setRegClass(Dst.getReg(), ADefRC);
2386 if (
Src2->isReg()) {
2392 DAG.MRI.setRegClass(
Src2->getReg(), AUseRC);
2401int64_t RewriteMFMAFormStage::getRewriteCost(
2402 ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands,
2405 MachineBlockFrequencyInfo *MBFI =
DAG.MBFI;
2407 int64_t BestSpillCost = 0;
2411 std::pair<unsigned, unsigned> MaxVectorRegs =
2412 ST.getMaxNumVectorRegs(
MF.getFunction());
2413 unsigned ArchVGPRThreshold = MaxVectorRegs.first;
2414 unsigned AGPRThreshold = MaxVectorRegs.second;
2415 unsigned CombinedThreshold =
ST.getMaxNumVGPRs(
MF);
2418 if (!RegionsWithExcessArchVGPR[Region])
2423 MF, ArchVGPRThreshold, AGPRThreshold, CombinedThreshold);
2431 MF, ArchVGPRThreshold, AGPRThreshold, CombinedThreshold);
2437 bool RelativeFreqIsDenom = EntryFreq > BlockFreq;
2438 uint64_t RelativeFreq = EntryFreq && BlockFreq
2439 ? (RelativeFreqIsDenom ? EntryFreq / BlockFreq
2440 : BlockFreq / EntryFreq)
2445 int64_t SpillCost = ((int)SpillCostAfter - (int)SpillCostBefore) * 2;
2448 if (RelativeFreqIsDenom)
2449 SpillCost /= (int64_t)RelativeFreq;
2451 SpillCost *= (int64_t)RelativeFreq;
2454 if (SpillCost > 0) {
2455 resetRewriteCandsToVGPR(RewriteCands);
2459 if (SpillCost < BestSpillCost)
2460 BestSpillCost = SpillCost;
2465 Cost = BestSpillCost;
2468 unsigned CopyCost = 0;
2472 for (MachineInstr *
DefMI : CopyForDef) {
2480 CopyCost +=
static_cast<unsigned>(RC->
getCopyCost() * DefFreq);
2484 for (
auto &[UseBlock, UseRegs] : CopyForUse) {
2490 CopyCost +=
static_cast<unsigned>(RC->
getCopyCost() * UseFreq);
2498 resetRewriteCandsToVGPR(RewriteCands);
2500 return Cost + CopyCost;
2503bool RewriteMFMAFormStage::rewrite(
2504 ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands) {
2505 DenseMap<MachineInstr *, unsigned> FirstMIToRegion;
2506 DenseMap<MachineInstr *, unsigned> LastMIToRegion;
2514 if (
Entry.second !=
Entry.first->getParent()->end())
2557 DenseSet<Register> RewriteRegs;
2560 DenseMap<Register, Register> RedefMap;
2562 DenseMap<Register, DenseSet<MachineOperand *>>
ReplaceMap;
2564 DenseMap<Register, SmallPtrSet<MachineInstr *, 8>> ReachingDefCopyMap;
2567 DenseMap<unsigned, DenseMap<Register, SmallPtrSet<MachineOperand *, 8>>>
2572 SmallPtrSet<MachineInstr *, 16> RewriteCandsSet;
2573 DenseSet<Register> RewriteSrc2Regs;
2574 for (
auto &[
MI, OriginalOpcode] : RewriteCands) {
2576 MachineOperand *
Src2 = TII->getNamedOperand(*
MI, AMDGPU::OpName::src2);
2577 if (Src2 &&
Src2->isReg())
2581 for (
auto &[
MI, OriginalOpcode] : RewriteCands) {
2583 if (ReplacementOp == -1)
2585 MI->setDesc(TII->get(ReplacementOp));
2588 MachineOperand *
Src2 = TII->getNamedOperand(*
MI, AMDGPU::OpName::src2);
2589 if (
Src2->isReg()) {
2596 findReachingDefs(*Src2,
DAG.LIS, Src2ReachingDefs);
2597 SmallSetVector<MachineInstr *, 8> Src2DefsReplace;
2601 bool Src2NeedsVGPR = Src2NeedsVGPRCache.lookup(
MI);
2603 for (SlotIndex RDIndex : Src2ReachingDefs) {
2604 MachineInstr *RD =
DAG.LIS->getInstructionFromIndex(RDIndex);
2605 if (!Src2NeedsVGPR &&
2609 Src2DefsReplace.
insert(RD);
2612 if (!Src2DefsReplace.
empty()) {
2613 auto RI = RedefMap.
find(Src2Reg);
2614 if (RI != RedefMap.
end()) {
2615 MappedReg = RI->second;
2620 SRI->getEquivalentVGPRClass(Src2RC);
2623 MappedReg =
DAG.MRI.createVirtualRegister(VGPRRC);
2624 RedefMap[Src2Reg] = MappedReg;
2629 for (MachineInstr *RD : Src2DefsReplace) {
2631 if (ReachingDefCopyMap[Src2Reg].insert(RD).second) {
2632 MachineInstrBuilder VGPRCopy =
2635 .
addDef(MappedReg, {}, 0)
2636 .addUse(Src2Reg, {}, 0);
2637 DAG.LIS->InsertMachineInstrInMaps(*VGPRCopy);
2642 unsigned UpdateRegion = LastMIToRegion[RD];
2643 DAG.Regions[UpdateRegion].second = VGPRCopy;
2644 LastMIToRegion.
erase(RD);
2651 RewriteRegs.
insert(Src2Reg);
2661 MachineOperand *Dst = &
MI->getOperand(0);
2670 SmallVector<MachineInstr *, 8> DstUseDefsReplace;
2672 findReachingUses(
MI,
DAG.LIS, DstReachingUses);
2674 for (MachineOperand *RUOp : DstReachingUses) {
2675 MachineInstr *UserMI = RUOp->
getParent();
2677 if (TII->isMAI(*UserMI) && RewriteCandsSet.
contains(UserMI))
2681 if (
find(DstReachingUseCopies, RUOp) == DstReachingUseCopies.
end())
2685 if (TII->isMAI(*UserMI))
2689 findReachingDefs(*RUOp,
DAG.LIS, DstUsesReachingDefs);
2691 for (SlotIndex RDIndex : DstUsesReachingDefs) {
2692 MachineInstr *RD =
DAG.LIS->getInstructionFromIndex(RDIndex);
2693 if (TII->isMAI(*RD))
2698 if (
find(DstUseDefsReplace, RD) == DstUseDefsReplace.
end())
2703 if (!DstUseDefsReplace.
empty()) {
2704 auto RI = RedefMap.
find(DstReg);
2705 if (RI != RedefMap.
end()) {
2706 MappedReg = RI->second;
2713 MappedReg =
DAG.MRI.createVirtualRegister(VGPRRC);
2714 RedefMap[DstReg] = MappedReg;
2719 for (MachineInstr *RD : DstUseDefsReplace) {
2721 if (ReachingDefCopyMap[DstReg].insert(RD).second) {
2722 MachineInstrBuilder VGPRCopy =
2725 .
addDef(MappedReg, {}, 0)
2726 .addUse(DstReg, {}, 0);
2727 DAG.LIS->InsertMachineInstrInMaps(*VGPRCopy);
2731 auto LMI = LastMIToRegion.
find(RD);
2732 if (LMI != LastMIToRegion.
end()) {
2733 unsigned UpdateRegion = LMI->second;
2734 DAG.Regions[UpdateRegion].second = VGPRCopy;
2735 LastMIToRegion.
erase(RD);
2741 DenseSet<MachineOperand *> &DstRegSet =
ReplaceMap[DstReg];
2744 MachineInstr *EarliestSameBlockUse =
nullptr;
2745 for (MachineOperand *RU : DstReachingUseCopies) {
2746 MachineBasicBlock *RUBlock = RU->getParent()->getParent();
2749 if (RUBlock !=
MI->getParent()) {
2755 if (!SameBlockCopyReg.
isValid()) {
2758 SameBlockCopyReg =
DAG.MRI.createVirtualRegister(VGPRRC);
2762 MachineInstr *UseInst = RU->getParent();
2763 if (!EarliestSameBlockUse ||
2765 DAG.LIS->getInstructionIndex(*UseInst),
2766 DAG.LIS->getInstructionIndex(*EarliestSameBlockUse)))
2767 EarliestSameBlockUse = UseInst;
2768 RU->setReg(SameBlockCopyReg);
2772 if (SameBlockCopyReg.
isValid()) {
2773 MachineInstrBuilder VGPRCopy =
2776 TII->get(TargetOpcode::COPY), SameBlockCopyReg)
2778 DAG.LIS->InsertMachineInstrInMaps(*VGPRCopy);
2783 RewriteRegs.
insert(DstReg);
2793 std::pair<unsigned, DenseMap<Register, SmallPtrSet<MachineOperand *, 8>>>;
2794 for (RUBType RUBlockEntry : ReachingUseTracker) {
2795 using RUDType = std::pair<Register, SmallPtrSet<MachineOperand *, 8>>;
2796 for (RUDType RUDst : RUBlockEntry.second) {
2797 MachineOperand *OpBegin = *RUDst.second.begin();
2798 SlotIndex InstPt =
DAG.LIS->getInstructionIndex(*OpBegin->
getParent());
2801 for (MachineOperand *User : RUDst.second) {
2802 SlotIndex NewInstPt =
DAG.LIS->getInstructionIndex(*
User->getParent());
2809 Register NewUseReg =
DAG.MRI.createVirtualRegister(VGPRRC);
2810 MachineInstr *UseInst =
DAG.LIS->getInstructionFromIndex(InstPt);
2812 MachineInstrBuilder VGPRCopy =
2815 .
addDef(NewUseReg, {}, 0)
2816 .addUse(RUDst.first, {}, 0);
2817 DAG.LIS->InsertMachineInstrInMaps(*VGPRCopy);
2821 auto FI = FirstMIToRegion.
find(UseInst);
2822 if (FI != FirstMIToRegion.
end()) {
2823 unsigned UpdateRegion = FI->second;
2824 DAG.Regions[UpdateRegion].first = VGPRCopy;
2825 FirstMIToRegion.
erase(UseInst);
2829 for (MachineOperand *User : RUDst.second) {
2830 User->setReg(NewUseReg);
2841 for (std::pair<Register, Register> NewDef : RedefMap) {
2846 for (MachineOperand *ReplaceOp :
ReplaceMap[OldReg])
2847 ReplaceOp->setReg(NewReg);
2851 for (
Register RewriteReg : RewriteRegs) {
2852 Register RegToRewrite = RewriteReg;
2855 auto RI = RedefMap.find(RewriteReg);
2856 if (RI != RedefMap.end())
2857 RegToRewrite = RI->second;
2862 DAG.MRI.setRegClass(RegToRewrite, AGPRRC);
2866 DAG.LIS->reanalyze(
DAG.MF);
2868 RegionPressureMap LiveInUpdater(&
DAG,
false);
2869 LiveInUpdater.buildLiveRegMap();
2872 DAG.LiveIns[Region] = LiveInUpdater.getLiveRegsForRegionIdx(Region);
2879unsigned PreRARematStage::getStageTargetOccupancy()
const {
2880 return TargetOcc ? *TargetOcc :
MFI.getMinWavesPerEU();
2892 if (
DAG.MinOccupancy >= *TargetOcc)
2896 for (
const auto &[
RegionIdx, OrigMIOrder, MaxPressure] : RegionReverts) {
2906 if (AchievedOcc >= *TargetOcc) {
2907 DAG.setTargetOccupancy(AchievedOcc);
2912 DAG.setTargetOccupancy(*TargetOcc - 1);
2913 Strategy->rollbackRecordedRemats();
2914 for (
unsigned RegionIdx : RescheduleRegions.set_bits()) {
2919#ifdef EXPENSIVE_CHECKS
2928void GCNScheduleDAGMILive::setTargetOccupancy(
unsigned TargetOccupancy) {
2929 MinOccupancy = TargetOccupancy;
2930 if (MFI.getOccupancy() < TargetOccupancy)
2931 MFI.increaseOccupancy(
MF, MinOccupancy);
2933 MFI.limitOccupancy(MinOccupancy);
2950 if (HasIGLPInstrs) {
2951 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 cl::opt< bool > GCNTrackers("amdgpu-use-amdgpu-trackers", cl::Hidden, cl::desc("Use the AMDGPU specific RPTrackers during scheduling"), cl::init(false))
static cl::opt< bool > DisableClusteredLowOccupancy("amdgpu-disable-clustered-low-occupancy-reschedule", cl::Hidden, cl::desc("Disable clustered low occupancy " "rescheduling for ILP scheduling stage."), cl::init(false))
static MachineInstr * getLastMIForRegion(MachineBasicBlock::iterator RegionBegin, MachineBasicBlock::iterator RegionEnd)
static bool shouldCheckPending(SchedBoundary &Zone, const TargetSchedModel *SchedModel)
static cl::opt< bool > EnableLiveIntervalRPReschedule("amdgpu-lirp-reschedule", cl::Hidden, cl::desc("Enable live interval RP reschedule stage"), cl::init(true))
static cl::opt< bool > RelaxedOcc("amdgpu-schedule-relaxed-occupancy", cl::Hidden, cl::desc("Relax occupancy targets for kernels which are memory " "bound (amdgpu-membound-threshold), or " "Wave Limited (amdgpu-limit-wave-threshold)."), cl::init(false))
static cl::opt< bool > DisableUnclusterHighRP("amdgpu-disable-unclustered-high-rp-reschedule", cl::Hidden, cl::desc("Disable unclustered high register pressure " "reduction scheduling stage."), cl::init(false))
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 cl::opt< bool > PrintMaxRPRegUsageAfterScheduler("amdgpu-print-max-reg-pressure-regusage-after-scheduler", cl::Hidden, cl::desc("Print a list of live registers along with their def/uses at the " "point of maximum register pressure after scheduling."), cl::init(false))
static bool hasIGLPInstrs(ScheduleDAGInstrs *DAG)
static cl::opt< bool > DisableRewriteMFMAFormSchedStage("amdgpu-disable-rewrite-mfma-form-sched-stage", cl::Hidden, cl::desc("Disable rewrite mfma rewrite scheduling stage"), cl::init(true))
static bool canUsePressureDiffs(const SUnit &SU)
Checks whether SU can use the cached DAG pressure diffs to compute the current register pressure.
static cl::opt< unsigned > LiveIntervalRPVGPRReduction("amdgpu-lirp-vgpr-reduction", cl::Hidden, cl::desc("Reduction factor (percent) for VGPR threshold during live interval RP " "reschedule stage"), cl::init(90))
static cl::opt< unsigned > PendingQueueLimit("amdgpu-scheduler-pending-queue-limit", cl::Hidden, cl::desc("Max (Available+Pending) size to inspect pending queue (0 disables)"), cl::init(256))
static cl::opt< bool > PrintMaxRPRegUsageBeforeScheduler("amdgpu-print-max-reg-pressure-regusage-before-scheduler", cl::Hidden, cl::desc("Print a list of live registers along with their def/uses at the " "point of maximum register pressure before scheduling."), cl::init(false))
static cl::opt< unsigned > LiveIntervalRPInstantLowerBound("amdgpu-lirp-instant-lower-bound", cl::Hidden, cl::desc("Lower bound (percent of the VGPR excess limit) on instant RP, " "below which a region is skipped"), cl::init(10))
static cl::opt< unsigned > ScheduleMetricBias("amdgpu-schedule-metric-bias", cl::Hidden, cl::desc("Sets the bias which adds weight to occupancy vs latency. Set it to " "100 to chase the occupancy only."), cl::init(10))
static cl::opt< unsigned > LiveIntervalRPThreshold("amdgpu-lirp-threshold", cl::Hidden, cl::desc("Percent increase of live interval RP over instant pressure to " "trigger rescheduling"), cl::init(10))
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
static constexpr std::pair< StringLiteral, StringLiteral > ReplaceMap[]
Promote Memory to Register
MachineRegisterInfo & MRI
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
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
unsigned VGPRCriticalLimit
void schedNode(SUnit *SU, bool IsTopNode) override
Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an instruction and updated scheduled/rem...
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()
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.
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...
LLVM_ABI void advance()
Advance across the current instruction.
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
unsigned getArchVGPRNum() const
unsigned getAGPRNum() const
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)