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