39 #include "llvm/Config/llvm-config.h" 63 #define DEBUG_TYPE "pre-RA-sched" 65 STATISTIC(NumBacktracks,
"Number of times scheduler backtracked");
66 STATISTIC(NumUnfolds,
"Number of nodes unfolded");
67 STATISTIC(NumDups,
"Number of duplicated nodes");
68 STATISTIC(NumPRCopies,
"Number of physical register copies");
72 "Bottom-up register reduction list scheduling",
77 "Similar to list-burr but schedules in source " 78 "order when possible",
83 "Bottom-up register pressure aware list scheduling " 84 "which tries to balance latency and register pressure",
89 "Bottom-up register pressure aware list scheduling " 90 "which tries to balance ILP and register pressure",
95 cl::desc(
"Disable cycle-level precision during preRA scheduling"));
101 cl::desc(
"Disable regpressure priority in sched=list-ilp"));
104 cl::desc(
"Disable live use priority in sched=list-ilp"));
107 cl::desc(
"Disable virtual register cycle interference checks"));
110 cl::desc(
"Disable physreg def-use affinity"));
113 cl::desc(
"Disable no-stall priority in sched=list-ilp"));
116 cl::desc(
"Disable critical path priority in sched=list-ilp"));
119 cl::desc(
"Disable scheduled-height priority in sched=list-ilp"));
122 cl::desc(
"Disable scheduler's two-address hack"));
126 cl::desc(
"Number of instructions to allow ahead of the critical path " 127 "in sched=list-ilp"));
131 cl::desc(
"Average inst/cycle whan no target itinerary exists."));
151 std::vector<SUnit *> PendingQueue;
157 unsigned CurCycle = 0;
160 unsigned MinAvailableCycle;
169 unsigned NumLiveRegs;
170 std::unique_ptr<SUnit*[]> LiveRegDefs;
171 std::unique_ptr<SUnit*[]> LiveRegGens;
194 NeedLatency(needlatency), AvailableQueue(availqueue),
195 Topo(SUnits, nullptr) {
203 ~ScheduleDAGRRList()
override {
205 delete AvailableQueue;
208 void Schedule()
override;
213 bool IsReachable(
const SUnit *SU,
const SUnit *TargetSU) {
219 bool WillCreateCycle(
SUnit *SU,
SUnit *TargetSU) {
234 void RemovePred(
SUnit *SU,
const SDep &D) {
240 bool isReady(
SUnit *SU) {
245 void ReleasePred(
SUnit *SU,
const SDep *PredEdge);
246 void ReleasePredecessors(
SUnit *SU);
247 void ReleasePending();
248 void AdvanceToCycle(
unsigned NextCycle);
249 void AdvancePastStalls(
SUnit *SU);
250 void EmitNode(
SUnit *SU);
251 void ScheduleNodeBottomUp(
SUnit*);
252 void CapturePred(
SDep *PredEdge);
253 void UnscheduleNodeBottomUp(
SUnit*);
254 void RestoreHazardCheckerBottomUp();
258 void InsertCopiesAndMoveSuccs(
SUnit*,
unsigned,
264 void releaseInterferences(
unsigned Reg = 0);
266 SUnit *PickNodeToScheduleBottomUp();
267 void ListScheduleBottomUp();
272 unsigned NumSUnits = SUnits.size();
273 SUnit *NewNode = newSUnit(N);
275 if (NewNode->
NodeNum >= NumSUnits)
283 unsigned NumSUnits = SUnits.size();
284 SUnit *NewNode = Clone(N);
286 if (NewNode->
NodeNum >= NumSUnits)
293 bool forceUnitLatencies()
const override {
308 unsigned &RegClass,
unsigned &Cost,
321 RegClass = RC->
getID();
327 if (Opcode == TargetOpcode::REG_SEQUENCE) {
328 unsigned DstRCIdx = cast<ConstantSDNode>(Node->
getOperand(0))->getZExtValue();
330 RegClass = RC->
getID();
335 unsigned Idx = RegDefPos.
GetIdx();
338 RegClass = RC->
getID();
349 void ScheduleDAGRRList::Schedule() {
351 <<
" '" << BB->getName() <<
"' **********\n");
360 LiveRegDefs.reset(
new SUnit*[
TRI->getNumRegs() + 1]());
361 LiveRegGens.reset(
new SUnit*[
TRI->getNumRegs() + 1]());
362 CallSeqEndForStart.
clear();
363 assert(Interferences.
empty() && LRegsMap.empty() &&
"stale Interferences");
366 BuildSchedGraph(
nullptr);
376 ListScheduleBottomUp();
381 dbgs() <<
"*** Final schedule ***\n";
393 void ScheduleDAGRRList::ReleasePred(
SUnit *SU,
const SDep *PredEdge) {
398 dbgs() <<
"*** Scheduling failed! ***\n";
400 dbgs() <<
" has been released too many times!\n";
406 if (!forceUnitLatencies()) {
418 if (Height < MinAvailableCycle)
419 MinAvailableCycle = Height;
421 if (isReady(PredSU)) {
422 AvailableQueue->
push(PredSU);
428 PendingQueue.push_back(PredSU);
465 goto found_chain_operand;
468 found_chain_operand:;
492 unsigned BestMaxNest = MaxNest;
494 unsigned MyNestLevel = NestLevel;
495 unsigned MyMaxNest = MaxNest;
497 MyNestLevel, MyMaxNest,
TII))
498 if (!Best || (MyMaxNest > BestMaxNest)) {
500 BestMaxNest = MyMaxNest;
504 MaxNest = BestMaxNest;
511 MaxNest =
std::max(MaxNest, NestLevel);
523 goto found_chain_operand;
526 found_chain_operand:;
549 void ScheduleDAGRRList::ReleasePredecessors(
SUnit *SU) {
552 ReleasePred(SU, &Pred);
558 SUnit *RegDef = LiveRegDefs[Pred.
getReg()]; (void)RegDef;
560 "interference on register dependence");
562 if (!LiveRegGens[Pred.
getReg()]) {
564 LiveRegGens[Pred.
getReg()] = SU;
572 unsigned CallResource =
TRI->getNumRegs();
573 if (!LiveRegDefs[CallResource])
574 for (
SDNode *Node = SU->
getNode(); Node; Node = Node->getGluedNode())
575 if (Node->isMachineOpcode() &&
576 Node->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
577 unsigned NestLevel = 0;
578 unsigned MaxNest = 0;
580 assert(N &&
"Must find call sequence start");
583 CallSeqEndForStart[
Def] = SU;
586 LiveRegDefs[CallResource] =
Def;
587 LiveRegGens[CallResource] = SU;
594 void ScheduleDAGRRList::ReleasePending() {
596 assert(PendingQueue.empty() &&
"pending instrs not allowed in this mode");
601 if (AvailableQueue->
empty())
606 for (
unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
607 unsigned ReadyCycle = PendingQueue[i]->getHeight();
608 if (ReadyCycle < MinAvailableCycle)
609 MinAvailableCycle = ReadyCycle;
612 if (!isReady(PendingQueue[i]))
614 AvailableQueue->
push(PendingQueue[i]);
616 PendingQueue[i]->isPending =
false;
617 PendingQueue[i] = PendingQueue.back();
618 PendingQueue.pop_back();
624 void ScheduleDAGRRList::AdvanceToCycle(
unsigned NextCycle) {
625 if (NextCycle <= CurCycle)
632 CurCycle = NextCycle;
635 for (; CurCycle != NextCycle; ++CurCycle) {
646 void ScheduleDAGRRList::AdvancePastStalls(
SUnit *SU) {
663 AdvanceToCycle(ReadyCycle);
683 AdvanceToCycle(CurCycle + Stalls);
688 void ScheduleDAGRRList::EmitNode(
SUnit *SU) {
699 "This target-independent node should not be scheduled.");
730 void ScheduleDAGRRList::ScheduleNodeBottomUp(
SUnit *SU) {
735 if (CurCycle < SU->getHeight())
737 <<
"] pipeline stall!\n");
757 AdvanceToCycle(CurCycle + 1);
761 ReleasePredecessors(SU);
767 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
769 LiveRegDefs[Succ.
getReg()] =
nullptr;
770 LiveRegGens[Succ.
getReg()] =
nullptr;
771 releaseInterferences(Succ.
getReg());
776 unsigned CallResource =
TRI->getNumRegs();
777 if (LiveRegDefs[CallResource] == SU)
780 if (SUNode->isMachineOpcode() &&
781 SUNode->getMachineOpcode() ==
TII->getCallFrameSetupOpcode()) {
782 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
784 LiveRegDefs[CallResource] =
nullptr;
785 LiveRegGens[CallResource] =
nullptr;
786 releaseInterferences(CallResource);
807 AdvanceToCycle(CurCycle + 1);
814 void ScheduleDAGRRList::CapturePred(
SDep *PredEdge) {
819 AvailableQueue->
remove(PredSU);
823 "NumSuccsLeft will overflow!");
829 void ScheduleDAGRRList::UnscheduleNodeBottomUp(
SUnit *SU) {
836 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
838 "Physical register dependency violated?");
840 LiveRegDefs[Pred.
getReg()] =
nullptr;
841 LiveRegGens[Pred.
getReg()] =
nullptr;
842 releaseInterferences(Pred.
getReg());
848 unsigned CallResource =
TRI->getNumRegs();
851 if (SUNode->isMachineOpcode() &&
852 SUNode->getMachineOpcode() ==
TII->getCallFrameSetupOpcode()) {
853 SUnit *SeqEnd = CallSeqEndForStart[SU];
854 assert(SeqEnd &&
"Call sequence start/end must be known");
855 assert(!LiveRegDefs[CallResource]);
856 assert(!LiveRegGens[CallResource]);
858 LiveRegDefs[CallResource] = SU;
859 LiveRegGens[CallResource] = SeqEnd;
865 if (LiveRegGens[CallResource] == SU)
868 if (SUNode->isMachineOpcode() &&
869 SUNode->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
870 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
871 assert(LiveRegDefs[CallResource]);
872 assert(LiveRegGens[CallResource]);
874 LiveRegDefs[CallResource] =
nullptr;
875 LiveRegGens[CallResource] =
nullptr;
876 releaseInterferences(CallResource);
880 for (
auto &Succ : SU->
Succs) {
881 if (Succ.isAssignedRegDep()) {
882 auto Reg = Succ.getReg();
883 if (!LiveRegDefs[
Reg])
887 LiveRegDefs[
Reg] = SU;
891 if (!LiveRegGens[Reg]) {
893 LiveRegGens[
Reg] = Succ.getSUnit();
894 for (
auto &Succ2 : SU->
Succs) {
895 if (Succ2.isAssignedRegDep() && Succ2.getReg() == Reg &&
896 Succ2.getSUnit()->getHeight() < LiveRegGens[
Reg]->getHeight())
897 LiveRegGens[Reg] = Succ2.getSUnit();
911 PendingQueue.push_back(SU);
914 AvailableQueue->
push(SU);
921 void ScheduleDAGRRList::RestoreHazardCheckerBottomUp() {
924 unsigned LookAhead = std::min((
unsigned)
Sequence.size(),
929 std::vector<SUnit *>::const_iterator
I = (
Sequence.end() - LookAhead);
930 unsigned HazardCycle = (*I)->getHeight();
933 for (; SU->
getHeight() > HazardCycle; ++HazardCycle) {
942 void ScheduleDAGRRList::BacktrackBottomUp(
SUnit *SU,
SUnit *BtSU) {
948 UnscheduleNodeBottomUp(OldSU);
957 RestoreHazardCheckerBottomUp();
967 if (SUNode->isOperandOf(N))
974 SUnit *ScheduleDAGRRList::TryUnfoldSU(
SUnit *SU) {
978 if (!
TII->unfoldMemoryOperand(*DAG, N, NewNodes))
983 if (NewNodes.
size() == 3)
986 assert(NewNodes.
size() == 2 &&
"Expected a load folding node!");
989 SDNode *LoadNode = NewNodes[0];
990 unsigned NumVals = N->getNumValues();
996 bool isNewLoad =
true;
1006 LoadSU = CreateNewSUnit(LoadNode);
1009 InitNumRegDefsLeft(LoadSU);
1010 computeLatency(LoadSU);
1016 if (N->getNodeId() != -1) {
1017 NewSU = &SUnits[N->getNodeId()];
1024 NewSU = CreateNewSUnit(N);
1037 InitNumRegDefsLeft(NewSU);
1038 computeLatency(NewSU);
1044 for (
unsigned i = 0; i != NumVals; ++i)
1046 DAG->ReplaceAllUsesOfValueWith(
SDValue(SU->
getNode(), OldNumVals - 1),
1071 for (
const SDep &Pred : ChainPreds) {
1072 RemovePred(SU, Pred);
1074 AddPred(LoadSU, Pred);
1076 for (
const SDep &Pred : LoadPreds) {
1077 RemovePred(SU, Pred);
1079 AddPred(LoadSU, Pred);
1081 for (
const SDep &Pred : NodePreds) {
1082 RemovePred(SU, Pred);
1083 AddPred(NewSU, Pred);
1085 for (
SDep D : NodeSuccs) {
1088 RemovePred(SuccDep, D);
1090 AddPred(SuccDep, D);
1096 for (
SDep D : ChainSuccs) {
1099 RemovePred(SuccDep, D);
1102 AddPred(SuccDep, D);
1113 AvailableQueue->
addNode(LoadSU);
1115 AvailableQueue->
addNode(NewSU);
1127 SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(
SUnit *SU) {
1136 !
TII->canCopyGluedNodeDuringSchedule(N)) {
1139 <<
"Giving up because it has incoming glue and the target does not " 1140 "want to copy it\n");
1145 bool TryUnfold =
false;
1146 for (
unsigned i = 0, e = N->
getNumValues(); i != e; ++i) {
1149 LLVM_DEBUG(
dbgs() <<
"Giving up because it has outgoing glue\n");
1155 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
1156 if (VT ==
MVT::Glue && !
TII->canCopyGluedNodeDuringSchedule(N)) {
1158 dbgs() <<
"Giving up because it one of the operands is glue and " 1159 "the target does not want to copy it\n");
1166 SUnit *UnfoldSU = TryUnfoldSU(SU);
1177 NewSU = CreateClone(SU);
1182 AddPred(NewSU, Pred);
1196 DelDeps.
push_back(std::make_pair(SuccSU, D));
1199 for (
auto &DelDep : DelDeps)
1200 RemovePred(DelDep.first, DelDep.second);
1203 AvailableQueue->
addNode(NewSU);
1211 void ScheduleDAGRRList::InsertCopiesAndMoveSuccs(
SUnit *SU,
unsigned Reg,
1215 SUnit *CopyFromSU = CreateNewSUnit(
nullptr);
1219 SUnit *CopyToSU = CreateNewSUnit(
nullptr);
1234 DelDeps.
push_back(std::make_pair(SuccSU, Succ));
1243 for (
auto &DelDep : DelDeps)
1244 RemovePred(DelDep.first, DelDep.second);
1248 AddPred(CopyFromSU, FromDep);
1251 AddPred(CopyToSU, ToDep);
1254 AvailableQueue->
addNode(CopyFromSU);
1255 AvailableQueue->
addNode(CopyToSU);
1287 SUnit **LiveRegDefs,
1294 if (!LiveRegDefs[*AliasI])
continue;
1297 if (LiveRegDefs[*AliasI] == SU)
continue;
1300 if (RegAdded.
insert(*AliasI).second) {
1313 for (
unsigned i = 1, e = LiveRegDefs.
size()-1; i != e; ++i) {
1314 if (!LiveRegDefs[i])
continue;
1315 if (LiveRegDefs[i] == SU)
continue;
1317 if (RegAdded.
insert(i).second)
1325 if (
const auto *RegOp = dyn_cast<RegisterMaskSDNode>(
Op.getNode()))
1326 return RegOp->getRegMask();
1334 bool ScheduleDAGRRList::
1336 if (NumLiveRegs == 0)
1347 RegAdded, LRegs,
TRI);
1350 for (
SDNode *Node = SU->
getNode(); Node; Node = Node->getGluedNode()) {
1353 unsigned NumOps = Node->getNumOperands();
1354 if (Node->getOperand(NumOps-1).getValueType() ==
MVT::Glue)
1359 cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
1367 for (; NumVals; --NumVals, ++i) {
1368 unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->
getReg();
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)
1406 for (
unsigned i = 0; i < MCID.
getNumDefs(); ++i)
1419 return !LRegs.
empty();
1422 void ScheduleDAGRRList::releaseInterferences(
unsigned Reg) {
1424 for (
unsigned i = Interferences.
size(); i > 0; --i) {
1425 SUnit *SU = Interferences[i-1];
1426 LRegsMapT::iterator LRegsPos = LRegsMap.find(SU);
1438 AvailableQueue->
push(SU);
1440 if (i < Interferences.
size())
1441 Interferences[i-1] = Interferences.
back();
1443 LRegsMap.erase(LRegsPos);
1451 SUnit *ScheduleDAGRRList::PickNodeToScheduleBottomUp() {
1452 SUnit *CurSU = AvailableQueue->
empty() ? nullptr : AvailableQueue->
pop();
1453 auto FindAvailableNode = [&]() {
1456 if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
1459 if (LRegs[0] ==
TRI->getNumRegs())
dbgs() <<
"CallResource";
1462 std::pair<LRegsMapT::iterator, bool> LRegsPair =
1463 LRegsMap.insert(std::make_pair(CurSU, LRegs));
1464 if (LRegsPair.second) {
1471 LRegsPair.first->second = LRegs;
1473 CurSU = AvailableQueue->
pop();
1476 FindAvailableNode();
1483 for (
SUnit *TrySU : Interferences) {
1488 SUnit *BtSU =
nullptr;
1490 for (
unsigned Reg : LRegs) {
1491 if (LiveRegGens[Reg]->getHeight() < LiveCycle) {
1492 BtSU = LiveRegGens[
Reg];
1496 if (!WillCreateCycle(TrySU, BtSU)) {
1498 BacktrackBottomUp(TrySU, BtSU);
1505 AvailableQueue->
remove(BtSU);
1508 <<
") to SU(" << TrySU->NodeNum <<
")\n");
1513 if (!TrySU->isAvailable || !TrySU->NodeQueueId) {
1514 LLVM_DEBUG(
dbgs() <<
"TrySU not available; choosing node from queue\n");
1515 CurSU = AvailableQueue->
pop();
1519 AvailableQueue->
remove(TrySU);
1522 FindAvailableNode();
1534 SUnit *TrySU = Interferences[0];
1536 assert(LRegs.
size() == 1 &&
"Can't handle this yet!");
1537 unsigned Reg = LRegs[0];
1541 TRI->getMinimalPhysRegClass(Reg, VT);
1551 SUnit *NewDef =
nullptr;
1553 NewDef = CopyAndMoveSuccessors(LRDef);
1554 if (!DestRC && !NewDef)
1560 InsertCopiesAndMoveSuccs(LRDef, Reg, DestRC, RC, Copies);
1564 NewDef = Copies.
back();
1568 <<
" to SU #" << TrySU->
NodeNum <<
"\n");
1569 LiveRegDefs[
Reg] = NewDef;
1574 assert(CurSU &&
"Unable to resolve live physical register dependencies!");
1580 void 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()) {
1610 "MinAvailableCycle uninitialized");
1611 AdvanceToCycle(
std::max(CurCycle + 1, MinAvailableCycle));
1619 VerifyScheduledSequence(
true);
1625 class RegReductionPQBase;
1628 bool isReady(
SUnit* SU,
unsigned CurCycle)
const {
return true; }
1633 struct 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);
1648 struct 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;
1662 struct 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;
1676 struct 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;
1693 struct 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;
1710 std::vector<SUnit *> Queue;
1711 unsigned CurQueueId = 0;
1712 bool TracksRegPressure;
1716 std::vector<SUnit> *SUnits;
1722 ScheduleDAGRRList *scheduleDAG =
nullptr;
1725 std::vector<unsigned> SethiUllmanNumbers;
1732 std::vector<unsigned> RegLimit;
1736 bool hasReadyFilter,
1743 SrcOrder(srcorder), MF(mf),
TII(tii),
TRI(tri), TLI(tli) {
1744 if (TracksRegPressure) {
1746 RegLimit.resize(NumRC);
1747 RegPressure.resize(NumRC);
1748 std::fill(RegLimit.begin(), RegLimit.end(), 0);
1749 std::fill(RegPressure.begin(), RegPressure.end(), 0);
1755 void setScheduleDAG(ScheduleDAGRRList *scheduleDag) {
1756 scheduleDAG = scheduleDag;
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();
1772 std::fill(RegPressure.begin(), RegPressure.end(), 0);
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 {
1791 void remove(
SUnit *SU)
override {
1792 assert(!Queue.empty() &&
"Queue is empty!");
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;
1817 void AddPseudoTwoAddrDeps();
1818 void PrescheduleNodesWithMultipleUses();
1819 void CalculateSethiUllmanNumbers();
1823 static SUnit *popFromQueueImpl(std::vector<SUnit *> &Q, SF &Picker) {
1824 std::vector<SUnit *>::iterator Best = Q.begin();
1825 for (
auto I = std::next(Q.begin()),
E = Q.end();
I !=
E; ++
I)
1826 if (Picker(*Best, *
I))
1829 if (Best != std::prev(Q.end()))
1836 SUnit *popFromQueue(std::vector<SUnit *> &Q, SF &Picker,
ScheduleDAG *DAG) {
1839 reverse_sort<SF> RPicker(Picker);
1840 return popFromQueueImpl(Q, RPicker);
1844 return popFromQueueImpl(Q, Picker);
1855 class RegReductionPriorityQueue :
public RegReductionPQBase {
1865 : RegReductionPQBase(mf, SF::HasReadyFilter, tracksrp, srcorder,
1869 bool isBottomUp()
const override {
return SF::IsBottomUp; }
1871 bool isReady(
SUnit *U)
const override {
1872 return Picker.HasReadyFilter && Picker.isReady(U, getCurCycle());
1875 SUnit *pop()
override {
1876 if (Queue.empty())
return nullptr;
1878 SUnit *V = popFromQueue(Queue, Picker, scheduleDAG);
1883 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1886 std::vector<SUnit *> DumpQueue = Queue;
1887 SF DumpPicker = Picker;
1888 while (!DumpQueue.empty()) {
1889 SUnit *SU = popFromQueue(DumpQueue, DumpPicker, scheduleDAG);
1897 using BURegReductionPriorityQueue = RegReductionPriorityQueue<bu_ls_rr_sort>;
1898 using SrcRegReductionPriorityQueue = RegReductionPriorityQueue<src_ls_rr_sort>;
1899 using HybridBURRPriorityQueue = RegReductionPriorityQueue<hybrid_ls_rr_sort>;
1900 using ILPBURRPriorityQueue = RegReductionPriorityQueue<ilp_ls_rr_sort>;
1917 if (LSchedLow != RSchedLow)
1918 return LSchedLow < RSchedLow ? 1 : -1;
1926 if (SUNumbers[SU->
NodeNum] != 0)
1927 return SUNumbers[SU->
NodeNum];
1931 WorkState(
const SUnit *SU) : SU(SU) {}
1933 unsigned PredsProcessed = 0;
1938 while (!WorkList.
empty()) {
1939 auto &Temp = WorkList.
back();
1940 auto *TempSU = Temp.SU;
1941 bool AllPredsKnown =
true;
1943 for (
unsigned P = Temp.PredsProcessed; P < TempSU->Preds.size(); ++
P) {
1944 auto &Pred = TempSU->Preds[
P];
1945 if (Pred.isCtrl())
continue;
1946 SUnit *PredSU = Pred.getSUnit();
1947 if (SUNumbers[PredSU->
NodeNum] == 0) {
1950 for (
auto It : WorkList)
1951 assert(It.SU != PredSU &&
"Trying to push an element twice?");
1954 Temp.PredsProcessed =
P + 1;
1955 WorkList.push_back(PredSU);
1956 AllPredsKnown =
false;
1965 unsigned SethiUllmanNumber = 0;
1967 for (
const SDep &Pred : TempSU->Preds) {
1968 if (Pred.
isCtrl())
continue;
1970 unsigned PredSethiUllman = SUNumbers[PredSU->
NodeNum];
1971 assert(PredSethiUllman > 0 &&
"We should have evaluated this pred!");
1972 if (PredSethiUllman > SethiUllmanNumber) {
1973 SethiUllmanNumber = PredSethiUllman;
1975 }
else if (PredSethiUllman == SethiUllmanNumber)
1979 SethiUllmanNumber += Extra;
1980 if (SethiUllmanNumber == 0)
1981 SethiUllmanNumber = 1;
1982 SUNumbers[TempSU->NodeNum] = SethiUllmanNumber;
1986 assert(SUNumbers[SU->
NodeNum] > 0 &&
"SethiUllman should never be zero!");
1987 return SUNumbers[SU->
NodeNum];
1992 void RegReductionPQBase::CalculateSethiUllmanNumbers() {
1993 SethiUllmanNumbers.assign(SUnits->size(), 0);
1995 for (
const SUnit &SU : *SUnits)
1999 void RegReductionPQBase::addNode(
const SUnit *SU) {
2000 unsigned SUSize = SethiUllmanNumbers.size();
2001 if (SUnits->size() > SUSize)
2002 SethiUllmanNumbers.resize(SUSize*2, 0);
2006 void RegReductionPQBase::updateNode(
const SUnit *SU) {
2007 SethiUllmanNumbers[SU->
NodeNum] = 0;
2013 unsigned RegReductionPQBase::getNodePriority(
const SUnit *SU)
const {
2020 if (Opc == TargetOpcode::EXTRACT_SUBREG ||
2021 Opc == TargetOpcode::SUBREG_TO_REG ||
2022 Opc == TargetOpcode::INSERT_SUBREG)
2038 return SethiUllmanNumbers[SU->
NodeNum];
2040 unsigned Priority = SethiUllmanNumbers[SU->
NodeNum];
2044 return (NP > 0) ? NP : 0;
2054 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 2057 unsigned Id = RC->getID();
2061 << RegLimit[
Id] <<
'\n');
2066 bool RegReductionPQBase::HighRegPressure(
const SUnit *SU)
const {
2080 RegDefPos.
IsValid(); RegDefPos.Advance()) {
2081 unsigned RCId, Cost;
2091 bool RegReductionPQBase::MayReduceRegPressure(
SUnit *SU)
const {
2098 for (
unsigned i = 0; i != NumDefs; ++i) {
2102 unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
2116 int RegReductionPQBase::RegPressureDiff(
SUnit *SU,
unsigned &LiveUses)
const {
2131 RegDefPos.
IsValid(); RegDefPos.Advance()) {
2132 MVT VT = RegDefPos.GetValue();
2133 unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
2144 for (
unsigned i = 0; i != NumDefs; ++i) {
2148 unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
2155 void RegReductionPQBase::scheduledNode(
SUnit *SU) {
2156 if (!TracksRegPressure)
2189 RegDefPos.
IsValid(); RegDefPos.Advance(), --SkipRegDefs) {
2193 unsigned RCId, Cost;
2205 RegDefPos.
IsValid(); RegDefPos.Advance(), --SkipRegDefs) {
2206 if (SkipRegDefs > 0)
2208 unsigned RCId, Cost;
2214 <<
") has too many regdefs\n");
2224 void RegReductionPQBase::unscheduledNode(
SUnit *SU) {
2225 if (!TracksRegPressure)
2236 if (Opc == TargetOpcode::EXTRACT_SUBREG ||
2237 Opc == TargetOpcode::INSERT_SUBREG ||
2238 Opc == TargetOpcode::SUBREG_TO_REG ||
2239 Opc == TargetOpcode::REG_SEQUENCE ||
2240 Opc == TargetOpcode::IMPLICIT_DEF)
2256 unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
2257 RegPressure[RCId] += TLI->getRepRegClassCostFor(VT);
2262 if (POpc == TargetOpcode::IMPLICIT_DEF)
2264 if (POpc == TargetOpcode::EXTRACT_SUBREG ||
2265 POpc == TargetOpcode::INSERT_SUBREG ||
2266 POpc == TargetOpcode::SUBREG_TO_REG) {
2268 unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
2269 RegPressure[RCId] += TLI->getRepRegClassCostFor(VT);
2273 for (
unsigned i = 0; i != NumDefs; ++i) {
2277 unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
2278 if (
RegPressure[RCId] < TLI->getRepRegClassCostFor(VT))
2282 RegPressure[RCId] -= TLI->getRepRegClassCostFor(VT);
2290 for (
unsigned i = NumDefs, e = N->
getNumValues(); i != e; ++i) {
2296 unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
2297 RegPressure[RCId] += TLI->getRepRegClassCostFor(VT);
2311 unsigned MaxHeight = 0;
2313 if (Succ.
isCtrl())
continue;
2320 if (Height > MaxHeight)
2329 unsigned Scratches = 0;
2331 if (Pred.
isCtrl())
continue;
2340 bool RetVal =
false;
2342 if (Pred.
isCtrl())
continue;
2362 bool RetVal =
false;
2364 if (Succ.
isCtrl())
continue;
2401 if (Pred.
isCtrl())
continue;
2413 if (Pred.
isCtrl())
continue;
2417 "VRegCycle def must be CopyFromReg");
2431 if (Pred.
isCtrl())
continue;
2445 if ((
int)SPQ->getCurCycle() < Height)
return true;
2446 if (SPQ->getHazardRec()->getHazardType(SU, 0)
2455 RegReductionPQBase *SPQ) {
2460 int LHeight = (int)left->
getHeight() + LPenalty;
2461 int RHeight = (int)right->
getHeight() + RPenalty;
2474 if (LHeight != RHeight)
2475 return LHeight > RHeight ? 1 : -1;
2487 if (!SPQ->getHazardRec()->isEnabled()) {
2488 if (LHeight != RHeight)
2489 return LHeight > RHeight ? 1 : -1;
2491 int LDepth = left->
getDepth() - LPenalty;
2492 int RDepth = right->
getDepth() - RPenalty;
2493 if (LDepth != RDepth) {
2495 <<
") depth " << LDepth <<
" vs SU (" << right->
NodeNum 2496 <<
") depth " << RDepth <<
"\n");
2497 return LDepth < RDepth ? 1 : -1;
2513 if (LHasPhysReg != RHasPhysReg) {
2515 static const char *
const PhysRegMsg[] = {
" has no physreg",
2516 " defines a physreg" };
2519 << PhysRegMsg[LHasPhysReg] <<
" SU(" << right->
NodeNum 2520 <<
") " << PhysRegMsg[RHasPhysReg] <<
"\n");
2521 return LHasPhysReg < RHasPhysReg;
2526 unsigned LPriority = SPQ->getNodePriority(left);
2527 unsigned RPriority = SPQ->getNodePriority(right);
2533 RPriority = (RPriority > RNumVals) ? (RPriority - RNumVals) : 0;
2537 LPriority = (LPriority > LNumVals) ? (LPriority - LNumVals) : 0;
2540 if (LPriority != RPriority)
2541 return LPriority > RPriority;
2546 unsigned LOrder = SPQ->getNodeOrdering(left);
2547 unsigned ROrder = SPQ->getNodeOrdering(right);
2551 if ((LOrder || ROrder) && LOrder != ROrder)
2552 return LOrder != 0 && (LOrder < ROrder || ROrder == 0);
2575 return LDist < RDist;
2580 if (LScratch != RScratch)
2581 return LScratch > RScratch;
2585 if ((left->
isCall && RPriority > 0) || (right->
isCall && LPriority > 0))
2604 "NodeQueueId cannot be zero");
2609 bool bu_ls_rr_sort::operator()(
SUnit *left,
SUnit *right)
const {
2617 bool src_ls_rr_sort::operator()(
SUnit *left,
SUnit *right)
const {
2621 unsigned LOrder = SPQ->getNodeOrdering(left);
2622 unsigned ROrder = SPQ->getNodeOrdering(right);
2626 if ((LOrder || ROrder) && LOrder != ROrder)
2627 return LOrder != 0 && (LOrder < ROrder || ROrder == 0);
2636 bool hybrid_ls_rr_sort::isReady(
SUnit *SU,
unsigned CurCycle)
const {
2637 static const unsigned ReadyDelay = 3;
2639 if (SPQ->MayReduceRegPressure(SU))
return true;
2641 if (SU->
getHeight() > (CurCycle + ReadyDelay))
return false;
2643 if (SPQ->getHazardRec()->getHazardType(SU, -ReadyDelay)
2651 bool hybrid_ls_rr_sort::operator()(
SUnit *left,
SUnit *right)
const {
2659 bool LHigh = SPQ->HighRegPressure(left);
2660 bool RHigh = SPQ->HighRegPressure(right);
2663 if (LHigh && !RHigh) {
2668 else if (!LHigh && RHigh) {
2673 if (!LHigh && !RHigh) {
2683 bool ilp_ls_rr_sort::isReady(
SUnit *SU,
unsigned CurCycle)
const {
2684 if (SU->
getHeight() > CurCycle)
return false;
2686 if (SPQ->getHazardRec()->getHazardType(SU, 0)
2700 if (Opc == TargetOpcode::EXTRACT_SUBREG ||
2701 Opc == TargetOpcode::SUBREG_TO_REG ||
2702 Opc == TargetOpcode::INSERT_SUBREG)
2717 bool ilp_ls_rr_sort::operator()(
SUnit *left,
SUnit *right)
const {
2725 unsigned LLiveUses = 0, RLiveUses = 0;
2726 int LPDiff = 0, RPDiff = 0;
2728 LPDiff = SPQ->RegPressureDiff(left, LLiveUses);
2729 RPDiff = SPQ->RegPressureDiff(right, RLiveUses);
2733 <<
"): " << LPDiff <<
" != SU(" << right->
NodeNum 2734 <<
"): " << RPDiff <<
"\n");
2735 return LPDiff > RPDiff;
2741 if (LReduce && !RReduce)
return false;
2742 if (RReduce && !LReduce)
return true;
2747 <<
" != SU(" << right->
NodeNum <<
"): " << RLiveUses
2749 return LLiveUses < RLiveUses;
2755 if (LStall != RStall)
2764 <<
"): " << right->
getDepth() <<
"\n");
2778 void RegReductionPQBase::initNodes(std::vector<SUnit> &sunits) {
2782 AddPseudoTwoAddrDeps();
2784 if (!TracksRegPressure && !SrcOrder)
2785 PrescheduleNodesWithMultipleUses();
2787 CalculateSethiUllmanNumbers();
2790 if (scheduleDAG->BB->isSuccessor(scheduleDAG->BB))
2791 for (
SUnit &SU : sunits)
2799 bool RegReductionPQBase::canClobber(
const SUnit *SU,
const SUnit *
Op) {
2805 for (
unsigned i = 0; i != NumOps; ++i) {
2821 ScheduleDAGRRList *scheduleDAG,
2827 if(!ImpDefs && !RegMask)
2832 for (
const SDep &SuccPred : SuccSU->
Preds) {
2838 scheduleDAG->IsReachable(DepSU, SuccPred.
getSUnit()))
2842 for (
const MCPhysReg *ImpDef = ImpDefs; *ImpDef; ++ImpDef)
2847 scheduleDAG->IsReachable(DepSU, SuccPred.
getSUnit()))
2862 assert(ImpDefs &&
"Caller should check hasPhysRegDefs");
2865 if (!SUNode->isMachineOpcode())
2868 TII->
get(SUNode->getMachineOpcode()).getImplicitDefs();
2870 if (!SUImpDefs && !SURegMask)
2872 for (
unsigned i = NumDefs, e = N->
getNumValues(); i != e; ++i) {
2878 unsigned Reg = ImpDefs[i - NumDefs];
2883 for (;*SUImpDefs; ++SUImpDefs) {
2884 unsigned SUReg = *SUImpDefs;
2923 void RegReductionPQBase::PrescheduleNodesWithMultipleUses() {
2925 for (
SUnit &SU : *SUnits) {
2939 (cast<RegisterSDNode>(N->getOperand(1))->
getReg()))
2943 SUnit *PredSU =
nullptr;
2963 (cast<RegisterSDNode>(N->getOperand(1))->
getReg()))
2967 for (
const SDep &PredSucc : PredSU->
Succs) {
2969 if (PredSuccSU == &SU)
continue;
2973 goto outer_loop_continue;
2977 goto outer_loop_continue;
2979 if (scheduleDAG->IsReachable(&SU, PredSuccSU))
2980 goto outer_loop_continue;
2986 dbgs() <<
" Prescheduling SU #" << SU.
NodeNum <<
" next to PredSU #" 2988 <<
" to guide scheduling in the presence of multiple uses\n");
2989 for (
unsigned i = 0; i != PredSU->
Succs.size(); ++i) {
2993 if (SuccSU != &SU) {
2995 scheduleDAG->RemovePred(SuccSU, Edge);
2996 scheduleDAG->AddPred(&SU, Edge);
2998 scheduleDAG->AddPred(SuccSU, Edge);
3002 outer_loop_continue:;
3013 void RegReductionPQBase::AddPseudoTwoAddrDeps() {
3014 for (
SUnit &SU : *SUnits) {
3027 for (
unsigned j = 0; j != NumOps; ++j) {
3051 while (SuccSU->
Succs.size() == 1 &&
3054 TargetOpcode::COPY_TO_REGCLASS)
3055 SuccSU = SuccSU->
Succs.front().getSUnit();
3068 if (SuccOpc == TargetOpcode::EXTRACT_SUBREG ||
3069 SuccOpc == TargetOpcode::INSERT_SUBREG ||
3070 SuccOpc == TargetOpcode::SUBREG_TO_REG)
3073 (!canClobber(SuccSU, DUSU) ||
3076 !scheduleDAG->IsReachable(SuccSU, &SU)) {
3078 <<
" Adding a pseudo-two-addr edge from SU #" 3098 BURegReductionPriorityQueue *PQ =
3099 new BURegReductionPriorityQueue(*IS->
MF,
false,
false, TII, TRI,
nullptr);
3100 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->
MF,
false, PQ, OptLevel);
3101 PQ->setScheduleDAG(SD);
3112 SrcRegReductionPriorityQueue *PQ =
3113 new SrcRegReductionPriorityQueue(*IS->
MF,
false,
true, TII, TRI,
nullptr);
3114 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->
MF,
false, PQ, OptLevel);
3115 PQ->setScheduleDAG(SD);
3127 HybridBURRPriorityQueue *PQ =
3128 new HybridBURRPriorityQueue(*IS->
MF,
true,
false, TII, TRI, TLI);
3130 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->
MF,
true, PQ, OptLevel);
3131 PQ->setScheduleDAG(SD);
3143 ILPBURRPriorityQueue *PQ =
3144 new ILPBURRPriorityQueue(*IS->
MF,
true,
false, TII, TRI, TLI);
3145 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->
MF,
true, PQ, OptLevel);
3146 PQ->setScheduleDAG(SD);
virtual void initNodes(std::vector< SUnit > &SUnits)=0
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
unsigned NumPreds
of SDep::Data preds.
virtual void updateNode(const SUnit *SU)=0
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
static int BUCompareLatency(SUnit *left, SUnit *right, bool checkPref, RegReductionPQBase *SPQ)
static bool canEnableCoalescing(SUnit *SU)
virtual const TargetRegisterClass * getRepRegClassFor(MVT VT) const
Return the 'representative' register class for the specified value type.
bool isCommutable() const
Return true if this may be a 2- or 3-address instruction (of the form "X = op Y, Z, ..."), which produces the same result if Y and Z are exchanged.
SDNode * getNode() const
Returns the representative SDNode for this SUnit.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
unsigned getIROrder() const
Return the node ordering.
static cl::opt< bool > DisableSchedRegPressure("disable-sched-reg-pressure", cl::Hidden, cl::init(false), cl::desc("Disable regpressure priority in sched=list-ilp"))
virtual bool tracksRegPressure() const
static cl::opt< unsigned > AvgIPC("sched-avg-ipc", cl::Hidden, cl::init(1), cl::desc("Average inst/cycle whan no target itinerary exists."))
void push_back(const T &Elt)
bool isTwoAddress
Is a two-address instruction.
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...
Describe properties that are true of each instruction in the target description file.
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 isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
virtual void dumpNode(const SUnit &SU) const =0
virtual void push(SUnit *U)=0
static bool isClobberKind(unsigned Flag)
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...
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
void removePred(const SDep &D)
Removes the specified edge as a pred of the current node if it exists.
static cl::opt< bool > DisableSchedVRegCycle("disable-sched-vrcycle", cl::Hidden, cl::init(false), cl::desc("Disable virtual register cycle interference checks"))
unsigned getCallFrameDestroyOpcode() const
void setNodeId(int Id)
Set unique node id.
unsigned getReg() const
Returns the register associated with this edge.
SDNode * getNode() const
get the SDNode which holds the desired result
static unsigned CalcNodeSethiUllmanNumber(const SUnit *SU, std::vector< unsigned > &SUNumbers)
CalcNodeSethiUllmanNumber - Compute Sethi Ullman number.
bool isAssignedRegDep() const
Tests if this is a Data dependence that is associated with a register.
static RegisterScheduler burrListDAGScheduler("list-burr", "Bottom-up register reduction list scheduling", createBURRListDAGScheduler)
static bool hasVRegCycleUse(const SUnit *SU)
const TargetRegisterClass * CopyDstRC
Is a special copy node if != nullptr.
virtual void dump(ScheduleDAG *) const
virtual unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const
Return the register pressure "high water mark" for the specific register class.
EntryToken - This is the marker used to indicate the start of a region.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
ScheduleDAGSDNodes * createHybridListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level)
createHybridListDAGScheduler - This creates a bottom up register pressure aware list scheduler that m...
const TargetRegisterClass * getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
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...
bool isScheduled
True once scheduled.
This interface is used to plug different priorities computation algorithms into the list scheduler...
static int checkSpecialNodes(const SUnit *left, const SUnit *right)
unsigned NumSuccs
of SDep::Data sucss.
virtual void unscheduledNode(SUnit *)
unsigned getLatency() const
Returns the latency value for this edge, which roughly means the minimum number of cycles that must e...
unsigned NumSuccsLeft
of succs not scheduled.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
const HexagonInstrInfo * TII
virtual void releaseState()=0
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
static RegisterScheduler sourceListDAGScheduler("source", "Similar to list-burr but schedules in source " "order when possible", createSourceListDAGScheduler)
const TargetRegisterClass * getRegClass(const MCInstrDesc &MCID, unsigned OpNum, const TargetRegisterInfo *TRI, const MachineFunction &MF) const
Given a machine instruction descriptor, returns the register class constraint for OpNum...
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
const TargetLowering * TLI
virtual uint8_t getRepRegClassCostFor(MVT VT) const
Return the cost of the 'representative' register class for the specified value type.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Regular data dependence (aka true-dependence).
CopyToReg - This node has three operands: a chain, a register number to set to this value...
iterator_range< regclass_iterator > regclasses() const
bool hasPhysRegDefs
Has physreg defs that are being used.
void setCurCycle(unsigned Cycle)
static bool isRegDefEarlyClobberKind(unsigned Flag)
static void CheckForLiveRegDef(SUnit *SU, unsigned Reg, SUnit **LiveRegDefs, SmallSet< unsigned, 4 > &RegAdded, SmallVectorImpl< unsigned > &LRegs, const TargetRegisterInfo *TRI)
CheckForLiveRegDef - Return true and update live register vector if the specified register def of the...
void InitDAGTopologicalSorting()
Creates the initial topological ordering from the DAG to be scheduled.
static const uint32_t * getNodeRegMask(const SDNode *N)
getNodeRegMask - Returns the register mask attached to an SDNode, if any.
unsigned getID() const
Return the register class ID number.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
INLINEASM - Represents an inline asm block.
unsigned getNumRegClasses() const
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
SUnit * OrigNode
If not this, the node from which this node was cloned.
virtual void RecedeCycle()
RecedeCycle - This callback is invoked whenever the next bottom-up instruction to be scheduled cannot...
ScheduleDAGSDNodes * createBURRListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level OptLevel)
createBURRListDAGScheduler - This creates a bottom up register usage reduction list scheduler...
bool isPending
True once pending.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
virtual const TargetInstrInfo * getInstrInfo() const
static bool isRegDefKind(unsigned Flag)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
TargetInstrInfo - Interface to description of machine instruction set.
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, and add them to LRegs.
This corresponds to the llvm.lifetime.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
void setHeightToAtLeast(unsigned NewHeight)
If NewDepth is greater than this node's depth value, set it to be the new height value.
initializer< Ty > init(const Ty &Val)
bool isCall
Is a function call.
const MCPhysReg * getImplicitDefs() const
Return a list of registers that are potentially written by any instance of this machine instruction...
bool WillCreateCycle(SUnit *TargetSU, SUnit *SU)
Returns true if addPred(TargetSU, SU) creates a cycle.
ScheduleDAGSDNodes - A ScheduleDAG for scheduling SDNode-based DAGs.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool isArtificial() const
Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...
unsigned getMaxLookAhead() const
static cl::opt< bool > DisableSchedStalls("disable-sched-stalls", cl::Hidden, cl::init(true), cl::desc("Disable no-stall priority in sched=list-ilp"))
HazardRecognizer - This determines whether or not an instruction can be issued this cycle...
bool isOptionalDef() const
Set if this operand is a optional def.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool hasOptionalDef() const
Set if this instruction has an optional definition, e.g.
unsigned short Latency
Node latency.
virtual void addNode(const SUnit *SU)=0
bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
virtual bool empty() const =0
size_t size() const
size - Get the array size.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
iterator_range< value_op_iterator > op_values() const
static RegisterScheduler ILPListDAGScheduler("list-ilp", "Bottom-up register pressure aware list scheduling " "which tries to balance ILP and register pressure", createILPListDAGScheduler)
const SDValue & getOperand(unsigned Num) const
ScheduleDAGSDNodes * createILPListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level)
createILPListDAGScheduler - This creates a bottom up register pressure aware list scheduler that trie...
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
static bool isOperandOf(const SUnit *SU, SDNode *N)
static unsigned calcMaxScratches(const SUnit *SU)
calcMaxScratches - Returns an cost estimate of the worse case requirement for scratch registers...
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 BUHasStall(SUnit *SU, int Height, RegReductionPQBase *SPQ)
const MCPhysReg * ImplicitDefs
const SDNode * GetNode() const
static unsigned getNumOperandRegisters(unsigned Flag)
getNumOperandRegisters - Extract the number of registers field from the inline asm operand flag...
static cl::opt< bool > DisableSchedCriticalPath("disable-sched-critical-path", cl::Hidden, cl::init(false), cl::desc("Disable critical path priority in sched=list-ilp"))
bool isVRegCycle
May use and def the same vreg.
unsigned getCallFrameSetupOpcode() const
These methods return the opcode of the frame setup/destroy instructions if they exist (-1 otherwise)...
MCRegAliasIterator enumerates all registers aliasing Reg.
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 void resetVRegCycle(SUnit *SU)
SDNode * getGluedNode() const
If this node has a glue operand, return the node to which the glue operand points.
static cl::opt< bool > DisableSchedLiveUses("disable-sched-live-uses", cl::Hidden, cl::init(true), cl::desc("Disable live use priority in sched=list-ilp"))
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void RemovePred(SUnit *M, SUnit *N)
Updates the topological ordering to accommodate an an edge to be removed from the specified node N fr...
static bool hasOnlyLiveInOpers(const SUnit *SU)
hasOnlyLiveInOpers - Return true if SU has only value predecessors that are CopyFromReg from a virtua...
static unsigned closestSucc(const SUnit *SU)
closestSucc - Returns the scheduled cycle of the successor which is closest to the current cycle...
Sched::Preference SchedulingPref
Scheduling preference.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
RegDefIter - In place iteration over the values defined by an SUnit.
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
EH_LABEL - Represents a label in mid basic block used to track locations needed for debug and excepti...
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
static bool BURRSort(SUnit *left, SUnit *right, RegReductionPQBase *SPQ)
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specific constraint if it is set.
TokenFactor - This node takes multiple tokens as input and produces a single token result...
bool isCommutable
Is a commutable instruction.
ScheduleDAGSDNodes * createSourceListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level OptLevel)
createBURRListDAGScheduler - This creates a bottom up list scheduler that schedules nodes in source c...
virtual void EmitInstruction(SUnit *)
EmitInstruction - This callback is invoked when an instruction is emitted, to advance the hazard stat...
static cl::opt< bool > DisableSchedHeight("disable-sched-height", cl::Hidden, cl::init(false), cl::desc("Disable scheduled-height priority in sched=list-ilp"))
virtual void remove(SUnit *SU)=0
bool regsOverlap(unsigned regA, unsigned regB) const
Returns true if the two registers are equal or alias each other.
static void initVRegCycle(SUnit *SU)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
Represents one node in the SelectionDAG.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
const TargetRegisterClass * CopySrcRC
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static bool clobbersPhysReg(const uint32_t *RegMask, unsigned PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
bool IsReachable(const SUnit *SU, const SUnit *TargetSU)
Checks if SU is reachable from TargetSU.
virtual void Reset()
Reset - This callback is invoked when a new block of instructions is about to be schedule.
virtual void scheduledNode(SUnit *)
As each node is scheduled, this method is invoked.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
bool isCallOp
Is a function call operand.
void setLatency(unsigned Lat)
Sets the latency for this edge.
TargetSubtargetInfo - Generic base class for all target subtargets.
int getNodeId() const
Return the unique node id.
bool isAvailable
True once available.
unsigned NodeQueueId
Queue id of node.
unsigned getHeight() const
Returns the height of this node, which is the length of the maximum path down to any node which has n...
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
static RegisterScheduler hybridListDAGScheduler("list-hybrid", "Bottom-up register pressure aware list scheduling " "which tries to balance latency and register pressure", createHybridListDAGScheduler)
virtual ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static bool hasOnlyLiveOutUses(const SUnit *SU)
hasOnlyLiveOutUses - Return true if SU has only value successors that are CopyToReg to a virtual regi...
LLVM_NODISCARD bool empty() const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
static cl::opt< bool > DisableSchedPhysRegJoin("disable-sched-physreg-join", cl::Hidden, cl::init(false), cl::desc("Disable physreg def-use affinity"))
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
unsigned short NumRegDefsLeft
of reg defs with no scheduled use.
static cl::opt< bool > Disable2AddrHack("disable-2addr-hack", cl::Hidden, cl::init(true), cl::desc("Disable scheduler's two-address hack"))
static MVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, const TargetInstrInfo *TII)
getPhysicalRegisterVT - Returns the ValueType of the physical register definition of the specified no...
static cl::opt< bool > DisableSchedCycles("disable-sched-cycles", cl::Hidden, cl::init(false), cl::desc("Disable cycle-level precision during preRA scheduling"))
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
unsigned NodeNum
Entry # of node in the node vector.
void setHeightDirty()
Sets a flag in this node to indicate that its stored Height value will require recomputation the next...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool addPred(const SDep &D, bool Required=true)
Adds the specified edge as a pred of the current node if not already.
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"))
virtual bool isReady(SUnit *) const
bool hasReadyFilter() const
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
SmallVector< SDep, 4 > Succs
All sunit successors.
const MCOperandInfo * OpInfo
Arbitrary strong DAG edge (no real dependence).
void AddPred(SUnit *Y, SUnit *X)
Updates the topological ordering to accommodate an edge to be added from SUnit X to SUnit Y...
static bool isLiveOut(const MachineBasicBlock &MBB, unsigned Reg)
bool isScheduleLow
True if preferable to schedule low.
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
for(unsigned i=Desc.getNumOperands(), e=OldMI.getNumOperands();i !=e;++i)
This class can compute a topological ordering for SUnits and provides methods for dynamically updatin...
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
bool hasPhysRegClobbers
Has any physreg defs, used or not.
bool isSucc(const SUnit *N) const
Tests if node N is a successor of this node.
virtual HazardType getHazardType(SUnit *m, int Stalls=0)
getHazardType - Return the hazard type of emitting this node.
Scheduling unit. This is a node in the scheduling DAG.
This file describes how to lower LLVM code to machine code.
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
virtual bool atIssueLimit() const
atIssueLimit - Return true if no more instructions may be issued in this cycle.