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

Mike Edwards via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 13 12:16:17 PDT 2017


Looks like the mirror in the lab is not updating again.  I’ll ping Galina and see if she can give it a kick.  Thanks for the heads up.

-Mike

Mike Edwards
 Apple, Inc.
☏ 408-862-7095
medwards at apple.com


> On Mar 13, 2017, at 11:50 AM, Adrian Prantl <aprantl at apple.com> wrote:
> 
> +Mike
> Strange, it looks like the green dragon incremental bot didn;t build anything after 9:44AM today.
> 
> -- adrian
>> On Mar 13, 2017, at 11:47 AM, Zachary Turner <zturner at google.com <mailto:zturner at google.com>> wrote:
>> 
>> 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 <mailto: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 <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 <mailto: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 <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 <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 <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 <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 <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 <mailto:llvm-commits at lists.llvm.org>
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits <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/26a84adf/attachment.html>


More information about the llvm-commits mailing list