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,166 @@ #ifndef LLVM_ADT_SEQUENCE_H #define LLVM_ADT_SEQUENCE_H -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include #include -#include 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; +template +struct value_range_iterator + : public std::iterator { +private: + using Base = std::iterator; - ValueT Value; +public: + using difference_type = typename Base::difference_type; + +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 Backward { + 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 + value_range_iterator() = default; + // copy-constructible + value_range_iterator(const value_range_iterator &) = default; + // value constructor + template ::value, bool> = true> + value_range_iterator(U &&Value) : Value(std::forward(Value)) {} + // copy-assignable + value_range_iterator &operator=(const value_range_iterator &) = default; + // destructible + ~value_range_iterator() = default; + + // Can be compared for equivalence using the equality/inequality operators, + bool operator!=(const value_range_iterator &RHS) const { + return Value != RHS.Value; + } + bool operator==(const value_range_iterator &RHS) const { + return Value == RHS.Value; + } + + // Comparison + bool operator<(const value_range_iterator &Other) const { + return Op::difference(Value, Other.Value) < 0; + } + bool operator<=(const value_range_iterator &Other) const { + return Op::difference(Value, Other.Value) <= 0; + } + bool operator>(const value_range_iterator &Other) const { + return Op::difference(Value, Other.Value) > 0; + } + bool operator>=(const value_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 + value_range_iterator operator+(difference_type Offset) const { + return {Op::add(Value, Offset)}; + } + value_range_iterator operator-(difference_type Offset) const { + return {Op::add(Value, -Offset)}; } - template ()))> - value_sequence_iterator(U &&Value) : Value(std::forward(Value)) {} + // Iterator difference + difference_type operator-(const value_range_iterator &Other) const { + return Op::difference(Value, Other.Value); + } - value_sequence_iterator &operator+=(difference_type N) { - Value += N; + // Pre/Post Increment + value_range_iterator &operator++() { + Op::increment(Value); return *this; } - value_sequence_iterator &operator-=(difference_type N) { - Value -= N; + value_range_iterator operator++(int) { + value_range_iterator Tmp = *this; + Op::increment(Value); + return Tmp; + } + + // Pre/Post Decrement + value_range_iterator &operator--() { + Op::decrement(Value); return *this; } - using BaseT::operator-; - difference_type operator-(const value_sequence_iterator &RHS) const { - return Value - RHS.Value; + value_range_iterator operator--(int) { + value_range_iterator Tmp = *this; + Op::decrement(Value); + return Tmp; } - bool operator==(const value_sequence_iterator &RHS) const { - return Value == RHS.Value; + // Compound assignment operators + value_range_iterator &operator+=(difference_type Offset) { + Op::offset(Value, Offset); + return *this; } - bool operator<(const value_sequence_iterator &RHS) const { - return Value < RHS.Value; + value_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 value_range { + using value_type = ValueT; + using reference = ValueT &; + using const_reference = const ValueT &; + using iterator = detail::value_range_iterator; + using const_iterator = iterator; + using reverse_iterator = detail::value_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> + value_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; } + + const_iterator begin() const { return {Begin}; } + const_iterator end() const { return {End}; } + + const_reverse_iterator rbegin() const { return {End - 1}; } + const_reverse_iterator rend() const { return {Begin - 1}; } + +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 value_range(std::move(Begin), std::move(End)); } } // end namespace llvm diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -13,6 +13,7 @@ #ifndef LLVM_ADT_SMALLVECTOR_H #define LLVM_ADT_SMALLVECTOR_H +#include "llvm/ADT/Sequence.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" 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,8 @@ 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())); + auto sequence = llvm::seq(0, switchNode->getChildren().size()); + SmallVector sortedChildren(sequence.begin(), sequence.end()); 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()])); + auto seq1 = llvm::seq(0, targetShape[indexOp.dim()]); + SmallVector constantSeq(seq1.begin(), seq1.end()); 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())); + auto seq2 = llvm::seq(0, linalgOp.getNumLoops()); + SmallVector transposition(seq2.begin(), seq2.end()); std::swap(transposition.back(), transposition[indexOp.dim()]); auto transposeOp = b.create(loc, broadCastOp, transposition);