xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/ScheduleDAG.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- ScheduleDAG.cpp - Implement the ScheduleDAG class ------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file Implements the ScheduleDAG class, which is a base class used by
100b57cec5SDimitry Andric /// scheduling implementation classes.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h"
150b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
170b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
240b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
250b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
260b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
270b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
290b57cec5SDimitry Andric #include <algorithm>
300b57cec5SDimitry Andric #include <cassert>
310b57cec5SDimitry Andric #include <iterator>
320b57cec5SDimitry Andric #include <limits>
330b57cec5SDimitry Andric #include <utility>
340b57cec5SDimitry Andric #include <vector>
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric #define DEBUG_TYPE "pre-RA-sched"
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric STATISTIC(NumNewPredsAdded, "Number of times a  single predecessor was added");
410b57cec5SDimitry Andric STATISTIC(NumTopoInits,
420b57cec5SDimitry Andric           "Number of times the topological order has been recomputed");
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric #ifndef NDEBUG
450b57cec5SDimitry Andric static cl::opt<bool> StressSchedOpt(
460b57cec5SDimitry Andric   "stress-sched", cl::Hidden, cl::init(false),
470b57cec5SDimitry Andric   cl::desc("Stress test instruction scheduling"));
480b57cec5SDimitry Andric #endif
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric void SchedulingPriorityQueue::anchor() {}
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric ScheduleDAG::ScheduleDAG(MachineFunction &mf)
530b57cec5SDimitry Andric     : TM(mf.getTarget()), TII(mf.getSubtarget().getInstrInfo()),
540b57cec5SDimitry Andric       TRI(mf.getSubtarget().getRegisterInfo()), MF(mf),
550b57cec5SDimitry Andric       MRI(mf.getRegInfo()) {
560b57cec5SDimitry Andric #ifndef NDEBUG
570b57cec5SDimitry Andric   StressSched = StressSchedOpt;
580b57cec5SDimitry Andric #endif
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric ScheduleDAG::~ScheduleDAG() = default;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric void ScheduleDAG::clearDAG() {
640b57cec5SDimitry Andric   SUnits.clear();
650b57cec5SDimitry Andric   EntrySU = SUnit();
660b57cec5SDimitry Andric   ExitSU = SUnit();
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric const MCInstrDesc *ScheduleDAG::getNodeDesc(const SDNode *Node) const {
700b57cec5SDimitry Andric   if (!Node || !Node->isMachineOpcode()) return nullptr;
710b57cec5SDimitry Andric   return &TII->get(Node->getMachineOpcode());
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric LLVM_DUMP_METHOD void SDep::dump(const TargetRegisterInfo *TRI) const {
750b57cec5SDimitry Andric   switch (getKind()) {
760b57cec5SDimitry Andric   case Data:   dbgs() << "Data"; break;
770b57cec5SDimitry Andric   case Anti:   dbgs() << "Anti"; break;
780b57cec5SDimitry Andric   case Output: dbgs() << "Out "; break;
790b57cec5SDimitry Andric   case Order:  dbgs() << "Ord "; break;
800b57cec5SDimitry Andric   }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   switch (getKind()) {
830b57cec5SDimitry Andric   case Data:
840b57cec5SDimitry Andric     dbgs() << " Latency=" << getLatency();
850b57cec5SDimitry Andric     if (TRI && isAssignedRegDep())
860b57cec5SDimitry Andric       dbgs() << " Reg=" << printReg(getReg(), TRI);
870b57cec5SDimitry Andric     break;
880b57cec5SDimitry Andric   case Anti:
890b57cec5SDimitry Andric   case Output:
900b57cec5SDimitry Andric     dbgs() << " Latency=" << getLatency();
910b57cec5SDimitry Andric     break;
920b57cec5SDimitry Andric   case Order:
930b57cec5SDimitry Andric     dbgs() << " Latency=" << getLatency();
940b57cec5SDimitry Andric     switch(Contents.OrdKind) {
950b57cec5SDimitry Andric     case Barrier:      dbgs() << " Barrier"; break;
960b57cec5SDimitry Andric     case MayAliasMem:
970b57cec5SDimitry Andric     case MustAliasMem: dbgs() << " Memory"; break;
980b57cec5SDimitry Andric     case Artificial:   dbgs() << " Artificial"; break;
990b57cec5SDimitry Andric     case Weak:         dbgs() << " Weak"; break;
1000b57cec5SDimitry Andric     case Cluster:      dbgs() << " Cluster"; break;
1010b57cec5SDimitry Andric     }
1020b57cec5SDimitry Andric     break;
1030b57cec5SDimitry Andric   }
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric bool SUnit::addPred(const SDep &D, bool Required) {
1070b57cec5SDimitry Andric   // If this node already has this dependence, don't add a redundant one.
1080b57cec5SDimitry Andric   for (SDep &PredDep : Preds) {
1090b57cec5SDimitry Andric     // Zero-latency weak edges may be added purely for heuristic ordering. Don't
1100b57cec5SDimitry Andric     // add them if another kind of edge already exists.
1110b57cec5SDimitry Andric     if (!Required && PredDep.getSUnit() == D.getSUnit())
1120b57cec5SDimitry Andric       return false;
1130b57cec5SDimitry Andric     if (PredDep.overlaps(D)) {
1140b57cec5SDimitry Andric       // Extend the latency if needed. Equivalent to
1150b57cec5SDimitry Andric       // removePred(PredDep) + addPred(D).
1160b57cec5SDimitry Andric       if (PredDep.getLatency() < D.getLatency()) {
1170b57cec5SDimitry Andric         SUnit *PredSU = PredDep.getSUnit();
1180b57cec5SDimitry Andric         // Find the corresponding successor in N.
1190b57cec5SDimitry Andric         SDep ForwardD = PredDep;
1200b57cec5SDimitry Andric         ForwardD.setSUnit(this);
1210b57cec5SDimitry Andric         for (SDep &SuccDep : PredSU->Succs) {
1220b57cec5SDimitry Andric           if (SuccDep == ForwardD) {
1230b57cec5SDimitry Andric             SuccDep.setLatency(D.getLatency());
1240b57cec5SDimitry Andric             break;
1250b57cec5SDimitry Andric           }
1260b57cec5SDimitry Andric         }
1270b57cec5SDimitry Andric         PredDep.setLatency(D.getLatency());
1280b57cec5SDimitry Andric       }
1290b57cec5SDimitry Andric       return false;
1300b57cec5SDimitry Andric     }
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric   // Now add a corresponding succ to N.
1330b57cec5SDimitry Andric   SDep P = D;
1340b57cec5SDimitry Andric   P.setSUnit(this);
1350b57cec5SDimitry Andric   SUnit *N = D.getSUnit();
1360b57cec5SDimitry Andric   // Update the bookkeeping.
1370b57cec5SDimitry Andric   if (D.getKind() == SDep::Data) {
1380b57cec5SDimitry Andric     assert(NumPreds < std::numeric_limits<unsigned>::max() &&
1390b57cec5SDimitry Andric            "NumPreds will overflow!");
1400b57cec5SDimitry Andric     assert(N->NumSuccs < std::numeric_limits<unsigned>::max() &&
1410b57cec5SDimitry Andric            "NumSuccs will overflow!");
1420b57cec5SDimitry Andric     ++NumPreds;
1430b57cec5SDimitry Andric     ++N->NumSuccs;
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric   if (!N->isScheduled) {
1460b57cec5SDimitry Andric     if (D.isWeak()) {
1470b57cec5SDimitry Andric       ++WeakPredsLeft;
1480b57cec5SDimitry Andric     }
1490b57cec5SDimitry Andric     else {
1500b57cec5SDimitry Andric       assert(NumPredsLeft < std::numeric_limits<unsigned>::max() &&
1510b57cec5SDimitry Andric              "NumPredsLeft will overflow!");
1520b57cec5SDimitry Andric       ++NumPredsLeft;
1530b57cec5SDimitry Andric     }
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric   if (!isScheduled) {
1560b57cec5SDimitry Andric     if (D.isWeak()) {
1570b57cec5SDimitry Andric       ++N->WeakSuccsLeft;
1580b57cec5SDimitry Andric     }
1590b57cec5SDimitry Andric     else {
1600b57cec5SDimitry Andric       assert(N->NumSuccsLeft < std::numeric_limits<unsigned>::max() &&
1610b57cec5SDimitry Andric              "NumSuccsLeft will overflow!");
1620b57cec5SDimitry Andric       ++N->NumSuccsLeft;
1630b57cec5SDimitry Andric     }
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric   Preds.push_back(D);
1660b57cec5SDimitry Andric   N->Succs.push_back(P);
1670b57cec5SDimitry Andric   if (P.getLatency() != 0) {
1680b57cec5SDimitry Andric     this->setDepthDirty();
1690b57cec5SDimitry Andric     N->setHeightDirty();
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric   return true;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric void SUnit::removePred(const SDep &D) {
1750b57cec5SDimitry Andric   // Find the matching predecessor.
1760b57cec5SDimitry Andric   SmallVectorImpl<SDep>::iterator I = llvm::find(Preds, D);
1770b57cec5SDimitry Andric   if (I == Preds.end())
1780b57cec5SDimitry Andric     return;
1790b57cec5SDimitry Andric   // Find the corresponding successor in N.
1800b57cec5SDimitry Andric   SDep P = D;
1810b57cec5SDimitry Andric   P.setSUnit(this);
1820b57cec5SDimitry Andric   SUnit *N = D.getSUnit();
1830b57cec5SDimitry Andric   SmallVectorImpl<SDep>::iterator Succ = llvm::find(N->Succs, P);
1840b57cec5SDimitry Andric   assert(Succ != N->Succs.end() && "Mismatching preds / succs lists!");
1850b57cec5SDimitry Andric   // Update the bookkeeping.
1860b57cec5SDimitry Andric   if (P.getKind() == SDep::Data) {
1870b57cec5SDimitry Andric     assert(NumPreds > 0 && "NumPreds will underflow!");
1880b57cec5SDimitry Andric     assert(N->NumSuccs > 0 && "NumSuccs will underflow!");
1890b57cec5SDimitry Andric     --NumPreds;
1900b57cec5SDimitry Andric     --N->NumSuccs;
1910b57cec5SDimitry Andric   }
1920b57cec5SDimitry Andric   if (!N->isScheduled) {
19306c3fb27SDimitry Andric     if (D.isWeak()) {
19406c3fb27SDimitry Andric       assert(WeakPredsLeft > 0 && "WeakPredsLeft will underflow!");
1950b57cec5SDimitry Andric       --WeakPredsLeft;
19606c3fb27SDimitry Andric     } else {
1970b57cec5SDimitry Andric       assert(NumPredsLeft > 0 && "NumPredsLeft will underflow!");
1980b57cec5SDimitry Andric       --NumPredsLeft;
1990b57cec5SDimitry Andric     }
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric   if (!isScheduled) {
20206c3fb27SDimitry Andric     if (D.isWeak()) {
2035f757f3fSDimitry Andric       assert(N->WeakSuccsLeft > 0 && "WeakSuccsLeft will underflow!");
2040b57cec5SDimitry Andric       --N->WeakSuccsLeft;
20506c3fb27SDimitry Andric     } else {
2060b57cec5SDimitry Andric       assert(N->NumSuccsLeft > 0 && "NumSuccsLeft will underflow!");
2070b57cec5SDimitry Andric       --N->NumSuccsLeft;
2080b57cec5SDimitry Andric     }
2090b57cec5SDimitry Andric   }
21006c3fb27SDimitry Andric   N->Succs.erase(Succ);
21106c3fb27SDimitry Andric   Preds.erase(I);
2120b57cec5SDimitry Andric   if (P.getLatency() != 0) {
2130b57cec5SDimitry Andric     this->setDepthDirty();
2140b57cec5SDimitry Andric     N->setHeightDirty();
2150b57cec5SDimitry Andric   }
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric void SUnit::setDepthDirty() {
2190b57cec5SDimitry Andric   if (!isDepthCurrent) return;
2200b57cec5SDimitry Andric   SmallVector<SUnit*, 8> WorkList;
2210b57cec5SDimitry Andric   WorkList.push_back(this);
2220b57cec5SDimitry Andric   do {
2230b57cec5SDimitry Andric     SUnit *SU = WorkList.pop_back_val();
2240b57cec5SDimitry Andric     SU->isDepthCurrent = false;
2250b57cec5SDimitry Andric     for (SDep &SuccDep : SU->Succs) {
2260b57cec5SDimitry Andric       SUnit *SuccSU = SuccDep.getSUnit();
2270b57cec5SDimitry Andric       if (SuccSU->isDepthCurrent)
2280b57cec5SDimitry Andric         WorkList.push_back(SuccSU);
2290b57cec5SDimitry Andric     }
2300b57cec5SDimitry Andric   } while (!WorkList.empty());
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric void SUnit::setHeightDirty() {
2340b57cec5SDimitry Andric   if (!isHeightCurrent) return;
2350b57cec5SDimitry Andric   SmallVector<SUnit*, 8> WorkList;
2360b57cec5SDimitry Andric   WorkList.push_back(this);
2370b57cec5SDimitry Andric   do {
2380b57cec5SDimitry Andric     SUnit *SU = WorkList.pop_back_val();
2390b57cec5SDimitry Andric     SU->isHeightCurrent = false;
2400b57cec5SDimitry Andric     for (SDep &PredDep : SU->Preds) {
2410b57cec5SDimitry Andric       SUnit *PredSU = PredDep.getSUnit();
2420b57cec5SDimitry Andric       if (PredSU->isHeightCurrent)
2430b57cec5SDimitry Andric         WorkList.push_back(PredSU);
2440b57cec5SDimitry Andric     }
2450b57cec5SDimitry Andric   } while (!WorkList.empty());
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric void SUnit::setDepthToAtLeast(unsigned NewDepth) {
2490b57cec5SDimitry Andric   if (NewDepth <= getDepth())
2500b57cec5SDimitry Andric     return;
2510b57cec5SDimitry Andric   setDepthDirty();
2520b57cec5SDimitry Andric   Depth = NewDepth;
2530b57cec5SDimitry Andric   isDepthCurrent = true;
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric void SUnit::setHeightToAtLeast(unsigned NewHeight) {
2570b57cec5SDimitry Andric   if (NewHeight <= getHeight())
2580b57cec5SDimitry Andric     return;
2590b57cec5SDimitry Andric   setHeightDirty();
2600b57cec5SDimitry Andric   Height = NewHeight;
2610b57cec5SDimitry Andric   isHeightCurrent = true;
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric /// Calculates the maximal path from the node to the exit.
2650b57cec5SDimitry Andric void SUnit::ComputeDepth() {
2660b57cec5SDimitry Andric   SmallVector<SUnit*, 8> WorkList;
2670b57cec5SDimitry Andric   WorkList.push_back(this);
2680b57cec5SDimitry Andric   do {
2690b57cec5SDimitry Andric     SUnit *Cur = WorkList.back();
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric     bool Done = true;
2720b57cec5SDimitry Andric     unsigned MaxPredDepth = 0;
2730b57cec5SDimitry Andric     for (const SDep &PredDep : Cur->Preds) {
2740b57cec5SDimitry Andric       SUnit *PredSU = PredDep.getSUnit();
2750b57cec5SDimitry Andric       if (PredSU->isDepthCurrent)
2760b57cec5SDimitry Andric         MaxPredDepth = std::max(MaxPredDepth,
2770b57cec5SDimitry Andric                                 PredSU->Depth + PredDep.getLatency());
2780b57cec5SDimitry Andric       else {
2790b57cec5SDimitry Andric         Done = false;
2800b57cec5SDimitry Andric         WorkList.push_back(PredSU);
2810b57cec5SDimitry Andric       }
2820b57cec5SDimitry Andric     }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric     if (Done) {
2850b57cec5SDimitry Andric       WorkList.pop_back();
2860b57cec5SDimitry Andric       if (MaxPredDepth != Cur->Depth) {
2870b57cec5SDimitry Andric         Cur->setDepthDirty();
2880b57cec5SDimitry Andric         Cur->Depth = MaxPredDepth;
2890b57cec5SDimitry Andric       }
2900b57cec5SDimitry Andric       Cur->isDepthCurrent = true;
2910b57cec5SDimitry Andric     }
2920b57cec5SDimitry Andric   } while (!WorkList.empty());
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric /// Calculates the maximal path from the node to the entry.
2960b57cec5SDimitry Andric void SUnit::ComputeHeight() {
2970b57cec5SDimitry Andric   SmallVector<SUnit*, 8> WorkList;
2980b57cec5SDimitry Andric   WorkList.push_back(this);
2990b57cec5SDimitry Andric   do {
3000b57cec5SDimitry Andric     SUnit *Cur = WorkList.back();
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric     bool Done = true;
3030b57cec5SDimitry Andric     unsigned MaxSuccHeight = 0;
3040b57cec5SDimitry Andric     for (const SDep &SuccDep : Cur->Succs) {
3050b57cec5SDimitry Andric       SUnit *SuccSU = SuccDep.getSUnit();
3060b57cec5SDimitry Andric       if (SuccSU->isHeightCurrent)
3070b57cec5SDimitry Andric         MaxSuccHeight = std::max(MaxSuccHeight,
3080b57cec5SDimitry Andric                                  SuccSU->Height + SuccDep.getLatency());
3090b57cec5SDimitry Andric       else {
3100b57cec5SDimitry Andric         Done = false;
3110b57cec5SDimitry Andric         WorkList.push_back(SuccSU);
3120b57cec5SDimitry Andric       }
3130b57cec5SDimitry Andric     }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric     if (Done) {
3160b57cec5SDimitry Andric       WorkList.pop_back();
3170b57cec5SDimitry Andric       if (MaxSuccHeight != Cur->Height) {
3180b57cec5SDimitry Andric         Cur->setHeightDirty();
3190b57cec5SDimitry Andric         Cur->Height = MaxSuccHeight;
3200b57cec5SDimitry Andric       }
3210b57cec5SDimitry Andric       Cur->isHeightCurrent = true;
3220b57cec5SDimitry Andric     }
3230b57cec5SDimitry Andric   } while (!WorkList.empty());
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric void SUnit::biasCriticalPath() {
3270b57cec5SDimitry Andric   if (NumPreds < 2)
3280b57cec5SDimitry Andric     return;
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   SUnit::pred_iterator BestI = Preds.begin();
3310b57cec5SDimitry Andric   unsigned MaxDepth = BestI->getSUnit()->getDepth();
3320b57cec5SDimitry Andric   for (SUnit::pred_iterator I = std::next(BestI), E = Preds.end(); I != E;
3330b57cec5SDimitry Andric        ++I) {
334*0fca6ea1SDimitry Andric     if (I->getKind() == SDep::Data && I->getSUnit()->getDepth() > MaxDepth) {
335*0fca6ea1SDimitry Andric       MaxDepth = I->getSUnit()->getDepth();
3360b57cec5SDimitry Andric       BestI = I;
3370b57cec5SDimitry Andric     }
338*0fca6ea1SDimitry Andric   }
3390b57cec5SDimitry Andric   if (BestI != Preds.begin())
3400b57cec5SDimitry Andric     std::swap(*Preds.begin(), *BestI);
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3440b57cec5SDimitry Andric LLVM_DUMP_METHOD void SUnit::dumpAttributes() const {
3450b57cec5SDimitry Andric   dbgs() << "  # preds left       : " << NumPredsLeft << "\n";
3460b57cec5SDimitry Andric   dbgs() << "  # succs left       : " << NumSuccsLeft << "\n";
3470b57cec5SDimitry Andric   if (WeakPredsLeft)
3480b57cec5SDimitry Andric     dbgs() << "  # weak preds left  : " << WeakPredsLeft << "\n";
3490b57cec5SDimitry Andric   if (WeakSuccsLeft)
3500b57cec5SDimitry Andric     dbgs() << "  # weak succs left  : " << WeakSuccsLeft << "\n";
3510b57cec5SDimitry Andric   dbgs() << "  # rdefs left       : " << NumRegDefsLeft << "\n";
3520b57cec5SDimitry Andric   dbgs() << "  Latency            : " << Latency << "\n";
3530b57cec5SDimitry Andric   dbgs() << "  Depth              : " << getDepth() << "\n";
3540b57cec5SDimitry Andric   dbgs() << "  Height             : " << getHeight() << "\n";
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric LLVM_DUMP_METHOD void ScheduleDAG::dumpNodeName(const SUnit &SU) const {
3580b57cec5SDimitry Andric   if (&SU == &EntrySU)
3590b57cec5SDimitry Andric     dbgs() << "EntrySU";
3600b57cec5SDimitry Andric   else if (&SU == &ExitSU)
3610b57cec5SDimitry Andric     dbgs() << "ExitSU";
3620b57cec5SDimitry Andric   else
3630b57cec5SDimitry Andric     dbgs() << "SU(" << SU.NodeNum << ")";
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric LLVM_DUMP_METHOD void ScheduleDAG::dumpNodeAll(const SUnit &SU) const {
3670b57cec5SDimitry Andric   dumpNode(SU);
3680b57cec5SDimitry Andric   SU.dumpAttributes();
3690b57cec5SDimitry Andric   if (SU.Preds.size() > 0) {
3700b57cec5SDimitry Andric     dbgs() << "  Predecessors:\n";
3710b57cec5SDimitry Andric     for (const SDep &Dep : SU.Preds) {
3720b57cec5SDimitry Andric       dbgs() << "    ";
3730b57cec5SDimitry Andric       dumpNodeName(*Dep.getSUnit());
3740b57cec5SDimitry Andric       dbgs() << ": ";
3750b57cec5SDimitry Andric       Dep.dump(TRI);
3760b57cec5SDimitry Andric       dbgs() << '\n';
3770b57cec5SDimitry Andric     }
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric   if (SU.Succs.size() > 0) {
3800b57cec5SDimitry Andric     dbgs() << "  Successors:\n";
3810b57cec5SDimitry Andric     for (const SDep &Dep : SU.Succs) {
3820b57cec5SDimitry Andric       dbgs() << "    ";
3830b57cec5SDimitry Andric       dumpNodeName(*Dep.getSUnit());
3840b57cec5SDimitry Andric       dbgs() << ": ";
3850b57cec5SDimitry Andric       Dep.dump(TRI);
3860b57cec5SDimitry Andric       dbgs() << '\n';
3870b57cec5SDimitry Andric     }
3880b57cec5SDimitry Andric   }
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric #endif
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric #ifndef NDEBUG
3930b57cec5SDimitry Andric unsigned ScheduleDAG::VerifyScheduledDAG(bool isBottomUp) {
3940b57cec5SDimitry Andric   bool AnyNotSched = false;
3950b57cec5SDimitry Andric   unsigned DeadNodes = 0;
3960b57cec5SDimitry Andric   for (const SUnit &SUnit : SUnits) {
3970b57cec5SDimitry Andric     if (!SUnit.isScheduled) {
3980b57cec5SDimitry Andric       if (SUnit.NumPreds == 0 && SUnit.NumSuccs == 0) {
3990b57cec5SDimitry Andric         ++DeadNodes;
4000b57cec5SDimitry Andric         continue;
4010b57cec5SDimitry Andric       }
4020b57cec5SDimitry Andric       if (!AnyNotSched)
4030b57cec5SDimitry Andric         dbgs() << "*** Scheduling failed! ***\n";
4040b57cec5SDimitry Andric       dumpNode(SUnit);
4050b57cec5SDimitry Andric       dbgs() << "has not been scheduled!\n";
4060b57cec5SDimitry Andric       AnyNotSched = true;
4070b57cec5SDimitry Andric     }
4080b57cec5SDimitry Andric     if (SUnit.isScheduled &&
4090b57cec5SDimitry Andric         (isBottomUp ? SUnit.getHeight() : SUnit.getDepth()) >
4100b57cec5SDimitry Andric           unsigned(std::numeric_limits<int>::max())) {
4110b57cec5SDimitry Andric       if (!AnyNotSched)
4120b57cec5SDimitry Andric         dbgs() << "*** Scheduling failed! ***\n";
4130b57cec5SDimitry Andric       dumpNode(SUnit);
4140b57cec5SDimitry Andric       dbgs() << "has an unexpected "
4150b57cec5SDimitry Andric            << (isBottomUp ? "Height" : "Depth") << " value!\n";
4160b57cec5SDimitry Andric       AnyNotSched = true;
4170b57cec5SDimitry Andric     }
4180b57cec5SDimitry Andric     if (isBottomUp) {
4190b57cec5SDimitry Andric       if (SUnit.NumSuccsLeft != 0) {
4200b57cec5SDimitry Andric         if (!AnyNotSched)
4210b57cec5SDimitry Andric           dbgs() << "*** Scheduling failed! ***\n";
4220b57cec5SDimitry Andric         dumpNode(SUnit);
4230b57cec5SDimitry Andric         dbgs() << "has successors left!\n";
4240b57cec5SDimitry Andric         AnyNotSched = true;
4250b57cec5SDimitry Andric       }
4260b57cec5SDimitry Andric     } else {
4270b57cec5SDimitry Andric       if (SUnit.NumPredsLeft != 0) {
4280b57cec5SDimitry Andric         if (!AnyNotSched)
4290b57cec5SDimitry Andric           dbgs() << "*** Scheduling failed! ***\n";
4300b57cec5SDimitry Andric         dumpNode(SUnit);
4310b57cec5SDimitry Andric         dbgs() << "has predecessors left!\n";
4320b57cec5SDimitry Andric         AnyNotSched = true;
4330b57cec5SDimitry Andric       }
4340b57cec5SDimitry Andric     }
4350b57cec5SDimitry Andric   }
4360b57cec5SDimitry Andric   assert(!AnyNotSched);
4370b57cec5SDimitry Andric   return SUnits.size() - DeadNodes;
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric #endif
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() {
4420b57cec5SDimitry Andric   // The idea of the algorithm is taken from
4430b57cec5SDimitry Andric   // "Online algorithms for managing the topological order of
4440b57cec5SDimitry Andric   // a directed acyclic graph" by David J. Pearce and Paul H.J. Kelly
4450b57cec5SDimitry Andric   // This is the MNR algorithm, which was first introduced by
4460b57cec5SDimitry Andric   // A. Marchetti-Spaccamela, U. Nanni and H. Rohnert in
4470b57cec5SDimitry Andric   // "Maintaining a topological order under edge insertions".
4480b57cec5SDimitry Andric   //
4490b57cec5SDimitry Andric   // Short description of the algorithm:
4500b57cec5SDimitry Andric   //
4510b57cec5SDimitry Andric   // Topological ordering, ord, of a DAG maps each node to a topological
4520b57cec5SDimitry Andric   // index so that for all edges X->Y it is the case that ord(X) < ord(Y).
4530b57cec5SDimitry Andric   //
4540b57cec5SDimitry Andric   // This means that if there is a path from the node X to the node Z,
4550b57cec5SDimitry Andric   // then ord(X) < ord(Z).
4560b57cec5SDimitry Andric   //
4570b57cec5SDimitry Andric   // This property can be used to check for reachability of nodes:
4580b57cec5SDimitry Andric   // if Z is reachable from X, then an insertion of the edge Z->X would
4590b57cec5SDimitry Andric   // create a cycle.
4600b57cec5SDimitry Andric   //
4610b57cec5SDimitry Andric   // The algorithm first computes a topological ordering for the DAG by
4620b57cec5SDimitry Andric   // initializing the Index2Node and Node2Index arrays and then tries to keep
4630b57cec5SDimitry Andric   // the ordering up-to-date after edge insertions by reordering the DAG.
4640b57cec5SDimitry Andric   //
4650b57cec5SDimitry Andric   // On insertion of the edge X->Y, the algorithm first marks by calling DFS
4660b57cec5SDimitry Andric   // the nodes reachable from Y, and then shifts them using Shift to lie
4670b57cec5SDimitry Andric   // immediately after X in Index2Node.
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric   // Cancel pending updates, mark as valid.
4700b57cec5SDimitry Andric   Dirty = false;
4710b57cec5SDimitry Andric   Updates.clear();
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric   unsigned DAGSize = SUnits.size();
4740b57cec5SDimitry Andric   std::vector<SUnit*> WorkList;
4750b57cec5SDimitry Andric   WorkList.reserve(DAGSize);
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   Index2Node.resize(DAGSize);
4780b57cec5SDimitry Andric   Node2Index.resize(DAGSize);
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric   // Initialize the data structures.
4810b57cec5SDimitry Andric   if (ExitSU)
4820b57cec5SDimitry Andric     WorkList.push_back(ExitSU);
4830b57cec5SDimitry Andric   for (SUnit &SU : SUnits) {
4840b57cec5SDimitry Andric     int NodeNum = SU.NodeNum;
4850b57cec5SDimitry Andric     unsigned Degree = SU.Succs.size();
4860b57cec5SDimitry Andric     // Temporarily use the Node2Index array as scratch space for degree counts.
4870b57cec5SDimitry Andric     Node2Index[NodeNum] = Degree;
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric     // Is it a node without dependencies?
4900b57cec5SDimitry Andric     if (Degree == 0) {
4910b57cec5SDimitry Andric       assert(SU.Succs.empty() && "SUnit should have no successors");
4920b57cec5SDimitry Andric       // Collect leaf nodes.
4930b57cec5SDimitry Andric       WorkList.push_back(&SU);
4940b57cec5SDimitry Andric     }
4950b57cec5SDimitry Andric   }
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   int Id = DAGSize;
4980b57cec5SDimitry Andric   while (!WorkList.empty()) {
4990b57cec5SDimitry Andric     SUnit *SU = WorkList.back();
5000b57cec5SDimitry Andric     WorkList.pop_back();
5010b57cec5SDimitry Andric     if (SU->NodeNum < DAGSize)
5020b57cec5SDimitry Andric       Allocate(SU->NodeNum, --Id);
5030b57cec5SDimitry Andric     for (const SDep &PredDep : SU->Preds) {
5040b57cec5SDimitry Andric       SUnit *SU = PredDep.getSUnit();
5050b57cec5SDimitry Andric       if (SU->NodeNum < DAGSize && !--Node2Index[SU->NodeNum])
5060b57cec5SDimitry Andric         // If all dependencies of the node are processed already,
5070b57cec5SDimitry Andric         // then the node can be computed now.
5080b57cec5SDimitry Andric         WorkList.push_back(SU);
5090b57cec5SDimitry Andric     }
5100b57cec5SDimitry Andric   }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   Visited.resize(DAGSize);
5130b57cec5SDimitry Andric   NumTopoInits++;
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric #ifndef NDEBUG
5160b57cec5SDimitry Andric   // Check correctness of the ordering
5170b57cec5SDimitry Andric   for (SUnit &SU : SUnits)  {
5180b57cec5SDimitry Andric     for (const SDep &PD : SU.Preds) {
5190b57cec5SDimitry Andric       assert(Node2Index[SU.NodeNum] > Node2Index[PD.getSUnit()->NodeNum] &&
5200b57cec5SDimitry Andric       "Wrong topological sorting");
5210b57cec5SDimitry Andric     }
5220b57cec5SDimitry Andric   }
5230b57cec5SDimitry Andric #endif
5240b57cec5SDimitry Andric }
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric void ScheduleDAGTopologicalSort::FixOrder() {
5270b57cec5SDimitry Andric   // Recompute from scratch after new nodes have been added.
5280b57cec5SDimitry Andric   if (Dirty) {
5290b57cec5SDimitry Andric     InitDAGTopologicalSorting();
5300b57cec5SDimitry Andric     return;
5310b57cec5SDimitry Andric   }
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric   // Otherwise apply updates one-by-one.
5340b57cec5SDimitry Andric   for (auto &U : Updates)
5350b57cec5SDimitry Andric     AddPred(U.first, U.second);
5360b57cec5SDimitry Andric   Updates.clear();
5370b57cec5SDimitry Andric }
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric void ScheduleDAGTopologicalSort::AddPredQueued(SUnit *Y, SUnit *X) {
5400b57cec5SDimitry Andric   // Recomputing the order from scratch is likely more efficient than applying
5410b57cec5SDimitry Andric   // updates one-by-one for too many updates. The current cut-off is arbitrarily
5420b57cec5SDimitry Andric   // chosen.
5430b57cec5SDimitry Andric   Dirty = Dirty || Updates.size() > 10;
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric   if (Dirty)
5460b57cec5SDimitry Andric     return;
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric   Updates.emplace_back(Y, X);
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric void ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) {
5520b57cec5SDimitry Andric   int UpperBound, LowerBound;
5530b57cec5SDimitry Andric   LowerBound = Node2Index[Y->NodeNum];
5540b57cec5SDimitry Andric   UpperBound = Node2Index[X->NodeNum];
5550b57cec5SDimitry Andric   bool HasLoop = false;
5560b57cec5SDimitry Andric   // Is Ord(X) < Ord(Y) ?
5570b57cec5SDimitry Andric   if (LowerBound < UpperBound) {
5580b57cec5SDimitry Andric     // Update the topological order.
5590b57cec5SDimitry Andric     Visited.reset();
5600b57cec5SDimitry Andric     DFS(Y, UpperBound, HasLoop);
5610b57cec5SDimitry Andric     assert(!HasLoop && "Inserted edge creates a loop!");
5620b57cec5SDimitry Andric     // Recompute topological indexes.
5630b57cec5SDimitry Andric     Shift(Visited, LowerBound, UpperBound);
5640b57cec5SDimitry Andric   }
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric   NumNewPredsAdded++;
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric void ScheduleDAGTopologicalSort::RemovePred(SUnit *M, SUnit *N) {
5700b57cec5SDimitry Andric   // InitDAGTopologicalSorting();
5710b57cec5SDimitry Andric }
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric void ScheduleDAGTopologicalSort::DFS(const SUnit *SU, int UpperBound,
5740b57cec5SDimitry Andric                                      bool &HasLoop) {
5750b57cec5SDimitry Andric   std::vector<const SUnit*> WorkList;
5760b57cec5SDimitry Andric   WorkList.reserve(SUnits.size());
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric   WorkList.push_back(SU);
5790b57cec5SDimitry Andric   do {
5800b57cec5SDimitry Andric     SU = WorkList.back();
5810b57cec5SDimitry Andric     WorkList.pop_back();
5820b57cec5SDimitry Andric     Visited.set(SU->NodeNum);
583349cc55cSDimitry Andric     for (const SDep &SuccDep : llvm::reverse(SU->Succs)) {
5840b57cec5SDimitry Andric       unsigned s = SuccDep.getSUnit()->NodeNum;
5850b57cec5SDimitry Andric       // Edges to non-SUnits are allowed but ignored (e.g. ExitSU).
5860b57cec5SDimitry Andric       if (s >= Node2Index.size())
5870b57cec5SDimitry Andric         continue;
5880b57cec5SDimitry Andric       if (Node2Index[s] == UpperBound) {
5890b57cec5SDimitry Andric         HasLoop = true;
5900b57cec5SDimitry Andric         return;
5910b57cec5SDimitry Andric       }
5920b57cec5SDimitry Andric       // Visit successors if not already and in affected region.
5930b57cec5SDimitry Andric       if (!Visited.test(s) && Node2Index[s] < UpperBound) {
5940b57cec5SDimitry Andric         WorkList.push_back(SuccDep.getSUnit());
5950b57cec5SDimitry Andric       }
5960b57cec5SDimitry Andric     }
5970b57cec5SDimitry Andric   } while (!WorkList.empty());
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric std::vector<int> ScheduleDAGTopologicalSort::GetSubGraph(const SUnit &StartSU,
6010b57cec5SDimitry Andric                                                          const SUnit &TargetSU,
6020b57cec5SDimitry Andric                                                          bool &Success) {
6030b57cec5SDimitry Andric   std::vector<const SUnit*> WorkList;
6040b57cec5SDimitry Andric   int LowerBound = Node2Index[StartSU.NodeNum];
6050b57cec5SDimitry Andric   int UpperBound = Node2Index[TargetSU.NodeNum];
6060b57cec5SDimitry Andric   bool Found = false;
6070b57cec5SDimitry Andric   BitVector VisitedBack;
6080b57cec5SDimitry Andric   std::vector<int> Nodes;
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   if (LowerBound > UpperBound) {
6110b57cec5SDimitry Andric     Success = false;
6120b57cec5SDimitry Andric     return Nodes;
6130b57cec5SDimitry Andric   }
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric   WorkList.reserve(SUnits.size());
6160b57cec5SDimitry Andric   Visited.reset();
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric   // Starting from StartSU, visit all successors up
6190b57cec5SDimitry Andric   // to UpperBound.
6200b57cec5SDimitry Andric   WorkList.push_back(&StartSU);
6210b57cec5SDimitry Andric   do {
6220b57cec5SDimitry Andric     const SUnit *SU = WorkList.back();
6230b57cec5SDimitry Andric     WorkList.pop_back();
6240eae32dcSDimitry Andric     for (const SDep &SD : llvm::reverse(SU->Succs)) {
6250eae32dcSDimitry Andric       const SUnit *Succ = SD.getSUnit();
6260b57cec5SDimitry Andric       unsigned s = Succ->NodeNum;
6270b57cec5SDimitry Andric       // Edges to non-SUnits are allowed but ignored (e.g. ExitSU).
6280b57cec5SDimitry Andric       if (Succ->isBoundaryNode())
6290b57cec5SDimitry Andric         continue;
6300b57cec5SDimitry Andric       if (Node2Index[s] == UpperBound) {
6310b57cec5SDimitry Andric         Found = true;
6320b57cec5SDimitry Andric         continue;
6330b57cec5SDimitry Andric       }
6340b57cec5SDimitry Andric       // Visit successors if not already and in affected region.
6350b57cec5SDimitry Andric       if (!Visited.test(s) && Node2Index[s] < UpperBound) {
6360b57cec5SDimitry Andric         Visited.set(s);
6370b57cec5SDimitry Andric         WorkList.push_back(Succ);
6380b57cec5SDimitry Andric       }
6390b57cec5SDimitry Andric     }
6400b57cec5SDimitry Andric   } while (!WorkList.empty());
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric   if (!Found) {
6430b57cec5SDimitry Andric     Success = false;
6440b57cec5SDimitry Andric     return Nodes;
6450b57cec5SDimitry Andric   }
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric   WorkList.clear();
6480b57cec5SDimitry Andric   VisitedBack.resize(SUnits.size());
6490b57cec5SDimitry Andric   Found = false;
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric   // Starting from TargetSU, visit all predecessors up
6520b57cec5SDimitry Andric   // to LowerBound. SUs that are visited by the two
6530b57cec5SDimitry Andric   // passes are added to Nodes.
6540b57cec5SDimitry Andric   WorkList.push_back(&TargetSU);
6550b57cec5SDimitry Andric   do {
6560b57cec5SDimitry Andric     const SUnit *SU = WorkList.back();
6570b57cec5SDimitry Andric     WorkList.pop_back();
6580eae32dcSDimitry Andric     for (const SDep &SD : llvm::reverse(SU->Preds)) {
6590eae32dcSDimitry Andric       const SUnit *Pred = SD.getSUnit();
6600b57cec5SDimitry Andric       unsigned s = Pred->NodeNum;
6610b57cec5SDimitry Andric       // Edges to non-SUnits are allowed but ignored (e.g. EntrySU).
6620b57cec5SDimitry Andric       if (Pred->isBoundaryNode())
6630b57cec5SDimitry Andric         continue;
6640b57cec5SDimitry Andric       if (Node2Index[s] == LowerBound) {
6650b57cec5SDimitry Andric         Found = true;
6660b57cec5SDimitry Andric         continue;
6670b57cec5SDimitry Andric       }
6680b57cec5SDimitry Andric       if (!VisitedBack.test(s) && Visited.test(s)) {
6690b57cec5SDimitry Andric         VisitedBack.set(s);
6700b57cec5SDimitry Andric         WorkList.push_back(Pred);
6710b57cec5SDimitry Andric         Nodes.push_back(s);
6720b57cec5SDimitry Andric       }
6730b57cec5SDimitry Andric     }
6740b57cec5SDimitry Andric   } while (!WorkList.empty());
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric   assert(Found && "Error in SUnit Graph!");
6770b57cec5SDimitry Andric   Success = true;
6780b57cec5SDimitry Andric   return Nodes;
6790b57cec5SDimitry Andric }
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric void ScheduleDAGTopologicalSort::Shift(BitVector& Visited, int LowerBound,
6820b57cec5SDimitry Andric                                        int UpperBound) {
6830b57cec5SDimitry Andric   std::vector<int> L;
6840b57cec5SDimitry Andric   int shift = 0;
6850b57cec5SDimitry Andric   int i;
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric   for (i = LowerBound; i <= UpperBound; ++i) {
6880b57cec5SDimitry Andric     // w is node at topological index i.
6890b57cec5SDimitry Andric     int w = Index2Node[i];
6900b57cec5SDimitry Andric     if (Visited.test(w)) {
6910b57cec5SDimitry Andric       // Unmark.
6920b57cec5SDimitry Andric       Visited.reset(w);
6930b57cec5SDimitry Andric       L.push_back(w);
6940b57cec5SDimitry Andric       shift = shift + 1;
6950b57cec5SDimitry Andric     } else {
6960b57cec5SDimitry Andric       Allocate(w, i - shift);
6970b57cec5SDimitry Andric     }
6980b57cec5SDimitry Andric   }
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric   for (unsigned LI : L) {
7010b57cec5SDimitry Andric     Allocate(LI, i - shift);
7020b57cec5SDimitry Andric     i = i + 1;
7030b57cec5SDimitry Andric   }
7040b57cec5SDimitry Andric }
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric bool ScheduleDAGTopologicalSort::WillCreateCycle(SUnit *TargetSU, SUnit *SU) {
7070b57cec5SDimitry Andric   FixOrder();
7080b57cec5SDimitry Andric   // Is SU reachable from TargetSU via successor edges?
7090b57cec5SDimitry Andric   if (IsReachable(SU, TargetSU))
7100b57cec5SDimitry Andric     return true;
7110b57cec5SDimitry Andric   for (const SDep &PredDep : TargetSU->Preds)
7120b57cec5SDimitry Andric     if (PredDep.isAssignedRegDep() &&
7130b57cec5SDimitry Andric         IsReachable(SU, PredDep.getSUnit()))
7140b57cec5SDimitry Andric       return true;
7150b57cec5SDimitry Andric   return false;
7160b57cec5SDimitry Andric }
7170b57cec5SDimitry Andric 
7185ffd83dbSDimitry Andric void ScheduleDAGTopologicalSort::AddSUnitWithoutPredecessors(const SUnit *SU) {
7195ffd83dbSDimitry Andric   assert(SU->NodeNum == Index2Node.size() && "Node cannot be added at the end");
7205ffd83dbSDimitry Andric   assert(SU->NumPreds == 0 && "Can only add SU's with no predecessors");
7215ffd83dbSDimitry Andric   Node2Index.push_back(Index2Node.size());
7225ffd83dbSDimitry Andric   Index2Node.push_back(SU->NodeNum);
7235ffd83dbSDimitry Andric   Visited.resize(Node2Index.size());
7245ffd83dbSDimitry Andric }
7255ffd83dbSDimitry Andric 
7260b57cec5SDimitry Andric bool ScheduleDAGTopologicalSort::IsReachable(const SUnit *SU,
7270b57cec5SDimitry Andric                                              const SUnit *TargetSU) {
72806c3fb27SDimitry Andric   assert(TargetSU != nullptr && "Invalid target SUnit");
72906c3fb27SDimitry Andric   assert(SU != nullptr && "Invalid SUnit");
7300b57cec5SDimitry Andric   FixOrder();
7310b57cec5SDimitry Andric   // If insertion of the edge SU->TargetSU would create a cycle
7320b57cec5SDimitry Andric   // then there is a path from TargetSU to SU.
7330b57cec5SDimitry Andric   int UpperBound, LowerBound;
7340b57cec5SDimitry Andric   LowerBound = Node2Index[TargetSU->NodeNum];
7350b57cec5SDimitry Andric   UpperBound = Node2Index[SU->NodeNum];
7360b57cec5SDimitry Andric   bool HasLoop = false;
7370b57cec5SDimitry Andric   // Is Ord(TargetSU) < Ord(SU) ?
7380b57cec5SDimitry Andric   if (LowerBound < UpperBound) {
7390b57cec5SDimitry Andric     Visited.reset();
7400b57cec5SDimitry Andric     // There may be a path from TargetSU to SU. Check for it.
7410b57cec5SDimitry Andric     DFS(TargetSU, UpperBound, HasLoop);
7420b57cec5SDimitry Andric   }
7430b57cec5SDimitry Andric   return HasLoop;
7440b57cec5SDimitry Andric }
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric void ScheduleDAGTopologicalSort::Allocate(int n, int index) {
7470b57cec5SDimitry Andric   Node2Index[n] = index;
7480b57cec5SDimitry Andric   Index2Node[index] = n;
7490b57cec5SDimitry Andric }
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric ScheduleDAGTopologicalSort::
7520b57cec5SDimitry Andric ScheduleDAGTopologicalSort(std::vector<SUnit> &sunits, SUnit *exitsu)
7530b57cec5SDimitry Andric   : SUnits(sunits), ExitSU(exitsu) {}
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric ScheduleHazardRecognizer::~ScheduleHazardRecognizer() = default;
756