21#define DEBUG_TYPE "machine-scheduler"
125 case NoCand:
return "NOCAND";
127 case Latency:
return "LATENCY";
129 case Depth:
return "DEPTH";
142 if (TryVal < CandVal) {
146 if (TryVal > CandVal) {
159 if (TryVal > CandVal) {
163 if (TryVal < CandVal) {
176 NodeNum2Index[SU->
NodeNum] = SUnits.size();
177 SUnits.push_back(SU);
181void SIScheduleBlock::traceCandidate(
const SISchedCandidate &Cand) {
188void SIScheduleBlock::tryCandidateTopDown(SISchedCandidate &Cand,
189 SISchedCandidate &TryCand) {
191 if (!Cand.isValid()) {
196 if (Cand.SGPRUsage > 60 &&
217 Cand.HasLowLatencyNonWaitedParent,
225 if (TryCand.IsLowLatency &&
235 if (TryCand.SU->NodeNum < Cand.SU->NodeNum) {
240SUnit* SIScheduleBlock::pickNode() {
241 SISchedCandidate TopCand;
243 for (SUnit* SU : TopReadySUs) {
244 SISchedCandidate TryCand;
245 std::vector<unsigned> pressure;
246 std::vector<unsigned> MaxPressure;
249 TopRPTracker.getDownwardPressure(SU->getInstr(), pressure, MaxPressure);
250 TryCand.SGPRUsage = pressure[AMDGPU::RegisterPressureSets::SReg_32];
251 TryCand.VGPRUsage = pressure[AMDGPU::RegisterPressureSets::VGPR_32];
252 TryCand.IsLowLatency = DAG->IsLowLatencySU[SU->NodeNum];
253 TryCand.LowLatencyOffset = DAG->LowLatencyOffset[SU->NodeNum];
254 TryCand.HasLowLatencyNonWaitedParent =
255 HasLowLatencyNonWaitedParent[NodeNum2Index[SU->NodeNum]];
256 tryCandidateTopDown(TopCand, TryCand);
257 if (TryCand.Reason !=
NoCand)
258 TopCand.setBest(TryCand);
271 for (
SUnit* SU : SUnits) {
272 if (!SU->NumPredsLeft)
273 TopReadySUs.push_back(SU);
276 while (!TopReadySUs.empty()) {
277 SUnit *SU = TopReadySUs[0];
278 ScheduledSUnits.push_back(SU);
290 if (
MI.isDebugValue())
293 if (InstSlot >=
First && InstSlot <=
Last)
301 IntervalPressure Pressure, BotPressure;
302 RegPressureTracker RPTracker(Pressure), BotRPTracker(BotPressure);
303 LiveIntervals *LIS = DAG->getLIS();
304 MachineRegisterInfo *MRI = DAG->getMRI();
305 DAG->initRPTracker(TopRPTracker);
306 DAG->initRPTracker(BotRPTracker);
307 DAG->initRPTracker(RPTracker);
311 for (SUnit* SU : ScheduledSUnits) {
312 RPTracker.setPos(SU->getInstr());
317 RPTracker.closeRegion();
320 TopRPTracker.addLiveRegs(RPTracker.getPressure().LiveInRegs);
321 BotRPTracker.addLiveRegs(RPTracker.getPressure().LiveOutRegs);
324 for (
const auto &RegMaskPair : RPTracker.getPressure().LiveInRegs) {
325 if (RegMaskPair.VRegOrUnit.isVirtualReg())
326 LiveInRegs.insert(RegMaskPair.VRegOrUnit.asVirtualReg());
351 for (
const auto &RegMaskPair : RPTracker.getPressure().LiveOutRegs) {
352 VirtRegOrUnit VRegOrUnit = RegMaskPair.VRegOrUnit;
366 LiveInPressure = TopPressure.MaxSetPressure;
370 TopRPTracker.closeTop();
379 initRegPressure(BeginBlock, EndBlock);
386 for (
SUnit* SU : SUnits) {
387 if (!SU->NumPredsLeft)
388 TopReadySUs.push_back(SU);
391 while (!TopReadySUs.empty()) {
392 SUnit *SU = pickNode();
393 ScheduledSUnits.push_back(SU);
394 TopRPTracker.setPos(SU->
getInstr());
395 TopRPTracker.advance();
400 InternalAdditionalPressure.resize(TopPressure.MaxSetPressure.size());
404 assert(SUnits.size() == ScheduledSUnits.size() &&
405 TopReadySUs.empty());
406 for (
SUnit* SU : SUnits) {
408 SU->NumPredsLeft == 0);
415void SIScheduleBlock::undoSchedule() {
416 for (
SUnit* SU : SUnits) {
417 SU->isScheduled =
false;
418 for (
SDep& Succ : SU->Succs) {
420 undoReleaseSucc(SU, &Succ);
423 HasLowLatencyNonWaitedParent.assign(SUnits.size(), 0);
424 ScheduledSUnits.clear();
428void SIScheduleBlock::undoReleaseSucc(
SUnit *SU,
SDep *SuccEdge) {
429 SUnit *SuccSU = SuccEdge->
getSUnit();
438void SIScheduleBlock::releaseSucc(
SUnit *SU,
SDep *SuccEdge) {
439 SUnit *SuccSU = SuccEdge->
getSUnit();
447 dbgs() <<
"*** Scheduling failed! ***\n";
448 DAG->dumpNode(*SuccSU);
449 dbgs() <<
" has been released too many times!\n";
458void SIScheduleBlock::releaseSuccessors(
SUnit *SU,
bool InOrOutBlock) {
459 for (SDep& Succ : SU->
Succs) {
462 if (SuccSU->
NodeNum >= DAG->SUnits.size())
465 if (BC->isSUInBlock(SuccSU, ID) != InOrOutBlock)
468 releaseSucc(SU, &Succ);
470 TopReadySUs.push_back(SuccSU);
474void SIScheduleBlock::nodeScheduled(
SUnit *SU) {
477 std::vector<SUnit *>::iterator
I =
llvm::find(TopReadySUs, SU);
478 if (
I == TopReadySUs.end()) {
479 dbgs() <<
"Data Structure Bug in SI Scheduler\n";
482 TopReadySUs.erase(
I);
484 releaseSuccessors(SU,
true);
487 if (HasLowLatencyNonWaitedParent[NodeNum2Index[SU->
NodeNum]])
488 HasLowLatencyNonWaitedParent.assign(SUnits.size(), 0);
490 if (DAG->IsLowLatencySU[SU->
NodeNum]) {
491 for (SDep& Succ : SU->
Succs) {
492 std::map<unsigned, unsigned>::iterator
I =
494 if (
I != NodeNum2Index.end())
495 HasLowLatencyNonWaitedParent[
I->second] = 1;
503 for (
SUnit* SU : SUnits) {
504 releaseSuccessors(SU,
false);
505 if (DAG->IsHighLatencySU[SU->
NodeNum])
506 HighLatencyBlock =
true;
508 HasLowLatencyNonWaitedParent.resize(SUnits.size(), 0);
513 unsigned PredID = Pred->getID();
517 if (PredID ==
P->getID())
520 Preds.push_back(Pred);
525 return PredID == S.first->getID();
527 "Loop in the Block Graph!");
532 unsigned SuccID = Succ->
getID();
535 for (std::pair<SIScheduleBlock*, SIScheduleBlockLinkKind> &S : Succs) {
536 if (SuccID == S.first->getID()) {
544 ++NumHighLatencySuccessors;
545 Succs.emplace_back(Succ, Kind);
549 "Loop in the Block Graph!");
554 dbgs() <<
"Block (" << ID <<
")\n";
558 dbgs() <<
"\nContains High Latency Instruction: "
559 << HighLatencyBlock <<
'\n';
560 dbgs() <<
"\nDepends On:\n";
562 P->printDebug(
false);
565 dbgs() <<
"\nSuccessors:\n";
566 for (std::pair<SIScheduleBlock*, SIScheduleBlockLinkKind> S : Succs) {
568 dbgs() <<
"(Data Dep) ";
569 S.first->printDebug(
false);
573 dbgs() <<
"LiveInPressure "
574 << LiveInPressure[AMDGPU::RegisterPressureSets::SReg_32] <<
' '
575 << LiveInPressure[AMDGPU::RegisterPressureSets::VGPR_32] <<
'\n';
576 dbgs() <<
"LiveOutPressure "
577 << LiveOutPressure[AMDGPU::RegisterPressureSets::SReg_32] <<
' '
578 << LiveOutPressure[AMDGPU::RegisterPressureSets::VGPR_32] <<
"\n\n";
579 dbgs() <<
"LiveIns:\n";
583 dbgs() <<
"\nLiveOuts:\n";
588 dbgs() <<
"\nInstructions:\n";
589 for (
const SUnit* SU : SUnits)
592 dbgs() <<
"///////////////////////\n";
603 std::map<SISchedulerBlockCreatorVariant, SIScheduleBlocks>::iterator
B =
604 Blocks.find(BlockVariant);
605 if (
B == Blocks.end()) {
607 createBlocksForVariant(BlockVariant);
609 scheduleInsideBlocks();
611 Res.
Blocks = CurrentBlocks;
614 Blocks[BlockVariant] = Res;
621 if (SU->
NodeNum >= DAG->SUnits.size())
623 return CurrentBlocks[Node2CurrentBlock[SU->
NodeNum]]->getID() == ID;
626void SIScheduleBlockCreator::colorHighLatenciesAlone() {
627 unsigned DAGSize = DAG->
SUnits.size();
629 for (
unsigned i = 0, e = DAGSize; i != e; ++i) {
632 CurrentColoring[SU->
NodeNum] = NextReservedID++;
639 for (
const auto &PredDep : SU.
Preds) {
640 if (PredDep.getSUnit() == &FromSU &&
647void SIScheduleBlockCreator::colorHighLatenciesGroups() {
648 unsigned DAGSize = DAG->SUnits.size();
649 unsigned NumHighLatencies = 0;
651 int Color = NextReservedID;
653 std::set<unsigned> FormingGroup;
655 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
656 SUnit *SU = &DAG->SUnits[i];
657 if (DAG->IsHighLatencySU[SU->
NodeNum])
661 if (NumHighLatencies == 0)
664 if (NumHighLatencies <= 6)
666 else if (NumHighLatencies <= 12)
671 for (
unsigned SUNum : DAG->TopDownIndex2SU) {
672 const SUnit &SU = DAG->SUnits[SUNum];
673 if (DAG->IsHighLatencySU[SU.
NodeNum]) {
674 unsigned CompatibleGroup =
true;
675 int ProposedColor = Color;
676 std::vector<int> AdditionalElements;
688 for (
unsigned j : FormingGroup) {
690 std::vector<int> SubGraph;
695 SubGraph = DAG->GetTopo()->GetSubGraph(SU, DAG->SUnits[j],
699 SubGraph = DAG->GetTopo()->GetSubGraph(DAG->SUnits[j], SU,
703 if (SubGraph.size() > 5) {
705 CompatibleGroup =
false;
709 for (
unsigned k : SubGraph) {
714 if (DAG->IsHighLatencySU[k] || (CurrentColoring[k] != ProposedColor &&
715 CurrentColoring[k] != 0)) {
716 CompatibleGroup =
false;
722 CompatibleGroup =
false;
726 if (!CompatibleGroup)
730 CompatibleGroup =
false;
740 if (CompatibleGroup) {
741 FormingGroup.insert(SU.
NodeNum);
742 for (
unsigned j : AdditionalElements)
743 CurrentColoring[
j] = ProposedColor;
744 CurrentColoring[SU.
NodeNum] = ProposedColor;
750 if (!CompatibleGroup) {
751 FormingGroup.clear();
752 Color = ++NextReservedID;
753 ProposedColor = Color;
754 FormingGroup.insert(SU.
NodeNum);
755 CurrentColoring[SU.
NodeNum] = ProposedColor;
757 }
else if (
Count == GroupSize) {
758 FormingGroup.clear();
759 Color = ++NextReservedID;
760 ProposedColor = Color;
767void SIScheduleBlockCreator::colorComputeReservedDependencies() {
768 unsigned DAGSize = DAG->SUnits.size();
769 std::map<std::set<unsigned>,
unsigned> ColorCombinations;
771 CurrentTopDownReservedDependencyColoring.clear();
772 CurrentBottomUpReservedDependencyColoring.clear();
774 CurrentTopDownReservedDependencyColoring.resize(DAGSize, 0);
775 CurrentBottomUpReservedDependencyColoring.resize(DAGSize, 0);
780 for (
unsigned SUNum : DAG->TopDownIndex2SU) {
781 SUnit *SU = &DAG->SUnits[SUNum];
782 std::set<unsigned> SUColors;
785 if (CurrentColoring[SU->
NodeNum]) {
786 CurrentTopDownReservedDependencyColoring[SU->
NodeNum] =
791 for (SDep& PredDep : SU->
Preds) {
795 if (CurrentTopDownReservedDependencyColoring[Pred->
NodeNum] > 0)
796 SUColors.insert(CurrentTopDownReservedDependencyColoring[Pred->
NodeNum]);
799 if (SUColors.empty())
802 if (SUColors.size() == 1 && *SUColors.begin() > DAGSize)
803 CurrentTopDownReservedDependencyColoring[SU->
NodeNum] =
807 ColorCombinations.try_emplace(SUColors, NextNonReservedID);
810 CurrentTopDownReservedDependencyColoring[SU->
NodeNum] = Pos->second;
814 ColorCombinations.clear();
818 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
819 SUnit *SU = &DAG->SUnits[SUNum];
820 std::set<unsigned> SUColors;
823 if (CurrentColoring[SU->
NodeNum]) {
824 CurrentBottomUpReservedDependencyColoring[SU->
NodeNum] =
829 for (SDep& SuccDep : SU->
Succs) {
833 if (CurrentBottomUpReservedDependencyColoring[Succ->
NodeNum] > 0)
834 SUColors.insert(CurrentBottomUpReservedDependencyColoring[Succ->
NodeNum]);
837 if (SUColors.empty())
840 if (SUColors.size() == 1 && *SUColors.begin() > DAGSize)
841 CurrentBottomUpReservedDependencyColoring[SU->
NodeNum] =
844 std::map<std::set<unsigned>,
unsigned>::iterator Pos =
845 ColorCombinations.find(SUColors);
846 if (Pos != ColorCombinations.end()) {
847 CurrentBottomUpReservedDependencyColoring[SU->
NodeNum] = Pos->second;
849 CurrentBottomUpReservedDependencyColoring[SU->
NodeNum] =
851 ColorCombinations[SUColors] = NextNonReservedID++;
857void SIScheduleBlockCreator::colorAccordingToReservedDependencies() {
858 std::map<std::pair<unsigned, unsigned>,
unsigned> ColorCombinations;
863 for (
const SUnit &SU : DAG->SUnits) {
864 std::pair<unsigned, unsigned> SUColors;
867 if (CurrentColoring[SU.
NodeNum])
870 SUColors.first = CurrentTopDownReservedDependencyColoring[SU.
NodeNum];
871 SUColors.second = CurrentBottomUpReservedDependencyColoring[SU.
NodeNum];
874 ColorCombinations.try_emplace(SUColors, NextNonReservedID);
875 CurrentColoring[SU.
NodeNum] = Pos->second;
881void SIScheduleBlockCreator::colorEndsAccordingToDependencies() {
882 unsigned DAGSize = DAG->SUnits.size();
883 std::vector<int> PendingColoring = CurrentColoring;
886 CurrentBottomUpReservedDependencyColoring.size() == DAGSize &&
887 CurrentTopDownReservedDependencyColoring.size() == DAGSize);
894 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
895 SUnit *SU = &DAG->SUnits[SUNum];
896 std::set<unsigned> SUColors;
897 std::set<unsigned> SUColorsPending;
899 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
902 if (CurrentBottomUpReservedDependencyColoring[SU->
NodeNum] > 0 ||
903 CurrentTopDownReservedDependencyColoring[SU->
NodeNum] > 0)
906 for (SDep& SuccDep : SU->
Succs) {
910 if (CurrentBottomUpReservedDependencyColoring[Succ->
NodeNum] > 0 ||
911 CurrentTopDownReservedDependencyColoring[Succ->
NodeNum] > 0)
912 SUColors.insert(CurrentColoring[Succ->
NodeNum]);
913 SUColorsPending.insert(PendingColoring[Succ->
NodeNum]);
918 if (SUColors.size() == 1 && SUColorsPending.size() == 1)
919 PendingColoring[SU->
NodeNum] = *SUColors.begin();
922 PendingColoring[SU->
NodeNum] = NextNonReservedID++;
924 CurrentColoring = std::move(PendingColoring);
928void SIScheduleBlockCreator::colorForceConsecutiveOrderInGroup() {
929 unsigned DAGSize = DAG->SUnits.size();
930 unsigned PreviousColor;
931 std::set<unsigned> SeenColors;
936 PreviousColor = CurrentColoring[0];
938 for (
unsigned i = 1, e = DAGSize; i !=
e; ++i) {
939 SUnit *SU = &DAG->SUnits[i];
940 unsigned CurrentColor = CurrentColoring[i];
941 unsigned PreviousColorSave = PreviousColor;
944 if (CurrentColor != PreviousColor)
945 SeenColors.insert(PreviousColor);
946 PreviousColor = CurrentColor;
948 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
951 if (SeenColors.find(CurrentColor) == SeenColors.end())
954 if (PreviousColorSave != CurrentColor)
955 CurrentColoring[i] = NextNonReservedID++;
957 CurrentColoring[i] = CurrentColoring[i-1];
961void SIScheduleBlockCreator::colorMergeConstantLoadsNextGroup() {
962 unsigned DAGSize = DAG->SUnits.size();
964 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
965 SUnit *SU = &DAG->SUnits[SUNum];
966 std::set<unsigned> SUColors;
968 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
973 if (!SU->
Preds.empty() && !DAG->IsLowLatencySU[SU->
NodeNum])
976 for (SDep& SuccDep : SU->
Succs) {
980 SUColors.insert(CurrentColoring[Succ->
NodeNum]);
982 if (SUColors.size() == 1)
983 CurrentColoring[SU->
NodeNum] = *SUColors.begin();
987void SIScheduleBlockCreator::colorMergeIfPossibleNextGroupOnlyForReserved() {
988 unsigned DAGSize = DAG->SUnits.size();
990 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
991 SUnit *SU = &DAG->SUnits[SUNum];
992 std::set<unsigned> SUColors;
994 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
997 for (SDep& SuccDep : SU->
Succs) {
1001 SUColors.insert(CurrentColoring[Succ->
NodeNum]);
1003 if (SUColors.size() == 1 && *SUColors.begin() <= DAGSize)
1004 CurrentColoring[SU->
NodeNum] = *SUColors.begin();
1008void SIScheduleBlockCreator::regroupNoUserInstructions() {
1009 unsigned DAGSize = DAG->SUnits.size();
1010 int GroupID = NextNonReservedID++;
1012 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
1013 SUnit *SU = &DAG->SUnits[SUNum];
1014 bool hasSuccessor =
false;
1016 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
1019 for (SDep& SuccDep : SU->
Succs) {
1023 hasSuccessor =
true;
1026 CurrentColoring[SU->
NodeNum] = GroupID;
1030void SIScheduleBlockCreator::colorExports() {
1031 unsigned ExportColor = NextNonReservedID++;
1032 SmallVector<unsigned, 8> ExpGroup;
1044 for (
unsigned SUNum : DAG->TopDownIndex2SU) {
1045 const SUnit &SU = DAG->SUnits[SUNum];
1049 for (
const SDep &SuccDep : SU.
Succs) {
1050 const SUnit *SuccSU = SuccDep.
getSUnit();
1051 if (SuccDep.
isWeak() || SuccSU->
NodeNum >= DAG->SUnits.size()) {
1056 "SUnit unexpectedly not representing an instruction!");
1072 for (
unsigned j : ExpGroup)
1073 CurrentColoring[
j] = ExportColor;
1077 unsigned DAGSize = DAG->SUnits.size();
1078 std::map<unsigned,unsigned> RealID;
1080 CurrentBlocks.clear();
1081 CurrentColoring.clear();
1082 CurrentColoring.resize(DAGSize, 0);
1083 Node2CurrentBlock.clear();
1086 DAG->restoreSULinksLeft();
1089 NextNonReservedID = DAGSize + 1;
1094 colorHighLatenciesGroups();
1096 colorHighLatenciesAlone();
1097 colorComputeReservedDependencies();
1098 colorAccordingToReservedDependencies();
1099 colorEndsAccordingToDependencies();
1101 colorForceConsecutiveOrderInGroup();
1102 regroupNoUserInstructions();
1103 colorMergeConstantLoadsNextGroup();
1104 colorMergeIfPossibleNextGroupOnlyForReserved();
1108 Node2CurrentBlock.resize(DAGSize, -1);
1109 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1110 SUnit *SU = &DAG->SUnits[i];
1111 unsigned Color = CurrentColoring[SU->
NodeNum];
1112 auto [It,
Inserted] = RealID.try_emplace(Color);
1114 int ID = CurrentBlocks.size();
1115 BlockPtrs.push_back(std::make_unique<SIScheduleBlock>(DAG,
this, ID));
1116 CurrentBlocks.push_back(BlockPtrs.rbegin()->get());
1119 CurrentBlocks[It->second]->addUnit(SU);
1120 Node2CurrentBlock[SU->
NodeNum] = It->second;
1124 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1125 SUnit *SU = &DAG->SUnits[i];
1126 int SUID = Node2CurrentBlock[i];
1127 for (SDep& SuccDep : SU->
Succs) {
1131 if (Node2CurrentBlock[Succ->
NodeNum] != SUID)
1132 CurrentBlocks[SUID]->addSucc(CurrentBlocks[Node2CurrentBlock[Succ->
NodeNum]],
1135 for (SDep& PredDep : SU->
Preds) {
1139 if (Node2CurrentBlock[Pred->
NodeNum] != SUID)
1140 CurrentBlocks[SUID]->
addPred(CurrentBlocks[Node2CurrentBlock[Pred->
NodeNum]]);
1145 for (SIScheduleBlock *
Block : CurrentBlocks)
1146 Block->finalizeUnits();
1148 dbgs() <<
"Blocks created:\n\n";
1149 for (SIScheduleBlock *
Block : CurrentBlocks)
1150 Block->printDebug(
true);
1160 for (;
I != End; ++
I) {
1161 if (!
I->isDebugInstr())
1167void SIScheduleBlockCreator::topologicalSort() {
1168 unsigned DAGSize = CurrentBlocks.size();
1169 std::vector<int> WorkList;
1173 WorkList.reserve(DAGSize);
1174 TopDownIndex2Block.resize(DAGSize);
1175 TopDownBlock2Index.resize(DAGSize);
1176 BottomUpIndex2Block.resize(DAGSize);
1178 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1179 SIScheduleBlock *
Block = CurrentBlocks[i];
1180 unsigned Degree =
Block->getSuccs().size();
1181 TopDownBlock2Index[i] = Degree;
1183 WorkList.push_back(i);
1188 while (!WorkList.empty()) {
1189 int i = WorkList.back();
1190 SIScheduleBlock *
Block = CurrentBlocks[i];
1191 WorkList.pop_back();
1192 TopDownBlock2Index[i] = --
Id;
1193 TopDownIndex2Block[
Id] = i;
1194 for (SIScheduleBlock* Pred :
Block->getPreds()) {
1195 if (!--TopDownBlock2Index[Pred->getID()])
1196 WorkList.push_back(Pred->getID());
1202 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1203 SIScheduleBlock *
Block = CurrentBlocks[i];
1204 for (SIScheduleBlock* Pred :
Block->getPreds()) {
1205 assert(TopDownBlock2Index[i] > TopDownBlock2Index[Pred->getID()] &&
1206 "Wrong Top Down topological sorting");
1211 BottomUpIndex2Block = std::vector<int>(TopDownIndex2Block.rbegin(),
1212 TopDownIndex2Block.rend());
1215void SIScheduleBlockCreator::scheduleInsideBlocks() {
1216 unsigned DAGSize = CurrentBlocks.size();
1222 LLVM_DEBUG(
dbgs() <<
"First phase: Fast scheduling for Reg Liveness\n");
1223 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1224 SIScheduleBlock *
Block = CurrentBlocks[i];
1225 Block->fastSchedule();
1233 std::vector<MachineBasicBlock::iterator> PosOld;
1234 std::vector<MachineBasicBlock::iterator> PosNew;
1235 PosOld.reserve(DAG->SUnits.size());
1236 PosNew.reserve(DAG->SUnits.size());
1238 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1239 int BlockIndice = TopDownIndex2Block[i];
1240 SIScheduleBlock *
Block = CurrentBlocks[BlockIndice];
1241 std::vector<SUnit*> SUs =
Block->getScheduledUnits();
1243 for (SUnit* SU : SUs) {
1246 PosOld.push_back(Pos);
1247 if (&*CurrentTopFastSched ==
MI) {
1248 PosNew.push_back(Pos);
1249 CurrentTopFastSched =
nextIfDebug(++CurrentTopFastSched,
1250 DAG->getCurrentBottom());
1253 DAG->getBB()->splice(CurrentTopFastSched, DAG->getBB(),
MI);
1260 DAG->getLIS()->handleMove(*
MI,
true);
1261 PosNew.push_back(CurrentTopFastSched);
1270 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1271 SIScheduleBlock *
Block = CurrentBlocks[i];
1272 std::vector<SUnit*> SUs =
Block->getScheduledUnits();
1273 Block->schedule((*SUs.begin())->getInstr(), (*SUs.rbegin())->getInstr());
1278 for (
unsigned i = PosOld.size(), e = 0; i != e; --i) {
1283 DAG->getBB()->splice(POld, DAG->getBB(), PNew);
1286 DAG->getLIS()->handleMove(*POld,
true);
1291 for (SIScheduleBlock *
Block : CurrentBlocks)
1292 Block->printDebug(
true);
1296void SIScheduleBlockCreator::fillStats() {
1297 unsigned DAGSize = CurrentBlocks.size();
1299 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1300 int BlockIndice = TopDownIndex2Block[i];
1301 SIScheduleBlock *
Block = CurrentBlocks[BlockIndice];
1302 if (
Block->getPreds().empty())
1306 for (SIScheduleBlock *Pred :
Block->getPreds()) {
1308 Depth = Pred->Depth + Pred->getCost();
1314 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1315 int BlockIndice = BottomUpIndex2Block[i];
1316 SIScheduleBlock *
Block = CurrentBlocks[BlockIndice];
1317 if (
Block->getSuccs().empty())
1320 unsigned Height = 0;
1321 for (
const auto &Succ :
Block->getSuccs())
1322 Height = std::max(Height, Succ.first->Height + Succ.first->getCost());
1323 Block->Height = Height;
1333 DAG(DAG), Variant(Variant), Blocks(BlocksStruct.Blocks),
1334 LastPosWaitedHighLatency(0), NumBlockScheduled(0), VregCurrentUsage(0),
1335 SregCurrentUsage(0), maxVregUsage(0), maxSregUsage(0) {
1347 LiveOutRegsNumUsages.resize(Blocks.size());
1353 std::set<Register> PredOutRegs = Pred->getOutRegs();
1354 std::set<Register>::iterator RegPos = PredOutRegs.find(Reg);
1356 if (RegPos != PredOutRegs.end()) {
1368 ++LiveOutRegsNumUsages[PredID][Reg];
1372 LastPosHighLatencyParentScheduled.resize(Blocks.size(), 0);
1373 BlockNumPredsLeft.resize(Blocks.size());
1374 BlockNumSuccsLeft.resize(Blocks.size());
1376 for (
unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1377 SIScheduleBlock *Block = Blocks[i];
1378 BlockNumPredsLeft[i] = Block->getPreds().size();
1379 BlockNumSuccsLeft[i] = Block->getSuccs().size();
1383 for (
unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1384 SIScheduleBlock *Block = Blocks[i];
1385 assert(Block->getID() == i);
1389 std::set<VirtRegOrUnit> InRegs = DAG->getInRegs();
1390 addLiveRegs(InRegs);
1396 for (unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1398 int ID = BlocksStruct.TopDownIndex2Block[Blocks.size()-1-i];
1399 SIScheduleBlock *Block = Blocks[ID];
1400 const std::set<Register> &OutRegs = Block->getOutRegs();
1402 if (!VRegOrUnit.isVirtualReg() ||
1403 OutRegs.find(VRegOrUnit.asVirtualReg()) == OutRegs.end())
1406 ++LiveOutRegsNumUsages[ID][VRegOrUnit.asVirtualReg()];
1417 std::set<Register> PredOutRegs = Pred->getOutRegs();
1418 std::set<Register>::iterator RegPos = PredOutRegs.find(Reg);
1420 if (RegPos != PredOutRegs.end()) {
1427 ++LiveRegsConsumers[
Reg];
1431 for (
unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1432 SIScheduleBlock *Block = Blocks[i];
1433 if (BlockNumPredsLeft[i] == 0) {
1434 ReadyBlocks.push_back(Block);
1439 BlocksScheduled.push_back(
Block);
1440 blockScheduled(
Block);
1444 : BlocksScheduled) {
1449bool SIScheduleBlockScheduler::tryCandidateLatency(SIBlockSchedCandidate &Cand,
1450 SIBlockSchedCandidate &TryCand) {
1451 if (!Cand.isValid()) {
1458 Cand.LastPosHighLatParentScheduled, TryCand, Cand,
Latency))
1465 TryCand, Cand,
Depth))
1468 Cand.NumHighLatencySuccessors,
1474bool SIScheduleBlockScheduler::tryCandidateRegUsage(SIBlockSchedCandidate &Cand,
1475 SIBlockSchedCandidate &TryCand) {
1476 if (!Cand.isValid()) {
1485 Cand.NumSuccessors > 0,
1497 SIBlockSchedCandidate Cand;
1498 std::vector<SIScheduleBlock*>::iterator Best;
1499 SIScheduleBlock *
Block;
1500 if (ReadyBlocks.empty())
1503 DAG->fillVgprSgprCost(LiveRegs.begin(), LiveRegs.end(),
1504 VregCurrentUsage, SregCurrentUsage);
1505 if (VregCurrentUsage > maxVregUsage)
1506 maxVregUsage = VregCurrentUsage;
1507 if (SregCurrentUsage > maxSregUsage)
1508 maxSregUsage = SregCurrentUsage;
1510 dbgs() <<
"Picking New Blocks\n";
1511 dbgs() <<
"Available: ";
1512 for (SIScheduleBlock *
Block : ReadyBlocks)
1514 dbgs() <<
"\nCurrent Live:\n";
1518 dbgs() <<
"Current VGPRs: " << VregCurrentUsage <<
'\n';
1519 dbgs() <<
"Current SGPRs: " << SregCurrentUsage <<
'\n';
1522 Cand.Block =
nullptr;
1523 for (std::vector<SIScheduleBlock*>::iterator
I = ReadyBlocks.begin(),
1524 E = ReadyBlocks.end();
I !=
E; ++
I) {
1525 SIBlockSchedCandidate TryCand;
1527 TryCand.IsHighLatency = TryCand.Block->isHighLatencyBlock();
1528 TryCand.VGPRUsageDiff =
1529 checkRegUsageImpact(TryCand.Block->getInRegs(),
1530 TryCand.Block->getOutRegs())[AMDGPU::RegisterPressureSets::VGPR_32];
1531 TryCand.NumSuccessors = TryCand.Block->getSuccs().size();
1532 TryCand.NumHighLatencySuccessors =
1533 TryCand.Block->getNumHighLatencySuccessors();
1534 TryCand.LastPosHighLatParentScheduled =
1535 (
unsigned int) std::max<int> (0,
1536 LastPosHighLatencyParentScheduled[TryCand.Block->getID()] -
1537 LastPosWaitedHighLatency);
1538 TryCand.Height = TryCand.Block->Height;
1540 if (VregCurrentUsage > 120 ||
1542 if (!tryCandidateRegUsage(Cand, TryCand) &&
1544 tryCandidateLatency(Cand, TryCand);
1546 if (!tryCandidateLatency(Cand, TryCand))
1547 tryCandidateRegUsage(Cand, TryCand);
1549 if (TryCand.Reason !=
NoCand) {
1550 Cand.setBest(TryCand);
1552 LLVM_DEBUG(
dbgs() <<
"Best Current Choice: " << Cand.Block->getID() <<
' '
1558 dbgs() <<
"Is a block with high latency instruction: "
1559 << (Cand.IsHighLatency ?
"yes\n" :
"no\n");
1560 dbgs() <<
"Position of last high latency dependency: "
1561 << Cand.LastPosHighLatParentScheduled <<
'\n';
1562 dbgs() <<
"VGPRUsageDiff: " << Cand.VGPRUsageDiff <<
'\n';
1566 ReadyBlocks.erase(Best);
1572void SIScheduleBlockScheduler::addLiveRegs(std::set<VirtRegOrUnit> &Regs) {
1573 for (VirtRegOrUnit VRegOrUnit : Regs) {
1583 std::set<Register> &Regs) {
1586 std::set<Register>::iterator Pos = LiveRegs.find(
Reg);
1587 assert (Pos != LiveRegs.end() &&
1588 LiveRegsConsumers.find(
Reg) != LiveRegsConsumers.end() &&
1589 LiveRegsConsumers[
Reg] >= 1);
1590 --LiveRegsConsumers[
Reg];
1591 if (LiveRegsConsumers[
Reg] == 0)
1592 LiveRegs.erase(Pos);
1596void SIScheduleBlockScheduler::releaseBlockSuccs(
SIScheduleBlock *Parent) {
1598 if (--BlockNumPredsLeft[
Block.first->getID()] == 0)
1599 ReadyBlocks.push_back(
Block.first);
1603 LastPosHighLatencyParentScheduled[
Block.first->getID()] = NumBlockScheduled;
1609 LiveRegs.insert(
Block->getOutRegs().begin(),
Block->getOutRegs().end());
1610 releaseBlockSuccs(
Block);
1611 for (
const auto &RegP : LiveOutRegsNumUsages[
Block->getID()]) {
1613 assert(LiveRegsConsumers.find(RegP.first) == LiveRegsConsumers.end() ||
1614 LiveRegsConsumers[RegP.first] == 0);
1615 LiveRegsConsumers[RegP.first] += RegP.second;
1617 if (LastPosHighLatencyParentScheduled[
Block->getID()] >
1618 (
unsigned)LastPosWaitedHighLatency)
1619 LastPosWaitedHighLatency =
1620 LastPosHighLatencyParentScheduled[
Block->getID()];
1621 ++NumBlockScheduled;
1625SIScheduleBlockScheduler::checkRegUsageImpact(std::set<Register> &InRegs,
1626 std::set<Register> &OutRegs) {
1627 std::vector<int> DiffSetPressure;
1628 DiffSetPressure.assign(DAG->getTRI()->getNumRegPressureSets(), 0);
1634 if (LiveRegsConsumers[
Reg] > 1)
1636 PSetIterator PSetI = DAG->getMRI()->getPressureSets(VirtRegOrUnit(
Reg));
1637 for (; PSetI.
isValid(); ++PSetI) {
1638 DiffSetPressure[*PSetI] -= PSetI.
getWeight();
1646 PSetIterator PSetI = DAG->getMRI()->getPressureSets(VirtRegOrUnit(
Reg));
1647 for (; PSetI.
isValid(); ++PSetI) {
1648 DiffSetPressure[*PSetI] += PSetI.
getWeight();
1652 return DiffSetPressure;
1659 SISchedulerBlockSchedulerVariant ScheduleVariant) {
1662 std::vector<SIScheduleBlock*> ScheduledBlocks;
1665 ScheduledBlocks =
Scheduler.getBlocks();
1668 std::vector<SUnit*>
SUs =
Block->getScheduledUnits();
1692void SIScheduleDAGMI::topologicalSort() {
1705void SIScheduleDAGMI::moveLowLatencies() {
1706 unsigned DAGSize =
SUnits.size();
1707 int LastLowLatencyUser = -1;
1708 int LastLowLatencyPos = -1;
1710 for (
unsigned i = 0, e = ScheduledSUnits.size(); i != e; ++i) {
1712 bool IsLowLatencyUser =
false;
1713 unsigned MinPos = 0;
1718 IsLowLatencyUser =
true;
1722 unsigned PredPos = ScheduledSUnitsInv[Pred->
NodeNum];
1723 if (PredPos >= MinPos)
1724 MinPos = PredPos + 1;
1727 if (SITII->isLowLatencyInstruction(*SU->
getInstr())) {
1728 unsigned BestPos = LastLowLatencyUser + 1;
1729 if ((
int)BestPos <= LastLowLatencyPos)
1730 BestPos = LastLowLatencyPos + 1;
1731 if (BestPos < MinPos)
1734 for (
unsigned u = i;
u > BestPos; --
u) {
1735 ++ScheduledSUnitsInv[ScheduledSUnits[
u-1]];
1736 ScheduledSUnits[
u] = ScheduledSUnits[
u-1];
1738 ScheduledSUnits[BestPos] = SU->
NodeNum;
1739 ScheduledSUnitsInv[SU->
NodeNum] = BestPos;
1741 LastLowLatencyPos = BestPos;
1742 if (IsLowLatencyUser)
1743 LastLowLatencyUser = BestPos;
1744 }
else if (IsLowLatencyUser) {
1745 LastLowLatencyUser = i;
1749 bool CopyForLowLat =
false;
1750 for (SDep& SuccDep : SU->
Succs) {
1754 if (SITII->isLowLatencyInstruction(*Succ->
getInstr())) {
1755 CopyForLowLat =
true;
1761 for (
unsigned u = i;
u > MinPos; --
u) {
1762 ++ScheduledSUnitsInv[ScheduledSUnits[
u-1]];
1763 ScheduledSUnits[
u] = ScheduledSUnits[
u-1];
1765 ScheduledSUnits[MinPos] = SU->
NodeNum;
1766 ScheduledSUnitsInv[SU->
NodeNum] = MinPos;
1773 for (
unsigned i = 0, e =
SUnits.size(); i != e; ++i) {
1774 SUnits[i].isScheduled =
false;
1775 SUnits[i].WeakPredsLeft = SUnitsLinksBackup[i].WeakPredsLeft;
1776 SUnits[i].NumPredsLeft = SUnitsLinksBackup[i].NumPredsLeft;
1777 SUnits[i].WeakSuccsLeft = SUnitsLinksBackup[i].WeakSuccsLeft;
1778 SUnits[i].NumSuccsLeft = SUnitsLinksBackup[i].NumSuccsLeft;
1783template<
typename _Iterator>
void
1785 unsigned &VgprUsage,
unsigned &SgprUsage) {
1788 for (_Iterator RegI =
First; RegI != End; ++RegI) {
1791 if (!Reg.isVirtual())
1794 for (; PSetI.
isValid(); ++PSetI) {
1795 if (*PSetI == AMDGPU::RegisterPressureSets::VGPR_32)
1797 else if (*PSetI == AMDGPU::RegisterPressureSets::SReg_32)
1829 SUnitsLinksBackup =
SUnits;
1838 for (
unsigned i = 0, e = (
unsigned)
SUnits.size(); i != e; ++i) {
1842 if (SITII->isLowLatencyInstruction(*SU->
getInstr())) {
1844 bool OffsetIsScalable;
1845 if (SITII->getMemOperandWithOffset(*SU->
getInstr(), BaseLatOp, OffLatReg,
1871 for (std::pair<SISchedulerBlockCreatorVariant, SISchedulerBlockSchedulerVariant> v : Variants) {
1872 Temp =
Scheduler.scheduleVariant(v.first, v.second);
1892 for (std::pair<SISchedulerBlockCreatorVariant, SISchedulerBlockSchedulerVariant> v : Variants) {
1893 Temp =
Scheduler.scheduleVariant(v.first, v.second);
1899 ScheduledSUnits = Best.
SUs;
1900 ScheduledSUnitsInv.resize(
SUnits.size());
1902 for (
unsigned i = 0, e = (
unsigned)
SUnits.size(); i != e; ++i) {
1903 ScheduledSUnitsInv[ScheduledSUnits[i]] = i;
1913 for (
unsigned I : ScheduledSUnits) {
1926 dbgs() <<
"*** Final schedule for "
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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.
Promote Memory to Register
Interface definition for SIInstrInfo.
static const char * getReasonStr(SIScheduleCandReason Reason)
static bool hasDataDependencyPred(const SUnit &SU, const SUnit &FromSU)
static bool isDefBetween(Register Reg, SlotIndex First, SlotIndex Last, const MachineRegisterInfo *MRI, const LiveIntervals *LIS)
SI Machine Scheduler interface.
GenericScheduler shrinks the unscheduled zone using heuristics to balance the schedule.
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
MachineInstrBundleIterator< const MachineInstr > const_iterator
MachineInstrBundleIterator< MachineInstr > iterator
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
iterator_range< def_instr_iterator > def_instructions(Register Reg) const
Iterate over the pressure sets affected by the given physical or virtual register.
unsigned getWeight() const
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
@ Data
Regular data dependence (aka true-dependence).
bool isWeak() const
Tests if this a weak dependence.
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
static bool isEXP(const MachineInstr &MI)
bool isLowLatencyInstruction(const MachineInstr &MI) const
bool isSUInBlock(SUnit *SU, unsigned ID)
SIScheduleBlockCreator(SIScheduleDAGMI *DAG)
SIScheduleBlocks getBlocks(SISchedulerBlockCreatorVariant BlockVariant)
SIScheduleBlockScheduler(SIScheduleDAGMI *DAG, SISchedulerBlockSchedulerVariant Variant, SIScheduleBlocks BlocksStruct)
SIScheduleBlock(SIScheduleDAGMI *DAG, SIScheduleBlockCreator *BC, unsigned ID)
ArrayRef< std::pair< SIScheduleBlock *, SIScheduleBlockLinkKind > > getSuccs() const
void addPred(SIScheduleBlock *Pred)
void printDebug(bool Full)
void addSucc(SIScheduleBlock *Succ, SIScheduleBlockLinkKind Kind)
void schedule(MachineBasicBlock::iterator BeginBlock, MachineBasicBlock::iterator EndBlock)
void addUnit(SUnit *SU)
Functions for Block construction.
bool isHighLatencyBlock()
void restoreSULinksLeft()
std::vector< int > BottomUpIndex2SU
std::vector< unsigned > IsHighLatencySU
std::vector< unsigned > LowLatencyOffset
std::vector< int > TopDownIndex2SU
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
void fillVgprSgprCost(_Iterator First, _Iterator End, unsigned &VgprUsage, unsigned &SgprUsage)
SIScheduleDAGMI(MachineSchedContext *C)
std::vector< unsigned > IsLowLatencySU
~SIScheduleDAGMI() override
struct SIScheduleBlockResult scheduleVariant(SISchedulerBlockCreatorVariant BlockVariant, SISchedulerBlockSchedulerVariant ScheduleVariant)
SIScheduler(SIScheduleDAGMI *DAG)
Scheduling unit. This is a node in the scheduling DAG.
bool isInstr() const
Returns true if this SUnit refers to a machine instruction as opposed to an SDNode.
unsigned NodeNum
Entry # of node in the node vector.
bool isScheduled
True once scheduled.
SmallVector< SDep, 4 > Succs
All sunit successors.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
LLVM_ABI bool addPred(const SDep &D, bool Required=true)
Adds the specified edge as a pred of the current node if not already.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
ScheduleDAGTopologicalSort Topo
Topo - A topological ordering for SUnits which permits fast IsReachable and similar queries.
MachineBasicBlock::iterator begin() const
Returns an iterator to the top of the current scheduling region.
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
void scheduleMI(SUnit *SU, bool IsTopNode)
Move an instruction and update register pressure.
void initQueues(ArrayRef< SUnit * > TopRoots, ArrayRef< SUnit * > BotRoots)
Release ExitSU predecessors and setup scheduler queues.
void buildDAGWithRegPressure()
Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking enabled.
ScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S)
void dump() const override
RegPressureTracker TopRPTracker
void dumpSchedule() const
dump the scheduled Sequence.
std::unique_ptr< MachineSchedStrategy > SchedImpl
void postProcessDAG()
Apply each ScheduleDAGMutation step in order.
void findRootsAndBiasEdges(SmallVectorImpl< SUnit * > &TopRoots, SmallVectorImpl< SUnit * > &BotRoots)
MachineBasicBlock::iterator CurrentBottom
The bottom of the unscheduled zone.
void viewGraph() override
Out-of-line implementation with no arguments is handy for gdb.
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
MachineBasicBlock::iterator CurrentTop
The top of the unscheduled zone.
LLVM_ABI void InitDAGTopologicalSorting()
Creates the initial topological ordering from the DAG to be scheduled.
reverse_iterator rbegin()
MachineRegisterInfo & MRI
Virtual/real register map.
const TargetInstrInfo * TII
Target instruction information.
std::vector< SUnit > SUnits
The scheduling units.
const TargetRegisterInfo * TRI
Target processor register info.
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Wrapper class representing a virtual register or register unit.
constexpr bool isVirtualReg() const
constexpr Register asVirtualReg() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool tryGreater(int TryVal, int CandVal, SISchedulerCandidate &TryCand, SISchedulerCandidate &Cand, SIScheduleCandReason Reason)
static bool tryLess(int TryVal, int CandVal, SISchedulerCandidate &TryCand, SISchedulerCandidate &Cand, SIScheduleCandReason Reason)
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
SISchedulerBlockSchedulerVariant
cl::opt< bool > ViewMISchedDAGs
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
SISchedulerBlockCreatorVariant
@ LatenciesAlonePlusConsecutive
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
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.
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
std::vector< unsigned > MaxSetPressure
Map of max reg pressure indexed by pressure set ID, not class ID.
std::vector< unsigned > SUs
std::vector< int > TopDownIndex2Block
std::vector< SIScheduleBlock * > Blocks
std::vector< int > TopDownBlock2Index
SIScheduleCandReason Reason
void setRepeat(SIScheduleCandReason R)