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 RemovePred(SUnit *SU,
const SDep &
D) {
233 Topo.RemovePred(SU,
D.getSUnit());
238 bool isReady(SUnit *SU) {
240 AvailableQueue->isReady(SU);
243 void ReleasePred(SUnit *SU,
const SDep *PredEdge);
244 void ReleasePredecessors(SUnit *SU);
245 void ReleasePending();
246 void AdvanceToCycle(
unsigned NextCycle);
247 void AdvancePastStalls(SUnit *SU);
248 void EmitNode(SUnit *SU);
249 void ScheduleNodeBottomUp(SUnit*);
250 void CapturePred(SDep *PredEdge);
251 void UnscheduleNodeBottomUp(SUnit*);
252 void RestoreHazardCheckerBottomUp();
253 void BacktrackBottomUp(SUnit*, SUnit*);
254 SUnit *TryUnfoldSU(SUnit *);
255 SUnit *CopyAndMoveSuccessors(SUnit*);
256 void InsertCopiesAndMoveSuccs(SUnit*,
unsigned,
259 SmallVectorImpl<SUnit*>&);
260 bool DelayForLiveRegsBottomUp(SUnit*, SmallVectorImpl<unsigned>&);
262 void releaseInterferences(
unsigned Reg = 0);
264 SUnit *PickNodeToScheduleBottomUp();
265 void ListScheduleBottomUp();
268 SUnit *CreateNewSUnit(SDNode *
N) {
269 unsigned NumSUnits = SUnits.size();
270 SUnit *NewNode = newSUnit(
N);
272 if (NewNode->
NodeNum >= NumSUnits)
273 Topo.AddSUnitWithoutPredecessors(NewNode);
278 SUnit *CreateClone(SUnit *
N) {
279 unsigned NumSUnits = SUnits.size();
280 SUnit *NewNode = Clone(
N);
282 if (NewNode->
NodeNum >= NumSUnits)
283 Topo.AddSUnitWithoutPredecessors(NewNode);
289 bool forceUnitLatencies()
const override {
306 unsigned &RegClass,
unsigned &Cost,
312 if (VT == MVT::Untyped) {
319 RegClass = RC->
getID();
324 unsigned Opcode =
Node->getMachineOpcode();
325 if (Opcode == TargetOpcode::REG_SEQUENCE) {
326 unsigned DstRCIdx =
Node->getConstantOperandVal(0);
328 RegClass = RC->
getID();
333 unsigned Idx = RegDefPos.
GetIdx();
336 assert(RC &&
"Not a valid register class");
337 RegClass = RC->
getID();
348void ScheduleDAGRRList::Schedule() {
350 <<
" '" << BB->getName() <<
"' **********\n");
359 LiveRegDefs.reset(
new SUnit*[
TRI->getNumRegs() + 1]());
360 LiveRegGens.reset(
new SUnit*[
TRI->getNumRegs() + 1]());
361 CallSeqEndForStart.
clear();
362 assert(Interferences.
empty() && LRegsMap.empty() &&
"stale Interferences");
375 ListScheduleBottomUp();
380 dbgs() <<
"*** Final schedule ***\n";
392void ScheduleDAGRRList::ReleasePred(SUnit *SU,
const SDep *PredEdge) {
393 SUnit *PredSU = PredEdge->
getSUnit();
397 dbgs() <<
"*** Scheduling failed! ***\n";
399 dbgs() <<
" has been released too many times!\n";
405 if (!forceUnitLatencies()) {
417 if (Height < MinAvailableCycle)
418 MinAvailableCycle = Height;
420 if (isReady(PredSU)) {
421 AvailableQueue->
push(PredSU);
427 PendingQueue.push_back(PredSU);
451 if (
N->isMachineOpcode()) {
452 if (
N->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
454 }
else if (
N->getMachineOpcode() ==
TII->getCallFrameSetupOpcode()) {
462 if (
Op.getValueType() == MVT::Other) {
464 goto found_chain_operand;
467 found_chain_operand:;
491 unsigned BestMaxNest = MaxNest;
493 unsigned MyNestLevel = NestLevel;
494 unsigned MyMaxNest = MaxNest;
496 MyNestLevel, MyMaxNest,
TII))
497 if (!Best || (MyMaxNest > BestMaxNest)) {
499 BestMaxNest = MyMaxNest;
503 MaxNest = BestMaxNest;
507 if (
N->isMachineOpcode()) {
508 if (
N->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
510 MaxNest = std::max(MaxNest, NestLevel);
511 }
else if (
N->getMachineOpcode() ==
TII->getCallFrameSetupOpcode()) {
520 if (
Op.getValueType() == MVT::Other) {
522 goto found_chain_operand;
525 found_chain_operand:;
548void ScheduleDAGRRList::ReleasePredecessors(SUnit *SU) {
550 for (SDep &Pred : SU->
Preds) {
551 ReleasePred(SU, &Pred);
557 SUnit *RegDef = LiveRegDefs[Pred.
getReg()]; (void)RegDef;
559 "interference on register dependence");
561 if (!LiveRegGens[Pred.
getReg()]) {
563 LiveRegGens[Pred.
getReg()] = SU;
571 unsigned CallResource =
TRI->getNumRegs();
572 if (!LiveRegDefs[CallResource])
573 for (SDNode *Node = SU->
getNode(); Node; Node =
Node->getGluedNode())
574 if (
Node->isMachineOpcode() &&
575 Node->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
576 unsigned NestLevel = 0;
577 unsigned MaxNest = 0;
579 assert(
N &&
"Must find call sequence start");
581 SUnit *
Def = &SUnits[
N->getNodeId()];
582 CallSeqEndForStart[
Def] = SU;
585 LiveRegDefs[CallResource] =
Def;
586 LiveRegGens[CallResource] = SU;
593void ScheduleDAGRRList::ReleasePending() {
595 assert(PendingQueue.empty() &&
"pending instrs not allowed in this mode");
600 if (AvailableQueue->
empty())
601 MinAvailableCycle = std::numeric_limits<unsigned>::max();
605 for (
unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
606 unsigned ReadyCycle = PendingQueue[i]->getHeight();
607 if (ReadyCycle < MinAvailableCycle)
608 MinAvailableCycle = ReadyCycle;
610 if (PendingQueue[i]->isAvailable) {
611 if (!isReady(PendingQueue[i]))
613 AvailableQueue->
push(PendingQueue[i]);
615 PendingQueue[i]->isPending =
false;
616 PendingQueue[i] = PendingQueue.back();
617 PendingQueue.pop_back();
623void ScheduleDAGRRList::AdvanceToCycle(
unsigned NextCycle) {
624 if (NextCycle <= CurCycle)
631 CurCycle = NextCycle;
634 for (; CurCycle != NextCycle; ++CurCycle) {
645void ScheduleDAGRRList::AdvancePastStalls(SUnit *SU) {
662 AdvanceToCycle(ReadyCycle);
682 AdvanceToCycle(CurCycle + Stalls);
687void ScheduleDAGRRList::EmitNode(SUnit *SU) {
698 "This target-independent node should not be scheduled.");
731void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) {
736 if (CurCycle < SU->getHeight())
738 <<
"] pipeline stall!\n");
758 AdvanceToCycle(CurCycle + 1);
762 ReleasePredecessors(SU);
765 for (SDep &Succ : SU->
Succs) {
768 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
770 LiveRegDefs[Succ.
getReg()] =
nullptr;
771 LiveRegGens[Succ.
getReg()] =
nullptr;
772 releaseInterferences(Succ.
getReg());
777 unsigned CallResource =
TRI->getNumRegs();
778 if (LiveRegDefs[CallResource] == SU)
779 for (
const SDNode *SUNode = SU->
getNode(); SUNode;
781 if (SUNode->isMachineOpcode() &&
782 SUNode->getMachineOpcode() ==
TII->getCallFrameSetupOpcode()) {
783 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
785 LiveRegDefs[CallResource] =
nullptr;
786 LiveRegGens[CallResource] =
nullptr;
787 releaseInterferences(CallResource);
808 AdvanceToCycle(CurCycle + 1);
815void ScheduleDAGRRList::CapturePred(SDep *PredEdge) {
816 SUnit *PredSU = PredEdge->
getSUnit();
820 AvailableQueue->
remove(PredSU);
824 "NumSuccsLeft will overflow!");
830void ScheduleDAGRRList::UnscheduleNodeBottomUp(SUnit *SU) {
834 for (SDep &Pred : SU->
Preds) {
837 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
839 "Physical register dependency violated?");
841 LiveRegDefs[Pred.
getReg()] =
nullptr;
842 LiveRegGens[Pred.
getReg()] =
nullptr;
843 releaseInterferences(Pred.
getReg());
849 unsigned CallResource =
TRI->getNumRegs();
850 for (
const SDNode *SUNode = SU->
getNode(); SUNode;
852 if (SUNode->isMachineOpcode() &&
853 SUNode->getMachineOpcode() ==
TII->getCallFrameSetupOpcode()) {
854 SUnit *SeqEnd = CallSeqEndForStart[SU];
855 assert(SeqEnd &&
"Call sequence start/end must be known");
856 assert(!LiveRegDefs[CallResource]);
857 assert(!LiveRegGens[CallResource]);
859 LiveRegDefs[CallResource] = SU;
860 LiveRegGens[CallResource] = SeqEnd;
866 if (LiveRegGens[CallResource] == SU)
867 for (
const SDNode *SUNode = SU->
getNode(); SUNode;
869 if (SUNode->isMachineOpcode() &&
870 SUNode->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
871 assert(NumLiveRegs > 0 &&
"NumLiveRegs is already zero!");
872 assert(LiveRegDefs[CallResource]);
873 assert(LiveRegGens[CallResource]);
875 LiveRegDefs[CallResource] =
nullptr;
876 LiveRegGens[CallResource] =
nullptr;
877 releaseInterferences(CallResource);
881 for (
auto &Succ : SU->
Succs) {
884 if (!LiveRegDefs[
Reg])
888 LiveRegDefs[
Reg] = SU;
892 if (!LiveRegGens[
Reg]) {
895 for (
auto &Succ2 : SU->
Succs) {
896 if (Succ2.isAssignedRegDep() && Succ2.getReg() ==
Reg &&
897 Succ2.getSUnit()->getHeight() < LiveRegGens[
Reg]->getHeight())
898 LiveRegGens[
Reg] = Succ2.getSUnit();
912 PendingQueue.push_back(SU);
915 AvailableQueue->
push(SU);
922void ScheduleDAGRRList::RestoreHazardCheckerBottomUp() {
925 unsigned LookAhead = std::min((
unsigned)
Sequence.size(),
930 std::vector<SUnit *>::const_iterator
I = (
Sequence.end() - LookAhead);
931 unsigned HazardCycle = (*I)->getHeight();
934 for (; SU->
getHeight() > HazardCycle; ++HazardCycle) {
943void ScheduleDAGRRList::BacktrackBottomUp(SUnit *SU, SUnit *BtSU) {
949 UnscheduleNodeBottomUp(OldSU);
958 RestoreHazardCheckerBottomUp();
968 if (SUNode->isOperandOf(
N))
975SUnit *ScheduleDAGRRList::TryUnfoldSU(SUnit *SU) {
979 if (!
TII->unfoldMemoryOperand(*DAG,
N, NewNodes))
982 assert(NewNodes.
size() == 2 &&
"Expected a load folding node!");
985 SDNode *LoadNode = NewNodes[0];
986 unsigned NumVals =
N->getNumValues();
992 bool isNewLoad =
true;
1002 LoadSU = CreateNewSUnit(LoadNode);
1005 InitNumRegDefsLeft(LoadSU);
1006 computeLatency(LoadSU);
1012 if (
N->getNodeId() != -1) {
1013 NewSU = &SUnits[
N->getNodeId()];
1021 NewSU = CreateNewSUnit(
N);
1024 const MCInstrDesc &MCID =
TII->get(
N->getMachineOpcode());
1034 InitNumRegDefsLeft(NewSU);
1035 computeLatency(NewSU);
1041 for (
unsigned i = 0; i != NumVals; ++i)
1042 DAG->ReplaceAllUsesOfValueWith(SDValue(SU->
getNode(), i), SDValue(
N, i));
1043 DAG->ReplaceAllUsesOfValueWith(SDValue(SU->
getNode(), OldNumVals - 1),
1044 SDValue(LoadNode, 1));
1052 for (SDep &Pred : SU->
Preds) {
1060 for (SDep &Succ : SU->
Succs) {
1068 for (
const SDep &Pred : ChainPreds) {
1069 RemovePred(SU, Pred);
1071 AddPredQueued(LoadSU, Pred);
1073 for (
const SDep &Pred : LoadPreds) {
1074 RemovePred(SU, Pred);
1076 AddPredQueued(LoadSU, Pred);
1078 for (
const SDep &Pred : NodePreds) {
1079 RemovePred(SU, Pred);
1080 AddPredQueued(NewSU, Pred);
1082 for (SDep &
D : NodeSuccs) {
1083 SUnit *SuccDep =
D.getSUnit();
1085 RemovePred(SuccDep,
D);
1087 AddPredQueued(SuccDep,
D);
1093 for (SDep &
D : ChainSuccs) {
1094 SUnit *SuccDep =
D.getSUnit();
1096 RemovePred(SuccDep,
D);
1099 AddPredQueued(SuccDep,
D);
1107 AddPredQueued(NewSU,
D);
1110 AvailableQueue->
addNode(LoadSU);
1112 AvailableQueue->
addNode(NewSU);
1124SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
1132 if (
N->getGluedNode() &&
1133 !
TII->canCopyGluedNodeDuringSchedule(
N)) {
1136 <<
"Giving up because it has incoming glue and the target does not "
1137 "want to copy it\n");
1142 bool TryUnfold =
false;
1143 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
1144 MVT VT =
N->getSimpleValueType(i);
1145 if (VT == MVT::Glue) {
1146 LLVM_DEBUG(
dbgs() <<
"Giving up because it has outgoing glue\n");
1148 }
else if (VT == MVT::Other)
1151 for (
const SDValue &
Op :
N->op_values()) {
1152 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
1153 if (VT == MVT::Glue && !
TII->canCopyGluedNodeDuringSchedule(
N)) {
1155 dbgs() <<
"Giving up because it one of the operands is glue and "
1156 "the target does not want to copy it\n");
1163 SUnit *UnfoldSU = TryUnfoldSU(SU);
1174 NewSU = CreateClone(SU);
1177 for (SDep &Pred : SU->
Preds)
1179 AddPredQueued(NewSU, Pred);
1188 for (SDep &Succ : SU->
Succs) {
1195 AddPredQueued(SuccSU,
D);
1200 for (
const auto &[DelSU, DelD] : DelDeps)
1201 RemovePred(DelSU, DelD);
1204 AvailableQueue->
addNode(NewSU);
1212void ScheduleDAGRRList::InsertCopiesAndMoveSuccs(SUnit *SU,
unsigned Reg,
1215 SmallVectorImpl<SUnit*> &
Copies) {
1216 SUnit *CopyFromSU = CreateNewSUnit(
nullptr);
1220 SUnit *CopyToSU = CreateNewSUnit(
nullptr);
1227 for (SDep &Succ : SU->
Succs) {
1234 AddPredQueued(SuccSU,
D);
1244 for (
const auto &[DelSU, DelD] : DelDeps)
1245 RemovePred(DelSU, DelD);
1248 FromDep.setLatency(SU->
Latency);
1249 AddPredQueued(CopyFromSU, FromDep);
1251 ToDep.setLatency(CopyFromSU->
Latency);
1252 AddPredQueued(CopyToSU, ToDep);
1255 AvailableQueue->
addNode(CopyFromSU);
1256 AvailableQueue->
addNode(CopyToSU);
1257 Copies.push_back(CopyFromSU);
1258 Copies.push_back(CopyToSU);
1273 if (!LiveRegDefs[*AliasI])
continue;
1276 if (LiveRegDefs[*AliasI] == SU)
continue;
1283 if (RegAdded.
insert(*AliasI).second) {
1296 for (
unsigned i = 1, e = LiveRegDefs.
size()-1; i != e; ++i) {
1297 if (!LiveRegDefs[i])
continue;
1298 if (LiveRegDefs[i] == SU)
continue;
1300 if (RegAdded.
insert(i).second)
1309 return RegOp->getRegMask();
1317bool ScheduleDAGRRList::
1318DelayForLiveRegsBottomUp(SUnit *SU, SmallVectorImpl<unsigned> &LRegs) {
1319 if (NumLiveRegs == 0)
1322 SmallSet<unsigned, 4> RegAdded;
1327 for (SDep &Pred : SU->
Preds) {
1330 RegAdded, LRegs,
TRI);
1333 for (SDNode *Node = SU->
getNode(); Node; Node =
Node->getGluedNode()) {
1338 if (
Node->getOperand(
NumOps-1).getValueType() == MVT::Glue)
1342 unsigned Flags =
Node->getConstantOperandVal(i);
1343 const InlineAsm::Flag
F(Flags);
1344 unsigned NumVals =
F.getNumOperandRegisters();
1347 if (
F.isRegDefKind() ||
F.isRegDefEarlyClobberKind() ||
1348 F.isClobberKind()) {
1350 for (; NumVals; --NumVals, ++i) {
1364 SDNode *SrcNode =
Node->getOperand(2).getNode();
1370 if (!
Node->isMachineOpcode())
1375 if (
Node->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
1377 unsigned CallResource =
TRI->getNumRegs();
1378 if (LiveRegDefs[CallResource]) {
1379 SDNode *Gen = LiveRegGens[CallResource]->getNode();
1383 RegAdded.
insert(CallResource).second)
1392 const MCInstrDesc &MCID =
TII->get(
Node->getMachineOpcode());
1398 for (
unsigned i = 0; i < MCID.
getNumDefs(); ++i)
1399 if (MCID.
operands()[i].isOptionalDef()) {
1409 return !LRegs.
empty();
1412void ScheduleDAGRRList::releaseInterferences(
unsigned Reg) {
1414 for (
unsigned i = Interferences.
size(); i > 0; --i) {
1415 SUnit *SU = Interferences[i-1];
1416 LRegsMapT::iterator LRegsPos = LRegsMap.find(SU);
1418 SmallVectorImpl<unsigned> &LRegs = LRegsPos->second;
1428 AvailableQueue->
push(SU);
1430 if (i < Interferences.
size())
1431 Interferences[i-1] = Interferences.
back();
1433 LRegsMap.erase(LRegsPos);
1441SUnit *ScheduleDAGRRList::PickNodeToScheduleBottomUp() {
1442 SUnit *CurSU = AvailableQueue->
empty() ? nullptr : AvailableQueue->
pop();
1443 auto FindAvailableNode = [&]() {
1445 SmallVector<unsigned, 4> LRegs;
1446 if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
1449 if (LRegs[0] ==
TRI->getNumRegs())
dbgs() <<
"CallResource";
1452 auto [LRegsIter, LRegsInserted] = LRegsMap.try_emplace(CurSU, LRegs);
1453 if (LRegsInserted) {
1460 LRegsIter->second = LRegs;
1462 CurSU = AvailableQueue->
pop();
1465 FindAvailableNode();
1477 for (SUnit *TrySU : Interferences) {
1478 SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU];
1482 SUnit *BtSU =
nullptr;
1483 unsigned LiveCycle = std::numeric_limits<unsigned>::max();
1484 for (
unsigned Reg : LRegs) {
1485 if (LiveRegGens[
Reg]->getHeight() < LiveCycle) {
1486 BtSU = LiveRegGens[
Reg];
1490 if (!WillCreateCycle(TrySU, BtSU)) {
1492 BacktrackBottomUp(TrySU, BtSU);
1499 AvailableQueue->
remove(BtSU);
1502 <<
") to SU(" << TrySU->NodeNum <<
")\n");
1507 if (!TrySU->isAvailable || !TrySU->NodeQueueId) {
1508 LLVM_DEBUG(
dbgs() <<
"TrySU not available; choosing node from queue\n");
1509 CurSU = AvailableQueue->
pop();
1513 AvailableQueue->
remove(TrySU);
1516 FindAvailableNode();
1528 SUnit *TrySU = Interferences[0];
1529 SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU];
1530 assert(LRegs.
size() == 1 &&
"Can't handle this yet!");
1531 unsigned Reg = LRegs[0];
1532 SUnit *LRDef = LiveRegDefs[
Reg];
1543 SUnit *NewDef =
nullptr;
1545 NewDef = CopyAndMoveSuccessors(LRDef);
1546 if (!DestRC && !NewDef)
1552 InsertCopiesAndMoveSuccs(LRDef,
Reg, DestRC, RC,
Copies);
1554 <<
" to SU #" <<
Copies.front()->NodeNum <<
"\n");
1560 <<
" to SU #" << TrySU->
NodeNum <<
"\n");
1561 LiveRegDefs[
Reg] = NewDef;
1566 assert(CurSU &&
"Unable to resolve live physical register dependencies!");
1572void ScheduleDAGRRList::ListScheduleBottomUp() {
1574 ReleasePredecessors(&ExitSU);
1577 if (!SUnits.empty()) {
1578 SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];
1579 assert(RootSU->
Succs.empty() &&
"Graph root shouldn't have successors!");
1581 AvailableQueue->
push(RootSU);
1587 while (!AvailableQueue->
empty() || !Interferences.empty()) {
1589 AvailableQueue->
dump(
this));
1593 SUnit *SU = PickNodeToScheduleBottomUp();
1595 AdvancePastStalls(SU);
1597 ScheduleNodeBottomUp(SU);
1599 while (AvailableQueue->
empty() && !PendingQueue.empty()) {
1601 assert(MinAvailableCycle < std::numeric_limits<unsigned>::max() &&
1602 "MinAvailableCycle uninitialized");
1603 AdvanceToCycle(std::max(CurCycle + 1, MinAvailableCycle));
1611 VerifyScheduledSequence(
true);
1617class RegReductionPQBase;
1620 bool isReady(SUnit* SU,
unsigned CurCycle)
const {
return true; }
1625struct reverse_sort :
public queue_sort {
1628 reverse_sort(SF &sf) : SortFunc(sf) {}
1630 bool operator()(SUnit* left, SUnit* right)
const {
1633 return SortFunc(right, left);
1640struct bu_ls_rr_sort :
public queue_sort {
1643 HasReadyFilter =
false
1646 RegReductionPQBase *SPQ;
1648 bu_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1650 bool operator()(SUnit* left, SUnit* right)
const;
1654struct src_ls_rr_sort :
public queue_sort {
1657 HasReadyFilter =
false
1660 RegReductionPQBase *SPQ;
1662 src_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1664 bool operator()(SUnit* left, SUnit* right)
const;
1668struct hybrid_ls_rr_sort :
public queue_sort {
1671 HasReadyFilter =
false
1674 RegReductionPQBase *SPQ;
1676 hybrid_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1678 bool isReady(SUnit *SU,
unsigned CurCycle)
const;
1680 bool operator()(SUnit* left, SUnit* right)
const;
1685struct ilp_ls_rr_sort :
public queue_sort {
1688 HasReadyFilter =
false
1691 RegReductionPQBase *SPQ;
1693 ilp_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1695 bool isReady(SUnit *SU,
unsigned CurCycle)
const;
1697 bool operator()(SUnit* left, SUnit* right)
const;
1700class RegReductionPQBase :
public SchedulingPriorityQueue {
1702 std::vector<SUnit *> Queue;
1703 unsigned CurQueueId = 0;
1704 bool TracksRegPressure;
1708 std::vector<SUnit> *SUnits =
nullptr;
1711 const TargetInstrInfo *
TII =
nullptr;
1712 const TargetRegisterInfo *
TRI =
nullptr;
1713 const TargetLowering *TLI =
nullptr;
1714 ScheduleDAGRRList *scheduleDAG =
nullptr;
1717 std::vector<unsigned> SethiUllmanNumbers;
1720 std::vector<unsigned> RegPressure;
1724 std::vector<unsigned> RegLimit;
1728 bool hasReadyFilter,
1731 const TargetInstrInfo *tii,
1732 const TargetRegisterInfo *tri,
1733 const TargetLowering *tli)
1734 : SchedulingPriorityQueue(hasReadyFilter), TracksRegPressure(tracksrp),
1735 SrcOrder(srcorder), MF(mf),
TII(tii),
TRI(tri), TLI(tli) {
1736 if (TracksRegPressure) {
1737 unsigned NumRC =
TRI->getNumRegClasses();
1738 RegLimit.resize(NumRC);
1747 void setScheduleDAG(ScheduleDAGRRList *scheduleDag) {
1748 scheduleDAG = scheduleDag;
1751 ScheduleHazardRecognizer* getHazardRec() {
1752 return scheduleDAG->getHazardRec();
1755 void initNodes(std::vector<SUnit> &sunits)
override;
1757 void addNode(
const SUnit *SU)
override;
1759 void updateNode(
const SUnit *SU)
override;
1761 void releaseState()
override {
1763 SethiUllmanNumbers.clear();
1767 unsigned getNodePriority(
const SUnit *SU)
const;
1769 unsigned getNodeOrdering(
const SUnit *SU)
const {
1775 bool empty()
const override {
return Queue.empty(); }
1777 void push(SUnit *U)
override {
1778 assert(!
U->NodeQueueId &&
"Node in the queue already");
1779 U->NodeQueueId = ++CurQueueId;
1783 void remove(SUnit *SU)
override {
1786 std::vector<SUnit *>::iterator
I =
llvm::find(Queue, SU);
1787 if (
I != std::prev(
Queue.end()))
1793 bool tracksRegPressure()
const override {
return TracksRegPressure; }
1795 void dumpRegPressure()
const;
1797 bool HighRegPressure(
const SUnit *SU)
const;
1799 bool MayReduceRegPressure(SUnit *SU)
const;
1801 int RegPressureDiff(SUnit *SU,
unsigned &LiveUses)
const;
1803 void scheduledNode(SUnit *SU)
override;
1805 void unscheduledNode(SUnit *SU)
override;
1808 bool canClobber(
const SUnit *SU,
const SUnit *
Op);
1809 void AddPseudoTwoAddrDeps();
1810 void PrescheduleNodesWithMultipleUses();
1811 void CalculateSethiUllmanNumbers();
1815static SUnit *popFromQueueImpl(std::vector<SUnit *> &Q, SF &Picker) {
1816 unsigned BestIdx = 0;
1819 for (
unsigned I = 1,
E = std::min(Q.size(), (
decltype(Q.size()))1000);
I !=
E;
1821 if (Picker(Q[BestIdx], Q[
I]))
1823 SUnit *
V = Q[BestIdx];
1824 if (BestIdx + 1 != Q.size())
1831SUnit *popFromQueue(std::vector<SUnit *> &Q, SF &Picker, ScheduleDAG *DAG) {
1834 reverse_sort<SF> RPicker(Picker);
1835 return popFromQueueImpl(Q, RPicker);
1839 return popFromQueueImpl(Q, Picker);
1850class RegReductionPriorityQueue :
public RegReductionPQBase {
1857 const TargetInstrInfo *tii,
1858 const TargetRegisterInfo *tri,
1859 const TargetLowering *tli)
1860 : RegReductionPQBase(mf, SF::HasReadyFilter, tracksrp, srcorder,
1864 bool isBottomUp()
const override {
return SF::IsBottomUp; }
1866 bool isReady(SUnit *U)
const override {
1867 return Picker.HasReadyFilter && Picker.isReady(U, getCurCycle());
1870 SUnit *pop()
override {
1871 if (
Queue.empty())
return nullptr;
1873 SUnit *
V = popFromQueue(Queue, Picker, scheduleDAG);
1878#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1881 std::vector<SUnit *> DumpQueue =
Queue;
1882 SF DumpPicker = Picker;
1883 while (!DumpQueue.empty()) {
1884 SUnit *SU = popFromQueue(DumpQueue, DumpPicker, scheduleDAG);
1892using BURegReductionPriorityQueue = RegReductionPriorityQueue<bu_ls_rr_sort>;
1893using SrcRegReductionPriorityQueue = RegReductionPriorityQueue<src_ls_rr_sort>;
1894using HybridBURRPriorityQueue = RegReductionPriorityQueue<hybrid_ls_rr_sort>;
1895using ILPBURRPriorityQueue = RegReductionPriorityQueue<ilp_ls_rr_sort>;
1912 if (LSchedLow != RSchedLow)
1913 return LSchedLow < RSchedLow ? 1 : -1;
1921 if (SUNumbers[SU->
NodeNum] != 0)
1922 return SUNumbers[SU->
NodeNum];
1926 WorkState(
const SUnit *SU) : SU(SU) {}
1928 unsigned PredsProcessed = 0;
1933 while (!WorkList.
empty()) {
1934 auto &Temp = WorkList.
back();
1935 auto *TempSU = Temp.SU;
1936 bool AllPredsKnown =
true;
1938 for (
unsigned P = Temp.PredsProcessed;
P < TempSU->Preds.size(); ++
P) {
1939 auto &Pred = TempSU->Preds[
P];
1940 if (Pred.isCtrl())
continue;
1941 SUnit *PredSU = Pred.getSUnit();
1942 if (SUNumbers[PredSU->
NodeNum] == 0) {
1945 for (
auto It : WorkList)
1946 assert(It.SU != PredSU &&
"Trying to push an element twice?");
1949 Temp.PredsProcessed =
P + 1;
1950 WorkList.push_back(PredSU);
1951 AllPredsKnown =
false;
1960 unsigned SethiUllmanNumber = 0;
1962 for (
const SDep &Pred : TempSU->Preds) {
1963 if (Pred.isCtrl())
continue;
1964 SUnit *PredSU = Pred.getSUnit();
1965 unsigned PredSethiUllman = SUNumbers[PredSU->
NodeNum];
1966 assert(PredSethiUllman > 0 &&
"We should have evaluated this pred!");
1967 if (PredSethiUllman > SethiUllmanNumber) {
1968 SethiUllmanNumber = PredSethiUllman;
1970 }
else if (PredSethiUllman == SethiUllmanNumber)
1974 SethiUllmanNumber += Extra;
1975 if (SethiUllmanNumber == 0)
1976 SethiUllmanNumber = 1;
1977 SUNumbers[TempSU->NodeNum] = SethiUllmanNumber;
1981 assert(SUNumbers[SU->
NodeNum] > 0 &&
"SethiUllman should never be zero!");
1982 return SUNumbers[SU->
NodeNum];
1987void RegReductionPQBase::CalculateSethiUllmanNumbers() {
1988 SethiUllmanNumbers.assign(SUnits->size(), 0);
1990 for (
const SUnit &SU : *SUnits)
1994void RegReductionPQBase::addNode(
const SUnit *SU) {
1995 unsigned SUSize = SethiUllmanNumbers.size();
1996 if (SUnits->size() > SUSize)
1997 SethiUllmanNumbers.resize(SUSize*2, 0);
2001void RegReductionPQBase::updateNode(
const SUnit *SU) {
2002 SethiUllmanNumbers[SU->
NodeNum] = 0;
2008unsigned RegReductionPQBase::getNodePriority(
const SUnit *SU)
const {
2015 if (
Opc == TargetOpcode::EXTRACT_SUBREG ||
2016 Opc == TargetOpcode::SUBREG_TO_REG ||
2017 Opc == TargetOpcode::INSERT_SUBREG)
2033 return SethiUllmanNumbers[SU->
NodeNum];
2035 unsigned Priority = SethiUllmanNumbers[SU->
NodeNum];
2039 return (NP > 0) ? NP : 0;
2049#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2056 << RegLimit[Id] <<
'\n');
2061bool RegReductionPQBase::HighRegPressure(
const SUnit *SU)
const {
2065 for (
const SDep &Pred : SU->
Preds) {
2074 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
2075 RegDefPos.IsValid(); RegDefPos.Advance()) {
2076 unsigned RCId,
Cost;
2079 if ((RegPressure[RCId] +
Cost) >= RegLimit[RCId])
2086bool RegReductionPQBase::MayReduceRegPressure(SUnit *SU)
const {
2089 if (!
N->isMachineOpcode() || !SU->
NumSuccs)
2092 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2093 for (
unsigned i = 0; i != NumDefs; ++i) {
2094 MVT VT =
N->getSimpleValueType(i);
2095 if (!
N->hasAnyUseOfValue(i))
2098 if (RegPressure[RCId] >= RegLimit[RCId])
2111int RegReductionPQBase::RegPressureDiff(SUnit *SU,
unsigned &LiveUses)
const {
2114 for (
const SDep &Pred : SU->
Preds) {
2125 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
2126 RegDefPos.IsValid(); RegDefPos.Advance()) {
2127 MVT VT = RegDefPos.GetValue();
2129 if (RegPressure[RCId] >= RegLimit[RCId])
2135 if (!
N || !
N->isMachineOpcode() || !SU->
NumSuccs)
2138 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2139 for (
unsigned i = 0; i != NumDefs; ++i) {
2140 MVT VT =
N->getSimpleValueType(i);
2141 if (!
N->hasAnyUseOfValue(i))
2144 if (RegPressure[RCId] >= RegLimit[RCId])
2150void RegReductionPQBase::scheduledNode(SUnit *SU) {
2151 if (!TracksRegPressure)
2157 for (
const SDep &Pred : SU->
Preds) {
2183 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
2184 RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) {
2188 unsigned RCId,
Cost;
2199 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(SU, scheduleDAG);
2200 RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) {
2201 if (SkipRegDefs > 0)
2203 unsigned RCId,
Cost;
2205 if (RegPressure[RCId] <
Cost) {
2209 <<
") has too many regdefs\n");
2219void RegReductionPQBase::unscheduledNode(SUnit *SU) {
2220 if (!TracksRegPressure)
2226 if (!
N->isMachineOpcode()) {
2230 unsigned Opc =
N->getMachineOpcode();
2231 if (
Opc == TargetOpcode::EXTRACT_SUBREG ||
2232 Opc == TargetOpcode::INSERT_SUBREG ||
2233 Opc == TargetOpcode::SUBREG_TO_REG ||
2234 Opc == TargetOpcode::REG_SEQUENCE ||
2235 Opc == TargetOpcode::IMPLICIT_DEF)
2239 for (
const SDep &Pred : SU->
Preds) {
2247 const SDNode *PN = PredSU->
getNode();
2257 if (POpc == TargetOpcode::IMPLICIT_DEF)
2259 if (POpc == TargetOpcode::EXTRACT_SUBREG ||
2260 POpc == TargetOpcode::INSERT_SUBREG ||
2261 POpc == TargetOpcode::SUBREG_TO_REG) {
2267 if (POpc == TargetOpcode::REG_SEQUENCE) {
2270 unsigned RCId = RC->
getID();
2277 for (
unsigned i = 0; i != NumDefs; ++i) {
2292 if (SU->
NumSuccs &&
N->isMachineOpcode()) {
2293 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2294 for (
unsigned i = NumDefs, e =
N->getNumValues(); i != e; ++i) {
2295 MVT VT =
N->getSimpleValueType(i);
2296 if (VT == MVT::Glue || VT == MVT::Other)
2298 if (!
N->hasAnyUseOfValue(i))
2315 unsigned MaxHeight = 0;
2317 if (Succ.
isCtrl())
continue;
2324 if (Height > MaxHeight)
2333 unsigned Scratches = 0;
2335 if (Pred.isCtrl())
continue;
2344 bool RetVal =
false;
2346 if (Pred.isCtrl())
continue;
2347 const SUnit *PredSU = Pred.getSUnit();
2352 if (
Reg.isVirtual()) {
2366 bool RetVal =
false;
2368 if (Succ.
isCtrl())
continue;
2373 if (
Reg.isVirtual()) {
2405 if (Pred.isCtrl())
continue;
2406 Pred.getSUnit()->isVRegCycle =
true;
2417 if (Pred.isCtrl())
continue;
2418 SUnit *PredSU = Pred.getSUnit();
2421 "VRegCycle def must be CopyFromReg");
2422 Pred.getSUnit()->isVRegCycle =
false;
2435 if (Pred.isCtrl())
continue;
2436 if (Pred.getSUnit()->isVRegCycle &&
2449 if ((
int)SPQ->getCurCycle() < Height)
return true;
2450 if (SPQ->getHazardRec()->getHazardType(SU, 0)
2459 RegReductionPQBase *SPQ) {
2464 int LHeight = (int)left->
getHeight() + LPenalty;
2465 int RHeight = (int)right->
getHeight() + RPenalty;
2478 if (LHeight != RHeight)
2479 return LHeight > RHeight ? 1 : -1;
2491 if (!SPQ->getHazardRec()->isEnabled()) {
2492 if (LHeight != RHeight)
2493 return LHeight > RHeight ? 1 : -1;
2495 int LDepth = left->
getDepth() - LPenalty;
2496 int RDepth = right->
getDepth() - RPenalty;
2497 if (LDepth != RDepth) {
2499 <<
") depth " << LDepth <<
" vs SU (" << right->
NodeNum
2500 <<
") depth " << RDepth <<
"\n");
2501 return LDepth < RDepth ? 1 : -1;
2517 if (LHasPhysReg != RHasPhysReg) {
2519 static const char *
const PhysRegMsg[] = {
" has no physreg",
2520 " defines a physreg" };
2523 << PhysRegMsg[LHasPhysReg] <<
" SU(" << right->
NodeNum
2524 <<
") " << PhysRegMsg[RHasPhysReg] <<
"\n");
2525 return LHasPhysReg < RHasPhysReg;
2530 unsigned LPriority = SPQ->getNodePriority(left);
2531 unsigned RPriority = SPQ->getNodePriority(right);
2537 RPriority = (RPriority > RNumVals) ? (RPriority - RNumVals) : 0;
2541 LPriority = (LPriority > LNumVals) ? (LPriority - LNumVals) : 0;
2544 if (LPriority != RPriority)
2545 return LPriority > RPriority;
2550 unsigned LOrder = SPQ->getNodeOrdering(left);
2551 unsigned ROrder = SPQ->getNodeOrdering(right);
2555 if ((LOrder || ROrder) && LOrder != ROrder)
2556 return LOrder != 0 && (LOrder < ROrder || ROrder == 0);
2579 return LDist < RDist;
2584 if (LScratch != RScratch)
2585 return LScratch > RScratch;
2589 if ((left->
isCall && RPriority > 0) || (right->
isCall && LPriority > 0))
2608 "NodeQueueId cannot be zero");
2613bool bu_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2621bool src_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2625 unsigned LOrder = SPQ->getNodeOrdering(left);
2626 unsigned ROrder = SPQ->getNodeOrdering(right);
2630 if ((LOrder || ROrder) && LOrder != ROrder)
2631 return LOrder != 0 && (LOrder < ROrder || ROrder == 0);
2640bool hybrid_ls_rr_sort::isReady(SUnit *SU,
unsigned CurCycle)
const {
2641 static const unsigned ReadyDelay = 3;
2643 if (SPQ->MayReduceRegPressure(SU))
return true;
2645 if (SU->
getHeight() > (CurCycle + ReadyDelay))
return false;
2647 if (SPQ->getHazardRec()->getHazardType(SU, -ReadyDelay)
2655bool hybrid_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2663 bool LHigh = SPQ->HighRegPressure(left);
2664 bool RHigh = SPQ->HighRegPressure(right);
2667 if (LHigh && !RHigh) {
2672 else if (!LHigh && RHigh) {
2677 if (!LHigh && !RHigh) {
2687bool ilp_ls_rr_sort::isReady(SUnit *SU,
unsigned CurCycle)
const {
2688 if (SU->
getHeight() > CurCycle)
return false;
2690 if (SPQ->getHazardRec()->getHazardType(SU, 0)
2704 if (
Opc == TargetOpcode::EXTRACT_SUBREG ||
2705 Opc == TargetOpcode::SUBREG_TO_REG ||
2706 Opc == TargetOpcode::INSERT_SUBREG)
2721bool ilp_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2729 unsigned LLiveUses = 0, RLiveUses = 0;
2730 int LPDiff = 0, RPDiff = 0;
2732 LPDiff = SPQ->RegPressureDiff(left, LLiveUses);
2733 RPDiff = SPQ->RegPressureDiff(right, RLiveUses);
2737 <<
"): " << LPDiff <<
" != SU(" << right->
NodeNum
2738 <<
"): " << RPDiff <<
"\n");
2739 return LPDiff > RPDiff;
2745 if (LReduce && !RReduce)
return false;
2746 if (RReduce && !LReduce)
return true;
2751 <<
" != SU(" << right->
NodeNum <<
"): " << RLiveUses
2753 return LLiveUses < RLiveUses;
2759 if (LStall != RStall)
2768 <<
"): " << right->
getDepth() <<
"\n");
2782void RegReductionPQBase::initNodes(std::vector<SUnit> &sunits) {
2786 AddPseudoTwoAddrDeps();
2788 if (!TracksRegPressure && !SrcOrder)
2789 PrescheduleNodesWithMultipleUses();
2791 CalculateSethiUllmanNumbers();
2794 if (scheduleDAG->BB->isSuccessor(scheduleDAG->BB))
2795 for (SUnit &SU : sunits)
2803bool RegReductionPQBase::canClobber(
const SUnit *SU,
const SUnit *
Op) {
2806 const MCInstrDesc &MCID =
TII->get(
Opc);
2809 for (
unsigned i = 0; i !=
NumOps; ++i) {
2825 ScheduleDAGRRList *scheduleDAG,
2831 if (ImpDefs.
empty() && !RegMask)
2836 for (
const SDep &SuccPred : SuccSU->
Preds) {
2842 scheduleDAG->IsReachable(DepSU, SuccPred.
getSUnit()))
2849 if (
TRI->regsOverlap(ImpDef, SuccPred.
getReg()) &&
2850 scheduleDAG->IsReachable(DepSU, SuccPred.
getSUnit()))
2864 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2866 assert(!ImpDefs.
empty() &&
"Caller should check hasPhysRegDefs");
2869 if (!SUNode->isMachineOpcode())
2872 TII->get(SUNode->getMachineOpcode()).implicit_defs();
2874 if (SUImpDefs.
empty() && !SURegMask)
2876 for (
unsigned i = NumDefs, e =
N->getNumValues(); i != e; ++i) {
2877 MVT VT =
N->getSimpleValueType(i);
2878 if (VT == MVT::Glue || VT == MVT::Other)
2880 if (!
N->hasAnyUseOfValue(i))
2886 if (
TRI->regsOverlap(
Reg, SUReg))
2924void RegReductionPQBase::PrescheduleNodesWithMultipleUses() {
2926 for (SUnit &SU : *SUnits) {
2942 SDNode *PredFrameSetup =
nullptr;
2943 for (
const SDep &Pred : SU.
Preds)
2957 PredFrameSetup = PredND;
2962 if (PredFrameSetup !=
nullptr)
2966 SUnit *PredSU =
nullptr;
2967 for (
const SDep &Pred : SU.
Preds)
2989 for (
const SDep &PredSucc : PredSU->
Succs) {
2990 SUnit *PredSuccSU = PredSucc.
getSUnit();
2991 if (PredSuccSU == &SU)
continue;
2995 goto outer_loop_continue;
2999 goto outer_loop_continue;
3001 if (scheduleDAG->IsReachable(&SU, PredSuccSU))
3002 goto outer_loop_continue;
3008 dbgs() <<
" Prescheduling SU #" << SU.
NodeNum <<
" next to PredSU #"
3010 <<
" to guide scheduling in the presence of multiple uses\n");
3011 for (
unsigned i = 0; i != PredSU->
Succs.size(); ++i) {
3014 SUnit *SuccSU =
Edge.getSUnit();
3015 if (SuccSU != &SU) {
3016 Edge.setSUnit(PredSU);
3017 scheduleDAG->RemovePred(SuccSU,
Edge);
3018 scheduleDAG->AddPredQueued(&SU,
Edge);
3020 scheduleDAG->AddPredQueued(SuccSU,
Edge);
3024 outer_loop_continue:;
3035void RegReductionPQBase::AddPseudoTwoAddrDeps() {
3036 for (SUnit &SU : *SUnits) {
3045 unsigned Opc =
Node->getMachineOpcode();
3046 const MCInstrDesc &MCID =
TII->get(
Opc);
3049 for (
unsigned j = 0;
j !=
NumOps; ++
j) {
3055 const SUnit *DUSU = &(*SUnits)[DU->
getNodeId()];
3058 for (
const SDep &Succ : DUSU->
Succs) {
3073 while (SuccSU->
Succs.size() == 1 &&
3076 TargetOpcode::COPY_TO_REGCLASS)
3077 SuccSU = SuccSU->
Succs.front().getSUnit();
3090 if (SuccOpc == TargetOpcode::EXTRACT_SUBREG ||
3091 SuccOpc == TargetOpcode::INSERT_SUBREG ||
3092 SuccOpc == TargetOpcode::SUBREG_TO_REG)
3095 (!canClobber(SuccSU, DUSU) ||
3098 !scheduleDAG->IsReachable(SuccSU, &SU)) {
3100 <<
" Adding a pseudo-two-addr edge from SU #"
3119 BURegReductionPriorityQueue *PQ =
3120 new BURegReductionPriorityQueue(*IS->MF,
false,
false,
TII,
TRI,
nullptr);
3121 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->MF,
false, PQ, OptLevel);
3122 PQ->setScheduleDAG(SD);
3133 SrcRegReductionPriorityQueue *PQ =
3134 new SrcRegReductionPriorityQueue(*IS->MF,
false,
true,
TII,
TRI,
nullptr);
3135 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->MF,
false, PQ, OptLevel);
3136 PQ->setScheduleDAG(SD);
3148 HybridBURRPriorityQueue *PQ =
3149 new HybridBURRPriorityQueue(*IS->MF,
true,
false,
TII,
TRI, TLI);
3151 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->MF,
true, PQ, OptLevel);
3152 PQ->setScheduleDAG(SD);
3163 ILPBURRPriorityQueue *PQ =
3164 new ILPBURRPriorityQueue(*IS->MF,
true,
false,
TII,
TRI, TLI);
3165 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->MF,
true, PQ, OptLevel);
3166 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.
unsigned getID() const
getID() - Return the register class ID number.
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...
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...
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.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.