[LLVMdev] [PATCH] Add functionality to scc_iterator
Patrick Alexander Simmons
simmon12 at cs.uiuc.edu
Fri Aug 7 12:22:38 PDT 2009
Chris Lattner wrote:
> It's more of an algorithm than a datastructure. Where else in the
> codebase would it be useful to use? If only in one place, it is
> probably reasonable to put it near the code that uses it.
>
> -Chris
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
I'm not sure where specifically it might be useful in the codebase; I
wrote it for use in an external (currently not public) project. I could
just put it in the utility header for that project, but then it wouldn't
be available to others, so I thought SCCIterator.h would be a better
place. I figured people who'd be interested in detecting cycles might
look in SCCIterator.h for a way to do so and find that code. It could
also serve as an example of how to use scc_iterator, and, since it's a
template, there's no penalty for having it in there if it's not used
anywhere. What a deal, right?
If you don't want it in LLVM, I'll put it back in my utility header
file, but I've included it in my revised patch in case you change your
mind. The revised patch does the following things:
1. Changes the templates of scc_begin and scc_end to pass by constant
reference rather than value (no reason to do a copy unless you have to).
2. Adds the inverse graph scc_begin and scc_end templates (similarly
fixed to pass by constant reference rather than value).
3. Adds the cycle-detection code as "is_in_cycle" rather than
"bb_reachable".
3. Fixes an incorrect comment in the GraphTraits.h header.
Index: include/llvm/ADT/SCCIterator.h
===================================================================
--- include/llvm/ADT/SCCIterator.h (revision 76093)
+++ include/llvm/ADT/SCCIterator.h (working copy)
@@ -135,8 +135,8 @@
typedef scc_iterator<GraphT, GT> _Self;
// Provide static "constructors"...
- static inline _Self begin(GraphT& G) { return
_Self(GT::getEntryNode(G)); }
- static inline _Self end (GraphT& G) { return _Self(); }
+ static inline _Self begin(const GraphT& G) { return
_Self(GT::getEntryNode(G)); }
+ static inline _Self end (const GraphT& G) { return _Self(); }
// Direct loop termination test (I.fini() is more efficient than I ==
end())
inline bool fini() const {
@@ -185,15 +185,43 @@
// Global constructor for the SCC iterator.
template <class T>
-scc_iterator<T> scc_begin(T G) {
+scc_iterator<T> scc_begin(const T& G) {
return scc_iterator<T>::begin(G);
}
template <class T>
-scc_iterator<T> scc_end(T G) {
+scc_iterator<T> scc_end(const T& G) {
return scc_iterator<T>::end(G);
}
+template <class T>
+scc_iterator<Inverse<T> > scc_begin(const Inverse<T>& G) {
+ return scc_iterator<Inverse<T> >::begin(G);
+}
+
+template <class T>
+scc_iterator<Inverse<T> > scc_end(const Inverse<T>& G) {
+ return scc_iterator<Inverse<T> >::end(G);
+}
+
+/*Discover whether a graph node is part of any cycle, including a
self-cycle.*/
+template<class T>
+bool is_in_cycle(T* bb)
+{
+ /*Return true iff we are in a nonsingular SCC.*/
+ scc_iterator<T*> cur = scc_begin(bb);
+ while(cur!=scc_end(bb))
+ {
+ for(typename std::vector<typename
GraphTraits<T*>::NodeType*>::iterator i = (*cur).begin();
i!=(*cur).end(); i++)
+ if(*i==bb)
+ return cur.hasLoop();
+ cur++;
+ }
+
+ //We should never get here.
+ abort();
+}
+
} // End llvm namespace
#endif
Index: include/llvm/ADT/GraphTraits.h
===================================================================
--- include/llvm/ADT/GraphTraits.h (revision 76093)
+++ include/llvm/ADT/GraphTraits.h (working copy)
@@ -30,7 +30,7 @@
// typedef NodeType - Type of Node in the graph
// typedef ChildIteratorType - Type used to iterate over children in
graph
- // static NodeType *getEntryNode(GraphType *)
+ // static NodeType *getEntryNode(const GraphType &)
// Return the entry node of the graph
// static ChildIteratorType child_begin(NodeType *)
More information about the llvm-dev
mailing list