diff --git a/llvm/include/llvm/ADT/Sequence.h b/llvm/include/llvm/ADT/Sequence.h --- a/llvm/include/llvm/ADT/Sequence.h +++ b/llvm/include/llvm/ADT/Sequence.h @@ -15,71 +15,172 @@ #ifndef LLVM_ADT_SEQUENCE_H #define LLVM_ADT_SEQUENCE_H -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include -#include -#include +#include "llvm/ADT/SmallVector.h" + +#include //std::ptrdiff_t +#include //std::random_access_iterator_tag namespace llvm { namespace detail { -template -class value_sequence_iterator - : public iterator_facade_base, - std::random_access_iterator_tag, - const ValueT> { - using BaseT = typename value_sequence_iterator::iterator_facade_base; - - ValueT Value; +template struct iota_range_iterator { + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = T *; + using reference = T &; + +private: + struct Forward { + static void increment(T &V) { ++V; } + static void decrement(T &V) { --V; } + static void offset(T &V, difference_type Offset) { V += Offset; } + static T add(const T &V, difference_type Offset) { return V + Offset; } + static difference_type difference(const T &A, const T &B) { return A - B; } + }; + + struct Reverse { + static void increment(T &V) { --V; } + static void decrement(T &V) { ++V; } + static void offset(T &V, difference_type Offset) { V -= Offset; } + static T add(const T &V, difference_type Offset) { return V - Offset; } + static difference_type difference(const T &A, const T &B) { return B - A; } + }; + + using Op = std::conditional_t; public: - using difference_type = typename BaseT::difference_type; - using reference = typename BaseT::reference; - - value_sequence_iterator() = default; - value_sequence_iterator(const value_sequence_iterator &) = default; - value_sequence_iterator(value_sequence_iterator &&Arg) - : Value(std::move(Arg.Value)) {} - value_sequence_iterator &operator=(const value_sequence_iterator &Arg) { - Value = Arg.Value; - return *this; + // default-constructible + iota_range_iterator() = default; + // copy-constructible + iota_range_iterator(const iota_range_iterator &) = default; + // value constructor + explicit iota_range_iterator(T Value) : Value(Value) {} + // copy-assignable + iota_range_iterator &operator=(const iota_range_iterator &) = default; + // destructible + ~iota_range_iterator() = default; + + // Can be compared for equivalence using the equality/inequality operators, + bool operator!=(const iota_range_iterator &RHS) const { + return Value != RHS.Value; + } + bool operator==(const iota_range_iterator &RHS) const { + return Value == RHS.Value; } - template ()))> - value_sequence_iterator(U &&Value) : Value(std::forward(Value)) {} + // Comparison + bool operator<(const iota_range_iterator &Other) const { + return Op::difference(Value, Other.Value) < 0; + } + bool operator<=(const iota_range_iterator &Other) const { + return Op::difference(Value, Other.Value) <= 0; + } + bool operator>(const iota_range_iterator &Other) const { + return Op::difference(Value, Other.Value) > 0; + } + bool operator>=(const iota_range_iterator &Other) const { + return Op::difference(Value, Other.Value) >= 0; + } + + // Dereference + T operator*() const { return Value; } + T operator[](difference_type Offset) const { return Op::add(Value, Offset); } + + // Arithmetic + iota_range_iterator operator+(difference_type Offset) const { + return {Op::add(Value, Offset)}; + } + iota_range_iterator operator-(difference_type Offset) const { + return {Op::add(Value, -Offset)}; + } + + // Iterator difference + difference_type operator-(const iota_range_iterator &Other) const { + return Op::difference(Value, Other.Value); + } - value_sequence_iterator &operator+=(difference_type N) { - Value += N; + // Pre/Post Increment + iota_range_iterator &operator++() { + Op::increment(Value); return *this; } - value_sequence_iterator &operator-=(difference_type N) { - Value -= N; + iota_range_iterator operator++(int) { + iota_range_iterator Tmp = *this; + Op::increment(Value); + return Tmp; + } + + // Pre/Post Decrement + iota_range_iterator &operator--() { + Op::decrement(Value); return *this; } - using BaseT::operator-; - difference_type operator-(const value_sequence_iterator &RHS) const { - return Value - RHS.Value; + iota_range_iterator operator--(int) { + iota_range_iterator Tmp = *this; + Op::decrement(Value); + return Tmp; } - bool operator==(const value_sequence_iterator &RHS) const { - return Value == RHS.Value; + // Compound assignment operators + iota_range_iterator &operator+=(difference_type Offset) { + Op::offset(Value, Offset); + return *this; } - bool operator<(const value_sequence_iterator &RHS) const { - return Value < RHS.Value; + iota_range_iterator &operator-=(difference_type Offset) { + Op::offset(Value, -Offset); + return *this; } - reference operator*() const { return Value; } +private: + T Value; }; -} // end namespace detail +} // namespace detail + +template struct iota_range { + static_assert(std::is_integral::value, + "ValueT must be an integral type"); + + using value_type = ValueT; + using reference = ValueT &; + using const_reference = const ValueT &; + using iterator = detail::iota_range_iterator; + using const_iterator = iterator; + using reverse_iterator = detail::iota_range_iterator; + using const_reverse_iterator = reverse_iterator; + using difference_type = typename iterator::difference_type; + using size_type = std::size_t; + + value_type Begin; + value_type End; + + template < + typename BeginT, typename EndT, + std::enable_if_t::value, bool> = true, + std::enable_if_t::value, bool> = true> + iota_range(BeginT &&Begin, EndT &&End) + : Begin(std::forward(Begin)), End(std::forward(End)) {} + + size_t size() const { return End - Begin; } + bool empty() const { return Begin == End; } + + auto begin() const { return const_iterator(Begin); } + auto end() const { return const_iterator(End); } + + auto rbegin() const { return const_reverse_iterator(End - 1); } + auto rend() const { return const_reverse_iterator(Begin - 1); } + + auto asSmallVector() const { return SmallVector(begin(), end()); } + +private: + static_assert(std::is_same>::value, + "ValueT must not be const nor volatile"); +}; -template -iterator_range> seq(ValueT Begin, - ValueT End) { - return make_range(detail::value_sequence_iterator(Begin), - detail::value_sequence_iterator(End)); +template auto seq(ValueT Begin, ValueT End) { + return iota_range(Begin, End); } } // end namespace llvm diff --git a/llvm/unittests/ADT/SequenceTest.cpp b/llvm/unittests/ADT/SequenceTest.cpp --- a/llvm/unittests/ADT/SequenceTest.cpp +++ b/llvm/unittests/ADT/SequenceTest.cpp @@ -15,26 +15,37 @@ namespace { -TEST(SequenceTest, Basic) { - int x = 0; - for (int i : seq(0, 10)) { - EXPECT_EQ(x, i); - x++; +TEST(SequenceTest, Forward) { + int X = 0; + for (int I : seq(0, 10)) { + EXPECT_EQ(X, I); + ++X; } - EXPECT_EQ(10, x); + EXPECT_EQ(10, X); +} - auto my_seq = seq(0, 4); - EXPECT_EQ(4, my_seq.end() - my_seq.begin()); - for (int i : {0, 1, 2, 3}) - EXPECT_EQ(i, (int)my_seq.begin()[i]); +TEST(SequenceTest, Backward) { + int X = 9; + for (int I : reverse(seq(0, 10))) { + EXPECT_EQ(X, I); + --X; + } + EXPECT_EQ(-1, X); +} - EXPECT_TRUE(my_seq.begin() < my_seq.end()); +TEST(SequenceTest, Distance) { + const auto Forward = seq(0, 10); + EXPECT_EQ(std::distance(Forward.begin(), Forward.end()), 10); + EXPECT_EQ(std::distance(Forward.rbegin(), Forward.rend()), 10); +} - auto adjusted_begin = my_seq.begin() + 2; - auto adjusted_end = my_seq.end() - 2; - EXPECT_TRUE(adjusted_begin == adjusted_end); - EXPECT_EQ(2, *adjusted_begin); - EXPECT_EQ(2, *adjusted_end); +TEST(SequenceTest, Dereferene) { + const auto Forward = seq(0, 10).begin(); + EXPECT_EQ(Forward[0], 0); + EXPECT_EQ(Forward[2], 2); + const auto Backward = seq(0, 10).rbegin(); + EXPECT_EQ(Backward[0], 9); + EXPECT_EQ(Backward[2], 7); } } // anonymous namespace diff --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td --- a/mlir/include/mlir/IR/BuiltinAttributes.td +++ b/mlir/include/mlir/IR/BuiltinAttributes.td @@ -707,7 +707,7 @@ let extraClassDeclaration = [{ template using iterator = - llvm::mapped_iterator, + llvm::mapped_iterator(0, 0))::const_iterator, std::function>; /// Return the values of this attribute in the form of the given type 'T'. diff --git a/mlir/lib/Conversion/PDLToPDLInterp/PDLToPDLInterp.cpp b/mlir/lib/Conversion/PDLToPDLInterp/PDLToPDLInterp.cpp --- a/mlir/lib/Conversion/PDLToPDLInterp/PDLToPDLInterp.cpp +++ b/mlir/lib/Conversion/PDLToPDLInterp/PDLToPDLInterp.cpp @@ -380,8 +380,9 @@ if (kind == Predicates::OperandCountAtLeastQuestion || kind == Predicates::ResultCountAtLeastQuestion) { // Order the children such that the cases are in reverse numerical order. - SmallVector sortedChildren( - llvm::seq(0, switchNode->getChildren().size())); + SmallVector sortedChildren = + llvm::seq(0, switchNode->getChildren().size()) + .asSmallVector(); llvm::sort(sortedChildren, [&](unsigned lhs, unsigned rhs) { return cast(switchNode->getChild(lhs).first)->getValue() > cast(switchNode->getChild(rhs).first)->getValue(); diff --git a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp --- a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp @@ -302,8 +302,8 @@ // Compute the static loop sizes of the index op. auto targetShape = linalgOp.computeStaticLoopSizes(); // Compute a one-dimensional index vector for the index op dimension. - SmallVector constantSeq( - llvm::seq(0, targetShape[indexOp.dim()])); + SmallVector constantSeq = + llvm::seq(0, targetShape[indexOp.dim()]).asSmallVector(); ConstantOp constantOp = b.create(loc, b.getIndexVectorAttr(constantSeq)); // Return the one-dimensional index vector if it lives in the trailing @@ -317,8 +317,8 @@ std::swap(targetShape[indexOp.dim()], targetShape.back()); auto broadCastOp = b.create( loc, VectorType::get(targetShape, b.getIndexType()), constantOp); - SmallVector transposition( - llvm::seq(0, linalgOp.getNumLoops())); + SmallVector transposition = + llvm::seq(0, linalgOp.getNumLoops()).asSmallVector(); std::swap(transposition.back(), transposition[indexOp.dim()]); auto transposeOp = b.create(loc, broadCastOp, transposition);