23 #ifndef LLVM_ADT_SCCITERATOR_H
24 #define LLVM_ADT_SCCITERATOR_H
39 template <
class GraphT,
class GT = GraphTraits<GraphT>>
42 scc_iterator<GraphT, GT>, std::forward_iterator_tag,
43 const std::vector<typename GT::NodeType *>, ptrdiff_t> {
45 typedef typename GT::ChildIteratorType ChildItTy;
46 typedef std::vector<NodeType *> SccTy;
47 typedef typename scc_iterator::reference reference;
55 StackElement(NodeType *Node,
const ChildItTy &Child,
unsigned Min)
56 : Node(Node), NextChild(Child), MinVisited(Min) {}
59 return Node == Other.Node &&
60 NextChild == Other.NextChild &&
61 MinVisited == Other.MinVisited;
73 std::vector<NodeType *> SCCNodeStack;
80 std::vector<StackElement> VisitStack;
83 void DFSVisitOne(NodeType *
N);
86 void DFSVisitChildren();
108 assert(!CurrentSCC.empty() || VisitStack.empty());
109 return CurrentSCC.empty();
113 return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC;
122 assert(!CurrentSCC.empty() &&
"Dereferencing END SCC iterator!");
135 assert(nodeVisitNumbers.
count(Old) &&
"Old not in scc_iterator?");
136 nodeVisitNumbers[New] = nodeVisitNumbers[Old];
137 nodeVisitNumbers.
erase(Old);
141 template <
class GraphT,
class GT>
142 void scc_iterator<GraphT, GT>::DFSVisitOne(
NodeType *
N) {
144 nodeVisitNumbers[
N] = visitNum;
145 SCCNodeStack.push_back(N);
146 VisitStack.push_back(StackElement(N, GT::child_begin(N), visitNum));
147 #if 0 // Enable if needed when debugging.
148 dbgs() <<
"TarjanSCC: Node " << N <<
149 " : visitNum = " << visitNum <<
"\n";
153 template <
class GraphT,
class GT>
154 void scc_iterator<GraphT, GT>::DFSVisitChildren() {
155 assert(!VisitStack.empty());
156 while (VisitStack.back().NextChild != GT::child_end(VisitStack.back().Node)) {
158 NodeType *childN = *VisitStack.back().NextChild++;
160 nodeVisitNumbers.find(childN);
161 if (Visited == nodeVisitNumbers.end()) {
167 unsigned childNum = Visited->second;
168 if (VisitStack.back().MinVisited > childNum)
169 VisitStack.back().MinVisited = childNum;
173 template <
class GraphT,
class GT>
void scc_iterator<GraphT, GT>::GetNextSCC() {
175 while (!VisitStack.empty()) {
179 NodeType *visitingN = VisitStack.back().Node;
180 unsigned minVisitNum = VisitStack.back().MinVisited;
181 assert(VisitStack.back().NextChild == GT::child_end(visitingN));
182 VisitStack.pop_back();
185 if (!VisitStack.empty() && VisitStack.back().MinVisited > minVisitNum)
186 VisitStack.back().MinVisited = minVisitNum;
188 #if 0 // Enable if needed when debugging.
189 dbgs() <<
"TarjanSCC: Popped node " << visitingN <<
190 " : minVisitNum = " << minVisitNum <<
"; Node visit num = " <<
191 nodeVisitNumbers[visitingN] <<
"\n";
194 if (minVisitNum != nodeVisitNumbers[visitingN])
202 CurrentSCC.push_back(SCCNodeStack.back());
203 SCCNodeStack.pop_back();
204 nodeVisitNumbers[CurrentSCC.back()] = ~0U;
205 }
while (CurrentSCC.back() != visitingN);
210 template <
class GraphT,
class GT>
212 assert(!CurrentSCC.empty() &&
"Dereferencing END SCC iterator!");
213 if (CurrentSCC.size() > 1)
215 NodeType *N = CurrentSCC.front();
216 for (ChildItTy CI = GT::child_begin(N), CE = GT::child_end(N); CI != CE;
reference operator*() const
const_iterator end(StringRef path)
Get end iterator over path.
scc_iterator & operator++()
bool isAtEnd() const
Direct loop termination test which is more efficient than comparison with end().
const_iterator begin(StringRef path)
Get begin iterator over path.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
bool hasLoop() const
Test if the current SCC has a loop.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
bool erase(const KeyT &Val)
scc_iterator< T > scc_end(const T &G)
Construct the end iterator for a deduced graph type T.
void ReplaceNode(NodeType *Old, NodeType *New)
This informs the scc_iterator that the specified Old node has been deleted, and New is to be used in ...
DenseMapIterator< NodeType *, unsigned, DenseMapInfo< NodeType * >, detail::DenseMapPair< NodeType *, unsigned > > iterator
bool operator==(const scc_iterator &x) const
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
static scc_iterator end(const GraphT &)
static scc_iterator begin(const GraphT &G)
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.