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");
181 cl::desc(
"Pre reg-alloc list scheduling direction"),
185 "Force top-down pre reg-alloc list scheduling"),
187 "Force bottom-up pre reg-alloc list scheduling"),
189 "Force bidirectional pre reg-alloc list scheduling")));
193 cl::desc(
"Post reg-alloc list scheduling direction"),
197 "Force top-down post reg-alloc list scheduling"),
199 "Force bottom-up post reg-alloc list scheduling"),
201 "Force bidirectional post reg-alloc list scheduling")));
205 cl::desc(
"Print critical path length to stdout"));
209 cl::desc(
"Set the post-RA MISched anti-dependency break mode"),
210 cl::init(TargetSubtargetInfo::ANTIDEP_NONE),
212 "No anti-dependency breaking"),
213 clEnumValN(TargetSubtargetInfo::ANTIDEP_CRITICAL,
"critical",
214 "Break critical-path anti-dependencies"),
215 clEnumValN(TargetSubtargetInfo::ANTIDEP_ALL,
"all",
216 "Break all anti-dependencies")));
220 cl::desc(
"Verify machine instrs before and after machine scheduling"));
231 cl::desc(
"Pop up a window to show MISched dags after they are processed"));
236 cl::desc(
"Dump resource usage at schedule boundary."));
239 cl::desc(
"Show details of invoking getNextResoufceCycle."));
244#ifdef LLVM_ENABLE_DUMP
253 cl::desc(
"Hide nodes with more predecessor/successor than cutoff"));
259 cl::desc(
"Only schedule this function"));
261 cl::desc(
"Only schedule this MBB#"));
276 cl::desc(
"Enable memop clustering."),
280 cl::desc(
"Switch to fast cluster algorithm with the lost "
281 "of some fusion opportunities"),
285 cl::desc(
"The threshold for fast cluster"),
288#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
291 cl::desc(
"Dump resource usage at schedule boundary."));
294 cl::desc(
"Set width of the columns with "
295 "the resources and schedule units"),
299 cl::desc(
"Set width of the columns showing resource booking."),
303 cl::desc(
"Sort the resources printed in the dump trace"));
314void MachineSchedStrategy::anchor() {}
316void ScheduleDAGMutation::anchor() {}
356 const RequiredAnalyses &Analyses);
384 const RequiredAnalyses &Analyses);
409 const RequiredAnalyses &Analyses);
426 MachineSchedulerImpl Impl;
429 MachineSchedulerLegacy();
430 void getAnalysisUsage(AnalysisUsage &AU)
const override;
438 SSAMachineSchedulerImpl Impl;
441 SSAMachineSchedulerLegacy();
442 void getAnalysisUsage(AnalysisUsage &AU)
const override;
450 PostMachineSchedulerImpl Impl;
453 PostMachineSchedulerLegacy();
454 void getAnalysisUsage(AnalysisUsage &AU)
const override;
462char MachineSchedulerLegacy::ID = 0;
467 "Machine Instruction Scheduler",
false,
false)
474 "Machine Instruction Scheduler",
false,
false)
478void MachineSchedulerLegacy::getAnalysisUsage(
AnalysisUsage &AU)
const {
491char SSAMachineSchedulerLegacy::ID = 0;
496 "SSA Machine Instruction Scheduler",
false,
false)
503 "SSA Machine Instruction Scheduler",
false,
false)
505SSAMachineSchedulerLegacy::SSAMachineSchedulerLegacy()
510void SSAMachineSchedulerLegacy::getAnalysisUsage(
AnalysisUsage &AU)
const {
523char PostMachineSchedulerLegacy::ID = 0;
528 "PostRA Machine Instruction Scheduler",
false,
false)
535PostMachineSchedulerLegacy::PostMachineSchedulerLegacy()
538void PostMachineSchedulerLegacy::getAnalysisUsage(
AnalysisUsage &AU)
const {
561 cl::desc(
"Machine instruction scheduler to use"));
569 cl::desc(
"Enable the machine instruction scheduling pass."),
cl::init(
true),
573 "enable-ssa-misched",
574 cl::desc(
"Enable the machine instruction scheduling pass in SSA."),
578 "enable-post-misched",
579 cl::desc(
"Enable the post-ra machine instruction scheduling pass."),
586 assert(
I != Beg &&
"reached the top of the region, cannot decrement");
588 if (!
I->isDebugOrPseudoInstr())
607 for(;
I !=
End; ++
I) {
608 if (!
I->isDebugOrPseudoInstr())
650 const char *MSchedBanner =
"Before machine scheduling.";
652 MF->verify(P, MSchedBanner, &
errs());
654 MF->verify(*MFAM, MSchedBanner, &
errs());
664 const char *MSchedBanner =
"After machine scheduling.";
666 MF->verify(P, MSchedBanner, &
errs());
668 MF->verify(*MFAM, MSchedBanner, &
errs());
697 const char *MSchedBanner =
"Before machine scheduling.";
699 MF->verify(P, MSchedBanner, &
errs());
701 MF->verify(*MFAM, MSchedBanner, &
errs());
712 const char *MSchedBanner =
"After machine scheduling.";
714 MF->verify(P, MSchedBanner, &
errs());
716 MF->verify(*MFAM, MSchedBanner, &
errs());
744 const char *PostMSchedBanner =
"Before post machine scheduling.";
746 MF->verify(P, PostMSchedBanner, &
errs());
748 MF->verify(*MFAM, PostMSchedBanner, &
errs());
757 const char *PostMSchedBanner =
"After post machine scheduling.";
759 MF->verify(P, PostMSchedBanner, &
errs());
761 MF->verify(*MFAM, PostMSchedBanner, &
errs());
782bool MachineSchedulerLegacy::runOnMachineFunction(
MachineFunction &MF) {
795 auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
796 auto &TM = getAnalysis<TargetPassConfig>().getTM<
TargetMachine>();
797 auto &
AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
798 auto &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
800 getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
801 auto &MBFI = getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
803 Impl.setLegacyPass(
this);
804 return Impl.run(MF, TM, {MLI,
AA, LIS, RegClassInfo, MBFI});
807bool SSAMachineSchedulerLegacy::runOnMachineFunction(
MachineFunction &MF) {
818 auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
819 auto &TM = getAnalysis<TargetPassConfig>().getTM<
TargetMachine>();
820 auto &
AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
821 auto &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
823 getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
824 auto &MBFI = getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
826 Impl.setLegacyPass(
this);
827 return Impl.run(MF, TM, {MLI,
AA, LIS, RegClassInfo, MBFI});
831 : Impl(
std::make_unique<MachineSchedulerImpl>()), TM(TM) {}
837 : Impl(
std::make_unique<SSAMachineSchedulerImpl>()), TM(TM) {}
843 : Impl(
std::make_unique<PostMachineSchedulerImpl>()), TM(TM) {}
867 Impl->setMFAM(&MFAM);
868 bool Changed = Impl->run(MF, *TM, {MLI,
AA, LIS, RegClassInfo, MBFI});
874 .preserve<SlotIndexesAnalysis>()
897 Impl->setMFAM(&MFAM);
898 bool Changed = Impl->run(MF, *TM, {MLI,
AA, LIS, RegClassInfo, MBFI});
907bool PostMachineSchedulerLegacy::runOnMachineFunction(
MachineFunction &MF) {
919 auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
920 auto &TM = getAnalysis<TargetPassConfig>().getTM<
TargetMachine>();
921 auto &
AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
922 auto &RCI = getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
923 Impl.setLegacyPass(
this);
924 return Impl.run(MF, TM, {MLI,
AA, RCI});
944 Impl->setMFAM(&MFAM);
945 bool Changed = Impl->run(MF, *TM, {MLI,
AA, RCI});
967 return MI->isCall() ||
TII->isSchedulingBoundary(*
MI,
MBB, *MF) ||
968 MI->isFakeUse() ||
MI->isPHI();
976 bool RegionsTopDown) {
982 RegionEnd !=
MBB->begin(); RegionEnd =
I) {
985 if (RegionEnd !=
MBB->end() ||
992 unsigned NumRegionInstrs = 0;
994 for (;
I !=
MBB->begin(); --
I) {
998 if (!
MI.isDebugOrPseudoInstr()) {
1007 if (NumRegionInstrs != 0)
1012 std::reverse(Regions.
begin(), Regions.
end());
1017 bool FixKillFlags) {
1050 bool ScheduleSingleMI =
Scheduler.shouldScheduleSingleMIRegions();
1054 unsigned NumRegionInstrs = R.NumRegionInstrs;
1058 Scheduler.enterRegion(&*
MBB,
I, RegionEnd, NumRegionInstrs);
1062 if (
I == RegionEnd || (!ScheduleSingleMI &&
I == std::prev(RegionEnd))) {
1068 auto DumpRegionHeader = [&] {
1069 dbgs() <<
"Current Schedule Region\n";
1071 <<
MBB->getName() <<
"\n From: " << *
I <<
" To: ";
1072 if (RegionEnd !=
MBB->end())
1073 dbgs() << *RegionEnd;
1076 dbgs() <<
" RegionInstrs: " << NumRegionInstrs <<
'\n';
1084 errs() <<
":%bb. " <<
MBB->getNumber();
1085 errs() <<
" " <<
MBB->getName() <<
" \n";
1105#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1107 dbgs() <<
"Queue " << Name <<
": ";
1108 for (
const SUnit *SU : Queue)
1109 dbgs() << *SU <<
" ";
1122 if (AntiDepMode == TargetSubtargetInfo::ANTIDEP_NONE)
1125 assert(
C->MF->getRegInfo().tracksLiveness() &&
1126 "Live-ins must be accurate for anti-dependency breaking");
1128 "Register class info is required for anti-dependency breaking");
1129 if (AntiDepMode == TargetSubtargetInfo::ANTIDEP_ALL) {
1131 C->MF->getSubtarget().getCriticalPathRCs(CriticalPathRCs);
1135 assert(AntiDepMode == TargetSubtargetInfo::ANTIDEP_CRITICAL &&
1136 "Unexpected anti-dependency break mode");
1143 for (
auto I = From;
I != To;) {
1145 --BoundaryScanIndex;
1146 if (!
MI.isDebugOrPseudoInstr())
1147 Breaker->Observe(
MI, BoundaryScanIndex, RegionEndIndex);
1149 BoundaryScanIndex -=
MI.getBundleSize();
1156 Breaker->StartBlock(
MBB);
1157 BoundaryScanPos =
MBB->end();
1158 BoundaryScanIndex =
MBB->size();
1159 RegionEndIndex = BoundaryScanIndex;
1165 Breaker->FinishBlock();
1174 scanRangeBackwards(BoundaryScanPos,
End);
1175 RegionEndIndex = BoundaryScanIndex;
1176 RegionProcessed =
false;
1184 BoundaryScanPos = Begin;
1185 if (RegionProcessed) {
1186 BoundaryScanIndex -= std::distance(Begin,
End);
1190 scanRangeBackwards(
End, Begin);
1200 RegionProcessed =
true;
1201 return Breaker->BreakAntiDependencies(SUnits, Begin,
End, RegionEndIndex,
1215 if (SuccEdge->
isWeak()) {
1221 dbgs() <<
"*** Scheduling failed! ***\n";
1223 dbgs() <<
" has been released too many times!\n";
1250 if (PredEdge->
isWeak()) {
1256 dbgs() <<
"*** Scheduling failed! ***\n";
1258 dbgs() <<
" has been released too many times!\n";
1297 unsigned regioninstrs) {
1307 else if (
SchedImpl->getPolicy().OnlyBottomUp)
1328 BB->splice(InsertPos,
BB,
MI);
1332 LIS->handleMove(*
MI,
true);
1340#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
1345 ++NumInstrsScheduled;
1385 bool IsTopNode =
false;
1390 LLVM_DEBUG(
dbgs() <<
"** ScheduleDAGMI::schedule picking next node\n");
1407 if (&*priorII ==
MI)
1429 dbgs() <<
"*** Final schedule for "
1446 assert(!SU.isBoundaryNode() &&
"Boundary node should not be in SUnits");
1449 SU.biasCriticalPath();
1452 if (!SU.NumPredsLeft)
1455 if (!SU.NumSuccsLeft)
1458 ExitSU.biasCriticalPath();
1468 for (
SUnit *SU : TopRoots)
1507 for (std::vector<std::pair<MachineInstr *, MachineInstr *>>
::iterator
1509 std::pair<MachineInstr *, MachineInstr *>
P = *std::prev(DI);
1520#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1532 dbgs() <<
" * Schedule table (TopDown):\n";
1550 for (
unsigned C = FirstCycle;
C <= LastCycle; ++
C)
1557 dbgs() <<
"Missing SUnit\n";
1560 std::string NodeName;
1563 unsigned C = FirstCycle;
1564 for (;
C <= LastCycle; ++
C) {
1582 return std::tie(LHS.AcquireAtCycle, LHS.ReleaseAtCycle) <
1583 std::tie(RHS.AcquireAtCycle, RHS.ReleaseAtCycle);
1587 const std::string ResName =
1588 SchedModel.getResourceName(PI.ProcResourceIdx);
1593 for (
unsigned I = 0, E = PI.ReleaseAtCycle - PI.AcquireAtCycle;
I != E;
1596 while (
C++ <= LastCycle)
1613 dbgs() <<
" * Schedule table (BottomUp):\n";
1626 if ((
int)SU->
BotReadyCycle - PI->ReleaseAtCycle + 1 < LastCycle)
1627 LastCycle = (int)SU->
BotReadyCycle - PI->ReleaseAtCycle + 1;
1632 for (
int C = FirstCycle;
C >= LastCycle; --
C)
1639 dbgs() <<
"Missing SUnit\n";
1642 std::string NodeName;
1646 for (;
C >= LastCycle; --
C) {
1663 return std::tie(LHS.AcquireAtCycle, LHS.ReleaseAtCycle) <
1664 std::tie(RHS.AcquireAtCycle, RHS.ReleaseAtCycle);
1668 const std::string ResName =
1669 SchedModel.getResourceName(PI.ProcResourceIdx);
1674 for (
unsigned I = 0, E = PI.ReleaseAtCycle - PI.AcquireAtCycle;
I != E;
1677 while (
C-- >= LastCycle)
1686#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1694 dbgs() <<
"* Schedule table (Bidirectional): not implemented\n";
1696 dbgs() <<
"* Schedule table: DumpDirection not set.\n";
1704 dbgs() <<
"Missing SUnit\n";
1729 if (!Reg.isVirtual())
1734 bool FoundDef =
false;
1736 if (MO2.getReg() == Reg && !MO2.isDead()) {
1747 for (; UI !=
VRegUses.end(); ++UI) {
1763 unsigned regioninstrs)
1777 "ShouldTrackLaneMasks requires ShouldTrackPressure");
1828 dbgs() <<
"Bottom Pressure: ";
1834 "Can't find the region bottom");
1842 unsigned Limit =
RegClassInfo->getRegPressureSetLimit(i);
1851 dbgs() <<
"Excess PSets: ";
1853 dbgs() <<
TRI->getRegPressureSetName(RCPS.getPSet()) <<
" ";
1861 const std::vector<unsigned> &NewMaxPressure) {
1867 unsigned ID = PC.getPSet();
1872 && NewMaxPressure[ID] <= (
unsigned)std::numeric_limits<int16_t>::max())
1875 unsigned Limit =
RegClassInfo->getRegPressureSetLimit(ID);
1876 if (NewMaxPressure[ID] >= Limit - 2) {
1878 << NewMaxPressure[ID]
1879 << ((NewMaxPressure[ID] > Limit) ?
" > " :
" <= ")
1891 if (!
P.VRegOrUnit.isVirtualReg())
1893 Register Reg =
P.VRegOrUnit.asVirtualReg();
1900 bool Decrement =
P.LaneMask.any();
1904 SUnit &SU = *V2SU.SU;
1914 <<
" UpdateRegPressure: " << SU <<
" "
1937 assert(VNI &&
"No live value at use.");
1940 SUnit *SU = V2SU.SU;
1964#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1965 if (
EntrySU.getInstr() !=
nullptr)
1970 dbgs() <<
" Pressure Diff : ";
1973 dbgs() <<
" Single Issue : ";
1974 if (
SchedModel.mustBeginGroup(SU.getInstr()) &&
1981 if (
ExitSU.getInstr() !=
nullptr)
2017 bool IsTopNode =
false;
2022 LLVM_DEBUG(
dbgs() <<
"** ScheduleDAGMILive::schedule picking next node\n");
2031 unsigned SubtreeID =
DFSResult->getSubtreeID(SU);
2049 dbgs() <<
"*** Final schedule for "
2118 if (!
BB->isSuccessor(
BB))
2121 unsigned MaxCyclicLatency = 0;
2124 if (!
P.VRegOrUnit.isVirtualReg())
2126 Register Reg =
P.VRegOrUnit.asVirtualReg();
2137 unsigned LiveOutHeight = DefSU->
getHeight();
2142 SUnit *SU = V2SU.SU;
2154 unsigned CyclicLatency = 0;
2156 CyclicLatency = LiveOutDepth - SU->
getDepth();
2159 if (LiveInHeight > LiveOutHeight) {
2160 if (LiveInHeight - LiveOutHeight < CyclicLatency)
2161 CyclicLatency = LiveInHeight - LiveOutHeight;
2165 LLVM_DEBUG(
dbgs() <<
"Cyclic Path: " << *DefSU <<
" -> " << *SU <<
" = "
2166 << CyclicLatency <<
"c\n");
2167 if (CyclicLatency > MaxCyclicLatency)
2168 MaxCyclicLatency = CyclicLatency;
2171 LLVM_DEBUG(
dbgs() <<
"Cyclic Critical Path: " << MaxCyclicLatency <<
"c\n");
2172 return MaxCyclicLatency;
2224 if (&*priorII ==
MI)
2275 bool OffsetIsScalable;
2279 : SU(SU), BaseOps(BaseOps),
Offset(
Offset), Width(Width),
2280 OffsetIsScalable(OffsetIsScalable) {}
2284 if (
A->getType() !=
B->getType())
2285 return A->getType() <
B->getType();
2287 return A->getReg() <
B->getReg();
2299 if (AIsFixed != BIsFixed)
2300 return StackGrowsDown ? !AIsFixed : AIsFixed;
2308 if (AOffset != BOffset)
2309 return AOffset < BOffset;
2311 return StackGrowsDown ?
A->getIndex() >
B->getIndex()
2312 :
A->getIndex() <
B->getIndex();
2322 if (std::lexicographical_compare(BaseOps.
begin(), BaseOps.
end(),
2323 RHS.BaseOps.begin(),
RHS.BaseOps.end(),
2326 if (std::lexicographical_compare(
RHS.BaseOps.begin(),
RHS.BaseOps.end(),
2327 BaseOps.
begin(), BaseOps.
end(), Compare))
2335 const TargetInstrInfo *
TII;
2337 bool ReorderWhileClustering;
2340 BaseMemOpClusterMutation(
const TargetInstrInfo *tii,
bool IsLoad,
2341 bool ReorderWhileClustering)
2342 :
TII(tii), IsLoad(IsLoad),
2343 ReorderWhileClustering(ReorderWhileClustering) {}
2345 void apply(ScheduleDAGInstrs *DAGInstrs)
override;
2349 ScheduleDAGInstrs *DAG);
2350 void collectMemOpRecords(std::vector<SUnit> &SUnits,
2351 SmallVectorImpl<MemOpInfo> &MemOpRecords);
2356class StoreClusterMutation :
public BaseMemOpClusterMutation {
2358 StoreClusterMutation(
const TargetInstrInfo *tii,
bool ReorderWhileClustering)
2359 : BaseMemOpClusterMutation(tii,
false, ReorderWhileClustering) {}
2362class LoadClusterMutation :
public BaseMemOpClusterMutation {
2364 LoadClusterMutation(
const TargetInstrInfo *tii,
bool ReorderWhileClustering)
2365 : BaseMemOpClusterMutation(tii,
true, ReorderWhileClustering) {}
2370std::unique_ptr<ScheduleDAGMutation>
2372 bool ReorderWhileClustering) {
2374 TII, ReorderWhileClustering)
2378std::unique_ptr<ScheduleDAGMutation>
2380 bool ReorderWhileClustering) {
2382 TII, ReorderWhileClustering)
2391void BaseMemOpClusterMutation::clusterNeighboringMemOps(
2400 for (
unsigned Idx = 0,
End = MemOpRecords.
size(); Idx < (
End - 1); ++Idx) {
2402 auto MemOpa = MemOpRecords[Idx];
2405 unsigned NextIdx = Idx + 1;
2406 for (; NextIdx <
End; ++NextIdx)
2409 if (!SUnit2ClusterInfo.
count(MemOpRecords[NextIdx].SU->NodeNum) &&
2411 (!DAG->
IsReachable(MemOpRecords[NextIdx].SU, MemOpa.SU) &&
2412 !DAG->
IsReachable(MemOpa.SU, MemOpRecords[NextIdx].SU))))
2417 auto MemOpb = MemOpRecords[NextIdx];
2418 unsigned ClusterLength = 2;
2419 unsigned CurrentClusterBytes = MemOpa.Width.getValue().getKnownMinValue() +
2420 MemOpb.Width.getValue().getKnownMinValue();
2421 auto It = SUnit2ClusterInfo.
find(MemOpa.SU->NodeNum);
2422 if (It != SUnit2ClusterInfo.
end()) {
2423 const auto &[Len, Bytes] = It->second;
2424 ClusterLength = Len + 1;
2425 CurrentClusterBytes = Bytes + MemOpb.Width.getValue().getKnownMinValue();
2428 if (!
TII->shouldClusterMemOps(MemOpa.BaseOps, MemOpa.Offset,
2429 MemOpa.OffsetIsScalable, MemOpb.BaseOps,
2430 MemOpb.Offset, MemOpb.OffsetIsScalable,
2431 ClusterLength, CurrentClusterBytes))
2434 SUnit *SUa = MemOpa.SU;
2435 SUnit *SUb = MemOpb.SU;
2445 LLVM_DEBUG(
dbgs() <<
"Cluster ld/st " << *SUa <<
" - " << *SUb <<
"\n");
2475 SUnit2ClusterInfo[MemOpb.SU->NodeNum] = {ClusterLength,
2476 CurrentClusterBytes};
2479 <<
", Curr cluster bytes: " << CurrentClusterBytes
2490 unsigned ClusterIdx = AllClusters.size();
2492 MemberI->ParentClusterIdx = ClusterIdx;
2495 AllClusters.push_back(Group);
2499void BaseMemOpClusterMutation::collectMemOpRecords(
2501 for (
auto &SU : SUnits) {
2509 bool OffsetIsScalable;
2512 OffsetIsScalable, Width)) {
2517 MemOpInfo(&SU, BaseOps,
Offset, OffsetIsScalable, Width));
2520 <<
Offset <<
", OffsetIsScalable: " << OffsetIsScalable
2521 <<
", Width: " << Width <<
"\n");
2524 for (
const auto *
Op : BaseOps)
2530bool BaseMemOpClusterMutation::groupMemOps(
2537 for (
const auto &
MemOp : MemOps) {
2538 unsigned ChainPredID = DAG->
SUnits.size();
2540 for (
const SDep &Pred :
MemOp.SU->Preds) {
2564 collectMemOpRecords(DAG->
SUnits, MemOpRecords);
2566 if (MemOpRecords.
size() < 2)
2573 bool FastCluster = groupMemOps(MemOpRecords, DAG,
Groups);
2575 for (
auto &Group :
Groups) {
2581 clusterNeighboringMemOps(Group.second, FastCluster, DAG);
2596 SlotIndex RegionBeginIdx;
2600 SlotIndex RegionEndIdx;
2603 CopyConstrain(
const TargetInstrInfo *) {}
2605 void apply(ScheduleDAGInstrs *DAGInstrs)
override;
2608 void constrainLocalCopy(SUnit *CopySU, ScheduleDAGMILive *DAG);
2613std::unique_ptr<ScheduleDAGMutation>
2615 return std::make_unique<CopyConstrain>(
TII);
2658 unsigned LocalReg = SrcReg;
2659 unsigned GlobalReg = DstReg;
2661 if (!LocalLI->
isLocal(RegionBeginIdx, RegionEndIdx)) {
2665 if (!LocalLI->
isLocal(RegionBeginIdx, RegionEndIdx))
2676 if (GlobalSegment == GlobalLI->
end())
2683 if (GlobalSegment->contains(LocalLI->
beginIndex()))
2686 if (GlobalSegment == GlobalLI->
end())
2690 if (GlobalSegment != GlobalLI->
begin()) {
2693 GlobalSegment->start)) {
2704 assert(std::prev(GlobalSegment)->start < LocalLI->beginIndex() &&
2705 "Disconnected LRG within the scheduling region.");
2721 for (
const SDep &Succ : LastLocalSU->
Succs) {
2736 for (
const SDep &Pred : GlobalSU->
Preds) {
2739 if (Pred.
getSUnit() == FirstLocalSU)
2747 for (
SUnit *LU : LocalUses) {
2748 LLVM_DEBUG(
dbgs() <<
" Local use SU(" << LU->NodeNum <<
") -> SU("
2749 << GlobalSU->
NodeNum <<
")\n");
2752 for (
SUnit *GU : GlobalUses) {
2753 LLVM_DEBUG(
dbgs() <<
" Global use " << *GU <<
" -> " << *FirstLocalSU
2766 if (FirstPos == DAG->
end())
2794 unsigned Latency,
bool AfterSchedNode) {
2797 return ResCntFactor >= (int)LFactor;
2799 return ResCntFactor > (int)LFactor;
2810 CheckPending =
false;
2813 MinReadyCycle = std::numeric_limits<unsigned>::max();
2814 ExpectedLatency = 0;
2815 DependentLatency = 0;
2817 MaxExecutedResCount = 0;
2819 IsResourceLimited =
false;
2820 ReservedCycles.clear();
2821 ReservedResourceSegments.clear();
2822 ReservedCyclesIndex.clear();
2823 ResourceGroupSubUnitMasks.clear();
2824#if LLVM_ENABLE_ABI_BREAKING_CHECKS
2828 MaxObservedStall = 0;
2831 ExecutedResCounts.resize(1);
2832 assert(!ExecutedResCounts[0] &&
"nonzero count for bad resource");
2848 unsigned PIdx = PI->ProcResourceIdx;
2850 assert(PI->ReleaseAtCycle >= PI->AcquireAtCycle);
2852 (Factor * (PI->ReleaseAtCycle - PI->AcquireAtCycle));
2864 unsigned ResourceCount =
SchedModel->getNumProcResourceKinds();
2865 ReservedCyclesIndex.resize(ResourceCount);
2866 ExecutedResCounts.resize(ResourceCount);
2867 ResourceGroupSubUnitMasks.resize(ResourceCount,
APInt(ResourceCount, 0));
2868 unsigned NumUnits = 0;
2870 for (
unsigned i = 0; i < ResourceCount; ++i) {
2871 ReservedCyclesIndex[i] = NumUnits;
2872 NumUnits +=
SchedModel->getProcResource(i)->NumUnits;
2874 auto SubUnits =
SchedModel->getProcResource(i)->SubUnitsIdxBegin;
2875 for (
unsigned U = 0, UE =
SchedModel->getProcResource(i)->NumUnits;
2877 ResourceGroupSubUnitMasks[i].setBit(SubUnits[U]);
2897 if (ReadyCycle > CurrCycle)
2898 return ReadyCycle - CurrCycle;
2905 unsigned ReleaseAtCycle,
2906 unsigned AcquireAtCycle) {
2909 return ReservedResourceSegments[InstanceIdx].getFirstAvailableAtFromTop(
2910 CurrCycle, AcquireAtCycle, ReleaseAtCycle);
2912 return ReservedResourceSegments[InstanceIdx].getFirstAvailableAtFromBottom(
2913 CurrCycle, AcquireAtCycle, ReleaseAtCycle);
2916 unsigned NextUnreserved = ReservedCycles[InstanceIdx];
2922 NextUnreserved = std::max(CurrCycle, NextUnreserved + ReleaseAtCycle);
2923 return NextUnreserved;
2929std::pair<unsigned, unsigned>
2931 unsigned ReleaseAtCycle,
2932 unsigned AcquireAtCycle) {
2934 LLVM_DEBUG(
dbgs() <<
" Resource booking (@" << CurrCycle <<
"c): \n");
2936 LLVM_DEBUG(
dbgs() <<
" getNextResourceCycle (@" << CurrCycle <<
"c): \n");
2939 unsigned InstanceIdx = 0;
2940 unsigned StartIndex = ReservedCyclesIndex[PIdx];
2941 unsigned NumberOfInstances =
SchedModel->getProcResource(PIdx)->NumUnits;
2942 assert(NumberOfInstances > 0 &&
2943 "Cannot have zero instances of a ProcResource");
2960 if (ResourceGroupSubUnitMasks[PIdx][PE.ProcResourceIdx])
2962 StartIndex, ReleaseAtCycle, AcquireAtCycle),
2965 auto SubUnits =
SchedModel->getProcResource(PIdx)->SubUnitsIdxBegin;
2966 for (
unsigned I = 0,
End = NumberOfInstances;
I <
End; ++
I) {
2967 unsigned NextUnreserved, NextInstanceIdx;
2968 std::tie(NextUnreserved, NextInstanceIdx) =
2970 if (MinNextUnreserved > NextUnreserved) {
2971 InstanceIdx = NextInstanceIdx;
2972 MinNextUnreserved = NextUnreserved;
2975 return std::make_pair(MinNextUnreserved, InstanceIdx);
2978 for (
unsigned I = StartIndex,
End = StartIndex + NumberOfInstances;
I <
End;
2980 unsigned NextUnreserved =
2984 << NextUnreserved <<
"c\n");
2985 if (MinNextUnreserved > NextUnreserved) {
2987 MinNextUnreserved = NextUnreserved;
2992 <<
"[" << InstanceIdx - StartIndex <<
"]"
2993 <<
" available @" << MinNextUnreserved <<
"c"
2995 return std::make_pair(MinNextUnreserved, InstanceIdx);
3015 <<
"hazard: " << *SU <<
" reported by HazardRec\n");
3020 if ((CurrMOps > 0) && (CurrMOps + uops >
SchedModel->getIssueWidth())) {
3022 <<
", CurrMOps = " << CurrMOps <<
", "
3023 <<
"CurrMOps + uops > issue width of "
3032 << (
isTop() ?
"begin" :
"end") <<
" group\n");
3041 unsigned ResIdx = PE.ProcResourceIdx;
3042 unsigned ReleaseAtCycle = PE.ReleaseAtCycle;
3043 unsigned AcquireAtCycle = PE.AcquireAtCycle;
3044 unsigned NRCycle, InstanceIdx;
3045 std::tie(NRCycle, InstanceIdx) =
3047 if (NRCycle > CurrCycle) {
3048#if LLVM_ENABLE_ABI_BREAKING_CHECKS
3049 MaxObservedStall = std::max(ReleaseAtCycle, MaxObservedStall);
3052 <<
"hazard: " << *SU <<
" "
3053 <<
SchedModel->getResourceName(ResIdx) <<
'['
3054 << InstanceIdx - ReservedCyclesIndex[ResIdx] <<
']' <<
"="
3055 << NRCycle <<
"c, is later than "
3056 <<
"CurrCycle = " << CurrCycle <<
"c\n");
3067 SUnit *LateSU =
nullptr;
3068 unsigned RemLatency = 0;
3069 for (
SUnit *SU : ReadySUs) {
3071 if (L > RemLatency) {
3078 << RemLatency <<
"c\n");
3092 unsigned OtherCritCount =
Rem->RemIssueCount
3093 + (RetiredMOps *
SchedModel->getMicroOpFactor());
3095 << OtherCritCount /
SchedModel->getMicroOpFactor() <<
'\n');
3096 for (
unsigned PIdx = 1, PEnd =
SchedModel->getNumProcResourceKinds();
3097 PIdx != PEnd; ++PIdx) {
3099 if (OtherCount > OtherCritCount) {
3100 OtherCritCount = OtherCount;
3101 OtherCritIdx = PIdx;
3106 dbgs() <<
" " <<
Available.getName() <<
" + Remain CritRes: "
3107 << OtherCritCount /
SchedModel->getResourceFactor(OtherCritIdx)
3108 <<
" " <<
SchedModel->getResourceName(OtherCritIdx) <<
"\n");
3110 return OtherCritCount;
3117#if LLVM_ENABLE_ABI_BREAKING_CHECKS
3121 if (ReadyCycle > CurrCycle)
3122 MaxObservedStall = std::max(ReadyCycle - CurrCycle, MaxObservedStall);
3125 if (ReadyCycle < MinReadyCycle)
3126 MinReadyCycle = ReadyCycle;
3130 bool IsBuffered =
SchedModel->getMicroOpBufferSize() != 0;
3131 bool HazardDetected = !IsBuffered && ReadyCycle > CurrCycle;
3134 <<
"hazard: " << *SU <<
" ReadyCycle = " << ReadyCycle
3135 <<
" is later than CurrCycle = " << CurrCycle
3136 <<
" on an unbuffered resource" <<
"\n");
3141 HazardDetected =
true;
3146 if (!HazardDetected) {
3161 if (
SchedModel->getMicroOpBufferSize() == 0) {
3162 assert(MinReadyCycle < std::numeric_limits<unsigned>::max() &&
3163 "MinReadyCycle uninitialized");
3164 if (MinReadyCycle > NextCycle)
3165 NextCycle = MinReadyCycle;
3168 unsigned DecMOps =
SchedModel->getIssueWidth() * (NextCycle - CurrCycle);
3169 CurrMOps = (CurrMOps <= DecMOps) ? 0 : CurrMOps - DecMOps;
3172 if ((NextCycle - CurrCycle) > DependentLatency)
3173 DependentLatency = 0;
3175 DependentLatency -= (NextCycle - CurrCycle);
3179 CurrCycle = NextCycle;
3182 for (; CurrCycle != NextCycle; ++CurrCycle) {
3189 CheckPending =
true;
3199 ExecutedResCounts[PIdx] +=
Count;
3200 if (ExecutedResCounts[PIdx] > MaxExecutedResCount)
3201 MaxExecutedResCount = ExecutedResCounts[PIdx];
3215 unsigned ReleaseAtCycle,
3217 unsigned AcquireAtCycle) {
3218 unsigned Factor =
SchedModel->getResourceFactor(PIdx);
3219 unsigned Count = Factor * (ReleaseAtCycle- AcquireAtCycle);
3221 << ReleaseAtCycle <<
"x" << Factor <<
"u\n");
3225 assert(
Rem->RemainingCounts[PIdx] >=
Count &&
"resource double counted");
3226 Rem->RemainingCounts[PIdx] -=
Count;
3231 ZoneCritResIdx = PIdx;
3238 unsigned NextAvailable, InstanceIdx;
3239 std::tie(NextAvailable, InstanceIdx) =
3241 if (NextAvailable > CurrCycle) {
3244 <<
'[' << InstanceIdx - ReservedCyclesIndex[PIdx] <<
']'
3245 <<
" reserved until @" << NextAvailable <<
"\n");
3247 return NextAvailable;
3257 (CurrMOps == 0 || (CurrMOps + IncMOps) <=
SchedModel->getIssueWidth()) &&
3258 "Cannot schedule this instruction's MicroOps in the current cycle.");
3263 unsigned NextCycle = CurrCycle;
3264 switch (
SchedModel->getMicroOpBufferSize()) {
3266 assert(ReadyCycle <= CurrCycle &&
"Broken PendingQueue");
3269 if (ReadyCycle > NextCycle) {
3270 NextCycle = ReadyCycle;
3271 LLVM_DEBUG(
dbgs() <<
" *** Stall until: " << ReadyCycle <<
"\n");
3280 NextCycle = ReadyCycle;
3283 RetiredMOps += IncMOps;
3287 unsigned DecRemIssue = IncMOps *
SchedModel->getMicroOpFactor();
3288 assert(
Rem->RemIssueCount >= DecRemIssue &&
"MOps double counted");
3289 Rem->RemIssueCount -= DecRemIssue;
3290 if (ZoneCritResIdx) {
3292 unsigned ScaledMOps =
3293 RetiredMOps *
SchedModel->getMicroOpFactor();
3301 << ScaledMOps /
SchedModel->getLatencyFactor()
3307 PE =
SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
3309 countResource(SC, PI->ProcResourceIdx, PI->ReleaseAtCycle, NextCycle,
3310 PI->AcquireAtCycle);
3311 if (RCycle > NextCycle)
3321 PE =
SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
3322 unsigned PIdx = PI->ProcResourceIdx;
3323 if (
SchedModel->getResourceBufferSize(PIdx) == 0) {
3326 unsigned ReservedUntil, InstanceIdx;
3328 SC, PIdx, PI->ReleaseAtCycle, PI->AcquireAtCycle);
3330 ReservedResourceSegments[InstanceIdx].add(
3332 NextCycle, PI->AcquireAtCycle, PI->ReleaseAtCycle),
3335 ReservedResourceSegments[InstanceIdx].add(
3337 NextCycle, PI->AcquireAtCycle, PI->ReleaseAtCycle),
3342 unsigned ReservedUntil, InstanceIdx;
3344 SC, PIdx, PI->ReleaseAtCycle, PI->AcquireAtCycle);
3346 ReservedCycles[InstanceIdx] =
3347 std::max(ReservedUntil, NextCycle + PI->ReleaseAtCycle);
3349 ReservedCycles[InstanceIdx] = NextCycle;
3356 unsigned &TopLatency =
isTop() ? ExpectedLatency : DependentLatency;
3357 unsigned &BotLatency =
isTop() ? DependentLatency : ExpectedLatency;
3361 <<
" " << TopLatency <<
"c\n");
3366 <<
" " << BotLatency <<
"c\n");
3369 if (NextCycle > CurrCycle)
3387 CheckPending =
true;
3394 CurrMOps += IncMOps;
3407 while (CurrMOps >=
SchedModel->getIssueWidth()) {
3408 LLVM_DEBUG(
dbgs() <<
" *** Max MOps " << CurrMOps <<
" at cycle "
3409 << CurrCycle <<
'\n');
3420 MinReadyCycle = std::numeric_limits<unsigned>::max();
3424 for (
unsigned I = 0, E =
Pending.size();
I < E; ++
I) {
3430 if (ReadyCycle < MinReadyCycle)
3431 MinReadyCycle = ReadyCycle;
3442 CheckPending =
false;
3471 for (
unsigned i = 0;
Available.empty(); ++i) {
3488#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3497 unsigned ResourceCount =
SchedModel->getNumProcResourceKinds();
3498 unsigned StartIdx = 0;
3500 for (
unsigned ResIdx = 0; ResIdx < ResourceCount; ++ResIdx) {
3501 const unsigned NumUnits =
SchedModel->getProcResource(ResIdx)->NumUnits;
3502 std::string ResName =
SchedModel->getResourceName(ResIdx);
3503 for (
unsigned UnitIdx = 0; UnitIdx < NumUnits; ++UnitIdx) {
3504 dbgs() << ResName <<
"(" << UnitIdx <<
") = ";
3506 if (ReservedResourceSegments.count(StartIdx + UnitIdx))
3507 dbgs() << ReservedResourceSegments.at(StartIdx + UnitIdx);
3511 dbgs() << ReservedCycles[StartIdx + UnitIdx] <<
"\n";
3513 StartIdx += NumUnits;
3522 if (ZoneCritResIdx) {
3523 ResFactor =
SchedModel->getResourceFactor(ZoneCritResIdx);
3527 ResCount = RetiredMOps * ResFactor;
3529 unsigned LFactor =
SchedModel->getLatencyFactor();
3531 <<
" Retired: " << RetiredMOps;
3533 dbgs() <<
"\n Critical: " << ResCount / LFactor <<
"c, "
3534 << ResCount / ResFactor <<
" "
3535 <<
SchedModel->getResourceName(ZoneCritResIdx)
3536 <<
"\n ExpectedLatency: " << ExpectedLatency <<
"c\n"
3537 << (IsResourceLimited ?
" - Resource" :
" - Latency")
3557 PE =
SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
3558 if (PI->ProcResourceIdx ==
Policy.ReduceResIdx)
3559 ResDelta.CritResources += PI->ReleaseAtCycle;
3560 if (PI->ProcResourceIdx ==
Policy.DemandResIdx)
3561 ResDelta.DemandedResources += PI->ReleaseAtCycle;
3567bool GenericSchedulerBase::shouldReduceLatency(
const CandPolicy &Policy,
3569 bool ComputeRemLatency,
3570 unsigned &RemLatency)
const {
3580 if (ComputeRemLatency)
3596 unsigned OtherCritIdx = 0;
3597 unsigned OtherCount =
3600 bool OtherResLimited =
false;
3601 unsigned RemLatency = 0;
3602 bool RemLatencyComputed =
false;
3603 if (
SchedModel->hasInstrSchedModel() && OtherCount != 0) {
3605 RemLatencyComputed =
true;
3607 OtherCount, RemLatency,
false);
3613 if (!OtherResLimited &&
3614 (IsPostRA || shouldReduceLatency(Policy, CurrZone, !RemLatencyComputed,
3618 <<
" RemainingLatency " << RemLatency <<
" + "
3620 <<
Rem.CriticalPath <<
"\n");
3627 dbgs() <<
" " << CurrZone.Available.getName() <<
" ResourceLimited: "
3628 << SchedModel->getResourceName(CurrZone.getZoneCritResIdx()) <<
"\n";
3629 }
if (OtherResLimited)
dbgs()
3630 <<
" RemainingLimit: "
3631 <<
SchedModel->getResourceName(OtherCritIdx) <<
"\n";
3633 <<
" Latency limited both directions.\n");
3638 if (OtherResLimited)
3647 case NoCand:
return "NOCAND ";
3648 case Only1:
return "ONLY1 ";
3649 case PhysReg:
return "PHYS-REG ";
3652 case Stall:
return "STALL ";
3653 case Cluster:
return "CLUSTER ";
3654 case Weak:
return "WEAK ";
3655 case RegMax:
return "REG-MAX ";
3671 unsigned ResIdx = 0;
3706 dbgs() <<
" " <<
TRI->getRegPressureSetName(
P.getPSet())
3707 <<
":" <<
P.getUnitInc() <<
" ";
3711 dbgs() <<
" " <<
SchedModel->getProcResource(ResIdx)->Name <<
" ";
3740 RemLatency = std::max(RemLatency,
3742 RemLatency = std::max(RemLatency,
3754 if (TryVal < CandVal) {
3758 if (TryVal > CandVal) {
3759 if (Cand.
Reason > Reason)
3770 if (TryVal > CandVal) {
3774 if (TryVal < CandVal) {
3775 if (Cand.
Reason > Reason)
3817 const bool IsTop,
const bool IsPostRA =
false) {
3818 assert(SU &&
"SU must not be null for tracing");
3819 LLVM_DEBUG(
dbgs() <<
"Pick " << (IsTop ?
"Top " :
"Bot ") <<
"Cand " << *SU
3821 << (IsPostRA ?
"post-RA" :
"pre-RA") <<
"]\n");
3840 NumRegExcessPostRA++;
3843 NumRegCriticalPostRA++;
3858 NumResourceReducePostRA++;
3861 NumResourceDemandPostRA++;
3864 NumTopDepthReducePostRA++;
3867 NumTopPathReducePostRA++;
3870 NumBotHeightReducePostRA++;
3873 NumBotPathReducePostRA++;
3876 NumNodeOrderPostRA++;
3879 NumFirstValidPostRA++;
3899 NumRegExcessPreRA++;
3902 NumRegCriticalPreRA++;
3917 NumResourceReducePreRA++;
3920 NumResourceDemandPreRA++;
3923 NumTopDepthReducePreRA++;
3926 NumTopPathReducePreRA++;
3929 NumBotHeightReducePreRA++;
3932 NumBotPathReducePreRA++;
3935 NumNodeOrderPreRA++;
3938 NumFirstValidPreRA++;
3946 const bool IsPostRA =
false) {
3952 "(PreRA)GenericScheduler needs vreg liveness");
3958 DAG->computeDFSResult();
3970 Top.HazardRec.reset(
DAG->TII->CreateTargetMIHazardRecognizer(Itin,
DAG));
3972 Bot.HazardRec.reset(
DAG->TII->CreateTargetMIHazardRecognizer(Itin,
DAG));
3992 for (
unsigned VT = MVT::i64; VT > (
unsigned)MVT::i1; --VT) {
3995 unsigned NIntRegs =
Context->RegClassInfo->getNumAllocatableRegs(
4033#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4034 dbgs() <<
"GenericScheduler RegionPolicy: "
4035 <<
" ShouldTrackPressure=" <<
RegionPolicy.ShouldTrackPressure
4052 if (
Rem.CyclicCritPath == 0 ||
Rem.CyclicCritPath >=
Rem.CriticalPath)
4056 unsigned IterCount =
4057 std::max(
Rem.CyclicCritPath *
SchedModel->getLatencyFactor(),
4060 unsigned AcyclicCount =
Rem.CriticalPath *
SchedModel->getLatencyFactor();
4062 unsigned InFlightCount =
4063 (AcyclicCount *
Rem.RemIssueCount + IterCount-1) / IterCount;
4064 unsigned BufferLimit =
4067 Rem.IsAcyclicLatencyLimited = InFlightCount > BufferLimit;
4070 dbgs() <<
"IssueCycles="
4071 <<
Rem.RemIssueCount /
SchedModel->getLatencyFactor() <<
"c "
4072 <<
"IterCycles=" << IterCount /
SchedModel->getLatencyFactor()
4073 <<
"c NumIters=" << (AcyclicCount + IterCount - 1) / IterCount
4074 <<
" InFlight=" << InFlightCount /
SchedModel->getMicroOpFactor()
4075 <<
"m BufferLim=" <<
SchedModel->getMicroOpBufferSize() <<
"m\n";
4076 if (
Rem.IsAcyclicLatencyLimited)
dbgs() <<
" ACYCLIC LATENCY LIMIT\n");
4080 Rem.CriticalPath =
DAG->ExitSU.getDepth();
4083 for (
const SUnit *SU :
Bot.Available) {
4089 errs() <<
"Critical Path(GS-RR ): " <<
Rem.CriticalPath <<
" \n";
4093 Rem.CyclicCritPath =
DAG->computeCyclicCriticalPath();
4119 if (TryPSet == CandPSet) {
4124 int TryRank = TryP.
isValid() ?
TRI->getRegPressureSetScore(MF, TryPSet) :
4125 std::numeric_limits<int>::max();
4127 int CandRank = CandP.
isValid() ?
TRI->getRegPressureSetScore(MF, CandPSet) :
4128 std::numeric_limits<int>::max();
4133 return tryGreater(TryRank, CandRank, TryCand, Cand, Reason);
4151 unsigned ScheduledOper = isTop ? 1 : 0;
4152 unsigned UnscheduledOper = isTop ? 0 : 1;
4155 if (
MI->getOperand(ScheduledOper).getReg().isPhysical())
4160 if (
MI->getOperand(UnscheduledOper).getReg().isPhysical())
4161 return AtBoundary ? -1 : 1;
4164 if (
MI->isMoveImmediate()) {
4170 if (
Op.isReg() && !
Op.getReg().isPhysical()) {
4177 return isTop ? -1 : 1;
4180 if (BiasPRegsExtra && !isTop &&
MI->getNumExplicitDefs() == 1)
4183 return MI->getOperand(0).getReg().isPhysical();
4193 if (
tryGreater(TryCandPRegBias, CandPRegBias, TryCand, Cand,
4196 if (BiasPRegsExtra && Zone !=
nullptr && TryCandPRegBias &&
4197 TryCandPRegBias == CandPRegBias) {
4216 if (
DAG->isTrackingPressure()) {
4221 DAG->getRegionCriticalPSets(),
4222 DAG->getRegPressure().MaxSetPressure);
4227 &
DAG->getPressureDiff(Cand.
SU),
4229 DAG->getRegionCriticalPSets(),
4230 DAG->getRegPressure().MaxSetPressure);
4234 DAG->getPressureDiff(Cand.
SU),
4236 DAG->getRegionCriticalPSets(),
4237 DAG->getRegPressure().MaxSetPressure);
4242 <<
" Try " << *Cand.
SU <<
" "
4290 bool SameBoundary = Zone !=
nullptr;
4313 bool CandIsClusterSucc =
4315 bool TryCandIsClusterSucc =
4318 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
4326 TryCand, Cand,
Weak))
4351 !
Rem.IsAcyclicLatencyLimited &&
tryLatency(TryCand, Cand, *Zone))
4378 for (
SUnit *SU : Q) {
4398 if (
SUnit *SU =
Bot.pickOnlyChoice()) {
4403 if (
SUnit *SU =
Top.pickOnlyChoice()) {
4420 BotCand.Policy != BotPolicy) {
4432 "Last pick result should correspond to re-picking right now");
4440 TopCand.Policy != TopPolicy) {
4452 "Last pick result should correspond to re-picking right now");
4467 IsTopNode = Cand.
AtTop;
4474 if (
DAG->top() ==
DAG->bottom()) {
4476 Bot.Available.empty() &&
Bot.Pending.empty() &&
"ReadyQ garbage");
4481 SU =
Top.pickOnlyChoice();
4494 SU =
Bot.pickOnlyChoice();
4527 Top.removeReady(SU);
4529 Bot.removeReady(SU);
4535 ++NumInstrsInSourceOrderPreRA;
4539 ++NumInstrsInSourceOrderPreRA;
4542 NumInstrsScheduledPreRA += 1;
4555 for (
SDep &Dep : Deps) {
4556 if (Dep.getKind() !=
SDep::Data || !Dep.getReg().isPhysical())
4558 SUnit *DepSU = Dep.getSUnit();
4559 if (isTop ? DepSU->
Succs.size() > 1 : DepSU->
Preds.size() > 1)
4562 if (!Copy->isCopy() && !Copy->isMoveImmediate())
4565 DAG->dumpNode(*Dep.getSUnit()));
4574 if (MO.isReg() && MO.getReg().isVirtual())
4576 bool FixUndef = !CopyVRegs.
empty();
4583 OldNext = std::next(Copy->getIterator());
4586 DAG->moveInstruction(Copy, InsertPos);
4596 if (NewIdx < OldIdx) {
4597 FixBegin = std::next(NewIt);
4599 }
else if (OldIdx < NewIdx) {
4603 for (
auto I = FixBegin;
I != FixEnd; ++
I)
4604 if (!
I->isDebugInstr())
4625 dbgs() <<
" Top Cluster: ";
4626 for (
auto *
N : *TopCluster) {
4627 DAG->dumpNodeName(*
N);
4642 dbgs() <<
" Bot Cluster: ";
4643 for (
auto *
N : *BotCluster) {
4644 DAG->dumpNodeName(*
N);
4660static MachineSchedRegistry
4681 Top.HazardRec.reset(
DAG->TII->CreateTargetMIHazardRecognizer(Itin,
DAG));
4683 Bot.HazardRec.reset(
DAG->TII->CreateTargetMIHazardRecognizer(Itin,
DAG));
4719 Rem.CriticalPath =
DAG->ExitSU.getDepth();
4722 for (
const SUnit *SU :
Bot.Available) {
4728 errs() <<
"Critical Path(PGS-RR ): " <<
Rem.CriticalPath <<
" \n";
4747 Top.getLatencyStallCycles(Cand.
SU), TryCand, Cand,
Stall))
4753 bool CandIsClusterSucc =
4755 bool TryCandIsClusterSucc =
4758 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
4791 for (
SUnit *SU : Q) {
4810 if (
SUnit *SU =
Bot.pickOnlyChoice()) {
4815 if (
SUnit *SU =
Top.pickOnlyChoice()) {
4832 BotCand.Policy != BotPolicy) {
4844 "Last pick result should correspond to re-picking right now");
4852 TopCand.Policy != TopPolicy) {
4864 "Last pick result should correspond to re-picking right now");
4879 IsTopNode = Cand.
AtTop;
4886 if (
DAG->top() ==
DAG->bottom()) {
4888 Bot.Available.empty() &&
Bot.Pending.empty() &&
"ReadyQ garbage");
4893 SU =
Bot.pickOnlyChoice();
4909 SU =
Top.pickOnlyChoice();
4930 Top.removeReady(SU);
4932 Bot.removeReady(SU);
4938 ++NumInstrsInSourceOrderPostRA;
4942 ++NumInstrsInSourceOrderPostRA;
4945 NumInstrsScheduledPostRA += 1;
4973 const BitVector *ScheduledTrees =
nullptr;
4976 ILPOrder(
bool MaxILP) : MaximizeILP(MaxILP) {}
4981 bool operator()(
const SUnit *
A,
const SUnit *
B)
const {
4984 if (SchedTreeA != SchedTreeB) {
4986 if (ScheduledTrees->
test(SchedTreeA) != ScheduledTrees->
test(SchedTreeB))
4987 return ScheduledTrees->
test(SchedTreeB);
5004class ILPScheduler :
public MachineSchedStrategy {
5005 ScheduleDAGMILive *DAG =
nullptr;
5008 std::vector<SUnit*> ReadyQ;
5011 ILPScheduler(
bool MaximizeILP) :
Cmp(MaximizeILP) {}
5013 void initialize(ScheduleDAGMI *dag)
override {
5015 DAG =
static_cast<ScheduleDAGMILive*
>(dag);
5022 void registerRoots()
override {
5024 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
5031 SUnit *pickNode(
bool &IsTopNode)
override {
5032 if (ReadyQ.empty())
return nullptr;
5033 std::pop_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
5034 SUnit *SU = ReadyQ.back();
5044 <<
"Scheduling " << *SU->
getInstr());
5049 void scheduleTree(
unsigned SubtreeID)
override {
5050 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
5055 void schedNode(SUnit *SU,
bool IsTopNode)
override {
5056 assert(!IsTopNode &&
"SchedDFSResult needs bottom-up");
5059 void releaseTopNode(SUnit *)
override { }
5061 void releaseBottomNode(SUnit *SU)
override {
5062 ReadyQ.push_back(SU);
5063 std::push_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
5090template<
bool IsReverse>
5094 return A->NodeNum >
B->NodeNum;
5096 return A->NodeNum <
B->NodeNum;
5101class InstructionShuffler :
public MachineSchedStrategy {
5108 PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<false>>
5112 PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<true>>
5116 InstructionShuffler(
bool alternate,
bool topdown)
5117 : IsAlternating(alternate), IsTopDown(topdown) {}
5127 SUnit *pickNode(
bool &IsTopNode)
override {
5131 if (TopQ.empty())
return nullptr;
5138 if (BottomQ.empty())
return nullptr;
5145 IsTopDown = !IsTopDown;
5149 void schedNode(SUnit *SU,
bool IsTopNode)
override {}
5151 void releaseTopNode(SUnit *SU)
override {
5154 void releaseBottomNode(SUnit *SU)
override {
5166 C, std::make_unique<InstructionShuffler>(Alternate, TopDown));
5170 "shuffle",
"Shuffle machine instructions alternating directions",
5178#if !defined(NDEBUG) && LLVM_ENABLE_ABI_BREAKING_CHECKS
5185struct llvm::DOTGraphTraits<ScheduleDAGMI *> :
public DefaultDOTGraphTraits {
5186 DOTGraphTraits(
bool isSimple =
false) : DefaultDOTGraphTraits(
isSimple) {}
5188 static std::string getGraphName(
const ScheduleDAG *
G) {
5189 return std::string(
G->MF.getName());
5192 static bool renderGraphFromBottomUp() {
5196 static bool isNodeHidden(
const SUnit *Node,
const ScheduleDAG *
G) {
5205 static std::string getEdgeAttributes(
const SUnit *Node,
5207 const ScheduleDAG *Graph) {
5209 return "color=cyan,style=dashed";
5211 return "color=blue,style=dashed";
5215 static std::string
getNodeLabel(
const SUnit *SU,
const ScheduleDAG *
G) {
5217 raw_string_ostream
SS(Str);
5218 const ScheduleDAGMI *DAG =
static_cast<const ScheduleDAGMI*
>(
G);
5220 static_cast<const ScheduleDAGMILive*
>(
G)->getDFSResult() :
nullptr;
5227 static std::string getNodeDescription(
const SUnit *SU,
const ScheduleDAG *
G) {
5228 return G->getGraphNodeLabel(SU);
5231 static std::string getNodeAttributes(
const SUnit *
N,
const ScheduleDAG *
G) {
5232 std::string Str(
"shape=Mrecord");
5233 const ScheduleDAGMI *DAG =
static_cast<const ScheduleDAGMI*
>(
G);
5235 static_cast<const ScheduleDAGMILive*
>(
G)->getDFSResult() :
nullptr;
5237 Str +=
",style=filled,fillcolor=\"#";
5250#if !defined(NDEBUG) && LLVM_ENABLE_ABI_BREAKING_CHECKS
5253 errs() <<
"ScheduleDAGMI::viewGraph is only available in debug builds on "
5254 <<
"systems with Graphviz or gv!\n";
5269 return A.first <
B.first;
5272unsigned ResourceSegments::getFirstAvailableAt(
5273 unsigned CurrCycle,
unsigned AcquireAtCycle,
unsigned ReleaseAtCycle,
5275 IntervalBuilder)
const {
5277 "Cannot execute on an un-sorted set of intervals.");
5281 if (AcquireAtCycle == ReleaseAtCycle)
5284 unsigned RetCycle = CurrCycle;
5286 IntervalBuilder(RetCycle, AcquireAtCycle, ReleaseAtCycle);
5287 for (
auto &
Interval : _Intervals) {
5294 "Invalid intervals configuration.");
5295 RetCycle += (unsigned)
Interval.second - (
unsigned)NewInterval.first;
5296 NewInterval = IntervalBuilder(RetCycle, AcquireAtCycle, ReleaseAtCycle);
5302 const unsigned CutOff) {
5303 assert(
A.first <=
A.second &&
"Cannot add negative resource usage");
5304 assert(CutOff > 0 &&
"0-size interval history has no use.");
5310 if (
A.first ==
A.second)
5317 "A resource is being overwritten");
5318 _Intervals.push_back(
A);
5324 while (_Intervals.size() > CutOff)
5325 _Intervals.pop_front();
5330 assert(
A.first <=
A.second &&
"Invalid interval");
5331 assert(
B.first <=
B.second &&
"Invalid interval");
5334 if ((
A.first ==
B.first) || (
A.second ==
B.second))
5339 if ((
A.first >
B.first) && (
A.second <
B.second))
5344 if ((
A.first >
B.first) && (
A.first <
B.second) && (
A.second >
B.second))
5349 if ((
A.first <
B.first) && (
B.first <
A.second) && (
B.second >
B.first))
5355void ResourceSegments::sortAndMerge() {
5356 if (_Intervals.size() <= 1)
5363 auto next = std::next(std::begin(_Intervals));
5364 auto E = std::end(_Intervals);
5365 for (; next != E; ++next) {
5366 if (std::prev(next)->second >= next->first) {
5367 next->first = std::prev(next)->first;
5368 _Intervals.erase(std::prev(next));
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis false
static const Function * getParent(const Value *V)
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#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, ArrayRef< InsnRange > Ranges, const InstructionOrdering &Ordering)
Check if the instruction range [StartMI, EndMI] intersects any instruction range in Ranges.
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 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")))
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))
PostRA 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 cl::opt< bool > EnableSSAMachineSched("enable-ssa-misched", cl::desc("Enable the machine instruction scheduling pass in SSA."), cl::init(false), cl::Hidden)
static cl::opt< bool > VerifyScheduling("verify-misched", cl::Hidden, cl::desc("Verify machine instrs before and after machine scheduling"))
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 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 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 cl::opt< TargetSubtargetInfo::AntiDepBreakMode > PostRABreakAntiDeps("misched-postra-break-antideps", cl::Hidden, cl::desc("Set the post-RA MISched anti-dependency break mode"), cl::init(TargetSubtargetInfo::ANTIDEP_NONE), cl::values(clEnumValN(TargetSubtargetInfo::ANTIDEP_NONE, "none", "No anti-dependency breaking"), clEnumValN(TargetSubtargetInfo::ANTIDEP_CRITICAL, "critical", "Break critical-path anti-dependencies"), clEnumValN(TargetSubtargetInfo::ANTIDEP_ALL, "all", "Break all anti-dependencies")))
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 cl::opt< MISched::Direction > PreRADirection("misched-prera-direction", cl::Hidden, cl::desc("Pre reg-alloc list scheduling direction"), cl::init(MISched::Unspecified), cl::values(clEnumValN(MISched::TopDown, "topdown", "Force top-down pre reg-alloc list scheduling"), clEnumValN(MISched::BottomUp, "bottomup", "Force bottom-up pre reg-alloc list scheduling"), clEnumValN(MISched::Bidirectional, "bidirectional", "Force bidirectional pre reg-alloc list scheduling")))
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< bool > MischedDetailResourceBooking("misched-detail-resource-booking", cl::Hidden, cl::init(false), cl::desc("Show details of invoking getNextResoufceCycle."))
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 void tracePick(const SUnit *SU, const GenericSchedulerBase::CandReason Reason, const bool IsTop, const bool IsPostRA=false)
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)
SmallVector< SchedRegion, 16 > MBBRegionsVector
static cl::opt< bool > MISchedDumpReservedCycles("misched-dump-reserved-cycles", cl::Hidden, cl::init(false), cl::desc("Dump resource usage at schedule boundary."))
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 cl::opt< bool > DumpCriticalPathLength("misched-dcpl", cl::Hidden, cl::desc("Print critical path length to stdout"))
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
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)
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.
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, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
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.
Class for arbitrary precision integers.
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:
std::vector< std::pair< MachineInstr *, MachineInstr * > > DbgValueVector
void startBlock(MachineBasicBlock *MBB)
bool breakAntiDependencies(const std::vector< SUnit > &SUnits, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, AntiDepBreaker::DbgValueVector &DbgValues)
void exitRegion(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End)
AntiDepState(MachineSchedContext *C, TargetSubtargetInfo::AntiDepBreakMode AntiDepMode)
void enterRegion(MachineBasicBlock::iterator End)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
reverse_iterator rend() const
size_t size() const
Get the array size.
reverse_iterator rbegin() const
bool test(unsigned Idx) const
Returns true if bit Idx is set.
Represents analyses that only rely on functions' control flow.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
iterator find(const_arg_type_t< KeyT > Val)
The EquivalenceClasses data structure is just a set of these.
This represents a collection of equivalence classes and supports three efficient operations: insert a...
iterator_range< member_iterator > members(const ECValue &ECV) const
member_iterator unionSets(const ElemTy &V1, const ElemTy &V2)
Merge the two equivalence sets for the specified values, inserting them if they do not already exist ...
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...
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 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.
bool shouldTrackLaneMasks() const override
Returns true if lanemasks should be tracked.
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 override
Get the base register and byte offset of a load/store instr.
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.
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
Result of a LiveRange query.
VNInfo * valueIn() const
Return the value that is live-in to the instruction.
Segments::iterator iterator
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)
MachineInstrBundleIterator< const MachineInstr > const_iterator
MachineInstrBundleIterator< MachineInstr > iterator
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
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.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
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.
MachineSchedRegistry provides a selection of available machine instruction schedulers.
static LLVM_ABI MachinePassRegistry< ScheduleDAGCtor > Registry
ScheduleDAGInstrs *(*)(MachineSchedContext *) ScheduleDAGCtor
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 ...
SchedCandidate BotCand
Candidate last picked from Bot boundary.
void pickNodeFromQueue(SchedBoundary &Zone, SchedCandidate &Cand)
void initialize(ScheduleDAGMI *Dag) override
Initialize the strategy after building the DAG for a new region.
SchedCandidate TopCand
Candidate last picked from Top boundary.
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(VirtRegOrUnit VRegOrUnit, bool IsDec, const MachineRegisterInfo *MRI)
Add a change in pressure to the pressure diff of a given instruction.
void clear()
clear - Erase all elements from the queue.
Helpers for implementing custom MachineSchedStrategy classes.
ArrayRef< SUnit * > elements()
LLVM_ABI void dump() const
std::vector< SUnit * >::iterator iterator
StringRef getName() const
Track the current register pressure at some position in the instruction stream, and remember the high...
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 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 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...
List of registers defined and used by a machine instruction.
LLVM_ABI void detectDeadDefs(const MachineInstr &MI, LiveIntervals &LIS, const MachineRegisterInfo &MRI)
Use liveness information to find dead defs at MI's dead slot not marked with a dead flag and move the...
LLVM_ABI void adjustLaneLiveness(LiveIntervals &LIS, const MachineRegisterInfo &MRI, SlotIndex Pos)
Use liveness information to find out which uses/defs are partially undefined/dead at Pos and adjust t...
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...
static LLVM_ABI void restoreLivenessFlags(MachineInstr &MI, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI, LiveIntervals &LIS, bool TrackLaneMasks=true, ArrayRef< Register > OnlyRegs={})
Clear potentially-stale read-undef flags on the defs of MI, then recompute them from LIS.
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.
LLVM_ABI ~SSAMachineSchedulerPass()
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
LLVM_ABI SSAMachineSchedulerPass(const TargetMachine *TM)
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.
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
bool isReservedGroup(unsigned PIdx) 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()
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.
std::unique_ptr< ScheduleHazardRecognizer > HazardRec
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.
ILPValue getILP(const SUnit *SU) const
Get the ILP value for a DAG node.
unsigned getSubtreeLevel(unsigned SubtreeID) const
Get the connection level of a subtree.
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.
std::string getDAGName() const override
Returns a label for the region of code covered by the DAG.
MachineBasicBlock * BB
The block in which to insert instructions.
MachineInstr * FirstDbgValue
virtual void startBlock(MachineBasicBlock *BB)
Prepares to perform scheduling in the given block.
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.
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.
virtual void exitRegion()
Called when the scheduler has finished scheduling the current region.
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 exitRegion() override
Called when the scheduler has finished scheduling the current region.
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.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
AntiDepState AntiDep
State for optional post-RA anti-dependency breaking.
void findRootsAndBiasEdges(SmallVectorImpl< SUnit * > &TopRoots, SmallVectorImpl< SUnit * > &BotRoots)
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(const Twine &Name, const Twine &Title) override
viewGraph - Pop up a ghostview window with the reachable parts of the DAG rendered using 'dot'.
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.
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
void dumpNodeName(const SUnit &SU) const
SUnit ExitSU
Special node for the region exit.
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.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
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_base< SparseMultiSet * > iterator
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 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...
Provide an instruction scheduling machine model to CodeGen passes.
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.
const MCWriteProcResEntry * ProcResIter
unsigned getResourceFactor(unsigned ResIdx) const
Multiply the number of units consumed for a resource by this factor to normalize it relative to other...
LLVM_ABI unsigned getNumMicroOps(const MachineInstr *MI, const MCSchedClassDesc *SC=nullptr) const
Return the number of issue slots required for this MI.
unsigned getNumProcResourceKinds() const
Get the number of kinds of resources for this target.
ProcResIter getWriteProcResBegin(const MCSchedClassDesc *SC) const
enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode
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 enableSSAMachineScheduler() const
True if the subtarget should run a machine scheduler before PHI elimination.
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...
Wrapper class representing a virtual register or register unit.
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)
MachineSchedulerImpl()=default
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)
ScheduleDAGInstrs * createPostMachineScheduler()
Instantiate a ScheduleDAGInstrs for PostRA scheduling that will be owned by the caller.
void setLegacyPass(MachineFunctionPass *P)
PostMachineSchedulerImpl()=default
Impl class for SSAMachineScheduler.
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.
void setMFAM(MachineFunctionAnalysisManager *MFAM)
SSAMachineSchedulerImpl()
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.
Abstract Attribute helper functions.
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)
NodeAddr< NodeBase * > Node
bool isSimple(Instruction *I)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI int biasPhysReg(const SUnit *SU, bool isTop, bool BiasPRegsExtra=false)
Minimize physical register live ranges.
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.
LLVM_ABI unsigned getWeakLeft(const SUnit *SU, bool isTop)
LLVM_ABI AntiDepBreaker * createAggressiveAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI, TargetSubtargetInfo::RegClassVector &CriticalPathRCs)
FormattedString right_justify(StringRef Str, unsigned Width)
right_justify - add spaces before string so total output is Width characters.
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createLoadClusterDAGMutation(const TargetInstrInfo *TII, bool ReorderWhileClustering=false)
If ReorderWhileClustering is set to true, no attempt will be made to reduce reordering due to store c...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI TargetSubtargetInfo::AntiDepBreakMode getPostRABreakAntiDeps()
Returns -misched-postra-break-antideps.
Printable PrintLaneMask(LaneBitmask LaneMask)
Create Printable object to print LaneBitmasks on a raw_ostream.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI char & MachineSchedulerID
MachineScheduler - This pass schedules machine instructions.
LLVM_ABI char & PostMachineSchedulerID
PostMachineScheduler - This pass schedules machine instructions postRA.
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createStoreClusterDAGMutation(const TargetInstrInfo *TII, bool ReorderWhileClustering=false)
If ReorderWhileClustering is set to true, no attempt will be made to reduce reordering due to store c...
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
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)
LLVM_ABI void initializeSSAMachineSchedulerLegacyPass(PassRegistry &)
ScheduleDAGMI * createSchedPostRA(MachineSchedContext *C)
Create a generic scheduler with no vreg liveness or DAG mutation passes.
void sort(IteratorTy Start, IteratorTy End)
cl::opt< bool > ViewMISchedDAGs
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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 shouldVerifyScheduling()
Returns whether -verify-misched is set.
LLVM_ABI bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, SchedBoundary &Zone)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI bool tryBiasPhysRegs(GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, SchedBoundary *Zone, bool BiasPRegsExtra)
LLVM_ABI char & SSAMachineSchedulerID
SSAMachineScheduler - This pass schedules machine instructions in SSA.
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createCopyConstrainDAGMutation(const TargetInstrInfo *TII)
DWARFExpression::Operation Op
LLVM_ABI bool tryGreater(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
SmallPtrSet< SUnit *, 8 > ClusterInfo
Keep record of which SUnit are in the same cluster group.
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.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI AntiDepBreaker * createCriticalAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI)
LLVM_ABI unsigned computeRemLatency(SchedBoundary &CurrZone)
Compute remaining latency.
LLVM_ABI void dumpRegSetPressure(ArrayRef< unsigned > SetPressure, const TargetRegisterInfo *TRI)
LLVM_ABI MISched::Direction getPreRADirection()
Returns -misched-prera-direction.
LLVM_ABI bool tryLess(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
Return true if this heuristic determines order.
@ End
Run the machine verifier once, at the end of the pipeline.
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.
cl::opt< bool > PrintDAGs
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.
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()
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
MachineBlockFrequencyInfo * MBFI
const MachineLoopInfo * MLI
virtual ~MachineSchedContext()
PressureChange CriticalMax
PressureChange CurrentMax
RegisterPressure computed within a region of instructions delimited by TopPos and BottomPos.
A region of an MBB for scheduling.
Summarize the unscheduled region.
LLVM_ABI void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel)
SmallVector< unsigned, 16 > RemainingCounts
An individual mapping from virtual register number to SUnit.
RegisterClassInfo & RegClassInfo
MachineBlockFrequencyInfo & MBFI
MachineBlockFrequencyInfo & MBFI
RegisterClassInfo & RegClassInfo