+//===----------------------------------------------------------------------===//
+// SchedDFSResult Implementation
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+/// \brief Internal state used to compute SchedDFSResult.
+class SchedDFSImpl {
+ SchedDFSResult &R;
+
+ /// Join DAG nodes into equivalence classes by their subtree.
+ IntEqClasses SubtreeClasses;
+ /// List PredSU, SuccSU pairs that represent data edges between subtrees.
+ std::vector<std::pair<const SUnit*, const SUnit*> > ConnectionPairs;
+
+public:
+ SchedDFSImpl(SchedDFSResult &r): R(r), SubtreeClasses(R.DFSData.size()) {}
+
+ /// SubtreID is initialized to zero, set to itself to flag the root of a
+ /// subtree, set to the parent to indicate an interior node,
+ /// then set to a representative subtree ID during finalization.
+ bool isVisited(const SUnit *SU) const {
+ return R.DFSData[SU->NodeNum].SubtreeID;
+ }
+
+ /// Initialize this node's instruction count. We don't need to flag the node
+ /// visited until visitPostorder because the DAG cannot have cycles.
+ void visitPreorder(const SUnit *SU) {
+ R.DFSData[SU->NodeNum].InstrCount = SU->getInstr()->isTransient() ? 0 : 1;
+ }
+
+ /// Mark this node as either the root of a subtree or an interior
+ /// node. Increment the parent node's instruction count.
+ void visitPostorder(const SUnit *SU, const SDep *PredDep, const SUnit *Parent) {
+ R.DFSData[SU->NodeNum].SubtreeID = SU->NodeNum;
+
+ // Join the child to its parent if they are connected via data dependence
+ // and do not exceed the limit.
+ if (!Parent || PredDep->getKind() != SDep::Data)
+ return;
+
+ unsigned PredCnt = R.DFSData[SU->NodeNum].InstrCount;
+ if (PredCnt > R.SubtreeLimit)
+ return;
+
+ R.DFSData[SU->NodeNum].SubtreeID = Parent->NodeNum;
+
+ // Add the recently finished predecessor's bottom-up descendent count.
+ R.DFSData[Parent->NodeNum].InstrCount += PredCnt;
+ SubtreeClasses.join(Parent->NodeNum, SU->NodeNum);
+ }
+
+ /// Determine whether the DFS cross edge should be considered a subtree edge
+ /// or a connection between subtrees.
+ void visitCross(const SDep &PredDep, const SUnit *Succ) {
+ if (PredDep.getKind() == SDep::Data) {
+ // If this is a cross edge to a root, join the subtrees. This happens when
+ // the root was first reached by a non-data dependence.
+ unsigned NodeNum = PredDep.getSUnit()->NodeNum;
+ unsigned PredCnt = R.DFSData[NodeNum].InstrCount;
+ if (R.DFSData[NodeNum].SubtreeID == NodeNum && PredCnt < R.SubtreeLimit) {
+ R.DFSData[NodeNum].SubtreeID = Succ->NodeNum;
+ R.DFSData[Succ->NodeNum].InstrCount += PredCnt;
+ SubtreeClasses.join(Succ->NodeNum, NodeNum);
+ return;
+ }
+ }
+ ConnectionPairs.push_back(std::make_pair(PredDep.getSUnit(), Succ));
+ }
+
+ /// Set each node's subtree ID to the representative ID and record connections
+ /// between trees.
+ void finalize() {
+ SubtreeClasses.compress();
+ R.SubtreeConnections.resize(SubtreeClasses.getNumClasses());
+ R.SubtreeConnectLevels.resize(SubtreeClasses.getNumClasses());
+ DEBUG(dbgs() << R.getNumSubtrees() << " subtrees:\n");
+ for (unsigned Idx = 0, End = R.DFSData.size(); Idx != End; ++Idx) {
+ R.DFSData[Idx].SubtreeID = SubtreeClasses[Idx];
+ DEBUG(dbgs() << " SU(" << Idx << ") in tree "
+ << R.DFSData[Idx].SubtreeID << '\n');
+ }
+ for (std::vector<std::pair<const SUnit*, const SUnit*> >::const_iterator
+ I = ConnectionPairs.begin(), E = ConnectionPairs.end();
+ I != E; ++I) {
+ unsigned PredTree = SubtreeClasses[I->first->NodeNum];
+ unsigned SuccTree = SubtreeClasses[I->second->NodeNum];
+ if (PredTree == SuccTree)
+ continue;
+ unsigned Depth = I->first->getDepth();
+ addConnection(PredTree, SuccTree, Depth);
+ addConnection(SuccTree, PredTree, Depth);
+ }
+ }
+
+protected:
+ /// Called by finalize() to record a connection between trees.
+ void addConnection(unsigned FromTree, unsigned ToTree, unsigned Depth) {
+ if (!Depth)
+ return;
+
+ SmallVectorImpl<SchedDFSResult::Connection> &Connections =
+ R.SubtreeConnections[FromTree];
+ for (SmallVectorImpl<SchedDFSResult::Connection>::iterator
+ I = Connections.begin(), E = Connections.end(); I != E; ++I) {
+ if (I->TreeID == ToTree) {
+ I->Level = std::max(I->Level, Depth);
+ return;
+ }
+ }
+ Connections.push_back(SchedDFSResult::Connection(ToTree, Depth));
+ }
+};
+} // namespace llvm
+