31#define DEBUG_TYPE "machine-scheduler"
36 "amdgpu-disable-unclustered-high-rp-reschedule",
cl::Hidden,
37 cl::desc(
"Disable unclustered high register pressure "
38 "reduction scheduling stage."),
42 "amdgpu-disable-clustered-low-occupancy-reschedule",
cl::Hidden,
43 cl::desc(
"Disable clustered low occupancy "
44 "rescheduling for ILP scheduling stage."),
50 "Sets the bias which adds weight to occupancy vs latency. Set it to "
51 "100 to chase the occupancy only."),
56 cl::desc(
"Relax occupancy targets for kernels which are memory "
57 "bound (amdgpu-membound-threshold), or "
58 "Wave Limited (amdgpu-limit-wave-threshold)."),
63 cl::desc(
"Use the AMDGPU specific RPTrackers during scheduling"),
70 DownwardTracker(*
C->LIS), UpwardTracker(*
C->LIS), HasHighPressure(
false) {
104 "VGPRCriticalLimit calculation method.\n");
109 VGPRBudget = std::max(VGPRBudget, Granule);
148 if (!
Op.isReg() ||
Op.isImplicit())
150 if (
Op.getReg().isPhysical() ||
151 (
Op.isDef() &&
Op.getSubReg() != AMDGPU::NoSubRegister))
159 std::vector<unsigned> &Pressure, std::vector<unsigned> &MaxPressure,
174 Pressure.resize(4, 0);
185 Pressure[AMDGPU::RegisterPressureSets::SReg_32] = NewPressure.
getSGPRNum();
186 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] =
188 Pressure[AMDGPU::RegisterPressureSets::AGPR_32] = NewPressure.
getAGPRNum();
194 return Opcode == AMDGPU::SCHED_GROUP_BARRIER || Opcode == AMDGPU::IGLP_OPT;
201 unsigned SGPRPressure,
202 unsigned VGPRPressure,
bool IsBottomUp) {
229 Pressure[AMDGPU::RegisterPressureSets::SReg_32] = SGPRPressure;
230 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] = VGPRPressure;
238 (IsBottomUp ? Diff.getUnitInc() : -Diff.getUnitInc());
241#ifdef EXPENSIVE_CHECKS
242 std::vector<unsigned> CheckPressure, CheckMaxPressure;
245 if (
Pressure[AMDGPU::RegisterPressureSets::SReg_32] !=
246 CheckPressure[AMDGPU::RegisterPressureSets::SReg_32] ||
247 Pressure[AMDGPU::RegisterPressureSets::VGPR_32] !=
248 CheckPressure[AMDGPU::RegisterPressureSets::VGPR_32]) {
249 errs() <<
"Register Pressure is inaccurate when calculated through "
251 <<
"SGPR got " <<
Pressure[AMDGPU::RegisterPressureSets::SReg_32]
253 << CheckPressure[AMDGPU::RegisterPressureSets::SReg_32] <<
"\n"
254 <<
"VGPR got " <<
Pressure[AMDGPU::RegisterPressureSets::VGPR_32]
256 << CheckPressure[AMDGPU::RegisterPressureSets::VGPR_32] <<
"\n";
262 unsigned NewSGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::SReg_32];
263 unsigned NewVGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::VGPR_32];
273 const unsigned MaxVGPRPressureInc = 16;
274 bool ShouldTrackVGPRs = VGPRPressure + MaxVGPRPressureInc >=
VGPRExcessLimit;
275 bool ShouldTrackSGPRs = !ShouldTrackVGPRs && SGPRPressure >=
SGPRExcessLimit;
306 if (SGPRDelta >= 0 || VGPRDelta >= 0) {
308 if (SGPRDelta > VGPRDelta) {
329 unsigned SGPRPressure = 0;
330 unsigned VGPRPressure = 0;
333 SGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::SReg_32];
334 VGPRPressure =
Pressure[AMDGPU::RegisterPressureSets::VGPR_32];
339 SGPRPressure =
T->getPressure().getSGPRNum();
340 VGPRPressure =
T->getPressure().getArchVGPRNum();
344 for (
SUnit *SU : Q) {
348 VGPRPressure, IsBottomUp);
401 "Last pick result should correspond to re-picking right now");
423 "Last pick result should correspond to re-picking right now");
439 IsTopNode = Cand.AtTop;
560 bool SameBoundary = Zone !=
nullptr;
593 const SUnit *CandNextClusterSU =
595 const SUnit *TryCandNextClusterSU =
598 Cand.
SU == CandNextClusterSU, TryCand, Cand,
Cluster))
668 const SUnit *CandNextClusterSU =
670 const SUnit *TryCandNextClusterSU =
673 Cand.
SU == CandNextClusterSU, TryCand, Cand,
Cluster))
681 bool SameBoundary = Zone !=
nullptr;
698 if (TryMayLoad || CandMayLoad) {
699 bool TryLongLatency =
701 bool CandLongLatency =
705 Zone->
isTop() ? CandLongLatency : TryLongLatency, TryCand,
760 StartingOccupancy(MFI.getOccupancy()), MinOccupancy(StartingOccupancy),
761 RegionLiveOuts(this,
true) {
763 LLVM_DEBUG(
dbgs() <<
"Starting occupancy is " << StartingOccupancy <<
".\n");
766 if (MinOccupancy != StartingOccupancy)
767 LLVM_DEBUG(
dbgs() <<
"Allowing Occupancy drops to " << MinOccupancy
772std::unique_ptr<GCNSchedStage>
774 switch (SchedStageID) {
776 return std::make_unique<OccInitialScheduleStage>(SchedStageID, *
this);
778 return std::make_unique<UnclusteredHighRPStage>(SchedStageID, *
this);
780 return std::make_unique<ClusteredLowOccStage>(SchedStageID, *
this);
782 return std::make_unique<PreRARematStage>(SchedStageID, *
this);
784 return std::make_unique<ILPInitialScheduleStage>(SchedStageID, *
this);
786 return std::make_unique<MemoryClauseInitialScheduleStage>(SchedStageID,
800GCNScheduleDAGMILive::getRealRegPressure(
unsigned RegionIdx)
const {
808 auto REnd = RegionEnd == RegionBegin->getParent()->end()
809 ? std::prev(RegionEnd)
814void GCNScheduleDAGMILive::computeBlockPressure(
unsigned RegionIdx,
829 if (!Candidate->empty() && Candidate->pred_size() == 1) {
832 OnlySucc = Candidate;
837 size_t CurRegion = RegionIdx;
838 for (
size_t E = Regions.size(); CurRegion != E; ++CurRegion)
839 if (Regions[CurRegion].first->getParent() !=
MBB)
844 auto LiveInIt = MBBLiveIns.find(
MBB);
845 auto &Rgn = Regions[CurRegion];
847 if (LiveInIt != MBBLiveIns.end()) {
848 auto LiveIn = std::move(LiveInIt->second);
850 MBBLiveIns.erase(LiveInIt);
853 auto LRS = BBLiveInMap.lookup(NonDbgMI);
854#ifdef EXPENSIVE_CHECKS
863 if (Regions[CurRegion].first ==
I || NonDbgMI ==
I) {
864 LiveIns[CurRegion] =
RPTracker.getLiveRegs();
868 if (Regions[CurRegion].second ==
I) {
869 Pressure[CurRegion] =
RPTracker.moveMaxPressure();
870 if (CurRegion-- == RegionIdx)
883 MBBLiveIns[OnlySucc] =
RPTracker.moveLiveRegs();
888GCNScheduleDAGMILive::getRegionLiveInMap()
const {
890 std::vector<MachineInstr *> RegionFirstMIs;
891 RegionFirstMIs.reserve(Regions.size());
892 auto I = Regions.rbegin(), E = Regions.rend();
893 auto *
BB =
I->first->getParent();
896 RegionFirstMIs.push_back(
MI);
899 }
while (
I != E &&
I->first->getParent() ==
BB);
905GCNScheduleDAGMILive::getRegionLiveOutMap()
const {
907 std::vector<MachineInstr *> RegionLastMIs;
908 RegionLastMIs.reserve(Regions.size());
916 IdxToInstruction.clear();
919 IsLiveOut ? DAG->getRegionLiveOutMap() : DAG->getRegionLiveInMap();
920 for (
unsigned I = 0;
I < DAG->Regions.size();
I++) {
924 : &*DAG->Regions[
I].first;
925 IdxToInstruction[
I] = RegionKey;
933 LiveIns.resize(Regions.size());
934 Pressure.resize(Regions.size());
935 RescheduleRegions.
resize(Regions.size());
936 RegionsWithHighRP.
resize(Regions.size());
937 RegionsWithExcessRP.
resize(Regions.size());
938 RegionsWithMinOcc.
resize(Regions.size());
939 RegionsWithIGLPInstrs.
resize(Regions.size());
940 RescheduleRegions.
set();
941 RegionsWithHighRP.
reset();
942 RegionsWithExcessRP.
reset();
943 RegionsWithMinOcc.
reset();
944 RegionsWithIGLPInstrs.
reset();
949void GCNScheduleDAGMILive::runSchedStages() {
950 LLVM_DEBUG(
dbgs() <<
"All regions recorded, starting actual scheduling.\n");
952 if (!Regions.empty()) {
953 BBLiveInMap = getRegionLiveInMap();
961 if (!Stage->initGCNSchedStage())
964 for (
auto Region : Regions) {
968 if (!Stage->initGCNRegion()) {
969 Stage->advanceRegion();
978 &LiveIns[Stage->getRegionIdx()];
981 ->reset(
MRI, *RegionLiveIns);
984 Stage->getRegionIdx()));
988 Stage->finalizeGCNRegion();
991 Stage->finalizeGCNSchedStage();
999 OS <<
"Max Occupancy Initial Schedule";
1002 OS <<
"Unclustered High Register Pressure Reschedule";
1005 OS <<
"Clustered Low Occupancy Reschedule";
1008 OS <<
"Pre-RA Rematerialize";
1011 OS <<
"Max ILP Initial Schedule";
1014 OS <<
"Max memory clause Initial Schedule";
1023 : DAG(DAG), S(static_cast<
GCNSchedStrategy &>(*DAG.SchedImpl)), MF(DAG.MF),
1024 MFI(DAG.MFI), ST(DAG.ST), StageID(StageID) {}
1041 if (
DAG.RegionsWithHighRP.
none() &&
DAG.RegionsWithExcessRP.
none())
1048 InitialOccupancy =
DAG.MinOccupancy;
1058 <<
"Retrying function scheduling without clustering. "
1059 "Aggressivly try to reduce register pressure to achieve occupancy "
1060 <<
DAG.MinOccupancy <<
".\n");
1075 if (
DAG.StartingOccupancy <=
DAG.MinOccupancy)
1079 dbgs() <<
"Retrying function scheduling with lowest recorded occupancy "
1080 <<
DAG.MinOccupancy <<
".\n");
1088 if (
DAG.RegionsWithMinOcc.
none() ||
DAG.Regions.size() == 1)
1102 collectRematerializableInstructions();
1103 if (RematerializableInsts.empty() || !sinkTriviallyRematInsts(
ST,
TII))
1107 dbgs() <<
"Retrying function scheduling with improved occupancy of "
1108 <<
DAG.MinOccupancy <<
" from rematerializing\n");
1120 if (
DAG.MinOccupancy > InitialOccupancy) {
1121 for (
unsigned IDX = 0; IDX <
DAG.Pressure.size(); ++IDX)
1122 DAG.RegionsWithMinOcc[IDX] =
1123 DAG.Pressure[IDX].getOccupancy(
DAG.ST) ==
DAG.MinOccupancy;
1126 <<
" stage successfully increased occupancy to "
1127 <<
DAG.MinOccupancy <<
'\n');
1138 unsigned NumRegionInstrs = std::distance(
DAG.
begin(),
DAG.
end());
1148 <<
"\n From: " << *
DAG.
begin() <<
" To: ";
1150 else dbgs() <<
"End";
1151 dbgs() <<
" RegionInstrs: " << NumRegionInstrs <<
'\n');
1158 for (
auto &
I :
DAG) {
1171 dbgs() <<
"Pressure before scheduling:\nRegion live-ins:"
1173 <<
"Region live-in pressure: "
1198 DAG.MinOccupancy <= InitialOccupancy) &&
1274 unsigned TargetOccupancy = std::min(
1276 unsigned WavesAfter =
1278 unsigned WavesBefore =
1280 LLVM_DEBUG(
dbgs() <<
"Occupancy before scheduling: " << WavesBefore
1281 <<
", after " << WavesAfter <<
".\n");
1287 unsigned NewOccupancy = std::max(WavesAfter, WavesBefore);
1291 if (WavesAfter < WavesBefore && WavesAfter <
DAG.MinOccupancy &&
1293 LLVM_DEBUG(
dbgs() <<
"Function is memory bound, allow occupancy drop up to "
1295 NewOccupancy = WavesAfter;
1298 if (NewOccupancy <
DAG.MinOccupancy) {
1299 DAG.MinOccupancy = NewOccupancy;
1303 <<
DAG.MinOccupancy <<
".\n");
1337 unsigned ReadyCycle = CurrCycle;
1338 for (
auto &
D : SU.
Preds) {
1339 if (
D.isAssignedRegDep()) {
1343 ReadyCycle = std::max(ReadyCycle, DefReady +
Latency);
1346 ReadyCycles[SU.
NodeNum] = ReadyCycle;
1353 std::pair<MachineInstr *, unsigned>
B)
const {
1354 return A.second <
B.second;
1360 if (ReadyCycles.empty())
1362 unsigned BBNum = ReadyCycles.begin()->first->getParent()->getNumber();
1363 dbgs() <<
"\n################## Schedule time ReadyCycles for MBB : " << BBNum
1364 <<
" ##################\n# Cycle #\t\t\tInstruction "
1368 for (
auto &
I : ReadyCycles) {
1369 if (
I.second > IPrev + 1)
1370 dbgs() <<
"****************************** BUBBLE OF " <<
I.second - IPrev
1371 <<
" CYCLES DETECTED ******************************\n\n";
1372 dbgs() <<
"[ " <<
I.second <<
" ] : " << *
I.first <<
"\n";
1385 unsigned SumBubbles = 0;
1387 unsigned CurrCycle = 0;
1388 for (
auto &SU : InputSchedule) {
1389 unsigned ReadyCycle =
1391 SumBubbles += ReadyCycle - CurrCycle;
1393 ReadyCyclesSorted.insert(std::make_pair(SU.getInstr(), ReadyCycle));
1395 CurrCycle = ++ReadyCycle;
1418 unsigned SumBubbles = 0;
1420 unsigned CurrCycle = 0;
1421 for (
auto &
MI :
DAG) {
1425 unsigned ReadyCycle =
1427 SumBubbles += ReadyCycle - CurrCycle;
1429 ReadyCyclesSorted.insert(std::make_pair(SU->
getInstr(), ReadyCycle));
1431 CurrCycle = ++ReadyCycle;
1448 if (WavesAfter <
DAG.MinOccupancy)
1483 <<
"\n\t *** In shouldRevertScheduling ***\n"
1484 <<
" *********** BEFORE UnclusteredHighRPStage ***********\n");
1489 <<
"\n *********** AFTER UnclusteredHighRPStage ***********\n");
1491 unsigned OldMetric = MBefore.
getMetric();
1492 unsigned NewMetric = MAfter.
getMetric();
1493 unsigned WavesBefore =
1500 LLVM_DEBUG(
dbgs() <<
"\tMetric before " << MBefore <<
"\tMetric after "
1501 << MAfter <<
"Profit: " << Profit <<
"\n");
1536 unsigned WavesAfter) {
1543 LLVM_DEBUG(
dbgs() <<
"New pressure will result in more spilling.\n");
1558 int SkippedDebugInstr = 0;
1560 if (
MI->isDebugInstr()) {
1561 ++SkippedDebugInstr;
1568 if (!
MI->isDebugInstr())
1573 for (
auto &
Op :
MI->all_defs())
1574 Op.setIsUndef(
false);
1577 if (!
MI->isDebugInstr()) {
1595 while (SkippedDebugInstr-- > 0)
1604 if (
MI->isDebugInstr())
1618bool PreRARematStage::allUsesAvailableAt(
const MachineInstr *InstToRemat,
1625 RematIdx = std::max(RematIdx, RematIdx.
getRegSlot(
true));
1627 if (!MO.isReg() || !MO.getReg() || !MO.readsReg())
1630 if (!MO.getReg().isVirtual()) {
1657 unsigned SubReg = MO.getSubReg();
1659 :
MRI.getMaxLaneMaskForVReg(MO.getReg());
1661 if ((SR.LaneMask & LM).none())
1663 if (!SR.liveAt(RematIdx))
1676void PreRARematStage::collectRematerializableInstructions() {
1690 if (
Op->getSubReg() != 0 || !isTriviallyReMaterializable(*Def))
1697 bool HasRematDependency =
false;
1700 for (
auto &RematEntry : RematerializableInsts) {
1701 if (
find_if(RematEntry.second,
1702 [&Def](std::pair<MachineInstr *, MachineInstr *> &Remat) {
1703 for (MachineOperand &MO : Def->operands()) {
1706 if (MO.getReg() == Remat.first->getOperand(0).getReg())
1710 }) != RematEntry.second.end()) {
1711 HasRematDependency =
true;
1721 if (HasRematDependency)
1725 for (
auto &RematEntry : RematerializableInsts) {
1726 if (
find_if(RematEntry.second,
1727 [&UseI](std::pair<MachineInstr *, MachineInstr *> &Remat) {
1728 return Remat.first == UseI;
1729 }) != RematEntry.second.end()) {
1730 HasRematDependency =
true;
1735 if (HasRematDependency)
1741 bool AddedToRematList =
false;
1742 for (
unsigned I = 0, E =
DAG.Regions.size();
I != E; ++
I) {
1743 auto It =
DAG.LiveIns[
I].find(Reg);
1744 if (It !=
DAG.LiveIns[
I].end() && !It->second.none()) {
1745 if (
DAG.RegionsWithMinOcc[
I]) {
1749 if (allUsesAvailableAt(Def, DefIdx, UseIdx)) {
1750 RematerializableInsts[
I][
Def] = UseI;
1751 AddedToRematList =
true;
1757 RematDefToLiveInRegions[
Def].push_back(
I);
1760 if (!AddedToRematList)
1761 RematDefToLiveInRegions.erase(Def);
1765bool PreRARematStage::sinkTriviallyRematInsts(
const GCNSubtarget &ST,
1770 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>, 32>
1778 NewRescheduleRegions.
resize(
DAG.Regions.size());
1782 for (
const auto &It : RematDefToLiveInRegions)
1783 ImpactedRegions.
insert(It.second.begin(), It.second.end());
1787 for (
auto Idx : ImpactedRegions) {
1791 NewRegions =
DAG.Regions;
1792 NewRescheduleRegions.
reset();
1795 bool Improved =
false;
1796 for (
auto I : ImpactedRegions) {
1797 if (!
DAG.RegionsWithMinOcc[
I])
1802 int SGPRUsage = NewPressure[
I].getSGPRNum();
1811 if (NewPressure[
I].getOccupancy(
ST) >
DAG.MinOccupancy) {
1812 NewRescheduleRegions[
I] =
true;
1820 int TotalSinkableRegs = 0;
1821 for (
const auto &It : RematerializableInsts[
I]) {
1824 TotalSinkableRegs +=
1826#ifdef EXPENSIVE_CHECKS
1830 if (!MO.isReg() || !MO.getReg() || !MO.readsReg())
1844 LaneBitmask UncoveredLanes = LM & ~(LiveInMask & LM);
1848 if (UncoveredLanes.
any()) {
1851 assert((SR.LaneMask & UncoveredLanes).none());
1856 int VGPRsAfterSink = VGPRUsage - TotalSinkableRegs;
1860 if (OptimisticOccupancy <=
DAG.MinOccupancy)
1863 unsigned ImproveOccupancy = 0;
1865 for (
auto &It : RematerializableInsts[
I]) {
1871 TII->reMaterialize(*InsertPos->getParent(), InsertPos, Reg,
1872 Def->getOperand(0).getSubReg(), *Def, *
DAG.
TRI);
1877 InsertedMIToOldDef[NewMI] =
Def;
1881 DAG.updateRegionBoundaries(NewRegions, Def,
nullptr,
1885 DAG.updateRegionBoundaries(NewRegions, InsertPos, NewMI);
1891 for (
auto Idx : RematDefToLiveInRegions[Def]) {
1893 if (InsertPos->getParent() !=
DAG.Regions[
Idx].first->getParent()) {
1900 NewRegions[
Idx].first, NewRegions[
Idx].second);
1901 RPT.reset(*NonDbgMI, &NewLiveIns[
Idx]);
1902 RPT.advance(NewRegions[
Idx].second);
1903 NewPressure[
Idx] = RPT.moveMaxPressure();
1908 ImproveOccupancy = NewPressure[
I].getOccupancy(
ST);
1909 if (ImproveOccupancy >
DAG.MinOccupancy)
1914 for (
auto &Def : SinkedDefs)
1915 for (
auto TrackedIdx : RematDefToLiveInRegions[Def])
1916 RematerializableInsts[TrackedIdx].
erase(Def);
1918 if (ImproveOccupancy <=
DAG.MinOccupancy)
1921 NewRescheduleRegions[
I] =
true;
1928 for (
auto &Entry : InsertedMIToOldDef) {
1933 MI->eraseFromParent();
1942 for (
auto &Entry : InsertedMIToOldDef) {
1947 DAG.BBLiveInMap.erase(OldMI);
1958 for (
auto Idx : ImpactedRegions) {
1961 DAG.MBBLiveIns.erase(
DAG.Regions[
Idx].first->getParent());
1963 DAG.Regions = NewRegions;
1964 DAG.RescheduleRegions = NewRescheduleRegions;
1975bool PreRARematStage::isTriviallyReMaterializable(
const MachineInstr &
MI) {
1982 if (MO.getReg().isPhysical()) {
1996void GCNScheduleDAGMILive::updateRegionBoundaries(
2000 unsigned I = 0, E = RegionBoundaries.size();
2002 while (
I != E &&
MI->getParent() != RegionBoundaries[
I].first->getParent())
2005 for (;
I != E; ++
I) {
2006 if (
MI->getParent() != RegionBoundaries[
I].first->getParent())
2009 if (Removing &&
MI == RegionBoundaries[
I].first &&
2010 MI == RegionBoundaries[
I].second) {
2013 RegionBoundaries[
I] =
2014 std::pair(
MI->getParent()->end(),
MI->getParent()->end());
2017 if (
MI == RegionBoundaries[
I].first) {
2019 RegionBoundaries[
I] =
2020 std::pair(std::next(
MI), RegionBoundaries[
I].second);
2024 RegionBoundaries[
I].second);
2027 if (Removing &&
MI == RegionBoundaries[
I].second) {
2028 RegionBoundaries[
I] = std::pair(RegionBoundaries[
I].first, std::prev(
MI));
2042 bool RemoveKillFlags)
2047 if (HasIGLPInstrs) {
2048 SavedMutations.clear();
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder MachineInstrBuilder & DefMI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
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 isIGLPMutationOnly(unsigned Opcode)
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
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
std::pair< unsigned, unsigned > getOccupancyWithWorkGroupSizes(uint32_t LDSBytes, const Function &F) const
Subtarget's minimum/maximum occupancy, in number of waves per EU, that can be achieved when the only ...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
bool none() const
none - Returns true if none of the bits are set.
bool initGCNSchedStage() override
bool shouldRevertScheduling(unsigned WavesAfter) override
bool initGCNRegion() override
This class represents an Operation in the Expression.
bool erase(const KeyT &Val)
bool advance(MachineInstr *MI=nullptr, bool UseInternalIterator=true)
Move to the state at the next MI.
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
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
GCNPostScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S, bool RemoveKillFlags)
GCNRegPressure getPressure() const
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.
const unsigned HighRPSGPRBias
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
Update the scheduler's state after scheduling a node.
GCNDownwardRPTracker * getDownwardTracker()
std::vector< unsigned > Pressure
void initialize(ScheduleDAGMI *DAG) override
Initialize the strategy after building the DAG for a new region.
GCNUpwardRPTracker UpwardTracker
const unsigned HighRPVGPRBias
void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop, const RegPressureTracker &RPTracker, const SIRegisterInfo *SRI, unsigned SGPRPressure, unsigned VGPRPressure, bool IsBottomUp)
unsigned getTargetOccupancy()
SUnit * pickNode(bool &IsTopNode) override
Pick the best node to balance the schedule. Implements MachineSchedStrategy.
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
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
GCNScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S)
unsigned getAddressableNumArchVGPRs() const
bool hasGFX90AInsts() const
const SIInstrInfo * getInstrInfo() const override
unsigned getMaxNumVGPRs(unsigned WavesPerEU) const
unsigned getOccupancyWithNumVGPRs(unsigned VGPRs) const
Return the maximum number of waves per SIMD for kernels using VGPRs VGPRs.
unsigned getOccupancyWithNumSGPRs(unsigned SGPRs) const
Return the maximum number of waves per SIMD for kernels using SGPRs SGPRs.
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)
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
GenericScheduler shrinks the unscheduled zone using heuristics to balance the schedule.
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.
bool shouldRevertScheduling(unsigned WavesAfter) override
A live range for subregisters.
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasSubRanges() const
Returns true if subregister liveness information is available.
iterator_range< subrange_iterator > subranges()
bool hasInterval(Register Reg) const
SlotIndex InsertMachineInstrInMaps(MachineInstr &MI)
void handleMove(MachineInstr &MI, bool UpdateFlags=false)
Call this method to notify LiveIntervals that instruction MI has been moved within a basic block.
SlotIndexes * getSlotIndexes() const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
void RemoveMachineInstrFromMaps(MachineInstr &MI)
LiveInterval & getInterval(Register Reg)
void removeInterval(Register Reg)
Interval removal.
LiveInterval & createAndComputeVirtRegInterval(Register Reg)
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
succ_iterator succ_begin()
MachineInstr * remove(MachineInstr *I)
Remove the unbundled instruction from the instruction list without deleting it.
unsigned succ_size() const
MachineInstrBundleIterator< MachineInstr > iterator
StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
iterator_range< mop_iterator > operands()
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
void clearRegisterDeads(Register Reg)
Clear all dead flags on operands defining register Reg.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
MachineOperand * getOneDef(Register Reg) const
Returns the defining operand if there is exactly one operand defining the specified register,...
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
bool hasOneDef(Register RegNo) const
Return true if there is exactly one operand defining the specified register.
LaneBitmask getMaxLaneMaskForVReg(Register Reg) const
Returns a mask covering all bits that can appear in lane masks of subregisters of the virtual registe...
bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
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...
void advance()
Advance across the current instruction.
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...
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.
GCNRPTracker::LiveRegSet & getLiveRegsForRegionIdx(unsigned RegionIdx)
unsigned getNumAllocatableRegs(const TargetRegisterClass *RC) const
getNumAllocatableRegs - Returns the number of actually allocatable registers in RC in the current fun...
List of registers defined and used by a machine instruction.
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...
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...
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 ...
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
const TargetSchedModel & getSchedModel() const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
unsigned getOccupancy() const
void increaseOccupancy(const MachineFunction &MF, unsigned Limit)
unsigned getMaxWavesPerEU() const
unsigned getMinWavesPerEU() const
unsigned getMinAllowedOccupancy() const
void limitOccupancy(const MachineFunction &MF)
static unsigned getNumCoveredRegs(LaneBitmask LM)
static bool isVGPRClass(const TargetRegisterClass *RC)
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.
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.
unsigned getLatencyStallCycles(SUnit *SU)
Get the difference between the given SUnit's ready time and the current cycle.
SUnit * pickOnlyChoice()
Call this before applying any other heuristics to the Available queue.
unsigned getCurrMOps() const
Micro-ops issued in the current cycle.
void removeReady(SUnit *SU)
Remove SU from the ready set for this boundary.
A ScheduleDAG for scheduling lists of MachineInstr.
MachineBasicBlock::iterator end() const
Returns an iterator to the bottom of the current scheduling region.
MachineBasicBlock * BB
The block in which to insert instructions.
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.
MachineBasicBlock::iterator begin() const
Returns an iterator to the top of the current scheduling region.
SUnit * getSUnit(MachineInstr *MI) const
Returns an existing SUnit for this MI, or nullptr.
virtual void exitRegion()
Called when the scheduler has finished scheduling the current region.
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
unsigned NumRegionInstrs
Instructions in this region (distance(RegionBegin, RegionEnd)).
ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules machine instructions while...
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
PressureDiff & getPressureDiff(const SUnit *SU)
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
bool ShouldTrackLaneMasks
const RegPressureTracker & getBotRPTracker() const
bool isTrackingPressure() const
Return true if register pressure tracking is enabled.
const RegPressureTracker & getTopRPTracker() const
RegPressureTracker RPTracker
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
void startBlock(MachineBasicBlock *bb) override
Prepares to perform scheduling in the given block.
void addMutation(std::unique_ptr< ScheduleDAGMutation > Mutation)
Add a postprocessing step to the DAG builder.
MachineBasicBlock::iterator top() const
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
MachineBasicBlock::iterator bottom() const
void finishBlock() override
Cleans up after scheduling in the given block.
const SUnit * getNextClusterPred() const
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
const SUnit * getNextClusterSucc() const
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.
std::vector< SUnit > SUnits
The scheduling units.
const TargetRegisterInfo * TRI
Target processor register info.
MachineFunction & MF
Machine function.
static const unsigned ScaleFactor
unsigned getMetric() const
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.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndex getMBBStartIdx(unsigned Num) const
Returns the first index in the given basic block number.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
bool isTriviallyReMaterializable(const MachineInstr &MI) const
Return true if the instruction is trivially rematerializable, meaning it has no side effects and requ...
virtual bool isIgnorableUse(const MachineOperand &MO) const
Given MO is a PhysReg use return if it can be ignored for the purpose of instruction rematerializatio...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
LaneBitmask getSubRegIndexLaneMask(unsigned SubIdx) const
Return a bitmask representing the parts of a register that are covered by SubIdx.
Provide an instruction scheduling machine model to CodeGen passes.
virtual const TargetInstrInfo * getInstrInfo() const
bool initGCNSchedStage() override
bool initGCNRegion() override
void finalizeGCNSchedStage() override
bool shouldRevertScheduling(unsigned WavesAfter) override
VNInfo - Value Number Information.
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 getVGPRAllocGranule(const MCSubtargetInfo *STI, std::optional< bool > EnableWavefrontSize32)
@ C
The default llvm calling convention, compatible with C.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)
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.
cl::opt< bool > VerifyScheduling
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)
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.
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)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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...
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if 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)
bool tryLess(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
Return true if this heuristic determines order.
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
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 getOccupancy(const GCNSubtarget &ST) const
unsigned getVGPRNum(bool UnifiedVGPRFile) const
unsigned getArchVGPRNum() const
unsigned getAGPRNum() const
unsigned getSGPRNum() const
bool less(const MachineFunction &MF, const GCNRegPressure &O, unsigned MaxOccupancy=std::numeric_limits< unsigned >::max()) const
Compares this GCNRegpressure to O, returning true if this is less.
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)
void initResourceDelta(const ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel)
SchedResourceDelta ResDelta
Status of an instruction's critical resource consumption.
unsigned DemandedResources
constexpr bool none() const
constexpr bool any() const
static constexpr LaneBitmask getNone()
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
RegisterClassInfo * RegClassInfo
bool DisableLatencyHeuristic
PressureChange CriticalMax
PressureChange CurrentMax
bool IsAcyclicLatencyLimited