LCOV - code coverage report
Current view: top level - lib/CodeGen - ScheduleDAG.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 195 257 75.9 %
Date: 2018-10-20 13:21:21 Functions: 21 24 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- ScheduleDAG.cpp - Implement the ScheduleDAG class ------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : /// \file Implements the ScheduleDAG class, which is a base class used by
      11             : /// scheduling implementation classes.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "llvm/CodeGen/ScheduleDAG.h"
      16             : #include "llvm/ADT/STLExtras.h"
      17             : #include "llvm/ADT/SmallVector.h"
      18             : #include "llvm/ADT/iterator_range.h"
      19             : #include "llvm/CodeGen/MachineFunction.h"
      20             : #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
      21             : #include "llvm/CodeGen/SelectionDAGNodes.h"
      22             : #include "llvm/CodeGen/TargetInstrInfo.h"
      23             : #include "llvm/CodeGen/TargetRegisterInfo.h"
      24             : #include "llvm/CodeGen/TargetSubtargetInfo.h"
      25             : #include "llvm/Config/llvm-config.h"
      26             : #include "llvm/Support/CommandLine.h"
      27             : #include "llvm/Support/Compiler.h"
      28             : #include "llvm/Support/Debug.h"
      29             : #include "llvm/Support/raw_ostream.h"
      30             : #include <algorithm>
      31             : #include <cassert>
      32             : #include <iterator>
      33             : #include <limits>
      34             : #include <utility>
      35             : #include <vector>
      36             : 
      37             : using namespace llvm;
      38             : 
      39             : #define DEBUG_TYPE "pre-RA-sched"
      40             : 
      41             : #ifndef NDEBUG
      42             : static cl::opt<bool> StressSchedOpt(
      43             :   "stress-sched", cl::Hidden, cl::init(false),
      44             :   cl::desc("Stress test instruction scheduling"));
      45             : #endif
      46             : 
      47           0 : void SchedulingPriorityQueue::anchor() {}
      48             : 
      49     1503384 : ScheduleDAG::ScheduleDAG(MachineFunction &mf)
      50     3006768 :     : TM(mf.getTarget()), TII(mf.getSubtarget().getInstrInfo()),
      51     1503384 :       TRI(mf.getSubtarget().getRegisterInfo()), MF(mf),
      52     1503384 :       MRI(mf.getRegInfo()) {
      53             : #ifndef NDEBUG
      54             :   StressSched = StressSchedOpt;
      55             : #endif
      56     1503384 : }
      57             : 
      58             : ScheduleDAG::~ScheduleDAG() = default;
      59             : 
      60     2173475 : void ScheduleDAG::clearDAG() {
      61             :   SUnits.clear();
      62     2173475 :   EntrySU = SUnit();
      63     2173475 :   ExitSU = SUnit();
      64     2173474 : }
      65             : 
      66      341509 : const MCInstrDesc *ScheduleDAG::getNodeDesc(const SDNode *Node) const {
      67      341509 :   if (!Node || !Node->isMachineOpcode()) return nullptr;
      68      665697 :   return &TII->get(Node->getMachineOpcode());
      69             : }
      70             : 
      71           0 : LLVM_DUMP_METHOD void SDep::dump(const TargetRegisterInfo *TRI) const {
      72           0 :   switch (getKind()) {
      73           0 :   case Data:   dbgs() << "Data"; break;
      74           0 :   case Anti:   dbgs() << "Anti"; break;
      75           0 :   case Output: dbgs() << "Out "; break;
      76           0 :   case Order:  dbgs() << "Ord "; break;
      77             :   }
      78             : 
      79           0 :   switch (getKind()) {
      80           0 :   case Data:
      81           0 :     dbgs() << " Latency=" << getLatency();
      82           0 :     if (TRI && isAssignedRegDep())
      83           0 :       dbgs() << " Reg=" << printReg(getReg(), TRI);
      84             :     break;
      85           0 :   case Anti:
      86             :   case Output:
      87           0 :     dbgs() << " Latency=" << getLatency();
      88             :     break;
      89           0 :   case Order:
      90           0 :     dbgs() << " Latency=" << getLatency();
      91           0 :     switch(Contents.OrdKind) {
      92           0 :     case Barrier:      dbgs() << " Barrier"; break;
      93           0 :     case MayAliasMem:
      94           0 :     case MustAliasMem: dbgs() << " Memory"; break;
      95           0 :     case Artificial:   dbgs() << " Artificial"; break;
      96           0 :     case Weak:         dbgs() << " Weak"; break;
      97           0 :     case Cluster:      dbgs() << " Cluster"; break;
      98             :     }
      99             :     break;
     100             :   }
     101           0 : }
     102             : 
     103    29998519 : bool SUnit::addPred(const SDep &D, bool Required) {
     104             :   // If this node already has this dependence, don't add a redundant one.
     105   103319006 :   for (SDep &PredDep : Preds) {
     106             :     // Zero-latency weak edges may be added purely for heuristic ordering. Don't
     107             :     // add them if another kind of edge already exists.
     108    76259367 :     if (!Required && PredDep.getSUnit() == D.getSUnit())
     109             :       return false;
     110     3089744 :     if (PredDep.overlaps(D)) {
     111             :       // Extend the latency if needed. Equivalent to
     112             :       // removePred(PredDep) + addPred(D).
     113     2904102 :       if (PredDep.getLatency() < D.getLatency()) {
     114             :         SUnit *PredSU = PredDep.getSUnit();
     115             :         // Find the corresponding successor in N.
     116        1081 :         SDep ForwardD = PredDep;
     117             :         ForwardD.setSUnit(this);
     118        1928 :         for (SDep &SuccDep : PredSU->Succs) {
     119        1928 :           if (SuccDep == ForwardD) {
     120             :             SuccDep.setLatency(D.getLatency());
     121             :             break;
     122             :           }
     123             :         }
     124        1081 :         PredDep.setLatency(D.getLatency());
     125             :       }
     126     2904102 :       return false;
     127             :     }
     128             :   }
     129             :   // Now add a corresponding succ to N.
     130    27059639 :   SDep P = D;
     131             :   P.setSUnit(this);
     132             :   SUnit *N = D.getSUnit();
     133             :   // Update the bookkeeping.
     134    27059639 :   if (D.getKind() == SDep::Data) {
     135             :     assert(NumPreds < std::numeric_limits<unsigned>::max() &&
     136             :            "NumPreds will overflow!");
     137             :     assert(N->NumSuccs < std::numeric_limits<unsigned>::max() &&
     138             :            "NumSuccs will overflow!");
     139    11777559 :     ++NumPreds;
     140    11777559 :     ++N->NumSuccs;
     141             :   }
     142    27059639 :   if (!N->isScheduled) {
     143             :     if (D.isWeak()) {
     144       50376 :       ++WeakPredsLeft;
     145             :     }
     146             :     else {
     147             :       assert(NumPredsLeft < std::numeric_limits<unsigned>::max() &&
     148             :              "NumPredsLeft will overflow!");
     149    27009264 :       ++NumPredsLeft;
     150             :     }
     151             :   }
     152    27059639 :   if (!isScheduled) {
     153             :     if (D.isWeak()) {
     154       50376 :       ++N->WeakSuccsLeft;
     155             :     }
     156             :     else {
     157             :       assert(N->NumSuccsLeft < std::numeric_limits<unsigned>::max() &&
     158             :              "NumSuccsLeft will overflow!");
     159    27008455 :       ++N->NumSuccsLeft;
     160             :     }
     161             :   }
     162    27059639 :   Preds.push_back(D);
     163    27059640 :   N->Succs.push_back(P);
     164    27059640 :   if (P.getLatency() != 0) {
     165    22232924 :     this->setDepthDirty();
     166    22232924 :     N->setHeightDirty();
     167             :   }
     168             :   return true;
     169             : }
     170             : 
     171        2260 : void SUnit::removePred(const SDep &D) {
     172             :   // Find the matching predecessor.
     173             :   SmallVectorImpl<SDep>::iterator I = llvm::find(Preds, D);
     174        2260 :   if (I == Preds.end())
     175         115 :     return;
     176             :   // Find the corresponding successor in N.
     177        2145 :   SDep P = D;
     178             :   P.setSUnit(this);
     179             :   SUnit *N = D.getSUnit();
     180             :   SmallVectorImpl<SDep>::iterator Succ = llvm::find(N->Succs, P);
     181             :   assert(Succ != N->Succs.end() && "Mismatching preds / succs lists!");
     182             :   N->Succs.erase(Succ);
     183             :   Preds.erase(I);
     184             :   // Update the bookkeeping.
     185        2145 :   if (P.getKind() == SDep::Data) {
     186             :     assert(NumPreds > 0 && "NumPreds will underflow!");
     187             :     assert(N->NumSuccs > 0 && "NumSuccs will underflow!");
     188         921 :     --NumPreds;
     189         921 :     --N->NumSuccs;
     190             :   }
     191        2145 :   if (!N->isScheduled) {
     192             :     if (D.isWeak())
     193           0 :       --WeakPredsLeft;
     194             :     else {
     195             :       assert(NumPredsLeft > 0 && "NumPredsLeft will underflow!");
     196        2145 :       --NumPredsLeft;
     197             :     }
     198             :   }
     199        2145 :   if (!isScheduled) {
     200             :     if (D.isWeak())
     201           0 :       --N->WeakSuccsLeft;
     202             :     else {
     203             :       assert(N->NumSuccsLeft > 0 && "NumSuccsLeft will underflow!");
     204        1451 :       --N->NumSuccsLeft;
     205             :     }
     206             :   }
     207        2145 :   if (P.getLatency() != 0) {
     208        2005 :     this->setDepthDirty();
     209        2005 :     N->setHeightDirty();
     210             :   }
     211             : }
     212             : 
     213    27156489 : void SUnit::setDepthDirty() {
     214    27156489 :   if (!isDepthCurrent) return;
     215             :   SmallVector<SUnit*, 8> WorkList;
     216      140413 :   WorkList.push_back(this);
     217             :   do {
     218             :     SUnit *SU = WorkList.pop_back_val();
     219      142146 :     SU->isDepthCurrent = false;
     220      832974 :     for (SDep &SuccDep : SU->Succs) {
     221      690828 :       SUnit *SuccSU = SuccDep.getSUnit();
     222      690828 :       if (SuccSU->isDepthCurrent)
     223        1733 :         WorkList.push_back(SuccSU);
     224             :     }
     225      142146 :   } while (!WorkList.empty());
     226             : }
     227             : 
     228    44826855 : void SUnit::setHeightDirty() {
     229    44826855 :   if (!isHeightCurrent) return;
     230             :   SmallVector<SUnit*, 8> WorkList;
     231     5181769 :   WorkList.push_back(this);
     232             :   do {
     233             :     SUnit *SU = WorkList.pop_back_val();
     234     5310208 :     SU->isHeightCurrent = false;
     235    12413549 :     for (SDep &PredDep : SU->Preds) {
     236     7103341 :       SUnit *PredSU = PredDep.getSUnit();
     237     7103341 :       if (PredSU->isHeightCurrent)
     238      128439 :         WorkList.push_back(PredSU);
     239             :     }
     240     5310208 :   } while (!WorkList.empty());
     241             : }
     242             : 
     243      900223 : void SUnit::setDepthToAtLeast(unsigned NewDepth) {
     244      900223 :   if (NewDepth <= getDepth())
     245             :     return;
     246      140192 :   setDepthDirty();
     247      140192 :   Depth = NewDepth;
     248      140192 :   isDepthCurrent = true;
     249             : }
     250             : 
     251    16552879 : void SUnit::setHeightToAtLeast(unsigned NewHeight) {
     252    16552879 :   if (NewHeight <= getHeight())
     253             :     return;
     254     5172925 :   setHeightDirty();
     255     5172925 :   Height = NewHeight;
     256     5172925 :   isHeightCurrent = true;
     257             : }
     258             : 
     259             : /// Calculates the maximal path from the node to the exit.
     260     4156604 : void SUnit::ComputeDepth() {
     261             :   SmallVector<SUnit*, 8> WorkList;
     262     4156604 :   WorkList.push_back(this);
     263             :   do {
     264    12330146 :     SUnit *Cur = WorkList.back();
     265             : 
     266             :     bool Done = true;
     267    12330146 :     unsigned MaxPredDepth = 0;
     268    28509233 :     for (const SDep &PredDep : Cur->Preds) {
     269    16179087 :       SUnit *PredSU = PredDep.getSUnit();
     270    16179087 :       if (PredSU->isDepthCurrent)
     271    11364467 :         MaxPredDepth = std::max(MaxPredDepth,
     272    17256915 :                                 PredSU->Depth + PredDep.getLatency());
     273             :       else {
     274             :         Done = false;
     275     4814620 :         WorkList.push_back(PredSU);
     276             :       }
     277             :     }
     278             : 
     279    12330146 :     if (Done) {
     280             :       WorkList.pop_back();
     281     8971224 :       if (MaxPredDepth != Cur->Depth) {
     282     4780277 :         Cur->setDepthDirty();
     283     4780277 :         Cur->Depth = MaxPredDepth;
     284             :       }
     285     8971224 :       Cur->isDepthCurrent = true;
     286             :     }
     287    12330146 :   } while (!WorkList.empty());
     288     4156604 : }
     289             : 
     290             : /// Calculates the maximal path from the node to the entry.
     291    18885517 : void SUnit::ComputeHeight() {
     292             :   SmallVector<SUnit*, 8> WorkList;
     293    18885517 :   WorkList.push_back(this);
     294             :   do {
     295    22204838 :     SUnit *Cur = WorkList.back();
     296             : 
     297             :     bool Done = true;
     298    22204838 :     unsigned MaxSuccHeight = 0;
     299    57807074 :     for (const SDep &SuccDep : Cur->Succs) {
     300    35602236 :       SUnit *SuccSU = SuccDep.getSUnit();
     301    35602236 :       if (SuccSU->isHeightCurrent)
     302    33372816 :         MaxSuccHeight = std::max(MaxSuccHeight,
     303    55669053 :                                  SuccSU->Height + SuccDep.getLatency());
     304             :       else {
     305             :         Done = false;
     306     2229420 :         WorkList.push_back(SuccSU);
     307             :       }
     308             :     }
     309             : 
     310    22204838 :     if (Done) {
     311             :       WorkList.pop_back();
     312    21114938 :       if (MaxSuccHeight != Cur->Height) {
     313    17409070 :         Cur->setHeightDirty();
     314    17409070 :         Cur->Height = MaxSuccHeight;
     315             :       }
     316    21114938 :       Cur->isHeightCurrent = true;
     317             :     }
     318    22204838 :   } while (!WorkList.empty());
     319    18885517 : }
     320             : 
     321     3139006 : void SUnit::biasCriticalPath() {
     322     3139006 :   if (NumPreds < 2)
     323             :     return;
     324             : 
     325             :   SUnit::pred_iterator BestI = Preds.begin();
     326             :   unsigned MaxDepth = BestI->getSUnit()->getDepth();
     327     1445778 :   for (SUnit::pred_iterator I = std::next(BestI), E = Preds.end(); I != E;
     328             :        ++I) {
     329     1631143 :     if (I->getKind() == SDep::Data && I->getSUnit()->getDepth() > MaxDepth)
     330             :       BestI = I;
     331             :   }
     332      403542 :   if (BestI != Preds.begin())
     333             :     std::swap(*Preds.begin(), *BestI);
     334             : }
     335             : 
     336             : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
     337             : LLVM_DUMP_METHOD void SUnit::dumpAttributes() const {
     338             :   dbgs() << "  # preds left       : " << NumPredsLeft << "\n";
     339             :   dbgs() << "  # succs left       : " << NumSuccsLeft << "\n";
     340             :   if (WeakPredsLeft)
     341             :     dbgs() << "  # weak preds left  : " << WeakPredsLeft << "\n";
     342             :   if (WeakSuccsLeft)
     343             :     dbgs() << "  # weak succs left  : " << WeakSuccsLeft << "\n";
     344             :   dbgs() << "  # rdefs left       : " << NumRegDefsLeft << "\n";
     345             :   dbgs() << "  Latency            : " << Latency << "\n";
     346             :   dbgs() << "  Depth              : " << getDepth() << "\n";
     347             :   dbgs() << "  Height             : " << getHeight() << "\n";
     348             : }
     349             : 
     350             : LLVM_DUMP_METHOD void ScheduleDAG::dumpNodeName(const SUnit &SU) const {
     351             :   if (&SU == &EntrySU)
     352             :     dbgs() << "EntrySU";
     353             :   else if (&SU == &ExitSU)
     354             :     dbgs() << "ExitSU";
     355             :   else
     356             :     dbgs() << "SU(" << SU.NodeNum << ")";
     357             : }
     358             : 
     359             : LLVM_DUMP_METHOD void ScheduleDAG::dumpNodeAll(const SUnit &SU) const {
     360             :   dumpNode(SU);
     361             :   SU.dumpAttributes();
     362             :   if (SU.Preds.size() > 0) {
     363             :     dbgs() << "  Predecessors:\n";
     364             :     for (const SDep &Dep : SU.Preds) {
     365             :       dbgs() << "    ";
     366             :       dumpNodeName(*Dep.getSUnit());
     367             :       dbgs() << ": ";
     368             :       Dep.dump(TRI);
     369             :       dbgs() << '\n';
     370             :     }
     371             :   }
     372             :   if (SU.Succs.size() > 0) {
     373             :     dbgs() << "  Successors:\n";
     374             :     for (const SDep &Dep : SU.Succs) {
     375             :       dbgs() << "    ";
     376             :       dumpNodeName(*Dep.getSUnit());
     377             :       dbgs() << ": ";
     378             :       Dep.dump(TRI);
     379             :       dbgs() << '\n';
     380             :     }
     381             :   }
     382             : }
     383             : #endif
     384             : 
     385             : #ifndef NDEBUG
     386             : unsigned ScheduleDAG::VerifyScheduledDAG(bool isBottomUp) {
     387             :   bool AnyNotSched = false;
     388             :   unsigned DeadNodes = 0;
     389             :   for (const SUnit &SUnit : SUnits) {
     390             :     if (!SUnit.isScheduled) {
     391             :       if (SUnit.NumPreds == 0 && SUnit.NumSuccs == 0) {
     392             :         ++DeadNodes;
     393             :         continue;
     394             :       }
     395             :       if (!AnyNotSched)
     396             :         dbgs() << "*** Scheduling failed! ***\n";
     397             :       dumpNode(SUnit);
     398             :       dbgs() << "has not been scheduled!\n";
     399             :       AnyNotSched = true;
     400             :     }
     401             :     if (SUnit.isScheduled &&
     402             :         (isBottomUp ? SUnit.getHeight() : SUnit.getDepth()) >
     403             :           unsigned(std::numeric_limits<int>::max())) {
     404             :       if (!AnyNotSched)
     405             :         dbgs() << "*** Scheduling failed! ***\n";
     406             :       dumpNode(SUnit);
     407             :       dbgs() << "has an unexpected "
     408             :            << (isBottomUp ? "Height" : "Depth") << " value!\n";
     409             :       AnyNotSched = true;
     410             :     }
     411             :     if (isBottomUp) {
     412             :       if (SUnit.NumSuccsLeft != 0) {
     413             :         if (!AnyNotSched)
     414             :           dbgs() << "*** Scheduling failed! ***\n";
     415             :         dumpNode(SUnit);
     416             :         dbgs() << "has successors left!\n";
     417             :         AnyNotSched = true;
     418             :       }
     419             :     } else {
     420             :       if (SUnit.NumPredsLeft != 0) {
     421             :         if (!AnyNotSched)
     422             :           dbgs() << "*** Scheduling failed! ***\n";
     423             :         dumpNode(SUnit);
     424             :         dbgs() << "has predecessors left!\n";
     425             :         AnyNotSched = true;
     426             :       }
     427             :     }
     428             :   }
     429             :   assert(!AnyNotSched);
     430             :   return SUnits.size() - DeadNodes;
     431             : }
     432             : #endif
     433             : 
     434     1721911 : void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() {
     435             :   // The idea of the algorithm is taken from
     436             :   // "Online algorithms for managing the topological order of
     437             :   // a directed acyclic graph" by David J. Pearce and Paul H.J. Kelly
     438             :   // This is the MNR algorithm, which was first introduced by
     439             :   // A. Marchetti-Spaccamela, U. Nanni and H. Rohnert in
     440             :   // "Maintaining a topological order under edge insertions".
     441             :   //
     442             :   // Short description of the algorithm:
     443             :   //
     444             :   // Topological ordering, ord, of a DAG maps each node to a topological
     445             :   // index so that for all edges X->Y it is the case that ord(X) < ord(Y).
     446             :   //
     447             :   // This means that if there is a path from the node X to the node Z,
     448             :   // then ord(X) < ord(Z).
     449             :   //
     450             :   // This property can be used to check for reachability of nodes:
     451             :   // if Z is reachable from X, then an insertion of the edge Z->X would
     452             :   // create a cycle.
     453             :   //
     454             :   // The algorithm first computes a topological ordering for the DAG by
     455             :   // initializing the Index2Node and Node2Index arrays and then tries to keep
     456             :   // the ordering up-to-date after edge insertions by reordering the DAG.
     457             :   //
     458             :   // On insertion of the edge X->Y, the algorithm first marks by calling DFS
     459             :   // the nodes reachable from Y, and then shifts them using Shift to lie
     460             :   // immediately after X in Index2Node.
     461     3443822 :   unsigned DAGSize = SUnits.size();
     462             :   std::vector<SUnit*> WorkList;
     463     1721911 :   WorkList.reserve(DAGSize);
     464             : 
     465     1721911 :   Index2Node.resize(DAGSize);
     466     1721912 :   Node2Index.resize(DAGSize);
     467             : 
     468             :   // Initialize the data structures.
     469     1721912 :   if (ExitSU)
     470      452260 :     WorkList.push_back(ExitSU);
     471    20878298 :   for (SUnit &SU : SUnits) {
     472    19156386 :     int NodeNum = SU.NodeNum;
     473    19156386 :     unsigned Degree = SU.Succs.size();
     474             :     // Temporarily use the Node2Index array as scratch space for degree counts.
     475    19156386 :     Node2Index[NodeNum] = Degree;
     476             : 
     477             :     // Is it a node without dependencies?
     478    19156386 :     if (Degree == 0) {
     479             :       assert(SU.Succs.empty() && "SUnit should have no successors");
     480             :       // Collect leaf nodes.
     481     1713730 :       WorkList.push_back(&SU);
     482             :     }
     483             :   }
     484             : 
     485     1721912 :   int Id = DAGSize;
     486    21330557 :   while (!WorkList.empty()) {
     487    19608646 :     SUnit *SU = WorkList.back();
     488             :     WorkList.pop_back();
     489    19608646 :     if (SU->NodeNum < DAGSize)
     490    19156386 :       Allocate(SU->NodeNum, --Id);
     491    44048051 :     for (const SDep &PredDep : SU->Preds) {
     492    24439406 :       SUnit *SU = PredDep.getSUnit();
     493    24439406 :       if (SU->NodeNum < DAGSize && !--Node2Index[SU->NodeNum])
     494             :         // If all dependencies of the node are processed already,
     495             :         // then the node can be computed now.
     496    17442656 :         WorkList.push_back(SU);
     497             :     }
     498             :   }
     499             : 
     500     1721911 :   Visited.resize(DAGSize);
     501             : 
     502             : #ifndef NDEBUG
     503             :   // Check correctness of the ordering
     504             :   for (SUnit &SU : SUnits)  {
     505             :     for (const SDep &PD : SU.Preds) {
     506             :       assert(Node2Index[SU.NodeNum] > Node2Index[PD.getSUnit()->NodeNum] &&
     507             :       "Wrong topological sorting");
     508             :     }
     509             :   }
     510             : #endif
     511     1721912 : }
     512             : 
     513      123734 : void ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) {
     514             :   int UpperBound, LowerBound;
     515      123734 :   LowerBound = Node2Index[Y->NodeNum];
     516      123734 :   UpperBound = Node2Index[X->NodeNum];
     517      123734 :   bool HasLoop = false;
     518             :   // Is Ord(X) < Ord(Y) ?
     519      123734 :   if (LowerBound < UpperBound) {
     520             :     // Update the topological order.
     521             :     Visited.reset();
     522       38433 :     DFS(Y, UpperBound, HasLoop);
     523             :     assert(!HasLoop && "Inserted edge creates a loop!");
     524             :     // Recompute topological indexes.
     525       38433 :     Shift(Visited, LowerBound, UpperBound);
     526             :   }
     527      123734 : }
     528             : 
     529        1391 : void ScheduleDAGTopologicalSort::RemovePred(SUnit *M, SUnit *N) {
     530             :   // InitDAGTopologicalSorting();
     531        1391 : }
     532             : 
     533       95019 : void ScheduleDAGTopologicalSort::DFS(const SUnit *SU, int UpperBound,
     534             :                                      bool &HasLoop) {
     535             :   std::vector<const SUnit*> WorkList;
     536      190038 :   WorkList.reserve(SUnits.size());
     537             : 
     538       95019 :   WorkList.push_back(SU);
     539             :   do {
     540      284833 :     SU = WorkList.back();
     541             :     WorkList.pop_back();
     542      284833 :     Visited.set(SU->NodeNum);
     543             :     for (const SDep &SuccDep
     544      912097 :          : make_range(SU->Succs.rbegin(), SU->Succs.rend())) {
     545      642484 :       unsigned s = SuccDep.getSUnit()->NodeNum;
     546             :       // Edges to non-SUnits are allowed but ignored (e.g. ExitSU).
     547     1284968 :       if (s >= Node2Index.size())
     548             :         continue;
     549      569781 :       if (Node2Index[s] == UpperBound) {
     550       15220 :         HasLoop = true;
     551             :         return;
     552             :       }
     553             :       // Visit successors if not already and in affected region.
     554      554561 :       if (!Visited.test(s) && Node2Index[s] < UpperBound) {
     555      256825 :         WorkList.push_back(SuccDep.getSUnit());
     556             :       }
     557             :     }
     558      269613 :   } while (!WorkList.empty());
     559             : }
     560             : 
     561           0 : std::vector<int> ScheduleDAGTopologicalSort::GetSubGraph(const SUnit &StartSU,
     562             :                                                          const SUnit &TargetSU,
     563             :                                                          bool &Success) {
     564             :   std::vector<const SUnit*> WorkList;
     565           0 :   int LowerBound = Node2Index[StartSU.NodeNum];
     566           0 :   int UpperBound = Node2Index[TargetSU.NodeNum];
     567             :   bool Found = false;
     568             :   BitVector VisitedBack;
     569             :   std::vector<int> Nodes;
     570             : 
     571           0 :   if (LowerBound > UpperBound) {
     572           0 :     Success = false;
     573           0 :     return Nodes;
     574             :   }
     575             : 
     576           0 :   WorkList.reserve(SUnits.size());
     577             :   Visited.reset();
     578             : 
     579             :   // Starting from StartSU, visit all successors up
     580             :   // to UpperBound.
     581           0 :   WorkList.push_back(&StartSU);
     582             :   do {
     583           0 :     const SUnit *SU = WorkList.back();
     584             :     WorkList.pop_back();
     585           0 :     for (int I = SU->Succs.size()-1; I >= 0; --I) {
     586           0 :       const SUnit *Succ = SU->Succs[I].getSUnit();
     587           0 :       unsigned s = Succ->NodeNum;
     588             :       // Edges to non-SUnits are allowed but ignored (e.g. ExitSU).
     589           0 :       if (Succ->isBoundaryNode())
     590           0 :         continue;
     591           0 :       if (Node2Index[s] == UpperBound) {
     592             :         Found = true;
     593             :         continue;
     594             :       }
     595             :       // Visit successors if not already and in affected region.
     596           0 :       if (!Visited.test(s) && Node2Index[s] < UpperBound) {
     597             :         Visited.set(s);
     598           0 :         WorkList.push_back(Succ);
     599             :       }
     600             :     }
     601           0 :   } while (!WorkList.empty());
     602             : 
     603           0 :   if (!Found) {
     604           0 :     Success = false;
     605           0 :     return Nodes;
     606             :   }
     607             : 
     608             :   WorkList.clear();
     609           0 :   VisitedBack.resize(SUnits.size());
     610             :   Found = false;
     611             : 
     612             :   // Starting from TargetSU, visit all predecessors up
     613             :   // to LowerBound. SUs that are visited by the two
     614             :   // passes are added to Nodes.
     615           0 :   WorkList.push_back(&TargetSU);
     616             :   do {
     617           0 :     const SUnit *SU = WorkList.back();
     618             :     WorkList.pop_back();
     619           0 :     for (int I = SU->Preds.size()-1; I >= 0; --I) {
     620           0 :       const SUnit *Pred = SU->Preds[I].getSUnit();
     621           0 :       unsigned s = Pred->NodeNum;
     622             :       // Edges to non-SUnits are allowed but ignored (e.g. EntrySU).
     623           0 :       if (Pred->isBoundaryNode())
     624           0 :         continue;
     625           0 :       if (Node2Index[s] == LowerBound) {
     626             :         Found = true;
     627             :         continue;
     628             :       }
     629           0 :       if (!VisitedBack.test(s) && Visited.test(s)) {
     630             :         VisitedBack.set(s);
     631           0 :         WorkList.push_back(Pred);
     632           0 :         Nodes.push_back(s);
     633             :       }
     634             :     }
     635           0 :   } while (!WorkList.empty());
     636             : 
     637             :   assert(Found && "Error in SUnit Graph!");
     638           0 :   Success = true;
     639           0 :   return Nodes;
     640             : }
     641             : 
     642       38433 : void ScheduleDAGTopologicalSort::Shift(BitVector& Visited, int LowerBound,
     643             :                                        int UpperBound) {
     644             :   std::vector<int> L;
     645             :   int shift = 0;
     646             :   int i;
     647             : 
     648      556975 :   for (i = LowerBound; i <= UpperBound; ++i) {
     649             :     // w is node at topological index i.
     650      518542 :     int w = Index2Node[i];
     651     1037084 :     if (Visited.test(w)) {
     652             :       // Unmark.
     653             :       Visited.reset(w);
     654       95457 :       L.push_back(w);
     655       95457 :       shift = shift + 1;
     656             :     } else {
     657      423085 :       Allocate(w, i - shift);
     658             :     }
     659             :   }
     660             : 
     661      133890 :   for (unsigned LI : L) {
     662       95457 :     Allocate(LI, i - shift);
     663       95457 :     i = i + 1;
     664             :   }
     665       38433 : }
     666             : 
     667        3423 : bool ScheduleDAGTopologicalSort::WillCreateCycle(SUnit *TargetSU, SUnit *SU) {
     668             :   // Is SU reachable from TargetSU via successor edges?
     669        3423 :   if (IsReachable(SU, TargetSU))
     670             :     return true;
     671        4613 :   for (const SDep &PredDep : TargetSU->Preds)
     672         983 :     if (PredDep.isAssignedRegDep() &&
     673         983 :         IsReachable(SU, PredDep.getSUnit()))
     674             :       return true;
     675             :   return false;
     676             : }
     677             : 
     678      145503 : bool ScheduleDAGTopologicalSort::IsReachable(const SUnit *SU,
     679             :                                              const SUnit *TargetSU) {
     680             :   // If insertion of the edge SU->TargetSU would create a cycle
     681             :   // then there is a path from TargetSU to SU.
     682             :   int UpperBound, LowerBound;
     683      145503 :   LowerBound = Node2Index[TargetSU->NodeNum];
     684      145503 :   UpperBound = Node2Index[SU->NodeNum];
     685      145503 :   bool HasLoop = false;
     686             :   // Is Ord(TargetSU) < Ord(SU) ?
     687      145503 :   if (LowerBound < UpperBound) {
     688             :     Visited.reset();
     689             :     // There may be a path from TargetSU to SU. Check for it.
     690       56586 :     DFS(TargetSU, UpperBound, HasLoop);
     691             :   }
     692      145503 :   return HasLoop;
     693             : }
     694             : 
     695    19674928 : void ScheduleDAGTopologicalSort::Allocate(int n, int index) {
     696    39349856 :   Node2Index[n] = index;
     697    39349856 :   Index2Node[index] = n;
     698    19674928 : }
     699             : 
     700     1458721 : ScheduleDAGTopologicalSort::
     701     1458721 : ScheduleDAGTopologicalSort(std::vector<SUnit> &sunits, SUnit *exitsu)
     702     2917442 :   : SUnits(sunits), ExitSU(exitsu) {}
     703             : 
     704             : ScheduleHazardRecognizer::~ScheduleHazardRecognizer() = default;

Generated by: LCOV version 1.13