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();
997 assert(
N->getNodeId() == -1 &&
"Node using a new load can't exist yet!");
999 SUnit *LoadSU = CreateNewSUnit(LoadNode);
1001 InitNumRegDefsLeft(LoadSU);
1002 computeLatency(LoadSU);
1004 SUnit *NewSU = CreateNewSUnit(
N);
1007 const MCInstrDesc &MCID =
TII->get(
N->getMachineOpcode());
1017 InitNumRegDefsLeft(NewSU);
1018 computeLatency(NewSU);
1023 for (
unsigned i = 0; i != NumVals; ++i)
1024 DAG->ReplaceAllUsesOfValueWith(SDValue(SU->
getNode(), i), SDValue(
N, i));
1025 DAG->ReplaceAllUsesOfValueWith(SDValue(SU->
getNode(), OldNumVals - 1),
1026 SDValue(LoadNode, 1));
1034 for (SDep &Pred : SU->
Preds) {
1042 for (SDep &Succ : SU->
Succs) {
1050 for (
const SDep &Pred : ChainPreds) {
1051 RemovePred(SU, Pred);
1052 AddPredQueued(LoadSU, Pred);
1054 for (
const SDep &Pred : LoadPreds) {
1055 RemovePred(SU, Pred);
1056 AddPredQueued(LoadSU, Pred);
1058 for (
const SDep &Pred : NodePreds) {
1059 RemovePred(SU, Pred);
1060 AddPredQueued(NewSU, Pred);
1062 for (SDep &
D : NodeSuccs) {
1063 SUnit *SuccDep =
D.getSUnit();
1065 RemovePred(SuccDep,
D);
1067 AddPredQueued(SuccDep,
D);
1073 for (SDep &
D : ChainSuccs) {
1074 SUnit *SuccDep =
D.getSUnit();
1076 RemovePred(SuccDep,
D);
1078 AddPredQueued(SuccDep,
D);
1085 AddPredQueued(NewSU,
D);
1087 AvailableQueue->
addNode(LoadSU);
1088 AvailableQueue->
addNode(NewSU);
1100SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
1108 if (
N->getGluedNode() &&
1109 !
TII->canCopyGluedNodeDuringSchedule(
N)) {
1112 <<
"Giving up because it has incoming glue and the target does not "
1113 "want to copy it\n");
1118 bool TryUnfold =
false;
1119 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
1120 MVT VT =
N->getSimpleValueType(i);
1121 if (VT == MVT::Glue) {
1122 LLVM_DEBUG(
dbgs() <<
"Giving up because it has outgoing glue\n");
1124 }
else if (VT == MVT::Other)
1127 for (
const SDValue &
Op :
N->op_values()) {
1128 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
1129 if (VT == MVT::Glue && !
TII->canCopyGluedNodeDuringSchedule(
N)) {
1131 dbgs() <<
"Giving up because it one of the operands is glue and "
1132 "the target does not want to copy it\n");
1139 SUnit *UnfoldSU = TryUnfoldSU(SU);
1150 NewSU = CreateClone(SU);
1153 for (SDep &Pred : SU->
Preds)
1155 AddPredQueued(NewSU, Pred);
1164 for (SDep &Succ : SU->
Succs) {
1171 AddPredQueued(SuccSU,
D);
1176 for (
const auto &[DelSU, DelD] : DelDeps)
1177 RemovePred(DelSU, DelD);
1180 AvailableQueue->
addNode(NewSU);
1188void ScheduleDAGRRList::InsertCopiesAndMoveSuccs(SUnit *SU,
unsigned Reg,
1191 SmallVectorImpl<SUnit*> &
Copies) {
1192 SUnit *CopyFromSU = CreateNewSUnit(
nullptr);
1196 SUnit *CopyToSU = CreateNewSUnit(
nullptr);
1203 for (SDep &Succ : SU->
Succs) {
1210 AddPredQueued(SuccSU,
D);
1220 for (
const auto &[DelSU, DelD] : DelDeps)
1221 RemovePred(DelSU, DelD);
1224 FromDep.setLatency(SU->
Latency);
1225 AddPredQueued(CopyFromSU, FromDep);
1227 ToDep.setLatency(CopyFromSU->
Latency);
1228 AddPredQueued(CopyToSU, ToDep);
1231 AvailableQueue->
addNode(CopyFromSU);
1232 AvailableQueue->
addNode(CopyToSU);
1233 Copies.push_back(CopyFromSU);
1234 Copies.push_back(CopyToSU);
1249 if (!LiveRegDefs[*AliasI])
continue;
1252 if (LiveRegDefs[*AliasI] == SU)
continue;
1259 if (RegAdded.
insert(*AliasI).second) {
1272 for (
unsigned i = 1, e = LiveRegDefs.
size()-1; i != e; ++i) {
1273 if (!LiveRegDefs[i])
continue;
1274 if (LiveRegDefs[i] == SU)
continue;
1276 if (RegAdded.
insert(i).second)
1285 return RegOp->getRegMask();
1293bool ScheduleDAGRRList::
1294DelayForLiveRegsBottomUp(SUnit *SU, SmallVectorImpl<unsigned> &LRegs) {
1295 if (NumLiveRegs == 0)
1298 SmallSet<unsigned, 4> RegAdded;
1303 for (SDep &Pred : SU->
Preds) {
1306 RegAdded, LRegs,
TRI);
1309 for (SDNode *Node = SU->
getNode(); Node; Node =
Node->getGluedNode()) {
1314 if (
Node->getOperand(
NumOps-1).getValueType() == MVT::Glue)
1318 unsigned Flags =
Node->getConstantOperandVal(i);
1319 const InlineAsm::Flag
F(Flags);
1320 unsigned NumVals =
F.getNumOperandRegisters();
1323 if (
F.isRegDefKind() ||
F.isRegDefEarlyClobberKind() ||
1324 F.isClobberKind()) {
1326 for (; NumVals; --NumVals, ++i) {
1340 SDNode *SrcNode =
Node->getOperand(2).getNode();
1346 if (!
Node->isMachineOpcode())
1351 if (
Node->getMachineOpcode() ==
TII->getCallFrameDestroyOpcode()) {
1353 unsigned CallResource =
TRI->getNumRegs();
1354 if (LiveRegDefs[CallResource]) {
1355 SDNode *Gen = LiveRegGens[CallResource]->getNode();
1359 RegAdded.
insert(CallResource).second)
1368 const MCInstrDesc &MCID =
TII->get(
Node->getMachineOpcode());
1374 for (
unsigned i = 0; i < MCID.
getNumDefs(); ++i)
1375 if (MCID.
operands()[i].isOptionalDef()) {
1385 return !LRegs.
empty();
1388void ScheduleDAGRRList::releaseInterferences(
unsigned Reg) {
1390 for (
unsigned i = Interferences.
size(); i > 0; --i) {
1391 SUnit *SU = Interferences[i-1];
1392 LRegsMapT::iterator LRegsPos = LRegsMap.find(SU);
1394 SmallVectorImpl<unsigned> &LRegs = LRegsPos->second;
1404 AvailableQueue->
push(SU);
1406 if (i < Interferences.
size())
1407 Interferences[i-1] = Interferences.
back();
1409 LRegsMap.erase(LRegsPos);
1417SUnit *ScheduleDAGRRList::PickNodeToScheduleBottomUp() {
1418 SUnit *CurSU = AvailableQueue->
empty() ? nullptr : AvailableQueue->
pop();
1419 auto FindAvailableNode = [&]() {
1421 SmallVector<unsigned, 4> LRegs;
1422 if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
1425 if (LRegs[0] ==
TRI->getNumRegs())
dbgs() <<
"CallResource";
1427 dbgs() <<
" " << *CurSU <<
'\n');
1428 auto [LRegsIter, LRegsInserted] = LRegsMap.try_emplace(CurSU, LRegs);
1429 if (LRegsInserted) {
1436 LRegsIter->second = LRegs;
1438 CurSU = AvailableQueue->
pop();
1441 FindAvailableNode();
1453 for (SUnit *TrySU : Interferences) {
1454 SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU];
1458 SUnit *BtSU =
nullptr;
1459 unsigned LiveCycle = std::numeric_limits<unsigned>::max();
1460 for (
unsigned Reg : LRegs) {
1461 if (LiveRegGens[
Reg]->getHeight() < LiveCycle) {
1462 BtSU = LiveRegGens[
Reg];
1466 if (!WillCreateCycle(TrySU, BtSU)) {
1468 BacktrackBottomUp(TrySU, BtSU);
1475 AvailableQueue->
remove(BtSU);
1477 LLVM_DEBUG(
dbgs() <<
"ARTIFICIAL edge from " << *BtSU <<
" to " << *TrySU
1483 if (!TrySU->isAvailable || !TrySU->NodeQueueId) {
1484 LLVM_DEBUG(
dbgs() <<
"TrySU not available; choosing node from queue\n");
1485 CurSU = AvailableQueue->
pop();
1489 AvailableQueue->
remove(TrySU);
1492 FindAvailableNode();
1504 SUnit *TrySU = Interferences[0];
1505 SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU];
1506 assert(LRegs.
size() == 1 &&
"Can't handle this yet!");
1507 unsigned Reg = LRegs[0];
1508 SUnit *LRDef = LiveRegDefs[
Reg];
1519 SUnit *NewDef =
nullptr;
1521 NewDef = CopyAndMoveSuccessors(LRDef);
1522 if (!DestRC && !NewDef)
1528 InsertCopiesAndMoveSuccs(LRDef,
Reg, DestRC, RC,
Copies);
1530 << *
Copies.front() <<
"\n");
1535 LLVM_DEBUG(
dbgs() <<
" Adding an edge from " << *NewDef <<
" to "
1537 LiveRegDefs[
Reg] = NewDef;
1542 assert(CurSU &&
"Unable to resolve live physical register dependencies!");
1548void ScheduleDAGRRList::ListScheduleBottomUp() {
1550 ReleasePredecessors(&ExitSU);
1553 if (!SUnits.empty()) {
1554 SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];
1555 assert(RootSU->
Succs.empty() &&
"Graph root shouldn't have successors!");
1557 AvailableQueue->
push(RootSU);
1563 while (!AvailableQueue->
empty() || !Interferences.empty()) {
1565 AvailableQueue->
dump(
this));
1569 SUnit *SU = PickNodeToScheduleBottomUp();
1571 AdvancePastStalls(SU);
1573 ScheduleNodeBottomUp(SU);
1575 while (AvailableQueue->
empty() && !PendingQueue.empty()) {
1577 assert(MinAvailableCycle < std::numeric_limits<unsigned>::max() &&
1578 "MinAvailableCycle uninitialized");
1579 AdvanceToCycle(std::max(CurCycle + 1, MinAvailableCycle));
1587 VerifyScheduledSequence(
true);
1593class RegReductionPQBase;
1596 bool isReady(SUnit* SU,
unsigned CurCycle)
const {
return true; }
1601struct reverse_sort :
public queue_sort {
1604 reverse_sort(SF &sf) : SortFunc(sf) {}
1606 bool operator()(SUnit* left, SUnit* right)
const {
1609 return SortFunc(right, left);
1616struct bu_ls_rr_sort :
public queue_sort {
1619 HasReadyFilter =
false
1622 RegReductionPQBase *SPQ;
1624 bu_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1626 bool operator()(SUnit* left, SUnit* right)
const;
1630struct src_ls_rr_sort :
public queue_sort {
1633 HasReadyFilter =
false
1636 RegReductionPQBase *SPQ;
1638 src_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1640 bool operator()(SUnit* left, SUnit* right)
const;
1644struct hybrid_ls_rr_sort :
public queue_sort {
1647 HasReadyFilter =
false
1650 RegReductionPQBase *SPQ;
1652 hybrid_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1654 bool isReady(SUnit *SU,
unsigned CurCycle)
const;
1656 bool operator()(SUnit* left, SUnit* right)
const;
1661struct ilp_ls_rr_sort :
public queue_sort {
1664 HasReadyFilter =
false
1667 RegReductionPQBase *SPQ;
1669 ilp_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}
1671 bool isReady(SUnit *SU,
unsigned CurCycle)
const;
1673 bool operator()(SUnit* left, SUnit* right)
const;
1676class RegReductionPQBase :
public SchedulingPriorityQueue {
1678 std::vector<SUnit *> Queue;
1679 unsigned CurQueueId = 0;
1680 bool TracksRegPressure;
1684 std::vector<SUnit> *SUnits =
nullptr;
1687 const TargetInstrInfo *
TII =
nullptr;
1688 const TargetRegisterInfo *
TRI =
nullptr;
1689 const TargetLowering *TLI =
nullptr;
1690 ScheduleDAGRRList *scheduleDAG =
nullptr;
1693 std::vector<unsigned> SethiUllmanNumbers;
1696 std::vector<unsigned> RegPressure;
1700 std::vector<unsigned> RegLimit;
1704 bool hasReadyFilter,
1707 const TargetInstrInfo *tii,
1708 const TargetRegisterInfo *tri,
1709 const TargetLowering *tli)
1710 : SchedulingPriorityQueue(hasReadyFilter), TracksRegPressure(tracksrp),
1711 SrcOrder(srcorder), MF(mf),
TII(tii),
TRI(tri), TLI(tli) {
1712 if (TracksRegPressure) {
1713 unsigned NumRC =
TRI->getNumRegClasses();
1714 RegLimit.resize(NumRC);
1723 void setScheduleDAG(ScheduleDAGRRList *scheduleDag) {
1724 scheduleDAG = scheduleDag;
1727 ScheduleHazardRecognizer* getHazardRec() {
1728 return scheduleDAG->getHazardRec();
1731 void initNodes(std::vector<SUnit> &sunits)
override;
1733 void addNode(
const SUnit *SU)
override;
1735 void updateNode(
const SUnit *SU)
override;
1737 void releaseState()
override {
1739 SethiUllmanNumbers.clear();
1743 unsigned getNodePriority(
const SUnit *SU)
const;
1745 unsigned getNodeOrdering(
const SUnit *SU)
const {
1751 bool empty()
const override {
return Queue.empty(); }
1753 void push(SUnit *U)
override {
1754 assert(!
U->NodeQueueId &&
"Node in the queue already");
1755 U->NodeQueueId = ++CurQueueId;
1759 void remove(SUnit *SU)
override {
1762 std::vector<SUnit *>::iterator
I =
llvm::find(Queue, SU);
1763 if (
I != std::prev(
Queue.end()))
1769 bool tracksRegPressure()
const override {
return TracksRegPressure; }
1771 void dumpRegPressure()
const;
1773 bool HighRegPressure(
const SUnit *SU)
const;
1775 bool MayReduceRegPressure(SUnit *SU)
const;
1777 int RegPressureDiff(SUnit *SU,
unsigned &LiveUses)
const;
1779 void scheduledNode(SUnit *SU)
override;
1781 void unscheduledNode(SUnit *SU)
override;
1784 bool canClobber(
const SUnit *SU,
const SUnit *
Op);
1785 void AddPseudoTwoAddrDeps();
1786 void PrescheduleNodesWithMultipleUses();
1787 void CalculateSethiUllmanNumbers();
1791static SUnit *popFromQueueImpl(std::vector<SUnit *> &Q, SF &Picker) {
1792 unsigned BestIdx = 0;
1795 for (
unsigned I = 1,
E = std::min(Q.size(), (
decltype(Q.size()))1000);
I !=
E;
1797 if (Picker(Q[BestIdx], Q[
I]))
1799 SUnit *
V = Q[BestIdx];
1800 if (BestIdx + 1 != Q.size())
1807SUnit *popFromQueue(std::vector<SUnit *> &Q, SF &Picker, ScheduleDAG *DAG) {
1810 reverse_sort<SF> RPicker(Picker);
1811 return popFromQueueImpl(Q, RPicker);
1815 return popFromQueueImpl(Q, Picker);
1826class RegReductionPriorityQueue :
public RegReductionPQBase {
1833 const TargetInstrInfo *tii,
1834 const TargetRegisterInfo *tri,
1835 const TargetLowering *tli)
1836 : RegReductionPQBase(mf, SF::HasReadyFilter, tracksrp, srcorder,
1840 bool isBottomUp()
const override {
return SF::IsBottomUp; }
1842 bool isReady(SUnit *U)
const override {
1843 return Picker.HasReadyFilter && Picker.isReady(U, getCurCycle());
1846 SUnit *pop()
override {
1847 if (
Queue.empty())
return nullptr;
1849 SUnit *
V = popFromQueue(Queue, Picker, scheduleDAG);
1854#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1857 std::vector<SUnit *> DumpQueue =
Queue;
1858 SF DumpPicker = Picker;
1859 while (!DumpQueue.empty()) {
1860 SUnit *SU = popFromQueue(DumpQueue, DumpPicker, scheduleDAG);
1868using BURegReductionPriorityQueue = RegReductionPriorityQueue<bu_ls_rr_sort>;
1869using SrcRegReductionPriorityQueue = RegReductionPriorityQueue<src_ls_rr_sort>;
1870using HybridBURRPriorityQueue = RegReductionPriorityQueue<hybrid_ls_rr_sort>;
1871using ILPBURRPriorityQueue = RegReductionPriorityQueue<ilp_ls_rr_sort>;
1888 if (LSchedLow != RSchedLow)
1889 return LSchedLow < RSchedLow ? 1 : -1;
1897 if (SUNumbers[SU->
NodeNum] != 0)
1898 return SUNumbers[SU->
NodeNum];
1902 WorkState(
const SUnit *SU) : SU(SU) {}
1904 unsigned PredsProcessed = 0;
1909 while (!WorkList.
empty()) {
1910 auto &Temp = WorkList.
back();
1911 auto *TempSU = Temp.SU;
1912 bool AllPredsKnown =
true;
1914 for (
unsigned P = Temp.PredsProcessed;
P < TempSU->Preds.size(); ++
P) {
1915 auto &Pred = TempSU->Preds[
P];
1916 if (Pred.isCtrl())
continue;
1917 SUnit *PredSU = Pred.getSUnit();
1918 if (SUNumbers[PredSU->
NodeNum] == 0) {
1921 for (
auto It : WorkList)
1922 assert(It.SU != PredSU &&
"Trying to push an element twice?");
1925 Temp.PredsProcessed =
P + 1;
1926 WorkList.push_back(PredSU);
1927 AllPredsKnown =
false;
1936 unsigned SethiUllmanNumber = 0;
1938 for (
const SDep &Pred : TempSU->Preds) {
1939 if (Pred.isCtrl())
continue;
1940 SUnit *PredSU = Pred.getSUnit();
1941 unsigned PredSethiUllman = SUNumbers[PredSU->
NodeNum];
1942 assert(PredSethiUllman > 0 &&
"We should have evaluated this pred!");
1943 if (PredSethiUllman > SethiUllmanNumber) {
1944 SethiUllmanNumber = PredSethiUllman;
1946 }
else if (PredSethiUllman == SethiUllmanNumber)
1950 SethiUllmanNumber += Extra;
1951 if (SethiUllmanNumber == 0)
1952 SethiUllmanNumber = 1;
1953 SUNumbers[TempSU->NodeNum] = SethiUllmanNumber;
1957 assert(SUNumbers[SU->
NodeNum] > 0 &&
"SethiUllman should never be zero!");
1958 return SUNumbers[SU->
NodeNum];
1963void RegReductionPQBase::CalculateSethiUllmanNumbers() {
1964 SethiUllmanNumbers.assign(SUnits->size(), 0);
1966 for (
const SUnit &SU : *SUnits)
1970void RegReductionPQBase::addNode(
const SUnit *SU) {
1971 unsigned SUSize = SethiUllmanNumbers.size();
1972 if (SUnits->size() > SUSize)
1973 SethiUllmanNumbers.resize(SUSize*2, 0);
1977void RegReductionPQBase::updateNode(
const SUnit *SU) {
1978 SethiUllmanNumbers[SU->
NodeNum] = 0;
1984unsigned RegReductionPQBase::getNodePriority(
const SUnit *SU)
const {
1991 if (
Opc == TargetOpcode::EXTRACT_SUBREG ||
1992 Opc == TargetOpcode::SUBREG_TO_REG ||
1993 Opc == TargetOpcode::INSERT_SUBREG)
2009 return SethiUllmanNumbers[SU->
NodeNum];
2011 unsigned Priority = SethiUllmanNumbers[SU->
NodeNum];
2015 return (NP > 0) ? NP : 0;
2025#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2032 << RegLimit[Id] <<
'\n');
2037bool RegReductionPQBase::HighRegPressure(
const SUnit *SU)
const {
2041 for (
const SDep &Pred : SU->
Preds) {
2050 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
2051 RegDefPos.IsValid(); RegDefPos.Advance()) {
2052 unsigned RCId,
Cost;
2055 if ((RegPressure[RCId] +
Cost) >= RegLimit[RCId])
2062bool RegReductionPQBase::MayReduceRegPressure(SUnit *SU)
const {
2065 if (!
N->isMachineOpcode() || !SU->
NumSuccs)
2068 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2069 for (
unsigned i = 0; i != NumDefs; ++i) {
2070 MVT VT =
N->getSimpleValueType(i);
2071 if (!
N->hasAnyUseOfValue(i))
2074 if (RegPressure[RCId] >= RegLimit[RCId])
2087int RegReductionPQBase::RegPressureDiff(SUnit *SU,
unsigned &LiveUses)
const {
2090 for (
const SDep &Pred : SU->
Preds) {
2101 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
2102 RegDefPos.IsValid(); RegDefPos.Advance()) {
2103 MVT VT = RegDefPos.GetValue();
2105 if (RegPressure[RCId] >= RegLimit[RCId])
2111 if (!
N || !
N->isMachineOpcode() || !SU->
NumSuccs)
2114 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2115 for (
unsigned i = 0; i != NumDefs; ++i) {
2116 MVT VT =
N->getSimpleValueType(i);
2117 if (!
N->hasAnyUseOfValue(i))
2120 if (RegPressure[RCId] >= RegLimit[RCId])
2126void RegReductionPQBase::scheduledNode(SUnit *SU) {
2127 if (!TracksRegPressure)
2133 for (
const SDep &Pred : SU->
Preds) {
2159 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
2160 RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) {
2164 unsigned RCId,
Cost;
2175 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(SU, scheduleDAG);
2176 RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) {
2177 if (SkipRegDefs > 0)
2179 unsigned RCId,
Cost;
2181 if (RegPressure[RCId] <
Cost) {
2194void RegReductionPQBase::unscheduledNode(SUnit *SU) {
2195 if (!TracksRegPressure)
2201 if (!
N->isMachineOpcode()) {
2205 unsigned Opc =
N->getMachineOpcode();
2206 if (
Opc == TargetOpcode::EXTRACT_SUBREG ||
2207 Opc == TargetOpcode::INSERT_SUBREG ||
2208 Opc == TargetOpcode::SUBREG_TO_REG ||
2209 Opc == TargetOpcode::REG_SEQUENCE ||
2210 Opc == TargetOpcode::IMPLICIT_DEF)
2214 for (
const SDep &Pred : SU->
Preds) {
2222 const SDNode *PN = PredSU->
getNode();
2232 if (POpc == TargetOpcode::IMPLICIT_DEF)
2234 if (POpc == TargetOpcode::EXTRACT_SUBREG ||
2235 POpc == TargetOpcode::INSERT_SUBREG ||
2236 POpc == TargetOpcode::SUBREG_TO_REG) {
2242 if (POpc == TargetOpcode::REG_SEQUENCE) {
2245 unsigned RCId = RC->
getID();
2252 for (
unsigned i = 0; i != NumDefs; ++i) {
2267 if (SU->
NumSuccs &&
N->isMachineOpcode()) {
2268 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2269 for (
unsigned i = NumDefs, e =
N->getNumValues(); i != e; ++i) {
2270 MVT VT =
N->getSimpleValueType(i);
2271 if (VT == MVT::Glue || VT == MVT::Other)
2273 if (!
N->hasAnyUseOfValue(i))
2290 unsigned MaxHeight = 0;
2292 if (Succ.
isCtrl())
continue;
2299 if (Height > MaxHeight)
2308 unsigned Scratches = 0;
2310 if (Pred.isCtrl())
continue;
2319 bool RetVal =
false;
2321 if (Pred.isCtrl())
continue;
2322 const SUnit *PredSU = Pred.getSUnit();
2327 if (
Reg.isVirtual()) {
2341 bool RetVal =
false;
2343 if (Succ.
isCtrl())
continue;
2348 if (
Reg.isVirtual()) {
2380 if (Pred.isCtrl())
continue;
2381 Pred.getSUnit()->isVRegCycle =
true;
2392 if (Pred.isCtrl())
continue;
2393 SUnit *PredSU = Pred.getSUnit();
2396 "VRegCycle def must be CopyFromReg");
2397 Pred.getSUnit()->isVRegCycle =
false;
2410 if (Pred.isCtrl())
continue;
2411 if (Pred.getSUnit()->isVRegCycle &&
2424 if ((
int)SPQ->getCurCycle() < Height)
return true;
2425 if (SPQ->getHazardRec()->getHazardType(SU, 0)
2434 RegReductionPQBase *SPQ) {
2439 int LHeight = (int)left->
getHeight() + LPenalty;
2440 int RHeight = (int)right->
getHeight() + RPenalty;
2453 if (LHeight != RHeight)
2454 return LHeight > RHeight ? 1 : -1;
2466 if (!SPQ->getHazardRec()->isEnabled()) {
2467 if (LHeight != RHeight)
2468 return LHeight > RHeight ? 1 : -1;
2470 int LDepth = left->
getDepth() - LPenalty;
2471 int RDepth = right->
getDepth() - RPenalty;
2472 if (LDepth != RDepth) {
2473 LLVM_DEBUG(
dbgs() <<
" Comparing latency of " << *left <<
" depth "
2474 << LDepth <<
" vs " << *right <<
" depth " << RDepth
2476 return LDepth < RDepth ? 1 : -1;
2492 if (LHasPhysReg != RHasPhysReg) {
2494 static const char *
const PhysRegMsg[] = {
" has no physreg",
2495 " defines a physreg" };
2497 LLVM_DEBUG(
dbgs() <<
" " << *left <<
" " << PhysRegMsg[LHasPhysReg]
2498 <<
" " << *right <<
" " << PhysRegMsg[RHasPhysReg]
2500 return LHasPhysReg < RHasPhysReg;
2505 unsigned LPriority = SPQ->getNodePriority(left);
2506 unsigned RPriority = SPQ->getNodePriority(right);
2512 RPriority = (RPriority > RNumVals) ? (RPriority - RNumVals) : 0;
2516 LPriority = (LPriority > LNumVals) ? (LPriority - LNumVals) : 0;
2519 if (LPriority != RPriority)
2520 return LPriority > RPriority;
2525 unsigned LOrder = SPQ->getNodeOrdering(left);
2526 unsigned ROrder = SPQ->getNodeOrdering(right);
2530 if ((LOrder || ROrder) && LOrder != ROrder)
2531 return LOrder != 0 && (LOrder < ROrder || ROrder == 0);
2554 return LDist < RDist;
2559 if (LScratch != RScratch)
2560 return LScratch > RScratch;
2564 if ((left->
isCall && RPriority > 0) || (right->
isCall && LPriority > 0))
2583 "NodeQueueId cannot be zero");
2588bool bu_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2596bool src_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2600 unsigned LOrder = SPQ->getNodeOrdering(left);
2601 unsigned ROrder = SPQ->getNodeOrdering(right);
2605 if ((LOrder || ROrder) && LOrder != ROrder)
2606 return LOrder != 0 && (LOrder < ROrder || ROrder == 0);
2615bool hybrid_ls_rr_sort::isReady(SUnit *SU,
unsigned CurCycle)
const {
2616 static const unsigned ReadyDelay = 3;
2618 if (SPQ->MayReduceRegPressure(SU))
return true;
2620 if (SU->
getHeight() > (CurCycle + ReadyDelay))
return false;
2622 if (SPQ->getHazardRec()->getHazardType(SU, -ReadyDelay)
2630bool hybrid_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2638 bool LHigh = SPQ->HighRegPressure(left);
2639 bool RHigh = SPQ->HighRegPressure(right);
2642 if (LHigh && !RHigh) {
2643 LLVM_DEBUG(
dbgs() <<
" pressure " << *left <<
" > " << *right <<
"\n");
2646 else if (!LHigh && RHigh) {
2647 LLVM_DEBUG(
dbgs() <<
" pressure " << *right <<
" > " << *left <<
"\n");
2650 if (!LHigh && !RHigh) {
2660bool ilp_ls_rr_sort::isReady(SUnit *SU,
unsigned CurCycle)
const {
2661 if (SU->
getHeight() > CurCycle)
return false;
2663 if (SPQ->getHazardRec()->getHazardType(SU, 0)
2677 if (
Opc == TargetOpcode::EXTRACT_SUBREG ||
2678 Opc == TargetOpcode::SUBREG_TO_REG ||
2679 Opc == TargetOpcode::INSERT_SUBREG)
2694bool ilp_ls_rr_sort::operator()(SUnit *left, SUnit *right)
const {
2702 unsigned LLiveUses = 0, RLiveUses = 0;
2703 int LPDiff = 0, RPDiff = 0;
2705 LPDiff = SPQ->RegPressureDiff(left, LLiveUses);
2706 RPDiff = SPQ->RegPressureDiff(right, RLiveUses);
2709 LLVM_DEBUG(
dbgs() <<
"RegPressureDiff " << *left <<
": " << LPDiff
2710 <<
" != " << *right <<
": " << RPDiff <<
"\n");
2711 return LPDiff > RPDiff;
2717 if (LReduce && !RReduce)
return false;
2718 if (RReduce && !LReduce)
return true;
2723 <<
" != " << *right <<
": " << RLiveUses <<
"\n");
2724 return LLiveUses < RLiveUses;
2730 if (LStall != RStall)
2738 <<
" != " << *right <<
": " << right->
getDepth()
2753void RegReductionPQBase::initNodes(std::vector<SUnit> &sunits) {
2757 AddPseudoTwoAddrDeps();
2759 if (!TracksRegPressure && !SrcOrder)
2760 PrescheduleNodesWithMultipleUses();
2762 CalculateSethiUllmanNumbers();
2765 if (scheduleDAG->BB->isSuccessor(scheduleDAG->BB))
2766 for (SUnit &SU : sunits)
2774bool RegReductionPQBase::canClobber(
const SUnit *SU,
const SUnit *
Op) {
2777 const MCInstrDesc &MCID =
TII->get(
Opc);
2780 for (
unsigned i = 0; i !=
NumOps; ++i) {
2796 ScheduleDAGRRList *scheduleDAG,
2802 if (ImpDefs.
empty() && !RegMask)
2807 for (
const SDep &SuccPred : SuccSU->
Preds) {
2813 scheduleDAG->IsReachable(DepSU, SuccPred.
getSUnit()))
2820 if (
TRI->regsOverlap(ImpDef, SuccPred.
getReg()) &&
2821 scheduleDAG->IsReachable(DepSU, SuccPred.
getSUnit()))
2835 unsigned NumDefs =
TII->get(
N->getMachineOpcode()).getNumDefs();
2837 assert(!ImpDefs.
empty() &&
"Caller should check hasPhysRegDefs");
2840 if (!SUNode->isMachineOpcode())
2843 TII->get(SUNode->getMachineOpcode()).implicit_defs();
2845 if (SUImpDefs.
empty() && !SURegMask)
2847 for (
unsigned i = NumDefs, e =
N->getNumValues(); i != e; ++i) {
2848 MVT VT =
N->getSimpleValueType(i);
2849 if (VT == MVT::Glue || VT == MVT::Other)
2851 if (!
N->hasAnyUseOfValue(i))
2857 if (
TRI->regsOverlap(
Reg, SUReg))
2895void RegReductionPQBase::PrescheduleNodesWithMultipleUses() {
2897 for (SUnit &SU : *SUnits) {
2913 SDNode *PredFrameSetup =
nullptr;
2914 for (
const SDep &Pred : SU.
Preds)
2928 PredFrameSetup = PredND;
2933 if (PredFrameSetup !=
nullptr)
2937 SUnit *PredSU =
nullptr;
2938 for (
const SDep &Pred : SU.
Preds)
2960 for (
const SDep &PredSucc : PredSU->
Succs) {
2961 SUnit *PredSuccSU = PredSucc.
getSUnit();
2962 if (PredSuccSU == &SU)
continue;
2966 goto outer_loop_continue;
2970 goto outer_loop_continue;
2972 if (scheduleDAG->IsReachable(&SU, PredSuccSU))
2973 goto outer_loop_continue;
2979 dbgs() <<
" Prescheduling " << SU <<
" next to PredSU " << *PredSU
2980 <<
" to guide scheduling in the presence of multiple uses\n");
2981 for (
unsigned i = 0; i != PredSU->
Succs.size(); ++i) {
2984 SUnit *SuccSU =
Edge.getSUnit();
2985 if (SuccSU != &SU) {
2986 Edge.setSUnit(PredSU);
2987 scheduleDAG->RemovePred(SuccSU,
Edge);
2988 scheduleDAG->AddPredQueued(&SU,
Edge);
2990 scheduleDAG->AddPredQueued(SuccSU,
Edge);
2994 outer_loop_continue:;
3005void RegReductionPQBase::AddPseudoTwoAddrDeps() {
3006 for (SUnit &SU : *SUnits) {
3015 unsigned Opc =
Node->getMachineOpcode();
3016 const MCInstrDesc &MCID =
TII->get(
Opc);
3019 for (
unsigned j = 0;
j !=
NumOps; ++
j) {
3025 const SUnit *DUSU = &(*SUnits)[DU->
getNodeId()];
3028 for (
const SDep &Succ : DUSU->
Succs) {
3043 while (SuccSU->
Succs.size() == 1 &&
3046 TargetOpcode::COPY_TO_REGCLASS)
3047 SuccSU = SuccSU->
Succs.front().getSUnit();
3060 if (SuccOpc == TargetOpcode::EXTRACT_SUBREG ||
3061 SuccOpc == TargetOpcode::INSERT_SUBREG ||
3062 SuccOpc == TargetOpcode::SUBREG_TO_REG)
3065 (!canClobber(SuccSU, DUSU) ||
3068 !scheduleDAG->IsReachable(SuccSU, &SU)) {
3069 LLVM_DEBUG(
dbgs() <<
" Adding a pseudo-two-addr edge from " << SU
3070 <<
" to " << *SuccSU <<
"\n");
3088 BURegReductionPriorityQueue *PQ =
3089 new BURegReductionPriorityQueue(*IS->MF,
false,
false,
TII,
TRI,
nullptr);
3090 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->MF,
false, PQ, OptLevel);
3091 PQ->setScheduleDAG(SD);
3102 SrcRegReductionPriorityQueue *PQ =
3103 new SrcRegReductionPriorityQueue(*IS->MF,
false,
true,
TII,
TRI,
nullptr);
3104 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->MF,
false, PQ, OptLevel);
3105 PQ->setScheduleDAG(SD);
3117 HybridBURRPriorityQueue *PQ =
3118 new HybridBURRPriorityQueue(*IS->MF,
true,
false,
TII,
TRI, TLI);
3120 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->MF,
true, PQ, OptLevel);
3121 PQ->setScheduleDAG(SD);
3132 ILPBURRPriorityQueue *PQ =
3133 new ILPBURRPriorityQueue(*IS->MF,
true,
false,
TII,
TRI, TLI);
3134 ScheduleDAGRRList *SD =
new ScheduleDAGRRList(*IS->MF,
true, PQ, OptLevel);
3135 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.