1193323Sed//===---- ScheduleDAG.cpp - Implement the ScheduleDAG class ---------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This implements the ScheduleDAG class, which is a base class used by
11193323Sed// scheduling implementation classes.
12193323Sed//
13193323Sed//===----------------------------------------------------------------------===//
14193323Sed
15193323Sed#define DEBUG_TYPE "pre-RA-sched"
16193323Sed#include "llvm/CodeGen/ScheduleDAG.h"
17193323Sed#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
18218893Sdim#include "llvm/CodeGen/SelectionDAGNodes.h"
19224145Sdim#include "llvm/Support/CommandLine.h"
20193323Sed#include "llvm/Support/Debug.h"
21198090Srdivacky#include "llvm/Support/raw_ostream.h"
22249423Sdim#include "llvm/Target/TargetInstrInfo.h"
23249423Sdim#include "llvm/Target/TargetMachine.h"
24249423Sdim#include "llvm/Target/TargetRegisterInfo.h"
25193323Sed#include <climits>
26193323Sedusing namespace llvm;
27193323Sed
28224145Sdim#ifndef NDEBUG
29226633Sdimstatic cl::opt<bool> StressSchedOpt(
30224145Sdim  "stress-sched", cl::Hidden, cl::init(false),
31224145Sdim  cl::desc("Stress test instruction scheduling"));
32224145Sdim#endif
33224145Sdim
34234353Sdimvoid SchedulingPriorityQueue::anchor() { }
35234353Sdim
36193323SedScheduleDAG::ScheduleDAG(MachineFunction &mf)
37193323Sed  : TM(mf.getTarget()),
38193323Sed    TII(TM.getInstrInfo()),
39193323Sed    TRI(TM.getRegisterInfo()),
40193323Sed    MF(mf), MRI(mf.getRegInfo()),
41193323Sed    EntrySU(), ExitSU() {
42224145Sdim#ifndef NDEBUG
43224145Sdim  StressSched = StressSchedOpt;
44224145Sdim#endif
45193323Sed}
46193323Sed
47193323SedScheduleDAG::~ScheduleDAG() {}
48193323Sed
49234353Sdim/// Clear the DAG state (e.g. between scheduling regions).
50234353Sdimvoid ScheduleDAG::clearDAG() {
51234353Sdim  SUnits.clear();
52234353Sdim  EntrySU = SUnit();
53234353Sdim  ExitSU = SUnit();
54234353Sdim}
55234353Sdim
56218893Sdim/// getInstrDesc helper to handle SDNodes.
57224145Sdimconst MCInstrDesc *ScheduleDAG::getNodeDesc(const SDNode *Node) const {
58218893Sdim  if (!Node || !Node->isMachineOpcode()) return NULL;
59218893Sdim  return &TII->get(Node->getMachineOpcode());
60218893Sdim}
61218893Sdim
62193323Sed/// addPred - This adds the specified edge as a pred of the current node if
63193323Sed/// not already.  It also adds the current node as a successor of the
64193323Sed/// specified node.
65249423Sdimbool SUnit::addPred(const SDep &D, bool Required) {
66193323Sed  // If this node already has this depenence, don't add a redundant one.
67263508Sdim  for (SmallVectorImpl<SDep>::iterator I = Preds.begin(), E = Preds.end();
68263508Sdim         I != E; ++I) {
69249423Sdim    // Zero-latency weak edges may be added purely for heuristic ordering. Don't
70249423Sdim    // add them if another kind of edge already exists.
71249423Sdim    if (!Required && I->getSUnit() == D.getSUnit())
72249423Sdim      return false;
73239462Sdim    if (I->overlaps(D)) {
74239462Sdim      // Extend the latency if needed. Equivalent to removePred(I) + addPred(D).
75239462Sdim      if (I->getLatency() < D.getLatency()) {
76239462Sdim        SUnit *PredSU = I->getSUnit();
77239462Sdim        // Find the corresponding successor in N.
78239462Sdim        SDep ForwardD = *I;
79239462Sdim        ForwardD.setSUnit(this);
80263508Sdim        for (SmallVectorImpl<SDep>::iterator II = PredSU->Succs.begin(),
81239462Sdim               EE = PredSU->Succs.end(); II != EE; ++II) {
82239462Sdim          if (*II == ForwardD) {
83239462Sdim            II->setLatency(D.getLatency());
84239462Sdim            break;
85239462Sdim          }
86239462Sdim        }
87239462Sdim        I->setLatency(D.getLatency());
88239462Sdim      }
89218893Sdim      return false;
90239462Sdim    }
91239462Sdim  }
92193323Sed  // Now add a corresponding succ to N.
93193323Sed  SDep P = D;
94193323Sed  P.setSUnit(this);
95193323Sed  SUnit *N = D.getSUnit();
96193323Sed  // Update the bookkeeping.
97193323Sed  if (D.getKind() == SDep::Data) {
98198090Srdivacky    assert(NumPreds < UINT_MAX && "NumPreds will overflow!");
99198090Srdivacky    assert(N->NumSuccs < UINT_MAX && "NumSuccs will overflow!");
100193323Sed    ++NumPreds;
101193323Sed    ++N->NumSuccs;
102193323Sed  }
103198090Srdivacky  if (!N->isScheduled) {
104249423Sdim    if (D.isWeak()) {
105249423Sdim      ++WeakPredsLeft;
106249423Sdim    }
107249423Sdim    else {
108249423Sdim      assert(NumPredsLeft < UINT_MAX && "NumPredsLeft will overflow!");
109249423Sdim      ++NumPredsLeft;
110249423Sdim    }
111198090Srdivacky  }
112198090Srdivacky  if (!isScheduled) {
113249423Sdim    if (D.isWeak()) {
114249423Sdim      ++N->WeakSuccsLeft;
115249423Sdim    }
116249423Sdim    else {
117249423Sdim      assert(N->NumSuccsLeft < UINT_MAX && "NumSuccsLeft will overflow!");
118249423Sdim      ++N->NumSuccsLeft;
119249423Sdim    }
120198090Srdivacky  }
121193323Sed  Preds.push_back(D);
122193323Sed  N->Succs.push_back(P);
123193323Sed  if (P.getLatency() != 0) {
124193323Sed    this->setDepthDirty();
125193323Sed    N->setHeightDirty();
126193323Sed  }
127218893Sdim  return true;
128193323Sed}
129193323Sed
130193323Sed/// removePred - This removes the specified edge as a pred of the current
131193323Sed/// node if it exists.  It also removes the current node as a successor of
132193323Sed/// the specified node.
133193323Sedvoid SUnit::removePred(const SDep &D) {
134193323Sed  // Find the matching predecessor.
135263508Sdim  for (SmallVectorImpl<SDep>::iterator I = Preds.begin(), E = Preds.end();
136263508Sdim         I != E; ++I)
137193323Sed    if (*I == D) {
138193323Sed      // Find the corresponding successor in N.
139193323Sed      SDep P = D;
140193323Sed      P.setSUnit(this);
141193323Sed      SUnit *N = D.getSUnit();
142249423Sdim      SmallVectorImpl<SDep>::iterator Succ = std::find(N->Succs.begin(),
143249423Sdim                                                       N->Succs.end(), P);
144249423Sdim      assert(Succ != N->Succs.end() && "Mismatching preds / succs lists!");
145249423Sdim      N->Succs.erase(Succ);
146193323Sed      Preds.erase(I);
147193323Sed      // Update the bookkeeping.
148193323Sed      if (P.getKind() == SDep::Data) {
149198090Srdivacky        assert(NumPreds > 0 && "NumPreds will underflow!");
150198090Srdivacky        assert(N->NumSuccs > 0 && "NumSuccs will underflow!");
151193323Sed        --NumPreds;
152193323Sed        --N->NumSuccs;
153193323Sed      }
154198090Srdivacky      if (!N->isScheduled) {
155249423Sdim        if (D.isWeak())
156249423Sdim          --WeakPredsLeft;
157249423Sdim        else {
158249423Sdim          assert(NumPredsLeft > 0 && "NumPredsLeft will underflow!");
159249423Sdim          --NumPredsLeft;
160249423Sdim        }
161198090Srdivacky      }
162198090Srdivacky      if (!isScheduled) {
163249423Sdim        if (D.isWeak())
164249423Sdim          --N->WeakSuccsLeft;
165249423Sdim        else {
166249423Sdim          assert(N->NumSuccsLeft > 0 && "NumSuccsLeft will underflow!");
167249423Sdim          --N->NumSuccsLeft;
168249423Sdim        }
169198090Srdivacky      }
170193323Sed      if (P.getLatency() != 0) {
171193323Sed        this->setDepthDirty();
172193323Sed        N->setHeightDirty();
173193323Sed      }
174193323Sed      return;
175193323Sed    }
176193323Sed}
177193323Sed
178193323Sedvoid SUnit::setDepthDirty() {
179193323Sed  if (!isDepthCurrent) return;
180193323Sed  SmallVector<SUnit*, 8> WorkList;
181193323Sed  WorkList.push_back(this);
182193323Sed  do {
183193323Sed    SUnit *SU = WorkList.pop_back_val();
184193323Sed    SU->isDepthCurrent = false;
185193323Sed    for (SUnit::const_succ_iterator I = SU->Succs.begin(),
186193323Sed         E = SU->Succs.end(); I != E; ++I) {
187193323Sed      SUnit *SuccSU = I->getSUnit();
188193323Sed      if (SuccSU->isDepthCurrent)
189193323Sed        WorkList.push_back(SuccSU);
190193323Sed    }
191193323Sed  } while (!WorkList.empty());
192193323Sed}
193193323Sed
194193323Sedvoid SUnit::setHeightDirty() {
195193323Sed  if (!isHeightCurrent) return;
196193323Sed  SmallVector<SUnit*, 8> WorkList;
197193323Sed  WorkList.push_back(this);
198193323Sed  do {
199193323Sed    SUnit *SU = WorkList.pop_back_val();
200193323Sed    SU->isHeightCurrent = false;
201193323Sed    for (SUnit::const_pred_iterator I = SU->Preds.begin(),
202193323Sed         E = SU->Preds.end(); I != E; ++I) {
203193323Sed      SUnit *PredSU = I->getSUnit();
204193323Sed      if (PredSU->isHeightCurrent)
205193323Sed        WorkList.push_back(PredSU);
206193323Sed    }
207193323Sed  } while (!WorkList.empty());
208193323Sed}
209193323Sed
210193323Sed/// setDepthToAtLeast - Update this node's successors to reflect the
211193323Sed/// fact that this node's depth just increased.
212193323Sed///
213199989Srdivackyvoid SUnit::setDepthToAtLeast(unsigned NewDepth) {
214199989Srdivacky  if (NewDepth <= getDepth())
215193323Sed    return;
216193323Sed  setDepthDirty();
217193323Sed  Depth = NewDepth;
218193323Sed  isDepthCurrent = true;
219193323Sed}
220193323Sed
221193323Sed/// setHeightToAtLeast - Update this node's predecessors to reflect the
222193323Sed/// fact that this node's height just increased.
223193323Sed///
224199989Srdivackyvoid SUnit::setHeightToAtLeast(unsigned NewHeight) {
225199989Srdivacky  if (NewHeight <= getHeight())
226193323Sed    return;
227193323Sed  setHeightDirty();
228193323Sed  Height = NewHeight;
229193323Sed  isHeightCurrent = true;
230193323Sed}
231193323Sed
232193323Sed/// ComputeDepth - Calculate the maximal path from the node to the exit.
233193323Sed///
234199989Srdivackyvoid SUnit::ComputeDepth() {
235193323Sed  SmallVector<SUnit*, 8> WorkList;
236193323Sed  WorkList.push_back(this);
237193323Sed  do {
238193323Sed    SUnit *Cur = WorkList.back();
239193323Sed
240193323Sed    bool Done = true;
241193323Sed    unsigned MaxPredDepth = 0;
242193323Sed    for (SUnit::const_pred_iterator I = Cur->Preds.begin(),
243193323Sed         E = Cur->Preds.end(); I != E; ++I) {
244193323Sed      SUnit *PredSU = I->getSUnit();
245193323Sed      if (PredSU->isDepthCurrent)
246193323Sed        MaxPredDepth = std::max(MaxPredDepth,
247193323Sed                                PredSU->Depth + I->getLatency());
248193323Sed      else {
249193323Sed        Done = false;
250193323Sed        WorkList.push_back(PredSU);
251193323Sed      }
252193323Sed    }
253193323Sed
254193323Sed    if (Done) {
255193323Sed      WorkList.pop_back();
256193323Sed      if (MaxPredDepth != Cur->Depth) {
257193323Sed        Cur->setDepthDirty();
258193323Sed        Cur->Depth = MaxPredDepth;
259193323Sed      }
260193323Sed      Cur->isDepthCurrent = true;
261193323Sed    }
262193323Sed  } while (!WorkList.empty());
263193323Sed}
264193323Sed
265193323Sed/// ComputeHeight - Calculate the maximal path from the node to the entry.
266193323Sed///
267199989Srdivackyvoid SUnit::ComputeHeight() {
268193323Sed  SmallVector<SUnit*, 8> WorkList;
269193323Sed  WorkList.push_back(this);
270193323Sed  do {
271193323Sed    SUnit *Cur = WorkList.back();
272193323Sed
273193323Sed    bool Done = true;
274193323Sed    unsigned MaxSuccHeight = 0;
275193323Sed    for (SUnit::const_succ_iterator I = Cur->Succs.begin(),
276193323Sed         E = Cur->Succs.end(); I != E; ++I) {
277193323Sed      SUnit *SuccSU = I->getSUnit();
278193323Sed      if (SuccSU->isHeightCurrent)
279193323Sed        MaxSuccHeight = std::max(MaxSuccHeight,
280193323Sed                                 SuccSU->Height + I->getLatency());
281193323Sed      else {
282193323Sed        Done = false;
283193323Sed        WorkList.push_back(SuccSU);
284193323Sed      }
285193323Sed    }
286193323Sed
287193323Sed    if (Done) {
288193323Sed      WorkList.pop_back();
289193323Sed      if (MaxSuccHeight != Cur->Height) {
290193323Sed        Cur->setHeightDirty();
291193323Sed        Cur->Height = MaxSuccHeight;
292193323Sed      }
293193323Sed      Cur->isHeightCurrent = true;
294193323Sed    }
295193323Sed  } while (!WorkList.empty());
296193323Sed}
297193323Sed
298249423Sdimvoid SUnit::biasCriticalPath() {
299249423Sdim  if (NumPreds < 2)
300249423Sdim    return;
301249423Sdim
302249423Sdim  SUnit::pred_iterator BestI = Preds.begin();
303249423Sdim  unsigned MaxDepth = BestI->getSUnit()->getDepth();
304249423Sdim  for (SUnit::pred_iterator
305249423Sdim         I = llvm::next(BestI), E = Preds.end(); I != E; ++I) {
306249423Sdim    if (I->getKind() == SDep::Data && I->getSUnit()->getDepth() > MaxDepth)
307249423Sdim      BestI = I;
308249423Sdim  }
309249423Sdim  if (BestI != Preds.begin())
310249423Sdim    std::swap(*Preds.begin(), *BestI);
311249423Sdim}
312249423Sdim
313243830Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
314193323Sed/// SUnit - Scheduling unit. It's an wrapper around either a single SDNode or
315193323Sed/// a group of nodes flagged together.
316193323Sedvoid SUnit::dump(const ScheduleDAG *G) const {
317202375Srdivacky  dbgs() << "SU(" << NodeNum << "): ";
318193323Sed  G->dumpNode(this);
319193323Sed}
320193323Sed
321193323Sedvoid SUnit::dumpAll(const ScheduleDAG *G) const {
322193323Sed  dump(G);
323193323Sed
324202375Srdivacky  dbgs() << "  # preds left       : " << NumPredsLeft << "\n";
325202375Srdivacky  dbgs() << "  # succs left       : " << NumSuccsLeft << "\n";
326249423Sdim  if (WeakPredsLeft)
327249423Sdim    dbgs() << "  # weak preds left  : " << WeakPredsLeft << "\n";
328249423Sdim  if (WeakSuccsLeft)
329249423Sdim    dbgs() << "  # weak succs left  : " << WeakSuccsLeft << "\n";
330218893Sdim  dbgs() << "  # rdefs left       : " << NumRegDefsLeft << "\n";
331202375Srdivacky  dbgs() << "  Latency            : " << Latency << "\n";
332249423Sdim  dbgs() << "  Depth              : " << getDepth() << "\n";
333249423Sdim  dbgs() << "  Height             : " << getHeight() << "\n";
334193323Sed
335193323Sed  if (Preds.size() != 0) {
336202375Srdivacky    dbgs() << "  Predecessors:\n";
337193323Sed    for (SUnit::const_succ_iterator I = Preds.begin(), E = Preds.end();
338193323Sed         I != E; ++I) {
339202375Srdivacky      dbgs() << "   ";
340193323Sed      switch (I->getKind()) {
341202375Srdivacky      case SDep::Data:        dbgs() << "val "; break;
342202375Srdivacky      case SDep::Anti:        dbgs() << "anti"; break;
343202375Srdivacky      case SDep::Output:      dbgs() << "out "; break;
344202375Srdivacky      case SDep::Order:       dbgs() << "ch  "; break;
345193323Sed      }
346234353Sdim      dbgs() << "SU(" << I->getSUnit()->NodeNum << ")";
347193323Sed      if (I->isArtificial())
348202375Srdivacky        dbgs() << " *";
349202375Srdivacky      dbgs() << ": Latency=" << I->getLatency();
350224145Sdim      if (I->isAssignedRegDep())
351234353Sdim        dbgs() << " Reg=" << PrintReg(I->getReg(), G->TRI);
352202375Srdivacky      dbgs() << "\n";
353193323Sed    }
354193323Sed  }
355193323Sed  if (Succs.size() != 0) {
356202375Srdivacky    dbgs() << "  Successors:\n";
357193323Sed    for (SUnit::const_succ_iterator I = Succs.begin(), E = Succs.end();
358193323Sed         I != E; ++I) {
359202375Srdivacky      dbgs() << "   ";
360193323Sed      switch (I->getKind()) {
361202375Srdivacky      case SDep::Data:        dbgs() << "val "; break;
362202375Srdivacky      case SDep::Anti:        dbgs() << "anti"; break;
363202375Srdivacky      case SDep::Output:      dbgs() << "out "; break;
364202375Srdivacky      case SDep::Order:       dbgs() << "ch  "; break;
365193323Sed      }
366234353Sdim      dbgs() << "SU(" << I->getSUnit()->NodeNum << ")";
367193323Sed      if (I->isArtificial())
368202375Srdivacky        dbgs() << " *";
369202375Srdivacky      dbgs() << ": Latency=" << I->getLatency();
370249423Sdim      if (I->isAssignedRegDep())
371249423Sdim        dbgs() << " Reg=" << PrintReg(I->getReg(), G->TRI);
372202375Srdivacky      dbgs() << "\n";
373193323Sed    }
374193323Sed  }
375202375Srdivacky  dbgs() << "\n";
376193323Sed}
377243830Sdim#endif
378193323Sed
379193323Sed#ifndef NDEBUG
380234353Sdim/// VerifyScheduledDAG - Verify that all SUnits were scheduled and that
381234353Sdim/// their state is consistent. Return the number of scheduled nodes.
382193323Sed///
383234353Sdimunsigned ScheduleDAG::VerifyScheduledDAG(bool isBottomUp) {
384193323Sed  bool AnyNotSched = false;
385193323Sed  unsigned DeadNodes = 0;
386193323Sed  for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
387193323Sed    if (!SUnits[i].isScheduled) {
388193323Sed      if (SUnits[i].NumPreds == 0 && SUnits[i].NumSuccs == 0) {
389193323Sed        ++DeadNodes;
390193323Sed        continue;
391193323Sed      }
392193323Sed      if (!AnyNotSched)
393202375Srdivacky        dbgs() << "*** Scheduling failed! ***\n";
394193323Sed      SUnits[i].dump(this);
395202375Srdivacky      dbgs() << "has not been scheduled!\n";
396193323Sed      AnyNotSched = true;
397193323Sed    }
398193323Sed    if (SUnits[i].isScheduled &&
399198892Srdivacky        (isBottomUp ? SUnits[i].getHeight() : SUnits[i].getDepth()) >
400193323Sed          unsigned(INT_MAX)) {
401193323Sed      if (!AnyNotSched)
402202375Srdivacky        dbgs() << "*** Scheduling failed! ***\n";
403193323Sed      SUnits[i].dump(this);
404202375Srdivacky      dbgs() << "has an unexpected "
405193323Sed           << (isBottomUp ? "Height" : "Depth") << " value!\n";
406193323Sed      AnyNotSched = true;
407193323Sed    }
408193323Sed    if (isBottomUp) {
409193323Sed      if (SUnits[i].NumSuccsLeft != 0) {
410193323Sed        if (!AnyNotSched)
411202375Srdivacky          dbgs() << "*** Scheduling failed! ***\n";
412193323Sed        SUnits[i].dump(this);
413202375Srdivacky        dbgs() << "has successors left!\n";
414193323Sed        AnyNotSched = true;
415193323Sed      }
416193323Sed    } else {
417193323Sed      if (SUnits[i].NumPredsLeft != 0) {
418193323Sed        if (!AnyNotSched)
419202375Srdivacky          dbgs() << "*** Scheduling failed! ***\n";
420193323Sed        SUnits[i].dump(this);
421202375Srdivacky        dbgs() << "has predecessors left!\n";
422193323Sed        AnyNotSched = true;
423193323Sed      }
424193323Sed    }
425193323Sed  }
426193323Sed  assert(!AnyNotSched);
427234353Sdim  return SUnits.size() - DeadNodes;
428193323Sed}
429193323Sed#endif
430193323Sed
431210299Sed/// InitDAGTopologicalSorting - create the initial topological
432193323Sed/// ordering from the DAG to be scheduled.
433193323Sed///
434210299Sed/// The idea of the algorithm is taken from
435193323Sed/// "Online algorithms for managing the topological order of
436193323Sed/// a directed acyclic graph" by David J. Pearce and Paul H.J. Kelly
437210299Sed/// This is the MNR algorithm, which was first introduced by
438210299Sed/// A. Marchetti-Spaccamela, U. Nanni and H. Rohnert in
439193323Sed/// "Maintaining a topological order under edge insertions".
440193323Sed///
441210299Sed/// Short description of the algorithm:
442193323Sed///
443193323Sed/// Topological ordering, ord, of a DAG maps each node to a topological
444193323Sed/// index so that for all edges X->Y it is the case that ord(X) < ord(Y).
445193323Sed///
446210299Sed/// This means that if there is a path from the node X to the node Z,
447193323Sed/// then ord(X) < ord(Z).
448193323Sed///
449193323Sed/// This property can be used to check for reachability of nodes:
450210299Sed/// if Z is reachable from X, then an insertion of the edge Z->X would
451193323Sed/// create a cycle.
452193323Sed///
453193323Sed/// The algorithm first computes a topological ordering for the DAG by
454193323Sed/// initializing the Index2Node and Node2Index arrays and then tries to keep
455193323Sed/// the ordering up-to-date after edge insertions by reordering the DAG.
456193323Sed///
457193323Sed/// On insertion of the edge X->Y, the algorithm first marks by calling DFS
458193323Sed/// the nodes reachable from Y, and then shifts them using Shift to lie
459193323Sed/// immediately after X in Index2Node.
460193323Sedvoid ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() {
461193323Sed  unsigned DAGSize = SUnits.size();
462193323Sed  std::vector<SUnit*> WorkList;
463193323Sed  WorkList.reserve(DAGSize);
464193323Sed
465193323Sed  Index2Node.resize(DAGSize);
466193323Sed  Node2Index.resize(DAGSize);
467193323Sed
468193323Sed  // Initialize the data structures.
469249423Sdim  if (ExitSU)
470249423Sdim    WorkList.push_back(ExitSU);
471193323Sed  for (unsigned i = 0, e = DAGSize; i != e; ++i) {
472193323Sed    SUnit *SU = &SUnits[i];
473193323Sed    int NodeNum = SU->NodeNum;
474193323Sed    unsigned Degree = SU->Succs.size();
475193323Sed    // Temporarily use the Node2Index array as scratch space for degree counts.
476193323Sed    Node2Index[NodeNum] = Degree;
477193323Sed
478193323Sed    // Is it a node without dependencies?
479193323Sed    if (Degree == 0) {
480193323Sed      assert(SU->Succs.empty() && "SUnit should have no successors");
481193323Sed      // Collect leaf nodes.
482193323Sed      WorkList.push_back(SU);
483193323Sed    }
484210299Sed  }
485193323Sed
486193323Sed  int Id = DAGSize;
487193323Sed  while (!WorkList.empty()) {
488193323Sed    SUnit *SU = WorkList.back();
489193323Sed    WorkList.pop_back();
490249423Sdim    if (SU->NodeNum < DAGSize)
491249423Sdim      Allocate(SU->NodeNum, --Id);
492193323Sed    for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
493193323Sed         I != E; ++I) {
494193323Sed      SUnit *SU = I->getSUnit();
495249423Sdim      if (SU->NodeNum < DAGSize && !--Node2Index[SU->NodeNum])
496193323Sed        // If all dependencies of the node are processed already,
497193323Sed        // then the node can be computed now.
498193323Sed        WorkList.push_back(SU);
499193323Sed    }
500193323Sed  }
501193323Sed
502193323Sed  Visited.resize(DAGSize);
503193323Sed
504193323Sed#ifndef NDEBUG
505193323Sed  // Check correctness of the ordering
506193323Sed  for (unsigned i = 0, e = DAGSize; i != e; ++i) {
507193323Sed    SUnit *SU = &SUnits[i];
508193323Sed    for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
509193323Sed         I != E; ++I) {
510210299Sed      assert(Node2Index[SU->NodeNum] > Node2Index[I->getSUnit()->NodeNum] &&
511193323Sed      "Wrong topological sorting");
512193323Sed    }
513193323Sed  }
514193323Sed#endif
515193323Sed}
516193323Sed
517221345Sdim/// AddPred - Updates the topological ordering to accommodate an edge
518193323Sed/// to be added from SUnit X to SUnit Y.
519193323Sedvoid ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) {
520193323Sed  int UpperBound, LowerBound;
521193323Sed  LowerBound = Node2Index[Y->NodeNum];
522193323Sed  UpperBound = Node2Index[X->NodeNum];
523193323Sed  bool HasLoop = false;
524193323Sed  // Is Ord(X) < Ord(Y) ?
525193323Sed  if (LowerBound < UpperBound) {
526193323Sed    // Update the topological order.
527193323Sed    Visited.reset();
528193323Sed    DFS(Y, UpperBound, HasLoop);
529193323Sed    assert(!HasLoop && "Inserted edge creates a loop!");
530193323Sed    // Recompute topological indexes.
531193323Sed    Shift(Visited, LowerBound, UpperBound);
532193323Sed  }
533193323Sed}
534193323Sed
535221345Sdim/// RemovePred - Updates the topological ordering to accommodate an
536193323Sed/// an edge to be removed from the specified node N from the predecessors
537193323Sed/// of the current node M.
538193323Sedvoid ScheduleDAGTopologicalSort::RemovePred(SUnit *M, SUnit *N) {
539193323Sed  // InitDAGTopologicalSorting();
540193323Sed}
541193323Sed
542193323Sed/// DFS - Make a DFS traversal to mark all nodes reachable from SU and mark
543193323Sed/// all nodes affected by the edge insertion. These nodes will later get new
544193323Sed/// topological indexes by means of the Shift method.
545193323Sedvoid ScheduleDAGTopologicalSort::DFS(const SUnit *SU, int UpperBound,
546218893Sdim                                     bool &HasLoop) {
547193323Sed  std::vector<const SUnit*> WorkList;
548210299Sed  WorkList.reserve(SUnits.size());
549193323Sed
550193323Sed  WorkList.push_back(SU);
551193323Sed  do {
552193323Sed    SU = WorkList.back();
553193323Sed    WorkList.pop_back();
554193323Sed    Visited.set(SU->NodeNum);
555193323Sed    for (int I = SU->Succs.size()-1; I >= 0; --I) {
556249423Sdim      unsigned s = SU->Succs[I].getSUnit()->NodeNum;
557249423Sdim      // Edges to non-SUnits are allowed but ignored (e.g. ExitSU).
558249423Sdim      if (s >= Node2Index.size())
559249423Sdim        continue;
560193323Sed      if (Node2Index[s] == UpperBound) {
561210299Sed        HasLoop = true;
562193323Sed        return;
563193323Sed      }
564193323Sed      // Visit successors if not already and in affected region.
565193323Sed      if (!Visited.test(s) && Node2Index[s] < UpperBound) {
566193323Sed        WorkList.push_back(SU->Succs[I].getSUnit());
567210299Sed      }
568210299Sed    }
569193323Sed  } while (!WorkList.empty());
570193323Sed}
571193323Sed
572210299Sed/// Shift - Renumber the nodes so that the topological ordering is
573193323Sed/// preserved.
574210299Sedvoid ScheduleDAGTopologicalSort::Shift(BitVector& Visited, int LowerBound,
575193323Sed                                       int UpperBound) {
576193323Sed  std::vector<int> L;
577193323Sed  int shift = 0;
578193323Sed  int i;
579193323Sed
580193323Sed  for (i = LowerBound; i <= UpperBound; ++i) {
581193323Sed    // w is node at topological index i.
582193323Sed    int w = Index2Node[i];
583193323Sed    if (Visited.test(w)) {
584193323Sed      // Unmark.
585193323Sed      Visited.reset(w);
586193323Sed      L.push_back(w);
587193323Sed      shift = shift + 1;
588193323Sed    } else {
589193323Sed      Allocate(w, i - shift);
590193323Sed    }
591193323Sed  }
592193323Sed
593193323Sed  for (unsigned j = 0; j < L.size(); ++j) {
594193323Sed    Allocate(L[j], i - shift);
595193323Sed    i = i + 1;
596193323Sed  }
597193323Sed}
598193323Sed
599193323Sed
600249423Sdim/// WillCreateCycle - Returns true if adding an edge to TargetSU from SU will
601249423Sdim/// create a cycle. If so, it is not safe to call AddPred(TargetSU, SU).
602249423Sdimbool ScheduleDAGTopologicalSort::WillCreateCycle(SUnit *TargetSU, SUnit *SU) {
603249423Sdim  // Is SU reachable from TargetSU via successor edges?
604249423Sdim  if (IsReachable(SU, TargetSU))
605193323Sed    return true;
606249423Sdim  for (SUnit::pred_iterator
607249423Sdim         I = TargetSU->Preds.begin(), E = TargetSU->Preds.end(); I != E; ++I)
608193323Sed    if (I->isAssignedRegDep() &&
609249423Sdim        IsReachable(SU, I->getSUnit()))
610193323Sed      return true;
611193323Sed  return false;
612193323Sed}
613193323Sed
614193323Sed/// IsReachable - Checks if SU is reachable from TargetSU.
615193323Sedbool ScheduleDAGTopologicalSort::IsReachable(const SUnit *SU,
616193323Sed                                             const SUnit *TargetSU) {
617193323Sed  // If insertion of the edge SU->TargetSU would create a cycle
618193323Sed  // then there is a path from TargetSU to SU.
619193323Sed  int UpperBound, LowerBound;
620193323Sed  LowerBound = Node2Index[TargetSU->NodeNum];
621193323Sed  UpperBound = Node2Index[SU->NodeNum];
622193323Sed  bool HasLoop = false;
623193323Sed  // Is Ord(TargetSU) < Ord(SU) ?
624193323Sed  if (LowerBound < UpperBound) {
625193323Sed    Visited.reset();
626210299Sed    // There may be a path from TargetSU to SU. Check for it.
627193323Sed    DFS(TargetSU, UpperBound, HasLoop);
628193323Sed  }
629193323Sed  return HasLoop;
630193323Sed}
631193323Sed
632193323Sed/// Allocate - assign the topological index to the node n.
633193323Sedvoid ScheduleDAGTopologicalSort::Allocate(int n, int index) {
634193323Sed  Node2Index[n] = index;
635193323Sed  Index2Node[index] = n;
636193323Sed}
637193323Sed
638210299SedScheduleDAGTopologicalSort::
639249423SdimScheduleDAGTopologicalSort(std::vector<SUnit> &sunits, SUnit *exitsu)
640249423Sdim  : SUnits(sunits), ExitSU(exitsu) {}
641193323Sed
642193323SedScheduleHazardRecognizer::~ScheduleHazardRecognizer() {}
643