[LLVMdev] [PATCH] Add functionality to scc_iterator
Vikram S. Adve
vadve at illinois.edu
Fri Aug 7 12:51:28 PDT 2009
Checking if a graph node is in a cycle or not must be a relatively
common query. E.g., we used this on DS graphs to decide if DS node
represented multiple objects or a single object. It's the basic query
to decide if a function is part of a recursive computation (a cycle in
the call graph). CFGs happen to have special code for natural loops
but you could use this query to handle irreducible loops as well.
--Vikram
Associate Professor, Computer Science
University of Illinois at Urbana-Champaign
http://llvm.org/~vadve
On Aug 7, 2009, at 2:22 PM, Patrick Alexander Simmons wrote:
> 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 *)
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
More information about the llvm-dev
mailing list