22#define DEBUG_TYPE "machine-scheduler"
126 case NoCand:
return "NOCAND";
128 case Latency:
return "LATENCY";
130 case Depth:
return "DEPTH";
143 if (TryVal < CandVal) {
147 if (TryVal > CandVal) {
160 if (TryVal > CandVal) {
164 if (TryVal < CandVal) {
177 NodeNum2Index[SU->
NodeNum] = SUnits.size();
178 SUnits.push_back(SU);
182void SIScheduleBlock::traceCandidate(
const SISchedCandidate &Cand) {
189void SIScheduleBlock::tryCandidateTopDown(SISchedCandidate &Cand,
190 SISchedCandidate &TryCand) {
192 if (!Cand.isValid()) {
197 if (Cand.SGPRUsage > 60 &&
218 Cand.HasLowLatencyNonWaitedParent,
226 if (TryCand.IsLowLatency &&
236 if (TryCand.SU->NodeNum < Cand.SU->NodeNum) {
241SUnit* SIScheduleBlock::pickNode() {
242 SISchedCandidate TopCand;
244 for (SUnit* SU : TopReadySUs) {
245 SISchedCandidate TryCand;
246 std::vector<unsigned> pressure;
247 std::vector<unsigned> MaxPressure;
250 TopRPTracker.getDownwardPressure(SU->getInstr(), pressure, MaxPressure);
251 TryCand.SGPRUsage = pressure[AMDGPU::RegisterPressureSets::SReg_32];
252 TryCand.VGPRUsage = pressure[AMDGPU::RegisterPressureSets::VGPR_32];
253 TryCand.IsLowLatency = DAG->IsLowLatencySU[SU->NodeNum];
254 TryCand.LowLatencyOffset = DAG->LowLatencyOffset[SU->NodeNum];
255 TryCand.HasLowLatencyNonWaitedParent =
256 HasLowLatencyNonWaitedParent[NodeNum2Index[SU->NodeNum]];
257 tryCandidateTopDown(TopCand, TryCand);
258 if (TryCand.Reason !=
NoCand)
259 TopCand.setBest(TryCand);
272 for (
SUnit* SU : SUnits) {
273 if (!SU->NumPredsLeft)
274 TopReadySUs.push_back(SU);
277 while (!TopReadySUs.empty()) {
278 SUnit *SU = TopReadySUs[0];
279 ScheduledSUnits.push_back(SU);
291 if (
MI.isDebugValue())
294 if (InstSlot >=
First && InstSlot <=
Last)
302 IntervalPressure Pressure, BotPressure;
303 RegPressureTracker RPTracker(Pressure), BotRPTracker(BotPressure);
304 LiveIntervals *LIS = DAG->getLIS();
305 MachineRegisterInfo *
MRI = DAG->getMRI();
306 DAG->initRPTracker(TopRPTracker);
307 DAG->initRPTracker(BotRPTracker);
308 DAG->initRPTracker(RPTracker);
312 for (SUnit* SU : ScheduledSUnits) {
313 RPTracker.setPos(SU->getInstr());
318 RPTracker.closeRegion();
321 TopRPTracker.addLiveRegs(RPTracker.getPressure().LiveInRegs);
322 BotRPTracker.addLiveRegs(RPTracker.getPressure().LiveOutRegs);
325 for (
const auto &RegMaskPair : RPTracker.getPressure().LiveInRegs) {
326 if (RegMaskPair.VRegOrUnit.isVirtualReg())
327 LiveInRegs.insert(RegMaskPair.VRegOrUnit.asVirtualReg());
352 for (
const auto &RegMaskPair : RPTracker.getPressure().LiveOutRegs) {
353 VirtRegOrUnit VRegOrUnit = RegMaskPair.VRegOrUnit;
367 LiveInPressure = TopPressure.MaxSetPressure;
371 TopRPTracker.closeTop();
380 initRegPressure(BeginBlock, EndBlock);
387 for (
SUnit* SU : SUnits) {
388 if (!SU->NumPredsLeft)
389 TopReadySUs.push_back(SU);
392 while (!TopReadySUs.empty()) {
393 SUnit *SU = pickNode();
394 ScheduledSUnits.push_back(SU);
395 TopRPTracker.setPos(SU->
getInstr());
396 TopRPTracker.advance();
401 InternalAdditionalPressure.resize(TopPressure.MaxSetPressure.size());
405 assert(SUnits.size() == ScheduledSUnits.size() &&
406 TopReadySUs.empty());
407 for (
SUnit* SU : SUnits) {
409 SU->NumPredsLeft == 0);
416void SIScheduleBlock::undoSchedule() {
417 for (
SUnit* SU : SUnits) {
418 SU->isScheduled =
false;
419 for (
SDep& Succ : SU->Succs) {
421 undoReleaseSucc(SU, &Succ);
424 HasLowLatencyNonWaitedParent.assign(SUnits.size(), 0);
425 ScheduledSUnits.clear();
429void SIScheduleBlock::undoReleaseSucc(
SUnit *SU,
SDep *SuccEdge) {
430 SUnit *SuccSU = SuccEdge->
getSUnit();
439void SIScheduleBlock::releaseSucc(
SUnit *SU,
SDep *SuccEdge) {
440 SUnit *SuccSU = SuccEdge->
getSUnit();
448 dbgs() <<
"*** Scheduling failed! ***\n";
449 DAG->dumpNode(*SuccSU);
450 dbgs() <<
" has been released too many times!\n";
459void SIScheduleBlock::releaseSuccessors(
SUnit *SU,
bool InOrOutBlock) {
460 for (SDep& Succ : SU->
Succs) {
463 if (SuccSU->
NodeNum >= DAG->SUnits.size())
466 if (BC->isSUInBlock(SuccSU, ID) != InOrOutBlock)
469 releaseSucc(SU, &Succ);
471 TopReadySUs.push_back(SuccSU);
475void SIScheduleBlock::nodeScheduled(
SUnit *SU) {
478 std::vector<SUnit *>::iterator
I =
llvm::find(TopReadySUs, SU);
479 if (
I == TopReadySUs.end()) {
480 dbgs() <<
"Data Structure Bug in SI Scheduler\n";
483 TopReadySUs.erase(
I);
485 releaseSuccessors(SU,
true);
488 if (HasLowLatencyNonWaitedParent[NodeNum2Index[SU->
NodeNum]])
489 HasLowLatencyNonWaitedParent.assign(SUnits.size(), 0);
491 if (DAG->IsLowLatencySU[SU->
NodeNum]) {
492 for (SDep& Succ : SU->
Succs) {
493 std::map<unsigned, unsigned>::iterator
I =
495 if (
I != NodeNum2Index.end())
496 HasLowLatencyNonWaitedParent[
I->second] = 1;
504 for (
SUnit* SU : SUnits) {
505 releaseSuccessors(SU,
false);
506 if (DAG->IsHighLatencySU[SU->
NodeNum])
507 HighLatencyBlock =
true;
509 HasLowLatencyNonWaitedParent.resize(SUnits.size(), 0);
514 unsigned PredID = Pred->getID();
518 if (PredID ==
P->getID())
521 Preds.push_back(Pred);
526 return PredID == S.first->getID();
528 "Loop in the Block Graph!");
533 unsigned SuccID = Succ->
getID();
536 for (std::pair<SIScheduleBlock*, SIScheduleBlockLinkKind> &S : Succs) {
537 if (SuccID == S.first->getID()) {
539 Kind == SIScheduleBlockLinkKind::Data)
545 ++NumHighLatencySuccessors;
546 Succs.emplace_back(Succ, Kind);
550 "Loop in the Block Graph!");
555 dbgs() <<
"Block (" << ID <<
")\n";
559 dbgs() <<
"\nContains High Latency Instruction: "
560 << HighLatencyBlock <<
'\n';
561 dbgs() <<
"\nDepends On:\n";
563 P->printDebug(
false);
566 dbgs() <<
"\nSuccessors:\n";
567 for (std::pair<SIScheduleBlock*, SIScheduleBlockLinkKind> S : Succs) {
568 if (S.second == SIScheduleBlockLinkKind::Data)
569 dbgs() <<
"(Data Dep) ";
570 S.first->printDebug(
false);
574 dbgs() <<
"LiveInPressure "
575 << LiveInPressure[AMDGPU::RegisterPressureSets::SReg_32] <<
' '
576 << LiveInPressure[AMDGPU::RegisterPressureSets::VGPR_32] <<
'\n';
577 dbgs() <<
"LiveOutPressure "
578 << LiveOutPressure[AMDGPU::RegisterPressureSets::SReg_32] <<
' '
579 << LiveOutPressure[AMDGPU::RegisterPressureSets::VGPR_32] <<
"\n\n";
580 dbgs() <<
"LiveIns:\n";
584 dbgs() <<
"\nLiveOuts:\n";
589 dbgs() <<
"\nInstructions:\n";
590 for (
const SUnit* SU : SUnits)
593 dbgs() <<
"///////////////////////\n";
604 std::map<SISchedulerBlockCreatorVariant, SIScheduleBlocks>::iterator
B =
605 Blocks.find(BlockVariant);
606 if (
B == Blocks.end()) {
608 createBlocksForVariant(BlockVariant);
610 scheduleInsideBlocks();
612 Res.
Blocks = CurrentBlocks;
615 Blocks[BlockVariant] = Res;
622 if (SU->
NodeNum >= DAG->SUnits.size())
624 return CurrentBlocks[Node2CurrentBlock[SU->
NodeNum]]->getID() ==
ID;
627void SIScheduleBlockCreator::colorHighLatenciesAlone() {
628 unsigned DAGSize = DAG->
SUnits.size();
630 for (
unsigned i = 0, e = DAGSize; i != e; ++i) {
633 CurrentColoring[SU->
NodeNum] = NextReservedID++;
640 for (
const auto &PredDep : SU.
Preds) {
641 if (PredDep.getSUnit() == &FromSU &&
648void SIScheduleBlockCreator::colorHighLatenciesGroups() {
649 unsigned DAGSize = DAG->SUnits.size();
650 unsigned NumHighLatencies = 0;
652 int Color = NextReservedID;
654 std::set<unsigned> FormingGroup;
656 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
657 SUnit *SU = &DAG->SUnits[i];
658 if (DAG->IsHighLatencySU[SU->
NodeNum])
662 if (NumHighLatencies == 0)
665 if (NumHighLatencies <= 6)
667 else if (NumHighLatencies <= 12)
672 for (
unsigned SUNum : DAG->TopDownIndex2SU) {
673 const SUnit &SU = DAG->SUnits[SUNum];
674 if (DAG->IsHighLatencySU[SU.
NodeNum]) {
675 unsigned CompatibleGroup =
true;
676 int ProposedColor = Color;
677 std::vector<int> AdditionalElements;
689 for (
unsigned j : FormingGroup) {
691 std::vector<int> SubGraph;
696 SubGraph = DAG->GetTopo()->GetSubGraph(SU, DAG->SUnits[j],
700 SubGraph = DAG->GetTopo()->GetSubGraph(DAG->SUnits[j], SU,
704 if (SubGraph.size() > 5) {
706 CompatibleGroup =
false;
710 for (
unsigned k : SubGraph) {
715 if (DAG->IsHighLatencySU[k] || (CurrentColoring[k] != ProposedColor &&
716 CurrentColoring[k] != 0)) {
717 CompatibleGroup =
false;
723 CompatibleGroup =
false;
727 if (!CompatibleGroup)
731 CompatibleGroup =
false;
741 if (CompatibleGroup) {
742 FormingGroup.insert(SU.
NodeNum);
743 for (
unsigned j : AdditionalElements)
744 CurrentColoring[
j] = ProposedColor;
745 CurrentColoring[SU.
NodeNum] = ProposedColor;
751 if (!CompatibleGroup) {
752 FormingGroup.clear();
753 Color = ++NextReservedID;
754 ProposedColor = Color;
755 FormingGroup.insert(SU.
NodeNum);
756 CurrentColoring[SU.
NodeNum] = ProposedColor;
758 }
else if (
Count == GroupSize) {
759 FormingGroup.clear();
760 Color = ++NextReservedID;
761 ProposedColor = Color;
768void SIScheduleBlockCreator::colorComputeReservedDependencies() {
769 unsigned DAGSize = DAG->SUnits.size();
770 std::map<std::set<unsigned>,
unsigned> ColorCombinations;
772 CurrentTopDownReservedDependencyColoring.clear();
773 CurrentBottomUpReservedDependencyColoring.clear();
775 CurrentTopDownReservedDependencyColoring.resize(DAGSize, 0);
776 CurrentBottomUpReservedDependencyColoring.resize(DAGSize, 0);
781 for (
unsigned SUNum : DAG->TopDownIndex2SU) {
782 SUnit *SU = &DAG->SUnits[SUNum];
783 std::set<unsigned> SUColors;
786 if (CurrentColoring[SU->
NodeNum]) {
787 CurrentTopDownReservedDependencyColoring[SU->
NodeNum] =
792 for (SDep& PredDep : SU->
Preds) {
796 if (CurrentTopDownReservedDependencyColoring[Pred->
NodeNum] > 0)
797 SUColors.insert(CurrentTopDownReservedDependencyColoring[Pred->
NodeNum]);
800 if (SUColors.empty())
803 if (SUColors.size() == 1 && *SUColors.begin() > DAGSize)
804 CurrentTopDownReservedDependencyColoring[SU->
NodeNum] =
808 ColorCombinations.try_emplace(SUColors, NextNonReservedID);
811 CurrentTopDownReservedDependencyColoring[SU->
NodeNum] = Pos->second;
815 ColorCombinations.clear();
819 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
820 SUnit *SU = &DAG->SUnits[SUNum];
821 std::set<unsigned> SUColors;
824 if (CurrentColoring[SU->
NodeNum]) {
825 CurrentBottomUpReservedDependencyColoring[SU->
NodeNum] =
830 for (SDep& SuccDep : SU->
Succs) {
834 if (CurrentBottomUpReservedDependencyColoring[Succ->
NodeNum] > 0)
835 SUColors.insert(CurrentBottomUpReservedDependencyColoring[Succ->
NodeNum]);
838 if (SUColors.empty())
841 if (SUColors.size() == 1 && *SUColors.begin() > DAGSize)
842 CurrentBottomUpReservedDependencyColoring[SU->
NodeNum] =
845 std::map<std::set<unsigned>,
unsigned>::iterator Pos =
846 ColorCombinations.find(SUColors);
847 if (Pos != ColorCombinations.end()) {
848 CurrentBottomUpReservedDependencyColoring[SU->
NodeNum] = Pos->second;
850 CurrentBottomUpReservedDependencyColoring[SU->
NodeNum] =
852 ColorCombinations[SUColors] = NextNonReservedID++;
858void SIScheduleBlockCreator::colorAccordingToReservedDependencies() {
859 std::map<std::pair<unsigned, unsigned>,
unsigned> ColorCombinations;
864 for (
const SUnit &SU : DAG->SUnits) {
865 std::pair<unsigned, unsigned> SUColors;
868 if (CurrentColoring[SU.
NodeNum])
871 SUColors.first = CurrentTopDownReservedDependencyColoring[SU.
NodeNum];
872 SUColors.second = CurrentBottomUpReservedDependencyColoring[SU.
NodeNum];
875 ColorCombinations.try_emplace(SUColors, NextNonReservedID);
876 CurrentColoring[SU.
NodeNum] = Pos->second;
882void SIScheduleBlockCreator::colorEndsAccordingToDependencies() {
883 unsigned DAGSize = DAG->SUnits.size();
884 std::vector<int> PendingColoring = CurrentColoring;
887 CurrentBottomUpReservedDependencyColoring.size() == DAGSize &&
888 CurrentTopDownReservedDependencyColoring.size() == DAGSize);
895 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
896 SUnit *SU = &DAG->SUnits[SUNum];
897 std::set<unsigned> SUColors;
898 std::set<unsigned> SUColorsPending;
900 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
903 if (CurrentBottomUpReservedDependencyColoring[SU->
NodeNum] > 0 ||
904 CurrentTopDownReservedDependencyColoring[SU->
NodeNum] > 0)
907 for (SDep& SuccDep : SU->
Succs) {
911 if (CurrentBottomUpReservedDependencyColoring[Succ->
NodeNum] > 0 ||
912 CurrentTopDownReservedDependencyColoring[Succ->
NodeNum] > 0)
913 SUColors.insert(CurrentColoring[Succ->
NodeNum]);
914 SUColorsPending.insert(PendingColoring[Succ->
NodeNum]);
919 if (SUColors.size() == 1 && SUColorsPending.size() == 1)
920 PendingColoring[SU->
NodeNum] = *SUColors.begin();
923 PendingColoring[SU->
NodeNum] = NextNonReservedID++;
925 CurrentColoring = PendingColoring;
929void SIScheduleBlockCreator::colorForceConsecutiveOrderInGroup() {
930 unsigned DAGSize = DAG->SUnits.size();
931 unsigned PreviousColor;
932 std::set<unsigned> SeenColors;
937 PreviousColor = CurrentColoring[0];
939 for (
unsigned i = 1, e = DAGSize; i !=
e; ++i) {
940 SUnit *SU = &DAG->SUnits[i];
941 unsigned CurrentColor = CurrentColoring[i];
942 unsigned PreviousColorSave = PreviousColor;
945 if (CurrentColor != PreviousColor)
946 SeenColors.insert(PreviousColor);
947 PreviousColor = CurrentColor;
949 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
952 if (SeenColors.find(CurrentColor) == SeenColors.end())
955 if (PreviousColorSave != CurrentColor)
956 CurrentColoring[i] = NextNonReservedID++;
958 CurrentColoring[i] = CurrentColoring[i-1];
962void SIScheduleBlockCreator::colorMergeConstantLoadsNextGroup() {
963 unsigned DAGSize = DAG->SUnits.size();
965 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
966 SUnit *SU = &DAG->SUnits[SUNum];
967 std::set<unsigned> SUColors;
969 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
974 if (SU->
Preds.size() > 0 && !DAG->IsLowLatencySU[SU->
NodeNum])
977 for (SDep& SuccDep : SU->
Succs) {
981 SUColors.insert(CurrentColoring[Succ->
NodeNum]);
983 if (SUColors.size() == 1)
984 CurrentColoring[SU->
NodeNum] = *SUColors.begin();
988void SIScheduleBlockCreator::colorMergeIfPossibleNextGroup() {
989 unsigned DAGSize = DAG->SUnits.size();
991 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
992 SUnit *SU = &DAG->SUnits[SUNum];
993 std::set<unsigned> SUColors;
995 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
998 for (SDep& SuccDep : SU->
Succs) {
1002 SUColors.insert(CurrentColoring[Succ->
NodeNum]);
1004 if (SUColors.size() == 1)
1005 CurrentColoring[SU->
NodeNum] = *SUColors.begin();
1009void SIScheduleBlockCreator::colorMergeIfPossibleNextGroupOnlyForReserved() {
1010 unsigned DAGSize = DAG->SUnits.size();
1012 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
1013 SUnit *SU = &DAG->SUnits[SUNum];
1014 std::set<unsigned> SUColors;
1016 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
1019 for (SDep& SuccDep : SU->
Succs) {
1023 SUColors.insert(CurrentColoring[Succ->
NodeNum]);
1025 if (SUColors.size() == 1 && *SUColors.begin() <= DAGSize)
1026 CurrentColoring[SU->
NodeNum] = *SUColors.begin();
1030void SIScheduleBlockCreator::colorMergeIfPossibleSmallGroupsToNextGroup() {
1031 unsigned DAGSize = DAG->SUnits.size();
1032 std::map<unsigned, unsigned> ColorCount;
1034 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
1035 SUnit *SU = &DAG->SUnits[SUNum];
1036 unsigned color = CurrentColoring[SU->
NodeNum];
1037 ++ColorCount[color];
1040 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
1041 SUnit *SU = &DAG->SUnits[SUNum];
1042 unsigned color = CurrentColoring[SU->
NodeNum];
1043 std::set<unsigned> SUColors;
1045 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
1048 if (ColorCount[color] > 1)
1051 for (SDep& SuccDep : SU->
Succs) {
1055 SUColors.insert(CurrentColoring[Succ->
NodeNum]);
1057 if (SUColors.size() == 1 && *SUColors.begin() != color) {
1058 --ColorCount[color];
1059 CurrentColoring[SU->
NodeNum] = *SUColors.begin();
1060 ++ColorCount[*SUColors.begin()];
1065void SIScheduleBlockCreator::cutHugeBlocks() {
1069void SIScheduleBlockCreator::regroupNoUserInstructions() {
1070 unsigned DAGSize = DAG->SUnits.size();
1071 int GroupID = NextNonReservedID++;
1073 for (
unsigned SUNum : DAG->BottomUpIndex2SU) {
1074 SUnit *SU = &DAG->SUnits[SUNum];
1075 bool hasSuccessor =
false;
1077 if (CurrentColoring[SU->
NodeNum] <= (
int)DAGSize)
1080 for (SDep& SuccDep : SU->
Succs) {
1084 hasSuccessor =
true;
1087 CurrentColoring[SU->
NodeNum] = GroupID;
1091void SIScheduleBlockCreator::colorExports() {
1092 unsigned ExportColor = NextNonReservedID++;
1093 SmallVector<unsigned, 8> ExpGroup;
1105 for (
unsigned SUNum : DAG->TopDownIndex2SU) {
1106 const SUnit &SU = DAG->SUnits[SUNum];
1110 for (
const SDep &SuccDep : SU.
Succs) {
1111 const SUnit *SuccSU = SuccDep.
getSUnit();
1112 if (SuccDep.
isWeak() || SuccSU->
NodeNum >= DAG->SUnits.size()) {
1117 "SUnit unexpectedly not representing an instruction!");
1133 for (
unsigned j : ExpGroup)
1134 CurrentColoring[
j] = ExportColor;
1138 unsigned DAGSize = DAG->SUnits.size();
1139 std::map<unsigned,unsigned> RealID;
1141 CurrentBlocks.clear();
1142 CurrentColoring.clear();
1143 CurrentColoring.resize(DAGSize, 0);
1144 Node2CurrentBlock.clear();
1147 DAG->restoreSULinksLeft();
1150 NextNonReservedID = DAGSize + 1;
1155 colorHighLatenciesGroups();
1157 colorHighLatenciesAlone();
1158 colorComputeReservedDependencies();
1159 colorAccordingToReservedDependencies();
1160 colorEndsAccordingToDependencies();
1162 colorForceConsecutiveOrderInGroup();
1163 regroupNoUserInstructions();
1164 colorMergeConstantLoadsNextGroup();
1165 colorMergeIfPossibleNextGroupOnlyForReserved();
1169 Node2CurrentBlock.resize(DAGSize, -1);
1170 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1171 SUnit *SU = &DAG->SUnits[i];
1172 unsigned Color = CurrentColoring[SU->
NodeNum];
1173 auto [It,
Inserted] = RealID.try_emplace(Color);
1175 int ID = CurrentBlocks.size();
1176 BlockPtrs.push_back(std::make_unique<SIScheduleBlock>(DAG,
this,
ID));
1177 CurrentBlocks.push_back(BlockPtrs.rbegin()->get());
1180 CurrentBlocks[It->second]->addUnit(SU);
1181 Node2CurrentBlock[SU->
NodeNum] = It->second;
1185 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1186 SUnit *SU = &DAG->SUnits[i];
1187 int SUID = Node2CurrentBlock[i];
1188 for (SDep& SuccDep : SU->
Succs) {
1192 if (Node2CurrentBlock[Succ->
NodeNum] != SUID)
1193 CurrentBlocks[SUID]->addSucc(CurrentBlocks[Node2CurrentBlock[Succ->
NodeNum]],
1196 for (SDep& PredDep : SU->
Preds) {
1200 if (Node2CurrentBlock[Pred->
NodeNum] != SUID)
1201 CurrentBlocks[SUID]->
addPred(CurrentBlocks[Node2CurrentBlock[Pred->
NodeNum]]);
1206 for (SIScheduleBlock *
Block : CurrentBlocks)
1207 Block->finalizeUnits();
1209 dbgs() <<
"Blocks created:\n\n";
1210 for (SIScheduleBlock *
Block : CurrentBlocks)
1211 Block->printDebug(
true);
1221 for (;
I != End; ++
I) {
1222 if (!
I->isDebugInstr())
1228void SIScheduleBlockCreator::topologicalSort() {
1229 unsigned DAGSize = CurrentBlocks.size();
1230 std::vector<int> WorkList;
1234 WorkList.reserve(DAGSize);
1235 TopDownIndex2Block.resize(DAGSize);
1236 TopDownBlock2Index.resize(DAGSize);
1237 BottomUpIndex2Block.resize(DAGSize);
1239 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1240 SIScheduleBlock *
Block = CurrentBlocks[i];
1241 unsigned Degree =
Block->getSuccs().size();
1242 TopDownBlock2Index[i] = Degree;
1244 WorkList.push_back(i);
1249 while (!WorkList.empty()) {
1250 int i = WorkList.back();
1251 SIScheduleBlock *
Block = CurrentBlocks[i];
1252 WorkList.pop_back();
1253 TopDownBlock2Index[i] = --
Id;
1254 TopDownIndex2Block[
Id] = i;
1255 for (SIScheduleBlock* Pred :
Block->getPreds()) {
1256 if (!--TopDownBlock2Index[Pred->getID()])
1257 WorkList.push_back(Pred->getID());
1263 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1264 SIScheduleBlock *
Block = CurrentBlocks[i];
1265 for (SIScheduleBlock* Pred :
Block->getPreds()) {
1266 assert(TopDownBlock2Index[i] > TopDownBlock2Index[Pred->getID()] &&
1267 "Wrong Top Down topological sorting");
1272 BottomUpIndex2Block = std::vector<int>(TopDownIndex2Block.rbegin(),
1273 TopDownIndex2Block.rend());
1276void SIScheduleBlockCreator::scheduleInsideBlocks() {
1277 unsigned DAGSize = CurrentBlocks.size();
1283 LLVM_DEBUG(
dbgs() <<
"First phase: Fast scheduling for Reg Liveness\n");
1284 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1285 SIScheduleBlock *
Block = CurrentBlocks[i];
1286 Block->fastSchedule();
1294 std::vector<MachineBasicBlock::iterator> PosOld;
1295 std::vector<MachineBasicBlock::iterator> PosNew;
1296 PosOld.reserve(DAG->SUnits.size());
1297 PosNew.reserve(DAG->SUnits.size());
1299 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1300 int BlockIndice = TopDownIndex2Block[i];
1301 SIScheduleBlock *
Block = CurrentBlocks[BlockIndice];
1302 std::vector<SUnit*> SUs =
Block->getScheduledUnits();
1304 for (SUnit* SU : SUs) {
1307 PosOld.push_back(Pos);
1308 if (&*CurrentTopFastSched ==
MI) {
1309 PosNew.push_back(Pos);
1310 CurrentTopFastSched =
nextIfDebug(++CurrentTopFastSched,
1311 DAG->getCurrentBottom());
1314 DAG->getBB()->splice(CurrentTopFastSched, DAG->getBB(),
MI);
1321 DAG->getLIS()->handleMove(*
MI,
true);
1322 PosNew.push_back(CurrentTopFastSched);
1331 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1332 SIScheduleBlock *
Block = CurrentBlocks[i];
1333 std::vector<SUnit*> SUs =
Block->getScheduledUnits();
1334 Block->schedule((*SUs.begin())->getInstr(), (*SUs.rbegin())->getInstr());
1339 for (
unsigned i = PosOld.size(), e = 0; i != e; --i) {
1344 DAG->getBB()->splice(POld, DAG->getBB(), PNew);
1347 DAG->getLIS()->handleMove(*POld,
true);
1352 for (SIScheduleBlock *
Block : CurrentBlocks)
1353 Block->printDebug(
true);
1357void SIScheduleBlockCreator::fillStats() {
1358 unsigned DAGSize = CurrentBlocks.size();
1360 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1361 int BlockIndice = TopDownIndex2Block[i];
1362 SIScheduleBlock *
Block = CurrentBlocks[BlockIndice];
1363 if (
Block->getPreds().empty())
1367 for (SIScheduleBlock *Pred :
Block->getPreds()) {
1369 Depth = Pred->Depth + Pred->getCost();
1375 for (
unsigned i = 0, e = DAGSize; i !=
e; ++i) {
1376 int BlockIndice = BottomUpIndex2Block[i];
1377 SIScheduleBlock *
Block = CurrentBlocks[BlockIndice];
1378 if (
Block->getSuccs().empty())
1381 unsigned Height = 0;
1382 for (
const auto &Succ :
Block->getSuccs())
1383 Height = std::max(Height, Succ.first->Height + Succ.first->getCost());
1384 Block->Height = Height;
1394 DAG(DAG), Variant(Variant), Blocks(BlocksStruct.Blocks),
1395 LastPosWaitedHighLatency(0), NumBlockScheduled(0), VregCurrentUsage(0),
1396 SregCurrentUsage(0), maxVregUsage(0), maxSregUsage(0) {
1408 LiveOutRegsNumUsages.resize(Blocks.size());
1414 std::set<Register> PredOutRegs = Pred->getOutRegs();
1415 std::set<Register>::iterator RegPos = PredOutRegs.find(Reg);
1417 if (RegPos != PredOutRegs.end()) {
1429 ++LiveOutRegsNumUsages[PredID][Reg];
1433 LastPosHighLatencyParentScheduled.resize(Blocks.size(), 0);
1434 BlockNumPredsLeft.resize(Blocks.size());
1435 BlockNumSuccsLeft.resize(Blocks.size());
1437 for (
unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1438 SIScheduleBlock *Block = Blocks[i];
1439 BlockNumPredsLeft[i] = Block->getPreds().size();
1440 BlockNumSuccsLeft[i] = Block->getSuccs().size();
1444 for (
unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1445 SIScheduleBlock *Block = Blocks[i];
1446 assert(Block->getID() == i);
1450 std::set<VirtRegOrUnit> InRegs = DAG->getInRegs();
1451 addLiveRegs(InRegs);
1457 for (unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1459 int ID = BlocksStruct.TopDownIndex2Block[Blocks.size()-1-i];
1460 SIScheduleBlock *Block = Blocks[ID];
1461 const std::set<Register> &OutRegs = Block->getOutRegs();
1463 if (!VRegOrUnit.isVirtualReg() ||
1464 OutRegs.find(VRegOrUnit.asVirtualReg()) == OutRegs.end())
1467 ++LiveOutRegsNumUsages[ID][VRegOrUnit.asVirtualReg()];
1478 std::set<Register> PredOutRegs = Pred->getOutRegs();
1479 std::set<Register>::iterator RegPos = PredOutRegs.find(Reg);
1481 if (RegPos != PredOutRegs.end()) {
1488 ++LiveRegsConsumers[
Reg];
1492 for (
unsigned i = 0, e = Blocks.size(); i != e; ++i) {
1493 SIScheduleBlock *Block = Blocks[i];
1494 if (BlockNumPredsLeft[i] == 0) {
1495 ReadyBlocks.push_back(Block);
1500 BlocksScheduled.push_back(
Block);
1501 blockScheduled(
Block);
1505 : BlocksScheduled) {
1510bool SIScheduleBlockScheduler::tryCandidateLatency(SIBlockSchedCandidate &Cand,
1511 SIBlockSchedCandidate &TryCand) {
1512 if (!Cand.isValid()) {
1519 Cand.LastPosHighLatParentScheduled, TryCand, Cand,
Latency))
1526 TryCand, Cand,
Depth))
1529 Cand.NumHighLatencySuccessors,
1535bool SIScheduleBlockScheduler::tryCandidateRegUsage(SIBlockSchedCandidate &Cand,
1536 SIBlockSchedCandidate &TryCand) {
1537 if (!Cand.isValid()) {
1546 Cand.NumSuccessors > 0,
1558 SIBlockSchedCandidate Cand;
1559 std::vector<SIScheduleBlock*>::iterator Best;
1560 SIScheduleBlock *
Block;
1561 if (ReadyBlocks.empty())
1564 DAG->fillVgprSgprCost(LiveRegs.begin(), LiveRegs.end(),
1565 VregCurrentUsage, SregCurrentUsage);
1566 if (VregCurrentUsage > maxVregUsage)
1567 maxVregUsage = VregCurrentUsage;
1568 if (SregCurrentUsage > maxSregUsage)
1569 maxSregUsage = SregCurrentUsage;
1571 dbgs() <<
"Picking New Blocks\n";
1572 dbgs() <<
"Available: ";
1573 for (SIScheduleBlock *
Block : ReadyBlocks)
1575 dbgs() <<
"\nCurrent Live:\n";
1579 dbgs() <<
"Current VGPRs: " << VregCurrentUsage <<
'\n';
1580 dbgs() <<
"Current SGPRs: " << SregCurrentUsage <<
'\n';
1583 Cand.Block =
nullptr;
1584 for (std::vector<SIScheduleBlock*>::iterator
I = ReadyBlocks.begin(),
1585 E = ReadyBlocks.end();
I !=
E; ++
I) {
1586 SIBlockSchedCandidate TryCand;
1588 TryCand.IsHighLatency = TryCand.Block->isHighLatencyBlock();
1589 TryCand.VGPRUsageDiff =
1590 checkRegUsageImpact(TryCand.Block->getInRegs(),
1591 TryCand.Block->getOutRegs())[AMDGPU::RegisterPressureSets::VGPR_32];
1592 TryCand.NumSuccessors = TryCand.Block->getSuccs().size();
1593 TryCand.NumHighLatencySuccessors =
1594 TryCand.Block->getNumHighLatencySuccessors();
1595 TryCand.LastPosHighLatParentScheduled =
1596 (
unsigned int) std::max<int> (0,
1597 LastPosHighLatencyParentScheduled[TryCand.Block->getID()] -
1598 LastPosWaitedHighLatency);
1599 TryCand.Height = TryCand.Block->Height;
1601 if (VregCurrentUsage > 120 ||
1603 if (!tryCandidateRegUsage(Cand, TryCand) &&
1605 tryCandidateLatency(Cand, TryCand);
1607 if (!tryCandidateLatency(Cand, TryCand))
1608 tryCandidateRegUsage(Cand, TryCand);
1610 if (TryCand.Reason !=
NoCand) {
1611 Cand.setBest(TryCand);
1613 LLVM_DEBUG(
dbgs() <<
"Best Current Choice: " << Cand.Block->getID() <<
' '
1619 dbgs() <<
"Is a block with high latency instruction: "
1620 << (Cand.IsHighLatency ?
"yes\n" :
"no\n");
1621 dbgs() <<
"Position of last high latency dependency: "
1622 << Cand.LastPosHighLatParentScheduled <<
'\n';
1623 dbgs() <<
"VGPRUsageDiff: " << Cand.VGPRUsageDiff <<
'\n';
1627 ReadyBlocks.erase(Best);
1633void SIScheduleBlockScheduler::addLiveRegs(std::set<VirtRegOrUnit> &Regs) {
1634 for (VirtRegOrUnit VRegOrUnit : Regs) {
1644 std::set<Register> &Regs) {
1647 std::set<Register>::iterator Pos = LiveRegs.find(
Reg);
1648 assert (Pos != LiveRegs.end() &&
1649 LiveRegsConsumers.find(
Reg) != LiveRegsConsumers.end() &&
1650 LiveRegsConsumers[
Reg] >= 1);
1651 --LiveRegsConsumers[
Reg];
1652 if (LiveRegsConsumers[
Reg] == 0)
1653 LiveRegs.erase(Pos);
1657void SIScheduleBlockScheduler::releaseBlockSuccs(
SIScheduleBlock *Parent) {
1659 if (--BlockNumPredsLeft[
Block.first->getID()] == 0)
1660 ReadyBlocks.push_back(
Block.first);
1663 Block.second == SIScheduleBlockLinkKind::Data)
1664 LastPosHighLatencyParentScheduled[
Block.first->getID()] = NumBlockScheduled;
1670 LiveRegs.insert(
Block->getOutRegs().begin(),
Block->getOutRegs().end());
1671 releaseBlockSuccs(
Block);
1672 for (
const auto &RegP : LiveOutRegsNumUsages[
Block->getID()]) {
1674 assert(LiveRegsConsumers.find(RegP.first) == LiveRegsConsumers.end() ||
1675 LiveRegsConsumers[RegP.first] == 0);
1676 LiveRegsConsumers[RegP.first] += RegP.second;
1678 if (LastPosHighLatencyParentScheduled[
Block->getID()] >
1679 (
unsigned)LastPosWaitedHighLatency)
1680 LastPosWaitedHighLatency =
1681 LastPosHighLatencyParentScheduled[
Block->getID()];
1682 ++NumBlockScheduled;
1686SIScheduleBlockScheduler::checkRegUsageImpact(std::set<Register> &InRegs,
1687 std::set<Register> &OutRegs) {
1688 std::vector<int> DiffSetPressure;
1689 DiffSetPressure.assign(DAG->getTRI()->getNumRegPressureSets(), 0);
1695 if (LiveRegsConsumers[
Reg] > 1)
1697 PSetIterator PSetI = DAG->getMRI()->getPressureSets(VirtRegOrUnit(
Reg));
1698 for (; PSetI.
isValid(); ++PSetI) {
1699 DiffSetPressure[*PSetI] -= PSetI.
getWeight();
1707 PSetIterator PSetI = DAG->getMRI()->getPressureSets(VirtRegOrUnit(
Reg));
1708 for (; PSetI.
isValid(); ++PSetI) {
1709 DiffSetPressure[*PSetI] += PSetI.
getWeight();
1713 return DiffSetPressure;
1720 SISchedulerBlockSchedulerVariant ScheduleVariant) {
1723 std::vector<SIScheduleBlock*> ScheduledBlocks;
1726 ScheduledBlocks =
Scheduler.getBlocks();
1729 std::vector<SUnit*>
SUs =
Block->getScheduledUnits();
1753void SIScheduleDAGMI::topologicalSort() {
1766void SIScheduleDAGMI::moveLowLatencies() {
1767 unsigned DAGSize =
SUnits.size();
1768 int LastLowLatencyUser = -1;
1769 int LastLowLatencyPos = -1;
1771 for (
unsigned i = 0, e = ScheduledSUnits.size(); i != e; ++i) {
1773 bool IsLowLatencyUser =
false;
1774 unsigned MinPos = 0;
1779 IsLowLatencyUser =
true;
1783 unsigned PredPos = ScheduledSUnitsInv[Pred->
NodeNum];
1784 if (PredPos >= MinPos)
1785 MinPos = PredPos + 1;
1788 if (SITII->isLowLatencyInstruction(*SU->
getInstr())) {
1789 unsigned BestPos = LastLowLatencyUser + 1;
1790 if ((
int)BestPos <= LastLowLatencyPos)
1791 BestPos = LastLowLatencyPos + 1;
1792 if (BestPos < MinPos)
1795 for (
unsigned u = i;
u > BestPos; --
u) {
1796 ++ScheduledSUnitsInv[ScheduledSUnits[
u-1]];
1797 ScheduledSUnits[
u] = ScheduledSUnits[
u-1];
1799 ScheduledSUnits[BestPos] = SU->
NodeNum;
1800 ScheduledSUnitsInv[SU->
NodeNum] = BestPos;
1802 LastLowLatencyPos = BestPos;
1803 if (IsLowLatencyUser)
1804 LastLowLatencyUser = BestPos;
1805 }
else if (IsLowLatencyUser) {
1806 LastLowLatencyUser = i;
1810 bool CopyForLowLat =
false;
1811 for (SDep& SuccDep : SU->
Succs) {
1815 if (SITII->isLowLatencyInstruction(*Succ->
getInstr())) {
1816 CopyForLowLat =
true;
1822 for (
unsigned u = i;
u > MinPos; --
u) {
1823 ++ScheduledSUnitsInv[ScheduledSUnits[
u-1]];
1824 ScheduledSUnits[
u] = ScheduledSUnits[
u-1];
1826 ScheduledSUnits[MinPos] = SU->
NodeNum;
1827 ScheduledSUnitsInv[SU->
NodeNum] = MinPos;
1834 for (
unsigned i = 0, e =
SUnits.size(); i != e; ++i) {
1835 SUnits[i].isScheduled =
false;
1836 SUnits[i].WeakPredsLeft = SUnitsLinksBackup[i].WeakPredsLeft;
1837 SUnits[i].NumPredsLeft = SUnitsLinksBackup[i].NumPredsLeft;
1838 SUnits[i].WeakSuccsLeft = SUnitsLinksBackup[i].WeakSuccsLeft;
1839 SUnits[i].NumSuccsLeft = SUnitsLinksBackup[i].NumSuccsLeft;
1844template<
typename _Iterator>
void
1846 unsigned &VgprUsage,
unsigned &SgprUsage) {
1849 for (_Iterator RegI =
First; RegI != End; ++RegI) {
1852 if (!Reg.isVirtual())
1855 for (; PSetI.
isValid(); ++PSetI) {
1856 if (*PSetI == AMDGPU::RegisterPressureSets::VGPR_32)
1858 else if (*PSetI == AMDGPU::RegisterPressureSets::SReg_32)
1890 SUnitsLinksBackup =
SUnits;
1899 for (
unsigned i = 0, e = (
unsigned)
SUnits.size(); i != e; ++i) {
1903 if (SITII->isLowLatencyInstruction(*SU->
getInstr())) {
1905 bool OffsetIsScalable;
1906 if (SITII->getMemOperandWithOffset(*SU->
getInstr(), BaseLatOp, OffLatReg,
1907 OffsetIsScalable,
TRI))
1932 for (std::pair<SISchedulerBlockCreatorVariant, SISchedulerBlockSchedulerVariant> v : Variants) {
1933 Temp =
Scheduler.scheduleVariant(v.first, v.second);
1953 for (std::pair<SISchedulerBlockCreatorVariant, SISchedulerBlockSchedulerVariant> v : Variants) {
1954 Temp =
Scheduler.scheduleVariant(v.first, v.second);
1960 ScheduledSUnits = Best.
SUs;
1961 ScheduledSUnitsInv.resize(
SUnits.size());
1963 for (
unsigned i = 0, e = (
unsigned)
SUnits.size(); i != e; ++i) {
1964 ScheduledSUnitsInv[ScheduledSUnits[i]] = i;
1974 for (
unsigned I : ScheduledSUnits) {
1988 dbgs() <<
"*** Final schedule for "
unsigned const MachineRegisterInfo * MRI
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Provides AMDGPU specific target descriptions.
static const Function * getParent(const Value *V)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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,...
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
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.
FunctionAddr VTableAddr Count
SISchedulerBlockCreatorVariant
@ LatenciesAlonePlusConsecutive
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
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)