51 #include "llvm/Config/llvm-config.h" 74 #define DEBUG_TYPE "machine-scheduler" 79 cl::desc(
"Force top-down list scheduling"));
81 cl::desc(
"Force bottom-up list scheduling"));
84 cl::desc(
"Print critical path length to stdout"));
90 cl::desc(
"Pop up a window to show MISched dags after they are processed"));
95 cl::desc(
"Hide nodes with more predecessor/successor than cutoff"));
101 cl::desc(
"Only schedule this function"));
103 cl::desc(
"Only schedule this MBB#"));
107 static const bool ViewMISchedDAGs =
false;
108 static const bool PrintDAGs =
false;
123 cl::desc(
"Enable memop clustering."),
127 cl::desc(
"Verify machine instrs before and after machine scheduling"));
133 void MachineSchedStrategy::anchor() {}
135 void ScheduleDAGMutation::anchor() {}
164 class MachineScheduler :
public MachineSchedulerBase {
179 class PostMachineScheduler :
public MachineSchedulerBase {
181 PostMachineScheduler();
200 "Machine Instruction Scheduler",
false,
false)
208 MachineScheduler::MachineScheduler() : MachineSchedulerBase(
ID) {
212 void MachineScheduler::getAnalysisUsage(
AnalysisUsage &AU)
const {
230 "PostRA Machine Instruction Scheduler",
false,
false)
232 PostMachineScheduler::PostMachineScheduler() : MachineSchedulerBase(
ID) {
236 void PostMachineScheduler::getAnalysisUsage(
AnalysisUsage &AU)
const {
258 cl::desc(
"Machine instruction scheduler to use"));
266 cl::desc(
"Enable the machine instruction scheduling pass."),
cl::init(
true),
270 "enable-post-misched",
271 cl::desc(
"Enable the post-ra machine instruction scheduling pass."),
278 assert(I != Beg &&
"reached the top of the region, cannot decrement");
280 if (!I->isDebugInstr())
299 for(; I != End; ++
I) {
300 if (!I->isDebugInstr())
364 if (!EnableMachineSched)
373 MLI = &getAnalysis<MachineLoopInfo>();
374 MDT = &getAnalysis<MachineDominatorTree>();
375 PassConfig = &getAnalysis<TargetPassConfig>();
376 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
378 LIS = &getAnalysis<LiveIntervals>();
380 if (VerifyScheduling) {
382 MF->verify(
this,
"Before machine scheduling.");
384 RegClassInfo->runOnMachineFunction(*MF);
388 std::unique_ptr<ScheduleDAGInstrs>
Scheduler(createMachineScheduler());
389 scheduleRegions(*Scheduler,
false);
392 if (VerifyScheduling)
393 MF->verify(
this,
"After machine scheduling.");
402 if (!EnablePostRAMachineSched)
412 MLI = &getAnalysis<MachineLoopInfo>();
413 PassConfig = &getAnalysis<TargetPassConfig>();
415 if (VerifyScheduling)
416 MF->
verify(
this,
"Before post machine scheduling.");
420 std::unique_ptr<ScheduleDAGInstrs>
Scheduler(createPostMachineScheduler());
421 scheduleRegions(*Scheduler,
true);
423 if (VerifyScheduling)
424 MF->verify(
this,
"After post machine scheduling.");
455 unsigned NumRegionInstrs;
459 RegionBegin(B), RegionEnd(E), NumRegionInstrs(N) {}
468 bool RegionsTopDown) {
474 RegionEnd != MBB->
begin(); RegionEnd =
I) {
477 if (RegionEnd != MBB->
end() ||
484 unsigned NumRegionInstrs = 0;
486 for (;I != MBB->
begin(); --
I) {
496 Regions.
push_back(SchedRegion(I, RegionEnd, NumRegionInstrs));
511 MBB != MBBEnd; ++MBB) {
519 && (int)SchedOnlyBlock != MBB->getNumber())
540 R != MBBRegions.
end(); ++R) {
543 unsigned NumRegionInstrs = R->NumRegionInstrs;
547 Scheduler.
enterRegion(&*MBB, I, RegionEnd, NumRegionInstrs);
550 if (I == RegionEnd || I == std::prev(RegionEnd)) {
558 <<
" " << MBB->getName() <<
"\n From: " << *I
560 if (RegionEnd != MBB->end())
dbgs() << *RegionEnd;
561 else dbgs() <<
"End";
562 dbgs() <<
" RegionInstrs: " << NumRegionInstrs <<
'\n');
564 errs() << MF->getName();
565 errs() <<
":%bb. " << MBB->getNumber();
566 errs() <<
" " << MBB->getName() <<
" \n";
590 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 593 for (
const SUnit *SU : Queue)
594 dbgs() << SU->NodeNum <<
" ";
609 return SuccSU == &ExitSU || !Topo.IsReachable(PredSU, SuccSU);
613 if (SuccSU != &ExitSU) {
616 if (Topo.IsReachable(PredDep.
getSUnit(), SuccSU))
618 Topo.AddPred(SuccSU, PredDep.
getSUnit());
635 NextClusterSucc = SuccSU;
640 dbgs() <<
"*** Scheduling failed! ***\n";
642 dbgs() <<
" has been released too many times!\n";
653 SchedImpl->releaseTopNode(SuccSU);
659 releaseSucc(SU, &Succ);
672 NextClusterPred = PredSU;
677 dbgs() <<
"*** Scheduling failed! ***\n";
679 dbgs() <<
" has been released too many times!\n";
690 SchedImpl->releaseBottomNode(PredSU);
696 releasePred(SU, &Pred);
701 SchedImpl->enterMBB(bb);
705 SchedImpl->leaveMBB();
716 unsigned regioninstrs)
720 SchedImpl->initPolicy(begin, end, regioninstrs);
728 if (&*RegionBegin == MI)
732 BB->splice(InsertPos, BB, MI);
736 LIS->handleMove(*MI,
true);
739 if (RegionBegin == InsertPos)
745 if (NumInstrsScheduled == MISchedCutoff && MISchedCutoff != ~0U) {
746 CurrentTop = CurrentBottom;
749 ++NumInstrsScheduled;
765 Topo.InitDAGTopologicalSorting();
770 findRootsAndBiasEdges(TopRoots, BotRoots);
773 if (PrintDAGs)
dump();
774 if (ViewMISchedDAGs) viewGraph();
778 SchedImpl->initialize(
this);
781 initQueues(TopRoots, BotRoots);
783 bool IsTopNode =
false;
785 LLVM_DEBUG(
dbgs() <<
"** ScheduleDAGMI::schedule picking next node\n");
786 SUnit *SU = SchedImpl->pickNode(IsTopNode);
790 if (!checkSchedLimit())
796 if (&*CurrentTop == MI)
797 CurrentTop =
nextIfDebug(++CurrentTop, CurrentBottom);
799 moveInstruction(MI, CurrentTop);
805 CurrentBottom = priorII;
807 if (&*CurrentTop == MI)
809 moveInstruction(MI, CurrentBottom);
817 SchedImpl->schedNode(SU, IsTopNode);
819 updateQueues(SU, IsTopNode);
821 assert(CurrentTop == CurrentBottom &&
"Nonempty unscheduled zone.");
826 dbgs() <<
"*** Final schedule for " 835 for (
auto &m : Mutations)
842 for (
SUnit &SU : SUnits) {
843 assert(!SU.isBoundaryNode() &&
"Boundary node should not be in SUnits");
846 SU.biasCriticalPath();
849 if (!SU.NumPredsLeft)
852 if (!SU.NumSuccsLeft)
855 ExitSU.biasCriticalPath();
861 NextClusterSucc =
nullptr;
862 NextClusterPred =
nullptr;
868 for (
SUnit *SU : TopRoots)
869 SchedImpl->releaseTopNode(SU);
875 SchedImpl->releaseBottomNode(*
I);
878 releaseSuccessors(&EntrySU);
879 releasePredecessors(&ExitSU);
881 SchedImpl->registerRoots();
885 CurrentBottom = RegionEnd;
892 releaseSuccessors(SU);
894 releasePredecessors(SU);
903 BB->splice(RegionBegin, BB, FirstDbgValue);
904 RegionBegin = FirstDbgValue;
907 for (std::vector<std::pair<MachineInstr *, MachineInstr *>>::iterator
908 DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
909 std::pair<MachineInstr *, MachineInstr *>
P = *std::prev(DI);
912 if (&*RegionBegin == DbgValue)
914 BB->splice(++OrigPrevMI, BB, DbgValue);
915 if (OrigPrevMI == std::prev(RegionEnd))
916 RegionEnd = DbgValue;
919 FirstDbgValue =
nullptr;
922 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 925 if (
SUnit *SU = getSUnit(&(*
MI)))
928 dbgs() <<
"Missing SUnit\n";
949 if (TrackLaneMasks && !MO.isUse())
952 unsigned Reg = MO.getReg();
957 if (TrackLaneMasks) {
958 bool FoundDef =
false;
960 if (MO2.isReg() && MO2.isDef() && MO2.getReg() == Reg && !MO2.isDead()) {
971 for (; UI != VRegUses.end(); ++UI) {
975 if (UI == VRegUses.end())
987 unsigned regioninstrs)
993 LiveRegionEnd = (RegionEnd == bb->
end()) ? RegionEnd : std::next(RegionEnd);
995 SUPressureDiffs.clear();
997 ShouldTrackPressure = SchedImpl->shouldTrackPressure();
998 ShouldTrackLaneMasks = SchedImpl->shouldTrackLaneMasks();
1000 assert((!ShouldTrackLaneMasks || ShouldTrackPressure) &&
1001 "ShouldTrackLaneMasks requires ShouldTrackPressure");
1008 VRegUses.setUniverse(
MRI.getNumVirtRegs());
1009 for (
SUnit &SU : SUnits)
1010 collectVRegUses(SU);
1012 TopRPTracker.init(&MF, RegClassInfo, LIS, BB, RegionBegin,
1013 ShouldTrackLaneMasks,
false);
1014 BotRPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd,
1015 ShouldTrackLaneMasks,
false);
1018 RPTracker.closeRegion();
1023 TopRPTracker.addLiveRegs(RPTracker.getPressure().LiveInRegs);
1024 BotRPTracker.addLiveRegs(RPTracker.getPressure().LiveOutRegs);
1029 TopRPTracker.closeTop();
1030 BotRPTracker.closeBottom();
1032 BotRPTracker.initLiveThru(RPTracker);
1033 if (!BotRPTracker.getLiveThru().empty()) {
1034 TopRPTracker.initLiveThru(BotRPTracker.getLiveThru());
1041 updatePressureDiffs(RPTracker.getPressure().LiveOutRegs);
1044 if (LiveRegionEnd != RegionEnd) {
1046 BotRPTracker.recede(&LiveUses);
1047 updatePressureDiffs(LiveUses);
1052 dbgs() <<
"Bottom Pressure:\n";
1055 assert((BotRPTracker.getPos() == RegionEnd ||
1056 (RegionEnd->isDebugInstr() &&
1057 BotRPTracker.getPos() ==
priorNonDebug(RegionEnd, RegionBegin))) &&
1058 "Can't find the region bottom");
1062 RegionCriticalPSets.clear();
1065 for (
unsigned i = 0, e = RegionPressure.size(); i < e; ++i) {
1066 unsigned Limit = RegClassInfo->getRegPressureSetLimit(i);
1067 if (RegionPressure[i] > Limit) {
1069 <<
" Actual " << RegionPressure[i] <<
"\n");
1075 : RegionCriticalPSets)
dbgs()
1076 <<
TRI->getRegPressureSetName(RCPS.getPSet()) <<
" ";
1082 const std::vector<unsigned> &NewMaxPressure) {
1084 unsigned CritIdx = 0, CritEnd = RegionCriticalPSets.size();
1088 unsigned ID = PC.getPSet();
1089 while (CritIdx != CritEnd && RegionCriticalPSets[CritIdx].getPSet() < ID)
1091 if (CritIdx != CritEnd && RegionCriticalPSets[CritIdx].getPSet() == ID) {
1092 if ((
int)NewMaxPressure[ID] > RegionCriticalPSets[CritIdx].getUnitInc()
1094 RegionCriticalPSets[CritIdx].setUnitInc(NewMaxPressure[ID]);
1096 unsigned Limit = RegClassInfo->getRegPressureSetLimit(ID);
1097 if (NewMaxPressure[ID] >= Limit - 2) {
1099 << NewMaxPressure[
ID]
1100 << ((NewMaxPressure[
ID] > Limit) ?
" > " :
" <= ")
1101 << Limit <<
"(+ " << BotRPTracker.getLiveThru()[
ID]
1112 unsigned Reg =
P.RegUnit;
1114 if (!
TRI->isVirtualRegister(Reg))
1117 if (ShouldTrackLaneMasks) {
1122 bool Decrement =
P.LaneMask.any();
1125 :
make_range(VRegUses.find(Reg), VRegUses.end())) {
1126 SUnit &SU = *V2SU.SU;
1155 assert(VNI &&
"No live value at use.");
1157 :
make_range(VRegUses.find(Reg), VRegUses.end())) {
1158 SUnit *SU = V2SU.SU;
1178 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1179 if (EntrySU.getInstr() !=
nullptr)
1180 dumpNodeAll(EntrySU);
1181 for (
const SUnit &SU : SUnits) {
1183 if (ShouldTrackPressure) {
1184 dbgs() <<
" Pressure Diff : ";
1185 getPressureDiff(&SU).dump(*
TRI);
1187 dbgs() <<
" Single Issue : ";
1188 if (SchedModel.mustBeginGroup(SU.getInstr()) &&
1189 SchedModel.mustEndGroup(SU.getInstr()))
1195 if (ExitSU.getInstr() !=
nullptr)
1196 dumpNodeAll(ExitSU);
1213 buildDAGWithRegPressure();
1215 Topo.InitDAGTopologicalSorting();
1220 findRootsAndBiasEdges(TopRoots, BotRoots);
1224 SchedImpl->initialize(
this);
1227 if (PrintDAGs)
dump();
1228 if (ViewMISchedDAGs) viewGraph();
1231 initQueues(TopRoots, BotRoots);
1233 bool IsTopNode =
false;
1235 LLVM_DEBUG(
dbgs() <<
"** ScheduleDAGMILive::schedule picking next node\n");
1236 SUnit *SU = SchedImpl->pickNode(IsTopNode);
1240 if (!checkSchedLimit())
1243 scheduleMI(SU, IsTopNode);
1246 unsigned SubtreeID = DFSResult->getSubtreeID(SU);
1247 if (!ScheduledTrees.test(SubtreeID)) {
1248 ScheduledTrees.set(SubtreeID);
1249 DFSResult->scheduleTree(SubtreeID);
1250 SchedImpl->scheduleTree(SubtreeID);
1255 SchedImpl->schedNode(SU, IsTopNode);
1257 updateQueues(SU, IsTopNode);
1259 assert(CurrentTop == CurrentBottom &&
"Nonempty unscheduled zone.");
1264 dbgs() <<
"*** Final schedule for " 1273 if (!ShouldTrackPressure) {
1275 RegionCriticalPSets.clear();
1276 buildSchedGraph(AA);
1281 RPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd,
1282 ShouldTrackLaneMasks,
true);
1285 if (LiveRegionEnd != RegionEnd)
1289 buildSchedGraph(AA, &RPTracker, &SUPressureDiffs, LIS, ShouldTrackLaneMasks);
1299 ScheduledTrees.clear();
1300 DFSResult->resize(SUnits.size());
1301 DFSResult->compute(SUnits);
1302 ScheduledTrees.resize(DFSResult->getNumSubtrees());
1333 if (!BB->isSuccessor(BB))
1336 unsigned MaxCyclicLatency = 0;
1339 unsigned Reg =
P.RegUnit;
1340 if (!
TRI->isVirtualRegister(Reg))
1348 const SUnit *DefSU = getSUnit(DefMI);
1352 unsigned LiveOutHeight = DefSU->
getHeight();
1356 :
make_range(VRegUses.find(Reg), VRegUses.end())) {
1357 SUnit *SU = V2SU.SU;
1369 unsigned CyclicLatency = 0;
1371 CyclicLatency = LiveOutDepth - SU->
getDepth();
1374 if (LiveInHeight > LiveOutHeight) {
1375 if (LiveInHeight - LiveOutHeight < CyclicLatency)
1376 CyclicLatency = LiveInHeight - LiveOutHeight;
1381 << SU->
NodeNum <<
") = " << CyclicLatency <<
"c\n");
1382 if (CyclicLatency > MaxCyclicLatency)
1383 MaxCyclicLatency = CyclicLatency;
1386 LLVM_DEBUG(
dbgs() <<
"Cyclic Critical Path: " << MaxCyclicLatency <<
"c\n");
1387 return MaxCyclicLatency;
1395 if (ShouldTrackPressure) {
1396 assert(TopRPTracker.getPos() == RegionBegin &&
"bad initial Top tracker");
1397 TopRPTracker.setPos(CurrentTop);
1408 if (&*CurrentTop == MI)
1409 CurrentTop =
nextIfDebug(++CurrentTop, CurrentBottom);
1411 moveInstruction(MI, CurrentTop);
1412 TopRPTracker.setPos(MI);
1415 if (ShouldTrackPressure) {
1418 RegOpers.
collect(*MI, *
TRI,
MRI, ShouldTrackLaneMasks,
false);
1419 if (ShouldTrackLaneMasks) {
1428 TopRPTracker.advance(RegOpers);
1429 assert(TopRPTracker.getPos() == CurrentTop &&
"out of sync");
1431 TopRPTracker.getRegSetPressureAtPos(),
TRI););
1433 updateScheduledPressure(SU, TopRPTracker.getPressure().MaxSetPressure);
1439 if (&*priorII == MI)
1440 CurrentBottom = priorII;
1442 if (&*CurrentTop == MI) {
1444 TopRPTracker.setPos(CurrentTop);
1446 moveInstruction(MI, CurrentBottom);
1448 BotRPTracker.setPos(CurrentBottom);
1450 if (ShouldTrackPressure) {
1452 RegOpers.
collect(*MI, *
TRI,
MRI, ShouldTrackLaneMasks,
false);
1453 if (ShouldTrackLaneMasks) {
1462 if (BotRPTracker.getPos() != CurrentBottom)
1463 BotRPTracker.recedeSkipDebugValues();
1465 BotRPTracker.recede(RegOpers, &LiveUses);
1466 assert(BotRPTracker.getPos() == CurrentBottom &&
"out of sync");
1468 BotRPTracker.getRegSetPressureAtPos(),
TRI););
1470 updateScheduledPressure(SU, BotRPTracker.getPressure().MaxSetPressure);
1471 updatePressureDiffs(LiveUses);
1491 : SU(su), BaseOp(Op),
Offset(ofs) {}
1493 bool operator<(
const MemOpInfo &RHS)
const {
1494 if (BaseOp->
getType() != RHS.BaseOp->getType())
1495 return BaseOp->
getType() < RHS.BaseOp->getType();
1497 if (BaseOp->
isReg())
1499 std::make_tuple(RHS.BaseOp->getReg(), RHS.Offset,
1501 if (BaseOp->
isFI()) {
1509 if (BaseOp->
getIndex() != RHS.BaseOp->getIndex())
1510 return StackGrowsDown ? BaseOp->
getIndex() > RHS.BaseOp->getIndex()
1511 : BaseOp->
getIndex() < RHS.BaseOp->getIndex();
1513 if (Offset != RHS.Offset)
1514 return StackGrowsDown ? Offset > RHS.Offset : Offset < RHS.Offset;
1516 return SU->
NodeNum < RHS.SU->NodeNum;
1531 :
TII(tii),
TRI(tri), IsLoad(IsLoad) {}
1539 class StoreClusterMutation :
public BaseMemOpClusterMutation {
1543 : BaseMemOpClusterMutation(tii, tri,
false) {}
1546 class LoadClusterMutation :
public BaseMemOpClusterMutation {
1549 : BaseMemOpClusterMutation(tii, tri,
true) {}
1556 std::unique_ptr<ScheduleDAGMutation>
1559 return EnableMemOpCluster ? llvm::make_unique<LoadClusterMutation>(
TII,
TRI)
1563 std::unique_ptr<ScheduleDAGMutation>
1566 return EnableMemOpCluster ? llvm::make_unique<StoreClusterMutation>(
TII,
TRI)
1572 void BaseMemOpClusterMutation::clusterNeighboringMemOps(
1575 for (
SUnit *SU : MemOps) {
1579 MemOpRecords.
push_back(MemOpInfo(SU, BaseOp, Offset));
1581 if (MemOpRecords.
size() < 2)
1585 unsigned ClusterLength = 1;
1586 for (
unsigned Idx = 0, End = MemOpRecords.
size(); Idx < (End - 1); ++Idx) {
1587 SUnit *SUa = MemOpRecords[Idx].SU;
1588 SUnit *SUb = MemOpRecords[Idx+1].SU;
1589 if (
TII->shouldClusterMemOps(*MemOpRecords[Idx].BaseOp,
1590 *MemOpRecords[Idx + 1].BaseOp,
1625 unsigned ChainPredID = DAG->
SUnits.size();
1634 unsigned NumChains = StoreChainDependents.
size();
1635 std::pair<DenseMap<unsigned, unsigned>::iterator,
bool> Result =
1636 StoreChainIDs.
insert(std::make_pair(ChainPredID, NumChains));
1638 StoreChainDependents.
resize(NumChains + 1);
1639 StoreChainDependents[Result.first->second].
push_back(&SU);
1643 for (
auto &SCD : StoreChainDependents)
1644 clusterNeighboringMemOps(SCD, DAG);
1677 std::unique_ptr<ScheduleDAGMutation>
1680 return llvm::make_unique<CopyConstrain>(
TII,
TRI);
1710 unsigned SrcReg = SrcOp.
getReg();
1715 unsigned DstReg = DstOp.
getReg();
1725 unsigned LocalReg = SrcReg;
1726 unsigned GlobalReg = DstReg;
1728 if (!LocalLI->
isLocal(RegionBeginIdx, RegionEndIdx)) {
1732 if (!LocalLI->
isLocal(RegionBeginIdx, RegionEndIdx))
1743 if (GlobalSegment == GlobalLI->
end())
1750 if (GlobalSegment->contains(LocalLI->
beginIndex()))
1753 if (GlobalSegment == GlobalLI->
end())
1757 if (GlobalSegment != GlobalLI->
begin()) {
1760 GlobalSegment->start)) {
1771 assert(std::prev(GlobalSegment)->start < LocalLI->beginIndex() &&
1772 "Disconnected LRG within the scheduling region.");
1788 for (
const SDep &Succ : LastLocalSU->
Succs) {
1803 for (
const SDep &Pred : GlobalSU->
Preds) {
1806 if (Pred.
getSUnit() == FirstLocalSU)
1816 LLVM_DEBUG(
dbgs() <<
" Local use SU(" << (*I)->NodeNum <<
") -> SU(" 1817 << GlobalSU->
NodeNum <<
")\n");
1821 I = GlobalUses.
begin(),
E = GlobalUses.
end();
I !=
E; ++
I) {
1822 LLVM_DEBUG(
dbgs() <<
" Global use SU(" << (*I)->NodeNum <<
") -> SU(" 1823 << FirstLocalSU->
NodeNum <<
")\n");
1835 if (FirstPos == DAG->
end())
1845 constrainLocalCopy(&SU, static_cast<ScheduleDAGMILive*>(DAG));
1862 return (
int)(Count - (Latency * LFactor)) > (int)LFactor;
1869 if (HazardRec && HazardRec->isEnabled()) {
1871 HazardRec =
nullptr;
1875 CheckPending =
false;
1879 ExpectedLatency = 0;
1880 DependentLatency = 0;
1882 MaxExecutedResCount = 0;
1884 IsResourceLimited =
false;
1885 ReservedCycles.clear();
1890 MaxObservedStall = 0;
1893 ExecutedResCounts.resize(1);
1894 assert(!ExecutedResCounts[0] &&
"nonzero count for bad resource");
1910 unsigned PIdx = PI->ProcResourceIdx;
1912 RemainingCounts[PIdx] += (Factor * PI->Cycles);
1921 SchedModel = smodel;
1923 if (SchedModel->hasInstrSchedModel()) {
1924 ExecutedResCounts.resize(SchedModel->getNumProcResourceKinds());
1925 ReservedCycles.resize(SchedModel->getNumProcResourceKinds(),
InvalidCycle);
1941 if (ReadyCycle > CurrCycle)
1942 return ReadyCycle - CurrCycle;
1950 unsigned NextUnreserved = ReservedCycles[PIdx];
1952 if (NextUnreserved == InvalidCycle)
1956 NextUnreserved += Cycles;
1957 return NextUnreserved;
1974 if (HazardRec->isEnabled()
1979 unsigned uops = SchedModel->getNumMicroOps(SU->
getInstr());
1980 if ((CurrMOps > 0) && (CurrMOps + uops > SchedModel->getIssueWidth())) {
1982 << SchedModel->getNumMicroOps(SU->
getInstr()) <<
'\n');
1987 ((isTop() && SchedModel->mustBeginGroup(SU->
getInstr())) ||
1988 (!isTop() && SchedModel->mustEndGroup(SU->
getInstr())))) {
1990 << (isTop() ?
"begin" :
"end") <<
" group\n");
1997 make_range(SchedModel->getWriteProcResBegin(SC),
1998 SchedModel->getWriteProcResEnd(SC))) {
1999 unsigned ResIdx = PE.ProcResourceIdx;
2000 unsigned Cycles = PE.Cycles;
2001 unsigned NRCycle = getNextResourceCycle(ResIdx, Cycles);
2002 if (NRCycle > CurrCycle) {
2004 MaxObservedStall =
std::max(Cycles, MaxObservedStall);
2007 << SchedModel->getResourceName(ResIdx) <<
"=" 2008 << NRCycle <<
"c\n");
2019 SUnit *LateSU =
nullptr;
2020 unsigned RemLatency = 0;
2021 for (
SUnit *SU : ReadySUs) {
2022 unsigned L = getUnscheduledLatency(SU);
2023 if (L > RemLatency) {
2030 << LateSU->
NodeNum <<
") " << RemLatency <<
"c\n");
2041 if (!SchedModel->hasInstrSchedModel())
2044 unsigned OtherCritCount = Rem->RemIssueCount
2045 + (RetiredMOps * SchedModel->getMicroOpFactor());
2046 LLVM_DEBUG(
dbgs() <<
" " << Available.getName() <<
" + Remain MOps: " 2047 << OtherCritCount / SchedModel->getMicroOpFactor() <<
'\n');
2048 for (
unsigned PIdx = 1, PEnd = SchedModel->getNumProcResourceKinds();
2049 PIdx != PEnd; ++PIdx) {
2050 unsigned OtherCount = getResourceCount(PIdx) + Rem->RemainingCounts[PIdx];
2051 if (OtherCount > OtherCritCount) {
2052 OtherCritCount = OtherCount;
2053 OtherCritIdx = PIdx;
2058 dbgs() <<
" " << Available.getName() <<
" + Remain CritRes: " 2059 << OtherCritCount / SchedModel->getResourceFactor(OtherCritIdx)
2060 <<
" " << SchedModel->getResourceName(OtherCritIdx) <<
"\n");
2062 return OtherCritCount;
2072 if (ReadyCycle > CurrCycle)
2073 MaxObservedStall =
std::max(ReadyCycle - CurrCycle, MaxObservedStall);
2076 if (ReadyCycle < MinReadyCycle)
2077 MinReadyCycle = ReadyCycle;
2081 bool IsBuffered = SchedModel->getMicroOpBufferSize() != 0;
2082 if ((!IsBuffered && ReadyCycle > CurrCycle) || checkHazard(SU) ||
2091 if (SchedModel->getMicroOpBufferSize() == 0) {
2093 "MinReadyCycle uninitialized");
2094 if (MinReadyCycle > NextCycle)
2095 NextCycle = MinReadyCycle;
2098 unsigned DecMOps = SchedModel->getIssueWidth() * (NextCycle - CurrCycle);
2099 CurrMOps = (CurrMOps <= DecMOps) ? 0 : CurrMOps - DecMOps;
2102 if ((NextCycle - CurrCycle) > DependentLatency)
2103 DependentLatency = 0;
2105 DependentLatency -= (NextCycle - CurrCycle);
2107 if (!HazardRec->isEnabled()) {
2109 CurrCycle = NextCycle;
2112 for (; CurrCycle != NextCycle; ++CurrCycle) {
2114 HazardRec->AdvanceCycle();
2116 HazardRec->RecedeCycle();
2119 CheckPending =
true;
2122 getScheduledLatency());
2124 LLVM_DEBUG(
dbgs() <<
"Cycle: " << CurrCycle <<
' ' << Available.getName()
2129 ExecutedResCounts[PIdx] += Count;
2130 if (ExecutedResCounts[PIdx] > MaxExecutedResCount)
2131 MaxExecutedResCount = ExecutedResCounts[PIdx];
2143 unsigned Factor = SchedModel->getResourceFactor(PIdx);
2144 unsigned Count = Factor * Cycles;
2145 LLVM_DEBUG(
dbgs() <<
" " << SchedModel->getResourceName(PIdx) <<
" +" 2146 << Cycles <<
"x" << Factor <<
"u\n");
2149 incExecutedResources(PIdx, Count);
2150 assert(Rem->RemainingCounts[PIdx] >= Count &&
"resource double counted");
2151 Rem->RemainingCounts[PIdx] -= Count;
2155 if (ZoneCritResIdx != PIdx && (getResourceCount(PIdx) > getCriticalCount())) {
2156 ZoneCritResIdx = PIdx;
2158 << SchedModel->getResourceName(PIdx) <<
": " 2159 << getResourceCount(PIdx) / SchedModel->getLatencyFactor()
2163 unsigned NextAvailable = getNextResourceCycle(PIdx, Cycles);
2164 if (NextAvailable > CurrCycle) {
2166 << SchedModel->getProcResource(PIdx)->Name
2167 <<
" reserved until @" << NextAvailable <<
"\n");
2169 return NextAvailable;
2175 if (HazardRec->isEnabled()) {
2176 if (!isTop() && SU->
isCall) {
2181 HazardRec->EmitInstruction(SU);
2186 unsigned IncMOps = SchedModel->getNumMicroOps(SU->
getInstr());
2188 (CurrMOps == 0 || (CurrMOps + IncMOps) <= SchedModel->getIssueWidth()) &&
2189 "Cannot schedule this instruction's MicroOps in the current cycle.");
2194 unsigned NextCycle = CurrCycle;
2195 switch (SchedModel->getMicroOpBufferSize()) {
2197 assert(ReadyCycle <= CurrCycle &&
"Broken PendingQueue");
2200 if (ReadyCycle > NextCycle) {
2201 NextCycle = ReadyCycle;
2202 LLVM_DEBUG(
dbgs() <<
" *** Stall until: " << ReadyCycle <<
"\n");
2211 NextCycle = ReadyCycle;
2214 RetiredMOps += IncMOps;
2217 if (SchedModel->hasInstrSchedModel()) {
2218 unsigned DecRemIssue = IncMOps * SchedModel->getMicroOpFactor();
2219 assert(Rem->RemIssueCount >= DecRemIssue &&
"MOps double counted");
2220 Rem->RemIssueCount -= DecRemIssue;
2221 if (ZoneCritResIdx) {
2223 unsigned ScaledMOps =
2224 RetiredMOps * SchedModel->getMicroOpFactor();
2228 if ((
int)(ScaledMOps - getResourceCount(ZoneCritResIdx))
2229 >= (
int)SchedModel->getLatencyFactor()) {
2232 << ScaledMOps / SchedModel->getLatencyFactor()
2237 PI = SchedModel->getWriteProcResBegin(SC),
2238 PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
2240 countResource(PI->ProcResourceIdx, PI->Cycles, NextCycle);
2241 if (RCycle > NextCycle)
2250 PI = SchedModel->getWriteProcResBegin(SC),
2251 PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
2252 unsigned PIdx = PI->ProcResourceIdx;
2253 if (SchedModel->getProcResource(PIdx)->BufferSize == 0) {
2255 ReservedCycles[PIdx] =
2256 std::max(getNextResourceCycle(PIdx, 0), NextCycle + PI->Cycles);
2259 ReservedCycles[PIdx] = NextCycle;
2265 unsigned &TopLatency = isTop() ? ExpectedLatency : DependentLatency;
2266 unsigned &BotLatency = isTop() ? DependentLatency : ExpectedLatency;
2269 LLVM_DEBUG(
dbgs() <<
" " << Available.getName() <<
" TopLatency SU(" 2270 << SU->
NodeNum <<
") " << TopLatency <<
"c\n");
2274 LLVM_DEBUG(
dbgs() <<
" " << Available.getName() <<
" BotLatency SU(" 2275 << SU->
NodeNum <<
") " << BotLatency <<
"c\n");
2278 if (NextCycle > CurrCycle)
2279 bumpCycle(NextCycle);
2285 getScheduledLatency());
2291 CurrMOps += IncMOps;
2297 if ((isTop() && SchedModel->mustEndGroup(SU->
getInstr())) ||
2298 (!isTop() && SchedModel->mustBeginGroup(SU->
getInstr()))) {
2299 LLVM_DEBUG(
dbgs() <<
" Bump cycle to " << (isTop() ?
"end" :
"begin")
2301 bumpCycle(++NextCycle);
2304 while (CurrMOps >= SchedModel->getIssueWidth()) {
2305 LLVM_DEBUG(
dbgs() <<
" *** Max MOps " << CurrMOps <<
" at cycle " 2306 << CurrCycle <<
'\n');
2307 bumpCycle(++NextCycle);
2316 if (Available.empty())
2321 bool IsBuffered = SchedModel->getMicroOpBufferSize() != 0;
2322 for (
unsigned i = 0, e = Pending.size(); i != e; ++i) {
2323 SUnit *SU = *(Pending.begin()+i);
2326 if (ReadyCycle < MinReadyCycle)
2327 MinReadyCycle = ReadyCycle;
2329 if (!IsBuffered && ReadyCycle > CurrCycle)
2332 if (checkHazard(SU))
2339 Pending.remove(Pending.begin()+i);
2342 CheckPending =
false;
2347 if (Available.isInQueue(SU))
2348 Available.remove(Available.find(SU));
2350 assert(Pending.isInQueue(SU) &&
"bad ready count");
2351 Pending.remove(Pending.find(SU));
2365 if (checkHazard(*
I)) {
2367 I = Available.remove(
I);
2373 for (
unsigned i = 0; Available.empty(); ++i) {
2378 bumpCycle(CurrCycle + 1);
2385 if (Available.size() == 1)
2386 return *Available.begin();
2390 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 2396 if (ZoneCritResIdx) {
2397 ResFactor = SchedModel->getResourceFactor(ZoneCritResIdx);
2398 ResCount = getResourceCount(ZoneCritResIdx);
2400 ResFactor = SchedModel->getMicroOpFactor();
2401 ResCount = RetiredMOps * ResFactor;
2403 unsigned LFactor = SchedModel->getLatencyFactor();
2404 dbgs() << Available.getName() <<
" @" << CurrCycle <<
"c\n" 2405 <<
" Retired: " << RetiredMOps;
2406 dbgs() <<
"\n Executed: " << getExecutedCount() / LFactor <<
"c";
2407 dbgs() <<
"\n Critical: " << ResCount / LFactor <<
"c, " 2408 << ResCount / ResFactor <<
" " 2409 << SchedModel->getResourceName(ZoneCritResIdx)
2410 <<
"\n ExpectedLatency: " << ExpectedLatency <<
"c\n" 2411 << (IsResourceLimited ?
" - Resource" :
" - Latency")
2423 if (!Policy.ReduceResIdx && !Policy.DemandResIdx)
2430 if (PI->ProcResourceIdx == Policy.ReduceResIdx)
2431 ResDelta.CritResources += PI->Cycles;
2432 if (PI->ProcResourceIdx == Policy.DemandResIdx)
2433 ResDelta.DemandedResources += PI->Cycles;
2464 bool GenericSchedulerBase::shouldReduceLatency(
const CandPolicy &Policy,
2466 bool ComputeRemLatency,
2467 unsigned &RemLatency)
const {
2477 if (ComputeRemLatency)
2480 return RemLatency + CurrZone.
getCurrCycle() > Rem.CriticalPath;
2493 unsigned OtherCritIdx = 0;
2494 unsigned OtherCount =
2497 bool OtherResLimited =
false;
2498 unsigned RemLatency = 0;
2499 bool RemLatencyComputed =
false;
2500 if (SchedModel->hasInstrSchedModel() && OtherCount != 0) {
2502 RemLatencyComputed =
true;
2504 OtherCount, RemLatency);
2510 if (!OtherResLimited &&
2511 (IsPostRA || shouldReduceLatency(Policy, CurrZone, !RemLatencyComputed,
2515 <<
" RemainingLatency " << RemLatency <<
" + " 2517 << Rem.CriticalPath <<
"\n");
2526 }
if (OtherResLimited)
dbgs()
2527 <<
" RemainingLimit: " 2528 << SchedModel->getResourceName(OtherCritIdx) <<
"\n";
2530 <<
" Latency limited both directions.\n");
2535 if (OtherResLimited)
2543 case NoCand:
return "NOCAND ";
2544 case Only1:
return "ONLY1 ";
2545 case PhysReg:
return "PHYS-REG ";
2546 case RegExcess:
return "REG-EXCESS";
2547 case RegCritical:
return "REG-CRIT ";
2548 case Stall:
return "STALL ";
2549 case Cluster:
return "CLUSTER ";
2550 case Weak:
return "WEAK ";
2551 case RegMax:
return "REG-MAX ";
2552 case ResourceReduce:
return "RES-REDUCE";
2553 case ResourceDemand:
return "RES-DEMAND";
2554 case TopDepthReduce:
return "TOP-DEPTH ";
2555 case TopPathReduce:
return "TOP-PATH ";
2556 case BotHeightReduce:
return "BOT-HEIGHT";
2557 case BotPathReduce:
return "BOT-PATH ";
2558 case NextDefUse:
return "DEF-USE ";
2566 unsigned ResIdx = 0;
2580 case ResourceReduce:
2583 case ResourceDemand:
2586 case TopDepthReduce:
2592 case BotHeightReduce:
2606 dbgs() <<
" " << SchedModel->getProcResource(ResIdx)->Name <<
" ";
2610 dbgs() <<
" " << Latency <<
" cycles ";
2623 if (TryVal < CandVal) {
2627 if (TryVal > CandVal) {
2628 if (Cand.
Reason > Reason)
2639 if (TryVal > CandVal) {
2643 if (TryVal < CandVal) {
2644 if (Cand.
Reason > Reason)
2688 "(PreRA)GenericScheduler needs vreg liveness");
2693 Rem.init(DAG, SchedModel);
2694 Top.init(DAG, SchedModel, &Rem);
2695 Bot.init(DAG, SchedModel, &Rem);
2702 if (!Top.HazardRec) {
2704 DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer(
2707 if (!Bot.HazardRec) {
2709 DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer(
2712 TopCand.SU =
nullptr;
2713 BotCand.SU =
nullptr;
2719 unsigned NumRegionInstrs) {
2726 RegionPolicy.ShouldTrackPressure =
true;
2730 unsigned NIntRegs =
Context->RegClassInfo->getNumAllocatableRegs(
2732 RegionPolicy.ShouldTrackPressure = NumRegionInstrs > (NIntRegs / 2);
2738 RegionPolicy.OnlyBottomUp =
true;
2744 if (!EnableRegPressure)
2745 RegionPolicy.ShouldTrackPressure =
false;
2750 "-misched-topdown incompatible with -misched-bottomup");
2753 if (RegionPolicy.OnlyBottomUp)
2754 RegionPolicy.OnlyTopDown =
false;
2758 if (RegionPolicy.OnlyTopDown)
2759 RegionPolicy.OnlyBottomUp =
false;
2765 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 2766 dbgs() <<
"GenericScheduler RegionPolicy: " 2767 <<
" ShouldTrackPressure=" << RegionPolicy.ShouldTrackPressure
2768 <<
" OnlyTopDown=" << RegionPolicy.OnlyTopDown
2769 <<
" OnlyBottomUp=" << RegionPolicy.OnlyBottomUp
2784 if (Rem.CyclicCritPath == 0 || Rem.CyclicCritPath >= Rem.CriticalPath)
2788 unsigned IterCount =
2789 std::max(Rem.CyclicCritPath * SchedModel->getLatencyFactor(),
2792 unsigned AcyclicCount = Rem.CriticalPath * SchedModel->getLatencyFactor();
2794 unsigned InFlightCount =
2795 (AcyclicCount * Rem.RemIssueCount + IterCount-1) / IterCount;
2796 unsigned BufferLimit =
2797 SchedModel->getMicroOpBufferSize() * SchedModel->getMicroOpFactor();
2799 Rem.IsAcyclicLatencyLimited = InFlightCount > BufferLimit;
2802 dbgs() <<
"IssueCycles=" 2803 << Rem.RemIssueCount / SchedModel->getLatencyFactor() <<
"c " 2804 <<
"IterCycles=" << IterCount / SchedModel->getLatencyFactor()
2805 <<
"c NumIters=" << (AcyclicCount + IterCount - 1) / IterCount
2806 <<
" InFlight=" << InFlightCount / SchedModel->getMicroOpFactor()
2807 <<
"m BufferLim=" << SchedModel->getMicroOpBufferSize() <<
"m\n";
2808 if (Rem.IsAcyclicLatencyLimited)
dbgs() <<
" ACYCLIC LATENCY LIMIT\n");
2815 for (
const SUnit *SU : Bot.Available) {
2816 if (SU->
getDepth() > Rem.CriticalPath)
2819 LLVM_DEBUG(
dbgs() <<
"Critical Path(GS-RR ): " << Rem.CriticalPath <<
'\n');
2821 errs() <<
"Critical Path(GS-RR ): " << Rem.CriticalPath <<
" \n";
2824 if (EnableCyclicPath && SchedModel->getMicroOpBufferSize() > 0) {
2826 checkAcyclicLatency();
2846 if (Cand.AtTop != TryCand.
AtTop)
2853 if (TryPSet == CandPSet) {
2867 return tryGreater(TryRank, CandRank, TryCand, Cand, Reason);
2885 unsigned ScheduledOper = isTop ? 1 : 0;
2886 unsigned UnscheduledOper = isTop ? 0 : 1;
2897 return AtBoundary ? -1 : 1;
2913 return isTop ? -1 : 1;
2934 if (VerifyScheduling) {
2952 <<
" Try SU(" << Cand.
SU->
NodeNum <<
") " 2984 TryCand, Cand, RegExcess,
TRI,
2991 TryCand, Cand, RegCritical,
TRI,
3000 bool SameBoundary = Zone !=
nullptr;
3005 if (Rem.IsAcyclicLatencyLimited && !Zone->
getCurrMOps() &&
3021 const SUnit *CandNextClusterSU =
3023 const SUnit *TryCandNextClusterSU =
3026 Cand.
SU == CandNextClusterSU,
3027 TryCand, Cand, Cluster))
3034 TryCand, Cand, Weak))
3041 TryCand, Cand, RegMax,
TRI,
3049 TryCand, Cand, ResourceReduce))
3053 TryCand, Cand, ResourceDemand))
3059 !Rem.IsAcyclicLatencyLimited &&
tryLatency(TryCand, Cand, *Zone))
3083 for (
SUnit *SU : Q) {
3086 initCandidate(TryCand, SU, Zone.
isTop(), RPTracker, TempTracker);
3089 tryCandidate(Cand, TryCand, ZoneArg);
3104 if (
SUnit *SU = Bot.pickOnlyChoice()) {
3109 if (
SUnit *SU = Top.pickOnlyChoice()) {
3117 setPolicy(BotPolicy,
false, Bot, &Top);
3121 setPolicy(TopPolicy,
false, Top, &Bot);
3125 if (!BotCand.isValid() || BotCand.SU->isScheduled ||
3126 BotCand.Policy != BotPolicy) {
3129 assert(BotCand.Reason !=
NoCand &&
"failed to find the first candidate");
3133 if (VerifyScheduling) {
3138 "Last pick result should correspond to re-picking right now");
3145 if (!TopCand.isValid() || TopCand.SU->isScheduled ||
3146 TopCand.Policy != TopPolicy) {
3149 assert(TopCand.Reason !=
NoCand &&
"failed to find the first candidate");
3153 if (VerifyScheduling) {
3158 "Last pick result should correspond to re-picking right now");
3164 assert(BotCand.isValid());
3165 assert(TopCand.isValid());
3168 tryCandidate(Cand, TopCand,
nullptr);
3169 if (TopCand.Reason !=
NoCand) {
3170 Cand.setBest(TopCand);
3174 IsTopNode = Cand.AtTop;
3182 assert(Top.Available.empty() && Top.Pending.empty() &&
3183 Bot.Available.empty() && Bot.Pending.empty() &&
"ReadyQ garbage");
3188 if (RegionPolicy.OnlyTopDown) {
3189 SU = Top.pickOnlyChoice();
3192 TopCand.reset(NoPolicy);
3194 assert(TopCand.Reason !=
NoCand &&
"failed to find a candidate");
3199 }
else if (RegionPolicy.OnlyBottomUp) {
3200 SU = Bot.pickOnlyChoice();
3203 BotCand.reset(NoPolicy);
3205 assert(BotCand.Reason !=
NoCand &&
"failed to find a candidate");
3211 SU = pickNodeBidirectional(IsTopNode);
3216 Top.removeReady(SU);
3218 Bot.removeReady(SU);
3233 for (
SDep &Dep : Deps) {
3234 if (Dep.getKind() !=
SDep::Data || !
TRI->isPhysicalRegister(Dep.getReg()))
3236 SUnit *DepSU = Dep.getSUnit();
3237 if (isTop ? DepSU->
Succs.size() > 1 : DepSU->
Preds.size() > 1)
3260 reschedulePhysReg(SU,
true);
3265 reschedulePhysReg(SU,
false);
3300 Rem.init(DAG, SchedModel);
3301 Top.init(DAG, SchedModel, &Rem);
3307 if (!Top.HazardRec) {
3318 for (
const SUnit *SU : BotRoots) {
3319 if (SU->getDepth() > Rem.CriticalPath)
3320 Rem.CriticalPath = SU->getDepth();
3322 LLVM_DEBUG(
dbgs() <<
"Critical Path: (PGS-RR) " << Rem.CriticalPath <<
'\n');
3324 errs() <<
"Critical Path(PGS-RR ): " << Rem.CriticalPath <<
" \n";
3341 if (
tryLess(Top.getLatencyStallCycles(TryCand.
SU),
3342 Top.getLatencyStallCycles(Cand.
SU), TryCand, Cand, Stall))
3348 TryCand, Cand, Cluster))
3353 TryCand, Cand, ResourceReduce))
3356 Cand.ResDelta.DemandedResources,
3357 TryCand, Cand, ResourceDemand))
3361 if (Cand.Policy.ReduceLatency &&
tryLatency(TryCand, Cand, Top)) {
3366 if (TryCand.
SU->
NodeNum < Cand.SU->NodeNum)
3372 for (
SUnit *SU : Q) {
3375 TryCand.
AtTop =
true;
3377 tryCandidate(Cand, TryCand);
3388 assert(Top.Available.empty() && Top.Pending.empty() &&
"ReadyQ garbage");
3393 SU = Top.pickOnlyChoice();
3401 setPolicy(TopCand.
Policy,
true, Top,
nullptr);
3402 pickNodeFromQueue(TopCand);
3410 Top.removeReady(SU);
3425 return new ScheduleDAGMI(C, llvm::make_unique<PostGenericScheduler>(C),
3438 const BitVector *ScheduledTrees =
nullptr;
3441 ILPOrder(
bool MaxILP) : MaximizeILP(MaxILP) {}
3446 bool operator()(
const SUnit *A,
const SUnit *
B)
const {
3449 if (SchedTreeA != SchedTreeB) {
3451 if (ScheduledTrees->
test(SchedTreeA) != ScheduledTrees->
test(SchedTreeB))
3452 return ScheduledTrees->
test(SchedTreeB);
3473 std::vector<SUnit*> ReadyQ;
3476 ILPScheduler(
bool MaximizeILP) : Cmp(MaximizeILP) {}
3482 Cmp.DFSResult = DAG->getDFSResult();
3483 Cmp.ScheduledTrees = &DAG->getScheduledTrees();
3489 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
3497 if (ReadyQ.empty())
return nullptr;
3498 std::pop_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
3499 SUnit *SU = ReadyQ.back();
3503 <<
"SU(" << SU->NodeNum <<
") " 3510 <<
"Scheduling " << *SU->getInstr());
3516 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
3522 assert(!IsTopNode &&
"SchedDFSResult needs bottom-up");
3528 ReadyQ.push_back(SU);
3529 std::push_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
3556 template<
bool IsReverse>
3582 InstructionShuffler(
bool alternate,
bool topdown)
3583 : IsAlternating(alternate), IsTopDown(topdown) {}
3597 if (TopQ.empty())
return nullptr;
3604 if (BottomQ.empty())
return nullptr;
3611 IsTopDown = !IsTopDown;
3631 "-misched-topdown incompatible with -misched-bottomup");
3633 C, llvm::make_unique<InstructionShuffler>(Alternate, TopDown));
3637 "shuffle",
"Shuffle machine instructions alternating directions",
3664 if (ViewMISchedCutoff == 0)
3666 return (Node->
Preds.size() > ViewMISchedCutoff
3676 return "color=cyan,style=dashed";
3678 return "color=blue,style=dashed";
3699 std::string Str(
"shape=Mrecord");
3704 Str +=
",style=filled,fillcolor=\"#";
3721 errs() <<
"ScheduleDAGMI::viewGraph is only available in debug builds on " 3722 <<
"systems with Graphviz or gv!\n";
3728 viewGraph(getDAGName(),
"Scheduling-Units Graph for " + getDAGName());
void computeDFSResult()
Compute a DFSResult after DAG building is complete, and before any queue comparisons.
std::reverse_iterator< const_iterator > const_reverse_iterator
unsigned findMaxLatency(ArrayRef< SUnit *> ReadySUs)
void releaseSucc(SUnit *SU, SDep *SuccEdge)
ReleaseSucc - Decrement the NumPredsLeft count of a successor.
int biasPhysReg(const SUnit *SU, bool isTop)
Minimize physical register live ranges.
Weak DAG edge linking a chain of clustered instrs.
bool isPHIDef() const
Returns true if this value is defined by a PHI instruction (or was, PHI instructions may have been el...
unsigned getNumInstrs(const SUnit *SU) const
Get the number of instructions in the given subtree and its children.
void schedNode(SUnit *SU, bool IsTopNode) override
Called after ScheduleDAGMI has scheduled an instruction and updated scheduled/remaining flags in the ...
const_iterator end(StringRef path)
Get end iterator over path.
virtual void finishBlock()
Cleans up after scheduling in the given block.
virtual void initialize(ScheduleDAGMI *DAG)=0
Initialize the strategy after building the DAG for a new region.
A common definition of LaneBitmask for use in TableGen and CodeGen.
unsigned getZoneCritResIdx() const
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static cl::opt< bool > ViewMISchedDAGs("view-misched-dags", cl::Hidden, cl::desc("Pop up a window to show MISched dags after they are processed"))
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static std::string getNodeAttributes(const SUnit *N, const ScheduleDAG *G)
static cl::opt< bool > EnablePostRAMachineSched("enable-post-misched", cl::desc("Enable the post-ra machine instruction scheduling pass."), cl::init(true), cl::Hidden)
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
static MachinePassRegistry< ScheduleDAGCtor > Registry
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
iterator_base< SparseMultiSet *> iterator
ProcResIter getWriteProcResBegin(const MCSchedClassDesc *SC) const
void detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS)
Use liveness information to find dead defs not marked with a dead flag and move them to the DeadDefs ...
void dumpSchedule() const
dump the scheduled Sequence.
typename SuperClass::const_iterator const_iterator
virtual ~MachineSchedContext()
Each Scheduling boundary is associated with ready queues.
SlotIndex def
The index of the defining instruction.
This class represents lattice values for constants.
void addPressureChange(unsigned RegUnit, bool IsDec, const MachineRegisterInfo *MRI)
Add a change in pressure to the pressure diff of a given instruction.
SUnit * pickNodeBidirectional(bool &IsTopNode)
Pick the best candidate node from either the top or bottom queue.
virtual void releaseTopNode(SUnit *SU)=0
When all predecessor dependencies have been resolved, free this node for top-down scheduling...
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel)
A Module instance is used to store all the information related to an LLVM module. ...
Segments::iterator iterator
const MCSchedClassDesc * getSchedClass(SUnit *SU) const
Resolves and cache a resolved scheduling class for an SUnit.
void push_back(const T &Elt)
void startBlock(MachineBasicBlock *bb) override
Prepares to perform scheduling in the given block.
char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
unsigned getCurrCycle() const
Number of cycles to issue the instructions scheduled in this zone.
LiveInterval - This class represents the liveness of a register, or stack slot.
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...
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
static cl::opt< std::string > SchedOnlyFunc("misched-only-func", cl::Hidden, cl::desc("Only schedule this function"))
unsigned getReg() const
getReg - Returns the register number.
unsigned computeCyclicCriticalPath()
Compute the cyclic critical path through the DAG.
void dump() const override
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
void fixupKills(MachineBasicBlock &MBB)
Fixes register kill flags that scheduling has made invalid.
virtual const TargetLowering * getTargetLowering() const
void traceCandidate(const SchedCandidate &Cand)
unsigned DemandedResources
reverse_iterator rbegin() const
static bool renderGraphFromBottomUp()
bool test(unsigned Idx) const
ScheduleDAGMI * createGenericSchedPostRA(MachineSchedContext *C)
Create a generic scheduler with no vreg liveness or DAG mutation passes.
ProcResIter getWriteProcResEnd(const MCSchedClassDesc *SC) const
Mutate the DAG as a postpass after normal DAG building.
const IntervalPressure & getRegPressure() const
Get register pressure for the entire scheduling region before scheduling.
void initQueues(ArrayRef< SUnit *> TopRoots, ArrayRef< SUnit *> BotRoots)
Release ExitSU predecessors and setup scheduler queues.
static ScheduleDAGInstrs * createILPMaxScheduler(MachineSchedContext *C)
virtual std::string getGraphNodeLabel(const SUnit *SU) const =0
Returns a label for an SUnit node in a visualization of the ScheduleDAG.
virtual const TargetRegisterClass * getRegClassFor(MVT VT) const
Return the register class that should be used for the specified value type.
unsigned getDependentLatency() const
static ScheduleDAGInstrs * createInstructionShuffler(MachineSchedContext *C)
unsigned const TargetRegisterInfo * TRI
Printable PrintLaneMask(LaneBitmask LaneMask)
Create Printable object to print LaneBitmasks on a raw_ostream.
char & MachineSchedulerID
MachineScheduler - This pass schedules machine instructions.
Summarize the unscheduled region.
void reset(const CandPolicy &NewPolicy)
const SchedDFSResult * getDFSResult() const
Return a non-null DFS result if the scheduling strategy initialized it.
RegisterPassParser class - Handle the addition of new machine passes.
unsigned getReg() const
Returns the register associated with this edge.
MachineSchedRegistry provides a selection of available machine instruction schedulers.
bool isBottomReady() const
VNInfo - Value Number Information.
iterator_range< mop_iterator > operands()
static std::string getNodeLabel(const SUnit *SU, const ScheduleDAG *G)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
static MachineSchedRegistry ShufflerRegistry("shuffle", "Shuffle machine instructions alternating directions", createInstructionShuffler)
unsigned BotReadyCycle
Cycle relative to end when node is ready.
static MachineSchedRegistry ILPMaxRegistry("ilpmax", "Schedule bottom-up for max ILP", createILPMaxScheduler)
void updateQueues(SUnit *SU, bool IsTopNode)
Update scheduler DAG and queues after scheduling an instruction.
virtual void schedNode(SUnit *SU, bool IsTopNode)=0
Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an instruction and updated scheduled/rem...
SmallVector< SDep, 4 > Preds
All sunit predecessors.
virtual void startBlock(MachineBasicBlock *BB)
Prepares to perform scheduling in the given block.
bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, SchedBoundary &Zone)
static cl::opt< bool > PrintDAGs("misched-print-dags", cl::Hidden, cl::desc("Print schedule DAGs"))
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction...
A register anti-dependence (aka WAR).
ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules machine instructions while...
*ViewGraph Emit a dot run run gv on the postscript *then cleanup For use from the debugger *void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames=false, const Twine &Title="", GraphProgram::Name Program=GraphProgram::DOT)
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
bool isScheduled
True once scheduled.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
ArrayRef< SUnit * > elements()
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
const RegPressureTracker & getBotRPTracker() const
amdgpu Simplify well known AMD library false Value Value const Twine & Name
unsigned getLatency() const
Returns the latency value for this edge, which roughly means the minimum number of cycles that must e...
unsigned NumSuccsLeft
of succs not scheduled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Provide an instruction scheduling machine model to CodeGen passes.
const HexagonInstrInfo * TII
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...
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
An individual mapping from virtual register number to SUnit.
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
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.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Regular data dependence (aka true-dependence).
Result of a LiveRange query.
bool hasPhysRegUses
Has physreg uses.
void apply(Opt *O, const Mod &M, const Mods &... Ms)
StringRef getName() const
bool hasPhysRegDefs
Has physreg defs that are being used.
PressureDiff & getPressureDiff(const SUnit *SU)
bool hasInstrSchedModel() const
Return true if this machine model includes an instruction-level scheduling model. ...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Target-Independent Code Generator Pass Configuration Options.
static constexpr LaneBitmask getNone()
void initPolicy(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned NumRegionInstrs) override
Initialize the per-region scheduling policy.
static bool isSimple(Instruction *I)
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
static const char * getReasonStr(SIScheduleCandReason Reason)
Compute the values of each DAG node for various metrics during DFS.
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
unsigned TopReadyCycle
Cycle relative to start when node is ready.
static const unsigned InvalidCycle
unsigned getNumMicroOps(const MachineInstr *MI, const MCSchedClassDesc *SC=nullptr) const
Return the number of issue slots required for this MI.
static cl::opt< bool > VerifyScheduling("verify-misched", cl::Hidden, cl::desc("Verify machine instrs before and after machine scheduling"))
MachineInstr * getInstructionFromIndex(SlotIndex index) const
Returns the instruction associated with the given index.
bool readsReg() const
readsReg - Returns true if this operand reads the previous value of its register. ...
void bumpCycle(unsigned NextCycle)
Move the boundary of scheduled code by one cycle.
unsigned countResource(unsigned PIdx, unsigned Cycles, unsigned ReadyCycle)
Add the given processor resource to this scheduled zone.
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.
bool hasReservedResource
Uses a reserved resource.
void scheduleMI(SUnit *SU, bool IsTopNode)
Move an instruction and update register pressure.
virtual void overrideSchedPolicy(MachineSchedPolicy &Policy, unsigned NumRegionInstrs) const
Override generic scheduling policy within a region.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def...
MachineBasicBlock::iterator top() const
void buildDAGWithRegPressure()
Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking enabled.
unsigned WeakSuccsLeft
of weak succs not scheduled.
static void getSchedRegions(MachineBasicBlock *MBB, MBBRegionsVector &Regions, bool RegionsTopDown)
static const char * getReasonStr(GenericSchedulerBase::CandReason Reason)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
static std::string getGraphName(const ScheduleDAG *G)
MachineBasicBlock::iterator begin() const
Returns an iterator to the top of the current scheduling region.
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
Itinerary data supplied by a subtarget to be used by a target.
unsigned NumPredsLeft
of preds not scheduled.
static void tracePick(GenericSchedulerBase::CandReason Reason, bool IsTop)
void releasePending()
Release pending ready nodes in to the available queue.
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...
COFF::MachineTypes Machine
ScheduleDAGMILive * createGenericSchedLive(MachineSchedContext *C)
Create the standard converging machine scheduler.
MachinePassRegistry - Track the registration of machine passes.
List of registers defined and used by a machine instruction.
virtual const TargetInstrInfo * getInstrInfo() const
std::vector< SUnit * >::iterator iterator
void collectVRegUses(SUnit &SU)
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.
unsigned getCurrMOps() const
Micro-ops issued in the current cycle.
const SUnit * getNextClusterSucc() const
void bumpNode(SUnit *SU)
Move the boundary of scheduled code by one SUnit.
SUnit * pickNode(bool &IsTopNode) override
Pick the next node to schedule.
unsigned getSubtreeID(const SUnit *SU) const
Get the ID of the subtree the given DAG node belongs to.
void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop, const RegPressureTracker &RPTracker, RegPressureTracker &TempTracker)
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
SUnit * getSUnit(MachineInstr *MI) const
Returns an existing SUnit for this MI, or nullptr.
void checkAcyclicLatency()
Set IsAcyclicLatencyLimited if the acyclic path is longer than the cyclic critical path by more cycle...
static std::string getNodeDescription(const SUnit *SU, const ScheduleDAG *G)
VNInfo * valueIn() const
Return the value that is live-in to the instruction.
void incExecutedResources(unsigned PIdx, unsigned Count)
LiveQueryResult Query(SlotIndex Idx) const
Query Liveness at Idx.
TargetInstrInfo - Interface to description of machine instruction set.
virtual void registerRoots()
Notify this strategy that all roots have been released (including those that depend on EntrySU or Exi...
bool isUnbuffered
Uses an unbuffered resource.
void getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, ArrayRef< PressureChange > CriticalPSets, ArrayRef< unsigned > MaxPressureLimit)
Consider the pressure increase caused by traversing this instruction top-down.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
unsigned getPSetOrMax() const
initializer< Ty > init(const Ty &Val)
bool isCall
Is a function call.
SlotIndex endIndex() const
endNumber - return the maximum point of the range of the whole, exclusive.
unsigned getNextResourceCycle(unsigned PIdx, unsigned Cycles)
Compute the next cycle at which the given processor resource can be scheduled.
CandReason
Represent the type of SchedCandidate found within a single queue.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
Helpers for implementing custom MachineSchedStrategy classes.
bool isArtificial() const
Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...
unsigned const MachineRegisterInfo * MRI
PressureChange CurrentMax
bool tryGreater(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
unsigned short Latency
Node latency.
static const unsigned MinSubtreeSize
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
void removeReady(SUnit *SU)
Remove SU from the ready set for this boundary.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Summarize the scheduling resources required for an instruction of a particular scheduling class...
void updatePressureDiffs(ArrayRef< RegisterMaskPair > LiveUses)
Update the PressureDiff array for liveness after scheduling this instruction.
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...
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
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.
Printable printVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *TRI)
Create Printable object to print virtual registers and physical registers on a raw_ostream.
RegisterPressure computed within a region of instructions delimited by TopPos and BottomPos...
int getNumOccurrences() const
virtual bool doMBBSchedRegionsTopDown() const
If this method returns true, handling of the scheduling regions themselves (in case of a scheduling b...
bool addEdge(SUnit *SuccSU, const SDep &PredDep)
Add a DAG edge to the given SU with the given predecessor dependence data.
Represent the analysis usage information of a pass.
Store the state used by GenericScheduler heuristics, required for the lifetime of one invocation of p...
bool checkHazard(SUnit *SU)
Does this SU have a hazard within the current instruction group.
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
void releasePred(SUnit *SU, SDep *PredEdge)
ReleasePred - Decrement the NumSuccsLeft count of a predecessor.
Track the current register pressure at some position in the instruction stream, and remember the high...
virtual void releaseBottomNode(SUnit *SU)=0
When all successor dependencies have been resolved, free this node for bottom-up scheduling.
Policy for scheduling the next instruction in the candidate's zone.
static ScheduleDAGInstrs * useDefaultMachineSched(MachineSchedContext *C)
A dummy default scheduler factory indicates whether the scheduler is overridden on the command line...
const TargetSchedModel * getSchedModel() const
Gets the machine model for instruction scheduling.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
unsigned getScheduledLatency() const
Get the number of latency cycles "covered" by the scheduled instructions.
List of PressureChanges in order of increasing, unique PSetID.
virtual void exitRegion()
Called when the scheduler has finished scheduling the current region.
DOTGraphTraits(bool isSimple=false)
SchedResourceDelta ResDelta
ScheduleDAGInstrs *(*)(MachineSchedContext *) ScheduleDAGCtor
std::unique_ptr< ScheduleDAGMutation > createStoreClusterDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
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...
void initQueues(ArrayRef< SUnit *> TopRoots, ArrayRef< SUnit *> BotRoots)
Release ExitSU predecessors and setup scheduler queues.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
unsigned getWeakLeft(const SUnit *SU, bool isTop)
bool isDebugInstr() const
void releaseSuccessors(SUnit *SU)
releaseSuccessors - Call releaseSucc on each of SU's successors.
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream...
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void viewGraph() override
Out-of-line implementation with no arguments is handy for gdb.
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...
virtual bool enableMachineScheduler() const
True if the subtarget should run MachineScheduler after aggressive coalescing.
static cl::opt< bool > EnableRegPressure("misched-regpressure", cl::Hidden, cl::desc("Enable register pressure scheduling."), cl::init(true))
void sort(IteratorTy Start, IteratorTy End)
iterator find(SlotIndex Pos)
find - Return an iterator pointing to the first segment that ends after Pos, or end().
unsigned WeakPredsLeft
of weak preds not scheduled.
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel, SchedRemainder *rem)
static cl::opt< unsigned > SchedOnlyBlock("misched-only-block", cl::Hidden, cl::desc("Only schedule this MBB#"))
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
std::vector< unsigned > MaxSetPressure
Map of max reg pressure indexed by pressure set ID, not class ID.
void adjustLaneLiveness(const LiveIntervals &LIS, const MachineRegisterInfo &MRI, SlotIndex Pos, MachineInstr *AddFlagsMI=nullptr)
Use liveness information to find out which uses/defs are partially undefined/dead and adjust the Regi...
virtual bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const
Test if the given instruction should be considered a scheduling boundary.
Iterator for intrusive lists based on ilist_node.
std::unique_ptr< ScheduleDAGMutation > createLoadClusterDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
static bool isSameInstr(SlotIndex A, SlotIndex B)
isSameInstr - Return true if A and B refer to the same instruction.
void registerRoots() override
Notify this strategy that all roots have been released (including those that depend on EntrySU or Exi...
AnalysisUsage & addRequiredID(const void *ID)
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
static cl::opt< unsigned > MISchedCutoff("misched-cutoff", cl::Hidden, cl::desc("Stop scheduling after N instructions"), cl::init(~0U))
static ScheduleDAGInstrs * createILPMinScheduler(MachineSchedContext *C)
MachineInstrBuilder MachineInstrBuilder & DefMI
static cl::opt< bool > EnableMachineSched("enable-misched", cl::desc("Enable the machine instruction scheduling pass."), cl::init(true), cl::Hidden)
Information about stack frame layout on the target.
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
cl::opt< bool > DumpCriticalPathLength("misched-dcpl", cl::Hidden, cl::desc("Print critical path length to stdout"))
void releaseNode(SUnit *SU, unsigned ReadyCycle)
unsigned getMicroOpFactor() const
Multiply number of micro-ops by this factor to normalize it relative to other resources.
CHAIN = SC CHAIN, Imm128 - System call.
const RegPressureTracker & getTopRPTracker() const
StringRef getColorString(unsigned NodeNumber)
Get a color string for this node number.
void updateScheduledPressure(const SUnit *SU, const std::vector< unsigned > &NewMaxPressure)
bool isResourceLimited() const
void setPreservesCFG()
This function should be called by the pass, iff they do not:
LiveInterval & getInterval(unsigned Reg)
std::unique_ptr< ScheduleDAGMutation > createCopyConstrainDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
static cl::opt< bool > EnableCyclicPath("misched-cyclicpath", cl::Hidden, cl::desc("Enable cyclic critical path analysis."), cl::init(true))
void initResourceDelta(const ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel)
INITIALIZE_PASS(PostMachineScheduler, "postmisched", "PostRA Machine Instruction Scheduler", false, false) PostMachineScheduler
const Function & getFunction() const
Return the LLVM function that this machine code represents.
~ScheduleDAGMILive() override
void initializeMachineSchedulerPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned getOtherResourceCount(unsigned &OtherCritIdx)
void dumpPolicy() const override
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
VNInfo * getVNInfoBefore(SlotIndex Idx) const
getVNInfoBefore - Return the VNInfo that is live up to but not necessarilly including Idx...
virtual void finalizeSchedule()
Allow targets to perform final scheduling actions at the level of the whole MachineFunction.
void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand)
Apply a set of heuristics to a new candidate for PostRA scheduling.
bool tryLess(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
Return true if this heuristic determines order.
bool getMemOperandWithOffset(MachineInstr &LdSt, MachineOperand *&BaseOp, int64_t &Offset, const TargetRegisterInfo *TRI) const override
Get the base register and byte offset of a load/store instr.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
PressureChange CriticalMax
virtual void schedule()=0
Orders nodes according to selected style.
unsigned getResourceFactor(unsigned ResIdx) const
Multiply the number of units consumed for a resource by this factor to normalize it relative to other...
typename SuperClass::iterator iterator
void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos)
Change the position of an instruction within the basic block and update live ranges and region bounda...
unsigned getNumProcResourceKinds() const
Get the number of kinds of resources for this target.
void dumpNode(const SUnit &SU) const override
static MachineSchedRegistry DefaultSchedRegistry("default", "Use the target's default scheduler choice.", useDefaultMachineSched)
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
void schedNode(SUnit *SU, bool IsTopNode) override
Update the scheduler's state after scheduling a node.
virtual void scheduleTree(unsigned SubtreeID)
Scheduler callback to notify that a new subtree is scheduled.
const MachineBasicBlock * getParent() const
void releasePredecessors(SUnit *SU)
releasePredecessors - Call releasePred on each of SU's predecessors.
unsigned getSubtreeLevel(unsigned SubtreeID) const
Get the connection level of a subtree.
void initialize(ScheduleDAGMI *dag) override
Initialize the strategy after building the DAG for a new region.
virtual void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const
Apply a set of heuristics to a new candidate.
virtual SUnit * pickNode(bool &IsTopNode)=0
Pick the next node to schedule, or return NULL.
unsigned getHeight() const
Returns the height of this node, which is the length of the maximum path down to any node which has n...
void reschedulePhysReg(SUnit *SU, bool isTop)
A ScheduleDAG for scheduling lists of MachineInstr.
reverse_iterator rend() const
Representation of each machine instruction.
SUnit ExitSU
Special node for the region exit.
void initializePostMachineSchedulerPass(PassRegistry &)
void dump(const TargetRegisterInfo &TRI) const
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
void initialize(ScheduleDAGMI *Dag) override
Initialize the strategy after building the DAG for a new region.
const TargetRegisterInfo * TRI
Target processor register info.
SUnit * pickOnlyChoice()
Call this before applying any other heuristics to the Available queue.
void findRootsAndBiasEdges(SmallVectorImpl< SUnit *> &TopRoots, SmallVectorImpl< SUnit *> &BotRoots)
void dumpRegSetPressure(ArrayRef< unsigned > SetPressure, const TargetRegisterInfo *TRI)
Status of an instruction's critical resource consumption.
~ScheduleDAGMI() override
LiveIntervals * getLIS() const
char & PostMachineSchedulerID
PostMachineScheduler - This pass schedules machine instructions postRA.
cl::opt< bool > ForceBottomUp
bool verify(Pass *p=nullptr, const char *Banner=nullptr, bool AbortOnError=true) const
Run the current MachineFunction through the machine code verifier, useful for debugger use...
void dumpScheduledState() const
MachineBasicBlock::iterator bottom() const
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
MachineSchedStrategy - Interface to the scheduling algorithm used by ScheduleDAGMI.
Capture a change in pressure for a single pressure set.
virtual const TargetFrameLowering * getFrameLowering() const
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
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.
const SUnit * getNextClusterPred() const
static ScheduleDAGInstrs * createConveringSched(MachineSchedContext *C)
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
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...
unsigned getLatencyStallCycles(SUnit *SU)
Get the difference between the given SUnit's ready time and the current cycle.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
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.
const TargetInstrInfo * TII
Target instruction information.
static bool isNodeHidden(const SUnit *Node)
Kind getKind() const
Returns an enum value representing the kind of the dependence.
static MachineSchedRegistry GenericSchedRegistry("converge", "Standard converging scheduler.", createConveringSched)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
virtual bool enablePostRAScheduler() const
True if the subtarget should run a scheduler after register allocation.
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...
unsigned NodeNum
Entry # of node in the node vector.
const std::vector< PressureChange > & getRegionCriticalPSets() const
bool isCtrlDep() const
Tests if this is not an SDep::Data dependence.
void registerRoots() override
Notify this strategy that all roots have been released (including those that depend on EntrySU or Exi...
MachineBasicBlock::iterator end() const
Returns an iterator to the bottom of the current scheduling region.
bool tryPressure(const PressureChange &TryP, const PressureChange &CandP, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason, const TargetRegisterInfo *TRI, const MachineFunction &MF)
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool addPred(const SDep &D, bool Required=true)
Adds the specified edge as a pred of the current node if not already.
bool operator<(int64_t V1, const APSInt &V2)
A raw_ostream that writes to an std::string.
bool isTrackingPressure() const
Return true if register pressure tracking is enabled.
SlotIndex beginIndex() const
beginIndex - Return the lowest numbered slot covered.
bool isLocal(SlotIndex Start, SlotIndex End) const
True iff this segment is a single segment that lies between the specified boundaries, exclusively.
static bool checkResourceLimit(unsigned LFactor, unsigned Count, unsigned Latency)
Given a Count of resource usage and a Latency value, return true if a SchedBoundary becomes resource ...
void postprocessDAG()
Apply each ScheduleDAGMutation step in order.
nonconst_iterator getNonConstIterator() const
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAG *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
SmallVector< SDep, 4 > Succs
All sunit successors.
bool isCluster() const
Tests if this is an Order dependence that is marked as "cluster", meaning it is artificial and wants ...
static const Function * getParent(const Value *V)
Arbitrary strong DAG edge (no real dependence).
bool isWeak() const
Tests if this a weak dependence.
This class implements an extremely fast bulk output stream that can only output to a stream...
DefaultDOTGraphTraits - This class provides the default implementations of all of the DOTGraphTraits ...
Machine Instruction Scheduler
void clear()
clear - Erase all elements from the queue.
INITIALIZE_PASS_BEGIN(MachineScheduler, DEBUG_TYPE, "Machine Instruction Scheduler", false, false) INITIALIZE_PASS_END(MachineScheduler
bool canAddEdge(SUnit *SuccSU, SUnit *PredSU)
True if an edge can be added from PredSU to SuccSU without creating a cycle.
static MachineSchedRegistry ILPMinRegistry("ilpmin", "Schedule bottom-up for min ILP", createILPMinScheduler)
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
std::vector< SUnit > SUnits
The scheduling units.
PriorityQueue - This class behaves like std::priority_queue and provides a few additional convenience...
const MachineOperand & getOperand(unsigned i) const
SlotIndex - An opaque wrapper around machine indexes.
void finishBlock() override
Cleans up after scheduling in the given block.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setBest(SchedCandidate &Best)
virtual unsigned getRegPressureSetScore(const MachineFunction &MF, unsigned PSetID) const
Return a heuristic for the machine scheduler to compare the profitability of increasing one register ...
void pickNodeFromQueue(SchedCandidate &Cand)
Scheduling unit. This is a node in the scheduling DAG.
This file describes how to lower LLVM code to machine code.
void addMutation(std::unique_ptr< ScheduleDAGMutation > Mutation)
Add a postprocessing step to the DAG builder.
cl::opt< bool > ForceTopDown
static unsigned computeRemLatency(SchedBoundary &CurrZone)
Compute remaining latency.
ILPValue getILP(const SUnit *SU) const
Get the ILP value for a DAG node.
static cl::opt< bool > EnableMemOpCluster("misched-cluster", cl::Hidden, cl::desc("Enable memop clustering."), cl::init(true))
bool isArtificialDep() const