[llvm] r297633 - [ADT] Improve the genericity of llvm::enumerate().
Adrian Prantl via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 13 11:50:06 PDT 2017
+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> 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/6f35e56a/attachment.html>
More information about the llvm-commits
mailing list