37#define DEBUG_TYPE "machine-scheduler"
42 "amdgpu-disable-unclustered-high-rp-reschedule",
cl::Hidden,
43 cl::desc(
"Disable unclustered high register pressure "
44 "reduction scheduling stage."),
48 "amdgpu-disable-clustered-low-occupancy-reschedule",
cl::Hidden,
49 cl::desc(
"Disable clustered low occupancy "
50 "rescheduling for ILP scheduling stage."),
56 "Sets the bias which adds weight to occupancy vs latency. Set it to "
57 "100 to chase the occupancy only."),
62 cl::desc(
"Relax occupancy targets for kernels which are memory "
63 "bound (amdgpu-membound-threshold), or "
64 "Wave Limited (amdgpu-limit-wave-threshold)."),
69 cl::desc(
"Use the AMDGPU specific RPTrackers during scheduling"),
87 Context->RegClassInfo->getNumAllocatableRegs(&AMDGPU::SGPR_32RegClass);
89 Context->RegClassInfo->getNumAllocatableRegs(&AMDGPU::VGPR_32RegClass);
111 "VGPRCriticalLimit calculation method.\n");
115 unsigned Addressable =
118 VGPRBudget = std::max(VGPRBudget, Granule);
157 if (!
Op.isReg() ||
Op.isImplicit())
159 if (
Op.getReg().isPhysical() ||
160 (
Op.isDef() &&
Op.getSubReg() != AMDGPU::NoSubRegister))
168 std::vector<unsigned> &Pressure, std::vector<unsigned> &MaxPressure,
183 Pressure.resize(4, 0);
194 Pressure[AMDGPU::RegisterPressureSets::SReg_32] = NewPressure.
getSGPRNum();
195 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] =
197 Pressure[AMDGPU::RegisterPressureSets::AGPR_32] = NewPressure.
getAGPRNum();
204 unsigned SGPRPressure,
205 unsigned VGPRPressure,
bool IsBottomUp) {
209 if (!
DAG->isTrackingPressure())
232 Pressure[AMDGPU::RegisterPressureSets::SReg_32] = SGPRPressure;
233 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] = VGPRPressure;
235 for (
const auto &Diff :
DAG->getPressureDiff(SU)) {
241 (IsBottomUp ? Diff.getUnitInc() : -Diff.getUnitInc());
244#ifdef EXPENSIVE_CHECKS
245 std::vector<unsigned> CheckPressure, CheckMaxPressure;
248 if (
Pressure[AMDGPU::RegisterPressureSets::SReg_32] !=
249 CheckPressure[AMDGPU::RegisterPressureSets::SReg_32] ||
250 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] !=
251 CheckPressure[AMDGPU::RegisterPressureSets::VGPR_32]) {
252 errs() <<
"Register Pressure is inaccurate when calculated through "
254 <<
"SGPR got " <<
Pressure[AMDGPU::RegisterPressureSets::SReg_32]
256 << CheckPressure[AMDGPU::RegisterPressureSets::SReg_32] <<
"\n"
257 <<
"VGPR got " <<
Pressure[AMDGPU::RegisterPressureSets::VGPR_32]
259 << CheckPressure[AMDGPU::RegisterPressureSets::VGPR_32] <<
"\n";
265 unsigned NewSGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::SReg_32];
266 unsigned NewVGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::VGPR_32];
276 const unsigned MaxVGPRPressureInc = 16;
277 bool ShouldTrackVGPRs = VGPRPressure + MaxVGPRPressureInc >=
VGPRExcessLimit;
278 bool ShouldTrackSGPRs = !ShouldTrackVGPRs && SGPRPressure >=
SGPRExcessLimit;
309 if (SGPRDelta >= 0 || VGPRDelta >= 0) {
311 if (SGPRDelta > VGPRDelta) {
332 unsigned SGPRPressure = 0;
333 unsigned VGPRPressure = 0;
334 if (
DAG->isTrackingPressure()) {
336 SGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::SReg_32];
337 VGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::VGPR_32];
342 SGPRPressure =
T->getPressure().getSGPRNum();
343 VGPRPressure =
T->getPressure().getArchVGPRNum();
347 for (
SUnit *SU : Q) {
351 VGPRPressure, IsBottomUp);
370 if (
SUnit *SU =
Bot.pickOnlyChoice()) {
374 if (
SUnit *SU =
Top.pickOnlyChoice()) {
404 "Last pick result should correspond to re-picking right now");
426 "Last pick result should correspond to re-picking right now");
442 IsTopNode = Cand.AtTop;
449 if (
DAG->top() ==
DAG->bottom()) {
451 Bot.Available.empty() &&
Bot.Pending.empty() &&
"ReadyQ garbage");
457 SU =
Top.pickOnlyChoice();
468 SU =
Bot.pickOnlyChoice();
553 if (
DAG->isTrackingPressure() &&
563 bool SameBoundary = Zone !=
nullptr;
598 bool CandIsClusterSucc =
600 bool TryCandIsClusterSucc =
602 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
607 if (
DAG->isTrackingPressure() &&
613 if (
DAG->isTrackingPressure() &&
659 if (
DAG->isTrackingPressure()) {
675 bool CandIsClusterSucc =
677 bool TryCandIsClusterSucc =
679 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
688 bool SameBoundary = Zone !=
nullptr;
705 if (TryMayLoad || CandMayLoad) {
706 bool TryLongLatency =
708 bool CandLongLatency =
712 Zone->
isTop() ? CandLongLatency : TryLongLatency, TryCand,
730 if (
DAG->isTrackingPressure() &&
749 !
Rem.IsAcyclicLatencyLimited &&
tryLatency(TryCand, Cand, *Zone))
767 StartingOccupancy(MFI.getOccupancy()), MinOccupancy(StartingOccupancy),
768 RegionLiveOuts(this,
true) {
774 LLVM_DEBUG(
dbgs() <<
"Starting occupancy is " << StartingOccupancy <<
".\n");
776 MinOccupancy = std::min(MFI.getMinAllowedOccupancy(), StartingOccupancy);
777 if (MinOccupancy != StartingOccupancy)
778 LLVM_DEBUG(
dbgs() <<
"Allowing Occupancy drops to " << MinOccupancy
783std::unique_ptr<GCNSchedStage>
785 switch (SchedStageID) {
787 return std::make_unique<OccInitialScheduleStage>(SchedStageID, *
this);
789 return std::make_unique<UnclusteredHighRPStage>(SchedStageID, *
this);
791 return std::make_unique<ClusteredLowOccStage>(SchedStageID, *
this);
793 return std::make_unique<PreRARematStage>(SchedStageID, *
this);
795 return std::make_unique<ILPInitialScheduleStage>(SchedStageID, *
this);
797 return std::make_unique<MemoryClauseInitialScheduleStage>(SchedStageID,
811GCNScheduleDAGMILive::getRealRegPressure(
unsigned RegionIdx)
const {
814 &LiveIns[RegionIdx]);
820 auto REnd = RegionEnd == RegionBegin->getParent()->end()
821 ? std::prev(RegionEnd)
826void GCNScheduleDAGMILive::computeBlockPressure(
unsigned RegionIdx,
838 const MachineBasicBlock *OnlySucc =
nullptr;
841 if (!Candidate->empty() && Candidate->pred_size() == 1) {
842 SlotIndexes *Ind =
LIS->getSlotIndexes();
844 OnlySucc = Candidate;
849 size_t CurRegion = RegionIdx;
850 for (
size_t E = Regions.size(); CurRegion !=
E; ++CurRegion)
851 if (Regions[CurRegion].first->getParent() !=
MBB)
856 auto LiveInIt = MBBLiveIns.find(
MBB);
857 auto &Rgn = Regions[CurRegion];
859 if (LiveInIt != MBBLiveIns.end()) {
860 auto LiveIn = std::move(LiveInIt->second);
862 MBBLiveIns.erase(LiveInIt);
865 auto LRS = BBLiveInMap.lookup(NonDbgMI);
866#ifdef EXPENSIVE_CHECKS
875 if (Regions[CurRegion].first ==
I || NonDbgMI ==
I) {
876 LiveIns[CurRegion] =
RPTracker.getLiveRegs();
880 if (Regions[CurRegion].second ==
I) {
881 Pressure[CurRegion] =
RPTracker.moveMaxPressure();
882 if (CurRegion-- == RegionIdx)
884 auto &Rgn = Regions[CurRegion];
897 MBBLiveIns[OnlySucc] =
RPTracker.moveLiveRegs();
902GCNScheduleDAGMILive::getRegionLiveInMap()
const {
904 std::vector<MachineInstr *> RegionFirstMIs;
905 RegionFirstMIs.reserve(Regions.size());
907 RegionFirstMIs.push_back(
914GCNScheduleDAGMILive::getRegionLiveOutMap()
const {
916 std::vector<MachineInstr *> RegionLastMIs;
917 RegionLastMIs.reserve(Regions.size());
925 IdxToInstruction.clear();
928 IsLiveOut ? DAG->getRegionLiveOutMap() : DAG->getRegionLiveInMap();
929 for (
unsigned I = 0;
I < DAG->Regions.size();
I++) {
933 : &*DAG->Regions[
I].first;
934 IdxToInstruction[
I] = RegionKey;
942 LiveIns.resize(Regions.size());
943 Pressure.resize(Regions.size());
944 RegionsWithHighRP.resize(Regions.size());
945 RegionsWithExcessRP.resize(Regions.size());
946 RegionsWithIGLPInstrs.resize(Regions.size());
947 RegionsWithHighRP.reset();
948 RegionsWithExcessRP.reset();
949 RegionsWithIGLPInstrs.reset();
954void GCNScheduleDAGMILive::runSchedStages() {
955 LLVM_DEBUG(
dbgs() <<
"All regions recorded, starting actual scheduling.\n");
957 if (!Regions.
empty()) {
958 BBLiveInMap = getRegionLiveInMap();
966 if (!Stage->initGCNSchedStage())
969 for (
auto Region : Regions) {
973 if (!Stage->initGCNRegion()) {
974 Stage->advanceRegion();
983 &LiveIns[Stage->getRegionIdx()];
985 reinterpret_cast<GCNRPTracker *
>(DownwardTracker)
986 ->reset(
MRI, *RegionLiveIns);
987 reinterpret_cast<GCNRPTracker *
>(UpwardTracker)
988 ->reset(
MRI, RegionLiveOuts.getLiveRegsForRegionIdx(
989 Stage->getRegionIdx()));
993 Stage->finalizeGCNRegion();
996 Stage->finalizeGCNSchedStage();
1004 OS <<
"Max Occupancy Initial Schedule";
1007 OS <<
"Unclustered High Register Pressure Reschedule";
1010 OS <<
"Clustered Low Occupancy Reschedule";
1013 OS <<
"Pre-RA Rematerialize";
1016 OS <<
"Max ILP Initial Schedule";
1019 OS <<
"Max memory clause Initial Schedule";
1046 if (
DAG.RegionsWithHighRP.none() &&
DAG.RegionsWithExcessRP.none())
1053 InitialOccupancy =
DAG.MinOccupancy;
1056 S.SGPRLimitBias =
S.HighRPSGPRBias;
1057 S.VGPRLimitBias =
S.HighRPVGPRBias;
1058 if (
MFI.getMaxWavesPerEU() >
DAG.MinOccupancy)
1059 MFI.increaseOccupancy(
MF, ++
DAG.MinOccupancy);
1063 <<
"Retrying function scheduling without clustering. "
1064 "Aggressivly try to reduce register pressure to achieve occupancy "
1065 <<
DAG.MinOccupancy <<
".\n");
1080 if (
DAG.StartingOccupancy <=
DAG.MinOccupancy)
1084 dbgs() <<
"Retrying function scheduling with lowest recorded occupancy "
1085 <<
DAG.MinOccupancy <<
".\n");
1090#define REMAT_PREFIX "[PreRARemat] "
1091#define REMAT_DEBUG(X) LLVM_DEBUG(dbgs() << REMAT_PREFIX; X;)
1104 const unsigned NumRegions =
DAG.Regions.size();
1105 RegionBB.reserve(NumRegions);
1106 for (
unsigned I = 0;
I < NumRegions; ++
I) {
1109 MIRegion.insert({&*
MI,
I});
1113 if (!canIncreaseOccupancyOrReduceSpill())
1119 DAG.RegionLiveOuts.buildLiveRegMap();
1121 dbgs() <<
"Retrying function scheduling with new min. occupancy of "
1122 << AchievedOcc <<
" from rematerializing (original was "
1123 <<
DAG.MinOccupancy;
1125 dbgs() <<
", target was " << *TargetOcc;
1129 if (AchievedOcc >
DAG.MinOccupancy) {
1130 DAG.MinOccupancy = AchievedOcc;
1132 MFI.increaseOccupancy(
MF,
DAG.MinOccupancy);
1144 S.SGPRLimitBias =
S.VGPRLimitBias = 0;
1145 if (
DAG.MinOccupancy > InitialOccupancy) {
1147 <<
" stage successfully increased occupancy to "
1148 <<
DAG.MinOccupancy <<
'\n');
1159 unsigned NumRegionInstrs = std::distance(
DAG.begin(),
DAG.end());
1163 if (
DAG.begin() ==
DAG.end() ||
DAG.begin() == std::prev(
DAG.end()))
1169 <<
"\n From: " << *
DAG.begin() <<
" To: ";
1171 else dbgs() <<
"End";
1172 dbgs() <<
" RegionInstrs: " << NumRegionInstrs <<
'\n');
1180 for (
auto &
I :
DAG) {
1193 dbgs() <<
"Pressure before scheduling:\nRegion live-ins:"
1195 <<
"Region live-in pressure: "
1199 S.HasHighPressure =
false;
1221 unsigned DynamicVGPRBlockSize =
DAG.MFI.getDynamicVGPRBlockSize();
1223 (
DAG.MinOccupancy <= InitialOccupancy ||
1224 DAG.Pressure[
RegionIdx].getOccupancy(
ST, DynamicVGPRBlockSize) !=
1263 if (
S.HasHighPressure)
1285 unsigned DynamicVGPRBlockSize =
DAG.MFI.getDynamicVGPRBlockSize();
1296 unsigned TargetOccupancy = std::min(
1297 S.getTargetOccupancy(),
ST.getOccupancyWithWorkGroupSizes(
MF).second);
1298 unsigned WavesAfter = std::min(
1299 TargetOccupancy,
PressureAfter.getOccupancy(
ST, DynamicVGPRBlockSize));
1300 unsigned WavesBefore = std::min(
1302 LLVM_DEBUG(
dbgs() <<
"Occupancy before scheduling: " << WavesBefore
1303 <<
", after " << WavesAfter <<
".\n");
1309 unsigned NewOccupancy = std::max(WavesAfter, WavesBefore);
1313 if (WavesAfter < WavesBefore && WavesAfter <
DAG.MinOccupancy &&
1314 WavesAfter >=
MFI.getMinAllowedOccupancy()) {
1315 LLVM_DEBUG(
dbgs() <<
"Function is memory bound, allow occupancy drop up to "
1316 <<
MFI.getMinAllowedOccupancy() <<
" waves\n");
1317 NewOccupancy = WavesAfter;
1320 if (NewOccupancy <
DAG.MinOccupancy) {
1321 DAG.MinOccupancy = NewOccupancy;
1322 MFI.limitOccupancy(
DAG.MinOccupancy);
1324 <<
DAG.MinOccupancy <<
".\n");
1328 unsigned MaxVGPRs =
ST.getMaxNumVGPRs(
MF);
1331 unsigned MaxArchVGPRs = std::min(MaxVGPRs,
ST.getAddressableNumArchVGPRs());
1332 unsigned MaxSGPRs =
ST.getMaxNumSGPRs(
MF);
1354 unsigned ReadyCycle = CurrCycle;
1355 for (
auto &
D : SU.
Preds) {
1356 if (
D.isAssignedRegDep()) {
1359 unsigned DefReady = ReadyCycles[
DAG.getSUnit(
DefMI)->NodeNum];
1360 ReadyCycle = std::max(ReadyCycle, DefReady +
Latency);
1363 ReadyCycles[SU.
NodeNum] = ReadyCycle;
1370 std::pair<MachineInstr *, unsigned>
B)
const {
1371 return A.second <
B.second;
1377 if (ReadyCycles.empty())
1379 unsigned BBNum = ReadyCycles.begin()->first->getParent()->getNumber();
1380 dbgs() <<
"\n################## Schedule time ReadyCycles for MBB : " << BBNum
1381 <<
" ##################\n# Cycle #\t\t\tInstruction "
1385 for (
auto &
I : ReadyCycles) {
1386 if (
I.second > IPrev + 1)
1387 dbgs() <<
"****************************** BUBBLE OF " <<
I.second - IPrev
1388 <<
" CYCLES DETECTED ******************************\n\n";
1389 dbgs() <<
"[ " <<
I.second <<
" ] : " << *
I.first <<
"\n";
1402 unsigned SumBubbles = 0;
1404 unsigned CurrCycle = 0;
1405 for (
auto &SU : InputSchedule) {
1406 unsigned ReadyCycle =
1408 SumBubbles += ReadyCycle - CurrCycle;
1410 ReadyCyclesSorted.insert(std::make_pair(SU.getInstr(), ReadyCycle));
1412 CurrCycle = ++ReadyCycle;
1435 unsigned SumBubbles = 0;
1437 unsigned CurrCycle = 0;
1438 for (
auto &
MI :
DAG) {
1442 unsigned ReadyCycle =
1444 SumBubbles += ReadyCycle - CurrCycle;
1446 ReadyCyclesSorted.insert(std::make_pair(SU->
getInstr(), ReadyCycle));
1448 CurrCycle = ++ReadyCycle;
1465 if (WavesAfter <
DAG.MinOccupancy)
1469 if (
DAG.MFI.isDynamicVGPREnabled()) {
1471 &
ST,
DAG.MFI.getDynamicVGPRBlockSize(),
1474 &
ST,
DAG.MFI.getDynamicVGPRBlockSize(),
1476 if (BlocksAfter > BlocksBefore)
1513 <<
"\n\t *** In shouldRevertScheduling ***\n"
1514 <<
" *********** BEFORE UnclusteredHighRPStage ***********\n");
1518 <<
"\n *********** AFTER UnclusteredHighRPStage ***********\n");
1520 unsigned OldMetric = MBefore.
getMetric();
1521 unsigned NewMetric = MAfter.
getMetric();
1522 unsigned WavesBefore = std::min(
1523 S.getTargetOccupancy(),
1530 LLVM_DEBUG(
dbgs() <<
"\tMetric before " << MBefore <<
"\tMetric after "
1531 << MAfter <<
"Profit: " << Profit <<
"\n");
1561 unsigned WavesAfter) {
1568 LLVM_DEBUG(
dbgs() <<
"New pressure will result in more spilling.\n");
1577 DAG.RegionEnd =
DAG.RegionBegin;
1578 int SkippedDebugInstr = 0;
1580 if (
MI->isDebugInstr()) {
1581 ++SkippedDebugInstr;
1585 if (
MI->getIterator() !=
DAG.RegionEnd) {
1587 if (!
MI->isDebugInstr())
1588 DAG.LIS->handleMove(*
MI,
true);
1592 for (
auto &
Op :
MI->all_defs())
1593 Op.setIsUndef(
false);
1596 if (!
MI->isDebugInstr()) {
1597 if (
DAG.ShouldTrackLaneMasks) {
1599 SlotIndex SlotIdx =
DAG.LIS->getInstructionIndex(*MI).getRegSlot();
1606 DAG.RegionEnd =
MI->getIterator();
1614 while (SkippedDebugInstr-- > 0)
1620 DAG.RegionBegin =
Unsched.front()->getIterator();
1621 if (
DAG.RegionBegin->isDebugInstr()) {
1623 if (
MI->isDebugInstr())
1625 DAG.RegionBegin =
MI->getIterator();
1632 DAG.placeDebugValues();
1637bool PreRARematStage::canIncreaseOccupancyOrReduceSpill() {
1646 auto ResetTargetRegions = [&]() {
1648 for (
unsigned I = 0, E =
DAG.Regions.
size();
I != E; ++
I) {
1656 ResetTargetRegions();
1657 if (!OptRegions.
empty() ||
DAG.MinOccupancy >=
MFI.getMaxWavesPerEU()) {
1660 TargetOcc = std::nullopt;
1664 TargetOcc =
DAG.MinOccupancy + 1;
1665 unsigned VGPRBlockSize =
1667 MaxSGPRs =
ST.getMaxNumSGPRs(*TargetOcc,
false);
1668 MaxVGPRs =
ST.getMaxNumVGPRs(*TargetOcc, VGPRBlockSize);
1669 ResetTargetRegions();
1672 dbgs() <<
"Analyzing ";
1673 MF.getFunction().printAsOperand(
dbgs(),
false);
1675 if (OptRegions.
empty()) {
1676 dbgs() <<
"no objective to achieve, occupancy is maximal at "
1677 <<
MFI.getMaxWavesPerEU();
1678 }
else if (!TargetOcc) {
1679 dbgs() <<
"reduce spilling (minimum target occupancy is "
1680 <<
MFI.getMinWavesPerEU() <<
')';
1682 dbgs() <<
"increase occupancy from " <<
DAG.MinOccupancy <<
" to "
1686 for (
unsigned I = 0,
E =
DAG.Regions.size();
I !=
E; ++
I) {
1687 if (
auto OptIt = OptRegions.
find(
I); OptIt != OptRegions.
end()) {
1693 if (OptRegions.
empty())
1700 auto ReduceRPInRegion = [&](
auto OptIt,
Register Reg, LaneBitmask
Mask,
1701 bool &Progress) ->
bool {
1702 GCNRPTarget &
Target = OptIt->getSecond();
1708 OptRegions.
erase(OptIt->getFirst());
1709 return OptRegions.
empty();
1714 DAG.RegionLiveOuts.buildLiveRegMap();
1717 DenseSet<unsigned> RematRegs;
1720 for (
unsigned I = 0,
E =
DAG.Regions.size();
I !=
E; ++
I) {
1725 if (!isReMaterializable(
DefMI))
1736 MachineInstr *
UseMI =
DAG.MRI.getOneNonDBGUser(
Reg);
1739 auto UseRegion = MIRegion.find(
UseMI);
1740 if (UseRegion != MIRegion.end() && UseRegion->second ==
I)
1749 if (Rematerializations.contains(
UseMI) ||
1751 return MO.isReg() && RematRegs.contains(MO.getReg());
1758 SlotIndex UseIdx =
DAG.LIS->getInstructionIndex(*UseMI).getRegSlot(
true);
1764 RematInstruction &Remat =
1765 Rematerializations.try_emplace(&
DefMI,
UseMI).first->second;
1767 bool RematUseful =
false;
1768 if (
auto It = OptRegions.
find(
I); It != OptRegions.
end()) {
1774 LaneBitmask
Mask =
DAG.RegionLiveOuts.getLiveRegsForRegionIdx(
I)[
Reg];
1775 if (ReduceRPInRegion(It,
Reg, Mask, RematUseful))
1779 for (
unsigned LIRegion = 0; LIRegion !=
E; ++LIRegion) {
1782 auto It =
DAG.LiveIns[LIRegion].find(
Reg);
1783 if (It ==
DAG.LiveIns[LIRegion].end() || It->second.none())
1785 Remat.LiveInRegions.insert(LIRegion);
1793 if (
auto It = OptRegions.
find(LIRegion); It != OptRegions.
end()) {
1795 if (ReduceRPInRegion(It,
Reg,
DAG.LiveIns[LIRegion][
Reg],
1804 Rematerializations.pop_back();
1805 REMAT_DEBUG(
dbgs() <<
" No impact, not rematerializing instruction\n");
1815 Rematerializations.clear();
1819 return !Rematerializations.empty();
1822void PreRARematStage::rematerialize() {
1823 const SIInstrInfo *
TII =
MF.getSubtarget<GCNSubtarget>().getInstrInfo();
1827 DenseSet<unsigned> RecomputeRP;
1830 for (
auto &[
DefMI, Remat] : Rematerializations) {
1833 unsigned DefRegion = MIRegion.at(
DefMI);
1836 TII->reMaterialize(*InsertPos->getParent(), InsertPos,
Reg,
1837 AMDGPU::NoSubRegister, *
DefMI, *
DAG.TRI);
1838 Remat.RematMI = &*std::prev(InsertPos);
1839 DAG.LIS->InsertMachineInstrInMaps(*Remat.RematMI);
1844 DAG.updateRegionBoundaries(
DAG.Regions[DefRegion],
DefMI,
nullptr);
1845 auto UseRegion = MIRegion.find(Remat.UseMI);
1846 if (UseRegion != MIRegion.end()) {
1847 DAG.updateRegionBoundaries(
DAG.Regions[UseRegion->second], InsertPos,
1850 DAG.LIS->RemoveMachineInstrFromMaps(*
DefMI);
1855 for (
unsigned I : Remat.LiveInRegions) {
1856 ImpactedRegions.insert({
I,
DAG.Pressure[
I]});
1859#ifdef EXPENSIVE_CHECKS
1870 LiveInterval &LI =
DAG.LIS->getInterval(
UseReg);
1871 LaneBitmask LM =
DAG.MRI.getMaxLaneMaskForVReg(MO.
getReg());
1875 LaneBitmask LiveInMask = RegionLiveIns.
at(
UseReg);
1876 LaneBitmask UncoveredLanes = LM & ~(LiveInMask & LM);
1880 if (UncoveredLanes.
any()) {
1882 for (LiveInterval::SubRange &SR : LI.
subranges())
1883 assert((SR.LaneMask & UncoveredLanes).none());
1893 LaneBitmask PrevMask = RegionLiveIns[
Reg];
1895 RegMasks.insert({{
I, Remat.RematMI->getOperand(0).getReg()}, PrevMask});
1896 if (Remat.UseMI->getParent() !=
DAG.Regions[
I].first->getParent())
1903 ImpactedRegions.insert({DefRegion,
DAG.Pressure[DefRegion]});
1904 RecomputeRP.
insert(DefRegion);
1907 Register RematReg = Remat.RematMI->getOperand(0).getReg();
1908 DAG.LIS->removeInterval(RematReg);
1909 DAG.LIS->createAndComputeVirtRegInterval(RematReg);
1915 unsigned DynamicVGPRBlockSize =
1917 AchievedOcc =
MFI.getMaxWavesPerEU();
1918 for (
auto &[
I, OriginalRP] : ImpactedRegions) {
1919 bool IsEmptyRegion =
DAG.Regions[
I].first ==
DAG.Regions[
I].second;
1920 RescheduleRegions[
I] = !IsEmptyRegion;
1925 if (IsEmptyRegion) {
1928 GCNDownwardRPTracker RPT(*
DAG.LIS);
1930 DAG.Regions[
I].second);
1931 if (NonDbgMI ==
DAG.Regions[
I].second) {
1935 RPT.reset(*NonDbgMI, &
DAG.LiveIns[
I]);
1936 RPT.advance(
DAG.Regions[
I].second);
1937 RP = RPT.moveMaxPressure();
1942 std::min(AchievedOcc,
RP.getOccupancy(
ST, DynamicVGPRBlockSize));
1948bool PreRARematStage::isReMaterializable(
const MachineInstr &
MI) {
1949 if (!
DAG.TII->isReMaterializable(
MI))
1952 for (
const MachineOperand &MO :
MI.all_uses()) {
1956 if (
DAG.MRI.isConstantPhysReg(MO.
getReg()) ||
DAG.TII->isIgnorableUse(MO))
1971 unsigned MaxOcc = std::max(AchievedOcc,
DAG.MinOccupancy);
1972 if (!TargetOcc || MaxOcc >= *TargetOcc)
1976 const SIInstrInfo *
TII =
MF.getSubtarget<GCNSubtarget>().getInstrInfo();
1979 for (
const auto &[
DefMI, Remat] : Rematerializations) {
1980 MachineInstr &RematMI = *Remat.RematMI;
1981 unsigned DefRegion = MIRegion.at(
DefMI);
1983 MachineBasicBlock *
MBB = RegionBB[DefRegion];
1989 TII->reMaterialize(*
MBB, InsertPos,
Reg, AMDGPU::NoSubRegister, RematMI,
1991 MachineInstr *NewMI = &*std::prev(InsertPos);
1992 DAG.LIS->InsertMachineInstrInMaps(*NewMI);
1994 auto UseRegion = MIRegion.find(Remat.UseMI);
1995 if (UseRegion != MIRegion.end()) {
1996 DAG.updateRegionBoundaries(
DAG.Regions[UseRegion->second], RematMI,
1999 DAG.updateRegionBoundaries(
DAG.Regions[DefRegion], InsertPos, NewMI);
2002 DAG.LIS->RemoveMachineInstrFromMaps(RematMI);
2006 DAG.LIS->removeInterval(
Reg);
2007 DAG.LIS->createAndComputeVirtRegInterval(
Reg);
2010 for (
unsigned LIRegion : Remat.LiveInRegions)
2011 DAG.LiveIns[LIRegion].insert({
Reg, RegMasks.at({LIRegion,
Reg})});
2015 for (
auto &[
I, OriginalRP] : ImpactedRegions)
2016 DAG.Pressure[
I] = OriginalRP;
2021void GCNScheduleDAGMILive::updateRegionBoundaries(
2024 assert((!NewMI || NewMI != RegionBounds.second) &&
2025 "cannot remove at region end");
2027 if (RegionBounds.first == RegionBounds.second) {
2028 assert(NewMI &&
"cannot remove from an empty region");
2029 RegionBounds.first = NewMI;
2035 if (
MI != RegionBounds.first)
2038 RegionBounds.first = std::next(
MI);
2040 RegionBounds.first = NewMI;
2057 if (HasIGLPInstrs) {
2058 SavedMutations.clear();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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...
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))
#define REMAT_PREFIX
Allows to easily filter for this stage's debug output.
static MachineInstr * getLastMIForRegion(MachineBasicBlock::iterator RegionBegin, MachineBasicBlock::iterator RegionEnd)
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 hasIGLPInstrs(ScheduleDAGInstrs *DAG)
static bool canUsePressureDiffs(const SUnit &SU)
Checks whether SU can use the cached DAG pressure diffs to compute the current register pressure.
static void getRegisterPressures(bool AtTop, const RegPressureTracker &RPTracker, SUnit *SU, std::vector< unsigned > &Pressure, std::vector< unsigned > &MaxPressure, GCNDownwardRPTracker &DownwardTracker, GCNUpwardRPTracker &UpwardTracker, ScheduleDAGMI *DAG, const SIRegisterInfo *SRI)
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 Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
A common definition of LaneBitmask for use in TableGen and CodeGen.
Promote Memory to Register
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool initGCNSchedStage() override
bool shouldRevertScheduling(unsigned WavesAfter) override
bool initGCNRegion() override
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
const ValueT & at(const_arg_type_t< KeyT > Val) const
at - Return the entry for the specified key, or abort if no such entry exists.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
GCNRegPressure bumpDownwardPressure(const MachineInstr *MI, const SIRegisterInfo *TRI) const
Mostly copy/paste from CodeGen/RegisterPressure.cpp Calculate the impact MI will have on CurPressure ...
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
DenseMap< unsigned, LaneBitmask > LiveRegSet
virtual bool initGCNRegion()
GCNRegPressure PressureBefore
bool isRegionWithExcessRP() const
bool mayCauseSpilling(unsigned WavesAfter)
ScheduleMetrics getScheduleMetrics(const std::vector< SUnit > &InputSchedule)
GCNScheduleDAGMILive & DAG
const GCNSchedStageID StageID
std::vector< MachineInstr * > Unsched
GCNRegPressure PressureAfter
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.
GCNDownwardRPTracker DownwardTracker
GCNSchedStrategy(const MachineSchedContext *C)
SmallVector< GCNSchedStageID, 4 > SchedStages
SUnit * pickNodeBidirectional(bool &IsTopNode)
void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy, const RegPressureTracker &RPTracker, SchedCandidate &Cand, bool IsBottomUp)
unsigned SGPRCriticalLimit
std::vector< unsigned > MaxPressure
bool hasNextStage() const
GCNSchedStageID getCurrentStage()
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...
GCNDownwardRPTracker * getDownwardTracker()
std::vector< unsigned > Pressure
void initialize(ScheduleDAGMI *DAG) override
Initialize the strategy after building the DAG for a new region.
GCNUpwardRPTracker UpwardTracker
void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop, const RegPressureTracker &RPTracker, const SIRegisterInfo *SRI, unsigned SGPRPressure, unsigned VGPRPressure, bool IsBottomUp)
SUnit * pickNode(bool &IsTopNode) override
Pick the next node to schedule, or return NULL.
GCNUpwardRPTracker * getUpwardTracker()
GCNSchedStageID getNextStage() const
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)
unsigned getMaxNumVGPRs(unsigned WavesPerEU, unsigned DynamicVGPRBlockSize) const
unsigned getMaxNumSGPRs(unsigned WavesPerEU, bool Addressable) const
void recede(const MachineInstr &MI)
Move to the state of RP just before the MI .
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
bool hasSubRanges() const
Returns true if subregister liveness information is available.
iterator_range< subrange_iterator > subranges()
succ_iterator succ_begin()
unsigned succ_size() const
MachineInstrBundleIterator< MachineInstr > iterator
Function & getFunction()
Return the LLVM function that this machine code represents.
Register getReg(unsigned Idx) const
Get the register for the operand index.
Representation of each machine instruction.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
unsigned getSubReg() const
bool readsReg() const
readsReg - Returns true if this operand reads the previous value of its register.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
bool shouldRevertScheduling(unsigned WavesAfter) override
bool shouldRevertScheduling(unsigned WavesAfter) override
bool shouldRevertScheduling(unsigned WavesAfter) 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.
RegionT * getParent() const
Get the parent of the Region.
List of registers defined and used by a machine instruction.
LLVM_ABI void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI, bool TrackLaneMasks, bool IgnoreDead)
Analyze the given instruction MI and fill in the Uses, Defs and DeadDefs list based on the MachineOpe...
LLVM_ABI void adjustLaneLiveness(const LiveIntervals &LIS, const MachineRegisterInfo &MRI, SlotIndex Pos, MachineInstr *AddFlagsMI=nullptr)
Use liveness information to find out which uses/defs are partially undefined/dead and adjust the VReg...
LLVM_ABI void detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS)
Use liveness information to find dead defs not marked with a dead flag and move them to the DeadDefs ...
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical 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 NodeNum
Entry # of node in the node vector.
unsigned short Latency
Node latency.
bool isScheduled
True once scheduled.
unsigned ParentClusterIdx
The parent cluster id.
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 unsigned getLatencyStallCycles(SUnit *SU)
Get the difference between the given SUnit's ready time and the current cycle.
unsigned getCurrMOps() const
Micro-ops issued in the current cycle.
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.
virtual void exitRegion()
Called when the scheduler has finished scheduling the current region.
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 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
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getMBBStartIdx(unsigned Num) const
Returns the first index in the given basic block number.
Provide an instruction scheduling machine model to CodeGen passes.
Target - Wrapper for Target specific information.
bool initGCNSchedStage() override
bool initGCNRegion() override
void finalizeGCNSchedStage() override
bool shouldRevertScheduling(unsigned WavesAfter) override
static bool allUsesAvailableAt(const MachineInstr *MI, SlotIndex UseIdx, const LiveIntervals &LIS, const MachineRegisterInfo &MRI, const TargetInstrInfo &TII)
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.
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 getVGPRAllocGranule(const MCSubtargetInfo *STI, unsigned DynamicVGPRBlockSize, std::optional< bool > EnableWavefrontSize32)
unsigned getAllocatedNumVGPRBlocks(const MCSubtargetInfo *STI, unsigned NumVGPRs, unsigned DynamicVGPRBlockSize, std::optional< bool > EnableWavefrontSize32)
unsigned getAddressableNumVGPRs(const MCSubtargetInfo *STI, unsigned DynamicVGPRBlockSize)
unsigned getDynamicVGPRBlockSize(const Function &F)
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
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)
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.
LLVM_ABI cl::opt< bool > VerifyScheduling
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
@ ClusteredLowOccupancyReschedule
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, SchedBoundary &Zone)
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.
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 Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
LLVM_ABI int biasPhysReg(const SUnit *SU, bool isTop)
Minimize physical register live ranges.
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
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
constexpr bool any() const
static constexpr LaneBitmask getNone()
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
PressureChange CriticalMax
PressureChange CurrentMax