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(
"Verify machine instrs before and after machine scheduling"));
217 cl::desc(
"Pop up a window to show MISched dags after they are processed"));
222 cl::desc(
"Dump resource usage at schedule boundary."));
225 cl::desc(
"Show details of invoking getNextResoufceCycle."));
230#ifdef LLVM_ENABLE_DUMP
239 cl::desc(
"Hide nodes with more predecessor/successor than cutoff"));
245 cl::desc(
"Only schedule this function"));
247 cl::desc(
"Only schedule this MBB#"));
262 cl::desc(
"Enable memop clustering."),
266 cl::desc(
"Switch to fast cluster algorithm with the lost "
267 "of some fusion opportunities"),
271 cl::desc(
"The threshold for fast cluster"),
274#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
277 cl::desc(
"Dump resource usage at schedule boundary."));
280 cl::desc(
"Set width of the columns with "
281 "the resources and schedule units"),
285 cl::desc(
"Set width of the columns showing resource booking."),
289 cl::desc(
"Sort the resources printed in the dump trace"));
300void MachineSchedStrategy::anchor() {}
302void ScheduleDAGMutation::anchor() {}
342 const RequiredAnalyses &Analyses);
366 const RequiredAnalyses &Analyses);
382 MachineSchedulerImpl Impl;
385 MachineSchedulerLegacy();
386 void getAnalysisUsage(AnalysisUsage &AU)
const override;
394 PostMachineSchedulerImpl Impl;
397 PostMachineSchedulerLegacy();
398 void getAnalysisUsage(AnalysisUsage &AU)
const override;
406char MachineSchedulerLegacy::ID = 0;
411 "Machine Instruction Scheduler",
false,
false)
418 "Machine Instruction Scheduler",
false,
false)
422void MachineSchedulerLegacy::getAnalysisUsage(
AnalysisUsage &AU)
const {
435char PostMachineSchedulerLegacy::ID = 0;
440 "PostRA Machine Instruction Scheduler",
false,
false)
447PostMachineSchedulerLegacy::PostMachineSchedulerLegacy()
450void PostMachineSchedulerLegacy::getAnalysisUsage(
AnalysisUsage &AU)
const {
472 cl::desc(
"Machine instruction scheduler to use"));
480 cl::desc(
"Enable the machine instruction scheduling pass."),
cl::init(
true),
484 "enable-post-misched",
485 cl::desc(
"Enable the post-ra machine instruction scheduling pass."),
492 assert(
I != Beg &&
"reached the top of the region, cannot decrement");
494 if (!
I->isDebugOrPseudoInstr())
513 for(;
I != End; ++
I) {
514 if (!
I->isDebugOrPseudoInstr())
556 const char *MSchedBanner =
"Before machine scheduling.";
558 MF->verify(P, MSchedBanner, &
errs());
560 MF->verify(*MFAM, MSchedBanner, &
errs());
570 const char *MSchedBanner =
"After machine scheduling.";
572 MF->verify(P, MSchedBanner, &
errs());
574 MF->verify(*MFAM, MSchedBanner, &
errs());
601 const char *PostMSchedBanner =
"Before post machine scheduling.";
603 MF->verify(P, PostMSchedBanner, &
errs());
605 MF->verify(*MFAM, PostMSchedBanner, &
errs());
614 const char *PostMSchedBanner =
"After post machine scheduling.";
616 MF->verify(P, PostMSchedBanner, &
errs());
618 MF->verify(*MFAM, PostMSchedBanner, &
errs());
639bool MachineSchedulerLegacy::runOnMachineFunction(
MachineFunction &MF) {
652 auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
653 auto &TM = getAnalysis<TargetPassConfig>().getTM<
TargetMachine>();
654 auto &
AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
655 auto &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
657 getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
658 auto &MBFI = getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
660 Impl.setLegacyPass(
this);
661 return Impl.run(MF, TM, {MLI,
AA, LIS, RegClassInfo, MBFI});
665 : Impl(
std::make_unique<MachineSchedulerImpl>()), TM(TM) {}
671 : Impl(
std::make_unique<PostMachineSchedulerImpl>()), TM(TM) {}
695 Impl->setMFAM(&MFAM);
696 bool Changed = Impl->run(MF, *TM, {MLI,
AA, LIS, RegClassInfo, MBFI});
702 .preserve<SlotIndexesAnalysis>()
706bool PostMachineSchedulerLegacy::runOnMachineFunction(
MachineFunction &MF) {
718 auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
719 auto &TM = getAnalysis<TargetPassConfig>().getTM<
TargetMachine>();
720 auto &
AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
721 Impl.setLegacyPass(
this);
722 return Impl.run(MF, TM, {MLI,
AA});
741 Impl->setMFAM(&MFAM);
742 bool Changed = Impl->run(MF, *TM, {MLI,
AA});
765 return MI->isCall() ||
TII->isSchedulingBoundary(*
MI,
MBB, *MF) ||
774 bool RegionsTopDown) {
780 RegionEnd !=
MBB->begin(); RegionEnd =
I) {
783 if (RegionEnd !=
MBB->end() ||
790 unsigned NumRegionInstrs = 0;
792 for (;
I !=
MBB->begin(); --
I) {
796 if (!
MI.isDebugOrPseudoInstr()) {
805 if (NumRegionInstrs != 0)
810 std::reverse(Regions.
begin(), Regions.
end());
848 bool ScheduleSingleMI =
Scheduler.shouldScheduleSingleMIRegions();
852 unsigned NumRegionInstrs = R.NumRegionInstrs;
860 if (
I == RegionEnd || (!ScheduleSingleMI &&
I == std::prev(RegionEnd))) {
866 auto DumpRegionHeader = [&] {
867 dbgs() <<
"Current Schedule Region\n";
869 <<
MBB->getName() <<
"\n From: " << *
I <<
" To: ";
870 if (RegionEnd !=
MBB->end())
871 dbgs() << *RegionEnd;
874 dbgs() <<
" RegionInstrs: " << NumRegionInstrs <<
'\n';
882 errs() <<
":%bb. " <<
MBB->getNumber();
883 errs() <<
" " <<
MBB->getName() <<
" \n";
903#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
905 dbgs() <<
"Queue " << Name <<
": ";
906 for (
const SUnit *SU : Queue)
907 dbgs() << SU->NodeNum <<
" ";
934 dbgs() <<
"*** Scheduling failed! ***\n";
936 dbgs() <<
" has been released too many times!\n";
969 dbgs() <<
"*** Scheduling failed! ***\n";
971 dbgs() <<
" has been released too many times!\n";
1008 unsigned regioninstrs)
1018 else if (
SchedImpl->getPolicy().OnlyBottomUp)
1034 BB->splice(InsertPos,
BB,
MI);
1038 LIS->handleMove(*
MI,
true);
1046#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
1051 ++NumInstrsScheduled;
1083 bool IsTopNode =
false;
1088 LLVM_DEBUG(
dbgs() <<
"** ScheduleDAGMI::schedule picking next node\n");
1105 if (&*priorII ==
MI)
1127 dbgs() <<
"*** Final schedule for "
1144 assert(!SU.isBoundaryNode() &&
"Boundary node should not be in SUnits");
1147 SU.biasCriticalPath();
1150 if (!SU.NumPredsLeft)
1153 if (!SU.NumSuccsLeft)
1156 ExitSU.biasCriticalPath();
1166 for (
SUnit *SU : TopRoots)
1205 for (std::vector<std::pair<MachineInstr *, MachineInstr *>>
::iterator
1207 std::pair<MachineInstr *, MachineInstr *>
P = *std::prev(DI);
1218#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1230 dbgs() <<
" * Schedule table (TopDown):\n";
1248 for (
unsigned C = FirstCycle;
C <= LastCycle; ++
C)
1255 dbgs() <<
"Missing SUnit\n";
1258 std::string NodeName(
"SU(");
1259 NodeName += std::to_string(SU->
NodeNum) +
")";
1261 unsigned C = FirstCycle;
1262 for (;
C <= LastCycle; ++
C) {
1280 return std::tie(LHS.AcquireAtCycle, LHS.ReleaseAtCycle) <
1281 std::tie(RHS.AcquireAtCycle, RHS.ReleaseAtCycle);
1285 const std::string ResName =
1286 SchedModel.getResourceName(PI.ProcResourceIdx);
1291 for (
unsigned I = 0, E = PI.ReleaseAtCycle - PI.AcquireAtCycle;
I != E;
1294 while (
C++ <= LastCycle)
1311 dbgs() <<
" * Schedule table (BottomUp):\n";
1324 if ((
int)SU->
BotReadyCycle - PI->ReleaseAtCycle + 1 < LastCycle)
1325 LastCycle = (int)SU->
BotReadyCycle - PI->ReleaseAtCycle + 1;
1330 for (
int C = FirstCycle;
C >= LastCycle; --
C)
1337 dbgs() <<
"Missing SUnit\n";
1340 std::string NodeName(
"SU(");
1341 NodeName += std::to_string(SU->
NodeNum) +
")";
1344 for (;
C >= LastCycle; --
C) {
1361 return std::tie(LHS.AcquireAtCycle, LHS.ReleaseAtCycle) <
1362 std::tie(RHS.AcquireAtCycle, RHS.ReleaseAtCycle);
1366 const std::string ResName =
1367 SchedModel.getResourceName(PI.ProcResourceIdx);
1372 for (
unsigned I = 0, E = PI.ReleaseAtCycle - PI.AcquireAtCycle;
I != E;
1375 while (
C-- >= LastCycle)
1384#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1392 dbgs() <<
"* Schedule table (Bidirectional): not implemented\n";
1394 dbgs() <<
"* Schedule table: DumpDirection not set.\n";
1402 dbgs() <<
"Missing SUnit\n";
1427 if (!Reg.isVirtual())
1432 bool FoundDef =
false;
1434 if (MO2.getReg() == Reg && !MO2.isDead()) {
1445 for (; UI !=
VRegUses.end(); ++UI) {
1461 unsigned regioninstrs)
1475 "ShouldTrackLaneMasks requires ShouldTrackPressure");
1526 dbgs() <<
"Bottom Pressure: ";
1532 "Can't find the region bottom");
1540 unsigned Limit =
RegClassInfo->getRegPressureSetLimit(i);
1549 dbgs() <<
"Excess PSets: ";
1551 dbgs() <<
TRI->getRegPressureSetName(RCPS.getPSet()) <<
" ";
1559 const std::vector<unsigned> &NewMaxPressure) {
1565 unsigned ID = PC.getPSet();
1570 && NewMaxPressure[ID] <= (
unsigned)std::numeric_limits<int16_t>::max())
1573 unsigned Limit =
RegClassInfo->getRegPressureSetLimit(ID);
1574 if (NewMaxPressure[ID] >= Limit - 2) {
1576 << NewMaxPressure[ID]
1577 << ((NewMaxPressure[ID] > Limit) ?
" > " :
" <= ")
1589 if (!
P.VRegOrUnit.isVirtualReg())
1591 Register Reg =
P.VRegOrUnit.asVirtualReg();
1598 bool Decrement =
P.LaneMask.any();
1602 SUnit &SU = *V2SU.SU;
1612 <<
" UpdateRegPressure: " << SU <<
" "
1635 assert(VNI &&
"No live value at use.");
1638 SUnit *SU = V2SU.SU;
1662#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1663 if (
EntrySU.getInstr() !=
nullptr)
1668 dbgs() <<
" Pressure Diff : ";
1671 dbgs() <<
" Single Issue : ";
1672 if (
SchedModel.mustBeginGroup(SU.getInstr()) &&
1679 if (
ExitSU.getInstr() !=
nullptr)
1715 bool IsTopNode =
false;
1720 LLVM_DEBUG(
dbgs() <<
"** ScheduleDAGMILive::schedule picking next node\n");
1729 unsigned SubtreeID =
DFSResult->getSubtreeID(SU);
1747 dbgs() <<
"*** Final schedule for "
1816 if (!
BB->isSuccessor(
BB))
1819 unsigned MaxCyclicLatency = 0;
1822 if (!
P.VRegOrUnit.isVirtualReg())
1824 Register Reg =
P.VRegOrUnit.asVirtualReg();
1835 unsigned LiveOutHeight = DefSU->
getHeight();
1840 SUnit *SU = V2SU.SU;
1852 unsigned CyclicLatency = 0;
1854 CyclicLatency = LiveOutDepth - SU->
getDepth();
1857 if (LiveInHeight > LiveOutHeight) {
1858 if (LiveInHeight - LiveOutHeight < CyclicLatency)
1859 CyclicLatency = LiveInHeight - LiveOutHeight;
1863 LLVM_DEBUG(
dbgs() <<
"Cyclic Path: " << *DefSU <<
" -> " << *SU <<
" = "
1864 << CyclicLatency <<
"c\n");
1865 if (CyclicLatency > MaxCyclicLatency)
1866 MaxCyclicLatency = CyclicLatency;
1869 LLVM_DEBUG(
dbgs() <<
"Cyclic Critical Path: " << MaxCyclicLatency <<
"c\n");
1870 return MaxCyclicLatency;
1922 if (&*priorII ==
MI)
1973 bool OffsetIsScalable;
1977 : SU(SU), BaseOps(BaseOps),
Offset(
Offset), Width(Width),
1978 OffsetIsScalable(OffsetIsScalable) {}
1982 if (
A->getType() !=
B->getType())
1983 return A->getType() <
B->getType();
1985 return A->getReg() <
B->getReg();
1997 if (AIsFixed != BIsFixed)
1998 return StackGrowsDown ? !AIsFixed : AIsFixed;
2006 if (AOffset != BOffset)
2007 return AOffset < BOffset;
2009 return StackGrowsDown ?
A->getIndex() >
B->getIndex()
2010 :
A->getIndex() <
B->getIndex();
2020 if (std::lexicographical_compare(BaseOps.
begin(), BaseOps.
end(),
2021 RHS.BaseOps.begin(),
RHS.BaseOps.end(),
2024 if (std::lexicographical_compare(
RHS.BaseOps.begin(),
RHS.BaseOps.end(),
2025 BaseOps.
begin(), BaseOps.
end(), Compare))
2033 const TargetInstrInfo *
TII;
2034 const TargetRegisterInfo *
TRI;
2036 bool ReorderWhileClustering;
2039 BaseMemOpClusterMutation(
const TargetInstrInfo *tii,
2040 const TargetRegisterInfo *tri,
bool IsLoad,
2041 bool ReorderWhileClustering)
2042 :
TII(tii),
TRI(tri), IsLoad(IsLoad),
2043 ReorderWhileClustering(ReorderWhileClustering) {}
2045 void apply(ScheduleDAGInstrs *DAGInstrs)
override;
2049 ScheduleDAGInstrs *DAG);
2050 void collectMemOpRecords(std::vector<SUnit> &SUnits,
2051 SmallVectorImpl<MemOpInfo> &MemOpRecords);
2056class StoreClusterMutation :
public BaseMemOpClusterMutation {
2058 StoreClusterMutation(
const TargetInstrInfo *tii,
2059 const TargetRegisterInfo *tri,
2060 bool ReorderWhileClustering)
2061 : BaseMemOpClusterMutation(tii, tri,
false, ReorderWhileClustering) {}
2064class LoadClusterMutation :
public BaseMemOpClusterMutation {
2066 LoadClusterMutation(
const TargetInstrInfo *tii,
const TargetRegisterInfo *tri,
2067 bool ReorderWhileClustering)
2068 : BaseMemOpClusterMutation(tii, tri,
true, ReorderWhileClustering) {}
2073std::unique_ptr<ScheduleDAGMutation>
2076 bool ReorderWhileClustering) {
2078 TII,
TRI, ReorderWhileClustering)
2082std::unique_ptr<ScheduleDAGMutation>
2085 bool ReorderWhileClustering) {
2087 TII,
TRI, ReorderWhileClustering)
2096void BaseMemOpClusterMutation::clusterNeighboringMemOps(
2105 for (
unsigned Idx = 0, End = MemOpRecords.
size(); Idx < (End - 1); ++Idx) {
2107 auto MemOpa = MemOpRecords[Idx];
2110 unsigned NextIdx = Idx + 1;
2111 for (; NextIdx < End; ++NextIdx)
2114 if (!SUnit2ClusterInfo.
count(MemOpRecords[NextIdx].SU->NodeNum) &&
2116 (!DAG->
IsReachable(MemOpRecords[NextIdx].SU, MemOpa.SU) &&
2117 !DAG->
IsReachable(MemOpa.SU, MemOpRecords[NextIdx].SU))))
2122 auto MemOpb = MemOpRecords[NextIdx];
2123 unsigned ClusterLength = 2;
2124 unsigned CurrentClusterBytes = MemOpa.Width.getValue().getKnownMinValue() +
2125 MemOpb.Width.getValue().getKnownMinValue();
2126 auto It = SUnit2ClusterInfo.
find(MemOpa.SU->NodeNum);
2127 if (It != SUnit2ClusterInfo.
end()) {
2128 const auto &[Len, Bytes] = It->second;
2129 ClusterLength = Len + 1;
2130 CurrentClusterBytes = Bytes + MemOpb.Width.getValue().getKnownMinValue();
2133 if (!
TII->shouldClusterMemOps(MemOpa.BaseOps, MemOpa.Offset,
2134 MemOpa.OffsetIsScalable, MemOpb.BaseOps,
2135 MemOpb.Offset, MemOpb.OffsetIsScalable,
2136 ClusterLength, CurrentClusterBytes))
2139 SUnit *SUa = MemOpa.SU;
2140 SUnit *SUb = MemOpb.SU;
2150 LLVM_DEBUG(
dbgs() <<
"Cluster ld/st " << *SUa <<
" - " << *SUb <<
"\n");
2180 SUnit2ClusterInfo[MemOpb.SU->NodeNum] = {ClusterLength,
2181 CurrentClusterBytes};
2184 <<
", Curr cluster bytes: " << CurrentClusterBytes
2195 unsigned ClusterIdx = AllClusters.size();
2197 MemberI->ParentClusterIdx = ClusterIdx;
2200 AllClusters.push_back(Group);
2204void BaseMemOpClusterMutation::collectMemOpRecords(
2206 for (
auto &SU : SUnits) {
2214 bool OffsetIsScalable;
2217 OffsetIsScalable, Width,
TRI)) {
2222 MemOpInfo(&SU, BaseOps,
Offset, OffsetIsScalable, Width));
2225 <<
Offset <<
", OffsetIsScalable: " << OffsetIsScalable
2226 <<
", Width: " << Width <<
"\n");
2229 for (
const auto *
Op : BaseOps)
2235bool BaseMemOpClusterMutation::groupMemOps(
2242 for (
const auto &
MemOp : MemOps) {
2243 unsigned ChainPredID = DAG->
SUnits.size();
2245 for (
const SDep &Pred :
MemOp.SU->Preds) {
2269 collectMemOpRecords(DAG->
SUnits, MemOpRecords);
2271 if (MemOpRecords.
size() < 2)
2278 bool FastCluster = groupMemOps(MemOpRecords, DAG,
Groups);
2280 for (
auto &Group :
Groups) {
2286 clusterNeighboringMemOps(Group.second, FastCluster, DAG);
2301 SlotIndex RegionBeginIdx;
2305 SlotIndex RegionEndIdx;
2308 CopyConstrain(
const TargetInstrInfo *,
const TargetRegisterInfo *) {}
2310 void apply(ScheduleDAGInstrs *DAGInstrs)
override;
2313 void constrainLocalCopy(SUnit *CopySU, ScheduleDAGMILive *DAG);
2318std::unique_ptr<ScheduleDAGMutation>
2321 return std::make_unique<CopyConstrain>(
TII,
TRI);
2364 unsigned LocalReg = SrcReg;
2365 unsigned GlobalReg = DstReg;
2367 if (!LocalLI->
isLocal(RegionBeginIdx, RegionEndIdx)) {
2371 if (!LocalLI->
isLocal(RegionBeginIdx, RegionEndIdx))
2382 if (GlobalSegment == GlobalLI->
end())
2389 if (GlobalSegment->contains(LocalLI->
beginIndex()))
2392 if (GlobalSegment == GlobalLI->
end())
2396 if (GlobalSegment != GlobalLI->
begin()) {
2399 GlobalSegment->start)) {
2410 assert(std::prev(GlobalSegment)->start < LocalLI->beginIndex() &&
2411 "Disconnected LRG within the scheduling region.");
2427 for (
const SDep &Succ : LastLocalSU->
Succs) {
2442 for (
const SDep &Pred : GlobalSU->
Preds) {
2445 if (Pred.
getSUnit() == FirstLocalSU)
2453 for (
SUnit *LU : LocalUses) {
2454 LLVM_DEBUG(
dbgs() <<
" Local use SU(" << LU->NodeNum <<
") -> SU("
2455 << GlobalSU->
NodeNum <<
")\n");
2458 for (
SUnit *GU : GlobalUses) {
2459 LLVM_DEBUG(
dbgs() <<
" Global use " << *GU <<
" -> " << *FirstLocalSU
2472 if (FirstPos == DAG->
end())
2500 unsigned Latency,
bool AfterSchedNode) {
2503 return ResCntFactor >= (int)LFactor;
2505 return ResCntFactor > (int)LFactor;
2516 CheckPending =
false;
2519 MinReadyCycle = std::numeric_limits<unsigned>::max();
2520 ExpectedLatency = 0;
2521 DependentLatency = 0;
2523 MaxExecutedResCount = 0;
2525 IsResourceLimited =
false;
2526 ReservedCycles.clear();
2527 ReservedResourceSegments.clear();
2528 ReservedCyclesIndex.clear();
2529 ResourceGroupSubUnitMasks.clear();
2530#if LLVM_ENABLE_ABI_BREAKING_CHECKS
2534 MaxObservedStall = 0;
2537 ExecutedResCounts.resize(1);
2538 assert(!ExecutedResCounts[0] &&
"nonzero count for bad resource");
2554 unsigned PIdx = PI->ProcResourceIdx;
2556 assert(PI->ReleaseAtCycle >= PI->AcquireAtCycle);
2558 (Factor * (PI->ReleaseAtCycle - PI->AcquireAtCycle));
2570 unsigned ResourceCount =
SchedModel->getNumProcResourceKinds();
2571 ReservedCyclesIndex.resize(ResourceCount);
2572 ExecutedResCounts.resize(ResourceCount);
2573 ResourceGroupSubUnitMasks.resize(ResourceCount,
APInt(ResourceCount, 0));
2574 unsigned NumUnits = 0;
2576 for (
unsigned i = 0; i < ResourceCount; ++i) {
2577 ReservedCyclesIndex[i] = NumUnits;
2578 NumUnits +=
SchedModel->getProcResource(i)->NumUnits;
2580 auto SubUnits =
SchedModel->getProcResource(i)->SubUnitsIdxBegin;
2581 for (
unsigned U = 0, UE =
SchedModel->getProcResource(i)->NumUnits;
2583 ResourceGroupSubUnitMasks[i].setBit(SubUnits[U]);
2603 if (ReadyCycle > CurrCycle)
2604 return ReadyCycle - CurrCycle;
2611 unsigned ReleaseAtCycle,
2612 unsigned AcquireAtCycle) {
2615 return ReservedResourceSegments[InstanceIdx].getFirstAvailableAtFromTop(
2616 CurrCycle, AcquireAtCycle, ReleaseAtCycle);
2618 return ReservedResourceSegments[InstanceIdx].getFirstAvailableAtFromBottom(
2619 CurrCycle, AcquireAtCycle, ReleaseAtCycle);
2622 unsigned NextUnreserved = ReservedCycles[InstanceIdx];
2628 NextUnreserved = std::max(CurrCycle, NextUnreserved + ReleaseAtCycle);
2629 return NextUnreserved;
2635std::pair<unsigned, unsigned>
2637 unsigned ReleaseAtCycle,
2638 unsigned AcquireAtCycle) {
2640 LLVM_DEBUG(
dbgs() <<
" Resource booking (@" << CurrCycle <<
"c): \n");
2642 LLVM_DEBUG(
dbgs() <<
" getNextResourceCycle (@" << CurrCycle <<
"c): \n");
2645 unsigned InstanceIdx = 0;
2646 unsigned StartIndex = ReservedCyclesIndex[PIdx];
2647 unsigned NumberOfInstances =
SchedModel->getProcResource(PIdx)->NumUnits;
2648 assert(NumberOfInstances > 0 &&
2649 "Cannot have zero instances of a ProcResource");
2666 if (ResourceGroupSubUnitMasks[PIdx][PE.ProcResourceIdx])
2668 StartIndex, ReleaseAtCycle, AcquireAtCycle),
2671 auto SubUnits =
SchedModel->getProcResource(PIdx)->SubUnitsIdxBegin;
2672 for (
unsigned I = 0, End = NumberOfInstances;
I < End; ++
I) {
2673 unsigned NextUnreserved, NextInstanceIdx;
2674 std::tie(NextUnreserved, NextInstanceIdx) =
2676 if (MinNextUnreserved > NextUnreserved) {
2677 InstanceIdx = NextInstanceIdx;
2678 MinNextUnreserved = NextUnreserved;
2681 return std::make_pair(MinNextUnreserved, InstanceIdx);
2684 for (
unsigned I = StartIndex, End = StartIndex + NumberOfInstances;
I < End;
2686 unsigned NextUnreserved =
2690 << NextUnreserved <<
"c\n");
2691 if (MinNextUnreserved > NextUnreserved) {
2693 MinNextUnreserved = NextUnreserved;
2698 <<
"[" << InstanceIdx - StartIndex <<
"]"
2699 <<
" available @" << MinNextUnreserved <<
"c"
2701 return std::make_pair(MinNextUnreserved, InstanceIdx);
2721 <<
"hazard: " << *SU <<
" reported by HazardRec\n");
2726 if ((CurrMOps > 0) && (CurrMOps + uops >
SchedModel->getIssueWidth())) {
2728 <<
", CurrMOps = " << CurrMOps <<
", "
2729 <<
"CurrMOps + uops > issue width of "
2738 << (
isTop() ?
"begin" :
"end") <<
" group\n");
2747 unsigned ResIdx = PE.ProcResourceIdx;
2748 unsigned ReleaseAtCycle = PE.ReleaseAtCycle;
2749 unsigned AcquireAtCycle = PE.AcquireAtCycle;
2750 unsigned NRCycle, InstanceIdx;
2751 std::tie(NRCycle, InstanceIdx) =
2753 if (NRCycle > CurrCycle) {
2754#if LLVM_ENABLE_ABI_BREAKING_CHECKS
2755 MaxObservedStall = std::max(ReleaseAtCycle, MaxObservedStall);
2758 <<
"hazard: " << *SU <<
" "
2759 <<
SchedModel->getResourceName(ResIdx) <<
'['
2760 << InstanceIdx - ReservedCyclesIndex[ResIdx] <<
']' <<
"="
2761 << NRCycle <<
"c, is later than "
2762 <<
"CurrCycle = " << CurrCycle <<
"c\n");
2773 SUnit *LateSU =
nullptr;
2774 unsigned RemLatency = 0;
2775 for (
SUnit *SU : ReadySUs) {
2777 if (L > RemLatency) {
2784 << RemLatency <<
"c\n");
2798 unsigned OtherCritCount =
Rem->RemIssueCount
2799 + (RetiredMOps *
SchedModel->getMicroOpFactor());
2801 << OtherCritCount /
SchedModel->getMicroOpFactor() <<
'\n');
2802 for (
unsigned PIdx = 1, PEnd =
SchedModel->getNumProcResourceKinds();
2803 PIdx != PEnd; ++PIdx) {
2805 if (OtherCount > OtherCritCount) {
2806 OtherCritCount = OtherCount;
2807 OtherCritIdx = PIdx;
2812 dbgs() <<
" " <<
Available.getName() <<
" + Remain CritRes: "
2813 << OtherCritCount /
SchedModel->getResourceFactor(OtherCritIdx)
2814 <<
" " <<
SchedModel->getResourceName(OtherCritIdx) <<
"\n");
2816 return OtherCritCount;
2823#if LLVM_ENABLE_ABI_BREAKING_CHECKS
2827 if (ReadyCycle > CurrCycle)
2828 MaxObservedStall = std::max(ReadyCycle - CurrCycle, MaxObservedStall);
2831 if (ReadyCycle < MinReadyCycle)
2832 MinReadyCycle = ReadyCycle;
2836 bool IsBuffered =
SchedModel->getMicroOpBufferSize() != 0;
2837 bool HazardDetected = !IsBuffered && ReadyCycle > CurrCycle;
2840 <<
"hazard: " << *SU <<
" ReadyCycle = " << ReadyCycle
2841 <<
" is later than CurrCycle = " << CurrCycle
2842 <<
" on an unbuffered resource" <<
"\n");
2847 HazardDetected =
true;
2852 if (!HazardDetected) {
2867 if (
SchedModel->getMicroOpBufferSize() == 0) {
2868 assert(MinReadyCycle < std::numeric_limits<unsigned>::max() &&
2869 "MinReadyCycle uninitialized");
2870 if (MinReadyCycle > NextCycle)
2871 NextCycle = MinReadyCycle;
2874 unsigned DecMOps =
SchedModel->getIssueWidth() * (NextCycle - CurrCycle);
2875 CurrMOps = (CurrMOps <= DecMOps) ? 0 : CurrMOps - DecMOps;
2878 if ((NextCycle - CurrCycle) > DependentLatency)
2879 DependentLatency = 0;
2881 DependentLatency -= (NextCycle - CurrCycle);
2885 CurrCycle = NextCycle;
2888 for (; CurrCycle != NextCycle; ++CurrCycle) {
2895 CheckPending =
true;
2905 ExecutedResCounts[PIdx] +=
Count;
2906 if (ExecutedResCounts[PIdx] > MaxExecutedResCount)
2907 MaxExecutedResCount = ExecutedResCounts[PIdx];
2921 unsigned ReleaseAtCycle,
2923 unsigned AcquireAtCycle) {
2924 unsigned Factor =
SchedModel->getResourceFactor(PIdx);
2925 unsigned Count = Factor * (ReleaseAtCycle- AcquireAtCycle);
2927 << ReleaseAtCycle <<
"x" << Factor <<
"u\n");
2931 assert(
Rem->RemainingCounts[PIdx] >=
Count &&
"resource double counted");
2932 Rem->RemainingCounts[PIdx] -=
Count;
2937 ZoneCritResIdx = PIdx;
2944 unsigned NextAvailable, InstanceIdx;
2945 std::tie(NextAvailable, InstanceIdx) =
2947 if (NextAvailable > CurrCycle) {
2950 <<
'[' << InstanceIdx - ReservedCyclesIndex[PIdx] <<
']'
2951 <<
" reserved until @" << NextAvailable <<
"\n");
2953 return NextAvailable;
2963 (CurrMOps == 0 || (CurrMOps + IncMOps) <=
SchedModel->getIssueWidth()) &&
2964 "Cannot schedule this instruction's MicroOps in the current cycle.");
2969 unsigned NextCycle = CurrCycle;
2970 switch (
SchedModel->getMicroOpBufferSize()) {
2972 assert(ReadyCycle <= CurrCycle &&
"Broken PendingQueue");
2975 if (ReadyCycle > NextCycle) {
2976 NextCycle = ReadyCycle;
2977 LLVM_DEBUG(
dbgs() <<
" *** Stall until: " << ReadyCycle <<
"\n");
2986 NextCycle = ReadyCycle;
2989 RetiredMOps += IncMOps;
2993 unsigned DecRemIssue = IncMOps *
SchedModel->getMicroOpFactor();
2994 assert(
Rem->RemIssueCount >= DecRemIssue &&
"MOps double counted");
2995 Rem->RemIssueCount -= DecRemIssue;
2996 if (ZoneCritResIdx) {
2998 unsigned ScaledMOps =
2999 RetiredMOps *
SchedModel->getMicroOpFactor();
3007 << ScaledMOps /
SchedModel->getLatencyFactor()
3013 PE =
SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
3015 countResource(SC, PI->ProcResourceIdx, PI->ReleaseAtCycle, NextCycle,
3016 PI->AcquireAtCycle);
3017 if (RCycle > NextCycle)
3027 PE =
SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
3028 unsigned PIdx = PI->ProcResourceIdx;
3029 if (
SchedModel->getResourceBufferSize(PIdx) == 0) {
3032 unsigned ReservedUntil, InstanceIdx;
3034 SC, PIdx, PI->ReleaseAtCycle, PI->AcquireAtCycle);
3036 ReservedResourceSegments[InstanceIdx].add(
3038 NextCycle, PI->AcquireAtCycle, PI->ReleaseAtCycle),
3041 ReservedResourceSegments[InstanceIdx].add(
3043 NextCycle, PI->AcquireAtCycle, PI->ReleaseAtCycle),
3048 unsigned ReservedUntil, InstanceIdx;
3050 SC, PIdx, PI->ReleaseAtCycle, PI->AcquireAtCycle);
3052 ReservedCycles[InstanceIdx] =
3053 std::max(ReservedUntil, NextCycle + PI->ReleaseAtCycle);
3055 ReservedCycles[InstanceIdx] = NextCycle;
3062 unsigned &TopLatency =
isTop() ? ExpectedLatency : DependentLatency;
3063 unsigned &BotLatency =
isTop() ? DependentLatency : ExpectedLatency;
3067 <<
" " << TopLatency <<
"c\n");
3072 <<
" " << BotLatency <<
"c\n");
3075 if (NextCycle > CurrCycle)
3093 CheckPending =
true;
3100 CurrMOps += IncMOps;
3113 while (CurrMOps >=
SchedModel->getIssueWidth()) {
3114 LLVM_DEBUG(
dbgs() <<
" *** Max MOps " << CurrMOps <<
" at cycle "
3115 << CurrCycle <<
'\n');
3126 MinReadyCycle = std::numeric_limits<unsigned>::max();
3130 for (
unsigned I = 0, E =
Pending.size();
I < E; ++
I) {
3136 if (ReadyCycle < MinReadyCycle)
3137 MinReadyCycle = ReadyCycle;
3148 CheckPending =
false;
3177 for (
unsigned i = 0;
Available.empty(); ++i) {
3194#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3203 unsigned ResourceCount =
SchedModel->getNumProcResourceKinds();
3204 unsigned StartIdx = 0;
3206 for (
unsigned ResIdx = 0; ResIdx < ResourceCount; ++ResIdx) {
3207 const unsigned NumUnits =
SchedModel->getProcResource(ResIdx)->NumUnits;
3208 std::string ResName =
SchedModel->getResourceName(ResIdx);
3209 for (
unsigned UnitIdx = 0; UnitIdx < NumUnits; ++UnitIdx) {
3210 dbgs() << ResName <<
"(" << UnitIdx <<
") = ";
3212 if (ReservedResourceSegments.count(StartIdx + UnitIdx))
3213 dbgs() << ReservedResourceSegments.at(StartIdx + UnitIdx);
3217 dbgs() << ReservedCycles[StartIdx + UnitIdx] <<
"\n";
3219 StartIdx += NumUnits;
3228 if (ZoneCritResIdx) {
3229 ResFactor =
SchedModel->getResourceFactor(ZoneCritResIdx);
3233 ResCount = RetiredMOps * ResFactor;
3235 unsigned LFactor =
SchedModel->getLatencyFactor();
3237 <<
" Retired: " << RetiredMOps;
3239 dbgs() <<
"\n Critical: " << ResCount / LFactor <<
"c, "
3240 << ResCount / ResFactor <<
" "
3241 <<
SchedModel->getResourceName(ZoneCritResIdx)
3242 <<
"\n ExpectedLatency: " << ExpectedLatency <<
"c\n"
3243 << (IsResourceLimited ?
" - Resource" :
" - Latency")
3263 PE =
SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
3264 if (PI->ProcResourceIdx ==
Policy.ReduceResIdx)
3265 ResDelta.CritResources += PI->ReleaseAtCycle;
3266 if (PI->ProcResourceIdx ==
Policy.DemandResIdx)
3267 ResDelta.DemandedResources += PI->ReleaseAtCycle;
3273bool GenericSchedulerBase::shouldReduceLatency(
const CandPolicy &Policy,
3275 bool ComputeRemLatency,
3276 unsigned &RemLatency)
const {
3286 if (ComputeRemLatency)
3302 unsigned OtherCritIdx = 0;
3303 unsigned OtherCount =
3306 bool OtherResLimited =
false;
3307 unsigned RemLatency = 0;
3308 bool RemLatencyComputed =
false;
3309 if (
SchedModel->hasInstrSchedModel() && OtherCount != 0) {
3311 RemLatencyComputed =
true;
3313 OtherCount, RemLatency,
false);
3319 if (!OtherResLimited &&
3320 (IsPostRA || shouldReduceLatency(Policy, CurrZone, !RemLatencyComputed,
3324 <<
" RemainingLatency " << RemLatency <<
" + "
3326 <<
Rem.CriticalPath <<
"\n");
3333 dbgs() <<
" " << CurrZone.Available.getName() <<
" ResourceLimited: "
3334 << SchedModel->getResourceName(CurrZone.getZoneCritResIdx()) <<
"\n";
3335 }
if (OtherResLimited)
dbgs()
3336 <<
" RemainingLimit: "
3337 <<
SchedModel->getResourceName(OtherCritIdx) <<
"\n";
3339 <<
" Latency limited both directions.\n");
3344 if (OtherResLimited)
3353 case NoCand:
return "NOCAND ";
3354 case Only1:
return "ONLY1 ";
3355 case PhysReg:
return "PHYS-REG ";
3358 case Stall:
return "STALL ";
3359 case Cluster:
return "CLUSTER ";
3360 case Weak:
return "WEAK ";
3361 case RegMax:
return "REG-MAX ";
3377 unsigned ResIdx = 0;
3412 dbgs() <<
" " <<
TRI->getRegPressureSetName(
P.getPSet())
3413 <<
":" <<
P.getUnitInc() <<
" ";
3417 dbgs() <<
" " <<
SchedModel->getProcResource(ResIdx)->Name <<
" ";
3446 RemLatency = std::max(RemLatency,
3448 RemLatency = std::max(RemLatency,
3460 if (TryVal < CandVal) {
3464 if (TryVal > CandVal) {
3465 if (Cand.
Reason > Reason)
3476 if (TryVal > CandVal) {
3480 if (TryVal < CandVal) {
3481 if (Cand.
Reason > Reason)
3523 const bool IsTop,
const bool IsPostRA =
false) {
3524 assert(SU &&
"SU must not be null for tracing");
3525 LLVM_DEBUG(
dbgs() <<
"Pick " << (IsTop ?
"Top " :
"Bot ") <<
"Cand " << *SU
3527 << (IsPostRA ?
"post-RA" :
"pre-RA") <<
"]\n");
3546 NumRegExcessPostRA++;
3549 NumRegCriticalPostRA++;
3564 NumResourceReducePostRA++;
3567 NumResourceDemandPostRA++;
3570 NumTopDepthReducePostRA++;
3573 NumTopPathReducePostRA++;
3576 NumBotHeightReducePostRA++;
3579 NumBotPathReducePostRA++;
3582 NumNodeOrderPostRA++;
3585 NumFirstValidPostRA++;
3605 NumRegExcessPreRA++;
3608 NumRegCriticalPreRA++;
3623 NumResourceReducePreRA++;
3626 NumResourceDemandPreRA++;
3629 NumTopDepthReducePreRA++;
3632 NumTopPathReducePreRA++;
3635 NumBotHeightReducePreRA++;
3638 NumBotPathReducePreRA++;
3641 NumNodeOrderPreRA++;
3644 NumFirstValidPreRA++;
3652 const bool IsPostRA =
false) {
3658 "(PreRA)GenericScheduler needs vreg liveness");
3664 DAG->computeDFSResult();
3676 Top.HazardRec.reset(
DAG->TII->CreateTargetMIHazardRecognizer(Itin,
DAG));
3678 Bot.HazardRec.reset(
DAG->TII->CreateTargetMIHazardRecognizer(Itin,
DAG));
3698 for (
unsigned VT = MVT::i64; VT > (
unsigned)MVT::i1; --VT) {
3701 unsigned NIntRegs =
Context->RegClassInfo->getNumAllocatableRegs(
3739#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3740 dbgs() <<
"GenericScheduler RegionPolicy: "
3741 <<
" ShouldTrackPressure=" <<
RegionPolicy.ShouldTrackPressure
3758 if (
Rem.CyclicCritPath == 0 ||
Rem.CyclicCritPath >=
Rem.CriticalPath)
3762 unsigned IterCount =
3763 std::max(
Rem.CyclicCritPath *
SchedModel->getLatencyFactor(),
3766 unsigned AcyclicCount =
Rem.CriticalPath *
SchedModel->getLatencyFactor();
3768 unsigned InFlightCount =
3769 (AcyclicCount *
Rem.RemIssueCount + IterCount-1) / IterCount;
3770 unsigned BufferLimit =
3773 Rem.IsAcyclicLatencyLimited = InFlightCount > BufferLimit;
3776 dbgs() <<
"IssueCycles="
3777 <<
Rem.RemIssueCount /
SchedModel->getLatencyFactor() <<
"c "
3778 <<
"IterCycles=" << IterCount /
SchedModel->getLatencyFactor()
3779 <<
"c NumIters=" << (AcyclicCount + IterCount - 1) / IterCount
3780 <<
" InFlight=" << InFlightCount /
SchedModel->getMicroOpFactor()
3781 <<
"m BufferLim=" <<
SchedModel->getMicroOpBufferSize() <<
"m\n";
3782 if (
Rem.IsAcyclicLatencyLimited)
dbgs() <<
" ACYCLIC LATENCY LIMIT\n");
3786 Rem.CriticalPath =
DAG->ExitSU.getDepth();
3789 for (
const SUnit *SU :
Bot.Available) {
3795 errs() <<
"Critical Path(GS-RR ): " <<
Rem.CriticalPath <<
" \n";
3799 Rem.CyclicCritPath =
DAG->computeCyclicCriticalPath();
3825 if (TryPSet == CandPSet) {
3830 int TryRank = TryP.
isValid() ?
TRI->getRegPressureSetScore(MF, TryPSet) :
3831 std::numeric_limits<int>::max();
3833 int CandRank = CandP.
isValid() ?
TRI->getRegPressureSetScore(MF, CandPSet) :
3834 std::numeric_limits<int>::max();
3839 return tryGreater(TryRank, CandRank, TryCand, Cand, Reason);
3857 unsigned ScheduledOper = isTop ? 1 : 0;
3858 unsigned UnscheduledOper = isTop ? 0 : 1;
3861 if (
MI->getOperand(ScheduledOper).getReg().isPhysical())
3866 if (
MI->getOperand(UnscheduledOper).getReg().isPhysical())
3867 return AtBoundary ? -1 : 1;
3870 if (
MI->isMoveImmediate()) {
3876 if (
Op.isReg() && !
Op.getReg().isPhysical()) {
3883 return isTop ? -1 : 1;
3886 if (BiasPRegsExtra && !isTop &&
MI->getNumExplicitDefs() == 1)
3889 return MI->getOperand(0).getReg().isPhysical();
3899 if (
tryGreater(TryCandPRegBias, CandPRegBias, TryCand, Cand,
3902 if (BiasPRegsExtra && Zone !=
nullptr && TryCandPRegBias &&
3903 TryCandPRegBias == CandPRegBias) {
3922 if (
DAG->isTrackingPressure()) {
3927 DAG->getRegionCriticalPSets(),
3928 DAG->getRegPressure().MaxSetPressure);
3933 &
DAG->getPressureDiff(Cand.
SU),
3935 DAG->getRegionCriticalPSets(),
3936 DAG->getRegPressure().MaxSetPressure);
3940 DAG->getPressureDiff(Cand.
SU),
3942 DAG->getRegionCriticalPSets(),
3943 DAG->getRegPressure().MaxSetPressure);
3948 <<
" Try " << *Cand.
SU <<
" "
3996 bool SameBoundary = Zone !=
nullptr;
4019 bool CandIsClusterSucc =
4021 bool TryCandIsClusterSucc =
4024 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
4032 TryCand, Cand,
Weak))
4057 !
Rem.IsAcyclicLatencyLimited &&
tryLatency(TryCand, Cand, *Zone))
4084 for (
SUnit *SU : Q) {
4104 if (
SUnit *SU =
Bot.pickOnlyChoice()) {
4109 if (
SUnit *SU =
Top.pickOnlyChoice()) {
4126 BotCand.Policy != BotPolicy) {
4138 "Last pick result should correspond to re-picking right now");
4146 TopCand.Policy != TopPolicy) {
4158 "Last pick result should correspond to re-picking right now");
4173 IsTopNode = Cand.
AtTop;
4180 if (
DAG->top() ==
DAG->bottom()) {
4182 Bot.Available.empty() &&
Bot.Pending.empty() &&
"ReadyQ garbage");
4187 SU =
Top.pickOnlyChoice();
4200 SU =
Bot.pickOnlyChoice();
4233 Top.removeReady(SU);
4235 Bot.removeReady(SU);
4241 ++NumInstrsInSourceOrderPreRA;
4245 ++NumInstrsInSourceOrderPreRA;
4248 NumInstrsScheduledPreRA += 1;
4261 for (
SDep &Dep : Deps) {
4262 if (Dep.getKind() !=
SDep::Data || !Dep.getReg().isPhysical())
4264 SUnit *DepSU = Dep.getSUnit();
4265 if (isTop ? DepSU->
Succs.size() > 1 : DepSU->
Preds.size() > 1)
4268 if (!Copy->isCopy() && !Copy->isMoveImmediate())
4271 DAG->dumpNode(*Dep.getSUnit()));
4272 DAG->moveInstruction(Copy, InsertPos);
4290 dbgs() <<
" Top Cluster: ";
4291 for (
auto *
N : *TopCluster)
4292 dbgs() <<
N->NodeNum <<
'\t';
4305 dbgs() <<
" Bot Cluster: ";
4306 for (
auto *
N : *BotCluster)
4307 dbgs() <<
N->NodeNum <<
'\t';
4321static MachineSchedRegistry
4342 Top.HazardRec.reset(
DAG->TII->CreateTargetMIHazardRecognizer(Itin,
DAG));
4344 Bot.HazardRec.reset(
DAG->TII->CreateTargetMIHazardRecognizer(Itin,
DAG));
4380 Rem.CriticalPath =
DAG->ExitSU.getDepth();
4383 for (
const SUnit *SU :
Bot.Available) {
4389 errs() <<
"Critical Path(PGS-RR ): " <<
Rem.CriticalPath <<
" \n";
4408 Top.getLatencyStallCycles(Cand.
SU), TryCand, Cand,
Stall))
4414 bool CandIsClusterSucc =
4416 bool TryCandIsClusterSucc =
4419 if (
tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
4452 for (
SUnit *SU : Q) {
4471 if (
SUnit *SU =
Bot.pickOnlyChoice()) {
4476 if (
SUnit *SU =
Top.pickOnlyChoice()) {
4493 BotCand.Policy != BotPolicy) {
4505 "Last pick result should correspond to re-picking right now");
4513 TopCand.Policy != TopPolicy) {
4525 "Last pick result should correspond to re-picking right now");
4540 IsTopNode = Cand.
AtTop;
4547 if (
DAG->top() ==
DAG->bottom()) {
4549 Bot.Available.empty() &&
Bot.Pending.empty() &&
"ReadyQ garbage");
4554 SU =
Bot.pickOnlyChoice();
4570 SU =
Top.pickOnlyChoice();
4591 Top.removeReady(SU);
4593 Bot.removeReady(SU);
4599 ++NumInstrsInSourceOrderPostRA;
4603 ++NumInstrsInSourceOrderPostRA;
4606 NumInstrsScheduledPostRA += 1;
4634 const BitVector *ScheduledTrees =
nullptr;
4637 ILPOrder(
bool MaxILP) : MaximizeILP(MaxILP) {}
4642 bool operator()(
const SUnit *
A,
const SUnit *
B)
const {
4645 if (SchedTreeA != SchedTreeB) {
4647 if (ScheduledTrees->
test(SchedTreeA) != ScheduledTrees->
test(SchedTreeB))
4648 return ScheduledTrees->
test(SchedTreeB);
4665class ILPScheduler :
public MachineSchedStrategy {
4666 ScheduleDAGMILive *DAG =
nullptr;
4669 std::vector<SUnit*> ReadyQ;
4672 ILPScheduler(
bool MaximizeILP) :
Cmp(MaximizeILP) {}
4674 void initialize(ScheduleDAGMI *dag)
override {
4676 DAG =
static_cast<ScheduleDAGMILive*
>(dag);
4683 void registerRoots()
override {
4685 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4692 SUnit *pickNode(
bool &IsTopNode)
override {
4693 if (ReadyQ.empty())
return nullptr;
4694 std::pop_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4695 SUnit *SU = ReadyQ.back();
4705 <<
"Scheduling " << *SU->
getInstr());
4710 void scheduleTree(
unsigned SubtreeID)
override {
4711 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4716 void schedNode(SUnit *SU,
bool IsTopNode)
override {
4717 assert(!IsTopNode &&
"SchedDFSResult needs bottom-up");
4720 void releaseTopNode(SUnit *)
override { }
4722 void releaseBottomNode(SUnit *SU)
override {
4723 ReadyQ.push_back(SU);
4724 std::push_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4751template<
bool IsReverse>
4755 return A->NodeNum >
B->NodeNum;
4757 return A->NodeNum <
B->NodeNum;
4762class InstructionShuffler :
public MachineSchedStrategy {
4769 PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<false>>
4773 PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<true>>
4777 InstructionShuffler(
bool alternate,
bool topdown)
4778 : IsAlternating(alternate), IsTopDown(topdown) {}
4788 SUnit *pickNode(
bool &IsTopNode)
override {
4792 if (TopQ.empty())
return nullptr;
4799 if (BottomQ.empty())
return nullptr;
4806 IsTopDown = !IsTopDown;
4810 void schedNode(SUnit *SU,
bool IsTopNode)
override {}
4812 void releaseTopNode(SUnit *SU)
override {
4815 void releaseBottomNode(SUnit *SU)
override {
4827 C, std::make_unique<InstructionShuffler>(Alternate, TopDown));
4831 "shuffle",
"Shuffle machine instructions alternating directions",
4850 return std::string(
G->MF.getName());
4870 return "color=cyan,style=dashed";
4872 return "color=blue,style=dashed";
4889 return G->getGraphNodeLabel(SU);
4893 std::string Str(
"shape=Mrecord");
4898 Str +=
",style=filled,fillcolor=\"#";
4914 errs() <<
"ScheduleDAGMI::viewGraph is only available in debug builds on "
4915 <<
"systems with Graphviz or gv!\n";
4930 return A.first <
B.first;
4933unsigned ResourceSegments::getFirstAvailableAt(
4934 unsigned CurrCycle,
unsigned AcquireAtCycle,
unsigned ReleaseAtCycle,
4936 IntervalBuilder)
const {
4938 "Cannot execute on an un-sorted set of intervals.");
4942 if (AcquireAtCycle == ReleaseAtCycle)
4945 unsigned RetCycle = CurrCycle;
4947 IntervalBuilder(RetCycle, AcquireAtCycle, ReleaseAtCycle);
4948 for (
auto &
Interval : _Intervals) {
4955 "Invalid intervals configuration.");
4956 RetCycle += (unsigned)
Interval.second - (
unsigned)NewInterval.first;
4957 NewInterval = IntervalBuilder(RetCycle, AcquireAtCycle, ReleaseAtCycle);
4963 const unsigned CutOff) {
4964 assert(
A.first <=
A.second &&
"Cannot add negative resource usage");
4965 assert(CutOff > 0 &&
"0-size interval history has no use.");
4971 if (
A.first ==
A.second)
4978 "A resource is being overwritten");
4979 _Intervals.push_back(
A);
4985 while (_Intervals.size() > CutOff)
4986 _Intervals.pop_front();
4991 assert(
A.first <=
A.second &&
"Invalid interval");
4992 assert(
B.first <=
B.second &&
"Invalid interval");
4995 if ((
A.first ==
B.first) || (
A.second ==
B.second))
5000 if ((
A.first >
B.first) && (
A.second <
B.second))
5005 if ((
A.first >
B.first) && (
A.first <
B.second) && (
A.second >
B.second))
5010 if ((
A.first <
B.first) && (
B.first <
A.second) && (
B.second >
B.first))
5016void ResourceSegments::sortAndMerge() {
5017 if (_Intervals.size() <= 1)
5024 auto next = std::next(std::begin(_Intervals));
5025 auto E = std::end(_Intervals);
5026 for (; next != E; ++next) {
5027 if (std::prev(next)->second >= next->first) {
5028 next->first = std::prev(next)->first;
5029 _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 > 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 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
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:
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.
void schedNode(SUnit *SU, bool IsTopNode) override
Update the scheduler's state after scheduling a node.
SUnit * pickNodeBidirectional(bool &IsTopNode)
Pick the best candidate node from either the top or bottom queue.
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const override
Get the base register and byte offset of a load/store instr.
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()
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, const 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(const 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...
RegisterPassParser class - Handle the addition of new machine passes.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
LLVM_ABI void add(IntervalTy A, const unsigned CutOff=10)
Adds an interval [a, b) to the collection of the instance.
static IntervalTy getResourceIntervalBottom(unsigned C, unsigned AcquireAtCycle, unsigned ReleaseAtCycle)
These function return the interval used by a resource in bottom and top scheduling.
static LLVM_ABI bool intersects(IntervalTy A, IntervalTy B)
Checks whether intervals intersect.
std::pair< int64_t, int64_t > IntervalTy
Represents an interval of discrete integer values closed on the left and open on the right: [a,...
static IntervalTy getResourceIntervalTop(unsigned C, unsigned AcquireAtCycle, unsigned ReleaseAtCycle)
Kind getKind() const
Returns an enum value representing the kind of the dependence.
@ Anti
A register anti-dependence (aka WAR).
@ Data
Regular data dependence (aka true-dependence).
bool isWeak() const
Tests if this a weak dependence.
@ Cluster
Weak DAG edge linking a chain of clustered instrs.
@ Artificial
Arbitrary strong DAG edge (no real dependence).
@ Weak
Arbitrary weak DAG edge.
unsigned getLatency() const
Returns the latency value for this edge, which roughly means the minimum number of cycles that must e...
bool isArtificial() const
Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
Register getReg() const
Returns the register associated with this edge.
bool isArtificialDep() const
bool isCtrlDep() const
Tests if this is not an SDep::Data dependence.
Scheduling unit. This is a node in the scheduling DAG.
bool isCall
Is a function call.
unsigned TopReadyCycle
Cycle relative to start when node is ready.
unsigned NodeNum
Entry # of node in the node vector.
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.
bool canAddEdge(SUnit *SuccSU, SUnit *PredSU)
True if an edge can be added from PredSU to SuccSU without creating a cycle.
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs)
Initialize the DAG and common scheduler state for a new scheduling region.
void dump() const override
void setDumpDirection(DumpDirection D)
ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules machine instructions while...
void scheduleMI(SUnit *SU, bool IsTopNode)
Move an instruction and update register pressure.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
VReg2SUnitMultiMap VRegUses
Maps vregs to the SUnits of their uses in the current scheduling region.
void computeDFSResult()
Compute a DFSResult after DAG building is complete, and before any queue comparisons.
PressureDiff & getPressureDiff(const SUnit *SU)
SchedDFSResult * DFSResult
Information about DAG subtrees.
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
void initQueues(ArrayRef< SUnit * > TopRoots, ArrayRef< SUnit * > BotRoots)
Release ExitSU predecessors and setup scheduler queues.
bool ShouldTrackLaneMasks
RegPressureTracker BotRPTracker
void buildDAGWithRegPressure()
Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking enabled.
std::vector< PressureChange > RegionCriticalPSets
List of pressure sets that exceed the target's pressure limit before scheduling, listed in increasing...
void updateScheduledPressure(const SUnit *SU, const std::vector< unsigned > &NewMaxPressure)
PressureDiffs SUPressureDiffs
unsigned computeCyclicCriticalPath()
Compute the cyclic critical path through the DAG.
void updatePressureDiffs(ArrayRef< VRegMaskOrUnit > LiveUses)
Update the PressureDiff array for liveness after scheduling this instruction.
void collectVRegUses(SUnit &SU)
RegisterClassInfo * RegClassInfo
const SchedDFSResult * getDFSResult() const
Return a non-null DFS result if the scheduling strategy initialized it.
RegPressureTracker RPTracker
bool ShouldTrackPressure
Register pressure in this region computed by initRegPressure.
~ScheduleDAGMILive() override
void dump() const override
BitVector & getScheduledTrees()
MachineBasicBlock::iterator LiveRegionEnd
RegPressureTracker TopRPTracker
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
void dumpSchedule() const
dump the scheduled Sequence.
std::unique_ptr< MachineSchedStrategy > SchedImpl
void startBlock(MachineBasicBlock *bb) override
Prepares to perform scheduling in the given block.
void releasePred(SUnit *SU, SDep *PredEdge)
ReleasePred - Decrement the NumSuccsLeft count of a predecessor.
void initQueues(ArrayRef< SUnit * > TopRoots, ArrayRef< SUnit * > BotRoots)
Release ExitSU predecessors and setup scheduler queues.
void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos)
Change the position of an instruction within the basic block and update live ranges and region bounda...
void releasePredecessors(SUnit *SU)
releasePredecessors - Call releasePred on each of SU's predecessors.
void postProcessDAG()
Apply each ScheduleDAGMutation step in order.
void dumpScheduleTraceTopDown() const
Print execution trace of the schedule top-down or bottom-up.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
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
SUnit ExitSU
Special node for the region exit.
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
virtual void overridePostRASchedPolicy(MachineSchedPolicy &Policy, const SchedRegion &Region) const
Override generic post-ra scheduling policy within a region.
virtual void overrideSchedPolicy(MachineSchedPolicy &Policy, const SchedRegion &Region) const
Override generic scheduling policy within a region.
virtual bool enableMachineScheduler() const
True if the subtarget should run MachineScheduler after aggressive coalescing.
virtual bool enablePostRAMachineScheduler() const
True if the subtarget should run a machine scheduler after register allocation.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
VNInfo - Value Number Information.
SlotIndex def
The index of the defining instruction.
bool isPHIDef() const
Returns true if this value is defined by a PHI instruction (or was, PHI instructions may have been el...
Wrapper class representing a virtual register or register unit.
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
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)
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)
FormattedString right_justify(StringRef Str, unsigned Width)
right_justify - add spaces before string so total output is Width characters.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Printable PrintLaneMask(LaneBitmask LaneMask)
Create Printable object to print LaneBitmasks on a raw_ostream.
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 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)
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 std::unique_ptr< ScheduleDAGMutation > createStoreClusterDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, bool ReorderWhileClustering=false)
If ReorderWhileClustering is set to true, no attempt will be made to reduce reordering due to store c...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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 std::unique_ptr< ScheduleDAGMutation > createLoadClusterDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, bool ReorderWhileClustering=false)
If ReorderWhileClustering is set to true, no attempt will be made to reduce reordering due to store c...
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 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.
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createCopyConstrainDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
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.
static std::string getNodeDescription(const SUnit *SU, const ScheduleDAG *G)
static std::string getEdgeAttributes(const SUnit *Node, SUnitIterator EI, const ScheduleDAG *Graph)
If you want to override the dot attributes printed for a particular edge, override this method.
static std::string getGraphName(const ScheduleDAG *G)
static std::string getNodeLabel(const SUnit *SU, const ScheduleDAG *G)
static bool isNodeHidden(const SUnit *Node, const ScheduleDAG *G)
DOTGraphTraits(bool isSimple=false)
static std::string getNodeAttributes(const SUnit *N, const ScheduleDAG *G)
static bool renderGraphFromBottomUp()
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
DefaultDOTGraphTraits(bool simple=false)
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