[llvm] r297633 - [ADT] Improve the genericity of llvm::enumerate().

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 13 11:47:03 PDT 2017


I believe I've fixed all of these (including the one you linked to above),
but it's taking some time for the builders to cycle.

On Mon, Mar 13, 2017 at 11:46 AM Adrian Prantl <aprantl at apple.com> wrote:

> This seems to have broken some bots:
>
>
> http://green.lab.llvm.org/green/job/clang-stage1-cmake-RA-incremental_build/36596/consoleFull#67046690349ba4694-19c4-4d7e-bec5-911270d8a58c
>
> could you please take a look?
> -- adrian
>
> On Mar 13, 2017, at 9:24 AM, Zachary Turner via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
> Author: zturner
> Date: Mon Mar 13 11:24:10 2017
> New Revision: 297633
>
> URL: http://llvm.org/viewvc/llvm-project?rev=297633&view=rev
> Log:
> [ADT] Improve the genericity of llvm::enumerate().
>
> There were some issues in the implementation of enumerate()
> preventing it from being used in various contexts.  These were
> all related to the fact that it did not supporter llvm's
> iterator_facade_base class.  So this patch adds support for that
> and additionally exposes a new helper method to_vector() that
> will evaluate an entire range and store the results in a
> vector.
>
> Differential Revision: https://reviews.llvm.org/D30853
>
> Modified:
>    llvm/trunk/include/llvm/ADT/STLExtras.h
>    llvm/trunk/unittests/ADT/STLExtrasTest.cpp
>    llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
>
> Modified: llvm/trunk/include/llvm/ADT/STLExtras.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/STLExtras.h?rev=297633&r1=297632&r2=297633&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/STLExtras.h (original)
> +++ llvm/trunk/include/llvm/ADT/STLExtras.h Mon Mar 13 11:24:10 2017
> @@ -28,6 +28,7 @@
> #include <utility> // for std::pair
>
> #include "llvm/ADT/Optional.h"
> +#include "llvm/ADT/SmallVector.h"
> #include "llvm/ADT/iterator.h"
> #include "llvm/ADT/iterator_range.h"
> #include "llvm/Support/Compiler.h"
> @@ -44,6 +45,10 @@ namespace detail {
> template <typename RangeT>
> using IterOfRange = decltype(std::begin(std::declval<RangeT &>()));
>
> +template <typename RangeT>
> +using ValueOfRange = typename std::remove_reference<decltype(
> +    *std::begin(std::declval<RangeT &>()))>::type;
> +
> } // End detail namespace
>
>
> //===----------------------------------------------------------------------===//
> @@ -883,6 +888,14 @@ auto partition(R &&Range, UnaryPredicate
>   return std::partition(std::begin(Range), std::end(Range), P);
> }
>
> +/// \brief Given a range of type R, iterate the entire range and return a
> +/// SmallVector with elements of the vector.  This is useful, for example,
> +/// when you want to iterate a range and then sort the results.
> +template <unsigned Size, typename R>
> +SmallVector<detail::ValueOfRange<R>, Size> to_vector(R &&Range) {
> +  return {std::begin(Range), std::end(Range)};
> +}
> +
> /// Provide a container algorithm similar to C++ Library Fundamentals v2's
> /// `erase_if` which is equivalent to:
> ///
> @@ -977,47 +990,82 @@ template <typename T> struct deref {
> };
>
> namespace detail {
> -template <typename R> class enumerator_impl {
> +template <typename R> class enumerator_iter;
> +
> +template <typename R> struct result_pair {
> +  friend class enumerator_iter<R>;
> +
> +  result_pair() : Index(-1) {}
> +  result_pair(std::size_t Index, IterOfRange<R> Iter)
> +      : Index(Index), Iter(Iter) {}
> +
> +  result_pair<R> &operator=(const result_pair<R> &Other) {
> +    Index = Other.Index;
> +    Iter = Other.Iter;
> +    return *this;
> +  }
> +
> +  std::size_t index() const { return Index; }
> +  const ValueOfRange<R> &value() const { return *Iter; }
> +  ValueOfRange<R> &value() { return *Iter; }
> +
> +private:
> +  std::size_t Index;
> +  IterOfRange<R> Iter;
> +};
> +
> +template <typename R>
> +class enumerator_iter
> +    : public iterator_facade_base<
> +          enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>,
> +          typename std::iterator_traits<IterOfRange<R>>::difference_type,
> +          typename std::iterator_traits<IterOfRange<R>>::pointer,
> +          typename std::iterator_traits<IterOfRange<R>>::reference> {
> +  using result_type = result_pair<R>;
> +
> public:
> -  template <typename X> struct result_pair {
> -    result_pair(std::size_t Index, X Value) : Index(Index), Value(Value)
> {}
> +  enumerator_iter(std::size_t Index, IterOfRange<R> Iter)
> +      : Result(Index, Iter) {}
>
> -    const std::size_t Index;
> -    X Value;
> -  };
> +  result_type &operator*() { return Result; }
> +  const result_type &operator*() const { return Result; }
>
> -  class iterator {
> -    typedef
> -        typename std::iterator_traits<IterOfRange<R>>::reference
> iter_reference;
> -    typedef result_pair<iter_reference> result_type;
> -
> -  public:
> -    iterator(IterOfRange<R> &&Iter, std::size_t Index)
> -        : Iter(Iter), Index(Index) {}
> -
> -    result_type operator*() const { return result_type(Index, *Iter); }
> -
> -    iterator &operator++() {
> -      ++Iter;
> -      ++Index;
> -      return *this;
> -    }
> -
> -    bool operator!=(const iterator &RHS) const { return Iter != RHS.Iter;
> }
> -
> -  private:
> -    IterOfRange<R> Iter;
> -    std::size_t Index;
> -  };
> +  enumerator_iter<R> &operator++() {
> +    assert(Result.Index != -1);
> +    ++Result.Iter;
> +    ++Result.Index;
> +    return *this;
> +  }
> +
> +  bool operator==(const enumerator_iter<R> &RHS) const {
> +    // Don't compare indices here, only iterators.  It's possible for an
> end
> +    // iterator to have different indices depending on whether it was
> created
> +    // by calling std::end() versus incrementing a valid iterator.
> +    return Result.Iter == RHS.Result.Iter;
> +  }
> +
> +  enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) {
> +    Result = Other.Result;
> +    return *this;
> +  }
>
> +private:
> +  result_type Result;
> +};
> +
> +template <typename R> class enumerator {
> public:
> -  explicit enumerator_impl(R &&Range) : Range(std::forward<R>(Range)) {}
> +  explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {}
>
> -  iterator begin() { return iterator(std::begin(Range), 0); }
> -  iterator end() { return iterator(std::end(Range), std::size_t(-1)); }
> +  enumerator_iter<R> begin() {
> +    return enumerator_iter<R>(0, std::begin(TheRange));
> +  }
> +  enumerator_iter<R> end() {
> +    return enumerator_iter<R>(-1, std::end(TheRange));
> +  }
>
> private:
> -  R Range;
> +  R TheRange;
> };
> }
>
> @@ -1036,8 +1084,8 @@ private:
> ///   Item 2 - C
> ///   Item 3 - D
> ///
> -template <typename R> detail::enumerator_impl<R> enumerate(R &&Range) {
> -  return detail::enumerator_impl<R>(std::forward<R>(Range));
> +template <typename R> detail::enumerator<R> enumerate(R &&TheRange) {
> +  return detail::enumerator<R>(std::forward<R>(TheRange));
> }
>
> namespace detail {
>
> Modified: llvm/trunk/unittests/ADT/STLExtrasTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/STLExtrasTest.cpp?rev=297633&r1=297632&r2=297633&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/ADT/STLExtrasTest.cpp (original)
> +++ llvm/trunk/unittests/ADT/STLExtrasTest.cpp Mon Mar 13 11:24:10 2017
> @@ -48,7 +48,7 @@ TEST(STLExtrasTest, EnumerateLValue) {
>   std::vector<CharPairType> CharResults;
>
>   for (auto X : llvm::enumerate(foo)) {
> -    CharResults.emplace_back(X.Index, X.Value);
> +    CharResults.emplace_back(X.index(), X.value());
>   }
>   ASSERT_EQ(3u, CharResults.size());
>   EXPECT_EQ(CharPairType(0u, 'a'), CharResults[0]);
> @@ -60,7 +60,7 @@ TEST(STLExtrasTest, EnumerateLValue) {
>   std::vector<IntPairType> IntResults;
>   const std::vector<int> bar = {1, 2, 3};
>   for (auto X : llvm::enumerate(bar)) {
> -    IntResults.emplace_back(X.Index, X.Value);
> +    IntResults.emplace_back(X.index(), X.value());
>   }
>   ASSERT_EQ(3u, IntResults.size());
>   EXPECT_EQ(IntPairType(0u, 1), IntResults[0]);
> @@ -71,7 +71,7 @@ TEST(STLExtrasTest, EnumerateLValue) {
>   IntResults.clear();
>   const std::vector<int> baz{};
>   for (auto X : llvm::enumerate(baz)) {
> -    IntResults.emplace_back(X.Index, X.Value);
> +    IntResults.emplace_back(X.index(), X.value());
>   }
>   EXPECT_TRUE(IntResults.empty());
> }
> @@ -82,7 +82,7 @@ TEST(STLExtrasTest, EnumerateModifyLValu
>   std::vector<char> foo = {'a', 'b', 'c'};
>
>   for (auto X : llvm::enumerate(foo)) {
> -    ++X.Value;
> +    ++X.value();
>   }
>   EXPECT_EQ('b', foo[0]);
>   EXPECT_EQ('c', foo[1]);
> @@ -97,7 +97,7 @@ TEST(STLExtrasTest, EnumerateRValueRef)
>   auto Enumerator = llvm::enumerate(std::vector<int>{1, 2, 3});
>
>   for (auto X : llvm::enumerate(std::vector<int>{1, 2, 3})) {
> -    Results.emplace_back(X.Index, X.Value);
> +    Results.emplace_back(X.index(), X.value());
>   }
>
>   ASSERT_EQ(3u, Results.size());
> @@ -114,8 +114,8 @@ TEST(STLExtrasTest, EnumerateModifyRValu
>   std::vector<PairType> Results;
>
>   for (auto X : llvm::enumerate(std::vector<char>{'1', '2', '3'})) {
> -    ++X.Value;
> -    Results.emplace_back(X.Index, X.Value);
> +    ++X.value();
> +    Results.emplace_back(X.index(), X.value());
>   }
>
>   ASSERT_EQ(3u, Results.size());
> @@ -255,6 +255,16 @@ TEST(STLExtrasTest, CountAdaptor) {
>   EXPECT_EQ(1, count(v, 4));
> }
>
> +TEST(STLExtrasTest, ToVector) {
> +  std::vector<char> v = {'a', 'b', 'c'};
> +  auto Enumerated = to_vector<4>(enumerate(v));
> +  ASSERT_EQ(3, Enumerated.size());
> +  for (size_t I = 0; I < v.size(); ++I) {
> +    EXPECT_EQ(I, Enumerated[I].index());
> +    EXPECT_EQ(v[I], Enumerated[I].value());
> +  }
> +}
> +
> TEST(STLExtrasTest, ConcatRange) {
>   std::vector<int> Expected = {1, 2, 3, 4, 5, 6, 7, 8};
>   std::vector<int> Test;
>
> Modified: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp?rev=297633&r1=297632&r2=297633&view=diff
>
> ==============================================================================
> --- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp (original)
> +++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp Mon Mar 13 11:24:10
> 2017
> @@ -582,9 +582,9 @@ private:
>   /// True if the instruction can be built solely by mutating the opcode.
>   bool canMutate() const {
>     for (const auto &Renderer : enumerate(OperandRenderers)) {
> -      if (const auto *Copy = dyn_cast<CopyRenderer>(&*Renderer.Value)) {
> +      if (const auto *Copy = dyn_cast<CopyRenderer>(&*Renderer.value())) {
>         if (Matched.getOperand(Copy->getSymbolicName()).getOperandIndex()
> !=
> -            Renderer.Index)
> +            Renderer.index())
>           return false;
>       } else
>         return false;
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170313/daf7f044/attachment.html>


More information about the llvm-commits mailing list