This revision moves the various range utilities present in MLIR to LLVM to enable greater reuse. This revision moves the following utilities:
* indexed_accessor_*
This is set of utility iterator/range base classes that allow for building a range class where the iterators are represented by an object+index pair.
* make_second_range
Given a range of pairs, returns a range iterating over the `second` elements.
* hasSingleElement
Returns if the given range has 1 element. size() == 1 checks end up being very common, but size() is not always O(1) (e.g., ilist). This method provides O(1) checks for those cases.
Differential Revision: https://reviews.llvm.org/D78064
return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer);
}
+/// Returns true of the given range only contains a single element.
+template <typename ContainerTy> bool hasSingleElement(ContainerTy &&c) {
+ auto it = std::begin(c), e = std::end(c);
+ return it != e && std::next(it) == e;
+}
+
/// Return a range covering \p RangeOrContainer with the first N elements
/// excluded.
template <typename T> auto drop_begin(T &&RangeOrContainer, size_t N) {
std::forward<RangeTs>(Ranges)...);
}
+/// A utility class used to implement an iterator that contains some base object
+/// and an index. The iterator moves the index but keeps the base constant.
+template <typename DerivedT, typename BaseT, typename T,
+ typename PointerT = T *, typename ReferenceT = T &>
+class indexed_accessor_iterator
+ : public llvm::iterator_facade_base<DerivedT,
+ std::random_access_iterator_tag, T,
+ std::ptrdiff_t, PointerT, ReferenceT> {
+public:
+ ptrdiff_t operator-(const indexed_accessor_iterator &rhs) const {
+ assert(base == rhs.base && "incompatible iterators");
+ return index - rhs.index;
+ }
+ bool operator==(const indexed_accessor_iterator &rhs) const {
+ return base == rhs.base && index == rhs.index;
+ }
+ bool operator<(const indexed_accessor_iterator &rhs) const {
+ assert(base == rhs.base && "incompatible iterators");
+ return index < rhs.index;
+ }
+
+ DerivedT &operator+=(ptrdiff_t offset) {
+ this->index += offset;
+ return static_cast<DerivedT &>(*this);
+ }
+ DerivedT &operator-=(ptrdiff_t offset) {
+ this->index -= offset;
+ return static_cast<DerivedT &>(*this);
+ }
+
+ /// Returns the current index of the iterator.
+ ptrdiff_t getIndex() const { return index; }
+
+ /// Returns the current base of the iterator.
+ const BaseT &getBase() const { return base; }
+
+protected:
+ indexed_accessor_iterator(BaseT base, ptrdiff_t index)
+ : base(base), index(index) {}
+ BaseT base;
+ ptrdiff_t index;
+};
+
+namespace detail {
+/// The class represents the base of a range of indexed_accessor_iterators. It
+/// provides support for many different range functionalities, e.g.
+/// drop_front/slice/etc.. Derived range classes must implement the following
+/// static methods:
+/// * ReferenceT dereference_iterator(const BaseT &base, ptrdiff_t index)
+/// - Dereference an iterator pointing to the base object at the given
+/// index.
+/// * BaseT offset_base(const BaseT &base, ptrdiff_t index)
+/// - Return a new base that is offset from the provide base by 'index'
+/// elements.
+template <typename DerivedT, typename BaseT, typename T,
+ typename PointerT = T *, typename ReferenceT = T &>
+class indexed_accessor_range_base {
+public:
+ using RangeBaseT =
+ indexed_accessor_range_base<DerivedT, BaseT, T, PointerT, ReferenceT>;
+
+ /// An iterator element of this range.
+ class iterator : public indexed_accessor_iterator<iterator, BaseT, T,
+ PointerT, ReferenceT> {
+ public:
+ // Index into this iterator, invoking a static method on the derived type.
+ ReferenceT operator*() const {
+ return DerivedT::dereference_iterator(this->getBase(), this->getIndex());
+ }
+
+ private:
+ iterator(BaseT owner, ptrdiff_t curIndex)
+ : indexed_accessor_iterator<iterator, BaseT, T, PointerT, ReferenceT>(
+ owner, curIndex) {}
+
+ /// Allow access to the constructor.
+ friend indexed_accessor_range_base<DerivedT, BaseT, T, PointerT,
+ ReferenceT>;
+ };
+
+ indexed_accessor_range_base(iterator begin, iterator end)
+ : base(DerivedT::offset_base(begin.getBase(), begin.getIndex())),
+ count(end.getIndex() - begin.getIndex()) {}
+ indexed_accessor_range_base(const iterator_range<iterator> &range)
+ : indexed_accessor_range_base(range.begin(), range.end()) {}
+ indexed_accessor_range_base(BaseT base, ptrdiff_t count)
+ : base(base), count(count) {}
+
+ iterator begin() const { return iterator(base, 0); }
+ iterator end() const { return iterator(base, count); }
+ ReferenceT operator[](unsigned index) const {
+ assert(index < size() && "invalid index for value range");
+ return DerivedT::dereference_iterator(base, index);
+ }
+
+ /// Compare this range with another.
+ template <typename OtherT> bool operator==(const OtherT &other) {
+ return size() == std::distance(other.begin(), other.end()) &&
+ std::equal(begin(), end(), other.begin());
+ }
+
+ /// Return the size of this range.
+ size_t size() const { return count; }
+
+ /// Return if the range is empty.
+ bool empty() const { return size() == 0; }
+
+ /// Drop the first N elements, and keep M elements.
+ DerivedT slice(size_t n, size_t m) const {
+ assert(n + m <= size() && "invalid size specifiers");
+ return DerivedT(DerivedT::offset_base(base, n), m);
+ }
+
+ /// Drop the first n elements.
+ DerivedT drop_front(size_t n = 1) const {
+ assert(size() >= n && "Dropping more elements than exist");
+ return slice(n, size() - n);
+ }
+ /// Drop the last n elements.
+ DerivedT drop_back(size_t n = 1) const {
+ assert(size() >= n && "Dropping more elements than exist");
+ return DerivedT(base, size() - n);
+ }
+
+ /// Take the first n elements.
+ DerivedT take_front(size_t n = 1) const {
+ return n < size() ? drop_back(size() - n)
+ : static_cast<const DerivedT &>(*this);
+ }
+
+ /// Take the last n elements.
+ DerivedT take_back(size_t n = 1) const {
+ return n < size() ? drop_front(size() - n)
+ : static_cast<const DerivedT &>(*this);
+ }
+
+ /// Allow conversion to any type accepting an iterator_range.
+ template <typename RangeT, typename = std::enable_if_t<std::is_constructible<
+ RangeT, iterator_range<iterator>>::value>>
+ operator RangeT() const {
+ return RangeT(iterator_range<iterator>(*this));
+ }
+
+protected:
+ indexed_accessor_range_base(const indexed_accessor_range_base &) = default;
+ indexed_accessor_range_base(indexed_accessor_range_base &&) = default;
+ indexed_accessor_range_base &
+ operator=(const indexed_accessor_range_base &) = default;
+
+ /// The base that owns the provided range of values.
+ BaseT base;
+ /// The size from the owning range.
+ ptrdiff_t count;
+};
+} // end namespace detail
+
+/// This class provides an implementation of a range of
+/// indexed_accessor_iterators where the base is not indexable. Ranges with
+/// bases that are offsetable should derive from indexed_accessor_range_base
+/// instead. Derived range classes are expected to implement the following
+/// static method:
+/// * ReferenceT dereference(const BaseT &base, ptrdiff_t index)
+/// - Dereference an iterator pointing to a parent base at the given index.
+template <typename DerivedT, typename BaseT, typename T,
+ typename PointerT = T *, typename ReferenceT = T &>
+class indexed_accessor_range
+ : public detail::indexed_accessor_range_base<
+ DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT> {
+public:
+ indexed_accessor_range(BaseT base, ptrdiff_t startIndex, ptrdiff_t count)
+ : detail::indexed_accessor_range_base<
+ DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT>(
+ std::make_pair(base, startIndex), count) {}
+ using detail::indexed_accessor_range_base<
+ DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT,
+ ReferenceT>::indexed_accessor_range_base;
+
+ /// Returns the current base of the range.
+ const BaseT &getBase() const { return this->base.first; }
+
+ /// Returns the current start index of the range.
+ ptrdiff_t getStartIndex() const { return this->base.second; }
+
+ /// See `detail::indexed_accessor_range_base` for details.
+ static std::pair<BaseT, ptrdiff_t>
+ offset_base(const std::pair<BaseT, ptrdiff_t> &base, ptrdiff_t index) {
+ // We encode the internal base as a pair of the derived base and a start
+ // index into the derived base.
+ return std::make_pair(base.first, base.second + index);
+ }
+ /// See `detail::indexed_accessor_range_base` for details.
+ static ReferenceT
+ dereference_iterator(const std::pair<BaseT, ptrdiff_t> &base,
+ ptrdiff_t index) {
+ return DerivedT::dereference(base.first, base.second + index);
+ }
+};
+
+/// Given a container of pairs, return a range over the second elements.
+template <typename ContainerTy> auto make_second_range(ContainerTy &&c) {
+ return llvm::map_range(
+ std::forward<ContainerTy>(c),
+ [](decltype((*std::begin(c))) elt) -> decltype((elt.second)) {
+ return elt.second;
+ });
+}
+
//===----------------------------------------------------------------------===//
// Extra additions to <utility>
//===----------------------------------------------------------------------===//
FormatVariadicTest.cpp
GlobPatternTest.cpp
Host.cpp
+ IndexedAccessorTest.cpp
ItaniumManglingCanonicalizerTest.cpp
JSONTest.cpp
KnownBitsTest.cpp
//
//===----------------------------------------------------------------------===//
-#include "mlir/Support/STLExtras.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
#include "gmock/gmock.h"
-using namespace mlir;
-using namespace mlir::detail;
+using namespace llvm;
+using namespace llvm::detail;
namespace {
/// Simple indexed accessor range that wraps an array.
using indexed_accessor_range<ArrayIndexedAccessorRange<T>, T *,
T>::indexed_accessor_range;
- /// See `indexed_accessor_range` for details.
+ /// See `llvm::indexed_accessor_range` for details.
static T &dereference(T *data, ptrdiff_t index) { return data[index]; }
};
} // end anonymous namespace
/// Range class for element types.
class ElementTypeRange
- : public ::mlir::detail::indexed_accessor_range_base<
+ : public ::llvm::detail::indexed_accessor_range_base<
ElementTypeRange, const Type *, Type, Type, Type> {
private:
using RangeBaseT::RangeBaseT;
- /// See `mlir::detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static const Type *offset_base(const Type *object, ptrdiff_t index) {
return object + index;
}
- /// See `mlir::detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static Type dereference_iterator(const Type *object, ptrdiff_t index) {
return object[index];
}
template <typename ConcreteT, typename T, typename PointerT = T *,
typename ReferenceT = T &>
class DenseElementIndexedIteratorImpl
- : public indexed_accessor_iterator<ConcreteT, DenseIterPtrAndSplat, T,
- PointerT, ReferenceT> {
+ : public llvm::indexed_accessor_iterator<ConcreteT, DenseIterPtrAndSplat, T,
+ PointerT, ReferenceT> {
protected:
DenseElementIndexedIteratorImpl(const char *data, bool isSplat,
size_t dataIndex)
- : indexed_accessor_iterator<ConcreteT, DenseIterPtrAndSplat, T, PointerT,
- ReferenceT>({data, isSplat}, dataIndex) {}
+ : llvm::indexed_accessor_iterator<ConcreteT, DenseIterPtrAndSplat, T,
+ PointerT, ReferenceT>({data, isSplat},
+ dataIndex) {}
/// Return the current index for this iterator, adjusted for the case of a
/// splat.
/// A utility iterator that allows walking over the internal Attribute values
/// of a DenseElementsAttr.
class AttributeElementIterator
- : public indexed_accessor_iterator<AttributeElementIterator, const void *,
- Attribute, Attribute, Attribute> {
+ : public llvm::indexed_accessor_iterator<AttributeElementIterator,
+ const void *, Attribute,
+ Attribute, Attribute> {
public:
/// Accesses the Attribute value at this iterator position.
Attribute operator*() const;
/// This class implements the successor iterators for Block.
class SuccessorRange final
- : public detail::indexed_accessor_range_base<SuccessorRange, BlockOperand *,
- Block *, Block *, Block *> {
+ : public llvm::detail::indexed_accessor_range_base<
+ SuccessorRange, BlockOperand *, Block *, Block *, Block *> {
public:
using RangeBaseT::RangeBaseT;
SuccessorRange(Block *block);
SuccessorRange(Operation *term);
private:
- /// See `detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static BlockOperand *offset_base(BlockOperand *object, ptrdiff_t index) {
return object + index;
}
- /// See `detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static Block *dereference_iterator(BlockOperand *object, ptrdiff_t index) {
return object[index].get();
}
void printArrowTypeList(TypeRange &&types) {
auto &os = getStream() << " -> ";
- bool wrapped = !has_single_element(types) ||
+ bool wrapped = !llvm::hasSingleElement(types) ||
(*types.begin()).template isa<FunctionType>();
if (wrapped)
os << '(';
/// suitable for a more derived type (e.g. ArrayRef) or a template range
/// parameter.
class TypeRange
- : public detail::indexed_accessor_range_base<
+ : public llvm::detail::indexed_accessor_range_base<
TypeRange,
llvm::PointerUnion<const Value *, const Type *, OpOperand *>, Type,
Type, Type> {
/// * A pointer to the first element of an array of operands.
using OwnerT = llvm::PointerUnion<const Value *, const Type *, OpOperand *>;
- /// See `detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static OwnerT offset_base(OwnerT object, ptrdiff_t index);
- /// See `detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static Type dereference_iterator(OwnerT object, ptrdiff_t index);
/// Allow access to `offset_base` and `dereference_iterator`.
// OperandRange
/// This class implements the operand iterators for the Operation class.
-class OperandRange final
- : public detail::indexed_accessor_range_base<OperandRange, OpOperand *,
- Value, Value, Value> {
+class OperandRange final : public llvm::detail::indexed_accessor_range_base<
+ OperandRange, OpOperand *, Value, Value, Value> {
public:
using RangeBaseT::RangeBaseT;
OperandRange(Operation *op);
unsigned getBeginOperandIndex() const;
private:
- /// See `detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static OpOperand *offset_base(OpOperand *object, ptrdiff_t index) {
return object + index;
}
- /// See `detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static Value dereference_iterator(OpOperand *object, ptrdiff_t index) {
return object[index].get();
}
/// This class implements the result iterators for the Operation class.
class ResultRange final
- : public indexed_accessor_range<ResultRange, Operation *, OpResult,
- OpResult, OpResult> {
+ : public llvm::indexed_accessor_range<ResultRange, Operation *, OpResult,
+ OpResult, OpResult> {
public:
using indexed_accessor_range<ResultRange, Operation *, OpResult, OpResult,
OpResult>::indexed_accessor_range;
auto getType() const { return getTypes(); }
private:
- /// See `indexed_accessor_range` for details.
+ /// See `llvm::indexed_accessor_range` for details.
static OpResult dereference(Operation *op, ptrdiff_t index);
/// Allow access to `dereference_iterator`.
- friend indexed_accessor_range<ResultRange, Operation *, OpResult, OpResult,
- OpResult>;
+ friend llvm::indexed_accessor_range<ResultRange, Operation *, OpResult,
+ OpResult, OpResult>;
};
//===----------------------------------------------------------------------===//
/// suitable for a more derived type (e.g. ArrayRef) or a template range
/// parameter.
class ValueRange final
- : public detail::indexed_accessor_range_base<
+ : public llvm::detail::indexed_accessor_range_base<
ValueRange, detail::ValueRangeOwner, Value, Value, Value> {
public:
using RangeBaseT::RangeBaseT;
private:
using OwnerT = detail::ValueRangeOwner;
- /// See `detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static OwnerT offset_base(const OwnerT &owner, ptrdiff_t index);
- /// See `detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static Value dereference_iterator(const OwnerT &owner, ptrdiff_t index);
/// Allow access to `offset_base` and `dereference_iterator`.
/// suitable for a more derived type (e.g. ArrayRef) or a template range
/// parameter.
class RegionRange
- : public detail::indexed_accessor_range_base<
+ : public llvm::detail::indexed_accessor_range_base<
RegionRange, PointerUnion<Region *, const std::unique_ptr<Region> *>,
Region *, Region *, Region *> {
/// The type representing the owner of this range. This is either a list of
RegionRange(ArrayRef<std::unique_ptr<Region>> regions);
private:
- /// See `detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static OwnerT offset_base(const OwnerT &owner, ptrdiff_t index);
- /// See `detail::indexed_accessor_range_base` for details.
+ /// See `llvm::detail::indexed_accessor_range_base` for details.
static Region *dereference_iterator(const OwnerT &owner, ptrdiff_t index);
/// Allow access to `offset_base` and `dereference_iterator`.
return {use_begin(value), use_end(value)};
}
bool hasOneUse(ValueType value) const {
- return mlir::has_single_element(getUses(value));
+ return llvm::hasSingleElement(getUses(value));
}
bool use_empty(ValueType value) const {
return use_begin(value) == use_end(value);
interleaveComma(c, os, [&](const T &a) { os << a; });
}
-//===----------------------------------------------------------------------===//
-// Extra additions to <iterator>
-//===----------------------------------------------------------------------===//
-
-/// A utility class used to implement an iterator that contains some base object
-/// and an index. The iterator moves the index but keeps the base constant.
-template <typename DerivedT, typename BaseT, typename T,
- typename PointerT = T *, typename ReferenceT = T &>
-class indexed_accessor_iterator
- : public llvm::iterator_facade_base<DerivedT,
- std::random_access_iterator_tag, T,
- std::ptrdiff_t, PointerT, ReferenceT> {
-public:
- ptrdiff_t operator-(const indexed_accessor_iterator &rhs) const {
- assert(base == rhs.base && "incompatible iterators");
- return index - rhs.index;
- }
- bool operator==(const indexed_accessor_iterator &rhs) const {
- return base == rhs.base && index == rhs.index;
- }
- bool operator<(const indexed_accessor_iterator &rhs) const {
- assert(base == rhs.base && "incompatible iterators");
- return index < rhs.index;
- }
-
- DerivedT &operator+=(ptrdiff_t offset) {
- this->index += offset;
- return static_cast<DerivedT &>(*this);
- }
- DerivedT &operator-=(ptrdiff_t offset) {
- this->index -= offset;
- return static_cast<DerivedT &>(*this);
- }
-
- /// Returns the current index of the iterator.
- ptrdiff_t getIndex() const { return index; }
-
- /// Returns the current base of the iterator.
- const BaseT &getBase() const { return base; }
-
-protected:
- indexed_accessor_iterator(BaseT base, ptrdiff_t index)
- : base(base), index(index) {}
- BaseT base;
- ptrdiff_t index;
-};
-
-namespace detail {
-/// The class represents the base of a range of indexed_accessor_iterators. It
-/// provides support for many different range functionalities, e.g.
-/// drop_front/slice/etc.. Derived range classes must implement the following
-/// static methods:
-/// * ReferenceT dereference_iterator(const BaseT &base, ptrdiff_t index)
-/// - Dereference an iterator pointing to the base object at the given
-/// index.
-/// * BaseT offset_base(const BaseT &base, ptrdiff_t index)
-/// - Return a new base that is offset from the provide base by 'index'
-/// elements.
-template <typename DerivedT, typename BaseT, typename T,
- typename PointerT = T *, typename ReferenceT = T &>
-class indexed_accessor_range_base {
-public:
- using RangeBaseT =
- indexed_accessor_range_base<DerivedT, BaseT, T, PointerT, ReferenceT>;
-
- /// An iterator element of this range.
- class iterator : public indexed_accessor_iterator<iterator, BaseT, T,
- PointerT, ReferenceT> {
- public:
- // Index into this iterator, invoking a static method on the derived type.
- ReferenceT operator*() const {
- return DerivedT::dereference_iterator(this->getBase(), this->getIndex());
- }
-
- private:
- iterator(BaseT owner, ptrdiff_t curIndex)
- : indexed_accessor_iterator<iterator, BaseT, T, PointerT, ReferenceT>(
- owner, curIndex) {}
-
- /// Allow access to the constructor.
- friend indexed_accessor_range_base<DerivedT, BaseT, T, PointerT,
- ReferenceT>;
- };
-
- indexed_accessor_range_base(iterator begin, iterator end)
- : base(DerivedT::offset_base(begin.getBase(), begin.getIndex())),
- count(end.getIndex() - begin.getIndex()) {}
- indexed_accessor_range_base(const iterator_range<iterator> &range)
- : indexed_accessor_range_base(range.begin(), range.end()) {}
- indexed_accessor_range_base(BaseT base, ptrdiff_t count)
- : base(base), count(count) {}
-
- iterator begin() const { return iterator(base, 0); }
- iterator end() const { return iterator(base, count); }
- ReferenceT operator[](unsigned index) const {
- assert(index < size() && "invalid index for value range");
- return DerivedT::dereference_iterator(base, index);
- }
-
- /// Compare this range with another.
- template <typename OtherT> bool operator==(const OtherT &other) {
- return size() == llvm::size(other) &&
- std::equal(begin(), end(), other.begin());
- }
-
- /// Return the size of this range.
- size_t size() const { return count; }
-
- /// Return if the range is empty.
- bool empty() const { return size() == 0; }
-
- /// Drop the first N elements, and keep M elements.
- DerivedT slice(size_t n, size_t m) const {
- assert(n + m <= size() && "invalid size specifiers");
- return DerivedT(DerivedT::offset_base(base, n), m);
- }
-
- /// Drop the first n elements.
- DerivedT drop_front(size_t n = 1) const {
- assert(size() >= n && "Dropping more elements than exist");
- return slice(n, size() - n);
- }
- /// Drop the last n elements.
- DerivedT drop_back(size_t n = 1) const {
- assert(size() >= n && "Dropping more elements than exist");
- return DerivedT(base, size() - n);
- }
-
- /// Take the first n elements.
- DerivedT take_front(size_t n = 1) const {
- return n < size() ? drop_back(size() - n)
- : static_cast<const DerivedT &>(*this);
- }
-
- /// Take the last n elements.
- DerivedT take_back(size_t n = 1) const {
- return n < size() ? drop_front(size() - n)
- : static_cast<const DerivedT &>(*this);
- }
-
- /// Allow conversion to SmallVector if necessary.
- /// TODO(riverriddle) Remove this when SmallVector accepts different range
- /// types in its constructor.
- template <typename SVT, unsigned N> operator SmallVector<SVT, N>() const {
- return {begin(), end()};
- }
-
-protected:
- indexed_accessor_range_base(const indexed_accessor_range_base &) = default;
- indexed_accessor_range_base(indexed_accessor_range_base &&) = default;
- indexed_accessor_range_base &
- operator=(const indexed_accessor_range_base &) = default;
-
- /// The base that owns the provided range of values.
- BaseT base;
- /// The size from the owning range.
- ptrdiff_t count;
-};
-} // end namespace detail
-
-/// This class provides an implementation of a range of
-/// indexed_accessor_iterators where the base is not indexable. Ranges with
-/// bases that are offsetable should derive from indexed_accessor_range_base
-/// instead. Derived range classes are expected to implement the following
-/// static method:
-/// * ReferenceT dereference(const BaseT &base, ptrdiff_t index)
-/// - Dereference an iterator pointing to a parent base at the given index.
-template <typename DerivedT, typename BaseT, typename T,
- typename PointerT = T *, typename ReferenceT = T &>
-class indexed_accessor_range
- : public detail::indexed_accessor_range_base<
- DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT> {
-public:
- indexed_accessor_range(BaseT base, ptrdiff_t startIndex, ptrdiff_t count)
- : detail::indexed_accessor_range_base<
- DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT>(
- std::make_pair(base, startIndex), count) {}
- using detail::indexed_accessor_range_base<
- DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT,
- ReferenceT>::indexed_accessor_range_base;
-
- /// Returns the current base of the range.
- const BaseT &getBase() const { return this->base.first; }
-
- /// Returns the current start index of the range.
- ptrdiff_t getStartIndex() const { return this->base.second; }
-
- /// See `detail::indexed_accessor_range_base` for details.
- static std::pair<BaseT, ptrdiff_t>
- offset_base(const std::pair<BaseT, ptrdiff_t> &base, ptrdiff_t index) {
- // We encode the internal base as a pair of the derived base and a start
- // index into the derived base.
- return std::make_pair(base.first, base.second + index);
- }
- /// See `detail::indexed_accessor_range_base` for details.
- static ReferenceT
- dereference_iterator(const std::pair<BaseT, ptrdiff_t> &base,
- ptrdiff_t index) {
- return DerivedT::dereference(base.first, base.second + index);
- }
-};
-
-/// Given a container of pairs, return a range over the second elements.
-template <typename ContainerTy> auto make_second_range(ContainerTy &&c) {
- return llvm::map_range(
- std::forward<ContainerTy>(c),
- [](decltype((*std::begin(c))) elt) -> decltype((elt.second)) {
- return elt.second;
- });
-}
-
-/// A range class that repeats a specific value for a set number of times.
-template <typename T>
-class RepeatRange
- : public detail::indexed_accessor_range_base<RepeatRange<T>, T, const T> {
-public:
- using detail::indexed_accessor_range_base<
- RepeatRange<T>, T, const T>::indexed_accessor_range_base;
-
- /// Given that we are repeating a specific value, we can simply return that
- /// value when offsetting the base or dereferencing the iterator.
- static T offset_base(const T &val, ptrdiff_t) { return val; }
- static const T &dereference_iterator(const T &val, ptrdiff_t) { return val; }
-};
-
-/// Make a range that repeats the given value 'n' times.
-template <typename ValueTy>
-RepeatRange<ValueTy> make_repeated_range(const ValueTy &value, size_t n) {
- return RepeatRange<ValueTy>(value, n);
-}
-
-/// Returns true of the given range only contains a single element.
-template <typename ContainerTy> bool has_single_element(ContainerTy &&c) {
- auto it = std::begin(c), e = std::end(c);
- return it != e && std::next(it) == e;
-}
-
} // end namespace mlir
#endif // MLIR_SUPPORT_STLEXTRAS_H
LogicalResult matchAndRewrite(AffineForOp forOp,
PatternRewriter &rewriter) const override {
// Check that the body only contains a terminator.
- if (!has_single_element(*forOp.getBody()))
+ if (!llvm::hasSingleElement(*forOp.getBody()))
return failure();
rewriter.eraseOp(forOp);
return success();
LogicalResult matchAndRewrite(AffineIfOp ifOp,
PatternRewriter &rewriter) const override {
- if (ifOp.elseRegion().empty() || !has_single_element(*ifOp.getElseBlock()))
+ if (ifOp.elseRegion().empty() ||
+ !llvm::hasSingleElement(*ifOp.getElseBlock()))
return failure();
rewriter.startRootUpdate(ifOp);
(void)toType;
assert(fromType.getShape() == toType.getShape());
assert(fromType.getRank() != 0);
- assert(has_single_element(region) &&
+ assert(llvm::hasSingleElement(region) &&
"unstructured control flow not supported");
OpBuilder builder(region.getContext());
Optional<RegionMatcher::BinaryOpKind>
RegionMatcher::matchAsScalarBinaryOp(GenericOp op) {
auto ®ion = op.region();
- if (!has_single_element(region))
+ if (!llvm::hasSingleElement(region))
return llvm::None;
Block &block = region.front();
return llvm::None;
auto &ops = block.getOperations();
- if (!has_single_element(block.without_terminator()))
+ if (!llvm::hasSingleElement(block.without_terminator()))
return llvm::None;
using mlir::matchers::m_Val;
/// given `dstBlock`.
static inline bool hasOneBranchOpTo(Block &srcBlock, Block &dstBlock) {
// Check that there is only one op in the `srcBlock`.
- if (!has_single_element(srcBlock))
+ if (!llvm::hasSingleElement(srcBlock))
return false;
auto branchOp = dyn_cast<spirv::BranchOp>(srcBlock.back());
// Check that the successor block has a single predecessor.
Block *succ = op.getDest();
Block *opParent = op.getOperation()->getBlock();
- if (succ == opParent || !has_single_element(succ->getPredecessors()))
+ if (succ == opParent || !llvm::hasSingleElement(succ->getPredecessors()))
return failure();
// Merge the successor into the current block and erase the branch.
/// Constructs a new iterator.
DenseElementsAttr::AttributeElementIterator::AttributeElementIterator(
DenseElementsAttr attr, size_t index)
- : indexed_accessor_iterator<AttributeElementIterator, const void *,
- Attribute, Attribute, Attribute>(
+ : llvm::indexed_accessor_iterator<AttributeElementIterator, const void *,
+ Attribute, Attribute, Attribute>(
attr.getAsOpaquePointer(), index) {}
/// Accesses the Attribute value at this iterator position.
auto &bodyRegion = getOperation()->getRegion(0);
// The body must contain a single basic block.
- if (!has_single_element(bodyRegion))
+ if (!llvm::hasSingleElement(bodyRegion))
return emitOpError("expected body region to have a single block");
// Check that the body has no block arguments.
this->base = owner.ptr.get<const Value *>();
}
-/// See `detail::indexed_accessor_range_base` for details.
+/// See `llvm::detail::indexed_accessor_range_base` for details.
TypeRange::OwnerT TypeRange::offset_base(OwnerT object, ptrdiff_t index) {
if (auto *value = object.dyn_cast<const Value *>())
return {value + index};
return {operand + index};
return {object.dyn_cast<const Type *>() + index};
}
-/// See `detail::indexed_accessor_range_base` for details.
+/// See `llvm::detail::indexed_accessor_range_base` for details.
Type TypeRange::dereference_iterator(OwnerT object, ptrdiff_t index) {
if (auto *value = object.dyn_cast<const Value *>())
return (value + index)->getType();
return getBase()->getResultTypes();
}
-/// See `indexed_accessor_range` for details.
+/// See `llvm::indexed_accessor_range` for details.
OpResult ResultRange::dereference(Operation *op, ptrdiff_t index) {
return op->getResult(index);
}
{values.getBase(), static_cast<unsigned>(values.getStartIndex())},
values.size()) {}
-/// See `detail::indexed_accessor_range_base` for details.
+/// See `llvm::detail::indexed_accessor_range_base` for details.
ValueRange::OwnerT ValueRange::offset_base(const OwnerT &owner,
ptrdiff_t index) {
if (auto *value = owner.ptr.dyn_cast<const Value *>())
Operation *operation = reinterpret_cast<Operation *>(owner.ptr.get<void *>());
return {operation, owner.startIndex + static_cast<unsigned>(index)};
}
-/// See `detail::indexed_accessor_range_base` for details.
+/// See `llvm::detail::indexed_accessor_range_base` for details.
Value ValueRange::dereference_iterator(const OwnerT &owner, ptrdiff_t index) {
if (auto *value = owner.ptr.dyn_cast<const Value *>())
return value[index];
RegionRange::RegionRange(ArrayRef<std::unique_ptr<Region>> regions)
: RegionRange(regions.data(), regions.size()) {}
-/// See `detail::indexed_accessor_range_base` for details.
+/// See `llvm::detail::indexed_accessor_range_base` for details.
RegionRange::OwnerT RegionRange::offset_base(const OwnerT &owner,
ptrdiff_t index) {
if (auto *operand = owner.dyn_cast<const std::unique_ptr<Region> *>())
return operand + index;
return &owner.get<Region *>()[index];
}
-/// See `detail::indexed_accessor_range_base` for details.
+/// See `llvm::detail::indexed_accessor_range_base` for details.
Region *RegionRange::dereference_iterator(const OwnerT &owner,
ptrdiff_t index) {
if (auto *operand = owner.dyn_cast<const std::unique_ptr<Region> *>())
"expected operation to have SymbolTable trait");
assert(symbolTableOp->getNumRegions() == 1 &&
"expected operation to have a single region");
- assert(has_single_element(symbolTableOp->getRegion(0)) &&
+ assert(llvm::hasSingleElement(symbolTableOp->getRegion(0)) &&
"expected operation to have a single block");
for (auto &op : symbolTableOp->getRegion(0).front()) {
if (op->getNumRegions() != 1)
return op->emitOpError()
<< "Operations with a 'SymbolTable' must have exactly one region";
- if (!has_single_element(op->getRegion(0)))
+ if (!llvm::hasSingleElement(op->getRegion(0)))
return op->emitOpError()
<< "Operations with a 'SymbolTable' must have exactly one block";
return promoteIfSingleIteration(forOp);
// Nothing in the loop body other than the terminator.
- if (has_single_element(forOp.getBody()->getOperations()))
+ if (llvm::hasSingleElement(forOp.getBody()->getOperations()))
return success();
// Loops where the lower bound is a max expression isn't supported for
return promoteIfSingleIteration(forOp);
// Nothing in the loop body other than the terminator.
- if (has_single_element(forOp.getBody()->getOperations()))
+ if (llvm::hasSingleElement(forOp.getBody()->getOperations()))
return success();
// Loops where both lower and upper bounds are multi-result maps won't be
add_subdirectory(IR)
add_subdirectory(Pass)
add_subdirectory(SDBM)
-add_subdirectory(Support)
add_subdirectory(TableGen)
+++ /dev/null
-add_mlir_unittest(MLIRSupportTests
- IndexedAccessorTest.cpp
-)
-
-target_link_libraries(MLIRSupportTests
- PRIVATE MLIRSupport)