39#include "llvm/Config/llvm-config.h"
62#define DEBUG_TYPE "pre-RA-sched"
64STATISTIC(NumBacktracks,
"Number of times scheduler backtracked");
67STATISTIC(NumPRCopies,
"Number of physical register copies");
71 "Bottom-up register reduction list scheduling",
76 "Similar to list-burr but schedules in source "
77 "order when possible",
82 "Bottom-up register pressure aware list scheduling "
83 "which tries to balance latency and register pressure",
88 "Bottom-up register pressure aware list scheduling "
89 "which tries to balance ILP and register pressure",
94 cl::desc(
"Disable cycle-level precision during preRA scheduling"));
100 cl::desc(
"Disable regpressure priority in sched=list-ilp"));
103 cl::desc(
"Disable live use priority in sched=list-ilp"));
106 cl::desc(
"Disable virtual register cycle interference checks"));
109 cl::desc(
"Disable physreg def-use affinity"));
112 cl::desc(
"Disable no-stall priority in sched=list-ilp"));
115 cl::desc(
"Disable critical path priority in sched=list-ilp"));
118 cl::desc(
"Disable scheduled-height priority in sched=list-ilp"));
121 cl::desc(
"Disable scheduler's two-address hack"));
125 cl::desc(
"Number of instructions to allow ahead of the critical path "
126 "in sched=list-ilp"));
130 cl::desc(
"Average inst/cycle when no target itinerary exists."));
150 std::vector<SUnit *> PendingQueue;
156 unsigned CurCycle = 0;
159 unsigned MinAvailableCycle = ~0u;
163 unsigned IssueCount = 0u;
168 unsigned NumLiveRegs = 0u;
169 std::unique_ptr<SUnit*[]> LiveRegDefs;
170 std::unique_ptr<SUnit*[]> LiveRegGens;
193 AvailableQueue(availqueue), Topo(SUnits, nullptr) {
198 HazardRec = STI.
getInstrInfo()->CreateTargetHazardRecognizer(&STI,
this);
201 ~ScheduleDAGRRList()
override {
203 delete AvailableQueue;
206 void Schedule()
override;
208 ScheduleHazardRecognizer *getHazardRec() {
return HazardRec; }
211 bool IsReachable(
const SUnit *SU,
const SUnit *TargetSU) {
212 return Topo.IsReachable(SU, TargetSU);
217 bool WillCreateCycle(SUnit *SU, SUnit *TargetSU) {
218 return Topo.WillCreateCycle(SU, TargetSU);
224 void AddPredQueued(SUnit *SU,
const SDep &
D) {
225 Topo.AddPredQueued(SU,
D.getSUnit());
232 void AddPred(SUnit *SU,
const SDep &
D) {
233 Topo.AddPred(SU,
D.getSUnit());
240 void RemovePred(SUnit *SU,
const SDep &
D) {
241 Topo.RemovePred(SU,
D.getSUnit());
246 bool isReady(SUnit *SU) {
248 AvailableQueue->isReady(SU);
251 void ReleasePred(SUnit *SU,
const SDep *PredEdge);
252 void ReleasePredecessors(SUnit *SU);
253 void ReleasePending();
254 void AdvanceToCycle(
unsigned NextCycle);
255 void AdvancePastStalls(SUnit *SU);
256 void EmitNode(SUnit *SU);
257 void ScheduleNodeBottomUp(SUnit*);
258 void CapturePred(SDep *PredEdge);
259 void UnscheduleNodeBottomUp(SUnit*);
260 void RestoreHazardCheckerBottomUp();
261 void BacktrackBottomUp(SUnit*, SUnit*);
262 SUnit *TryUnfoldSU(SUnit *);
263 SUnit *CopyAndMoveSuccessors(SUnit*);
264 void InsertCopiesAndMoveSuccs(SUnit*,
unsigned,
265 const TargetRegisterClass*,
266 const TargetRegisterClass*,
267 SmallVectorImpl<SUnit*>&);
268 bool DelayForLiveRegsBottomUp(SUnit*, SmallVectorImpl<unsigned>&);
270 void releaseInterferences(
unsigned Reg = 0);
272 SUnit *PickNodeToScheduleBottomUp();
273 void ListScheduleBottomUp();
276 SUnit *CreateNewSUnit(SDNode *
N) {
277 unsigned NumSUnits = SUnits.size();
278 SUnit *NewNode = newSUnit(
N);
280 if (NewNode->
NodeNum >= NumSUnits)
281 Topo.AddSUnitWithoutPredecessors(NewNode);
286 SUnit *CreateClone(SUnit *
N) {
287 unsigned NumSUnits = SUnits.size();
288 SUnit *NewNode = Clone(
N);
290 if (NewNode->
NodeNum >= NumSUnits)
291 Topo.AddSUnitWithoutPredecessors(NewNode);
297 bool forceUnitLatencies()
const override {
314 unsigned &RegClass,
unsigned &Cost,
320 if (VT == MVT::Untyped) {
327 RegClass = RC->
getID();
332 unsigned Opcode =
Node->getMachineOpcode();
333 if (Opcode == TargetOpcode::REG_SEQUENCE) {
334 unsigned DstRCIdx =
Node->getConstantOperandVal(0);
336 RegClass = RC->
getID();
341 unsigned Idx = RegDefPos.
GetIdx();
344 assert(RC &&
"Not a valid register class");
345 RegClass = RC->
getID();
356void ScheduleDAGRRList::Schedule() {
358 <<
" '" << BB->getName() <<
"' **********\n");
367 LiveRegDefs.reset(
new SUnit*[
TRI->getNumRegs() + 1]());
368 LiveRegGens.reset(
new SUnit*[
TRI->getNumRegs() + 1]());
369 CallSeqEndForStart.
clear();
370 assert(Interferences.
empty() && LRegsMap.empty() &&
"stale Interferences");
383 ListScheduleBottomUp();
388 dbgs() <<
"*** Final schedule ***\n";
400void ScheduleDAGRRList::ReleasePred(SUnit *SU,
const SDep *PredEdge) {
401 SUnit *PredSU = PredEdge->
getSUnit();
405 dbgs() <<
"*** Scheduling failed! ***\n";
407 dbgs() <<
" has been released too many times!\n";
413 if (!forceUnitLatencies()) {
425 if (Height < MinAvailableCycle)
426 MinAvailableCycle = Height;
428 if (isReady(PredSU)) {
429 AvailableQueue->
push(PredSU);
435 PendingQueue.push_back(PredSU);
459 if (
N->isMachineOpcode()) {
460 if (
N->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
462 }
else if (
N->getMachineOpcode() ==
TII->getCallFrameSetupOpcode()) {
470 if (
Op.getValueType() == MVT::Other) {
472 goto found_chain_operand;
475 found_chain_operand:;
499 unsigned BestMaxNest = MaxNest;
501 unsigned MyNestLevel = NestLevel;
502 unsigned MyMaxNest = MaxNest;
504 MyNestLevel, MyMaxNest,
TII))
505 if (!Best || (MyMaxNest > BestMaxNest)) {
507 BestMaxNest = MyMaxNest;
511 MaxNest = BestMaxNest;
515 if (
N->isMachineOpcode()) {
516 if (
N->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
518 MaxNest = std::max(MaxNest, NestLevel);
519 }
else if (
N->getMachineOpcode() ==
TII->getCallFrameSetupOpcode()) {
528 if (
Op.getValueType() == MVT::Other) {
530 goto found_chain_operand;
533 found_chain_operand:;
556void ScheduleDAGRRList::ReleasePredecessors(SUnit *SU) {
558 for (SDep &Pred : SU->
Preds) {
559 ReleasePred(SU, &Pred);
565 SUnit *RegDef = LiveRegDefs[Pred.
getReg()]; (void)RegDef;
567 "interference on register dependence");
569 if (!LiveRegGens[Pred.
getReg()]) {
571 LiveRegGens[Pred.
getReg()] = SU;
579 unsigned CallResource =
TRI->getNumRegs();
580 if (!LiveRegDefs[CallResource])
581 for (SDNode *Node = SU->
getNode(); Node; Node =
Node->getGluedNode())
582 if (
Node->isMachineOpcode() &&
583 Node->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
584 unsigned NestLevel = 0;
585 unsigned MaxNest = 0;
587 assert(
N &&
"Must find call sequence start");
589 SUnit *
Def = &SUnits[
N->getNodeId()];
590 CallSeqEndForStart[
Def] = SU;
593 LiveRegDefs[CallResource] =
Def;
594 LiveRegGens[CallResource] = SU;
601void ScheduleDAGRRList::ReleasePending() {
603 assert(PendingQueue.empty() &&
"pending instrs not allowed in this mode");
608 if (AvailableQueue->
empty())
609 MinAvailableCycle = std::numeric_limits<unsigned>::max();
613 for (
unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
614 unsigned ReadyCycle = PendingQueue[i]->getHeight();
615 if (ReadyCycle < MinAvailableCycle)
616 MinAvailableCycle = ReadyCycle;
618 if (PendingQueue[i]->isAvailable) {
619 if (!isReady(PendingQueue[i]))
621 AvailableQueue->
push(PendingQueue[i]);
623 PendingQueue[i]->isPending =
false;
624 PendingQueue[i] = PendingQueue.back();
625 PendingQueue.pop_back();
631void ScheduleDAGRRList::AdvanceToCycle(
unsigned NextCycle) {
632 if (NextCycle <= CurCycle)
639 CurCycle = NextCycle;
642 for (; CurCycle != NextCycle; ++CurCycle) {
653void ScheduleDAGRRList::AdvancePastStalls(SUnit *SU) {
670 AdvanceToCycle(ReadyCycle);
690 AdvanceToCycle(CurCycle + Stalls);
695void ScheduleDAGRRList::EmitNode(SUnit *SU) {
706 "This target-independent node should not be scheduled.");
739void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) {
744 if (CurCycle < SU->getHeight())
746 <<
"] pipeline stall!\n");
766 AdvanceToCycle(CurCycle + 1);
770 ReleasePredecessors(SU);
773 for (SDep &Succ : SU->
Succs) {
776 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
778 LiveRegDefs[Succ.
getReg()] =
nullptr;
779 LiveRegGens[Succ.
getReg()] =
nullptr;
780 releaseInterferences(Succ.
getReg());
785 unsigned CallResource =
TRI->getNumRegs();
786 if (LiveRegDefs[CallResource] == SU)
787 for (
const SDNode *SUNode = SU->
getNode(); SUNode;
789 if (SUNode->isMachineOpcode() &&
790 SUNode->getMachineOpcode() ==
TII->getCallFrameSetupOpcode()) {
791 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
793 LiveRegDefs[CallResource] =
nullptr;
794 LiveRegGens[CallResource] =
nullptr;
795 releaseInterferences(CallResource);
816 AdvanceToCycle(CurCycle + 1);
823void ScheduleDAGRRList::CapturePred(SDep *PredEdge) {
824 SUnit *PredSU = PredEdge->
getSUnit();
828 AvailableQueue->
remove(PredSU);
832 "NumSuccsLeft will overflow!");
838void ScheduleDAGRRList::UnscheduleNodeBottomUp(SUnit *SU) {
842 for (SDep &Pred : SU->
Preds) {
845 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
847 "Physical register dependency violated?");
849 LiveRegDefs[Pred.
getReg()] =
nullptr;
850 LiveRegGens[Pred.
getReg()] =
nullptr;
851 releaseInterferences(Pred.
getReg());
857 unsigned CallResource =
TRI->getNumRegs();
858 for (
const SDNode *SUNode = SU->
getNode(); SUNode;
860 if (SUNode->isMachineOpcode() &&
861 SUNode->getMachineOpcode() ==
TII->getCallFrameSetupOpcode()) {
862 SUnit *SeqEnd = CallSeqEndForStart[SU];
863 assert(SeqEnd &&
"Call sequence start/end must be known");
864 assert(!LiveRegDefs[CallResource]);
865 assert(!LiveRegGens[CallResource]);
867 LiveRegDefs[CallResource] = SU;
868 LiveRegGens[CallResource] = SeqEnd;
874 if (LiveRegGens[CallResource] == SU)
875 for (
const SDNode *SUNode = SU->
getNode(); SUNode;
877 if (SUNode->isMachineOpcode() &&
878 SUNode->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
879 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
880 assert(LiveRegDefs[CallResource]);
881 assert(LiveRegGens[CallResource]);
883 LiveRegDefs[CallResource] =
nullptr;
884 LiveRegGens[CallResource] =
nullptr;
885 releaseInterferences(CallResource);
889 for (
auto &Succ : SU->
Succs) {
892 if (!LiveRegDefs[
Reg])
896 LiveRegDefs[
Reg] = SU;
900 if (!LiveRegGens[
Reg]) {
903 for (
auto &Succ2 : SU->
Succs) {
904 if (Succ2.isAssignedRegDep() && Succ2.getReg() ==
Reg &&
905 Succ2.getSUnit()->getHeight() < LiveRegGens[
Reg]->getHeight())
906 LiveRegGens[
Reg] = Succ2.getSUnit();
920 PendingQueue.push_back(SU);
923 AvailableQueue->
push(SU);
930void ScheduleDAGRRList::RestoreHazardCheckerBottomUp() {
933 unsigned LookAhead = std::min((
unsigned)
Sequence.size(),
938 std::vector<SUnit *>::const_iterator
I = (
Sequence.end() - LookAhead);
939 unsigned HazardCycle = (*I)->getHeight();
942 for (; SU->
getHeight() > HazardCycle; ++HazardCycle) {
951void ScheduleDAGRRList::BacktrackBottomUp(SUnit *SU, SUnit *BtSU) {
957 UnscheduleNodeBottomUp(OldSU);
966 RestoreHazardCheckerBottomUp();
976 if (SUNode->isOperandOf(
N))
983SUnit *ScheduleDAGRRList::TryUnfoldSU(SUnit *SU) {
987 if (!
TII->unfoldMemoryOperand(*DAG,
N, NewNodes))
990 assert(NewNodes.
size() == 2 &&
"Expected a load folding node!");
993 SDNode *LoadNode = NewNodes[0];
994 unsigned NumVals =
N->getNumValues();
1000 bool isNewLoad =
true;
1003 LoadSU = &SUnits[LoadNode->
getNodeId()];
1010 LoadSU = CreateNewSUnit(LoadNode);
1013 InitNumRegDefsLeft(LoadSU);
1014 computeLatency(LoadSU);
1020 if (
N->getNodeId() != -1) {
1021 NewSU = &SUnits[
N->getNodeId()];
1029 NewSU = CreateNewSUnit(
N);
1032 const MCInstrDesc &MCID =
TII->get(
N->getMachineOpcode());
1042 InitNumRegDefsLeft(NewSU);
1043 computeLatency(NewSU);
1049 for (
unsigned i = 0; i != NumVals; ++i)
1051 DAG->ReplaceAllUsesOfValueWith(
SDValue(SU->
getNode(), OldNumVals - 1),
1060 for (SDep &Pred : SU->
Preds) {
1068 for (SDep &Succ : SU->
Succs) {
1076 for (
const SDep &Pred : ChainPreds) {
1077 RemovePred(SU, Pred);
1079 AddPredQueued(LoadSU, Pred);
1081 for (
const SDep &Pred : LoadPreds) {
1082 RemovePred(SU, Pred);
1084 AddPredQueued(LoadSU, Pred);
1086 for (
const SDep &Pred : NodePreds) {
1087 RemovePred(SU, Pred);
1088 AddPredQueued(NewSU, Pred);
1090 for (SDep &
D : NodeSuccs) {
1091 SUnit *SuccDep =
D.getSUnit();
1093 RemovePred(SuccDep,
D);
1095 AddPredQueued(SuccDep,
D);
1101 for (SDep &
D : ChainSuccs) {
1102 SUnit *SuccDep =
D.getSUnit();
1104 RemovePred(SuccDep,
D);
1107 AddPredQueued(SuccDep,
D);
1115 AddPredQueued(NewSU,
D);
1118 AvailableQueue->
addNode(LoadSU);
1120 AvailableQueue->
addNode(NewSU);
1132SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
1140 if (
N->getGluedNode() &&
1141 !
TII->canCopyGluedNodeDuringSchedule(
N)) {
1144 <<
"Giving up because it has incoming glue and the target does not "
1145 "want to copy it\n");
1150 bool TryUnfold =
false;
1151 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
1152 MVT VT =
N->getSimpleValueType(i);
1153 if (VT == MVT::Glue) {
1154 LLVM_DEBUG(
dbgs() <<
"Giving up because it has outgoing glue\n");
1156 }
else if (VT == MVT::Other)
1160 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
1161 if (VT == MVT::Glue && !
TII->canCopyGluedNodeDuringSchedule(
N)) {
1163 dbgs() <<
"Giving up because it one of the operands is glue and "
1164 "the target does not want to copy it\n");
1171 SUnit *UnfoldSU = TryUnfoldSU(SU);
1182 NewSU = CreateClone(SU);
1185 for (SDep &Pred : SU->
Preds)
1187 AddPredQueued(NewSU, Pred);
1196 for (SDep &Succ : SU->
Succs) {
1203 AddPredQueued(SuccSU,
D);
1208 for (
const auto &[DelSU, DelD] : DelDeps)
1209 RemovePred(DelSU, DelD);
1212 AvailableQueue->
addNode(NewSU);
1220void ScheduleDAGRRList::InsertCopiesAndMoveSuccs(SUnit *SU,
unsigned Reg,
1221 const TargetRegisterClass *DestRC,
1222 const TargetRegisterClass *SrcRC,
1223 SmallVectorImpl<SUnit*> &
Copies) {
1224 SUnit *CopyFromSU = CreateNewSUnit(
nullptr);
1228 SUnit *CopyToSU = CreateNewSUnit(
nullptr);
1235 for (SDep &Succ : SU->
Succs) {
1242 AddPredQueued(SuccSU,
D);
1252 for (
const auto &[DelSU, DelD] : DelDeps)
1253 RemovePred(DelSU, DelD);
1256 FromDep.setLatency(SU->
Latency);
1257 AddPredQueued(CopyFromSU, FromDep);
1259 ToDep.setLatency(CopyFromSU->
Latency);
1260 AddPredQueued(CopyToSU, ToDep);
1263 AvailableQueue->
addNode(CopyFromSU);
1264 AvailableQueue->
addNode(CopyToSU);
1265 Copies.push_back(CopyFromSU);
1266 Copies.push_back(CopyToSU);
1281 if (!LiveRegDefs[*AliasI])
continue;
1284 if (LiveRegDefs[*AliasI] == SU)
continue;
1291 if (RegAdded.
insert(*AliasI).second) {
1304 for (
unsigned i = 1, e = LiveRegDefs.
size()-1; i != e; ++i) {
1305 if (!LiveRegDefs[i])
continue;
1306 if (LiveRegDefs[i] == SU)
continue;
1308 if (RegAdded.
insert(i).second)
1317 return RegOp->getRegMask();
1325bool ScheduleDAGRRList::
1326DelayForLiveRegsBottomUp(SUnit *SU, SmallVectorImpl<unsigned> &LRegs) {
1327 if (NumLiveRegs == 0)
1330 SmallSet<unsigned, 4> RegAdded;
1335 for (SDep &Pred : SU->
Preds) {
1338 RegAdded, LRegs,
TRI);
1341 for (SDNode *Node = SU->
getNode(); Node; Node =
Node->getGluedNode()) {
1346 if (
Node->getOperand(
NumOps-1).getValueType() == MVT::Glue)
1350 unsigned Flags =
Node->getConstantOperandVal(i);
1351 const InlineAsm::Flag
F(Flags);
1352 unsigned NumVals =
F.getNumOperandRegisters();
1355 if (
F.isRegDefKind() ||
F.isRegDefEarlyClobberKind() ||
1356 F.isClobberKind()) {
1358 for (; NumVals; --NumVals, ++i) {
1372 SDNode *SrcNode =
Node->getOperand(2).getNode();
1378 if (!
Node->isMachineOpcode())
1383 if (
Node->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
1385 unsigned CallResource =
TRI->getNumRegs();
1386 if (LiveRegDefs[CallResource]) {
1387 SDNode *Gen = LiveRegGens[CallResource]->getNode();
1391 RegAdded.
insert(CallResource).second)
1400 const MCInstrDesc &MCID =
TII->get(
Node->getMachineOpcode());
1406 for (
unsigned i = 0; i < MCID.
getNumDefs(); ++i)
1407 if (MCID.
operands()[i].isOptionalDef()) {
1417 return !LRegs.
empty();
1420void ScheduleDAGRRList::releaseInterferences(
unsigned Reg) {
1422 for (
unsigned i = Interferences.
size(); i > 0; --i) {
1423 SUnit *SU = Interferences[i-1];
1424 LRegsMapT::iterator LRegsPos = LRegsMap.find(SU);
1426 SmallVectorImpl<unsigned> &LRegs = LRegsPos->second;
1436 AvailableQueue->
push(SU);
1438 if (i < Interferences.
size())
1439 Interferences[i-1] = Interferences.
back();
1441 LRegsMap.erase(LRegsPos);
1449SUnit *ScheduleDAGRRList::PickNodeToScheduleBottomUp() {
1450 SUnit *CurSU = AvailableQueue->
empty() ? nullptr : AvailableQueue->
pop();
1451 auto FindAvailableNode = [&]() {
1453 SmallVector<unsigned, 4> LRegs;
1454 if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
1457 if (LRegs[0] ==
TRI->getNumRegs())
dbgs() <<
"CallResource";
1460 auto [LRegsIter, LRegsInserted] = LRegsMap.try_emplace(CurSU, LRegs);
1461 if (LRegsInserted) {
1468 LRegsIter->second = LRegs;
1470 CurSU = AvailableQueue->
pop();
1473 FindAvailableNode();
1485 for (SUnit *TrySU : Interferences) {
1486 SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU];
1490 SUnit *BtSU =
nullptr;
1491 unsigned LiveCycle = std::numeric_limits<unsigned>::max();
1492 for (
unsigned Reg : LRegs) {
1493 if (LiveRegGens[
Reg]->getHeight() < LiveCycle) {
1494 BtSU = LiveRegGens[
Reg];
1498 if (!WillCreateCycle(TrySU, BtSU)) {
1500 BacktrackBottomUp(TrySU, BtSU);
1507 AvailableQueue->
remove(BtSU);
1510 <<
") to SU(" << TrySU->NodeNum <<
")\n");
1515 if (!TrySU->isAvailable || !TrySU->NodeQueueId) {
1516 LLVM_DEBUG(
dbgs() <<
"TrySU not available; choosing node from queue\n");
1517 CurSU = AvailableQueue->
pop();
1521 AvailableQueue->
remove(TrySU);
1524 FindAvailableNode();
1536 SUnit *TrySU = Interferences[0];
1537 SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU];
1538 assert(LRegs.
size() == 1 &&
"Can't handle this yet!");
1539 unsigned Reg = LRegs[0];
1540 SUnit *LRDef = LiveRegDefs[
Reg];
1541 const TargetRegisterClass *RC =
TRI->getMinimalPhysRegClass(
Reg);
1542 const TargetRegisterClass *DestRC =
TRI->getCrossCopyRegClass(RC);
1551 SUnit *NewDef =
nullptr;
1553 NewDef = CopyAndMoveSuccessors(LRDef);
1554 if (!DestRC && !NewDef)
1560 InsertCopiesAndMoveSuccs(LRDef,
Reg, DestRC, RC,
Copies);
1562 <<
" to SU #" <<
Copies.front()->NodeNum <<
"\n");
1568 <<
" to SU #" << TrySU->
NodeNum <<
"\n");
1569 LiveRegDefs[
Reg] = NewDef;
1574 assert(CurSU &&
"Unable to resolve live physical register dependencies!");
1580void ScheduleDAGRRList::ListScheduleBottomUp() {
1582 ReleasePredecessors(&ExitSU);
1585 if (!SUnits.empty()) {
1586 SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];
1587 assert(RootSU->
Succs.empty() &&
"Graph root shouldn't have successors!");
1589 AvailableQueue->
push(RootSU);
1595 while (!AvailableQueue->
empty() || !Interferences.empty()) {
1597 AvailableQueue->
dump(
this));
1601 SUnit *SU = PickNodeToScheduleBottomUp();
1603 AdvancePastStalls(SU);
1605 ScheduleNodeBottomUp(SU);
1607 while (AvailableQueue->
empty() && !PendingQueue.empty()) {
1609 assert(MinAvailableCycle < std::numeric_limits<unsigned>::max() &&
1610 "MinAvailableCycle uninitialized");
1611 AdvanceToCycle(std::max(CurCycle + 1, MinAvailableCycle));
1619 VerifyScheduledSequence(
true);
1625class RegReductionPQBase;
1628 bool isReady(SUnit* SU,
unsigned CurCycle)
const {
return true; }
1633struct reverse_sort :
public queue_sort {
1636 reverse_sort(SF &sf) : SortFunc(sf) {}
1638 bool operator()(SUnit* left, SUnit* right)
const {
1641 return SortFunc(right, left);
1648struct bu_ls_rr_sort :
public queue_sort {
1651 HasReadyFilter =
false
1654 RegReductionPQBase *SPQ;
1656 bu_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1658 bool operator()(SUnit* left, SUnit* right)
const;
1662struct src_ls_rr_sort :
public queue_sort {
1665 HasReadyFilter =
false
1668 RegReductionPQBase *SPQ;
1670 src_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1672 bool operator()(SUnit* left, SUnit* right)
const;
1676struct hybrid_ls_rr_sort :
public queue_sort {
1679 HasReadyFilter =
false
1682 RegReductionPQBase *SPQ;
1684 hybrid_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1686 bool isReady(SUnit *SU,
unsigned CurCycle)
const;
1688 bool operator()(SUnit* left, SUnit* right)
const;
1693struct ilp_ls_rr_sort :
public queue_sort {
1696 HasReadyFilter =
false
1699 RegReductionPQBase *SPQ;
1701 ilp_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1703 bool isReady(SUnit *SU,
unsigned CurCycle)
const;
1705 bool operator()(SUnit* left, SUnit* right)
const;
1708class RegReductionPQBase :
public SchedulingPriorityQueue {
1710 std::vector<SUnit *> Queue;
1711 unsigned CurQueueId = 0;
1712 bool TracksRegPressure;
1716 std::vector<SUnit> *SUnits =
nullptr;
1718 MachineFunction &MF;
1719 const TargetInstrInfo *
TII =
nullptr;
1720 const TargetRegisterInfo *
TRI =
nullptr;
1721 const TargetLowering *TLI =
nullptr;
1722 ScheduleDAGRRList *scheduleDAG =
nullptr;
1725 std::vector<unsigned> SethiUllmanNumbers;
1728 std::vector<unsigned> RegPressure;
1732 std::vector<unsigned> RegLimit;
1735 RegReductionPQBase(MachineFunction &mf,
1736 bool hasReadyFilter,
1739 const TargetInstrInfo *tii,
1740 const TargetRegisterInfo *tri,
1741 const TargetLowering *tli)
1742 : SchedulingPriorityQueue(hasReadyFilter), TracksRegPressure(tracksrp),
1743 SrcOrder(srcorder), MF(mf),
TII(tii),
TRI(tri), TLI(tli) {
1744 if (TracksRegPressure) {
1745 unsigned NumRC =
TRI->getNumRegClasses();
1746 RegLimit.resize(NumRC);
1750 for (
const TargetRegisterClass *RC :
TRI->regclasses())
1755 void setScheduleDAG(ScheduleDAGRRList *scheduleDag) {
1756 scheduleDAG = scheduleDag;
1759 ScheduleHazardRecognizer* getHazardRec() {
1760 return scheduleDAG->getHazardRec();
1763 void initNodes(std::vector<SUnit> &sunits)
override;
1765 void addNode(
const SUnit *SU)
override;
1767 void updateNode(
const SUnit *SU)
override;
1769 void releaseState()
override {
1771 SethiUllmanNumbers.clear();
1775 unsigned getNodePriority(
const SUnit *SU)
const;
1777 unsigned getNodeOrdering(
const SUnit *SU)
const {
1783 bool empty()
const override {
return Queue.empty(); }
1785 void push(SUnit *U)
override {
1786 assert(!
U->NodeQueueId &&
"Node in the queue already");
1787 U->NodeQueueId = ++CurQueueId;
1791 void remove(SUnit *SU)
override {
1794 std::vector<SUnit *>::iterator
I =
llvm::find(Queue, SU);
1795 if (
I != std::prev(
Queue.end()))
1801 bool tracksRegPressure()
const override {
return TracksRegPressure; }
1803 void dumpRegPressure()
const;
1805 bool HighRegPressure(
const SUnit *SU)
const;
1807 bool MayReduceRegPressure(SUnit *SU)
const;
1809 int RegPressureDiff(SUnit *SU,
unsigned &LiveUses)
const;
1811 void scheduledNode(SUnit *SU)
override;
1813 void unscheduledNode(SUnit *SU)
override;
1816 bool canClobber(
const SUnit *SU,
const SUnit *
Op);
1817 void AddPseudoTwoAddrDeps();
1818 void PrescheduleNodesWithMultipleUses();
1819 void CalculateSethiUllmanNumbers();
1823static SUnit *popFromQueueImpl(std::vector<SUnit *> &Q, SF &Picker) {
1824 unsigned BestIdx = 0;
1827 for (
unsigned I = 1,
E = std::min(Q.size(), (
decltype(Q.size()))1000);
I !=
E;
1829 if (Picker(Q[BestIdx], Q[
I]))
1831 SUnit *
V = Q[BestIdx];
1832 if (BestIdx + 1 != Q.size())
1839SUnit *popFromQueue(std::vector<SUnit *> &Q, SF &Picker, ScheduleDAG *DAG) {
1842 reverse_sort<SF> RPicker(Picker);
1843 return popFromQueueImpl(Q, RPicker);
1847 return popFromQueueImpl(Q, Picker);
1858class RegReductionPriorityQueue :
public RegReductionPQBase {
1862 RegReductionPriorityQueue(MachineFunction &mf,
1865 const TargetInstrInfo *tii,
1866 const TargetRegisterInfo *tri,
1867 const TargetLowering *tli)
1868 : RegReductionPQBase(mf, SF::HasReadyFilter, tracksrp, srcorder,
1872 bool isBottomUp()
const override {
return SF::IsBottomUp; }
1874 bool isReady(SUnit *U)
const override {
1875 return Picker.HasReadyFilter && Picker.isReady(U, getCurCycle());
1878 SUnit *pop()
override {
1879 if (
Queue.empty())
return nullptr;
1881 SUnit *
V = popFromQueue(Queue, Picker, scheduleDAG);
1886#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1889 std::vector<SUnit *> DumpQueue =
Queue;
1890 SF DumpPicker = Picker;
1891 while (!DumpQueue.empty()) {
1892 SUnit *SU = popFromQueue(DumpQueue, DumpPicker, scheduleDAG);
1900using BURegReductionPriorityQueue = RegReductionPriorityQueue<bu_ls_rr_sort>;
1901using SrcRegReductionPriorityQueue = RegReductionPriorityQueue<src_ls_rr_sort>;
1902using HybridBURRPriorityQueue = RegReductionPriorityQueue<hybrid_ls_rr_sort>;
1903using ILPBURRPriorityQueue = RegReductionPriorityQueue<ilp_ls_rr_sort>;
1920 if (LSchedLow != RSchedLow)
1921 return LSchedLow < RSchedLow ? 1 : -1;
1929 if (SUNumbers[SU->
NodeNum] != 0)
1930 return SUNumbers[SU->
NodeNum];
1934 WorkState(
const SUnit *SU) : SU(SU) {}
1936 unsigned PredsProcessed = 0;
1941 while (!WorkList.
empty()) {
1942 auto &Temp = WorkList.
back();
1943 auto *TempSU = Temp.SU;
1944 bool AllPredsKnown =
true;
1946 for (
unsigned P = Temp.PredsProcessed;
P < TempSU->Preds.size(); ++
P) {
1947 auto &Pred = TempSU->Preds[
P];
1948 if (Pred.isCtrl())
continue;
1949 SUnit *PredSU = Pred.getSUnit();
1950 if (SUNumbers[PredSU->
NodeNum] == 0) {
1953 for (
auto It : WorkList)
1954 assert(It.SU != PredSU &&
"Trying to push an element twice?");
1957 Temp.PredsProcessed =
P + 1;
1958 WorkList.push_back(PredSU);
1959 AllPredsKnown =
false;
1968 unsigned SethiUllmanNumber = 0;
1970 for (
const SDep &Pred : TempSU->Preds) {
1971 if (Pred.isCtrl())
continue;
1972 SUnit *PredSU = Pred.getSUnit();
1973 unsigned PredSethiUllman = SUNumbers[PredSU->
NodeNum];
1974 assert(PredSethiUllman > 0 &&
"We should have evaluated this pred!");
1975 if (PredSethiUllman > SethiUllmanNumber) {
1976 SethiUllmanNumber = PredSethiUllman;
1978 }
else if (PredSethiUllman == SethiUllmanNumber)
1982 SethiUllmanNumber += Extra;
1983 if (SethiUllmanNumber == 0)
1984 SethiUllmanNumber = 1;
1985 SUNumbers[TempSU->NodeNum] = SethiUllmanNumber;
1989 assert(SUNumbers[SU->
NodeNum] > 0 &&
"SethiUllman should never be zero!");
1990 return SUNumbers[SU->
NodeNum];
1995void RegReductionPQBase::CalculateSethiUllmanNumbers() {
1996 SethiUllmanNumbers.assign(SUnits->size(), 0);
1998 for (
const SUnit &SU : *SUnits)
2002void RegReductionPQBase::addNode(
const SUnit *SU) {
2003 unsigned SUSize = SethiUllmanNumbers.size();
2004 if (SUnits->size() > SUSize)
2005 SethiUllmanNumbers.resize(SUSize*2, 0);
2009void RegReductionPQBase::updateNode(
const SUnit *SU) {
2010 SethiUllmanNumbers[SU->
NodeNum] = 0;
2016unsigned RegReductionPQBase::getNodePriority(
const SUnit *SU)
const {
2023 if (
Opc == TargetOpcode::EXTRACT_SUBREG ||
2024 Opc == TargetOpcode::SUBREG_TO_REG ||
2025 Opc == TargetOpcode::INSERT_SUBREG)
2041 return SethiUllmanNumbers[SU->
NodeNum];
2043 unsigned Priority = SethiUllmanNumbers[SU->
NodeNum];
2047 return (NP > 0) ? NP : 0;
2057#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2059 for (
const TargetRegisterClass *RC :
TRI->regclasses()) {
2064 << RegLimit[Id] <<
'\n');
2069bool RegReductionPQBase::HighRegPressure(
const SUnit *SU)
const {
2073 for (
const SDep &Pred : SU->
Preds) {
2082 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
2083 RegDefPos.IsValid(); RegDefPos.Advance()) {
2084 unsigned RCId,
Cost;
2087 if ((RegPressure[RCId] +
Cost) >= RegLimit[RCId])
2094bool RegReductionPQBase::MayReduceRegPressure(SUnit *SU)
const {
2097 if (!
N->isMachineOpcode() || !SU->
NumSuccs)
2100 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2101 for (
unsigned i = 0; i != NumDefs; ++i) {
2102 MVT VT =
N->getSimpleValueType(i);
2103 if (!
N->hasAnyUseOfValue(i))
2106 if (RegPressure[RCId] >= RegLimit[RCId])
2119int RegReductionPQBase::RegPressureDiff(SUnit *SU,
unsigned &LiveUses)
const {
2122 for (
const SDep &Pred : SU->
Preds) {
2133 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
2134 RegDefPos.IsValid(); RegDefPos.Advance()) {
2135 MVT VT = RegDefPos.GetValue();
2137 if (RegPressure[RCId] >= RegLimit[RCId])
2143 if (!
N || !
N->isMachineOpcode() || !SU->
NumSuccs)
2146 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2147 for (
unsigned i = 0; i != NumDefs; ++i) {
2148 MVT VT =
N->getSimpleValueType(i);
2149 if (!
N->hasAnyUseOfValue(i))
2152 if (RegPressure[RCId] >= RegLimit[RCId])
2158void RegReductionPQBase::scheduledNode(SUnit *SU) {
2159 if (!TracksRegPressure)
2165 for (
const SDep &Pred : SU->
Preds) {
2191 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
2192 RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) {
2196 unsigned RCId,
Cost;
2207 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(SU, scheduleDAG);
2208 RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) {
2209 if (SkipRegDefs > 0)
2211 unsigned RCId,
Cost;
2213 if (RegPressure[RCId] <
Cost) {
2217 <<
") has too many regdefs\n");
2227void RegReductionPQBase::unscheduledNode(SUnit *SU) {
2228 if (!TracksRegPressure)
2234 if (!
N->isMachineOpcode()) {
2238 unsigned Opc =
N->getMachineOpcode();
2239 if (
Opc == TargetOpcode::EXTRACT_SUBREG ||
2240 Opc == TargetOpcode::INSERT_SUBREG ||
2241 Opc == TargetOpcode::SUBREG_TO_REG ||
2242 Opc == TargetOpcode::REG_SEQUENCE ||
2243 Opc == TargetOpcode::IMPLICIT_DEF)
2247 for (
const SDep &Pred : SU->
Preds) {
2255 const SDNode *PN = PredSU->
getNode();
2265 if (POpc == TargetOpcode::IMPLICIT_DEF)
2267 if (POpc == TargetOpcode::EXTRACT_SUBREG ||
2268 POpc == TargetOpcode::INSERT_SUBREG ||
2269 POpc == TargetOpcode::SUBREG_TO_REG) {
2275 if (POpc == TargetOpcode::REG_SEQUENCE) {
2277 const TargetRegisterClass *RC =
TRI->getRegClass(DstRCIdx);
2278 unsigned RCId = RC->
getID();
2285 for (
unsigned i = 0; i != NumDefs; ++i) {
2300 if (SU->
NumSuccs &&
N->isMachineOpcode()) {
2301 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2302 for (
unsigned i = NumDefs, e =
N->getNumValues(); i != e; ++i) {
2303 MVT VT =
N->getSimpleValueType(i);
2304 if (VT == MVT::Glue || VT == MVT::Other)
2306 if (!
N->hasAnyUseOfValue(i))
2323 unsigned MaxHeight = 0;
2325 if (Succ.
isCtrl())
continue;
2332 if (Height > MaxHeight)
2341 unsigned Scratches = 0;
2343 if (Pred.isCtrl())
continue;
2352 bool RetVal =
false;
2354 if (Pred.isCtrl())
continue;
2355 const SUnit *PredSU = Pred.getSUnit();
2360 if (
Reg.isVirtual()) {
2374 bool RetVal =
false;
2376 if (Succ.
isCtrl())
continue;
2381 if (
Reg.isVirtual()) {
2413 if (Pred.isCtrl())
continue;
2414 Pred.getSUnit()->isVRegCycle =
true;
2425 if (Pred.isCtrl())
continue;
2426 SUnit *PredSU = Pred.getSUnit();
2429 "VRegCycle def must be CopyFromReg");
2430 Pred.getSUnit()->isVRegCycle =
false;
2443 if (Pred.isCtrl())
continue;
2444 if (Pred.getSUnit()->isVRegCycle &&
2457 if ((
int)SPQ->getCurCycle() < Height)
return true;
2458 if (SPQ->getHazardRec()->getHazardType(SU, 0)
2467 RegReductionPQBase *SPQ) {
2472 int LHeight = (int)left->
getHeight() + LPenalty;
2473 int RHeight = (int)right->
getHeight() + RPenalty;
2486 if (LHeight != RHeight)
2487 return LHeight > RHeight ? 1 : -1;
2499 if (!SPQ->getHazardRec()->isEnabled()) {
2500 if (LHeight != RHeight)
2501 return LHeight > RHeight ? 1 : -1;
2503 int LDepth = left->
getDepth() - LPenalty;
2504 int RDepth = right->
getDepth() - RPenalty;
2505 if (LDepth != RDepth) {
2507 <<
") depth " << LDepth <<
" vs SU (" << right->
NodeNum
2508 <<
") depth " << RDepth <<
"\n");
2509 return LDepth < RDepth ? 1 : -1;
2525 if (LHasPhysReg != RHasPhysReg) {
2527 static const char *
const PhysRegMsg[] = {
" has no physreg",
2528 " defines a physreg" };
2531 << PhysRegMsg[LHasPhysReg] <<
" SU(" << right->
NodeNum
2532 <<
") " << PhysRegMsg[RHasPhysReg] <<
"\n");
2533 return LHasPhysReg < RHasPhysReg;
2538 unsigned LPriority = SPQ->getNodePriority(left);
2539 unsigned RPriority = SPQ->getNodePriority(right);
2545 RPriority = (RPriority > RNumVals) ? (RPriority - RNumVals) : 0;
2549 LPriority = (LPriority > LNumVals) ? (LPriority - LNumVals) : 0;
2552 if (LPriority != RPriority)
2553 return LPriority > RPriority;
2558 unsigned LOrder = SPQ->getNodeOrdering(left);
2559 unsigned ROrder = SPQ->getNodeOrdering(right);
2563 if ((LOrder || ROrder) && LOrder != ROrder)
2564 return LOrder != 0 && (LOrder < ROrder || ROrder == 0);
2587 return LDist < RDist;
2592 if (LScratch != RScratch)
2593 return LScratch > RScratch;
2597 if ((left->
isCall && RPriority > 0) || (right->
isCall && LPriority > 0))
2616 "NodeQueueId cannot be zero");
2621bool bu_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2629bool src_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2633 unsigned LOrder = SPQ->getNodeOrdering(left);
2634 unsigned ROrder = SPQ->getNodeOrdering(right);
2638 if ((LOrder || ROrder) && LOrder != ROrder)
2639 return LOrder != 0 && (LOrder < ROrder || ROrder == 0);
2648bool hybrid_ls_rr_sort::isReady(SUnit *SU,
unsigned CurCycle)
const {
2649 static const unsigned ReadyDelay = 3;
2651 if (SPQ->MayReduceRegPressure(SU))
return true;
2653 if (SU->
getHeight() > (CurCycle + ReadyDelay))
return false;
2655 if (SPQ->getHazardRec()->getHazardType(SU, -ReadyDelay)
2663bool hybrid_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2671 bool LHigh = SPQ->HighRegPressure(left);
2672 bool RHigh = SPQ->HighRegPressure(right);
2675 if (LHigh && !RHigh) {
2680 else if (!LHigh && RHigh) {
2685 if (!LHigh && !RHigh) {
2695bool ilp_ls_rr_sort::isReady(SUnit *SU,
unsigned CurCycle)
const {
2696 if (SU->
getHeight() > CurCycle)
return false;
2698 if (SPQ->getHazardRec()->getHazardType(SU, 0)
2712 if (
Opc == TargetOpcode::EXTRACT_SUBREG ||
2713 Opc == TargetOpcode::SUBREG_TO_REG ||
2714 Opc == TargetOpcode::INSERT_SUBREG)
2729bool ilp_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2737 unsigned LLiveUses = 0, RLiveUses = 0;
2738 int LPDiff = 0, RPDiff = 0;
2740 LPDiff = SPQ->RegPressureDiff(left, LLiveUses);
2741 RPDiff = SPQ->RegPressureDiff(right, RLiveUses);
2745 <<
"): " << LPDiff <<
" != SU(" << right->
NodeNum
2746 <<
"): " << RPDiff <<
"\n");
2747 return LPDiff > RPDiff;
2753 if (LReduce && !RReduce)
return false;
2754 if (RReduce && !LReduce)
return true;
2759 <<
" != SU(" << right->
NodeNum <<
"): " << RLiveUses
2761 return LLiveUses < RLiveUses;
2767 if (LStall != RStall)
2776 <<
"): " << right->
getDepth() <<
"\n");
2790void RegReductionPQBase::initNodes(std::vector<SUnit> &sunits) {
2794 AddPseudoTwoAddrDeps();
2796 if (!TracksRegPressure && !SrcOrder)
2797 PrescheduleNodesWithMultipleUses();
2799 CalculateSethiUllmanNumbers();
2802 if (scheduleDAG->BB->isSuccessor(scheduleDAG->BB))
2803 for (SUnit &SU : sunits)
2811bool RegReductionPQBase::canClobber(
const SUnit *SU,
const SUnit *
Op) {
2814 const MCInstrDesc &MCID =
TII->get(
Opc);
2817 for (
unsigned i = 0; i !=
NumOps; ++i) {
2833 ScheduleDAGRRList *scheduleDAG,
2839 if (ImpDefs.
empty() && !RegMask)
2844 for (
const SDep &SuccPred : SuccSU->
Preds) {
2850 scheduleDAG->IsReachable(DepSU, SuccPred.
getSUnit()))
2857 if (
TRI->regsOverlap(ImpDef, SuccPred.
getReg()) &&
2858 scheduleDAG->IsReachable(DepSU, SuccPred.
getSUnit()))
2872 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2874 assert(!ImpDefs.
empty() &&
"Caller should check hasPhysRegDefs");
2877 if (!SUNode->isMachineOpcode())
2880 TII->get(SUNode->getMachineOpcode()).implicit_defs();
2882 if (SUImpDefs.
empty() && !SURegMask)
2884 for (
unsigned i = NumDefs, e =
N->getNumValues(); i != e; ++i) {
2885 MVT VT =
N->getSimpleValueType(i);
2886 if (VT == MVT::Glue || VT == MVT::Other)
2888 if (!
N->hasAnyUseOfValue(i))
2894 if (
TRI->regsOverlap(
Reg, SUReg))
2932void RegReductionPQBase::PrescheduleNodesWithMultipleUses() {
2934 for (SUnit &SU : *SUnits) {
2950 SDNode *PredFrameSetup =
nullptr;
2951 for (
const SDep &Pred : SU.
Preds)
2965 PredFrameSetup = PredND;
2970 if (PredFrameSetup !=
nullptr)
2974 SUnit *PredSU =
nullptr;
2975 for (
const SDep &Pred : SU.
Preds)
2997 for (
const SDep &PredSucc : PredSU->
Succs) {
2998 SUnit *PredSuccSU = PredSucc.
getSUnit();
2999 if (PredSuccSU == &SU)
continue;
3003 goto outer_loop_continue;
3007 goto outer_loop_continue;
3009 if (scheduleDAG->IsReachable(&SU, PredSuccSU))
3010 goto outer_loop_continue;
3016 dbgs() <<
" Prescheduling SU #" << SU.
NodeNum <<
" next to PredSU #"
3018 <<
" to guide scheduling in the presence of multiple uses\n");
3019 for (
unsigned i = 0; i != PredSU->
Succs.size(); ++i) {
3022 SUnit *SuccSU =
Edge.getSUnit();
3023 if (SuccSU != &SU) {
3024 Edge.setSUnit(PredSU);
3025 scheduleDAG->RemovePred(SuccSU,
Edge);
3026 scheduleDAG->AddPredQueued(&SU,
Edge);
3028 scheduleDAG->AddPredQueued(SuccSU,
Edge);
3032 outer_loop_continue:;
3043void RegReductionPQBase::AddPseudoTwoAddrDeps() {
3044 for (SUnit &SU : *SUnits) {
3053 unsigned Opc =
Node->getMachineOpcode();
3054 const MCInstrDesc &MCID =
TII->get(
Opc);
3057 for (
unsigned j = 0;
j !=
NumOps; ++
j) {
3063 const SUnit *DUSU = &(*SUnits)[DU->
getNodeId()];
3066 for (
const SDep &Succ : DUSU->
Succs) {
3081 while (SuccSU->
Succs.size() == 1 &&
3084 TargetOpcode::COPY_TO_REGCLASS)
3085 SuccSU = SuccSU->
Succs.front().getSUnit();
3098 if (SuccOpc == TargetOpcode::EXTRACT_SUBREG ||
3099 SuccOpc == TargetOpcode::INSERT_SUBREG ||
3100 SuccOpc == TargetOpcode::SUBREG_TO_REG)
3103 (!canClobber(SuccSU, DUSU) ||
3106 !scheduleDAG->IsReachable(SuccSU, &SU)) {
3108 <<
" Adding a pseudo-two-addr edge from SU #"
3127 BURegReductionPriorityQueue *PQ =
3128 new BURegReductionPriorityQueue(*IS->
MF,
false,
false,
TII,
TRI,
nullptr);
3129 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->
MF,
false, PQ, OptLevel);
3130 PQ->setScheduleDAG(SD);
3141 SrcRegReductionPriorityQueue *PQ =
3142 new SrcRegReductionPriorityQueue(*IS->
MF,
false,
true,
TII,
TRI,
nullptr);
3143 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->
MF,
false, PQ, OptLevel);
3144 PQ->setScheduleDAG(SD);
3156 HybridBURRPriorityQueue *PQ =
3157 new HybridBURRPriorityQueue(*IS->
MF,
true,
false,
TII,
TRI, TLI);
3159 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->
MF,
true, PQ, OptLevel);
3160 PQ->setScheduleDAG(SD);
3171 ILPBURRPriorityQueue *PQ =
3172 new ILPBURRPriorityQueue(*IS->
MF,
true,
false,
TII,
TRI, TLI);
3173 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->
MF,
true, PQ, OptLevel);
3174 PQ->setScheduleDAG(SD);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static bool isLiveOut(const MachineBasicBlock &MBB, unsigned Reg)
std::pair< BasicBlock *, BasicBlock * > Edge
static bool CheckForLiveRegDef(SUnit *SU, MCRegister Reg, std::vector< SUnit * > &LiveRegDefs, SmallSet< unsigned, 4 > &RegAdded, SmallVectorImpl< unsigned > &LRegs, const TargetRegisterInfo *TRI, const SDNode *Node=nullptr)
CheckForLiveRegDef - Return true and update live register vector if the specified register def of the...
static bool canEnableCoalescing(SUnit *SU)
static RegisterScheduler sourceListDAGScheduler("source", "Similar to list-burr but schedules in source " "order when possible", createSourceListDAGScheduler)
static cl::opt< bool > DisableSchedCycles("disable-sched-cycles", cl::Hidden, cl::init(false), cl::desc("Disable cycle-level precision during preRA scheduling"))
static cl::opt< bool > DisableSchedStalls("disable-sched-stalls", cl::Hidden, cl::init(true), cl::desc("Disable no-stall priority in sched=list-ilp"))
static bool hasOnlyLiveInOpers(const SUnit *SU)
hasOnlyLiveInOpers - Return true if SU has only value predecessors that are CopyFromReg from a virtua...
static bool IsChainDependent(SDNode *Outer, SDNode *Inner, unsigned NestLevel, const TargetInstrInfo *TII)
IsChainDependent - Test if Outer is reachable from Inner through chain dependencies.
static bool hasOnlyLiveOutUses(const SUnit *SU)
hasOnlyLiveOutUses - Return true if SU has only value successors that are CopyToReg to a virtual regi...
static cl::opt< bool > DisableSchedCriticalPath("disable-sched-critical-path", cl::Hidden, cl::init(false), cl::desc("Disable critical path priority in sched=list-ilp"))
static cl::opt< bool > Disable2AddrHack("disable-2addr-hack", cl::Hidden, cl::init(true), cl::desc("Disable scheduler's two-address hack"))
static RegisterScheduler ILPListDAGScheduler("list-ilp", "Bottom-up register pressure aware list scheduling " "which tries to balance ILP and register pressure", createILPListDAGScheduler)
static void resetVRegCycle(SUnit *SU)
static RegisterScheduler hybridListDAGScheduler("list-hybrid", "Bottom-up register pressure aware list scheduling " "which tries to balance latency and register pressure", createHybridListDAGScheduler)
static bool canClobberReachingPhysRegUse(const SUnit *DepSU, const SUnit *SU, ScheduleDAGRRList *scheduleDAG, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
canClobberReachingPhysRegUse - True if SU would clobber one of it's successor's explicit physregs who...
static cl::opt< bool > DisableSchedPhysRegJoin("disable-sched-physreg-join", cl::Hidden, cl::init(false), cl::desc("Disable physreg def-use affinity"))
static bool canClobberPhysRegDefs(const SUnit *SuccSU, const SUnit *SU, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
canClobberPhysRegDefs - True if SU would clobber one of SuccSU's physical register defs.
static cl::opt< unsigned > AvgIPC("sched-avg-ipc", cl::Hidden, cl::init(1), cl::desc("Average inst/cycle when no target itinerary exists."))
static void GetCostForDef(const ScheduleDAGSDNodes::RegDefIter &RegDefPos, const TargetLowering *TLI, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, unsigned &RegClass, unsigned &Cost, const MachineFunction &MF)
GetCostForDef - Looks up the register class and cost for a given definition.
static bool BURRSort(SUnit *left, SUnit *right, RegReductionPQBase *SPQ)
static cl::opt< bool > DisableSchedRegPressure("disable-sched-reg-pressure", cl::Hidden, cl::init(false), cl::desc("Disable regpressure priority in sched=list-ilp"))
static bool BUHasStall(SUnit *SU, int Height, RegReductionPQBase *SPQ)
static void initVRegCycle(SUnit *SU)
static constexpr unsigned RegSequenceCost
static cl::opt< int > MaxReorderWindow("max-sched-reorder", cl::Hidden, cl::init(6), cl::desc("Number of instructions to allow ahead of the critical path " "in sched=list-ilp"))
static SDNode * FindCallSeqStart(SDNode *N, unsigned &NestLevel, unsigned &MaxNest, const TargetInstrInfo *TII)
FindCallSeqStart - Starting from the (lowered) CALLSEQ_END node, locate the corresponding (lowered) C...
static bool isOperandOf(const SUnit *SU, SDNode *N)
static cl::opt< bool > DisableSchedVRegCycle("disable-sched-vrcycle", cl::Hidden, cl::init(false), cl::desc("Disable virtual register cycle interference checks"))
static int checkSpecialNodes(const SUnit *left, const SUnit *right)
static cl::opt< bool > DisableSchedLiveUses("disable-sched-live-uses", cl::Hidden, cl::init(true), cl::desc("Disable live use priority in sched=list-ilp"))
static const uint32_t * getNodeRegMask(const SDNode *N)
getNodeRegMask - Returns the register mask attached to an SDNode, if any.
static unsigned closestSucc(const SUnit *SU)
closestSucc - Returns the scheduled cycle of the successor which is closest to the current cycle.
static bool hasVRegCycleUse(const SUnit *SU)
static cl::opt< bool > DisableSchedHeight("disable-sched-height", cl::Hidden, cl::init(false), cl::desc("Disable scheduled-height priority in sched=list-ilp"))
static RegisterScheduler burrListDAGScheduler("list-burr", "Bottom-up register reduction list scheduling", createBURRListDAGScheduler)
static unsigned calcMaxScratches(const SUnit *SU)
calcMaxScratches - Returns an cost estimate of the worse case requirement for scratch registers,...
static unsigned CalcNodeSethiUllmanNumber(const SUnit *SU, std::vector< unsigned > &SUNumbers)
CalcNodeSethiUllmanNumber - Compute Sethi Ullman number.
static int BUCompareLatency(SUnit *left, SUnit *right, bool checkPref, RegReductionPQBase *SPQ)
static void CheckForLiveRegDefMasked(SUnit *SU, const uint32_t *RegMask, ArrayRef< SUnit * > LiveRegDefs, SmallSet< unsigned, 4 > &RegAdded, SmallVectorImpl< unsigned > &LRegs)
CheckForLiveRegDefMasked - Check for any live physregs that are clobbered by RegMask,...
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file describes how to lower LLVM code to machine code.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool hasOptionalDef() const
Set if this instruction has an optional definition, e.g.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
ArrayRef< MCPhysReg > implicit_defs() const
Return a list of registers that are potentially written by any instance of this machine instruction.
bool isCommutable() const
Return true if this may be a 2- or 3-address instruction (of the form "X = op Y, Z,...
MCRegAliasIterator enumerates all registers aliasing Reg.
Wrapper class representing physical registers. Should be passed by value.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
int getNodeId() const
Return the unique node id.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
unsigned getIROrder() const
Return the node ordering.
void setNodeId(int Id)
Set unique node id.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
SDNode * getGluedNode() const
If this node has a glue operand, return the node to which the glue operand points.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
@ Data
Regular data dependence (aka true-dependence).
@ Artificial
Arbitrary strong DAG edge (no real dependence).
unsigned getLatency() const
Returns the latency value for this edge, which roughly means the minimum number of cycles that must e...
bool isAssignedRegDep() const
Tests if this is a Data dependence that is associated with a register.
bool isArtificial() const
Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
Register getReg() const
Returns the register associated with this edge.
Scheduling unit. This is a node in the scheduling DAG.
bool isCall
Is a function call.
LLVM_ABI void setHeightToAtLeast(unsigned NewHeight)
If NewHeight is greater than this node's height value, set it to be the new height value.
unsigned NodeQueueId
Queue id of node.
unsigned NodeNum
Entry # of node in the node vector.
bool hasPhysRegClobbers
Has any physreg defs, used or not.
bool isCallOp
Is a function call operand.
const TargetRegisterClass * CopyDstRC
Is a special copy node if != nullptr.
unsigned getHeight() const
Returns the height of this node, which is the length of the maximum path down to any node which has n...
LLVM_ABI void setHeightDirty()
Sets a flag in this node to indicate that its stored Height value will require recomputation the next...
bool isSucc(const SUnit *N) const
Tests if node N is a successor of this node.
LLVM_ABI void removePred(const SDep &D)
Removes the specified edge as a pred of the current node if it exists.
unsigned short Latency
Node latency.
unsigned short NumRegDefsLeft
bool isPending
True once pending.
unsigned getDepth() const
Returns the depth of this node, which is the length of the maximum path up to any node which has no p...
bool isScheduled
True once scheduled.
bool isAvailable
True once available.
bool isScheduleLow
True if preferable to schedule low.
bool hasPhysRegDefs
Has physreg defs that are being used.
SmallVector< SDep, 4 > Succs
All sunit successors.
Sched::Preference SchedulingPref
Scheduling preference.
const TargetRegisterClass * CopySrcRC
SDNode * getNode() const
Returns the representative SDNode for this SUnit.
bool isTwoAddress
Is a two-address instruction.
bool isCommutable
Is a commutable instruction.
bool isVRegCycle
May use and def the same vreg.
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.
RegDefIter - In place iteration over the values defined by an SUnit.
const SDNode * GetNode() const
ScheduleDAGSDNodes - A ScheduleDAG for scheduling SDNode-based DAGs.
This class can compute a topological ordering for SUnits and provides methods for dynamically updatin...
void MarkDirty()
Mark the ordering as temporarily broken, after a new node has been added.
virtual void dumpNode(const SUnit &SU) const =0
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
unsigned getMaxLookAhead() const
virtual void RecedeCycle()
RecedeCycle - This callback is invoked whenever the next bottom-up instruction to be scheduled cannot...
virtual void Reset()
Reset - This callback is invoked when a new block of instructions is about to be schedule.
virtual void EmitInstruction(SUnit *)
EmitInstruction - This callback is invoked when an instruction is emitted, to advance the hazard stat...
virtual bool atIssueLimit() const
atIssueLimit - Return true if no more instructions may be issued in this cycle.
virtual HazardType getHazardType(SUnit *, int Stalls=0)
getHazardType - Return the hazard type of emitting this node.
This interface is used to plug different priorities computation algorithms into the list scheduler.
void setCurCycle(unsigned Cycle)
virtual void remove(SUnit *SU)=0
virtual void releaseState()=0
virtual void scheduledNode(SUnit *)
As each node is scheduled, this method is invoked.
virtual bool tracksRegPressure() const
virtual void dump(ScheduleDAG *) const
bool hasReadyFilter() const
virtual void initNodes(std::vector< SUnit > &SUnits)=0
virtual bool empty() const =0
virtual void unscheduledNode(SUnit *)
virtual void addNode(const SUnit *SU)=0
virtual void updateNode(const SUnit *SU)=0
virtual void push(SUnit *U)=0
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
const TargetLowering * TLI
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
virtual uint8_t getRepRegClassCostFor(MVT VT) const
Return the cost of the 'representative' register class for the specified value type.
virtual const TargetRegisterClass * getRepRegClassFor(MVT VT) const
Return the 'representative' register class for the specified value type.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
unsigned getID() const
Return the register class ID number.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const
Return the register pressure "high water mark" for the specific register class.
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ EH_LABEL
EH_LABEL - Represents a label in mid basic block used to track locations needed for debug and excepti...
@ ANNOTATION_LABEL
ANNOTATION_LABEL - Represents a mid basic block label used by annotations.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ EntryToken
EntryToken - This is the marker used to indicate the start of a region.
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ LIFETIME_START
This corresponds to the llvm.lifetime.
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ INLINEASM
INLINEASM - Represents an inline asm block.
initializer< Ty > init(const Ty &Val)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
NodeAddr< DefNode * > Def
NodeAddr< NodeBase * > Node
LLVM_ABI std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
void fill(R &&Range, T &&Value)
Provide wrappers to std::fill which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI ScheduleDAGSDNodes * createBURRListDAGScheduler(SelectionDAGISel *IS, CodeGenOptLevel OptLevel)
createBURRListDAGScheduler - This creates a bottom up register usage reduction list scheduler.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI ScheduleDAGSDNodes * createHybridListDAGScheduler(SelectionDAGISel *IS, CodeGenOptLevel)
createHybridListDAGScheduler - This creates a bottom up register pressure aware list scheduler that m...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI ScheduleDAGSDNodes * createSourceListDAGScheduler(SelectionDAGISel *IS, CodeGenOptLevel OptLevel)
createSourceListDAGScheduler - This creates a bottom up list scheduler that schedules nodes in source...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ScheduleDAGSDNodes * createILPListDAGScheduler(SelectionDAGISel *IS, CodeGenOptLevel)
createILPListDAGScheduler - This creates a bottom up register pressure aware list scheduler that trie...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
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.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.