- Moved TypeRange into its own header/cpp file, and add hashing support.
- Change FunctionType::get() and TupleType::get() to use TypeRange
Differential Revision: https://reviews.llvm.org/D85075
return [](mlir::MLIRContext *context) -> mlir::Type {
// FIXME: a namelist group must be some well-defined data structure, use a
// tuple as a proxy for the moment
- return mlir::TupleType::get(llvm::None, context);
+ return mlir::TupleType::get(context);
};
}
template <>
IntegerType getI64Type();
IntegerType getIntegerType(unsigned width);
IntegerType getIntegerType(unsigned width, bool isSigned);
- FunctionType getFunctionType(ArrayRef<Type> inputs, ArrayRef<Type> results);
- TupleType getTupleType(ArrayRef<Type> elementTypes);
+ FunctionType getFunctionType(TypeRange inputs, TypeRange results);
+ TupleType getTupleType(TypeRange elementTypes);
NoneType getNoneType();
/// Get or construct an instance of the type 'ty' with provided arguments.
#include "mlir/IR/Attributes.h"
#include "mlir/IR/Identifier.h"
#include "mlir/IR/Location.h"
+#include "mlir/IR/TypeRange.h"
#include "mlir/IR/Types.h"
#include "mlir/IR/Value.h"
#include "mlir/Support/InterfaceSupport.h"
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
-// 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 *>, 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.
- using OwnerT = llvm::PointerUnion<const Value *, const Type *, OpOperand *>;
-
- /// 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;
-};
-
-//===----------------------------------------------------------------------===//
-// ValueTypeRange
-
-/// This class implements iteration on the types of a given range of values.
-template <typename ValueIteratorT>
-class ValueTypeIterator final
- : public llvm::mapped_iterator<ValueIteratorT, Type (*)(Value)> {
- static Type unwrap(Value value) { return value.getType(); }
-
-public:
- using reference = Type;
-
- /// Provide a const dereference method.
- Type operator*() const { return unwrap(*this->I); }
-
- /// Initializes the type iterator to the specified value iterator.
- ValueTypeIterator(ValueIteratorT it)
- : llvm::mapped_iterator<ValueIteratorT, Type (*)(Value)>(it, &unwrap) {}
-};
-
-/// 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()) {}
-
- /// 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());
-}
-
-//===----------------------------------------------------------------------===//
// OperandRange
/// This class implements the operand iterators for the Operation class.
/// Get or create a new TupleType with the provided element types. Assumes the
/// arguments define a well-formed type.
- static TupleType get(ArrayRef<Type> elementTypes, MLIRContext *context);
+ static TupleType get(TypeRange elementTypes, MLIRContext *context);
/// Get or create an empty tuple type.
- static TupleType get(MLIRContext *context) { return get({}, context); }
+ static TupleType get(MLIRContext *context);
/// Return the elements types for this tuple.
ArrayRef<Type> getTypes() const;
--- /dev/null
+//===- 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"
+
+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 *>, 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.
+ using OwnerT = llvm::PointerUnion<const Value *, const Type *, OpOperand *>;
+
+ /// 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());
+}
+
+//===----------------------------------------------------------------------===//
+// ValueTypeRange
+
+/// This class implements iteration on the types of a given range of values.
+template <typename ValueIteratorT>
+class ValueTypeIterator final
+ : public llvm::mapped_iterator<ValueIteratorT, Type (*)(Value)> {
+ static Type unwrap(Value value) { return value.getType(); }
+
+public:
+ using reference = Type;
+
+ /// Provide a const dereference method.
+ Type operator*() const { return unwrap(*this->I); }
+
+ /// Initializes the type iterator to the specified value iterator.
+ ValueTypeIterator(ValueIteratorT it)
+ : llvm::mapped_iterator<ValueIteratorT, Type (*)(Value)>(it, &unwrap) {}
+};
+
+/// 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()) {}
+
+ /// 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
class IntegerType;
class MLIRContext;
class TypeStorage;
+class TypeRange;
namespace detail {
struct FunctionTypeStorage;
public:
using Base::Base;
- static FunctionType get(ArrayRef<Type> inputs, ArrayRef<Type> results,
+ static FunctionType get(TypeRange inputs, TypeRange results,
MLIRContext *context);
// Input types.
unsigned getNumInputs() const { return getSubclassData(); }
-
Type getInput(unsigned i) const { return getInputs()[i]; }
-
ArrayRef<Type> getInputs() const;
// Result types.
unsigned getNumResults() const;
-
Type getResult(unsigned i) const { return getResults()[i]; }
-
ArrayRef<Type> getResults() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast.
else
p << op.getOperand(0);
- p << '(' << op.getOperands().drop_front(isDirect ? 0 : 1) << ')';
+ auto args = op.getOperands().drop_front(isDirect ? 0 : 1);
+ p << '(' << args << ')';
p.printOptionalAttrDict(op.getAttrs(), {"callee"});
// Reconstruct the function MLIR function type from operand and result types.
- SmallVector<Type, 8> argTypes(
- llvm::drop_begin(op.getOperandTypes(), isDirect ? 0 : 1));
-
p << " : "
- << FunctionType::get(argTypes, op.getResultTypes(), op.getContext());
+ << FunctionType::get(args.getTypes(), op.getResultTypes(), op.getContext());
}
// <operation> ::= `llvm.call` (function-id | ssa-use) `(` ssa-use-list `)`
}
FunctionType CallOp::getCalleeType() {
- SmallVector<Type, 8> argTypes(getOperandTypes());
- return FunctionType::get(argTypes, getResultTypes(), getContext());
+ return FunctionType::get(getOperandTypes(), getResultTypes(), getContext());
}
//===----------------------------------------------------------------------===//
width, isSigned ? IntegerType::Signed : IntegerType::Unsigned, context);
}
-FunctionType Builder::getFunctionType(ArrayRef<Type> inputs,
- ArrayRef<Type> results) {
+FunctionType Builder::getFunctionType(TypeRange inputs, TypeRange results) {
return FunctionType::get(inputs, results, context);
}
-TupleType Builder::getTupleType(ArrayRef<Type> elementTypes) {
+TupleType Builder::getTupleType(TypeRange elementTypes) {
return TupleType::get(elementTypes, context);
}
StandardTypes.cpp
SymbolTable.cpp
Types.cpp
+ TypeRange.cpp
TypeUtilities.cpp
Value.cpp
Verifier.cpp
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
-// TypeRange
-
-TypeRange::TypeRange(ArrayRef<Type> types)
- : TypeRange(types.data(), types.size()) {}
-TypeRange::TypeRange(OperandRange values)
- : TypeRange(values.begin().getBase(), values.size()) {}
-TypeRange::TypeRange(ResultRange values)
- : TypeRange(values.getBase()->getResultTypes().slice(values.getStartIndex(),
- values.size())) {}
-TypeRange::TypeRange(ArrayRef<Value> values)
- : TypeRange(values.data(), values.size()) {}
-TypeRange::TypeRange(ValueRange values) : TypeRange(OwnerT(), values.size()) {
- detail::ValueRangeOwner owner = values.begin().getBase();
- if (auto *op = reinterpret_cast<Operation *>(owner.ptr.dyn_cast<void *>()))
- this->base = op->getResultTypes().drop_front(owner.startIndex).data();
- else if (auto *operand = owner.ptr.dyn_cast<OpOperand *>())
- this->base = operand;
- else
- this->base = owner.ptr.get<const Value *>();
-}
-
-/// 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};
- if (auto *operand = object.dyn_cast<OpOperand *>())
- return {operand + index};
- return {object.dyn_cast<const Type *>() + index};
-}
-/// 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();
- if (auto *operand = object.dyn_cast<OpOperand *>())
- return (operand + index)->get().getType();
- return object.dyn_cast<const Type *>()[index];
-}
-
-//===----------------------------------------------------------------------===//
// OperandRange
OperandRange::OperandRange(Operation *op)
/// Get or create a new TupleType with the provided element types. Assumes the
/// arguments define a well-formed type.
-TupleType TupleType::get(ArrayRef<Type> elementTypes, MLIRContext *context) {
+TupleType TupleType::get(TypeRange elementTypes, MLIRContext *context) {
return Base::get(context, StandardTypes::Tuple, elementTypes);
}
+/// Get or create an empty tuple type.
+TupleType TupleType::get(MLIRContext *context) { return get({}, context); }
+
/// Return the elements types for this tuple.
ArrayRef<Type> TupleType::getTypes() const { return getImpl()->getTypes(); }
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Identifier.h"
#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/OperationSupport.h"
#include "mlir/IR/StandardTypes.h"
+#include "mlir/IR/TypeRange.h"
#include "llvm/ADT/bit.h"
#include "llvm/Support/TrailingObjects.h"
inputsAndResults(inputsAndResults) {}
/// The hash key used for uniquing.
- using KeyTy = std::pair<ArrayRef<Type>, ArrayRef<Type>>;
+ using KeyTy = std::pair<TypeRange, TypeRange>;
bool operator==(const KeyTy &key) const {
return key == KeyTy(getInputs(), getResults());
}
/// Construction.
static FunctionTypeStorage *construct(TypeStorageAllocator &allocator,
const KeyTy &key) {
- ArrayRef<Type> inputs = key.first, results = key.second;
+ TypeRange inputs = key.first, results = key.second;
// Copy the inputs and results into the bump pointer.
SmallVector<Type, 16> types;
struct TupleTypeStorage final
: public TypeStorage,
public llvm::TrailingObjects<TupleTypeStorage, Type> {
- using KeyTy = ArrayRef<Type>;
+ using KeyTy = TypeRange;
TupleTypeStorage(unsigned numTypes) : TypeStorage(numTypes) {}
/// Construction.
static TupleTypeStorage *construct(TypeStorageAllocator &allocator,
- ArrayRef<Type> key) {
+ TypeRange key) {
// Allocate a new storage instance.
auto byteSize = TupleTypeStorage::totalSizeToAlloc<Type>(key.size());
auto rawMem = allocator.allocate(byteSize, alignof(TupleTypeStorage));
--- /dev/null
+//===- TypeRange.cpp ------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/IR/TypeRange.h"
+#include "mlir/IR/Operation.h"
+using namespace mlir;
+
+//===----------------------------------------------------------------------===//
+// TypeRange
+
+TypeRange::TypeRange(ArrayRef<Type> types)
+ : TypeRange(types.data(), types.size()) {}
+TypeRange::TypeRange(OperandRange values)
+ : TypeRange(values.begin().getBase(), values.size()) {}
+TypeRange::TypeRange(ResultRange values)
+ : TypeRange(values.getBase()->getResultTypes().slice(values.getStartIndex(),
+ values.size())) {}
+TypeRange::TypeRange(ArrayRef<Value> values)
+ : TypeRange(values.data(), values.size()) {}
+TypeRange::TypeRange(ValueRange values) : TypeRange(OwnerT(), values.size()) {
+ detail::ValueRangeOwner owner = values.begin().getBase();
+ if (auto *op = reinterpret_cast<Operation *>(owner.ptr.dyn_cast<void *>()))
+ this->base = op->getResultTypes().drop_front(owner.startIndex).data();
+ else if (auto *operand = owner.ptr.dyn_cast<OpOperand *>())
+ this->base = operand;
+ else
+ this->base = owner.ptr.get<const Value *>();
+}
+
+/// See `llvm::detail::indexed_accessor_range_base` for details.
+TypeRange::OwnerT TypeRange::offset_base(OwnerT object, ptrdiff_t index) {
+ if (const auto *value = object.dyn_cast<const Value *>())
+ return {value + index};
+ if (auto *operand = object.dyn_cast<OpOperand *>())
+ return {operand + index};
+ return {object.dyn_cast<const Type *>() + index};
+}
+/// See `llvm::detail::indexed_accessor_range_base` for details.
+Type TypeRange::dereference_iterator(OwnerT object, ptrdiff_t index) {
+ if (const auto *value = object.dyn_cast<const Value *>())
+ return (value + index)->getType();
+ if (auto *operand = object.dyn_cast<OpOperand *>())
+ return (operand + index)->get().getType();
+ return object.dyn_cast<const Type *>()[index];
+}
// FunctionType
//===----------------------------------------------------------------------===//
-FunctionType FunctionType::get(ArrayRef<Type> inputs, ArrayRef<Type> results,
+FunctionType FunctionType::get(TypeRange inputs, TypeRange results,
MLIRContext *context) {
return Base::get(context, Type::Kind::Function, inputs, results);
}