52#include "llvm/Config/llvm-config.h"
76#define DEBUG_TYPE "machine-scheduler"
79 "Number of instructions in source order after pre-RA scheduling");
81 "Number of instructions in source order after post-RA scheduling");
83 "Number of instructions scheduled by pre-RA scheduler");
85 "Number of instructions scheduled by post-RA scheduler");
86STATISTIC(NumClustered,
"Number of load/store pairs clustered");
89 "Number of scheduling units chosen from top queue pre-RA");
91 "Number of scheduling units chosen from bottom queue pre-RA");
93 "Number of scheduling units chosen for NoCand heuristic pre-RA");
95 "Number of scheduling units chosen for Only1 heuristic pre-RA");
97 "Number of scheduling units chosen for PhysReg heuristic pre-RA");
99 "Number of scheduling units chosen for RegExcess heuristic pre-RA");
101 "Number of scheduling units chosen for RegCritical heuristic pre-RA");
103 "Number of scheduling units chosen for Stall heuristic pre-RA");
105 "Number of scheduling units chosen for Cluster heuristic pre-RA");
107 "Number of scheduling units chosen for Weak heuristic pre-RA");
109 "Number of scheduling units chosen for RegMax heuristic pre-RA");
111 NumResourceReducePreRA,
112 "Number of scheduling units chosen for ResourceReduce heuristic pre-RA");
114 NumResourceDemandPreRA,
115 "Number of scheduling units chosen for ResourceDemand heuristic pre-RA");
117 NumTopDepthReducePreRA,
118 "Number of scheduling units chosen for TopDepthReduce heuristic pre-RA");
120 NumTopPathReducePreRA,
121 "Number of scheduling units chosen for TopPathReduce heuristic pre-RA");
123 NumBotHeightReducePreRA,
124 "Number of scheduling units chosen for BotHeightReduce heuristic pre-RA");
126 NumBotPathReducePreRA,
127 "Number of scheduling units chosen for BotPathReduce heuristic pre-RA");
129 "Number of scheduling units chosen for NodeOrder heuristic pre-RA");
131 "Number of scheduling units chosen for FirstValid heuristic pre-RA");
134 "Number of scheduling units chosen from top queue post-RA");
136 "Number of scheduling units chosen from bottom queue post-RA");
138 "Number of scheduling units chosen for NoCand heuristic post-RA");
140 "Number of scheduling units chosen for Only1 heuristic post-RA");
142 "Number of scheduling units chosen for PhysReg heuristic post-RA");
144 "Number of scheduling units chosen for RegExcess heuristic post-RA");
146 NumRegCriticalPostRA,
147 "Number of scheduling units chosen for RegCritical heuristic post-RA");
149 "Number of scheduling units chosen for Stall heuristic post-RA");
151 "Number of scheduling units chosen for Cluster heuristic post-RA");
153 "Number of scheduling units chosen for Weak heuristic post-RA");
155 "Number of scheduling units chosen for RegMax heuristic post-RA");
157 NumResourceReducePostRA,
158 "Number of scheduling units chosen for ResourceReduce heuristic post-RA");
160 NumResourceDemandPostRA,
161 "Number of scheduling units chosen for ResourceDemand heuristic post-RA");
163 NumTopDepthReducePostRA,
164 "Number of scheduling units chosen for TopDepthReduce heuristic post-RA");
166 NumTopPathReducePostRA,
167 "Number of scheduling units chosen for TopPathReduce heuristic post-RA");
169 NumBotHeightReducePostRA,
170 "Number of scheduling units chosen for BotHeightReduce heuristic post-RA");
172 NumBotPathReducePostRA,
173 "Number of scheduling units chosen for BotPathReduce heuristic post-RA");
175 "Number of scheduling units chosen for NodeOrder heuristic post-RA");
177 "Number of scheduling units chosen for FirstValid heuristic post-RA");
183 cl::desc(
"Pre reg-alloc list scheduling direction"),
187 "Force top-down pre reg-alloc list scheduling"),
189 "Force bottom-up pre reg-alloc list scheduling"),
191 "Force bidirectional pre reg-alloc list scheduling")));
195 cl::desc(
"Post reg-alloc list scheduling direction"),
199 "Force top-down post reg-alloc list scheduling"),
201 "Force bottom-up post reg-alloc list scheduling"),
203 "Force bidirectional post reg-alloc list scheduling")));
207 cl::desc(
"Print critical path length to stdout"));
211 cl::desc(
"Verify machine instrs before and after machine scheduling"));
216 cl::desc(
"Pop up a window to show MISched dags after they are processed"));
221 cl::desc(
"Dump resource usage at schedule boundary."));
224 cl::desc(
"Show details of invoking getNextResoufceCycle."));
229#ifdef LLVM_ENABLE_DUMP
240 cl::desc(
"Hide nodes with more predecessor/successor than cutoff"));
246 cl::desc(
"Only schedule this function"));
248 cl::desc(
"Only schedule this MBB#"));
263 cl::desc(
"Enable memop clustering."),
267 cl::desc(
"Switch to fast cluster algorithm with the lost "
268 "of some fusion opportunities"),
272 cl::desc(
"The threshold for fast cluster"),
275#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
278 cl::desc(
"Dump resource usage at schedule boundary."));
281 cl::desc(
"Set width of the columns with "
282 "the resources and schedule units"),
286 cl::desc(
"Set width of the columns showing resource booking."),
290 cl::desc(
"Sort the resources printed in the dump trace"));
301void MachineSchedStrategy::anchor() {}
303void ScheduleDAGMutation::anchor() {}
318namespace impl_detail {
347 const RequiredAnalyses &Analyses);
371 const RequiredAnalyses &Analyses);
390 MachineSchedulerLegacy();
402 PostMachineSchedulerLegacy();
411char MachineSchedulerLegacy::ID = 0;
416 "Machine Instruction Scheduler",
false,
false)
429void MachineSchedulerLegacy::getAnalysisUsage(
AnalysisUsage &AU)
const {
442char PostMachineSchedulerLegacy::ID = 0;
447 "PostRA Machine Instruction Scheduler",
false,
false)
454PostMachineSchedulerLegacy::PostMachineSchedulerLegacy()
459void PostMachineSchedulerLegacy::getAnalysisUsage(
AnalysisUsage &AU)
const {
482 cl::desc(
"Machine instruction scheduler to use"));
490 cl::desc(
"Enable the machine instruction scheduling pass."),
cl::init(
true),
494 "enable-post-misched",
495 cl::desc(
"Enable the post-ra machine instruction scheduling pass."),
502 assert(
I != Beg &&
"reached the top of the region, cannot decrement");
504 if (!
I->isDebugOrPseudoInstr())
523 for(;
I !=
End; ++
I) {
524 if (!
I->isDebugOrPseudoInstr())
565 const char *MSchedBanner =
"Before machine scheduling.";
567 MF->verify(
P, MSchedBanner, &
errs());
569 MF->verify(*MFAM, MSchedBanner, &
errs());
571 RegClassInfo->runOnMachineFunction(*MF);
575 std::unique_ptr<ScheduleDAGInstrs>
Scheduler(createMachineScheduler());
580 const char *MSchedBanner =
"After machine scheduling.";
582 MF->verify(
P, MSchedBanner, &
errs());
584 MF->verify(*MFAM, MSchedBanner, &
errs());
611 const char *PostMSchedBanner =
"Before post machine scheduling.";
613 MF->verify(
P, PostMSchedBanner, &
errs());
615 MF->verify(*MFAM, PostMSchedBanner, &
errs());
620 std::unique_ptr<ScheduleDAGInstrs>
Scheduler(createPostMachineScheduler());
624 const char *PostMSchedBanner =
"After post machine scheduling.";
626 MF->verify(
P, PostMSchedBanner, &
errs());
628 MF->verify(*MFAM, PostMSchedBanner, &
errs());
649bool MachineSchedulerLegacy::runOnMachineFunction(
MachineFunction &MF) {
662 auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
663 auto &MDT = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
664 auto &TM = getAnalysis<TargetPassConfig>().getTM<
TargetMachine>();
665 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
666 auto &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
667 Impl.setLegacyPass(
this);
668 return Impl.run(MF, TM, {MLI, MDT, AA, LIS});
700 Impl->setMFAM(&MFAM);
701 bool Changed = Impl->run(MF, *TM, {MLI, MDT, AA, LIS});
707 .preserve<SlotIndexesAnalysis>()
711bool PostMachineSchedulerLegacy::runOnMachineFunction(
MachineFunction &MF) {
723 auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
725 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
726 Impl.setLegacyPass(
this);
727 return Impl.run(MF, TM, {MLI, AA});
746 Impl->setMFAM(&MFAM);
747 bool Changed = Impl->run(MF, *TM, {MLI, AA});
779 bool RegionsTopDown) {
785 RegionEnd !=
MBB->
begin(); RegionEnd =
I) {
788 if (RegionEnd !=
MBB->
end() ||
795 unsigned NumRegionInstrs = 0;
801 if (!
MI.isDebugOrPseudoInstr()) {
810 if (NumRegionInstrs != 0)
815 std::reverse(Regions.
begin(), Regions.
end());
854 bool ScheduleSingleMI =
Scheduler.shouldScheduleSingleMIRegions();
858 unsigned NumRegionInstrs = R.NumRegionInstrs;
866 if (
I == RegionEnd || (!ScheduleSingleMI &&
I == std::prev(RegionEnd))) {
877 else dbgs() <<
"End\n";
878 dbgs() <<
" RegionInstrs: " << NumRegionInstrs <<
'\n');
902#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
904 dbgs() <<
"Queue " << Name <<
": ";
905 for (
const SUnit *SU : Queue)
906 dbgs() << SU->NodeNum <<
" ";
933 dbgs() <<
"*** Scheduling failed! ***\n";
935 dbgs() <<
" has been released too many times!\n";
968 dbgs() <<
"*** Scheduling failed! ***\n";
970 dbgs() <<
" has been released too many times!\n";
1007 unsigned regioninstrs)
1017 else if (
SchedImpl->getPolicy().OnlyBottomUp)
1045#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
1050 ++NumInstrsScheduled;
1082 bool IsTopNode =
false;
1087 LLVM_DEBUG(
dbgs() <<
"** ScheduleDAGMI::schedule picking next node\n");
1104 if (&*priorII ==
MI)
1126 dbgs() <<
"*** Final schedule for "
1143 assert(!SU.isBoundaryNode() &&
"Boundary node should not be in SUnits");
1146 SU.biasCriticalPath();
1149 if (!SU.NumPredsLeft)
1152 if (!SU.NumSuccsLeft)
1165 for (
SUnit *SU : TopRoots)
1204 for (std::vector<std::pair<MachineInstr *, MachineInstr *>>::iterator
1206 std::pair<MachineInstr *, MachineInstr *>
P = *std::prev(DI);
1217#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1229 dbgs() <<
" * Schedule table (TopDown):\n";
1247 for (
unsigned C = FirstCycle;
C <= LastCycle; ++
C)
1254 dbgs() <<
"Missing SUnit\n";
1257 std::string NodeName(
"SU(");
1258 NodeName += std::to_string(SU->
NodeNum) +
")";
1260 unsigned C = FirstCycle;
1261 for (;
C <= LastCycle; ++
C) {
1279 return std::tie(
LHS.AcquireAtCycle,
LHS.ReleaseAtCycle) <
1280 std::tie(
RHS.AcquireAtCycle,
RHS.ReleaseAtCycle);
1284 const std::string ResName =
1290 for (
unsigned I = 0, E = PI.ReleaseAtCycle - PI.AcquireAtCycle;
I != E;
1293 while (
C++ <= LastCycle)
1310 dbgs() <<
" * Schedule table (BottomUp):\n";
1323 if ((
int)SU->
BotReadyCycle - PI->ReleaseAtCycle + 1 < LastCycle)
1324 LastCycle = (int)SU->
BotReadyCycle - PI->ReleaseAtCycle + 1;
1329 for (
int C = FirstCycle;
C >= LastCycle; --
C)
1336 dbgs() <<
"Missing SUnit\n";
1339 std::string NodeName(
"SU(");
1340 NodeName += std::to_string(SU->
NodeNum) +
")";
1343 for (;
C >= LastCycle; --
C) {
1360 return std::tie(
LHS.AcquireAtCycle,
LHS.ReleaseAtCycle) <
1361 std::tie(
RHS.AcquireAtCycle,
RHS.ReleaseAtCycle);
1365 const std::string ResName =
1371 for (
unsigned I = 0, E = PI.ReleaseAtCycle - PI.AcquireAtCycle;
I != E;
1374 while (
C-- >= LastCycle)
1383#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1391 dbgs() <<
"* Schedule table (Bidirectional): not implemented\n";
1393 dbgs() <<
"* Schedule table: DumpDirection not set.\n";
1401 dbgs() <<
"Missing SUnit\n";
1426 if (!Reg.isVirtual())
1431 bool FoundDef =
false;
1433 if (MO2.getReg() == Reg && !MO2.isDead()) {
1460 unsigned regioninstrs)
1474 "ShouldTrackLaneMasks requires ShouldTrackPressure");
1525 dbgs() <<
"Bottom Pressure: ";
1531 "Can't find the region bottom");
1548 dbgs() <<
"Excess PSets: ";
1549 for (const PressureChange &RCPS : RegionCriticalPSets)
1550 dbgs() << TRI->getRegPressureSetName(RCPS.getPSet()) <<
" ";
1558 const std::vector<unsigned> &NewMaxPressure) {
1564 unsigned ID = PC.getPSet();
1569 && NewMaxPressure[
ID] <= (
unsigned)std::numeric_limits<int16_t>::max())
1573 if (NewMaxPressure[
ID] >= Limit - 2) {
1575 << NewMaxPressure[
ID]
1576 << ((NewMaxPressure[
ID] > Limit) ?
" > " :
" <= ")
1589 if (!Reg.isVirtual())
1597 bool Decrement =
P.LaneMask.any();
1601 SUnit &SU = *V2SU.SU;
1611 <<
" UpdateRegPressure: SU(" << SU.
NodeNum <<
") "
1634 assert(VNI &&
"No live value at use.");
1637 SUnit *SU = V2SU.SU;
1661#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1667 dbgs() <<
" Pressure Diff : ";
1670 dbgs() <<
" Single Issue : ";
1714 bool IsTopNode =
false;
1719 LLVM_DEBUG(
dbgs() <<
"** ScheduleDAGMILive::schedule picking next node\n");
1746 dbgs() <<
"*** Final schedule for "
1818 unsigned MaxCyclicLatency = 0;
1822 if (!Reg.isVirtual())
1834 unsigned LiveOutHeight = DefSU->
getHeight();
1839 SUnit *SU = V2SU.SU;
1851 unsigned CyclicLatency = 0;
1853 CyclicLatency = LiveOutDepth - SU->
getDepth();
1856 if (LiveInHeight > LiveOutHeight) {
1857 if (LiveInHeight - LiveOutHeight < CyclicLatency)
1858 CyclicLatency = LiveInHeight - LiveOutHeight;
1863 << SU->
NodeNum <<
") = " << CyclicLatency <<
"c\n");
1864 if (CyclicLatency > MaxCyclicLatency)
1865 MaxCyclicLatency = CyclicLatency;
1868 LLVM_DEBUG(
dbgs() <<
"Cyclic Critical Path: " << MaxCyclicLatency <<
"c\n");
1869 return MaxCyclicLatency;
1922 if (&*priorII ==
MI)
1974 bool OffsetIsScalable;
1978 : SU(SU), BaseOps(BaseOps),
Offset(
Offset), Width(Width),
1979 OffsetIsScalable(OffsetIsScalable) {}
1983 if (
A->getType() !=
B->getType())
1984 return A->getType() <
B->getType();
1986 return A->getReg() <
B->getReg();
1992 return StackGrowsDown ?
A->getIndex() >
B->getIndex()
1993 :
A->getIndex() <
B->getIndex();
2003 if (std::lexicographical_compare(BaseOps.
begin(), BaseOps.
end(),
2004 RHS.BaseOps.begin(),
RHS.BaseOps.end(),
2007 if (std::lexicographical_compare(
RHS.BaseOps.begin(),
RHS.BaseOps.end(),
2008 BaseOps.
begin(), BaseOps.
end(), Compare))
2019 bool ReorderWhileClustering;
2024 bool ReorderWhileClustering)
2025 :
TII(tii),
TRI(tri), IsLoad(IsLoad),
2026 ReorderWhileClustering(ReorderWhileClustering) {}
2033 void collectMemOpRecords(std::vector<SUnit> &SUnits,
2039class StoreClusterMutation :
public BaseMemOpClusterMutation {
2043 bool ReorderWhileClustering)
2044 : BaseMemOpClusterMutation(tii, tri,
false, ReorderWhileClustering) {}
2047class LoadClusterMutation :
public BaseMemOpClusterMutation {
2050 bool ReorderWhileClustering)
2051 : BaseMemOpClusterMutation(tii, tri,
true, ReorderWhileClustering) {}
2058std::unique_ptr<ScheduleDAGMutation>
2061 bool ReorderWhileClustering) {
2063 TII,
TRI, ReorderWhileClustering)
2067std::unique_ptr<ScheduleDAGMutation>
2070 bool ReorderWhileClustering) {
2072 TII,
TRI, ReorderWhileClustering)
2083void BaseMemOpClusterMutation::clusterNeighboringMemOps(
2094 auto MemOpa = MemOpRecords[
Idx];
2097 unsigned NextIdx =
Idx + 1;
2098 for (; NextIdx <
End; ++NextIdx)
2101 if (!SUnit2ClusterInfo.
count(MemOpRecords[NextIdx].SU->NodeNum) &&
2103 (!DAG->
IsReachable(MemOpRecords[NextIdx].SU, MemOpa.SU) &&
2104 !DAG->
IsReachable(MemOpa.SU, MemOpRecords[NextIdx].SU))))
2109 auto MemOpb = MemOpRecords[NextIdx];
2110 unsigned ClusterLength = 2;
2111 unsigned CurrentClusterBytes = MemOpa.Width.getValue().getKnownMinValue() +
2112 MemOpb.Width.getValue().getKnownMinValue();
2113 auto It = SUnit2ClusterInfo.
find(MemOpa.SU->NodeNum);
2114 if (It != SUnit2ClusterInfo.
end()) {
2115 const auto &[
Len, Bytes] = It->second;
2116 ClusterLength =
Len + 1;
2117 CurrentClusterBytes = Bytes + MemOpb.Width.getValue().getKnownMinValue();
2120 if (!
TII->shouldClusterMemOps(MemOpa.BaseOps, MemOpa.Offset,
2121 MemOpa.OffsetIsScalable, MemOpb.BaseOps,
2122 MemOpb.Offset, MemOpb.OffsetIsScalable,
2123 ClusterLength, CurrentClusterBytes))
2126 SUnit *SUa = MemOpa.SU;
2127 SUnit *SUb = MemOpb.SU;
2169 SUnit2ClusterInfo[MemOpb.SU->NodeNum] = {ClusterLength,
2170 CurrentClusterBytes};
2173 <<
", Curr cluster bytes: " << CurrentClusterBytes
2184 unsigned ClusterIdx = AllClusters.
size();
2186 MemberI->ParentClusterIdx = ClusterIdx;
2189 AllClusters.push_back(Group);
2193void BaseMemOpClusterMutation::collectMemOpRecords(
2195 for (
auto &SU : SUnits) {
2203 bool OffsetIsScalable;
2206 OffsetIsScalable, Width,
TRI)) {
2211 MemOpInfo(&SU, BaseOps,
Offset, OffsetIsScalable, Width));
2214 <<
Offset <<
", OffsetIsScalable: " << OffsetIsScalable
2215 <<
", Width: " << Width <<
"\n");
2218 for (
const auto *
Op : BaseOps)
2224bool BaseMemOpClusterMutation::groupMemOps(
2231 for (
const auto &
MemOp : MemOps) {
2232 unsigned ChainPredID = DAG->
SUnits.size();
2234 for (
const SDep &Pred :
MemOp.SU->Preds) {
2258 collectMemOpRecords(DAG->
SUnits, MemOpRecords);
2260 if (MemOpRecords.
size() < 2)
2267 bool FastCluster = groupMemOps(MemOpRecords, DAG,
Groups);
2269 for (
auto &Group :
Groups) {
2275 clusterNeighboringMemOps(Group.second, FastCluster, DAG);
2309std::unique_ptr<ScheduleDAGMutation>
2312 return std::make_unique<CopyConstrain>(
TII,
TRI);
2357 unsigned LocalReg = SrcReg;
2358 unsigned GlobalReg = DstReg;
2360 if (!LocalLI->
isLocal(RegionBeginIdx, RegionEndIdx)) {
2364 if (!LocalLI->
isLocal(RegionBeginIdx, RegionEndIdx))
2375 if (GlobalSegment == GlobalLI->
end())
2382 if (GlobalSegment->contains(LocalLI->
beginIndex()))
2385 if (GlobalSegment == GlobalLI->
end())
2389 if (GlobalSegment != GlobalLI->
begin()) {
2392 GlobalSegment->start)) {
2403 assert(std::prev(GlobalSegment)->start < LocalLI->beginIndex() &&
2404 "Disconnected LRG within the scheduling region.");
2420 for (
const SDep &Succ : LastLocalSU->
Succs) {
2435 for (
const SDep &Pred : GlobalSU->
Preds) {
2438 if (Pred.
getSUnit() == FirstLocalSU)
2446 for (
SUnit *LU : LocalUses) {
2447 LLVM_DEBUG(
dbgs() <<
" Local use SU(" << LU->NodeNum <<
") -> SU("
2448 << GlobalSU->
NodeNum <<
")\n");
2451 for (
SUnit *GU : GlobalUses) {
2452 LLVM_DEBUG(
dbgs() <<
" Global use SU(" << GU->NodeNum <<
") -> SU("
2453 << FirstLocalSU->
NodeNum <<
")\n");
2465 if (FirstPos == DAG->
end())
2493 unsigned Latency,
bool AfterSchedNode) {
2494 int ResCntFactor = (int)(Count - (
Latency * LFactor));
2496 return ResCntFactor >= (int)LFactor;
2498 return ResCntFactor > (int)LFactor;
2511 CheckPending =
false;
2514 MinReadyCycle = std::numeric_limits<unsigned>::max();
2515 ExpectedLatency = 0;
2516 DependentLatency = 0;
2518 MaxExecutedResCount = 0;
2520 IsResourceLimited =
false;
2521 ReservedCycles.clear();
2522 ReservedResourceSegments.clear();
2523 ReservedCyclesIndex.
clear();
2524 ResourceGroupSubUnitMasks.clear();
2525#if LLVM_ENABLE_ABI_BREAKING_CHECKS
2529 MaxObservedStall = 0;
2532 ExecutedResCounts.
resize(1);
2533 assert(!ExecutedResCounts[0] &&
"nonzero count for bad resource");
2549 unsigned PIdx = PI->ProcResourceIdx;
2551 assert(PI->ReleaseAtCycle >= PI->AcquireAtCycle);
2553 (Factor * (PI->ReleaseAtCycle - PI->AcquireAtCycle));
2566 ReservedCyclesIndex.
resize(ResourceCount);
2567 ExecutedResCounts.
resize(ResourceCount);
2568 ResourceGroupSubUnitMasks.resize(ResourceCount,
APInt(ResourceCount, 0));
2569 unsigned NumUnits = 0;
2571 for (
unsigned i = 0; i < ResourceCount; ++i) {
2572 ReservedCyclesIndex[i] = NumUnits;
2578 ResourceGroupSubUnitMasks[i].setBit(SubUnits[U]);
2598 if (ReadyCycle > CurrCycle)
2599 return ReadyCycle - CurrCycle;
2606 unsigned ReleaseAtCycle,
2607 unsigned AcquireAtCycle) {
2610 return ReservedResourceSegments[InstanceIdx].getFirstAvailableAtFromTop(
2611 CurrCycle, AcquireAtCycle, ReleaseAtCycle);
2613 return ReservedResourceSegments[InstanceIdx].getFirstAvailableAtFromBottom(
2614 CurrCycle, AcquireAtCycle, ReleaseAtCycle);
2617 unsigned NextUnreserved = ReservedCycles[InstanceIdx];
2623 NextUnreserved = std::max(CurrCycle, NextUnreserved + ReleaseAtCycle);
2624 return NextUnreserved;
2630std::pair<unsigned, unsigned>
2632 unsigned ReleaseAtCycle,
2633 unsigned AcquireAtCycle) {
2635 LLVM_DEBUG(
dbgs() <<
" Resource booking (@" << CurrCycle <<
"c): \n");
2637 LLVM_DEBUG(
dbgs() <<
" getNextResourceCycle (@" << CurrCycle <<
"c): \n");
2640 unsigned InstanceIdx = 0;
2641 unsigned StartIndex = ReservedCyclesIndex[PIdx];
2643 assert(NumberOfInstances > 0 &&
2644 "Cannot have zero instances of a ProcResource");
2661 if (ResourceGroupSubUnitMasks[PIdx][PE.ProcResourceIdx])
2663 StartIndex, ReleaseAtCycle, AcquireAtCycle),
2667 for (
unsigned I = 0,
End = NumberOfInstances;
I <
End; ++
I) {
2668 unsigned NextUnreserved, NextInstanceIdx;
2669 std::tie(NextUnreserved, NextInstanceIdx) =
2671 if (MinNextUnreserved > NextUnreserved) {
2672 InstanceIdx = NextInstanceIdx;
2673 MinNextUnreserved = NextUnreserved;
2676 return std::make_pair(MinNextUnreserved, InstanceIdx);
2679 for (
unsigned I = StartIndex,
End = StartIndex + NumberOfInstances;
I <
End;
2681 unsigned NextUnreserved =
2685 << NextUnreserved <<
"c\n");
2686 if (MinNextUnreserved > NextUnreserved) {
2688 MinNextUnreserved = NextUnreserved;
2693 <<
"[" << InstanceIdx - StartIndex <<
"]"
2694 <<
" available @" << MinNextUnreserved <<
"c"
2696 return std::make_pair(MinNextUnreserved, InstanceIdx);
2716 <<
"hazard: SU(" << SU->
NodeNum <<
") reported by HazardRec\n");
2723 << uops <<
", CurrMOps = " << CurrMOps <<
", "
2724 <<
"CurrMOps + uops > issue width of "
2733 << (
isTop() ?
"begin" :
"end") <<
" group\n");
2742 unsigned ResIdx = PE.ProcResourceIdx;
2743 unsigned ReleaseAtCycle = PE.ReleaseAtCycle;
2744 unsigned AcquireAtCycle = PE.AcquireAtCycle;
2745 unsigned NRCycle, InstanceIdx;
2746 std::tie(NRCycle, InstanceIdx) =
2748 if (NRCycle > CurrCycle) {
2749#if LLVM_ENABLE_ABI_BREAKING_CHECKS
2750 MaxObservedStall = std::max(ReleaseAtCycle, MaxObservedStall);
2753 <<
"hazard: SU(" << SU->
NodeNum <<
") "
2755 << InstanceIdx - ReservedCyclesIndex[ResIdx] <<
']' <<
"="
2756 << NRCycle <<
"c, is later than "
2757 <<
"CurrCycle = " << CurrCycle <<
"c\n");
2768 SUnit *LateSU =
nullptr;
2769 unsigned RemLatency = 0;
2770 for (
SUnit *SU : ReadySUs) {
2772 if (L > RemLatency) {
2779 << LateSU->
NodeNum <<
") " << RemLatency <<
"c\n");
2798 PIdx != PEnd; ++PIdx) {
2800 if (OtherCount > OtherCritCount) {
2801 OtherCritCount = OtherCount;
2802 OtherCritIdx = PIdx;
2811 return OtherCritCount;
2818#if LLVM_ENABLE_ABI_BREAKING_CHECKS
2822 if (ReadyCycle > CurrCycle)
2823 MaxObservedStall = std::max(ReadyCycle - CurrCycle, MaxObservedStall);
2826 if (ReadyCycle < MinReadyCycle)
2827 MinReadyCycle = ReadyCycle;
2832 bool HazardDetected = !IsBuffered && ReadyCycle > CurrCycle;
2835 <<
") ReadyCycle = " << ReadyCycle
2836 <<
" is later than CurrCycle = " << CurrCycle
2837 <<
" on an unbuffered resource" <<
"\n");
2842 HazardDetected =
true;
2847 if (!HazardDetected) {
2850 <<
"Move SU(" << SU->
NodeNum <<
") into Available Q\n");
2864 assert(MinReadyCycle < std::numeric_limits<unsigned>::max() &&
2865 "MinReadyCycle uninitialized");
2866 if (MinReadyCycle > NextCycle)
2867 NextCycle = MinReadyCycle;
2871 CurrMOps = (CurrMOps <= DecMOps) ? 0 : CurrMOps - DecMOps;
2874 if ((NextCycle - CurrCycle) > DependentLatency)
2875 DependentLatency = 0;
2877 DependentLatency -= (NextCycle - CurrCycle);
2881 CurrCycle = NextCycle;
2884 for (; CurrCycle != NextCycle; ++CurrCycle) {
2891 CheckPending =
true;
2901 ExecutedResCounts[PIdx] += Count;
2902 if (ExecutedResCounts[PIdx] > MaxExecutedResCount)
2903 MaxExecutedResCount = ExecutedResCounts[PIdx];
2917 unsigned ReleaseAtCycle,
2919 unsigned AcquireAtCycle) {
2921 unsigned Count = Factor * (ReleaseAtCycle- AcquireAtCycle);
2923 << ReleaseAtCycle <<
"x" << Factor <<
"u\n");
2933 ZoneCritResIdx = PIdx;
2940 unsigned NextAvailable, InstanceIdx;
2941 std::tie(NextAvailable, InstanceIdx) =
2943 if (NextAvailable > CurrCycle) {
2946 <<
'[' << InstanceIdx - ReservedCyclesIndex[PIdx] <<
']'
2947 <<
" reserved until @" << NextAvailable <<
"\n");
2949 return NextAvailable;
2963 CheckPending =
true;
2971 "Cannot schedule this instruction's MicroOps in the current cycle.");
2976 unsigned NextCycle = CurrCycle;
2979 assert(ReadyCycle <= CurrCycle &&
"Broken PendingQueue");
2982 if (ReadyCycle > NextCycle) {
2983 NextCycle = ReadyCycle;
2984 LLVM_DEBUG(
dbgs() <<
" *** Stall until: " << ReadyCycle <<
"\n");
2993 NextCycle = ReadyCycle;
2996 RetiredMOps += IncMOps;
3003 if (ZoneCritResIdx) {
3005 unsigned ScaledMOps =
3022 countResource(SC, PI->ProcResourceIdx, PI->ReleaseAtCycle, NextCycle,
3023 PI->AcquireAtCycle);
3024 if (RCycle > NextCycle)
3035 unsigned PIdx = PI->ProcResourceIdx;
3039 unsigned ReservedUntil, InstanceIdx;
3041 SC, PIdx, PI->ReleaseAtCycle, PI->AcquireAtCycle);
3043 ReservedResourceSegments[InstanceIdx].add(
3045 NextCycle, PI->AcquireAtCycle, PI->ReleaseAtCycle),
3048 ReservedResourceSegments[InstanceIdx].add(
3050 NextCycle, PI->AcquireAtCycle, PI->ReleaseAtCycle),
3055 unsigned ReservedUntil, InstanceIdx;
3057 SC, PIdx, PI->ReleaseAtCycle, PI->AcquireAtCycle);
3059 ReservedCycles[InstanceIdx] =
3060 std::max(ReservedUntil, NextCycle + PI->ReleaseAtCycle);
3062 ReservedCycles[InstanceIdx] = NextCycle;
3069 unsigned &TopLatency =
isTop() ? ExpectedLatency : DependentLatency;
3070 unsigned &BotLatency =
isTop() ? DependentLatency : ExpectedLatency;
3074 << SU->
NodeNum <<
") " << TopLatency <<
"c\n");
3079 << SU->
NodeNum <<
") " << BotLatency <<
"c\n");
3082 if (NextCycle > CurrCycle)
3095 CurrMOps += IncMOps;
3109 LLVM_DEBUG(
dbgs() <<
" *** Max MOps " << CurrMOps <<
" at cycle "
3110 << CurrCycle <<
'\n');
3121 MinReadyCycle = std::numeric_limits<unsigned>::max();
3131 if (ReadyCycle < MinReadyCycle)
3132 MinReadyCycle = ReadyCycle;
3143 CheckPending =
false;
3189#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3199 unsigned StartIdx = 0;
3201 for (
unsigned ResIdx = 0; ResIdx < ResourceCount; ++ResIdx) {
3204 for (
unsigned UnitIdx = 0; UnitIdx < NumUnits; ++UnitIdx) {
3205 dbgs() << ResName <<
"(" << UnitIdx <<
") = ";
3207 if (ReservedResourceSegments.count(StartIdx + UnitIdx))
3208 dbgs() << ReservedResourceSegments.at(StartIdx + UnitIdx);
3212 dbgs() << ReservedCycles[StartIdx + UnitIdx] <<
"\n";
3214 StartIdx += NumUnits;
3223 if (ZoneCritResIdx) {
3228 ResCount = RetiredMOps * ResFactor;
3232 <<
" Retired: " << RetiredMOps;
3234 dbgs() <<
"\n Critical: " << ResCount / LFactor <<
"c, "
3235 << ResCount / ResFactor <<
" "
3237 <<
"\n ExpectedLatency: " << ExpectedLatency <<
"c\n"
3238 << (IsResourceLimited ?
" - Resource" :
" - Latency")
3284 RemLatency = std::max(RemLatency,
3286 RemLatency = std::max(RemLatency,
3293bool GenericSchedulerBase::shouldReduceLatency(
const CandPolicy &Policy,
3295 bool ComputeRemLatency,
3296 unsigned &RemLatency)
const {
3306 if (ComputeRemLatency)
3322 unsigned OtherCritIdx = 0;
3323 unsigned OtherCount =
3326 bool OtherResLimited =
false;
3327 unsigned RemLatency = 0;
3328 bool RemLatencyComputed =
false;
3331 RemLatencyComputed =
true;
3333 OtherCount, RemLatency,
false);
3339 if (!OtherResLimited &&
3340 (IsPostRA || shouldReduceLatency(Policy, CurrZone, !RemLatencyComputed,
3344 <<
" RemainingLatency " << RemLatency <<
" + "
3353 dbgs() <<
" " << CurrZone.Available.getName() <<
" ResourceLimited: "
3354 << SchedModel->getResourceName(CurrZone.getZoneCritResIdx()) <<
"\n";
3355 }
if (OtherResLimited)
dbgs()
3356 <<
" RemainingLimit: "
3359 <<
" Latency limited both directions.\n");
3364 if (OtherResLimited)
3373 case NoCand:
return "NOCAND ";
3374 case Only1:
return "ONLY1 ";
3375 case PhysReg:
return "PHYS-REG ";
3378 case Stall:
return "STALL ";
3379 case Cluster:
return "CLUSTER ";
3380 case Weak:
return "WEAK ";
3381 case RegMax:
return "REG-MAX ";
3397 unsigned ResIdx = 0;
3433 <<
":" <<
P.getUnitInc() <<
" ";
3456 if (TryVal < CandVal) {
3460 if (TryVal > CandVal) {
3461 if (Cand.
Reason > Reason)
3472 if (TryVal > CandVal) {
3476 if (TryVal < CandVal) {
3477 if (Cand.
Reason > Reason)
3519 bool IsPostRA =
false) {
3522 << (IsPostRA ?
"post-RA" :
"pre-RA") <<
"]\n");
3541 NumRegExcessPostRA++;
3544 NumRegCriticalPostRA++;
3559 NumResourceReducePostRA++;
3562 NumResourceDemandPostRA++;
3565 NumTopDepthReducePostRA++;
3568 NumTopPathReducePostRA++;
3571 NumBotHeightReducePostRA++;
3574 NumBotPathReducePostRA++;
3577 NumNodeOrderPostRA++;
3580 NumFirstValidPostRA++;
3600 NumRegExcessPreRA++;
3603 NumRegCriticalPreRA++;
3618 NumResourceReducePreRA++;
3621 NumResourceDemandPreRA++;
3624 NumTopDepthReducePreRA++;
3627 NumTopPathReducePreRA++;
3630 NumBotHeightReducePreRA++;
3633 NumBotPathReducePreRA++;
3636 NumNodeOrderPreRA++;
3639 NumFirstValidPreRA++;
3647 bool IsPostRA =
false) {
3653 "(PreRA)GenericScheduler needs vreg liveness");
3659 DAG->computeDFSResult();
3670 if (!Top.HazardRec) {
3673 if (!Bot.HazardRec) {
3676 TopCand.SU =
nullptr;
3677 BotCand.SU =
nullptr;
3695 for (
unsigned VT = MVT::i64; VT > (
unsigned)MVT::i1; --VT) {
3736#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3737 dbgs() <<
"GenericScheduler RegionPolicy: "
3759 unsigned IterCount =
3765 unsigned InFlightCount =
3767 unsigned BufferLimit =
3773 dbgs() <<
"IssueCycles="
3776 <<
"c NumIters=" << (AcyclicCount + IterCount - 1) / IterCount
3786 for (
const SUnit *SU : Bot.Available) {
3797 checkAcyclicLatency();
3824 if (TryPSet == CandPSet) {
3829 int TryRank = TryP.
isValid() ?
TRI->getRegPressureSetScore(MF, TryPSet) :
3830 std::numeric_limits<int>::max();
3832 int CandRank = CandP.
isValid() ?
TRI->getRegPressureSetScore(MF, CandPSet) :
3833 std::numeric_limits<int>::max();
3838 return tryGreater(TryRank, CandRank, TryCand, Cand, Reason);
3856 unsigned ScheduledOper = isTop ? 1 : 0;
3857 unsigned UnscheduledOper = isTop ? 0 : 1;
3860 if (
MI->getOperand(ScheduledOper).getReg().isPhysical())
3865 if (
MI->getOperand(UnscheduledOper).getReg().isPhysical())
3866 return AtBoundary ? -1 : 1;
3869 if (
MI->isMoveImmediate()) {
3875 if (
Op.isReg() && !
Op.getReg().isPhysical()) {
3882 return isTop ? -1 : 1;
3895 if (DAG->isTrackingPressure()) {
3900 DAG->getRegionCriticalPSets(),
3901 DAG->getRegPressure().MaxSetPressure);
3906 &DAG->getPressureDiff(Cand.
SU),
3908 DAG->getRegionCriticalPSets(),
3909 DAG->getRegPressure().MaxSetPressure);
3913 DAG->getPressureDiff(Cand.
SU),
3915 DAG->getRegionCriticalPSets(),
3916 DAG->getRegPressure().MaxSetPressure);
3921 <<
" Try SU(" << Cand.
SU->
NodeNum <<
") "
3970 bool SameBoundary = Zone !=
nullptr;
3991 unsigned CandZoneCluster = Cand.
AtTop ? TopClusterID : BotClusterID;
3992 unsigned TryCandZoneCluster = TryCand.
AtTop ? TopClusterID : BotClusterID;
3993 bool CandIsClusterSucc =
3995 bool TryCandIsClusterSucc =
3998 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
4006 TryCand, Cand,
Weak))
4058 for (
SUnit *SU : Q) {
4061 initCandidate(TryCand, SU, Zone.
isTop(), RPTracker, TempTracker);
4064 if (tryCandidate(Cand, TryCand, ZoneArg)) {
4078 if (
SUnit *SU = Bot.pickOnlyChoice()) {
4083 if (
SUnit *SU = Top.pickOnlyChoice()) {
4099 if (!BotCand.isValid() || BotCand.SU->isScheduled ||
4100 BotCand.Policy != BotPolicy) {
4102 pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), BotCand);
4103 assert(BotCand.Reason !=
NoCand &&
"failed to find the first candidate");
4110 pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), TCand);
4112 "Last pick result should correspond to re-picking right now");
4119 if (!TopCand.isValid() || TopCand.SU->isScheduled ||
4120 TopCand.Policy != TopPolicy) {
4122 pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TopCand);
4123 assert(TopCand.Reason !=
NoCand &&
"failed to find the first candidate");
4130 pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TCand);
4132 "Last pick result should correspond to re-picking right now");
4138 assert(BotCand.isValid());
4139 assert(TopCand.isValid());
4142 if (tryCandidate(Cand, TopCand,
nullptr)) {
4147 IsTopNode = Cand.
AtTop;
4155 assert(Top.Available.empty() && Top.Pending.empty() &&
4156 Bot.Available.empty() && Bot.Pending.empty() &&
"ReadyQ garbage");
4162 SU = Top.pickOnlyChoice();
4165 TopCand.reset(NoPolicy);
4166 pickNodeFromQueue(Top, NoPolicy, DAG->getTopRPTracker(), TopCand);
4167 assert(TopCand.Reason !=
NoCand &&
"failed to find a candidate");
4173 SU = Bot.pickOnlyChoice();
4176 BotCand.reset(NoPolicy);
4177 pickNodeFromQueue(Bot, NoPolicy, DAG->getBotRPTracker(), BotCand);
4178 assert(BotCand.Reason !=
NoCand &&
"failed to find a candidate");
4184 SU = pickNodeBidirectional(IsTopNode);
4204 Top.removeReady(SU);
4206 Bot.removeReady(SU);
4213 ++NumInstrsInSourceOrderPreRA;
4217 ++NumInstrsInSourceOrderPreRA;
4220 NumInstrsScheduledPreRA += 1;
4233 for (
SDep &Dep : Deps) {
4234 if (Dep.getKind() !=
SDep::Data || !Dep.getReg().isPhysical())
4236 SUnit *DepSU = Dep.getSUnit();
4237 if (isTop ? DepSU->
Succs.size() > 1 : DepSU->
Preds.size() > 1)
4240 if (!Copy->isCopy() && !Copy->isMoveImmediate())
4262 dbgs() <<
" Top Cluster: ";
4263 for (
auto *
N : *TopCluster)
4264 dbgs() <<
N->NodeNum <<
'\t';
4270 reschedulePhysReg(SU,
true);
4277 dbgs() <<
" Bot Cluster: ";
4278 for (
auto *
N : *BotCluster)
4279 dbgs() <<
N->NodeNum <<
'\t';
4285 reschedulePhysReg(SU,
false);
4313 if (!Top.HazardRec) {
4316 if (!Bot.HazardRec) {
4357 for (
const SUnit *SU : Bot.Available) {
4381 if (
tryLess(Top.getLatencyStallCycles(TryCand.
SU),
4382 Top.getLatencyStallCycles(Cand.
SU), TryCand, Cand,
Stall))
4386 unsigned CandZoneCluster = Cand.
AtTop ? TopClusterID : BotClusterID;
4387 unsigned TryCandZoneCluster = TryCand.
AtTop ? TopClusterID : BotClusterID;
4388 bool CandIsClusterSucc =
4390 bool TryCandIsClusterSucc =
4393 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
4426 for (
SUnit *SU : Q) {
4431 if (tryCandidate(Cand, TryCand)) {
4445 if (
SUnit *SU = Bot.pickOnlyChoice()) {
4450 if (
SUnit *SU = Top.pickOnlyChoice()) {
4466 if (!BotCand.isValid() || BotCand.SU->isScheduled ||
4467 BotCand.Policy != BotPolicy) {
4469 pickNodeFromQueue(Bot, BotCand);
4470 assert(BotCand.Reason !=
NoCand &&
"failed to find the first candidate");
4477 pickNodeFromQueue(Bot, BotCand);
4479 "Last pick result should correspond to re-picking right now");
4486 if (!TopCand.isValid() || TopCand.SU->isScheduled ||
4487 TopCand.Policy != TopPolicy) {
4489 pickNodeFromQueue(Top, TopCand);
4490 assert(TopCand.Reason !=
NoCand &&
"failed to find the first candidate");
4497 pickNodeFromQueue(Top, TopCand);
4499 "Last pick result should correspond to re-picking right now");
4505 assert(BotCand.isValid());
4506 assert(TopCand.isValid());
4509 if (tryCandidate(Cand, TopCand)) {
4514 IsTopNode = Cand.
AtTop;
4522 assert(Top.Available.empty() && Top.Pending.empty() &&
4523 Bot.Available.empty() && Bot.Pending.empty() &&
"ReadyQ garbage");
4529 SU = Bot.pickOnlyChoice();
4534 BotCand.reset(NoPolicy);
4537 setPolicy(BotCand.Policy,
true, Bot,
nullptr);
4538 pickNodeFromQueue(Bot, BotCand);
4539 assert(BotCand.Reason !=
NoCand &&
"failed to find a candidate");
4545 SU = Top.pickOnlyChoice();
4550 TopCand.reset(NoPolicy);
4553 setPolicy(TopCand.Policy,
true, Top,
nullptr);
4554 pickNodeFromQueue(Top, TopCand);
4555 assert(TopCand.Reason !=
NoCand &&
"failed to find a candidate");
4561 SU = pickNodeBidirectional(IsTopNode);
4566 Top.removeReady(SU);
4568 Bot.removeReady(SU);
4575 ++NumInstrsInSourceOrderPostRA;
4579 ++NumInstrsInSourceOrderPostRA;
4582 NumInstrsScheduledPostRA += 1;
4610 const BitVector *ScheduledTrees =
nullptr;
4613 ILPOrder(
bool MaxILP) : MaximizeILP(MaxILP) {}
4618 bool operator()(
const SUnit *
A,
const SUnit *
B)
const {
4621 if (SchedTreeA != SchedTreeB) {
4623 if (ScheduledTrees->
test(SchedTreeA) != ScheduledTrees->
test(SchedTreeB))
4624 return ScheduledTrees->
test(SchedTreeB);
4645 std::vector<SUnit*> ReadyQ;
4648 ILPScheduler(
bool MaximizeILP) :
Cmp(MaximizeILP) {}
4659 void registerRoots()
override {
4661 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4668 SUnit *pickNode(
bool &IsTopNode)
override {
4669 if (ReadyQ.empty())
return nullptr;
4670 std::pop_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4671 SUnit *SU = ReadyQ.back();
4675 <<
"SU(" << SU->
NodeNum <<
") "
4682 <<
"Scheduling " << *SU->
getInstr());
4687 void scheduleTree(
unsigned SubtreeID)
override {
4688 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4693 void schedNode(
SUnit *SU,
bool IsTopNode)
override {
4694 assert(!IsTopNode &&
"SchedDFSResult needs bottom-up");
4697 void releaseTopNode(
SUnit *)
override { }
4699 void releaseBottomNode(
SUnit *SU)
override {
4700 ReadyQ.push_back(SU);
4701 std::push_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4728template<
bool IsReverse>
4732 return A->NodeNum >
B->NodeNum;
4734 return A->NodeNum <
B->NodeNum;
4754 InstructionShuffler(
bool alternate,
bool topdown)
4755 : IsAlternating(alternate), IsTopDown(topdown) {}
4765 SUnit *pickNode(
bool &IsTopNode)
override {
4769 if (TopQ.empty())
return nullptr;
4776 if (BottomQ.empty())
return nullptr;
4783 IsTopDown = !IsTopDown;
4787 void schedNode(
SUnit *SU,
bool IsTopNode)
override {}
4789 void releaseTopNode(
SUnit *SU)
override {
4792 void releaseBottomNode(
SUnit *SU)
override {
4804 C, std::make_unique<InstructionShuffler>(Alternate, TopDown));
4808 "shuffle",
"Shuffle machine instructions alternating directions",
4827 return std::string(
G->MF.getName());
4847 return "color=cyan,style=dashed";
4849 return "color=blue,style=dashed";
4866 return G->getGraphNodeLabel(SU);
4870 std::string Str(
"shape=Mrecord");
4875 Str +=
",style=filled,fillcolor=\"#";
4892 errs() <<
"ScheduleDAGMI::viewGraph is only available in debug builds on "
4893 <<
"systems with Graphviz or gv!\n";
4899 viewGraph(getDAGName(),
"Scheduling-Units Graph for " + getDAGName());
4908 return A.first <
B.first;
4911unsigned ResourceSegments::getFirstAvailableAt(
4912 unsigned CurrCycle,
unsigned AcquireAtCycle,
unsigned ReleaseAtCycle,
4914 IntervalBuilder)
const {
4916 "Cannot execute on an un-sorted set of intervals.");
4920 if (AcquireAtCycle == ReleaseAtCycle)
4923 unsigned RetCycle = CurrCycle;
4925 IntervalBuilder(RetCycle, AcquireAtCycle, ReleaseAtCycle);
4926 for (
auto &
Interval : _Intervals) {
4933 "Invalid intervals configuration.");
4935 NewInterval = IntervalBuilder(RetCycle, AcquireAtCycle, ReleaseAtCycle);
4941 const unsigned CutOff) {
4942 assert(
A.first <=
A.second &&
"Cannot add negative resource usage");
4943 assert(CutOff > 0 &&
"0-size interval history has no use.");
4949 if (
A.first ==
A.second)
4956 "A resource is being overwritten");
4957 _Intervals.push_back(
A);
4963 while (_Intervals.size() > CutOff)
4964 _Intervals.pop_front();
4969 assert(
A.first <=
A.second &&
"Invalid interval");
4970 assert(
B.first <=
B.second &&
"Invalid interval");
4973 if ((
A.first ==
B.first) || (
A.second ==
B.second))
4978 if ((
A.first >
B.first) && (
A.second <
B.second))
4983 if ((
A.first >
B.first) && (
A.first <
B.second) && (
A.second >
B.second))
4988 if ((
A.first <
B.first) && (
B.first <
A.second) && (
B.second >
B.first))
4994void ResourceSegments::sortAndMerge() {
4995 if (_Intervals.size() <= 1)
5002 auto next = std::next(std::begin(_Intervals));
5003 auto E = std::end(_Intervals);
5004 for (; next !=
E; ++next) {
5005 if (std::prev(next)->second >= next->first) {
5006 next->first = std::prev(next)->first;
5007 _Intervals.erase(std::prev(next));
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const Function * getParent(const Value *V)
This file implements the BitVector class.
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")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
COFF::MachineTypes Machine
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static std::optional< ArrayRef< InsnRange >::iterator > intersects(const MachineInstr *StartMI, const MachineInstr *EndMI, const ArrayRef< InsnRange > &Ranges, const InstructionOrdering &Ordering)
Check if the instruction range [StartMI, EndMI] intersects any instruction range in Ranges.
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
This file defines the DenseMap class.
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
const HexagonInstrInfo * TII
A common definition of LaneBitmask for use in TableGen and CodeGen.
static bool isSchedBoundary(MachineBasicBlock::iterator MI, MachineBasicBlock *MBB, MachineFunction *MF, const TargetInstrInfo *TII)
Return true of the given instruction should not be included in a scheduling region.
static MachineSchedRegistry ILPMaxRegistry("ilpmax", "Schedule bottom-up for max ILP", createILPMaxScheduler)
static cl::opt< bool > EnableMemOpCluster("misched-cluster", cl::Hidden, cl::desc("Enable memop clustering."), cl::init(true))
Machine Instruction Scheduler
static MachineBasicBlock::const_iterator nextIfDebug(MachineBasicBlock::const_iterator I, MachineBasicBlock::const_iterator End)
If this iterator is a debug value, increment until reaching the End or a non-debug instruction.
static const unsigned MinSubtreeSize
static const unsigned InvalidCycle
static cl::opt< bool > MISchedSortResourcesInTrace("misched-sort-resources-in-trace", cl::Hidden, cl::init(true), cl::desc("Sort the resources printed in the dump trace"))
static cl::opt< bool > EnableCyclicPath("misched-cyclicpath", cl::Hidden, cl::desc("Enable cyclic critical path analysis."), cl::init(true))
static MachineBasicBlock::const_iterator priorNonDebug(MachineBasicBlock::const_iterator I, MachineBasicBlock::const_iterator Beg)
Decrement this iterator until reaching the top or a non-debug instr.
static cl::opt< MachineSchedRegistry::ScheduleDAGCtor, false, RegisterPassParser< MachineSchedRegistry > > MachineSchedOpt("misched", cl::init(&useDefaultMachineSched), cl::Hidden, cl::desc("Machine instruction scheduler to use"))
MachineSchedOpt allows command line selection of the scheduler.
static cl::opt< bool > EnableMachineSched("enable-misched", cl::desc("Enable the machine instruction scheduling pass."), cl::init(true), cl::Hidden)
static unsigned computeRemLatency(SchedBoundary &CurrZone)
Compute remaining latency.
static cl::opt< unsigned > MISchedCutoff("misched-cutoff", cl::Hidden, cl::desc("Stop scheduling after N instructions"), cl::init(~0U))
static cl::opt< unsigned > SchedOnlyBlock("misched-only-block", cl::Hidden, cl::desc("Only schedule this MBB#"))
static cl::opt< bool > EnableRegPressure("misched-regpressure", cl::Hidden, cl::desc("Enable register pressure scheduling."), cl::init(true))
static void tracePick(GenericSchedulerBase::CandReason Reason, bool IsTop, bool IsPostRA=false)
static MachineSchedRegistry GenericSchedRegistry("converge", "Standard converging scheduler.", createConvergingSched)
static cl::opt< unsigned > HeaderColWidth("misched-dump-schedule-trace-col-header-width", cl::Hidden, cl::desc("Set width of the columns with " "the resources and schedule units"), cl::init(19))
static cl::opt< bool > ForceFastCluster("force-fast-cluster", cl::Hidden, cl::desc("Switch to fast cluster algorithm with the lost " "of some fusion opportunities"), cl::init(false))
static cl::opt< unsigned > FastClusterThreshold("fast-cluster-threshold", cl::Hidden, cl::desc("The threshold for fast cluster"), cl::init(1000))
static bool checkResourceLimit(unsigned LFactor, unsigned Count, unsigned Latency, bool AfterSchedNode)
Given a Count of resource usage and a Latency value, return true if a SchedBoundary becomes resource ...
static ScheduleDAGInstrs * createInstructionShuffler(MachineSchedContext *C)
static ScheduleDAGInstrs * useDefaultMachineSched(MachineSchedContext *C)
A dummy default scheduler factory indicates whether the scheduler is overridden on the command line.
static bool sortIntervals(const ResourceSegments::IntervalTy &A, const ResourceSegments::IntervalTy &B)
Sort predicate for the intervals stored in an instance of ResourceSegments.
static cl::opt< unsigned > ColWidth("misched-dump-schedule-trace-col-width", cl::Hidden, cl::desc("Set width of the columns showing resource booking."), cl::init(5))
static MachineSchedRegistry DefaultSchedRegistry("default", "Use the target's default scheduler choice.", useDefaultMachineSched)
static cl::opt< std::string > SchedOnlyFunc("misched-only-func", cl::Hidden, cl::desc("Only schedule this function"))
static const char * scheduleTableLegend
static ScheduleDAGInstrs * createConvergingSched(MachineSchedContext *C)
static cl::opt< unsigned > ViewMISchedCutoff("view-misched-cutoff", cl::Hidden, cl::desc("Hide nodes with more predecessor/successor than cutoff"))
In some situations a few uninteresting nodes depend on nearly all other nodes in the graph,...
static MachineSchedRegistry ShufflerRegistry("shuffle", "Shuffle machine instructions alternating directions", createInstructionShuffler)
static cl::opt< bool > EnablePostRAMachineSched("enable-post-misched", cl::desc("Enable the post-ra machine instruction scheduling pass."), cl::init(true), cl::Hidden)
static void getSchedRegions(MachineBasicBlock *MBB, MBBRegionsVector &Regions, bool RegionsTopDown)
static cl::opt< unsigned > MIResourceCutOff("misched-resource-cutoff", cl::Hidden, cl::desc("Number of intervals to track"), cl::init(10))
static ScheduleDAGInstrs * createILPMaxScheduler(MachineSchedContext *C)
static cl::opt< unsigned > ReadyListLimit("misched-limit", cl::Hidden, cl::desc("Limit ready list to N instructions"), cl::init(256))
Avoid quadratic complexity in unusually large basic blocks by limiting the size of the ready lists.
static ScheduleDAGInstrs * createILPMinScheduler(MachineSchedContext *C)
static cl::opt< bool > MISchedDumpScheduleTrace("misched-dump-schedule-trace", cl::Hidden, cl::init(false), cl::desc("Dump resource usage at schedule boundary."))
static MachineSchedRegistry ILPMinRegistry("ilpmin", "Schedule bottom-up for min ILP", createILPMinScheduler)
Register const TargetRegisterInfo * TRI
std::pair< uint64_t, uint64_t > Interval
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the PriorityQueue class.
static bool isSimple(Instruction *I)
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringLiteral > StandardNames)
Initialize the set of available library functions based on the specified target triple.
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
static const X86InstrFMA3Group Groups[]
Class recording the (high level) value of a variable.
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
A private abstract base class describing the concept of an individual alias analysis implementation.
Class for arbitrary precision integers.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
reverse_iterator rend() const
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
reverse_iterator rbegin() const
bool test(unsigned Idx) const
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
void clear()
clear - Removes all bits from the bitvector.
Represents analyses that only rely on functions' control flow.
This class represents an Operation in the Expression.
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
ECValue - The EquivalenceClasses data structure is just a set of these.
EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...
iterator_range< member_iterator > members(const ECValue &ECV) const
member_iterator unionSets(const ElemTy &V1, const ElemTy &V2)
union - Merge the two equivalence sets for the specified values, inserting them if they do not alread...
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
static const char * getReasonStr(GenericSchedulerBase::CandReason Reason)
const MachineSchedContext * Context
CandReason
Represent the type of SchedCandidate found within a single queue.
const TargetRegisterInfo * TRI
void checkAcyclicLatency()
Set IsAcyclicLatencyLimited if the acyclic path is longer than the cyclic critical path by more cycle...
virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const
Apply a set of heuristics to a new candidate.
void dumpPolicy() const override
void initialize(ScheduleDAGMI *dag) override
Initialize the strategy after building the DAG for a new region.
void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop, const RegPressureTracker &RPTracker, RegPressureTracker &TempTracker)
void registerRoots() override
Notify this strategy that all roots have been released (including those that depend on EntrySU or Exi...
void initPolicy(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned NumRegionInstrs) override
Initialize the per-region scheduling policy.
void reschedulePhysReg(SUnit *SU, bool isTop)
SUnit * pickNode(bool &IsTopNode) override
Pick the best node to balance the schedule. Implements MachineSchedStrategy.
void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy, const RegPressureTracker &RPTracker, SchedCandidate &Candidate)
Pick the best candidate from the queue.
void schedNode(SUnit *SU, bool IsTopNode) override
Update the scheduler's state after scheduling a node.
SUnit * pickNodeBidirectional(bool &IsTopNode)
Pick the best candidate node from either the top or bottom queue.
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const override
Get the base register and byte offset of a load/store instr.
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
Test if the given instruction should be considered a scheduling boundary.
Itinerary data supplied by a subtarget to be used by a target.
LiveInterval - This class represents the liveness of a register, or stack slot.
MachineInstr * getInstructionFromIndex(SlotIndex index) const
Returns the instruction associated with the given index.
LLVM_ABI void handleMove(MachineInstr &MI, bool UpdateFlags=false)
Call this method to notify LiveIntervals that instruction MI has been moved within a basic block.
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)
Result of a LiveRange query.
VNInfo * valueIn() const
Return the value that is live-in to the instruction.
LiveQueryResult Query(SlotIndex Idx) const
Query Liveness at Idx.
VNInfo * getVNInfoBefore(SlotIndex Idx) const
getVNInfoBefore - Return the VNInfo that is live up to but not necessarily including Idx,...
SlotIndex beginIndex() const
beginIndex - Return the lowest numbered slot covered.
SlotIndex endIndex() const
endNumber - return the maximum point of the range of the whole, exclusive.
bool isLocal(SlotIndex Start, SlotIndex End) const
True iff this segment is a single segment that lies between the specified boundaries,...
LLVM_ABI iterator find(SlotIndex Pos)
find - Return an iterator pointing to the first segment that ends after Pos, or end().
static LocationSize precise(uint64_t Value)
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI bool isSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a successor of this block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
Analysis pass which computes a MachineDominatorTree.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream.
nonconst_iterator getNonConstIterator() const
Representation of each machine instruction.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
Analysis pass that exposes the MachineLoopInfo for a machine function.
MachineOperand class - Representation of each machine instruction operand.
MachinePassRegistry - Track the registration of machine passes.
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
MachineSchedRegistry provides a selection of available machine instruction schedulers.
static LLVM_ABI MachinePassRegistry< ScheduleDAGCtor > Registry
ScheduleDAGInstrs *(*)(MachineSchedContext *) ScheduleDAGCtor
MachineSchedStrategy - Interface to the scheduling algorithm used by ScheduleDAGMI.
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
LLVM_ABI MachineSchedulerPass(const TargetMachine *TM)
LLVM_ABI ~MachineSchedulerPass()
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
void initPolicy(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned NumRegionInstrs) override
Optionally override the per-region scheduling policy.
virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand)
Apply a set of heuristics to a new candidate for PostRA scheduling.
void schedNode(SUnit *SU, bool IsTopNode) override
Called after ScheduleDAGMI has scheduled an instruction and updated scheduled/remaining flags in the ...
void pickNodeFromQueue(SchedBoundary &Zone, SchedCandidate &Cand)
void initialize(ScheduleDAGMI *Dag) override
Initialize the strategy after building the DAG for a new region.
SUnit * pickNodeBidirectional(bool &IsTopNode)
Pick the best candidate node from either the top or bottom queue.
void registerRoots() override
Notify this strategy that all roots have been released (including those that depend on EntrySU or Exi...
SUnit * pickNode(bool &IsTopNode) override
Pick the next node to schedule.
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
LLVM_ABI PostMachineSchedulerPass(const TargetMachine *TM)
LLVM_ABI ~PostMachineSchedulerPass()
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Capture a change in pressure for a single pressure set.
unsigned getPSetOrMax() const
List of PressureChanges in order of increasing, unique PSetID.
LLVM_ABI void dump(const TargetRegisterInfo &TRI) const
LLVM_ABI void addPressureChange(Register RegUnit, bool IsDec, const MachineRegisterInfo *MRI)
Add a change in pressure to the pressure diff of a given instruction.
PriorityQueue - This class behaves like std::priority_queue and provides a few additional convenience...
void clear()
clear - Erase all elements from the queue.
Helpers for implementing custom MachineSchedStrategy classes.
ArrayRef< SUnit * > elements()
LLVM_ABI void dump() const
bool isInQueue(SUnit *SU) const
std::vector< SUnit * >::iterator iterator
StringRef getName() const
iterator remove(iterator I)
Track the current register pressure at some position in the instruction stream, and remember the high...
LLVM_ABI void closeRegion()
Finalize the region boundaries and recored live ins and live outs.
void setPos(MachineBasicBlock::const_iterator Pos)
ArrayRef< unsigned > getLiveThru() const
LLVM_ABI void closeBottom()
Set the boundary for the bottom of the region and summarize live outs.
LLVM_ABI void recede(SmallVectorImpl< VRegMaskOrUnit > *LiveUses=nullptr)
Recede across the previous instruction.
RegisterPressure & getPressure()
Get the resulting register pressure over the traversed region.
LLVM_ABI void addLiveRegs(ArrayRef< VRegMaskOrUnit > Regs)
Force liveness of virtual registers or physical register units.
LLVM_ABI void recedeSkipDebugValues()
Recede until we find an instruction which is not a DebugValue.
LLVM_ABI void getMaxUpwardPressureDelta(const MachineInstr *MI, PressureDiff *PDiff, RegPressureDelta &Delta, ArrayRef< PressureChange > CriticalPSets, ArrayRef< unsigned > MaxPressureLimit)
Consider the pressure increase caused by traversing this instruction bottom-up.
LLVM_ABI void initLiveThru(const RegPressureTracker &RPTracker)
Initialize the LiveThru pressure set based on the untied defs found in RPTracker.
LLVM_ABI void dump() const
LLVM_ABI void init(const MachineFunction *mf, const RegisterClassInfo *rci, const LiveIntervals *lis, const MachineBasicBlock *mbb, MachineBasicBlock::const_iterator pos, bool TrackLaneMasks, bool TrackUntiedDefs)
Setup the RegPressureTracker.
MachineBasicBlock::const_iterator getPos() const
Get the MI position corresponding to this register pressure.
LLVM_ABI void closeTop()
Set the boundary for the top of the region and summarize live ins.
LLVM_ABI void getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, ArrayRef< PressureChange > CriticalPSets, ArrayRef< unsigned > MaxPressureLimit)
Consider the pressure increase caused by traversing this instruction top-down.
LLVM_ABI void advance()
Advance across the current instruction.
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 getUpwardPressureDelta(const MachineInstr *MI, PressureDiff &PDiff, RegPressureDelta &Delta, ArrayRef< PressureChange > CriticalPSets, ArrayRef< unsigned > MaxPressureLimit) const
This is the fast version of querying register pressure that does not directly depend on current liven...
unsigned getNumAllocatableRegs(const TargetRegisterClass *RC) const
getNumAllocatableRegs - Returns the number of actually allocatable registers in RC in the current fun...
unsigned getRegPressureSetLimit(unsigned Idx) const
Get the register unit limit for the given pressure set index.
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 ...
RegisterPassParser class - Handle the addition of new machine passes.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
LLVM_ABI void add(IntervalTy A, const unsigned CutOff=10)
Adds an interval [a, b) to the collection of the instance.
static IntervalTy getResourceIntervalBottom(unsigned C, unsigned AcquireAtCycle, unsigned ReleaseAtCycle)
These function return the interval used by a resource in bottom and top scheduling.
static LLVM_ABI bool intersects(IntervalTy A, IntervalTy B)
Checks whether intervals intersect.
std::pair< int64_t, int64_t > IntervalTy
Represents an interval of discrete integer values closed on the left and open on the right: [a,...
static IntervalTy getResourceIntervalTop(unsigned C, unsigned AcquireAtCycle, unsigned ReleaseAtCycle)
Kind getKind() const
Returns an enum value representing the kind of the dependence.
@ Anti
A register anti-dependence (aka WAR).
@ Data
Regular data dependence (aka true-dependence).
bool isWeak() const
Tests if this a weak dependence.
@ Cluster
Weak DAG edge linking a chain of clustered instrs.
@ Artificial
Arbitrary strong DAG edge (no real dependence).
@ Weak
Arbitrary weak DAG edge.
unsigned getLatency() const
Returns the latency value for this edge, which roughly means the minimum number of cycles that must e...
bool isArtificial() const
Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
Register getReg() const
Returns the register associated with this edge.
bool isArtificialDep() const
bool isCtrlDep() const
Tests if this is not an SDep::Data dependence.
Scheduling unit. This is a node in the scheduling DAG.
bool isCall
Is a function call.
unsigned TopReadyCycle
Cycle relative to start when node is ready.
unsigned NodeNum
Entry # of node in the node vector.
LLVM_ABI void biasCriticalPath()
Orders this node's predecessor edges such that the critical path edge occurs first.
bool isUnbuffered
Uses an unbuffered resource.
unsigned getHeight() const
Returns the height of this node, which is the length of the maximum path down to any node which has n...
unsigned short Latency
Node latency.
unsigned getDepth() const
Returns the depth of this node, which is the length of the maximum path up to any node which has no p...
bool isScheduled
True once scheduled.
unsigned ParentClusterIdx
The parent cluster id.
bool hasPhysRegDefs
Has physreg defs that are being used.
unsigned BotReadyCycle
Cycle relative to end when node is ready.
SmallVector< SDep, 4 > Succs
All sunit successors.
bool hasReservedResource
Uses a reserved resource.
bool isBottomReady() const
bool hasPhysRegUses
Has physreg uses.
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 getNextResourceCycleByInstance(unsigned InstanceIndex, unsigned ReleaseAtCycle, unsigned AcquireAtCycle)
Compute the next cycle at which the given processor resource unit can be scheduled.
LLVM_ABI void releasePending()
Release pending ready nodes in to the available queue.
unsigned getDependentLatency() const
unsigned getScheduledLatency() const
Get the number of latency cycles "covered" by the scheduled instructions.
LLVM_ABI void incExecutedResources(unsigned PIdx, unsigned Count)
bool isResourceLimited() const
const TargetSchedModel * SchedModel
unsigned getExecutedCount() const
Get a scaled count for the minimum execution time of the scheduled micro-ops that are ready to execut...
LLVM_ABI unsigned getLatencyStallCycles(SUnit *SU)
Get the difference between the given SUnit's ready time and the current cycle.
LLVM_ABI unsigned findMaxLatency(ArrayRef< SUnit * > ReadySUs)
LLVM_ABI void dumpReservedCycles() const
Dump the state of the information that tracks resource usage.
LLVM_ABI unsigned getOtherResourceCount(unsigned &OtherCritIdx)
LLVM_ABI void bumpNode(SUnit *SU)
Move the boundary of scheduled code by one SUnit.
unsigned getCriticalCount() const
Get the scaled count of scheduled micro-ops and resources, including executed resources.
LLVM_ABI SUnit * pickOnlyChoice()
Call this before applying any other heuristics to the Available queue.
LLVM_ABI void releaseNode(SUnit *SU, unsigned ReadyCycle, bool InPQueue, unsigned Idx=0)
Release SU to make it ready.
LLVM_ABI unsigned countResource(const MCSchedClassDesc *SC, unsigned PIdx, unsigned Cycles, unsigned ReadyCycle, unsigned StartAtCycle)
Add the given processor resource to this scheduled zone.
LLVM_ABI ~SchedBoundary()
ScheduleHazardRecognizer * HazardRec
bool isUnbufferedGroup(unsigned PIdx) const
LLVM_ABI void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel, SchedRemainder *rem)
unsigned getResourceCount(unsigned ResIdx) const
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.
LLVM_ABI std::pair< unsigned, unsigned > getNextResourceCycle(const MCSchedClassDesc *SC, unsigned PIdx, unsigned ReleaseAtCycle, unsigned AcquireAtCycle)
Compute the next cycle at which the given processor resource can be scheduled.
LLVM_ABI void dumpScheduledState() const
LLVM_ABI void removeReady(SUnit *SU)
Remove SU from the ready set for this boundary.
unsigned getZoneCritResIdx() const
unsigned getUnscheduledLatency(SUnit *SU) const
Compute the values of each DAG node for various metrics during DFS.
unsigned getNumInstrs(const SUnit *SU) const
Get the number of instructions in the given subtree and its children.
unsigned getSubtreeID(const SUnit *SU) const
Get the ID of the subtree the given DAG node belongs to.
void clear()
Clear the results.
ILPValue getILP(const SUnit *SU) const
Get the ILP value for a DAG node.
void compute(ArrayRef< SUnit > SUnits)
Compute various metrics for the DAG with given roots.
unsigned getNumSubtrees() const
The number of subtrees detected in this DAG.
unsigned getSubtreeLevel(unsigned SubtreeID) const
Get the connection level of a subtree.
void resize(unsigned NumSUnits)
Initialize the result data with the size of the DAG.
void scheduleTree(unsigned SubtreeID)
Scheduler callback to update SubtreeConnectLevels when a tree is initially scheduled.
A ScheduleDAG for scheduling lists of MachineInstr.
SmallVector< ClusterInfo > & getClusters()
Returns the array of the clusters.
virtual void finishBlock()
Cleans up after scheduling in the given block.
MachineBasicBlock::iterator end() const
Returns an iterator to the bottom of the current scheduling region.
MachineBasicBlock * BB
The block in which to insert instructions.
MachineInstr * FirstDbgValue
virtual void startBlock(MachineBasicBlock *BB)
Prepares to perform scheduling in the given block.
const TargetSchedModel * getSchedModel() const
Gets the machine model for instruction scheduling.
MachineBasicBlock::iterator RegionEnd
The end of the range to be scheduled.
const MCSchedClassDesc * getSchedClass(SUnit *SU) const
Resolves and cache a resolved scheduling class for an SUnit.
DbgValueVector DbgValues
Remember instruction that precedes DBG_VALUE.
bool addEdge(SUnit *SuccSU, const SDep &PredDep)
Add a DAG edge to the given SU with the given predecessor dependence data.
DumpDirection
The direction that should be used to dump the scheduled Sequence.
bool TrackLaneMasks
Whether lane masks should get tracked.
ClusterInfo * getCluster(unsigned Idx)
Get the specific cluster, return nullptr for InvalidClusterId.
void dumpNode(const SUnit &SU) const override
bool IsReachable(SUnit *SU, SUnit *TargetSU)
IsReachable - Checks if SU is reachable from TargetSU.
MachineBasicBlock::iterator begin() const
Returns an iterator to the top of the current scheduling region.
void buildSchedGraph(AAResults *AA, RegPressureTracker *RPTracker=nullptr, PressureDiffs *PDiffs=nullptr, LiveIntervals *LIS=nullptr, bool TrackLaneMasks=false)
Builds SUnits for the current region.
SUnit * getSUnit(MachineInstr *MI) const
Returns an existing SUnit for this MI, or nullptr.
TargetSchedModel SchedModel
TargetSchedModel provides an interface to the machine model.
bool canAddEdge(SUnit *SuccSU, SUnit *PredSU)
True if an edge can be added from PredSU to SuccSU without creating a cycle.
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs)
Initialize the DAG and common scheduler state for a new scheduling region.
void dump() const override
void setDumpDirection(DumpDirection D)
ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules machine instructions while...
void scheduleMI(SUnit *SU, bool IsTopNode)
Move an instruction and update register pressure.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
VReg2SUnitMultiMap VRegUses
Maps vregs to the SUnits of their uses in the current scheduling region.
void computeDFSResult()
Compute a DFSResult after DAG building is complete, and before any queue comparisons.
PressureDiff & getPressureDiff(const SUnit *SU)
SchedDFSResult * DFSResult
Information about DAG subtrees.
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
void initQueues(ArrayRef< SUnit * > TopRoots, ArrayRef< SUnit * > BotRoots)
Release ExitSU predecessors and setup scheduler queues.
bool ShouldTrackLaneMasks
RegPressureTracker BotRPTracker
void buildDAGWithRegPressure()
Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking enabled.
std::vector< PressureChange > RegionCriticalPSets
List of pressure sets that exceed the target's pressure limit before scheduling, listed in increasing...
void updateScheduledPressure(const SUnit *SU, const std::vector< unsigned > &NewMaxPressure)
PressureDiffs SUPressureDiffs
unsigned computeCyclicCriticalPath()
Compute the cyclic critical path through the DAG.
void updatePressureDiffs(ArrayRef< VRegMaskOrUnit > LiveUses)
Update the PressureDiff array for liveness after scheduling this instruction.
void collectVRegUses(SUnit &SU)
RegisterClassInfo * RegClassInfo
const SchedDFSResult * getDFSResult() const
Return a non-null DFS result if the scheduling strategy initialized it.
RegPressureTracker RPTracker
bool ShouldTrackPressure
Register pressure in this region computed by initRegPressure.
~ScheduleDAGMILive() override
void dump() const override
BitVector & getScheduledTrees()
MachineBasicBlock::iterator LiveRegionEnd
RegPressureTracker TopRPTracker
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
void dumpSchedule() const
dump the scheduled Sequence.
std::unique_ptr< MachineSchedStrategy > SchedImpl
void startBlock(MachineBasicBlock *bb) override
Prepares to perform scheduling in the given block.
void releasePred(SUnit *SU, SDep *PredEdge)
ReleasePred - Decrement the NumSuccsLeft count of a predecessor.
void initQueues(ArrayRef< SUnit * > TopRoots, ArrayRef< SUnit * > BotRoots)
Release ExitSU predecessors and setup scheduler queues.
void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos)
Change the position of an instruction within the basic block and update live ranges and region bounda...
void releasePredecessors(SUnit *SU)
releasePredecessors - Call releasePred on each of SU's predecessors.
void postProcessDAG()
Apply each ScheduleDAGMutation step in order.
void dumpScheduleTraceTopDown() const
Print execution trace of the schedule top-down or bottom-up.
MachineBasicBlock::iterator top() const
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
void findRootsAndBiasEdges(SmallVectorImpl< SUnit * > &TopRoots, SmallVectorImpl< SUnit * > &BotRoots)
MachineBasicBlock::iterator bottom() const
MachineBasicBlock::iterator CurrentBottom
The bottom of the unscheduled zone.
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
LiveIntervals * getLIS() const
void viewGraph() override
Out-of-line implementation with no arguments is handy for gdb.
void releaseSucc(SUnit *SU, SDep *SuccEdge)
ReleaseSucc - Decrement the NumPredsLeft count of a successor.
void dumpScheduleTraceBottomUp() const
~ScheduleDAGMI() override
void finishBlock() override
Cleans up after scheduling in the given block.
void updateQueues(SUnit *SU, bool IsTopNode)
Update scheduler DAG and queues after scheduling an instruction.
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
MachineBasicBlock::iterator CurrentTop
The top of the unscheduled zone.
void releaseSuccessors(SUnit *SU)
releaseSuccessors - Call releaseSucc on each of SU's successors.
std::vector< std::unique_ptr< ScheduleDAGMutation > > Mutations
Ordered list of DAG postprocessing steps.
Mutate the DAG as a postpass after normal DAG building.
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.
SUnit EntrySU
Special node for the region entry.
MachineFunction & MF
Machine function.
void dumpNodeAll(const SUnit &SU) const
SUnit ExitSU
Special node for the region exit.
virtual void RecedeCycle()
RecedeCycle - This callback is invoked whenever the next bottom-up instruction to be scheduled cannot...
virtual void Reset()
Reset - This callback is invoked when a new block of instructions is about to be schedule.
virtual void EmitInstruction(SUnit *)
EmitInstruction - This callback is invoked when an instruction is emitted, to advance the hazard stat...
virtual void AdvanceCycle()
AdvanceCycle - This callback is invoked whenever the next top-down instruction to be scheduled cannot...
virtual HazardType getHazardType(SUnit *, int Stalls=0)
getHazardType - Return the hazard type of emitting this node.
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.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
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)
std::reverse_iterator< const_iterator > const_reverse_iterator
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
iterator find(const KeyT &Key)
Find an element by its key.
void clear()
Clears the set.
iterator end()
Returns an iterator past this container.
iterator insert(const ValueT &Val)
Insert a new element at the tail of the subset list.
iterator_base< SparseMultiSet * > iterator
void setUniverse(unsigned U)
Set the universe size which determines the largest key the set can hold.
Information about stack frame layout on the target.
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
TargetInstrInfo - Interface to description of machine instruction set.
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
Target-Independent Code Generator Pass Configuration Options.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const char * getRegPressureSetName(unsigned Idx) const =0
Get the name of this register unit pressure set.
Provide an instruction scheduling machine model to CodeGen passes.
const char * getResourceName(unsigned PIdx) const
LLVM_ABI bool mustEndGroup(const MachineInstr *MI, const MCSchedClassDesc *SC=nullptr) const
Return true if current group must end.
unsigned getIssueWidth() const
Maximum number of micro-ops that may be scheduled per cycle.
unsigned getMicroOpFactor() const
Multiply number of micro-ops by this factor to normalize it relative to other resources.
ProcResIter getWriteProcResEnd(const MCSchedClassDesc *SC) const
LLVM_ABI bool hasInstrSchedModel() const
Return true if this machine model includes an instruction-level scheduling model.
LLVM_ABI bool mustBeginGroup(const MachineInstr *MI, const MCSchedClassDesc *SC=nullptr) const
Return true if new group must begin.
unsigned getLatencyFactor() const
Multiply cycle count by this factor to normalize it relative to other resources.
unsigned getResourceFactor(unsigned ResIdx) const
Multiply the number of units consumed for a resource by this factor to normalize it relative to other...
unsigned getMicroOpBufferSize() const
Number of micro-ops that may be buffered for OOO execution.
LLVM_ABI unsigned getNumMicroOps(const MachineInstr *MI, const MCSchedClassDesc *SC=nullptr) const
Return the number of issue slots required for this MI.
const MCProcResourceDesc * getProcResource(unsigned PIdx) const
Get a processor resource by ID for convenience.
unsigned getNumProcResourceKinds() const
Get the number of kinds of resources for this target.
const InstrItineraryData * getInstrItineraries() const
LLVM_ABI bool enableIntervals() const
ProcResIter getWriteProcResBegin(const MCSchedClassDesc *SC) const
virtual void overridePostRASchedPolicy(MachineSchedPolicy &Policy, const SchedRegion &Region) const
Override generic post-ra scheduling policy within a region.
virtual void overrideSchedPolicy(MachineSchedPolicy &Policy, const SchedRegion &Region) const
Override generic scheduling policy within a region.
virtual bool enableMachineScheduler() const
True if the subtarget should run MachineScheduler after aggressive coalescing.
virtual bool enablePostRAMachineScheduler() const
True if the subtarget should run a machine scheduler after register allocation.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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...
int getNumOccurrences() const
Base class for the machine scheduler classes.
void scheduleRegions(ScheduleDAGInstrs &Scheduler, bool FixKillFlags)
Main driver for both MachineScheduler and PostMachineScheduler.
Impl class for MachineScheduler.
void setMFAM(MachineFunctionAnalysisManager *MFAM)
void setLegacyPass(MachineFunctionPass *P)
bool run(MachineFunction &MF, const TargetMachine &TM, const RequiredAnalyses &Analyses)
ScheduleDAGInstrs * createMachineScheduler()
Instantiate a ScheduleDAGInstrs that will be owned by the caller.
Impl class for PostMachineScheduler.
bool run(MachineFunction &Func, const TargetMachine &TM, const RequiredAnalyses &Analyses)
void setMFAM(MachineFunctionAnalysisManager *MFAM)
PostMachineSchedulerImpl()
ScheduleDAGInstrs * createPostMachineScheduler()
Instantiate a ScheduleDAGInstrs for PostRA scheduling that will be owned by the caller.
void setLegacyPass(MachineFunctionPass *P)
A raw_ostream that writes to an std::string.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI StringRef getColorString(unsigned NodeNumber)
Get a color string for this node number.
void apply(Opt *O, const Mod &M, const Mods &... Ms)
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
ScheduleDAGMILive * createSchedLive(MachineSchedContext *C)
Create the standard converging machine scheduler.
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
cl::opt< bool > PrintDAGs
LLVM_ABI unsigned getWeakLeft(const SUnit *SU, bool isTop)
FormattedString right_justify(StringRef Str, unsigned Width)
right_justify - add spaces before string so total output is Width characters.
static cl::opt< MISched::Direction > PostRADirection("misched-postra-direction", cl::Hidden, cl::desc("Post reg-alloc list scheduling direction"), cl::init(MISched::Unspecified), cl::values(clEnumValN(MISched::TopDown, "topdown", "Force top-down post reg-alloc list scheduling"), clEnumValN(MISched::BottomUp, "bottomup", "Force bottom-up post reg-alloc list scheduling"), clEnumValN(MISched::Bidirectional, "bidirectional", "Force bidirectional post reg-alloc list scheduling")))
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Printable PrintLaneMask(LaneBitmask LaneMask)
Create Printable object to print LaneBitmasks on a raw_ostream.
cl::opt< bool > MISchedDumpReservedCycles("misched-dump-reserved-cycles", cl::Hidden, cl::init(false), cl::desc("Dump resource usage at schedule boundary."))
LLVM_ABI cl::opt< bool > VerifyScheduling
LLVM_ABI char & MachineSchedulerID
MachineScheduler - This pass schedules machine instructions.
LLVM_ABI char & PostMachineSchedulerID
PostMachineScheduler - This pass schedules machine instructions postRA.
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
cl::opt< bool > ViewMISchedDAGs
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)
ScheduleDAGMI * createSchedPostRA(MachineSchedContext *C)
Create a generic scheduler with no vreg liveness or DAG mutation passes.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI Printable printVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *TRI)
Create Printable object to print virtual registers and physical registers on a raw_ostream.
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createStoreClusterDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, bool ReorderWhileClustering=false)
If ReorderWhileClustering is set to true, no attempt will be made to reduce reordering due to store c...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static cl::opt< bool > DumpCriticalPathLength("misched-dcpl", cl::Hidden, cl::desc("Print critical path length to stdout"))
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
LLVM_ABI bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, SchedBoundary &Zone)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
constexpr unsigned InvalidClusterId
FormattedString left_justify(StringRef Str, unsigned Width)
left_justify - append spaces after string so total output is Width characters.
bool isTheSameCluster(unsigned A, unsigned B)
Return whether the input cluster ID's are the same and valid.
LLVM_ABI cl::opt< MISched::Direction > PreRADirection
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createLoadClusterDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, bool ReorderWhileClustering=false)
If ReorderWhileClustering is set to true, no attempt will be made to reduce reordering due to store c...
LLVM_ABI bool tryGreater(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames=false, const Twine &Title="", GraphProgram::Name Program=GraphProgram::DOT)
ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, then cleanup.
LLVM_ABI void initializeMachineSchedulerLegacyPass(PassRegistry &)
LLVM_ABI void dumpRegSetPressure(ArrayRef< unsigned > SetPressure, const TargetRegisterInfo *TRI)
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 std::unique_ptr< ScheduleDAGMutation > createCopyConstrainDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
LLVM_ABI void initializePostMachineSchedulerLegacyPass(PassRegistry &)
cl::opt< bool > MischedDetailResourceBooking("misched-detail-resource-booking", cl::Hidden, cl::init(false), cl::desc("Show details of invoking getNextResoufceCycle."))
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.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static std::string getNodeDescription(const SUnit *SU, const ScheduleDAG *G)
static std::string getEdgeAttributes(const SUnit *Node, SUnitIterator EI, const ScheduleDAG *Graph)
If you want to override the dot attributes printed for a particular edge, override this method.
static std::string getGraphName(const ScheduleDAG *G)
static std::string getNodeLabel(const SUnit *SU, const ScheduleDAG *G)
static bool isNodeHidden(const SUnit *Node, const ScheduleDAG *G)
DOTGraphTraits(bool isSimple=false)
static std::string getNodeAttributes(const SUnit *N, const ScheduleDAG *G)
static bool renderGraphFromBottomUp()
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
DefaultDOTGraphTraits - This class provides the default implementations of all of the DOTGraphTraits ...
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
static constexpr LaneBitmask getNone()
const unsigned * SubUnitsIdxBegin
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
RegisterClassInfo * RegClassInfo
virtual ~MachineSchedContext()
bool DisableLatencyHeuristic
bool ShouldTrackLaneMasks
Track LaneMasks to allow reordering of independent subregister writes of the same vreg.
PressureChange CriticalMax
PressureChange CurrentMax
RegisterPressure computed within a region of instructions delimited by TopPos and BottomPos.
SmallVector< VRegMaskOrUnit, 8 > LiveOutRegs
SmallVector< VRegMaskOrUnit, 8 > LiveInRegs
List of live in virtual registers or physical register units.
std::vector< unsigned > MaxSetPressure
Map of max reg pressure indexed by pressure set ID, not class ID.
A region of an MBB for scheduling.
Summarize the unscheduled region.
LLVM_ABI void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel)
SmallVector< unsigned, 16 > RemainingCounts
bool IsAcyclicLatencyLimited
An individual mapping from virtual register number to SUnit.
MachineDominatorTree & MDT