diff options
| author | 2020-08-03 15:06:44 +0000 | |
|---|---|---|
| committer | 2020-08-03 15:06:44 +0000 | |
| commit | b64793999546ed8adebaeebd9d8345d18db8927d (patch) | |
| tree | 4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/lib/CodeGen/ScheduleDAG.cpp | |
| parent | Add support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff) | |
| download | wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip | |
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/lib/CodeGen/ScheduleDAG.cpp')
| -rw-r--r-- | gnu/llvm/lib/CodeGen/ScheduleDAG.cpp | 704 |
1 files changed, 0 insertions, 704 deletions
diff --git a/gnu/llvm/lib/CodeGen/ScheduleDAG.cpp b/gnu/llvm/lib/CodeGen/ScheduleDAG.cpp deleted file mode 100644 index 6c135b3d69d..00000000000 --- a/gnu/llvm/lib/CodeGen/ScheduleDAG.cpp +++ /dev/null @@ -1,704 +0,0 @@ -//===- ScheduleDAG.cpp - Implement the ScheduleDAG class ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -/// \file Implements the ScheduleDAG class, which is a base class used by -/// scheduling implementation classes. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/ScheduleDAG.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/ScheduleHazardRecognizer.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <iterator> -#include <limits> -#include <utility> -#include <vector> - -using namespace llvm; - -#define DEBUG_TYPE "pre-RA-sched" - -#ifndef NDEBUG -static cl::opt<bool> StressSchedOpt( - "stress-sched", cl::Hidden, cl::init(false), - cl::desc("Stress test instruction scheduling")); -#endif - -void SchedulingPriorityQueue::anchor() {} - -ScheduleDAG::ScheduleDAG(MachineFunction &mf) - : TM(mf.getTarget()), TII(mf.getSubtarget().getInstrInfo()), - TRI(mf.getSubtarget().getRegisterInfo()), MF(mf), - MRI(mf.getRegInfo()) { -#ifndef NDEBUG - StressSched = StressSchedOpt; -#endif -} - -ScheduleDAG::~ScheduleDAG() = default; - -void ScheduleDAG::clearDAG() { - SUnits.clear(); - EntrySU = SUnit(); - ExitSU = SUnit(); -} - -const MCInstrDesc *ScheduleDAG::getNodeDesc(const SDNode *Node) const { - if (!Node || !Node->isMachineOpcode()) return nullptr; - return &TII->get(Node->getMachineOpcode()); -} - -LLVM_DUMP_METHOD void SDep::dump(const TargetRegisterInfo *TRI) const { - switch (getKind()) { - case Data: dbgs() << "Data"; break; - case Anti: dbgs() << "Anti"; break; - case Output: dbgs() << "Out "; break; - case Order: dbgs() << "Ord "; break; - } - - switch (getKind()) { - case Data: - dbgs() << " Latency=" << getLatency(); - if (TRI && isAssignedRegDep()) - dbgs() << " Reg=" << printReg(getReg(), TRI); - break; - case Anti: - case Output: - dbgs() << " Latency=" << getLatency(); - break; - case Order: - dbgs() << " Latency=" << getLatency(); - switch(Contents.OrdKind) { - case Barrier: dbgs() << " Barrier"; break; - case MayAliasMem: - case MustAliasMem: dbgs() << " Memory"; break; - case Artificial: dbgs() << " Artificial"; break; - case Weak: dbgs() << " Weak"; break; - case Cluster: dbgs() << " Cluster"; break; - } - break; - } -} - -bool SUnit::addPred(const SDep &D, bool Required) { - // If this node already has this dependence, don't add a redundant one. - for (SDep &PredDep : Preds) { - // Zero-latency weak edges may be added purely for heuristic ordering. Don't - // add them if another kind of edge already exists. - if (!Required && PredDep.getSUnit() == D.getSUnit()) - return false; - if (PredDep.overlaps(D)) { - // Extend the latency if needed. Equivalent to - // removePred(PredDep) + addPred(D). - if (PredDep.getLatency() < D.getLatency()) { - SUnit *PredSU = PredDep.getSUnit(); - // Find the corresponding successor in N. - SDep ForwardD = PredDep; - ForwardD.setSUnit(this); - for (SDep &SuccDep : PredSU->Succs) { - if (SuccDep == ForwardD) { - SuccDep.setLatency(D.getLatency()); - break; - } - } - PredDep.setLatency(D.getLatency()); - } - return false; - } - } - // Now add a corresponding succ to N. - SDep P = D; - P.setSUnit(this); - SUnit *N = D.getSUnit(); - // Update the bookkeeping. - if (D.getKind() == SDep::Data) { - assert(NumPreds < std::numeric_limits<unsigned>::max() && - "NumPreds will overflow!"); - assert(N->NumSuccs < std::numeric_limits<unsigned>::max() && - "NumSuccs will overflow!"); - ++NumPreds; - ++N->NumSuccs; - } - if (!N->isScheduled) { - if (D.isWeak()) { - ++WeakPredsLeft; - } - else { - assert(NumPredsLeft < std::numeric_limits<unsigned>::max() && - "NumPredsLeft will overflow!"); - ++NumPredsLeft; - } - } - if (!isScheduled) { - if (D.isWeak()) { - ++N->WeakSuccsLeft; - } - else { - assert(N->NumSuccsLeft < std::numeric_limits<unsigned>::max() && - "NumSuccsLeft will overflow!"); - ++N->NumSuccsLeft; - } - } - Preds.push_back(D); - N->Succs.push_back(P); - if (P.getLatency() != 0) { - this->setDepthDirty(); - N->setHeightDirty(); - } - return true; -} - -void SUnit::removePred(const SDep &D) { - // Find the matching predecessor. - SmallVectorImpl<SDep>::iterator I = llvm::find(Preds, D); - if (I == Preds.end()) - return; - // Find the corresponding successor in N. - SDep P = D; - P.setSUnit(this); - SUnit *N = D.getSUnit(); - SmallVectorImpl<SDep>::iterator Succ = llvm::find(N->Succs, P); - assert(Succ != N->Succs.end() && "Mismatching preds / succs lists!"); - N->Succs.erase(Succ); - Preds.erase(I); - // Update the bookkeeping. - if (P.getKind() == SDep::Data) { - assert(NumPreds > 0 && "NumPreds will underflow!"); - assert(N->NumSuccs > 0 && "NumSuccs will underflow!"); - --NumPreds; - --N->NumSuccs; - } - if (!N->isScheduled) { - if (D.isWeak()) - --WeakPredsLeft; - else { - assert(NumPredsLeft > 0 && "NumPredsLeft will underflow!"); - --NumPredsLeft; - } - } - if (!isScheduled) { - if (D.isWeak()) - --N->WeakSuccsLeft; - else { - assert(N->NumSuccsLeft > 0 && "NumSuccsLeft will underflow!"); - --N->NumSuccsLeft; - } - } - if (P.getLatency() != 0) { - this->setDepthDirty(); - N->setHeightDirty(); - } -} - -void SUnit::setDepthDirty() { - if (!isDepthCurrent) return; - SmallVector<SUnit*, 8> WorkList; - WorkList.push_back(this); - do { - SUnit *SU = WorkList.pop_back_val(); - SU->isDepthCurrent = false; - for (SDep &SuccDep : SU->Succs) { - SUnit *SuccSU = SuccDep.getSUnit(); - if (SuccSU->isDepthCurrent) - WorkList.push_back(SuccSU); - } - } while (!WorkList.empty()); -} - -void SUnit::setHeightDirty() { - if (!isHeightCurrent) return; - SmallVector<SUnit*, 8> WorkList; - WorkList.push_back(this); - do { - SUnit *SU = WorkList.pop_back_val(); - SU->isHeightCurrent = false; - for (SDep &PredDep : SU->Preds) { - SUnit *PredSU = PredDep.getSUnit(); - if (PredSU->isHeightCurrent) - WorkList.push_back(PredSU); - } - } while (!WorkList.empty()); -} - -void SUnit::setDepthToAtLeast(unsigned NewDepth) { - if (NewDepth <= getDepth()) - return; - setDepthDirty(); - Depth = NewDepth; - isDepthCurrent = true; -} - -void SUnit::setHeightToAtLeast(unsigned NewHeight) { - if (NewHeight <= getHeight()) - return; - setHeightDirty(); - Height = NewHeight; - isHeightCurrent = true; -} - -/// Calculates the maximal path from the node to the exit. -void SUnit::ComputeDepth() { - SmallVector<SUnit*, 8> WorkList; - WorkList.push_back(this); - do { - SUnit *Cur = WorkList.back(); - - bool Done = true; - unsigned MaxPredDepth = 0; - for (const SDep &PredDep : Cur->Preds) { - SUnit *PredSU = PredDep.getSUnit(); - if (PredSU->isDepthCurrent) - MaxPredDepth = std::max(MaxPredDepth, - PredSU->Depth + PredDep.getLatency()); - else { - Done = false; - WorkList.push_back(PredSU); - } - } - - if (Done) { - WorkList.pop_back(); - if (MaxPredDepth != Cur->Depth) { - Cur->setDepthDirty(); - Cur->Depth = MaxPredDepth; - } - Cur->isDepthCurrent = true; - } - } while (!WorkList.empty()); -} - -/// Calculates the maximal path from the node to the entry. -void SUnit::ComputeHeight() { - SmallVector<SUnit*, 8> WorkList; - WorkList.push_back(this); - do { - SUnit *Cur = WorkList.back(); - - bool Done = true; - unsigned MaxSuccHeight = 0; - for (const SDep &SuccDep : Cur->Succs) { - SUnit *SuccSU = SuccDep.getSUnit(); - if (SuccSU->isHeightCurrent) - MaxSuccHeight = std::max(MaxSuccHeight, - SuccSU->Height + SuccDep.getLatency()); - else { - Done = false; - WorkList.push_back(SuccSU); - } - } - - if (Done) { - WorkList.pop_back(); - if (MaxSuccHeight != Cur->Height) { - Cur->setHeightDirty(); - Cur->Height = MaxSuccHeight; - } - Cur->isHeightCurrent = true; - } - } while (!WorkList.empty()); -} - -void SUnit::biasCriticalPath() { - if (NumPreds < 2) - return; - - SUnit::pred_iterator BestI = Preds.begin(); - unsigned MaxDepth = BestI->getSUnit()->getDepth(); - for (SUnit::pred_iterator I = std::next(BestI), E = Preds.end(); I != E; - ++I) { - if (I->getKind() == SDep::Data && I->getSUnit()->getDepth() > MaxDepth) - BestI = I; - } - if (BestI != Preds.begin()) - std::swap(*Preds.begin(), *BestI); -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void SUnit::dumpAttributes() const { - dbgs() << " # preds left : " << NumPredsLeft << "\n"; - dbgs() << " # succs left : " << NumSuccsLeft << "\n"; - if (WeakPredsLeft) - dbgs() << " # weak preds left : " << WeakPredsLeft << "\n"; - if (WeakSuccsLeft) - dbgs() << " # weak succs left : " << WeakSuccsLeft << "\n"; - dbgs() << " # rdefs left : " << NumRegDefsLeft << "\n"; - dbgs() << " Latency : " << Latency << "\n"; - dbgs() << " Depth : " << getDepth() << "\n"; - dbgs() << " Height : " << getHeight() << "\n"; -} - -LLVM_DUMP_METHOD void ScheduleDAG::dumpNodeName(const SUnit &SU) const { - if (&SU == &EntrySU) - dbgs() << "EntrySU"; - else if (&SU == &ExitSU) - dbgs() << "ExitSU"; - else - dbgs() << "SU(" << SU.NodeNum << ")"; -} - -LLVM_DUMP_METHOD void ScheduleDAG::dumpNodeAll(const SUnit &SU) const { - dumpNode(SU); - SU.dumpAttributes(); - if (SU.Preds.size() > 0) { - dbgs() << " Predecessors:\n"; - for (const SDep &Dep : SU.Preds) { - dbgs() << " "; - dumpNodeName(*Dep.getSUnit()); - dbgs() << ": "; - Dep.dump(TRI); - dbgs() << '\n'; - } - } - if (SU.Succs.size() > 0) { - dbgs() << " Successors:\n"; - for (const SDep &Dep : SU.Succs) { - dbgs() << " "; - dumpNodeName(*Dep.getSUnit()); - dbgs() << ": "; - Dep.dump(TRI); - dbgs() << '\n'; - } - } -} -#endif - -#ifndef NDEBUG -unsigned ScheduleDAG::VerifyScheduledDAG(bool isBottomUp) { - bool AnyNotSched = false; - unsigned DeadNodes = 0; - for (const SUnit &SUnit : SUnits) { - if (!SUnit.isScheduled) { - if (SUnit.NumPreds == 0 && SUnit.NumSuccs == 0) { - ++DeadNodes; - continue; - } - if (!AnyNotSched) - dbgs() << "*** Scheduling failed! ***\n"; - dumpNode(SUnit); - dbgs() << "has not been scheduled!\n"; - AnyNotSched = true; - } - if (SUnit.isScheduled && - (isBottomUp ? SUnit.getHeight() : SUnit.getDepth()) > - unsigned(std::numeric_limits<int>::max())) { - if (!AnyNotSched) - dbgs() << "*** Scheduling failed! ***\n"; - dumpNode(SUnit); - dbgs() << "has an unexpected " - << (isBottomUp ? "Height" : "Depth") << " value!\n"; - AnyNotSched = true; - } - if (isBottomUp) { - if (SUnit.NumSuccsLeft != 0) { - if (!AnyNotSched) - dbgs() << "*** Scheduling failed! ***\n"; - dumpNode(SUnit); - dbgs() << "has successors left!\n"; - AnyNotSched = true; - } - } else { - if (SUnit.NumPredsLeft != 0) { - if (!AnyNotSched) - dbgs() << "*** Scheduling failed! ***\n"; - dumpNode(SUnit); - dbgs() << "has predecessors left!\n"; - AnyNotSched = true; - } - } - } - assert(!AnyNotSched); - return SUnits.size() - DeadNodes; -} -#endif - -void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() { - // The idea of the algorithm is taken from - // "Online algorithms for managing the topological order of - // a directed acyclic graph" by David J. Pearce and Paul H.J. Kelly - // This is the MNR algorithm, which was first introduced by - // A. Marchetti-Spaccamela, U. Nanni and H. Rohnert in - // "Maintaining a topological order under edge insertions". - // - // Short description of the algorithm: - // - // Topological ordering, ord, of a DAG maps each node to a topological - // index so that for all edges X->Y it is the case that ord(X) < ord(Y). - // - // This means that if there is a path from the node X to the node Z, - // then ord(X) < ord(Z). - // - // This property can be used to check for reachability of nodes: - // if Z is reachable from X, then an insertion of the edge Z->X would - // create a cycle. - // - // The algorithm first computes a topological ordering for the DAG by - // initializing the Index2Node and Node2Index arrays and then tries to keep - // the ordering up-to-date after edge insertions by reordering the DAG. - // - // On insertion of the edge X->Y, the algorithm first marks by calling DFS - // the nodes reachable from Y, and then shifts them using Shift to lie - // immediately after X in Index2Node. - unsigned DAGSize = SUnits.size(); - std::vector<SUnit*> WorkList; - WorkList.reserve(DAGSize); - - Index2Node.resize(DAGSize); - Node2Index.resize(DAGSize); - - // Initialize the data structures. - if (ExitSU) - WorkList.push_back(ExitSU); - for (SUnit &SU : SUnits) { - int NodeNum = SU.NodeNum; - unsigned Degree = SU.Succs.size(); - // Temporarily use the Node2Index array as scratch space for degree counts. - Node2Index[NodeNum] = Degree; - - // Is it a node without dependencies? - if (Degree == 0) { - assert(SU.Succs.empty() && "SUnit should have no successors"); - // Collect leaf nodes. - WorkList.push_back(&SU); - } - } - - int Id = DAGSize; - while (!WorkList.empty()) { - SUnit *SU = WorkList.back(); - WorkList.pop_back(); - if (SU->NodeNum < DAGSize) - Allocate(SU->NodeNum, --Id); - for (const SDep &PredDep : SU->Preds) { - SUnit *SU = PredDep.getSUnit(); - if (SU->NodeNum < DAGSize && !--Node2Index[SU->NodeNum]) - // If all dependencies of the node are processed already, - // then the node can be computed now. - WorkList.push_back(SU); - } - } - - Visited.resize(DAGSize); - -#ifndef NDEBUG - // Check correctness of the ordering - for (SUnit &SU : SUnits) { - for (const SDep &PD : SU.Preds) { - assert(Node2Index[SU.NodeNum] > Node2Index[PD.getSUnit()->NodeNum] && - "Wrong topological sorting"); - } - } -#endif -} - -void ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) { - int UpperBound, LowerBound; - LowerBound = Node2Index[Y->NodeNum]; - UpperBound = Node2Index[X->NodeNum]; - bool HasLoop = false; - // Is Ord(X) < Ord(Y) ? - if (LowerBound < UpperBound) { - // Update the topological order. - Visited.reset(); - DFS(Y, UpperBound, HasLoop); - assert(!HasLoop && "Inserted edge creates a loop!"); - // Recompute topological indexes. - Shift(Visited, LowerBound, UpperBound); - } -} - -void ScheduleDAGTopologicalSort::RemovePred(SUnit *M, SUnit *N) { - // InitDAGTopologicalSorting(); -} - -void ScheduleDAGTopologicalSort::DFS(const SUnit *SU, int UpperBound, - bool &HasLoop) { - std::vector<const SUnit*> WorkList; - WorkList.reserve(SUnits.size()); - - WorkList.push_back(SU); - do { - SU = WorkList.back(); - WorkList.pop_back(); - Visited.set(SU->NodeNum); - for (const SDep &SuccDep - : make_range(SU->Succs.rbegin(), SU->Succs.rend())) { - unsigned s = SuccDep.getSUnit()->NodeNum; - // Edges to non-SUnits are allowed but ignored (e.g. ExitSU). - if (s >= Node2Index.size()) - continue; - if (Node2Index[s] == UpperBound) { - HasLoop = true; - return; - } - // Visit successors if not already and in affected region. - if (!Visited.test(s) && Node2Index[s] < UpperBound) { - WorkList.push_back(SuccDep.getSUnit()); - } - } - } while (!WorkList.empty()); -} - -std::vector<int> ScheduleDAGTopologicalSort::GetSubGraph(const SUnit &StartSU, - const SUnit &TargetSU, - bool &Success) { - std::vector<const SUnit*> WorkList; - int LowerBound = Node2Index[StartSU.NodeNum]; - int UpperBound = Node2Index[TargetSU.NodeNum]; - bool Found = false; - BitVector VisitedBack; - std::vector<int> Nodes; - - if (LowerBound > UpperBound) { - Success = false; - return Nodes; - } - - WorkList.reserve(SUnits.size()); - Visited.reset(); - - // Starting from StartSU, visit all successors up - // to UpperBound. - WorkList.push_back(&StartSU); - do { - const SUnit *SU = WorkList.back(); - WorkList.pop_back(); - for (int I = SU->Succs.size()-1; I >= 0; --I) { - const SUnit *Succ = SU->Succs[I].getSUnit(); - unsigned s = Succ->NodeNum; - // Edges to non-SUnits are allowed but ignored (e.g. ExitSU). - if (Succ->isBoundaryNode()) - continue; - if (Node2Index[s] == UpperBound) { - Found = true; - continue; - } - // Visit successors if not already and in affected region. - if (!Visited.test(s) && Node2Index[s] < UpperBound) { - Visited.set(s); - WorkList.push_back(Succ); - } - } - } while (!WorkList.empty()); - - if (!Found) { - Success = false; - return Nodes; - } - - WorkList.clear(); - VisitedBack.resize(SUnits.size()); - Found = false; - - // Starting from TargetSU, visit all predecessors up - // to LowerBound. SUs that are visited by the two - // passes are added to Nodes. - WorkList.push_back(&TargetSU); - do { - const SUnit *SU = WorkList.back(); - WorkList.pop_back(); - for (int I = SU->Preds.size()-1; I >= 0; --I) { - const SUnit *Pred = SU->Preds[I].getSUnit(); - unsigned s = Pred->NodeNum; - // Edges to non-SUnits are allowed but ignored (e.g. EntrySU). - if (Pred->isBoundaryNode()) - continue; - if (Node2Index[s] == LowerBound) { - Found = true; - continue; - } - if (!VisitedBack.test(s) && Visited.test(s)) { - VisitedBack.set(s); - WorkList.push_back(Pred); - Nodes.push_back(s); - } - } - } while (!WorkList.empty()); - - assert(Found && "Error in SUnit Graph!"); - Success = true; - return Nodes; -} - -void ScheduleDAGTopologicalSort::Shift(BitVector& Visited, int LowerBound, - int UpperBound) { - std::vector<int> L; - int shift = 0; - int i; - - for (i = LowerBound; i <= UpperBound; ++i) { - // w is node at topological index i. - int w = Index2Node[i]; - if (Visited.test(w)) { - // Unmark. - Visited.reset(w); - L.push_back(w); - shift = shift + 1; - } else { - Allocate(w, i - shift); - } - } - - for (unsigned LI : L) { - Allocate(LI, i - shift); - i = i + 1; - } -} - -bool ScheduleDAGTopologicalSort::WillCreateCycle(SUnit *TargetSU, SUnit *SU) { - // Is SU reachable from TargetSU via successor edges? - if (IsReachable(SU, TargetSU)) - return true; - for (const SDep &PredDep : TargetSU->Preds) - if (PredDep.isAssignedRegDep() && - IsReachable(SU, PredDep.getSUnit())) - return true; - return false; -} - -bool ScheduleDAGTopologicalSort::IsReachable(const SUnit *SU, - const SUnit *TargetSU) { - // If insertion of the edge SU->TargetSU would create a cycle - // then there is a path from TargetSU to SU. - int UpperBound, LowerBound; - LowerBound = Node2Index[TargetSU->NodeNum]; - UpperBound = Node2Index[SU->NodeNum]; - bool HasLoop = false; - // Is Ord(TargetSU) < Ord(SU) ? - if (LowerBound < UpperBound) { - Visited.reset(); - // There may be a path from TargetSU to SU. Check for it. - DFS(TargetSU, UpperBound, HasLoop); - } - return HasLoop; -} - -void ScheduleDAGTopologicalSort::Allocate(int n, int index) { - Node2Index[n] = index; - Index2Node[index] = n; -} - -ScheduleDAGTopologicalSort:: -ScheduleDAGTopologicalSort(std::vector<SUnit> &sunits, SUnit *exitsu) - : SUnits(sunits), ExitSU(exitsu) {} - -ScheduleHazardRecognizer::~ScheduleHazardRecognizer() = default; |
