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::colorMergeIfPossibleNextGroup() {
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)
1004 CurrentColoring[SU->
NodeNum] = *SUColors.begin();
1008void SIScheduleBlockCreator::colorMergeIfPossibleNextGroupOnlyForReserved() {
1009 unsigned DAGSize = DAG->SUnits.size();
1011 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
1012 SUnit *SU = &DAG->SUnits[SUNum];
1013 std::set<unsigned> SUColors;
1015 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
1018 for (SDep& SuccDep : SU->
Succs) {
1022 SUColors.insert(CurrentColoring[Succ->
NodeNum]);
1024 if (SUColors.size() == 1 && *SUColors.begin() <= DAGSize)
1025 CurrentColoring[SU->
NodeNum] = *SUColors.begin();
1029void SIScheduleBlockCreator::colorMergeIfPossibleSmallGroupsToNextGroup() {
1030 unsigned DAGSize = DAG->SUnits.size();
1031 std::map<unsigned, unsigned> ColorCount;
1033 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
1034 SUnit *SU = &DAG->SUnits[SUNum];
1035 unsigned color = CurrentColoring[SU->
NodeNum];
1036 ++ColorCount[color];
1039 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
1040 SUnit *SU = &DAG->SUnits[SUNum];
1041 unsigned color = CurrentColoring[SU->
NodeNum];
1042 std::set<unsigned> SUColors;
1044 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
1047 if (ColorCount[color] > 1)
1050 for (SDep& SuccDep : SU->
Succs) {
1054 SUColors.insert(CurrentColoring[Succ->
NodeNum]);
1056 if (SUColors.size() == 1 && *SUColors.begin() != color) {
1057 --ColorCount[color];
1058 CurrentColoring[SU->
NodeNum] = *SUColors.begin();
1059 ++ColorCount[*SUColors.begin()];
1064void SIScheduleBlockCreator::cutHugeBlocks() {
1068void SIScheduleBlockCreator::regroupNoUserInstructions() {
1069 unsigned DAGSize = DAG->SUnits.size();
1070 int GroupID = NextNonReservedID++;
1072 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
1073 SUnit *SU = &DAG->SUnits[SUNum];
1074 bool hasSuccessor =
false;
1076 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
1079 for (SDep& SuccDep : SU->
Succs) {
1083 hasSuccessor =
true;
1086 CurrentColoring[SU->
NodeNum] = GroupID;
1090void SIScheduleBlockCreator::colorExports() {
1091 unsigned ExportColor = NextNonReservedID++;
1092 SmallVector<unsigned, 8> ExpGroup;
1104 for (
unsigned SUNum : DAG->TopDownIndex2SU) {
1105 const SUnit &SU = DAG->SUnits[SUNum];
1109 for (
const SDep &SuccDep : SU.
Succs) {
1110 const SUnit *SuccSU = SuccDep.
getSUnit();
1111 if (SuccDep.
isWeak() || SuccSU->
NodeNum >= DAG->SUnits.size()) {
1116 "SUnit unexpectedly not representing an instruction!");
1132 for (
unsigned j : ExpGroup)
1133 CurrentColoring[
j] = ExportColor;
1137 unsigned DAGSize = DAG->SUnits.size();
1138 std::map<unsigned,unsigned> RealID;
1140 CurrentBlocks.clear();
1141 CurrentColoring.clear();
1142 CurrentColoring.resize(DAGSize, 0);
1143 Node2CurrentBlock.clear();
1146 DAG->restoreSULinksLeft();
1149 NextNonReservedID = DAGSize + 1;
1154 colorHighLatenciesGroups();
1156 colorHighLatenciesAlone();
1157 colorComputeReservedDependencies();
1158 colorAccordingToReservedDependencies();
1159 colorEndsAccordingToDependencies();
1161 colorForceConsecutiveOrderInGroup();
1162 regroupNoUserInstructions();
1163 colorMergeConstantLoadsNextGroup();
1164 colorMergeIfPossibleNextGroupOnlyForReserved();
1168 Node2CurrentBlock.resize(DAGSize, -1);
1169 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1170 SUnit *SU = &DAG->SUnits[i];
1171 unsigned Color = CurrentColoring[SU->
NodeNum];
1172 auto [It,
Inserted] = RealID.try_emplace(Color);
1174 int ID = CurrentBlocks.size();
1175 BlockPtrs.push_back(std::make_unique<SIScheduleBlock>(DAG,
this, ID));
1176 CurrentBlocks.push_back(BlockPtrs.rbegin()->get());
1179 CurrentBlocks[It->second]->addUnit(SU);
1180 Node2CurrentBlock[SU->
NodeNum] = It->second;
1184 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1185 SUnit *SU = &DAG->SUnits[i];
1186 int SUID = Node2CurrentBlock[i];
1187 for (SDep& SuccDep : SU->
Succs) {
1191 if (Node2CurrentBlock[Succ->
NodeNum] != SUID)
1192 CurrentBlocks[SUID]->addSucc(CurrentBlocks[Node2CurrentBlock[Succ->
NodeNum]],
1195 for (SDep& PredDep : SU->
Preds) {
1199 if (Node2CurrentBlock[Pred->
NodeNum] != SUID)
1200 CurrentBlocks[SUID]->
addPred(CurrentBlocks[Node2CurrentBlock[Pred->
NodeNum]]);
1205 for (SIScheduleBlock *
Block : CurrentBlocks)
1206 Block->finalizeUnits();
1208 dbgs() <<
"Blocks created:\n\n";
1209 for (SIScheduleBlock *
Block : CurrentBlocks)
1210 Block->printDebug(
true);
1220 for (;
I != End; ++
I) {
1221 if (!
I->isDebugInstr())
1227void SIScheduleBlockCreator::topologicalSort() {
1228 unsigned DAGSize = CurrentBlocks.size();
1229 std::vector<int> WorkList;
1233 WorkList.reserve(DAGSize);
1234 TopDownIndex2Block.resize(DAGSize);
1235 TopDownBlock2Index.resize(DAGSize);
1236 BottomUpIndex2Block.resize(DAGSize);
1238 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1239 SIScheduleBlock *
Block = CurrentBlocks[i];
1240 unsigned Degree =
Block->getSuccs().size();
1241 TopDownBlock2Index[i] = Degree;
1243 WorkList.push_back(i);
1248 while (!WorkList.empty()) {
1249 int i = WorkList.back();
1250 SIScheduleBlock *
Block = CurrentBlocks[i];
1251 WorkList.pop_back();
1252 TopDownBlock2Index[i] = --
Id;
1253 TopDownIndex2Block[
Id] = i;
1254 for (SIScheduleBlock* Pred :
Block->getPreds()) {
1255 if (!--TopDownBlock2Index[Pred->getID()])
1256 WorkList.push_back(Pred->getID());
1262 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1263 SIScheduleBlock *
Block = CurrentBlocks[i];
1264 for (SIScheduleBlock* Pred :
Block->getPreds()) {
1265 assert(TopDownBlock2Index[i] > TopDownBlock2Index[Pred->getID()] &&
1266 "Wrong Top Down topological sorting");
1271 BottomUpIndex2Block = std::vector<int>(TopDownIndex2Block.rbegin(),
1272 TopDownIndex2Block.rend());
1275void SIScheduleBlockCreator::scheduleInsideBlocks() {
1276 unsigned DAGSize = CurrentBlocks.size();
1282 LLVM_DEBUG(
dbgs() <<
"First phase: Fast scheduling for Reg Liveness\n");
1283 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1284 SIScheduleBlock *
Block = CurrentBlocks[i];
1285 Block->fastSchedule();
1293 std::vector<MachineBasicBlock::iterator> PosOld;
1294 std::vector<MachineBasicBlock::iterator> PosNew;
1295 PosOld.reserve(DAG->SUnits.size());
1296 PosNew.reserve(DAG->SUnits.size());
1298 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1299 int BlockIndice = TopDownIndex2Block[i];
1300 SIScheduleBlock *
Block = CurrentBlocks[BlockIndice];
1301 std::vector<SUnit*> SUs =
Block->getScheduledUnits();
1303 for (SUnit* SU : SUs) {
1306 PosOld.push_back(Pos);
1307 if (&*CurrentTopFastSched ==
MI) {
1308 PosNew.push_back(Pos);
1309 CurrentTopFastSched =
nextIfDebug(++CurrentTopFastSched,
1310 DAG->getCurrentBottom());
1313 DAG->getBB()->splice(CurrentTopFastSched, DAG->getBB(),
MI);
1320 DAG->getLIS()->handleMove(*
MI,
true);
1321 PosNew.push_back(CurrentTopFastSched);
1330 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1331 SIScheduleBlock *
Block = CurrentBlocks[i];
1332 std::vector<SUnit*> SUs =
Block->getScheduledUnits();
1333 Block->schedule((*SUs.begin())->getInstr(), (*SUs.rbegin())->getInstr());
1338 for (
unsigned i = PosOld.size(), e = 0; i != e; --i) {
1343 DAG->getBB()->splice(POld, DAG->getBB(), PNew);
1346 DAG->getLIS()->handleMove(*POld,
true);
1351 for (SIScheduleBlock *
Block : CurrentBlocks)
1352 Block->printDebug(
true);
1356void SIScheduleBlockCreator::fillStats() {
1357 unsigned DAGSize = CurrentBlocks.size();
1359 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1360 int BlockIndice = TopDownIndex2Block[i];
1361 SIScheduleBlock *
Block = CurrentBlocks[BlockIndice];
1362 if (
Block->getPreds().empty())
1366 for (SIScheduleBlock *Pred :
Block->getPreds()) {
1368 Depth = Pred->Depth + Pred->getCost();
1374 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1375 int BlockIndice = BottomUpIndex2Block[i];
1376 SIScheduleBlock *
Block = CurrentBlocks[BlockIndice];
1377 if (
Block->getSuccs().empty())
1380 unsigned Height = 0;
1381 for (
const auto &Succ :
Block->getSuccs())
1382 Height = std::max(Height, Succ.first->Height + Succ.first->getCost());
1383 Block->Height = Height;
1393 DAG(DAG), Variant(Variant), Blocks(BlocksStruct.Blocks),
1394 LastPosWaitedHighLatency(0), NumBlockScheduled(0), VregCurrentUsage(0),
1395 SregCurrentUsage(0), maxVregUsage(0), maxSregUsage(0) {
1407 LiveOutRegsNumUsages.resize(Blocks.size());
1413 std::set<Register> PredOutRegs = Pred->getOutRegs();
1414 std::set<Register>::iterator RegPos = PredOutRegs.find(Reg);
1416 if (RegPos != PredOutRegs.end()) {
1428 ++LiveOutRegsNumUsages[PredID][Reg];
1432 LastPosHighLatencyParentScheduled.resize(Blocks.size(), 0);
1433 BlockNumPredsLeft.resize(Blocks.size());
1434 BlockNumSuccsLeft.resize(Blocks.size());
1436 for (
unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1437 SIScheduleBlock *Block = Blocks[i];
1438 BlockNumPredsLeft[i] = Block->getPreds().size();
1439 BlockNumSuccsLeft[i] = Block->getSuccs().size();
1443 for (
unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1444 SIScheduleBlock *Block = Blocks[i];
1445 assert(Block->getID() == i);
1449 std::set<VirtRegOrUnit> InRegs = DAG->getInRegs();
1450 addLiveRegs(InRegs);
1456 for (unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1458 int ID = BlocksStruct.TopDownIndex2Block[Blocks.size()-1-i];
1459 SIScheduleBlock *Block = Blocks[ID];
1460 const std::set<Register> &OutRegs = Block->getOutRegs();
1462 if (!VRegOrUnit.isVirtualReg() ||
1463 OutRegs.find(VRegOrUnit.asVirtualReg()) == OutRegs.end())
1466 ++LiveOutRegsNumUsages[ID][VRegOrUnit.asVirtualReg()];
1477 std::set<Register> PredOutRegs = Pred->getOutRegs();
1478 std::set<Register>::iterator RegPos = PredOutRegs.find(Reg);
1480 if (RegPos != PredOutRegs.end()) {
1487 ++LiveRegsConsumers[
Reg];
1491 for (
unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1492 SIScheduleBlock *Block = Blocks[i];
1493 if (BlockNumPredsLeft[i] == 0) {
1494 ReadyBlocks.push_back(Block);
1499 BlocksScheduled.push_back(
Block);
1500 blockScheduled(
Block);
1504 : BlocksScheduled) {
1509bool SIScheduleBlockScheduler::tryCandidateLatency(SIBlockSchedCandidate &Cand,
1510 SIBlockSchedCandidate &TryCand) {
1511 if (!Cand.isValid()) {
1518 Cand.LastPosHighLatParentScheduled, TryCand, Cand,
Latency))
1525 TryCand, Cand,
Depth))
1528 Cand.NumHighLatencySuccessors,
1534bool SIScheduleBlockScheduler::tryCandidateRegUsage(SIBlockSchedCandidate &Cand,
1535 SIBlockSchedCandidate &TryCand) {
1536 if (!Cand.isValid()) {
1545 Cand.NumSuccessors > 0,
1557 SIBlockSchedCandidate Cand;
1558 std::vector<SIScheduleBlock*>::iterator Best;
1559 SIScheduleBlock *
Block;
1560 if (ReadyBlocks.empty())
1563 DAG->fillVgprSgprCost(LiveRegs.begin(), LiveRegs.end(),
1564 VregCurrentUsage, SregCurrentUsage);
1565 if (VregCurrentUsage > maxVregUsage)
1566 maxVregUsage = VregCurrentUsage;
1567 if (SregCurrentUsage > maxSregUsage)
1568 maxSregUsage = SregCurrentUsage;
1570 dbgs() <<
"Picking New Blocks\n";
1571 dbgs() <<
"Available: ";
1572 for (SIScheduleBlock *
Block : ReadyBlocks)
1574 dbgs() <<
"\nCurrent Live:\n";
1578 dbgs() <<
"Current VGPRs: " << VregCurrentUsage <<
'\n';
1579 dbgs() <<
"Current SGPRs: " << SregCurrentUsage <<
'\n';
1582 Cand.Block =
nullptr;
1583 for (std::vector<SIScheduleBlock*>::iterator
I = ReadyBlocks.begin(),
1584 E = ReadyBlocks.end();
I !=
E; ++
I) {
1585 SIBlockSchedCandidate TryCand;
1587 TryCand.IsHighLatency = TryCand.Block->isHighLatencyBlock();
1588 TryCand.VGPRUsageDiff =
1589 checkRegUsageImpact(TryCand.Block->getInRegs(),
1590 TryCand.Block->getOutRegs())[AMDGPU::RegisterPressureSets::VGPR_32];
1591 TryCand.NumSuccessors = TryCand.Block->getSuccs().size();
1592 TryCand.NumHighLatencySuccessors =
1593 TryCand.Block->getNumHighLatencySuccessors();
1594 TryCand.LastPosHighLatParentScheduled =
1595 (
unsigned int) std::max<int> (0,
1596 LastPosHighLatencyParentScheduled[TryCand.Block->getID()] -
1597 LastPosWaitedHighLatency);
1598 TryCand.Height = TryCand.Block->Height;
1600 if (VregCurrentUsage > 120 ||
1602 if (!tryCandidateRegUsage(Cand, TryCand) &&
1604 tryCandidateLatency(Cand, TryCand);
1606 if (!tryCandidateLatency(Cand, TryCand))
1607 tryCandidateRegUsage(Cand, TryCand);
1609 if (TryCand.Reason !=
NoCand) {
1610 Cand.setBest(TryCand);
1612 LLVM_DEBUG(
dbgs() <<
"Best Current Choice: " << Cand.Block->getID() <<
' '
1618 dbgs() <<
"Is a block with high latency instruction: "
1619 << (Cand.IsHighLatency ?
"yes\n" :
"no\n");
1620 dbgs() <<
"Position of last high latency dependency: "
1621 << Cand.LastPosHighLatParentScheduled <<
'\n';
1622 dbgs() <<
"VGPRUsageDiff: " << Cand.VGPRUsageDiff <<
'\n';
1626 ReadyBlocks.erase(Best);
1632void SIScheduleBlockScheduler::addLiveRegs(std::set<VirtRegOrUnit> &Regs) {
1633 for (VirtRegOrUnit VRegOrUnit : Regs) {
1643 std::set<Register> &Regs) {
1646 std::set<Register>::iterator Pos = LiveRegs.find(
Reg);
1647 assert (Pos != LiveRegs.end() &&
1648 LiveRegsConsumers.find(
Reg) != LiveRegsConsumers.end() &&
1649 LiveRegsConsumers[
Reg] >= 1);
1650 --LiveRegsConsumers[
Reg];
1651 if (LiveRegsConsumers[
Reg] == 0)
1652 LiveRegs.erase(Pos);
1656void SIScheduleBlockScheduler::releaseBlockSuccs(
SIScheduleBlock *Parent) {
1658 if (--BlockNumPredsLeft[
Block.first->getID()] == 0)
1659 ReadyBlocks.push_back(
Block.first);
1663 LastPosHighLatencyParentScheduled[
Block.first->getID()] = NumBlockScheduled;
1669 LiveRegs.insert(
Block->getOutRegs().begin(),
Block->getOutRegs().end());
1670 releaseBlockSuccs(
Block);
1671 for (
const auto &RegP : LiveOutRegsNumUsages[
Block->getID()]) {
1673 assert(LiveRegsConsumers.find(RegP.first) == LiveRegsConsumers.end() ||
1674 LiveRegsConsumers[RegP.first] == 0);
1675 LiveRegsConsumers[RegP.first] += RegP.second;
1677 if (LastPosHighLatencyParentScheduled[
Block->getID()] >
1678 (
unsigned)LastPosWaitedHighLatency)
1679 LastPosWaitedHighLatency =
1680 LastPosHighLatencyParentScheduled[
Block->getID()];
1681 ++NumBlockScheduled;
1685SIScheduleBlockScheduler::checkRegUsageImpact(std::set<Register> &InRegs,
1686 std::set<Register> &OutRegs) {
1687 std::vector<int> DiffSetPressure;
1688 DiffSetPressure.assign(DAG->getTRI()->getNumRegPressureSets(), 0);
1694 if (LiveRegsConsumers[
Reg] > 1)
1696 PSetIterator PSetI = DAG->getMRI()->getPressureSets(VirtRegOrUnit(
Reg));
1697 for (; PSetI.
isValid(); ++PSetI) {
1698 DiffSetPressure[*PSetI] -= PSetI.
getWeight();
1706 PSetIterator PSetI = DAG->getMRI()->getPressureSets(VirtRegOrUnit(
Reg));
1707 for (; PSetI.
isValid(); ++PSetI) {
1708 DiffSetPressure[*PSetI] += PSetI.
getWeight();
1712 return DiffSetPressure;
1719 SISchedulerBlockSchedulerVariant ScheduleVariant) {
1722 std::vector<SIScheduleBlock*> ScheduledBlocks;
1725 ScheduledBlocks =
Scheduler.getBlocks();
1728 std::vector<SUnit*>
SUs =
Block->getScheduledUnits();
1752void SIScheduleDAGMI::topologicalSort() {
1765void SIScheduleDAGMI::moveLowLatencies() {
1766 unsigned DAGSize =
SUnits.size();
1767 int LastLowLatencyUser = -1;
1768 int LastLowLatencyPos = -1;
1770 for (
unsigned i = 0, e = ScheduledSUnits.size(); i != e; ++i) {
1772 bool IsLowLatencyUser =
false;
1773 unsigned MinPos = 0;
1778 IsLowLatencyUser =
true;
1782 unsigned PredPos = ScheduledSUnitsInv[Pred->
NodeNum];
1783 if (PredPos >= MinPos)
1784 MinPos = PredPos + 1;
1787 if (SITII->isLowLatencyInstruction(*SU->
getInstr())) {
1788 unsigned BestPos = LastLowLatencyUser + 1;
1789 if ((
int)BestPos <= LastLowLatencyPos)
1790 BestPos = LastLowLatencyPos + 1;
1791 if (BestPos < MinPos)
1794 for (
unsigned u = i;
u > BestPos; --
u) {
1795 ++ScheduledSUnitsInv[ScheduledSUnits[
u-1]];
1796 ScheduledSUnits[
u] = ScheduledSUnits[
u-1];
1798 ScheduledSUnits[BestPos] = SU->
NodeNum;
1799 ScheduledSUnitsInv[SU->
NodeNum] = BestPos;
1801 LastLowLatencyPos = BestPos;
1802 if (IsLowLatencyUser)
1803 LastLowLatencyUser = BestPos;
1804 }
else if (IsLowLatencyUser) {
1805 LastLowLatencyUser = i;
1809 bool CopyForLowLat =
false;
1810 for (SDep& SuccDep : SU->
Succs) {
1814 if (SITII->isLowLatencyInstruction(*Succ->
getInstr())) {
1815 CopyForLowLat =
true;
1821 for (
unsigned u = i;
u > MinPos; --
u) {
1822 ++ScheduledSUnitsInv[ScheduledSUnits[
u-1]];
1823 ScheduledSUnits[
u] = ScheduledSUnits[
u-1];
1825 ScheduledSUnits[MinPos] = SU->
NodeNum;
1826 ScheduledSUnitsInv[SU->
NodeNum] = MinPos;
1833 for (
unsigned i = 0, e =
SUnits.size(); i != e; ++i) {
1834 SUnits[i].isScheduled =
false;
1835 SUnits[i].WeakPredsLeft = SUnitsLinksBackup[i].WeakPredsLeft;
1836 SUnits[i].NumPredsLeft = SUnitsLinksBackup[i].NumPredsLeft;
1837 SUnits[i].WeakSuccsLeft = SUnitsLinksBackup[i].WeakSuccsLeft;
1838 SUnits[i].NumSuccsLeft = SUnitsLinksBackup[i].NumSuccsLeft;
1843template<
typename _Iterator>
void
1845 unsigned &VgprUsage,
unsigned &SgprUsage) {
1848 for (_Iterator RegI =
First; RegI != End; ++RegI) {
1851 if (!Reg.isVirtual())
1854 for (; PSetI.
isValid(); ++PSetI) {
1855 if (*PSetI == AMDGPU::RegisterPressureSets::VGPR_32)
1857 else if (*PSetI == AMDGPU::RegisterPressureSets::SReg_32)
1889 SUnitsLinksBackup =
SUnits;
1898 for (
unsigned i = 0, e = (
unsigned)
SUnits.size(); i != e; ++i) {
1902 if (SITII->isLowLatencyInstruction(*SU->
getInstr())) {
1904 bool OffsetIsScalable;
1905 if (SITII->getMemOperandWithOffset(*SU->
getInstr(), BaseLatOp, OffLatReg,
1906 OffsetIsScalable,
TRI))
1931 for (std::pair<SISchedulerBlockCreatorVariant, SISchedulerBlockSchedulerVariant> v : Variants) {
1932 Temp =
Scheduler.scheduleVariant(v.first, v.second);
1952 for (std::pair<SISchedulerBlockCreatorVariant, SISchedulerBlockSchedulerVariant> v : Variants) {
1953 Temp =
Scheduler.scheduleVariant(v.first, v.second);
1959 ScheduledSUnits = Best.
SUs;
1960 ScheduledSUnitsInv.resize(
SUnits.size());
1962 for (
unsigned i = 0, e = (
unsigned)
SUnits.size(); i != e; ++i) {
1963 ScheduledSUnitsInv[ScheduledSUnits[i]] = i;
1973 for (
unsigned I : ScheduledSUnits) {
1987 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)