diff --git a/mlir/bindings/python/pybind.cpp b/mlir/bindings/python/pybind.cpp index caff9af59acc..10445edaf125 100644 --- a/mlir/bindings/python/pybind.cpp +++ b/mlir/bindings/python/pybind.cpp @@ -87,8 +87,7 @@ struct PythonValueHandle { operator ValueHandle &() { return value; } std::string str() const { - return std::to_string( - reinterpret_cast(value.getValue().getAsOpaquePointer())); + return std::to_string(reinterpret_cast(value.getValue())); } PythonValueHandle call(const std::vector &args) { diff --git a/mlir/include/mlir/Analysis/AffineAnalysis.h b/mlir/include/mlir/Analysis/AffineAnalysis.h index 6029a9ccdaa4..5d9422883c11 100644 --- a/mlir/include/mlir/Analysis/AffineAnalysis.h +++ b/mlir/include/mlir/Analysis/AffineAnalysis.h @@ -15,7 +15,9 @@ #ifndef MLIR_ANALYSIS_AFFINE_ANALYSIS_H #define MLIR_ANALYSIS_AFFINE_ANALYSIS_H -#include "mlir/IR/Value.h" +#include "mlir/Support/LLVM.h" +#include "mlir/Support/LogicalResult.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" @@ -26,9 +28,10 @@ class AffineForOp; class AffineValueMap; class FlatAffineConstraints; class Operation; +class Value; // TODO(riverriddle) Remove this after Value is value-typed. -using ValuePtr = Value; +using ValuePtr = Value *; /// Returns in `affineApplyOps`, the sequence of those AffineApplyOp /// Operations that are reachable via a search starting from `operands` and diff --git a/mlir/include/mlir/Analysis/Liveness.h b/mlir/include/mlir/Analysis/Liveness.h index cbd2e63fd3ef..791c164c7d29 100644 --- a/mlir/include/mlir/Analysis/Liveness.h +++ b/mlir/include/mlir/Analysis/Liveness.h @@ -33,7 +33,7 @@ class Region; class Value; // TODO(riverriddle) Remove this after Value is value-typed. -using ValuePtr = Value; +using ValuePtr = Value *; /// Represents an analysis for computing liveness information from a /// given top-level operation. The analysis iterates over all associated diff --git a/mlir/include/mlir/Analysis/LoopAnalysis.h b/mlir/include/mlir/Analysis/LoopAnalysis.h index 75d7b98e20f7..66f0033bf2fc 100644 --- a/mlir/include/mlir/Analysis/LoopAnalysis.h +++ b/mlir/include/mlir/Analysis/LoopAnalysis.h @@ -28,7 +28,7 @@ class Operation; class Value; // TODO(riverriddle) Remove this after Value is value-typed. -using ValuePtr = Value; +using ValuePtr = Value *; /// Returns the trip count of the loop as an affine map with its corresponding /// operands if the latter is expressible as an affine expression, and nullptr diff --git a/mlir/include/mlir/Conversion/AffineToStandard/AffineToStandard.h b/mlir/include/mlir/Conversion/AffineToStandard/AffineToStandard.h index c8298760bad0..8e873bfb1c3b 100644 --- a/mlir/include/mlir/Conversion/AffineToStandard/AffineToStandard.h +++ b/mlir/include/mlir/Conversion/AffineToStandard/AffineToStandard.h @@ -22,7 +22,7 @@ class RewritePattern; class Value; // TODO(riverriddle) Remove this after Value is value-typed. -using ValuePtr = Value; +using ValuePtr = Value *; // Owning list of rewriting patterns. class OwningRewritePatternList; diff --git a/mlir/include/mlir/Conversion/LoopsToGPU/LoopsToGPU.h b/mlir/include/mlir/Conversion/LoopsToGPU/LoopsToGPU.h index b7423a58f2a4..5f3ea87f3cc8 100644 --- a/mlir/include/mlir/Conversion/LoopsToGPU/LoopsToGPU.h +++ b/mlir/include/mlir/Conversion/LoopsToGPU/LoopsToGPU.h @@ -16,7 +16,7 @@ struct LogicalResult; class Value; // TODO(riverriddle) Remove this after Value is value-typed. -using ValuePtr = Value; +using ValuePtr = Value *; namespace loop { class ForOp; diff --git a/mlir/include/mlir/Dialect/VectorOps/Utils.h b/mlir/include/mlir/Dialect/VectorOps/Utils.h index 04bd8b50fb66..b4d8ad65e60f 100644 --- a/mlir/include/mlir/Dialect/VectorOps/Utils.h +++ b/mlir/include/mlir/Dialect/VectorOps/Utils.h @@ -26,7 +26,7 @@ class Value; class VectorType; // TODO(riverriddle) Remove this after Value is value-typed. -using ValuePtr = Value; +using ValuePtr = Value *; /// Computes and returns the multi-dimensional ratio of `superShape` to /// `subShape`. This is calculated by performing a traversal from minor to major diff --git a/mlir/include/mlir/EDSC/Builders.h b/mlir/include/mlir/EDSC/Builders.h index f9629a8d99e9..6607f267057b 100644 --- a/mlir/include/mlir/EDSC/Builders.h +++ b/mlir/include/mlir/EDSC/Builders.h @@ -329,7 +329,6 @@ public: /// Implicit conversion useful for automatic conversion to Container. operator ValuePtr() const { return getValue(); } - operator bool() const { return hasValue(); } /// Generic mlir::Op create. This is the key to being extensible to the whole /// of MLIR without duplicating the type system or the op definitions. diff --git a/mlir/include/mlir/IR/Block.h b/mlir/include/mlir/IR/Block.h index 33feea7bcbb4..b5189b48a85f 100644 --- a/mlir/include/mlir/IR/Block.h +++ b/mlir/include/mlir/IR/Block.h @@ -63,7 +63,7 @@ public: //===--------------------------------------------------------------------===// // This is the list of arguments to the block. - using BlockArgListType = MutableArrayRef; + using BlockArgListType = ArrayRef; BlockArgListType getArguments() { return arguments; } diff --git a/mlir/include/mlir/IR/BlockAndValueMapping.h b/mlir/include/mlir/IR/BlockAndValueMapping.h index b7ad36072bd1..82173c34368b 100644 --- a/mlir/include/mlir/IR/BlockAndValueMapping.h +++ b/mlir/include/mlir/IR/BlockAndValueMapping.h @@ -28,18 +28,14 @@ public: /// Inserts a new mapping for 'from' to 'to'. If there is an existing mapping, /// it is overwritten. void map(Block *from, Block *to) { valueMap[from] = to; } - void map(Value from, Value to) { - valueMap[from.getAsOpaquePointer()] = to.getAsOpaquePointer(); - } + void map(ValuePtr from, ValuePtr to) { valueMap[from] = to; } /// Erases a mapping for 'from'. - void erase(Block *from) { valueMap.erase(from); } - void erase(Value from) { valueMap.erase(from.getAsOpaquePointer()); } + void erase(IRObjectWithUseList *from) { valueMap.erase(from); } /// Checks to see if a mapping for 'from' exists. - bool contains(Block *from) const { return valueMap.count(from); } - bool contains(Value from) const { - return valueMap.count(from.getAsOpaquePointer()); + bool contains(IRObjectWithUseList *from) const { + return valueMap.count(from); } /// Lookup a mapped value within the map. If a mapping for the provided value @@ -47,19 +43,23 @@ public: Block *lookupOrNull(Block *from) const { return lookupOrValue(from, (Block *)nullptr); } - Value lookupOrNull(Value from) const { return lookupOrValue(from, Value()); } + ValuePtr lookupOrNull(ValuePtr from) const { + return lookupOrValue(from, (ValuePtr) nullptr); + } /// Lookup a mapped value within the map. If a mapping for the provided value /// does not exist then return the provided value. Block *lookupOrDefault(Block *from) const { return lookupOrValue(from, from); } - Value lookupOrDefault(Value from) const { return lookupOrValue(from, from); } + ValuePtr lookupOrDefault(ValuePtr from) const { + return lookupOrValue(from, from); + } /// Lookup a mapped value within the map. This asserts the provided value /// exists within the map. - template T lookup(T from) const { - auto result = lookupOrNull(from); + template T *lookup(T *from) const { + auto *result = lookupOrNull(from); assert(result && "expected 'from' to be contained within the map"); return result; } @@ -69,18 +69,14 @@ public: private: /// Utility lookupOrValue that looks up an existing key or returns the - /// provided value. - Block *lookupOrValue(Block *from, Block *value) const { + /// provided value. This function assumes that if a mapping does exist, then + /// it is of 'T' type. + template T *lookupOrValue(T *from, T *value) const { auto it = valueMap.find(from); - return it != valueMap.end() ? reinterpret_cast(it->second) : value; - } - Value lookupOrValue(Value from, Value value) const { - auto it = valueMap.find(from.getAsOpaquePointer()); - return it != valueMap.end() ? Value::getFromOpaquePointer(it->second) - : value; + return it != valueMap.end() ? static_cast(it->second) : value; } - DenseMap valueMap; + DenseMap valueMap; }; } // end namespace mlir diff --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h index 8e2aed29500b..e58a5b070383 100644 --- a/mlir/include/mlir/IR/OpImplementation.h +++ b/mlir/include/mlir/IR/OpImplementation.h @@ -142,14 +142,17 @@ private: // Make the implementations convenient to use. inline OpAsmPrinter &operator<<(OpAsmPrinter &p, ValueRef value) { - p.printOperand(value); + p.printOperand(&value); return p; } +inline OpAsmPrinter &operator<<(OpAsmPrinter &p, ValuePtr value) { + return p << *value; +} -template ::value && - !std::is_convertible::value, - T>::type * = nullptr> +template ::value && + !std::is_convertible::value, + T>::type * = nullptr> inline OpAsmPrinter &operator<<(OpAsmPrinter &p, const T &values) { p.printOperands(values); return p; @@ -169,7 +172,8 @@ inline OpAsmPrinter &operator<<(OpAsmPrinter &p, Attribute attr) { // even if it isn't exactly one of them. For example, we want to print // FunctionType with the Type version above, not have it match this. template ::value && + !std::is_convertible::value && + !std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value && diff --git a/mlir/include/mlir/IR/Operation.h b/mlir/include/mlir/IR/Operation.h index 29227613468a..9ab900c87616 100644 --- a/mlir/include/mlir/IR/Operation.h +++ b/mlir/include/mlir/IR/Operation.h @@ -246,7 +246,7 @@ public: unsigned getNumResults() { return numResults; } - ValuePtr getResult(unsigned idx) { return getOpResult(idx); } + ValuePtr getResult(unsigned idx) { return &getOpResult(idx); } /// Support result iteration. using result_range = ResultRange; diff --git a/mlir/include/mlir/IR/OperationSupport.h b/mlir/include/mlir/IR/OperationSupport.h index ef2ff44ef6e0..146816633725 100644 --- a/mlir/include/mlir/IR/OperationSupport.h +++ b/mlir/include/mlir/IR/OperationSupport.h @@ -525,8 +525,8 @@ private: /// This class implements iteration on the types of a given range of values. template class ValueTypeIterator final - : public llvm::mapped_iterator { - static Type unwrap(Value value) { return value.getType(); } + : public llvm::mapped_iterator { + static Type unwrap(ValuePtr value) { return value->getType(); } public: using reference = Type; @@ -536,7 +536,8 @@ public: /// Initializes the type iterator to the specified value iterator. ValueTypeIterator(ValueIteratorT it) - : llvm::mapped_iterator(it, &unwrap) {} + : llvm::mapped_iterator(it, &unwrap) { + } }; //===----------------------------------------------------------------------===// @@ -545,7 +546,7 @@ public: /// This class implements the operand iterators for the Operation class. class OperandRange final : public detail::indexed_accessor_range_base { + ValuePtr, ValuePtr, ValuePtr> { public: using RangeBaseT::RangeBaseT; OperandRange(Operation *op); @@ -560,7 +561,7 @@ private: return object + index; } /// See `detail::indexed_accessor_range_base` for details. - static Value dereference_iterator(OpOperand *object, ptrdiff_t index) { + static ValuePtr dereference_iterator(OpOperand *object, ptrdiff_t index) { return object[index].get(); } @@ -573,8 +574,8 @@ private: /// This class implements the result iterators for the Operation class. class ResultRange final - : public detail::indexed_accessor_range_base { + : public detail::indexed_accessor_range_base { public: using RangeBaseT::RangeBaseT; ResultRange(Operation *op); @@ -585,12 +586,12 @@ public: private: /// See `detail::indexed_accessor_range_base` for details. - static OpResult *offset_base(OpResult *object, ptrdiff_t index) { + static OpResultPtr offset_base(OpResultPtr object, ptrdiff_t index) { return object + index; } /// See `detail::indexed_accessor_range_base` for details. - static Value dereference_iterator(OpResult *object, ptrdiff_t index) { - return object[index]; + static ValuePtr dereference_iterator(OpResultPtr object, ptrdiff_t index) { + return &object[index]; } /// Allow access to `offset_base` and `dereference_iterator`. @@ -607,24 +608,25 @@ private: /// parameter. class ValueRange final : public detail::indexed_accessor_range_base< - ValueRange, PointerUnion, - Value, Value, Value> { + ValueRange, PointerUnion, + ValuePtr, ValuePtr, ValuePtr> { public: using RangeBaseT::RangeBaseT; template , Arg>::value && - !std::is_convertible::value>> - ValueRange(Arg &&arg) : ValueRange(ArrayRef(std::forward(arg))) {} - ValueRange(const Value &value) : ValueRange(&value, /*count=*/1) {} - ValueRange(const std::initializer_list &values) - : ValueRange(ArrayRef(values)) {} + std::is_constructible, Arg>::value && + !std::is_convertible::value>> + ValueRange(Arg &&arg) + : ValueRange(ArrayRef(std::forward(arg))) {} + ValueRange(ValuePtr const &value) : ValueRange(&value, /*count=*/1) {} + ValueRange(const std::initializer_list &values) + : ValueRange(ArrayRef(values)) {} ValueRange(iterator_range values) : ValueRange(OperandRange(values)) {} ValueRange(iterator_range values) : ValueRange(ResultRange(values)) {} - ValueRange(ArrayRef values = llvm::None); + ValueRange(ArrayRef values = llvm::None); ValueRange(OperandRange values); ValueRange(ResultRange values); @@ -635,12 +637,12 @@ public: private: /// The type representing the owner of this range. This is either a list of /// values, operands, or results. - using OwnerT = PointerUnion; + using OwnerT = PointerUnion; /// See `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. - static Value dereference_iterator(const OwnerT &owner, ptrdiff_t index); + static ValuePtr dereference_iterator(const OwnerT &owner, ptrdiff_t index); /// Allow access to `offset_base` and `dereference_iterator`. friend RangeBaseT; diff --git a/mlir/include/mlir/IR/TypeUtilities.h b/mlir/include/mlir/IR/TypeUtilities.h index fd9d317ed359..b4713226559d 100644 --- a/mlir/include/mlir/IR/TypeUtilities.h +++ b/mlir/include/mlir/IR/TypeUtilities.h @@ -33,6 +33,7 @@ Type getElementTypeOrSelf(Type type); /// Return the element type or return the type itself. Type getElementTypeOrSelf(Attribute attr); Type getElementTypeOrSelf(ValuePtr val); +Type getElementTypeOrSelf(ValueRef val); /// Get the types within a nested Tuple. A helper for the class method that /// handles storage concerns, which is tricky to do in tablegen. diff --git a/mlir/include/mlir/IR/UseDefLists.h b/mlir/include/mlir/IR/UseDefLists.h index 05720ed39af8..898d0da2b28a 100644 --- a/mlir/include/mlir/IR/UseDefLists.h +++ b/mlir/include/mlir/IR/UseDefLists.h @@ -21,7 +21,6 @@ namespace mlir { class IROperand; class Operation; -class Value; template class ValueUseIterator; template class ValueUserIterator; @@ -168,22 +167,6 @@ private: } }; -/// A reference to a value, suitable for use as an operand of an operation. -class OpOperand : public IROperand { -public: - OpOperand(Operation *owner) : IROperand(owner) {} - OpOperand(Operation *owner, Value value); - - /// Return the current value being used by this operand. - Value get(); - - /// Set the current value being used by this operand. - void set(Value newValue); - - /// Return which operand this is in the operand list of the User. - unsigned getOperandNumber(); -}; - /// A reference to a value, suitable for use as an operand of an operation, /// operation, etc. IRValueTy is the root type to use for values this tracks, /// and SSAUserTy is the type that will contain operands. diff --git a/mlir/include/mlir/IR/Value.h b/mlir/include/mlir/IR/Value.h index 26703a253063..030e6fa58b12 100644 --- a/mlir/include/mlir/IR/Value.h +++ b/mlir/include/mlir/IR/Value.h @@ -25,101 +25,40 @@ class OpResult; class Region; class Value; -namespace detail { -/// The internal implementation of a Value. -class ValueImpl : public IRObjectWithUseList { -protected: - /// This enumerates all of the SSA value kinds. - enum class Kind { - BlockArgument, - OpResult, - }; +/// Using directives that simplify the transition of Value to being value typed. +using BlockArgumentPtr = BlockArgument *; +using OpResultPtr = OpResult *; +using ValueRef = Value &; +using ValuePtr = Value *; - ValueImpl(Kind kind, Type type) : typeAndKind(type, kind) {} +/// Operands contain a Value. +using OpOperand = IROperandImpl; -private: - /// The type of the value and its kind. - llvm::PointerIntPair typeAndKind; - - /// Allow access to 'typeAndKind'. - friend Value; -}; - -/// The internal implementation of a BlockArgument. -class BlockArgumentImpl : public ValueImpl { - BlockArgumentImpl(Type type, Block *owner) - : ValueImpl(Kind::BlockArgument, type), owner(owner) {} - - /// The owner of this argument. - Block *owner; - - /// Allow access to owner and constructor. - friend BlockArgument; -}; - -class OpResultImpl : public ValueImpl { - OpResultImpl(Type type, Operation *owner) - : ValueImpl(Kind::OpResult, type), owner(owner) {} - - /// The owner of this result. - Operation *owner; - - /// Allow access to owner and the constructor. - friend OpResult; -}; -} // end namespace detail - -/// This class represents an instance of an SSA value in the MLIR system, -/// representing a computable value that has a type and a set of users. An SSA -/// value is either a BlockArgument or the result of an operation. Note: This -/// class has value-type semantics and is just a simple wrapper around a -/// ValueImpl that is either owner by a block(in the case of a BlockArgument) or -/// an Operation(in the case of an OpResult). +/// This is the common base class for all SSA values in the MLIR system, +/// representing a computable value that has a type and a set of users. /// -class Value { +class Value : public IRObjectWithUseList { public: /// This enumerates all of the SSA value kinds in the MLIR system. enum class Kind { - BlockArgument, - OpResult, + BlockArgument, // block argument + OpResult, // operation result }; - Value(std::nullptr_t) : impl(nullptr) {} - Value(detail::ValueImpl *impl = nullptr) : impl(impl) {} - Value(const Value &) = default; - Value &operator=(const Value &) = default; ~Value() {} - template bool isa() const { - assert(impl && "isa<> used on a null type."); - return U::classof(*this); + template bool isa() const { return U::classof(this); } + template U *dyn_cast() const { + return isa() ? (U *)this : nullptr; } - template U dyn_cast() const { - return isa() ? U(impl) : U(nullptr); - } - template U dyn_cast_or_null() const { - return (impl && isa()) ? U(impl) : U(nullptr); - } - template U cast() const { + template U *cast() const { assert(isa()); - return U(impl); + return (U *)this; } - /// Temporary methods to enable transition of Value to being used as a - /// value-type. - /// TODO(riverriddle) Remove these when all usages have been removed. - Value operator*() const { return *this; } - Value *operator->() const { return (Value *)this; } + Kind getKind() const { return typeAndKind.getInt(); } - operator bool() const { return impl; } - bool operator==(const Value &other) const { return impl == other.impl; } - bool operator!=(const Value &other) const { return !(*this == other); } - - /// Return the kind of this value. - Kind getKind() const { return (Kind)impl->typeAndKind.getInt(); } - - /// Return the type of this value. - Type getType() const { return impl->typeAndKind.getPointer(); } + Type getType() const { return typeAndKind.getPointer(); } /// Utility to get the associated MLIRContext that this value is defined in. MLIRContext *getContext() const { return getType().getContext(); } @@ -130,18 +69,18 @@ public: /// completely invalid IR very easily. It is strongly recommended that you /// recreate IR objects with the right types instead of mutating them in /// place. - void setType(Type newType) { impl->typeAndKind.setPointer(newType); } + void setType(Type newType) { typeAndKind.setPointer(newType); } /// Replace all uses of 'this' value with the new value, updating anything in /// the IR that uses 'this' to use the other value instead. When this returns /// there are zero uses of 'this'. - void replaceAllUsesWith(Value newValue) const { - impl->replaceAllUsesWith(newValue.impl); + void replaceAllUsesWith(ValuePtr newValue) { + IRObjectWithUseList::replaceAllUsesWith(newValue); } /// If this value is the result of an operation, return the operation that /// defines it. - Operation *getDefiningOp() const; + Operation *getDefiningOp(); /// If this value is the result of an operation, use it as a location, /// otherwise return an unknown location. @@ -159,51 +98,24 @@ public: /// Returns a range of all uses, which is useful for iterating over all uses. inline use_range getUses(); - using user_iterator = ValueUserIterator; - using user_range = iterator_range; - - user_iterator user_begin() const { return impl->user_begin(); } - user_iterator user_end() const { return impl->user_end(); } - - /// Returns a range of all users. - user_range getUsers() const { return impl->getUsers(); } - - /// Returns true if this value has no uses. - bool use_empty() const { return impl->use_empty(); } - - /// Returns true if this value has exactly one use. - bool hasOneUse() const { return impl->hasOneUse(); } - - /// Drop all uses of this object from their respective owners. - void dropAllUses() const { impl->dropAllUses(); } - void print(raw_ostream &os); void dump(); - /// Methods for supporting PointerLikeTypeTraits. - void *getAsOpaquePointer() const { return static_cast(impl); } - static Value getFromOpaquePointer(const void *pointer) { - return reinterpret_cast(const_cast(pointer)); - } - - friend ::llvm::hash_code hash_value(Value arg); - protected: - /// The internal implementation of this value. - mutable detail::ValueImpl *impl; + Value(Kind kind, Type type) : typeAndKind(type, kind) {} - /// Allow access to 'impl'. - friend OpOperand; +private: + llvm::PointerIntPair typeAndKind; }; -inline raw_ostream &operator<<(raw_ostream &os, Value value) { +inline raw_ostream &operator<<(raw_ostream &os, ValueRef value) { value.print(os); return os; } // Utility functions for iterating through Value uses. inline auto Value::use_begin() -> use_iterator { - return use_iterator((OpOperand *)impl->getFirstUse()); + return use_iterator((OpOperand *)getFirstUse()); } inline auto Value::use_end() -> use_iterator { return use_iterator(nullptr); } @@ -215,154 +127,47 @@ inline auto Value::getUses() -> iterator_range { /// Block arguments are values. class BlockArgument : public Value { public: - using Value::Value; - - /// Temporary methods to enable transition of Value to being used as a - /// value-type. - /// TODO(riverriddle) Remove this when all usages have been removed. - BlockArgument *operator->() { return this; } - - static bool classof(Value value) { - return value.getKind() == Kind::BlockArgument; + static bool classof(const Value *value) { + return const_cast(value)->getKind() == Kind::BlockArgument; } - /// Returns the block that owns this argument. - Block *getOwner() const { return getImpl()->owner; } + Block *getOwner() { return owner; } /// Returns the number of this argument. - unsigned getArgNumber() const; + unsigned getArgNumber(); private: - /// Allocate a new argument with the given type and owner. - static BlockArgument create(Type type, Block *owner) { - return new detail::BlockArgumentImpl(type, owner); - } + friend class Block; // For access to private constructor. + BlockArgument(Type type, Block *owner) + : Value(Value::Kind::BlockArgument, type), owner(owner) {} - /// Destroy and deallocate this argument. - void destroy() { delete getImpl(); } - - /// Get a raw pointer to the internal implementation. - detail::BlockArgumentImpl *getImpl() const { - return reinterpret_cast(impl); - } - - /// Allow access to `create` and `destroy`. - friend Block; + /// The owner of this operand. + /// TODO: can encode this more efficiently to avoid the space hit of this + /// through bitpacking shenanigans. + Block *const owner; }; /// This is a value defined by a result of an operation. class OpResult : public Value { public: - using Value::Value; + OpResult(Type type, Operation *owner) + : Value(Value::Kind::OpResult, type), owner(owner) {} - /// Temporary methods to enable transition of Value to being used as a - /// value-type. - /// TODO(riverriddle) Remove these when all usages have been removed. - OpResult *operator*() { return this; } - OpResult *operator->() { return this; } + static bool classof(const Value *value) { + return const_cast(value)->getKind() == Kind::OpResult; + } - static bool classof(Value value) { return value.getKind() == Kind::OpResult; } - - /// Returns the operation that owns this result. - Operation *getOwner() const { return getImpl()->owner; } + Operation *getOwner() { return owner; } /// Returns the number of this result. - unsigned getResultNumber() const; + unsigned getResultNumber(); private: - /// Allocate a new result with the given type and owner. - static OpResult create(Type type, Operation *owner) { - return new detail::OpResultImpl(type, owner); - } - - /// Destroy and deallocate this result. - void destroy() { delete getImpl(); } - - /// Get a raw pointer to the internal implementation. - detail::OpResultImpl *getImpl() const { - return reinterpret_cast(impl); - } - - /// Allow access to `create` and `destroy`. - friend Operation; + /// The owner of this operand. + /// TODO: can encode this more efficiently to avoid the space hit of this + /// through bitpacking shenanigans. + Operation *const owner; }; - -/// Make Value hashable. -inline ::llvm::hash_code hash_value(Value arg) { - return ::llvm::hash_value(arg.impl); -} - -/// Using directives that simplify the transition of Value to being value typed. -using BlockArgumentPtr = BlockArgument; -using OpResultPtr = OpResult; -using ValueRef = Value; -using ValuePtr = Value; - } // namespace mlir -namespace llvm { - -template <> struct DenseMapInfo { - static mlir::Value getEmptyKey() { - auto pointer = llvm::DenseMapInfo::getEmptyKey(); - return mlir::Value(static_cast(pointer)); - } - static mlir::Value getTombstoneKey() { - auto pointer = llvm::DenseMapInfo::getTombstoneKey(); - return mlir::Value(static_cast(pointer)); - } - static unsigned getHashValue(mlir::Value val) { - return mlir::hash_value(val); - } - static bool isEqual(mlir::Value LHS, mlir::Value RHS) { return LHS == RHS; } -}; - -/// Allow stealing the low bits of a value. -template <> struct PointerLikeTypeTraits { -public: - static inline void *getAsVoidPointer(mlir::Value I) { - return const_cast(I.getAsOpaquePointer()); - } - static inline mlir::Value getFromVoidPointer(void *P) { - return mlir::Value::getFromOpaquePointer(P); - } - enum { - NumLowBitsAvailable = - PointerLikeTypeTraits::NumLowBitsAvailable - }; -}; - -template <> struct DenseMapInfo { - static mlir::BlockArgument getEmptyKey() { - auto pointer = llvm::DenseMapInfo::getEmptyKey(); - return mlir::BlockArgument(static_cast(pointer)); - } - static mlir::BlockArgument getTombstoneKey() { - auto pointer = llvm::DenseMapInfo::getTombstoneKey(); - return mlir::BlockArgument(static_cast(pointer)); - } - static unsigned getHashValue(mlir::BlockArgument val) { - return mlir::hash_value(val); - } - static bool isEqual(mlir::BlockArgument LHS, mlir::BlockArgument RHS) { - return LHS == RHS; - } -}; - -/// Allow stealing the low bits of a value. -template <> struct PointerLikeTypeTraits { -public: - static inline void *getAsVoidPointer(mlir::Value I) { - return const_cast(I.getAsOpaquePointer()); - } - static inline mlir::BlockArgument getFromVoidPointer(void *P) { - return mlir::Value::getFromOpaquePointer(P).cast(); - } - enum { - NumLowBitsAvailable = - PointerLikeTypeTraits::NumLowBitsAvailable - }; -}; -} // end namespace llvm - #endif diff --git a/mlir/lib/Analysis/AffineStructures.cpp b/mlir/lib/Analysis/AffineStructures.cpp index ce96a19751fc..7ab547483cdb 100644 --- a/mlir/lib/Analysis/AffineStructures.cpp +++ b/mlir/lib/Analysis/AffineStructures.cpp @@ -1965,7 +1965,7 @@ void FlatAffineConstraints::addLocalFloorDiv(ArrayRef dividend, bool FlatAffineConstraints::findId(ValueRef id, unsigned *pos) const { unsigned i = 0; for (const auto &mayBeId : ids) { - if (mayBeId.hasValue() && mayBeId.getValue() == id) { + if (mayBeId.hasValue() && mayBeId.getValue() == &id) { *pos = i; return true; } @@ -1976,7 +1976,7 @@ bool FlatAffineConstraints::findId(ValueRef id, unsigned *pos) const { bool FlatAffineConstraints::containsId(ValueRef id) const { return llvm::any_of(ids, [&](const Optional &mayBeId) { - return mayBeId.hasValue() && mayBeId.getValue() == id; + return mayBeId.hasValue() && mayBeId.getValue() == &id; }); } diff --git a/mlir/lib/Analysis/Dominance.cpp b/mlir/lib/Analysis/Dominance.cpp index ea1501e8998e..060a505593a6 100644 --- a/mlir/lib/Analysis/Dominance.cpp +++ b/mlir/lib/Analysis/Dominance.cpp @@ -129,7 +129,7 @@ bool DominanceInfo::properlyDominates(ValuePtr a, Operation *b) { // block arguments properly dominate all operations in their own block, so // we use a dominates check here, not a properlyDominates check. - return dominates(a.cast()->getOwner(), b->getBlock()); + return dominates(cast(a)->getOwner(), b->getBlock()); } DominanceInfoNode *DominanceInfo::getNode(Block *a) { diff --git a/mlir/lib/Analysis/Liveness.cpp b/mlir/lib/Analysis/Liveness.cpp index 9b7b806c558f..bef0b9fa3856 100644 --- a/mlir/lib/Analysis/Liveness.cpp +++ b/mlir/lib/Analysis/Liveness.cpp @@ -174,7 +174,7 @@ Liveness::OperationListT Liveness::resolveLiveness(ValuePtr value) const { if (Operation *defOp = value->getDefiningOp()) currentBlock = defOp->getBlock(); else - currentBlock = value.cast()->getOwner(); + currentBlock = cast(value)->getOwner(); toProcess.push_back(currentBlock); visited.insert(currentBlock); @@ -272,7 +272,7 @@ void Liveness::print(raw_ostream &os) const { if (Operation *defOp = value->getDefiningOp()) os << "val_" << defOp->getName(); else { - auto blockArg = value.cast(); + auto blockArg = cast(value); os << "arg" << blockArg->getArgNumber() << "@" << blockIds[blockArg->getOwner()]; } diff --git a/mlir/lib/Analysis/SliceAnalysis.cpp b/mlir/lib/Analysis/SliceAnalysis.cpp index 89ee613b370c..befe3d397598 100644 --- a/mlir/lib/Analysis/SliceAnalysis.cpp +++ b/mlir/lib/Analysis/SliceAnalysis.cpp @@ -96,7 +96,7 @@ static void getBackwardSliceImpl(Operation *op, for (auto en : llvm::enumerate(op->getOperands())) { auto operand = en.value(); - if (auto blockArg = operand.dyn_cast()) { + if (auto blockArg = dyn_cast(operand)) { if (auto affIv = getForInductionVarOwner(operand)) { auto *affOp = affIv.getOperation(); if (backwardSlice->count(affOp) == 0) diff --git a/mlir/lib/Dialect/AffineOps/AffineOps.cpp b/mlir/lib/Dialect/AffineOps/AffineOps.cpp index d80f9865ccbe..bfe72101e852 100644 --- a/mlir/lib/Dialect/AffineOps/AffineOps.cpp +++ b/mlir/lib/Dialect/AffineOps/AffineOps.cpp @@ -107,7 +107,7 @@ static bool isFunctionRegion(Region *region) { /// function. A value of index type defined at the top level is always a valid /// symbol. bool mlir::isTopLevelValue(ValuePtr value) { - if (auto arg = value.dyn_cast()) + if (auto arg = dyn_cast(value)) return isFunctionRegion(arg->getOwner()->getParent()); return isFunctionRegion(value->getDefiningOp()->getParentRegion()); } @@ -134,7 +134,7 @@ bool mlir::isValidDim(ValuePtr value) { return false; } // This value has to be a block argument for a FuncOp or an affine.for. - auto *parentOp = value.cast()->getOwner()->getParentOp(); + auto *parentOp = cast(value)->getOwner()->getParentOp(); return isa(parentOp) || isa(parentOp); } @@ -1571,7 +1571,7 @@ bool mlir::isForInductionVar(ValuePtr val) { /// Returns the loop parent of an induction variable. If the provided value is /// not an induction variable, then return nullptr. AffineForOp mlir::getForInductionVarOwner(ValuePtr val) { - auto ivArg = val.dyn_cast(); + auto ivArg = dyn_cast(val); if (!ivArg || !ivArg->getOwner()) return AffineForOp(); auto *containingInst = ivArg->getOwner()->getParent()->getParentOp(); diff --git a/mlir/lib/Dialect/Linalg/Analysis/DependenceAnalysis.cpp b/mlir/lib/Dialect/Linalg/Analysis/DependenceAnalysis.cpp index be90b1ce5a69..5fbbdea60c21 100644 --- a/mlir/lib/Dialect/Linalg/Analysis/DependenceAnalysis.cpp +++ b/mlir/lib/Dialect/Linalg/Analysis/DependenceAnalysis.cpp @@ -41,7 +41,7 @@ static StringRef toStringRef(LinalgDependenceGraph::DependenceType dt) { } ValuePtr Aliases::find(ValuePtr v) { - if (v.isa()) + if (isa(v)) return v; auto it = aliases.find(v); @@ -51,7 +51,7 @@ ValuePtr Aliases::find(ValuePtr v) { } while (true) { - if (v.isa()) + if (isa(v)) return v; if (auto alloc = dyn_cast_or_null(v->getDefiningOp())) { if (isStrided(alloc.getType())) diff --git a/mlir/lib/Dialect/LoopOps/LoopOps.cpp b/mlir/lib/Dialect/LoopOps/LoopOps.cpp index 8e19eba911a9..d3040c1bbb23 100644 --- a/mlir/lib/Dialect/LoopOps/LoopOps.cpp +++ b/mlir/lib/Dialect/LoopOps/LoopOps.cpp @@ -136,7 +136,7 @@ LogicalResult ForOp::moveOutOfLoop(ArrayRef ops) { } ForOp mlir::loop::getForInductionVarOwner(ValuePtr val) { - auto ivArg = val.dyn_cast(); + auto ivArg = dyn_cast(val); if (!ivArg) return ForOp(); assert(ivArg->getOwner() && "unlinked block argument"); diff --git a/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp b/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp index 424c2e0427e2..7ff471dfda5d 100644 --- a/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp +++ b/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp @@ -509,7 +509,7 @@ void Serializer::printValueIDMap(raw_ostream &os) { << "id = " << valueIDPair.second << ' '; if (auto *op = val->getDefiningOp()) { os << "from op '" << op->getName() << "'"; - } else if (auto arg = val.dyn_cast()) { + } else if (auto arg = dyn_cast(val)) { Block *block = arg->getOwner(); os << "from argument of block " << block << ' '; os << " in op '" << block->getParentOp()->getName() << "'"; diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp index 4eeb5e4e95c9..a574f87c530d 100644 --- a/mlir/lib/IR/AsmPrinter.cpp +++ b/mlir/lib/IR/AsmPrinter.cpp @@ -1612,7 +1612,7 @@ void OperationPrinter::numberValuesInRegion(Region ®ion) { void OperationPrinter::numberValuesInBlock(Block &block) { auto setArgNameFn = [&](ValuePtr arg, StringRef name) { assert(!valueIDs.count(arg) && "arg numbered multiple times"); - assert(arg.cast()->getOwner() == &block && + assert(cast(arg)->getOwner() == &block && "arg not defined in 'block'"); setValueName(arg, name); }; @@ -1658,7 +1658,7 @@ void OperationPrinter::numberValuesInOp(Operation &op) { setValueName(result, name); // Record the result number for groups not anchored at 0. - if (int resultNo = result.cast()->getResultNumber()) + if (int resultNo = cast(result)->getResultNumber()) resultGroups.push_back(resultNo); }; @@ -1831,7 +1831,7 @@ void OperationPrinter::printValueIDImpl(ValuePtr value, bool printResultNo, // If this is a reference to the result of a multi-result operation or // operation, print out the # identifier and make sure to map our lookup // to the first result of the operation. - if (OpResultPtr result = value.dyn_cast()) + if (OpResultPtr result = dyn_cast(value)) getResultIDAndNumber(result, lookupValue, resultNo); auto it = valueIDs.find(lookupValue); diff --git a/mlir/lib/IR/Block.cpp b/mlir/lib/IR/Block.cpp index 3abbe1027cee..b168a8facd21 100644 --- a/mlir/lib/IR/Block.cpp +++ b/mlir/lib/IR/Block.cpp @@ -16,10 +16,10 @@ using namespace mlir; //===----------------------------------------------------------------------===// /// Returns the number of this argument. -unsigned BlockArgument::getArgNumber() const { +unsigned BlockArgument::getArgNumber() { // Arguments are not stored in place, so we have to find it within the list. auto argList = getOwner()->getArguments(); - return std::distance(argList.begin(), llvm::find(argList, *this)); + return std::distance(argList.begin(), llvm::find(argList, this)); } //===----------------------------------------------------------------------===// @@ -29,8 +29,7 @@ unsigned BlockArgument::getArgNumber() const { Block::~Block() { assert(!verifyOpOrder() && "Expected valid operation ordering."); clear(); - for (BlockArgument arg : arguments) - arg.destroy(); + llvm::DeleteContainerPointers(arguments); } Region *Block::getParent() const { return parentValidOpOrderPair.getPointer(); } @@ -144,7 +143,7 @@ void Block::recomputeOpOrder() { //===----------------------------------------------------------------------===// BlockArgumentPtr Block::addArgument(Type type) { - BlockArgument arg = BlockArgument::create(type, this); + auto *arg = new BlockArgument(type, this); arguments.push_back(arg); return arg; } @@ -164,7 +163,7 @@ void Block::eraseArgument(unsigned index, bool updatePredTerms) { assert(index < arguments.size()); // Delete the argument. - arguments[index].destroy(); + delete arguments[index]; arguments.erase(arguments.begin() + index); // If we aren't updating predecessors, there is nothing left to do. diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp index 77288b228aa3..1dc7cb4bafd3 100644 --- a/mlir/lib/IR/Operation.cpp +++ b/mlir/lib/IR/Operation.cpp @@ -68,29 +68,23 @@ OperationName OperationName::getFromOpaquePointer(void *pointer) { //===----------------------------------------------------------------------===// /// Return the result number of this result. -unsigned OpResult::getResultNumber() const { - // Results are not stored in place, so we have to find it within the list. - auto resList = getOwner()->getOpResults(); - return std::distance(resList.begin(), llvm::find(resList, *this)); +unsigned OpResult::getResultNumber() { + // Results are always stored consecutively, so use pointer subtraction to + // figure out what number this is. + return this - &getOwner()->getOpResults()[0]; } //===----------------------------------------------------------------------===// // OpOperand //===----------------------------------------------------------------------===// -OpOperand::OpOperand(Operation *owner, Value value) - : IROperand(owner, value.impl) {} - -/// Return the current value being used by this operand. -Value OpOperand::get() { return (detail::ValueImpl *)IROperand::get(); } - -/// Set the current value being used by this operand. -void OpOperand::set(Value newValue) { IROperand::set(newValue.impl); } - +// TODO: This namespace is only required because of a bug in GCC<7.0. +namespace mlir { /// Return which operand this is in the operand list. -unsigned OpOperand::getOperandNumber() { +template <> unsigned OpOperand::getOperandNumber() { return this - &getOwner()->getOpOperands()[0]; } +} // end namespace mlir //===----------------------------------------------------------------------===// // BlockOperand @@ -185,7 +179,7 @@ Operation *Operation::create(Location location, OperationName name, auto instResults = op->getOpResults(); for (unsigned i = 0, e = resultTypes.size(); i != e; ++i) - new (&instResults[i]) OpResult(OpResult::create(resultTypes[i], op)); + new (&instResults[i]) OpResult(resultTypes[i], op); auto opOperands = op->getOpOperands(); @@ -262,7 +256,7 @@ Operation::~Operation() { getOperandStorage().~OperandStorage(); for (auto &result : getOpResults()) - result.destroy(); + result.~OpResult(); // Explicitly run the destructors for the successors. for (auto &successor : getBlockOperands()) diff --git a/mlir/lib/IR/OperationSupport.cpp b/mlir/lib/IR/OperationSupport.cpp index 5dfd3b02cc64..1c68686a0cbc 100644 --- a/mlir/lib/IR/OperationSupport.cpp +++ b/mlir/lib/IR/OperationSupport.cpp @@ -155,7 +155,7 @@ ResultRange::ResultRange(Operation *op) //===----------------------------------------------------------------------===// // ValueRange -ValueRange::ValueRange(ArrayRef values) +ValueRange::ValueRange(ArrayRef values) : ValueRange(values.data(), values.size()) {} ValueRange::ValueRange(OperandRange values) : ValueRange(values.begin().getBase(), values.size()) {} @@ -167,18 +167,19 @@ ValueRange::OwnerT ValueRange::offset_base(const OwnerT &owner, ptrdiff_t index) { if (OpOperand *operand = owner.dyn_cast()) return operand + index; - if (OpResult *result = owner.dyn_cast()) + if (OpResultPtr result = owner.dyn_cast()) return result + index; - return owner.get() + index; + return owner.get() + index; } /// See `detail::indexed_accessor_range_base` for details. -Value ValueRange::dereference_iterator(const OwnerT &owner, ptrdiff_t index) { +ValuePtr ValueRange::dereference_iterator(const OwnerT &owner, + ptrdiff_t index) { // Operands access the held value via 'get'. if (OpOperand *operand = owner.dyn_cast()) return operand[index].get(); // An OpResult is a value, so we can return it directly. - if (OpResult *result = owner.dyn_cast()) - return result[index]; + if (OpResultPtr result = owner.dyn_cast()) + return &result[index]; // Otherwise, this is a raw value array so just index directly. - return owner.get()[index]; + return owner.get()[index]; } diff --git a/mlir/lib/IR/TypeUtilities.cpp b/mlir/lib/IR/TypeUtilities.cpp index 1fa13a85c514..8bc67e46fdcf 100644 --- a/mlir/lib/IR/TypeUtilities.cpp +++ b/mlir/lib/IR/TypeUtilities.cpp @@ -28,6 +28,10 @@ Type mlir::getElementTypeOrSelf(ValuePtr val) { return getElementTypeOrSelf(val->getType()); } +Type mlir::getElementTypeOrSelf(ValueRef val) { + return getElementTypeOrSelf(val.getType()); +} + Type mlir::getElementTypeOrSelf(Attribute attr) { return getElementTypeOrSelf(attr.getType()); } diff --git a/mlir/lib/IR/Value.cpp b/mlir/lib/IR/Value.cpp index ffb9601f1c93..d723eec8b29c 100644 --- a/mlir/lib/IR/Value.cpp +++ b/mlir/lib/IR/Value.cpp @@ -13,8 +13,8 @@ using namespace mlir; /// If this value is the result of an Operation, return the operation that /// defines it. -Operation *Value::getDefiningOp() const { - if (auto result = dyn_cast()) +Operation *Value::getDefiningOp() { + if (auto *result = dyn_cast()) return result->getOwner(); return nullptr; }