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 @@ -12,74 +12,170 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_SEQUENCE_H -#define LLVM_ADT_SEQUENCE_H +#ifndef LLVM_LLVM_INCLUDE_LLVM_ADT_SEQUENCE_H +#define LLVM_LLVM_INCLUDE_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 Inc(T &V) { ++V; } + static void Dec(T &V) { --V; } + static void PlusAssign(T &V, difference_type Offset) { V += Offset; } + static void MinusAssign(T &V, difference_type Offset) { V -= Offset; } + static T Plus(const T &V, difference_type Offset) { return V + Offset; } + static T Minus(const T &V, difference_type Offset) { return V - Offset; } + static T ItDiff(const T &A, const T &B) { return A - B; } + static difference_type Cmp(const T &It1, const T &It2) { return It1 - It2; } + }; + struct Backward { + static void Inc(T &V) { --V; } + static void Dec(T &V) { ++V; } + static void PlusAssign(T &V, difference_type Offset) { V -= Offset; } + static void MinusAssign(T &V, difference_type Offset) { V += Offset; } + static T Plus(const T &V, difference_type Offset) { return V - Offset; } + static T Minus(const T &V, difference_type Offset) { return V + Offset; } + static T ItDiff(const T &A, const T &B) { return B - A; } + static difference_type Cmp(const T &It1, const T &It2) { return It2 - It1; } + }; + 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 + value_range_iterator(T Value) : Value(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::Cmp(Value, Other.Value) < 0; + } + bool operator<=(const value_range_iterator &Other) const { + return Op::Cmp(Value, Other.Value) <= 0; + } + bool operator>(const value_range_iterator &Other) const { + return Op::Cmp(Value, Other.Value) > 0; + } + bool operator>=(const value_range_iterator &Other) const { + return Op::Cmp(Value, Other.Value) >= 0; } - template ()))> - value_sequence_iterator(U &&Value) : Value(std::forward(Value)) {} + // Dereference + T operator*() const { return Value; } + T operator[](difference_type Offset) const { return Op::Plus(Value, Offset); } + + // Arithmetic + value_range_iterator operator+(difference_type Offset) const { + return {Op::Plus(Value, Offset)}; + } + value_range_iterator operator-(difference_type Offset) const { + return {Op::Minus(Value, Offset)}; + } + + // Iterator difference + difference_type operator-(const value_range_iterator &Other) const { + return Op::ItDiff(Value, Other.Value); + } - value_sequence_iterator &operator+=(difference_type N) { - Value += N; + // Pre/Post Increment + value_range_iterator &operator++() { + Op::Inc(Value); return *this; } - value_sequence_iterator &operator-=(difference_type N) { - Value -= N; + value_range_iterator operator++(int) { + value_range_iterator Tmp = *this; + Op::Inc(Value); + return Tmp; + } + + // Pre/Post Decrement + value_range_iterator &operator--() { + Op::Dec(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::Dec(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::PlusAssign(Value, Offset); + return *this; } - bool operator<(const value_sequence_iterator &RHS) const { - return Value < RHS.Value; + value_range_iterator &operator-=(difference_type Offset) { + Op::MinusAssign(Value, Offset); + return *this; } - reference operator*() const { return Value; } +private: + T Value; }; -} // end namespace detail +} // namespace detail + +template struct value_range { + using value_type = const ValueT; + using reference = ValueT &; + using const_reference = const ValueT &; + using pointer = ValueT *; + using const_pointer = const ValueT *; + using difference_type = std::ptrdiff_t; + using size_type = std::size_t; + using iterator = detail::value_range_iterator; + using const_iterator = detail::value_range_iterator; + using reverse_iterator = detail::value_range_iterator; + using const_reverse_iterator = detail::value_range_iterator; + + value_type Begin; + value_type End; + + value_range(ValueT Begin, ValueT End) : Begin(Begin), End(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(Begin, 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 @@ -10,9 +10,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_SMALLVECTOR_H -#define LLVM_ADT_SMALLVECTOR_H +#ifndef LLVM_LLVM_INCLUDE_LLVM_ADT_SMALLVECTOR_H +#define LLVM_LLVM_INCLUDE_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" @@ -1194,6 +1195,11 @@ this->append(R.begin(), R.end()); } + template + explicit SmallVector(const value_range &R) : SmallVectorImpl(N) { + this->append(R.begin(), R.end()); + } + SmallVector(std::initializer_list IL) : SmallVectorImpl(N) { this->assign(IL); } 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'.