[PATCH] [ADT] Add a leader_iterator to EquivalenceClasses

Adam Nemet anemet at apple.com
Thu Jul 2 09:58:49 PDT 2015


Yeah, I think what you say sounds applicable here.  Let me play with this to try to generalize the filtering capability.

> On Jul 2, 2015, at 9:18 AM, David Blaikie <dblaikie at gmail.com> wrote:
> 
> (shooting from the hip a bit - only glanced at the code)
> 
> It'd be good to have a generic filtering iterator abstraction as we already have a few uses for such a thing special cased & could refactor those out. (I'd have to go looking to find the existing examples if none come to mind/are already known to you)
> 
> It could take a function pointer as a non-type template parameter, or a lambda (ugh, stateless lambdas still aren't default constructible, and I'm not sure you can derive from them, so I don't know if you can do the empty base class optimization with them... )
> 
> On Wed, Jul 1, 2015 at 11:53 PM, Adam Nemet <anemet at apple.com <mailto:anemet at apple.com>> wrote:
> Hi dblaikie, dexonsmith,
> 
> Recently we had a bug that was caught during the review where the
> isLeader check was mistakenly omitted from the usual pattern of
> traversing an EC:
> 
>   for (EquivalenceClasses<int>::iterator I = EC.begin(), E = EC.end();
>        I != E; ++I) {
>     if (!I->isLeader()) continue // <----------- this line
>     for (EquivalenceClasses<int>::member_iterator MI = EC.member_begin(I);
>          MI != EC.member_end(); ++MI)
>       ...
> 
> I don't think that anything bad really happens if the check is omitted
> other than some overhead but that made me think if we could have an
> iterator in the outer loop that only traverses the leaders/classes:
> 
>   for (EquivalenceClasses<int>::leader_iterator I = EC.leader_begin(),
>          E = EC.leader_end(); I != E; ++I) {
>     for (EquivalenceClasses<int>::member_iterator MI = EC.member_begin(I);
>          MI != EC.member_end(); ++MI)
>       ...
> 
> EC internally uses a set, so leader_iterator is built on top of the
> set::iterator.  In addition, it also needs the end iterator to avoid
> over-running the set when looking for the leader.
> 
> Let me know if this seems like a good idea and then I will update the
> patch with unit tests.
> 
> http://reviews.llvm.org/D10891 <http://reviews.llvm.org/D10891>
> 
> Files:
>   include/llvm/ADT/EquivalenceClasses.h
> 
> Index: include/llvm/ADT/EquivalenceClasses.h
> ===================================================================
> --- include/llvm/ADT/EquivalenceClasses.h
> +++ include/llvm/ADT/EquivalenceClasses.h
> @@ -15,6 +15,7 @@
>  #ifndef LLVM_ADT_EQUIVALENCECLASSES_H
>  #define LLVM_ADT_EQUIVALENCECLASSES_H
> 
> +#include "llvm/ADT/iterator.h"
>  #include "llvm/Support/DataTypes.h"
>  #include <cassert>
>  #include <cstddef>
> @@ -150,10 +151,23 @@
>      // Only leaders provide anything to iterate over.
>      return member_iterator(I->isLeader() ? &*I : nullptr);
>    }
> +  class leader_iterator;
> +  member_iterator member_begin(leader_iterator I) const {
> +    return member_iterator(&*I);
> +  }
>    member_iterator member_end() const {
>      return member_iterator(nullptr);
>    }
> 
> +  /// Iterate over the leaders (i.e. the equivalence classes).
> +  leader_iterator leader_begin() const {
> +    // Only leaders provide anything to iterate over.
> +    return leader_iterator(TheMapping.begin(), TheMapping.end());
> +  }
> +  leader_iterator leader_end() const {
> +    return leader_iterator(TheMapping.end(), TheMapping.end());
> +  }
> +
>    /// findValue - Return an iterator to the specified value.  If it does not
>    /// exist, end() is returned.
>    iterator findValue(const ElemTy &V) const {
> @@ -276,6 +290,51 @@
>        return Node != RHS.Node;
>      }
>    };
> +
> +  class leader_iterator
> +      : public iterator_facade_base<leader_iterator, std::forward_iterator_tag,
> +                                    const ECValue> {
> +    typedef iterator_facade_base<leader_iterator, std::forward_iterator_tag,
> +                                 const ECValue> super;
> +
> +    iterator Iter;
> +    iterator End;
> +
> +    void findLeader() {
> +      for (; Iter != End; ++Iter)
> +        if (Iter->isLeader())
> +          break;
> +    }
> +
> +  public:
> +    typedef size_t size_type;
> +    typedef typename super::pointer pointer;
> +    typedef typename super::reference reference;
> +
> +    explicit leader_iterator() {}
> +    explicit leader_iterator(iterator First, iterator Last)
> +        : Iter(First), End(Last) {
> +      // Ensure that Iter is pointing at the first leader.
> +      findLeader();
> +    }
> +
> +    leader_iterator &operator++() {
> +      assert(Iter != End && "++'d off the end of the list!");
> +      ++Iter;
> +      // If this is not a leader, keep going.
> +      findLeader();
> +      return *this;
> +    }
> +
> +    reference operator*() const {
> +      assert(Iter != End && "Dereferencing end()!");
> +      return *Iter;
> +    }
> +
> +    bool operator==(const leader_iterator &RHS) const {
> +      return Iter == RHS.Iter;
> +    }
> +  };
>  };
> 
>  } // End llvm namespace
> 
> EMAIL PREFERENCES
>   http://reviews.llvm.org/settings/panel/emailpreferences/ <http://reviews.llvm.org/settings/panel/emailpreferences/>
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150702/0b3fd0c8/attachment.html>


More information about the llvm-commits mailing list