| //===- TypeRange.h ----------------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the TypeRange and ValueTypeRange classes. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef MLIR_IR_TYPERANGE_H |
| #define MLIR_IR_TYPERANGE_H |
| |
| #include "mlir/IR/Types.h" |
| #include "mlir/IR/Value.h" |
| #include "llvm/ADT/PointerUnion.h" |
| #include "llvm/ADT/Sequence.h" |
| |
| namespace mlir { |
| class OperandRange; |
| class ResultRange; |
| class Type; |
| class Value; |
| class ValueRange; |
| template <typename ValueRangeT> |
| class ValueTypeRange; |
| |
| //===----------------------------------------------------------------------===// |
| // TypeRange |
| |
| /// This class provides an abstraction over the various different ranges of |
| /// value types. In many cases, this prevents the need to explicitly materialize |
| /// a SmallVector/std::vector. This class should be used in places that are not |
| /// suitable for a more derived type (e.g. ArrayRef) or a template range |
| /// parameter. |
| class TypeRange : public llvm::detail::indexed_accessor_range_base< |
| TypeRange, |
| llvm::PointerUnion<const Value *, const Type *, |
| OpOperand *, detail::OpResultImpl *>, |
| Type, Type, Type> { |
| public: |
| using RangeBaseT::RangeBaseT; |
| TypeRange(ArrayRef<Type> types = llvm::None); |
| explicit TypeRange(OperandRange values); |
| explicit TypeRange(ResultRange values); |
| explicit TypeRange(ValueRange values); |
| explicit TypeRange(ArrayRef<Value> values); |
| explicit TypeRange(ArrayRef<BlockArgument> values) |
| : TypeRange(ArrayRef<Value>(values.data(), values.size())) {} |
| template <typename ValueRangeT> |
| TypeRange(ValueTypeRange<ValueRangeT> values) |
| : TypeRange(ValueRangeT(values.begin().getCurrent(), |
| values.end().getCurrent())) {} |
| template <typename Arg, |
| typename = typename std::enable_if_t< |
| std::is_constructible<ArrayRef<Type>, Arg>::value>> |
| TypeRange(Arg &&arg) : TypeRange(ArrayRef<Type>(std::forward<Arg>(arg))) {} |
| TypeRange(std::initializer_list<Type> types) |
| : TypeRange(ArrayRef<Type>(types)) {} |
| |
| private: |
| /// The owner of the range is either: |
| /// * A pointer to the first element of an array of values. |
| /// * A pointer to the first element of an array of types. |
| /// * A pointer to the first element of an array of operands. |
| /// * A pointer to the first element of an array of results. |
| using OwnerT = llvm::PointerUnion<const Value *, const Type *, OpOperand *, |
| detail::OpResultImpl *>; |
| |
| /// See `llvm::detail::indexed_accessor_range_base` for details. |
| static OwnerT offset_base(OwnerT object, ptrdiff_t index); |
| /// 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`. |
| friend RangeBaseT; |
| }; |
| |
| /// Make TypeRange hashable. |
| inline ::llvm::hash_code hash_value(TypeRange arg) { |
| return ::llvm::hash_combine_range(arg.begin(), arg.end()); |
| } |
| |
| /// Emit a type range to the given output stream. |
| inline raw_ostream &operator<<(raw_ostream &os, const TypeRange &types) { |
| llvm::interleaveComma(types, os); |
| return os; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // TypeRangeRange |
| |
| using TypeRangeRangeIterator = |
| llvm::mapped_iterator<llvm::iota_range<unsigned>::iterator, |
| std::function<TypeRange(unsigned)>>; |
| |
| /// This class provides an abstraction for a range of TypeRange. This is useful |
| /// when accessing the types of a range of ranges, such as when using |
| /// OperandRangeRange. |
| class TypeRangeRange : public llvm::iterator_range<TypeRangeRangeIterator> { |
| public: |
| template <typename RangeT> |
| TypeRangeRange(const RangeT &range) |
| : TypeRangeRange(llvm::seq<unsigned>(0, range.size()), range) {} |
| |
| private: |
| template <typename RangeT> |
| TypeRangeRange(llvm::iota_range<unsigned> sizeRange, const RangeT &range) |
| : llvm::iterator_range<TypeRangeRangeIterator>( |
| {sizeRange.begin(), getRangeFn(range)}, |
| {sizeRange.end(), nullptr}) {} |
| |
| template <typename RangeT> |
| static std::function<TypeRange(unsigned)> getRangeFn(const RangeT &range) { |
| return [=](unsigned index) -> TypeRange { return TypeRange(range[index]); }; |
| } |
| }; |
| |
| //===----------------------------------------------------------------------===// |
| // ValueTypeRange |
| |
| /// This class implements iteration on the types of a given range of values. |
| template <typename ValueIteratorT> |
| class ValueTypeIterator final |
| : public llvm::mapped_iterator_base<ValueTypeIterator<ValueIteratorT>, |
| ValueIteratorT, Type> { |
| public: |
| using llvm::mapped_iterator_base<ValueTypeIterator<ValueIteratorT>, |
| ValueIteratorT, Type>::mapped_iterator_base; |
| |
| /// Map the element to the iterator result type. |
| Type mapElement(Value value) const { return value.getType(); } |
| }; |
| |
| /// This class implements iteration on the types of a given range of values. |
| template <typename ValueRangeT> |
| class ValueTypeRange final |
| : public llvm::iterator_range< |
| ValueTypeIterator<typename ValueRangeT::iterator>> { |
| public: |
| using llvm::iterator_range< |
| ValueTypeIterator<typename ValueRangeT::iterator>>::iterator_range; |
| template <typename Container> |
| ValueTypeRange(Container &&c) : ValueTypeRange(c.begin(), c.end()) {} |
| |
| /// Return the type at the given index. |
| Type operator[](size_t index) const { |
| assert(index < size() && "invalid index into type range"); |
| return *(this->begin() + index); |
| } |
| |
| /// Return the size of this range. |
| size_t size() const { return llvm::size(*this); } |
| |
| /// Return first type in the range. |
| Type front() { return (*this)[0]; } |
| |
| /// Compare this range with another. |
| template <typename OtherT> |
| bool operator==(const OtherT &other) const { |
| return llvm::size(*this) == llvm::size(other) && |
| std::equal(this->begin(), this->end(), other.begin()); |
| } |
| template <typename OtherT> |
| bool operator!=(const OtherT &other) const { |
| return !(*this == other); |
| } |
| }; |
| |
| template <typename RangeT> |
| inline bool operator==(ArrayRef<Type> lhs, const ValueTypeRange<RangeT> &rhs) { |
| return lhs.size() == static_cast<size_t>(llvm::size(rhs)) && |
| std::equal(lhs.begin(), lhs.end(), rhs.begin()); |
| } |
| |
| } // namespace mlir |
| |
| namespace llvm { |
| |
| // Provide DenseMapInfo for TypeRange. |
| template <> |
| struct DenseMapInfo<mlir::TypeRange> { |
| static mlir::TypeRange getEmptyKey() { |
| return mlir::TypeRange(getEmptyKeyPointer(), 0); |
| } |
| |
| static mlir::TypeRange getTombstoneKey() { |
| return mlir::TypeRange(getTombstoneKeyPointer(), 0); |
| } |
| |
| static unsigned getHashValue(mlir::TypeRange val) { return hash_value(val); } |
| |
| static bool isEqual(mlir::TypeRange lhs, mlir::TypeRange rhs) { |
| if (isEmptyKey(rhs)) |
| return isEmptyKey(lhs); |
| if (isTombstoneKey(rhs)) |
| return isTombstoneKey(lhs); |
| return lhs == rhs; |
| } |
| |
| private: |
| static const mlir::Type *getEmptyKeyPointer() { |
| return DenseMapInfo<mlir::Type *>::getEmptyKey(); |
| } |
| |
| static const mlir::Type *getTombstoneKeyPointer() { |
| return DenseMapInfo<mlir::Type *>::getTombstoneKey(); |
| } |
| |
| static bool isEmptyKey(mlir::TypeRange range) { |
| if (const auto *type = range.getBase().dyn_cast<const mlir::Type *>()) |
| return type == getEmptyKeyPointer(); |
| return false; |
| } |
| |
| static bool isTombstoneKey(mlir::TypeRange range) { |
| if (const auto *type = range.getBase().dyn_cast<const mlir::Type *>()) |
| return type == getTombstoneKeyPointer(); |
| return false; |
| } |
| }; |
| |
| } // namespace llvm |
| |
| #endif // MLIR_IR_TYPERANGE_H |