23 #ifndef LLVM_ADT_SCCITERATOR_H
24 #define LLVM_ADT_SCCITERATOR_H
42 template <
class GraphT,
class GT = GraphTraits<GraphT>>
44 scc_iterator<GraphT, GT>, std::forward_iterator_tag,
45 const std::vector<typename GT::NodeRef>, ptrdiff_t> {
46 typedef typename GT::NodeRef NodeRef;
47 typedef typename GT::ChildIteratorType ChildItTy;
48 typedef std::vector<NodeRef> SccTy;
49 typedef typename scc_iterator::reference reference;
57 StackElement(NodeRef Node,
const ChildItTy &Child,
unsigned Min)
58 : Node(Node), NextChild(Child), MinVisited(Min) {}
61 return Node == Other.Node &&
62 NextChild == Other.NextChild &&
63 MinVisited == Other.MinVisited;
75 std::vector<NodeRef> SCCNodeStack;
82 std::vector<StackElement> VisitStack;
85 void DFSVisitOne(NodeRef
N);
88 void DFSVisitChildren();
110 assert(!CurrentSCC.empty() || VisitStack.empty());
111 return CurrentSCC.empty();
115 return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC;
124 assert(!CurrentSCC.empty() &&
"Dereferencing END SCC iterator!");
137 assert(nodeVisitNumbers.
count(Old) &&
"Old not in scc_iterator?");
138 nodeVisitNumbers[New] = nodeVisitNumbers[Old];
139 nodeVisitNumbers.
erase(Old);
143 template <
class GraphT,
class GT>
144 void scc_iterator<GraphT, GT>::DFSVisitOne(NodeRef
N) {
146 nodeVisitNumbers[
N] = visitNum;
147 SCCNodeStack.push_back(N);
148 VisitStack.push_back(StackElement(N, GT::child_begin(N), visitNum));
149 #if 0 // Enable if needed when debugging.
150 dbgs() <<
"TarjanSCC: Node " << N <<
151 " : visitNum = " << visitNum <<
"\n";
155 template <
class GraphT,
class GT>
156 void scc_iterator<GraphT, GT>::DFSVisitChildren() {
157 assert(!VisitStack.empty());
158 while (VisitStack.back().NextChild != GT::child_end(VisitStack.back().Node)) {
160 NodeRef childN = *VisitStack.back().NextChild++;
162 nodeVisitNumbers.find(childN);
163 if (Visited == nodeVisitNumbers.end()) {
169 unsigned childNum = Visited->second;
170 if (VisitStack.back().MinVisited > childNum)
171 VisitStack.back().MinVisited = childNum;
175 template <
class GraphT,
class GT>
void scc_iterator<GraphT, GT>::GetNextSCC() {
177 while (!VisitStack.empty()) {
181 NodeRef visitingN = VisitStack.back().Node;
182 unsigned minVisitNum = VisitStack.back().MinVisited;
183 assert(VisitStack.back().NextChild == GT::child_end(visitingN));
184 VisitStack.pop_back();
187 if (!VisitStack.empty() && VisitStack.back().MinVisited > minVisitNum)
188 VisitStack.back().MinVisited = minVisitNum;
190 #if 0 // Enable if needed when debugging.
191 dbgs() <<
"TarjanSCC: Popped node " << visitingN <<
192 " : minVisitNum = " << minVisitNum <<
"; Node visit num = " <<
193 nodeVisitNumbers[visitingN] <<
"\n";
196 if (minVisitNum != nodeVisitNumbers[visitingN])
204 CurrentSCC.push_back(SCCNodeStack.back());
205 SCCNodeStack.pop_back();
206 nodeVisitNumbers[CurrentSCC.back()] = ~0U;
207 }
while (CurrentSCC.back() != visitingN);
212 template <
class GraphT,
class GT>
214 assert(!CurrentSCC.empty() &&
"Dereferencing END SCC iterator!");
215 if (CurrentSCC.size() > 1)
217 NodeRef N = CurrentSCC.front();
218 for (ChildItTy CI = GT::child_begin(N), CE = GT::child_end(N); CI != CE;
247 #endif // LLVM_ADT_SCCITERATOR_H
reference operator*() const
const_iterator end(StringRef path)
Get end iterator over path.
void ReplaceNode(NodeRef Old, NodeRef New)
This informs the scc_iterator that the specified Old node has been deleted, and New is to be used in ...
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.
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.
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > 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 &)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static scc_iterator begin(const GraphT &G)
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.