operator ValueHandle &() { return value; }
std::string str() const {
- return std::to_string(
- reinterpret_cast<intptr_t>(value.getValue().getAsOpaquePointer()));
+ return std::to_string(reinterpret_cast<intptr_t>(value.getValue()));
}
PythonValueHandle call(const std::vector<PythonValueHandle> &args) {
#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"
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
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
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
class Value;
// TODO(riverriddle) Remove this after Value is value-typed.
-using ValuePtr = Value;
+using ValuePtr = Value *;
// Owning list of rewriting patterns.
class OwningRewritePatternList;
class Value;
// TODO(riverriddle) Remove this after Value is value-typed.
-using ValuePtr = Value;
+using ValuePtr = Value *;
namespace loop {
class ForOp;
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
/// Implicit conversion useful for automatic conversion to Container<Value>.
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.
//===--------------------------------------------------------------------===//
// This is the list of arguments to the block.
- using BlockArgListType = MutableArrayRef<BlockArgumentPtr>;
+ using BlockArgListType = ArrayRef<BlockArgumentPtr>;
BlockArgListType getArguments() { return arguments; }
/// 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
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 <typename T> T lookup(T from) const {
- auto result = lookupOrNull(from);
+ template <typename T> T *lookup(T *from) const {
+ auto *result = lookupOrNull(from);
assert(result && "expected 'from' to be contained within the map");
return result;
}
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 <typename T> T *lookupOrValue(T *from, T *value) const {
auto it = valueMap.find(from);
- return it != valueMap.end() ? reinterpret_cast<Block *>(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<T *>(it->second) : value;
}
- DenseMap<void *, void *> valueMap;
+ DenseMap<IRObjectWithUseList *, IRObjectWithUseList *> valueMap;
};
} // end namespace mlir
// 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 <typename T,
- typename std::enable_if<std::is_convertible<T &, ValueRange>::value &&
- !std::is_convertible<T &, Value &>::value,
- T>::type * = nullptr>
+template <typename T, typename std::enable_if<
+ std::is_convertible<T &, ValueRange>::value &&
+ !std::is_convertible<T &, ValuePtr>::value,
+ T>::type * = nullptr>
inline OpAsmPrinter &operator<<(OpAsmPrinter &p, const T &values) {
p.printOperands(values);
return p;
// 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 <typename T, typename std::enable_if<
- !std::is_convertible<T &, Value &>::value &&
+ !std::is_convertible<T &, ValueRef>::value &&
+ !std::is_convertible<T &, ValuePtr>::value &&
!std::is_convertible<T &, Type &>::value &&
!std::is_convertible<T &, Attribute &>::value &&
!std::is_convertible<T &, ValueRange>::value &&
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;
/// 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 llvm::mapped_iterator<ValueIteratorT, Type (*)(ValuePtr)> {
+ static Type unwrap(ValuePtr value) { return value->getType(); }
public:
using reference = Type;
/// Initializes the type iterator to the specified value iterator.
ValueTypeIterator(ValueIteratorT it)
- : llvm::mapped_iterator<ValueIteratorT, Type (*)(Value)>(it, &unwrap) {}
+ : llvm::mapped_iterator<ValueIteratorT, Type (*)(ValuePtr)>(it, &unwrap) {
+ }
};
//===----------------------------------------------------------------------===//
/// This class implements the operand iterators for the Operation class.
class OperandRange final
: public detail::indexed_accessor_range_base<OperandRange, OpOperand *,
- Value, Value, Value> {
+ ValuePtr, ValuePtr, ValuePtr> {
public:
using RangeBaseT::RangeBaseT;
OperandRange(Operation *op);
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();
}
/// This class implements the result iterators for the Operation class.
class ResultRange final
- : public detail::indexed_accessor_range_base<ResultRange, OpResult *, Value,
- Value, Value> {
+ : public detail::indexed_accessor_range_base<ResultRange, OpResultPtr,
+ ValuePtr, ValuePtr, ValuePtr> {
public:
using RangeBaseT::RangeBaseT;
ResultRange(Operation *op);
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`.
/// parameter.
class ValueRange final
: public detail::indexed_accessor_range_base<
- ValueRange, PointerUnion<const Value *, OpOperand *, OpResult *>,
- Value, Value, Value> {
+ ValueRange, PointerUnion<ValuePtr const *, OpOperand *, OpResultPtr>,
+ ValuePtr, ValuePtr, ValuePtr> {
public:
using RangeBaseT::RangeBaseT;
template <typename Arg,
typename = typename std::enable_if_t<
- std::is_constructible<ArrayRef<Value>, Arg>::value &&
- !std::is_convertible<Arg, Value>::value>>
- ValueRange(Arg &&arg) : ValueRange(ArrayRef<Value>(std::forward<Arg>(arg))) {}
- ValueRange(const Value &value) : ValueRange(&value, /*count=*/1) {}
- ValueRange(const std::initializer_list<Value> &values)
- : ValueRange(ArrayRef<Value>(values)) {}
+ std::is_constructible<ArrayRef<ValuePtr>, Arg>::value &&
+ !std::is_convertible<Arg, ValuePtr>::value>>
+ ValueRange(Arg &&arg)
+ : ValueRange(ArrayRef<ValuePtr>(std::forward<Arg>(arg))) {}
+ ValueRange(ValuePtr const &value) : ValueRange(&value, /*count=*/1) {}
+ ValueRange(const std::initializer_list<ValuePtr> &values)
+ : ValueRange(ArrayRef<ValuePtr>(values)) {}
ValueRange(iterator_range<OperandRange::iterator> values)
: ValueRange(OperandRange(values)) {}
ValueRange(iterator_range<ResultRange::iterator> values)
: ValueRange(ResultRange(values)) {}
- ValueRange(ArrayRef<Value> values = llvm::None);
+ ValueRange(ArrayRef<ValuePtr> values = llvm::None);
ValueRange(OperandRange values);
ValueRange(ResultRange values);
private:
/// The type representing the owner of this range. This is either a list of
/// values, operands, or results.
- using OwnerT = PointerUnion<const Value *, OpOperand *, OpResult *>;
+ using OwnerT = PointerUnion<ValuePtr const *, OpOperand *, OpResultPtr>;
/// 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;
/// 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.
class IROperand;
class Operation;
-class Value;
template <typename OperandType> class ValueUseIterator;
template <typename OperandType> class ValueUserIterator;
}
};
-/// 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.
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,
- };
-
- ValueImpl(Kind kind, Type type) : typeAndKind(type, kind) {}
-
-private:
- /// The type of the value and its kind.
- llvm::PointerIntPair<Type, 1, Kind> 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) {}
+/// Using directives that simplify the transition of Value to being value typed.
+using BlockArgumentPtr = BlockArgument *;
+using OpResultPtr = OpResult *;
+using ValueRef = Value &;
+using ValuePtr = Value *;
- /// The owner of this result.
- Operation *owner;
+/// Operands contain a Value.
+using OpOperand = IROperandImpl<Value>;
- /// 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 <typename U> bool isa() const {
- assert(impl && "isa<> used on a null type.");
- return U::classof(*this);
- }
- template <typename U> U dyn_cast() const {
- return isa<U>() ? U(impl) : U(nullptr);
+ template <typename U> bool isa() const { return U::classof(this); }
+ template <typename U> U *dyn_cast() const {
+ return isa<U>() ? (U *)this : nullptr;
}
- template <typename U> U dyn_cast_or_null() const {
- return (impl && isa<U>()) ? U(impl) : U(nullptr);
- }
- template <typename U> U cast() const {
+ template <typename U> U *cast() const {
assert(isa<U>());
- 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; }
-
- operator bool() const { return impl; }
- bool operator==(const Value &other) const { return impl == other.impl; }
- bool operator!=(const Value &other) const { return !(*this == other); }
+ Kind getKind() const { return typeAndKind.getInt(); }
- /// 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(); }
/// 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.
/// Returns a range of all uses, which is useful for iterating over all uses.
inline use_range getUses();
- using user_iterator = ValueUserIterator<IROperand>;
- using user_range = iterator_range<user_iterator>;
-
- 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<void *>(impl); }
- static Value getFromOpaquePointer(const void *pointer) {
- return reinterpret_cast<detail::ValueImpl *>(const_cast<void *>(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<Type, 1, Kind> 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); }
/// 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 *>(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);
- }
-
- /// Destroy and deallocate this argument.
- void destroy() { delete getImpl(); }
-
- /// Get a raw pointer to the internal implementation.
- detail::BlockArgumentImpl *getImpl() const {
- return reinterpret_cast<detail::BlockArgumentImpl *>(impl);
- }
-
- /// Allow access to `create` and `destroy`.
- friend Block;
+ friend class Block; // For access to private constructor.
+ BlockArgument(Type type, Block *owner)
+ : Value(Value::Kind::BlockArgument, type), owner(owner) {}
+
+ /// 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;
-
- /// 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; }
+ OpResult(Type type, Operation *owner)
+ : Value(Value::Kind::OpResult, type), owner(owner) {}
- static bool classof(Value value) { return value.getKind() == Kind::OpResult; }
+ static bool classof(const Value *value) {
+ return const_cast<Value *>(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<detail::OpResultImpl *>(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<mlir::Value> {
- static mlir::Value getEmptyKey() {
- auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
- return mlir::Value(static_cast<mlir::detail::ValueImpl *>(pointer));
- }
- static mlir::Value getTombstoneKey() {
- auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
- return mlir::Value(static_cast<mlir::detail::ValueImpl *>(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<mlir::Value> {
-public:
- static inline void *getAsVoidPointer(mlir::Value I) {
- return const_cast<void *>(I.getAsOpaquePointer());
- }
- static inline mlir::Value getFromVoidPointer(void *P) {
- return mlir::Value::getFromOpaquePointer(P);
- }
- enum {
- NumLowBitsAvailable =
- PointerLikeTypeTraits<mlir::detail::ValueImpl *>::NumLowBitsAvailable
- };
-};
-
-template <> struct DenseMapInfo<mlir::BlockArgument> {
- static mlir::BlockArgument getEmptyKey() {
- auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
- return mlir::BlockArgument(static_cast<mlir::detail::ValueImpl *>(pointer));
- }
- static mlir::BlockArgument getTombstoneKey() {
- auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
- return mlir::BlockArgument(static_cast<mlir::detail::ValueImpl *>(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<mlir::BlockArgument> {
-public:
- static inline void *getAsVoidPointer(mlir::Value I) {
- return const_cast<void *>(I.getAsOpaquePointer());
- }
- static inline mlir::BlockArgument getFromVoidPointer(void *P) {
- return mlir::Value::getFromOpaquePointer(P).cast<mlir::BlockArgument>();
- }
- enum {
- NumLowBitsAvailable =
- PointerLikeTypeTraits<mlir::detail::ValueImpl *>::NumLowBitsAvailable
- };
-};
-} // end namespace llvm
-
#endif
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;
}
bool FlatAffineConstraints::containsId(ValueRef id) const {
return llvm::any_of(ids, [&](const Optional<ValuePtr> &mayBeId) {
- return mayBeId.hasValue() && mayBeId.getValue() == id;
+ return mayBeId.hasValue() && mayBeId.getValue() == &id;
});
}
// 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<BlockArgument>()->getOwner(), b->getBlock());
+ return dominates(cast<BlockArgument>(a)->getOwner(), b->getBlock());
}
DominanceInfoNode *DominanceInfo::getNode(Block *a) {
if (Operation *defOp = value->getDefiningOp())
currentBlock = defOp->getBlock();
else
- currentBlock = value.cast<BlockArgument>()->getOwner();
+ currentBlock = cast<BlockArgument>(value)->getOwner();
toProcess.push_back(currentBlock);
visited.insert(currentBlock);
if (Operation *defOp = value->getDefiningOp())
os << "val_" << defOp->getName();
else {
- auto blockArg = value.cast<BlockArgument>();
+ auto blockArg = cast<BlockArgument>(value);
os << "arg" << blockArg->getArgNumber() << "@"
<< blockIds[blockArg->getOwner()];
}
for (auto en : llvm::enumerate(op->getOperands())) {
auto operand = en.value();
- if (auto blockArg = operand.dyn_cast<BlockArgument>()) {
+ if (auto blockArg = dyn_cast<BlockArgument>(operand)) {
if (auto affIv = getForInductionVarOwner(operand)) {
auto *affOp = affIv.getOperation();
if (backwardSlice->count(affOp) == 0)
/// 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<BlockArgument>())
+ if (auto arg = dyn_cast<BlockArgument>(value))
return isFunctionRegion(arg->getOwner()->getParent());
return isFunctionRegion(value->getDefiningOp()->getParentRegion());
}
return false;
}
// This value has to be a block argument for a FuncOp or an affine.for.
- auto *parentOp = value.cast<BlockArgument>()->getOwner()->getParentOp();
+ auto *parentOp = cast<BlockArgument>(value)->getOwner()->getParentOp();
return isa<FuncOp>(parentOp) || isa<AffineForOp>(parentOp);
}
/// 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<BlockArgument>();
+ auto ivArg = dyn_cast<BlockArgument>(val);
if (!ivArg || !ivArg->getOwner())
return AffineForOp();
auto *containingInst = ivArg->getOwner()->getParent()->getParentOp();
}
ValuePtr Aliases::find(ValuePtr v) {
- if (v.isa<BlockArgument>())
+ if (isa<BlockArgument>(v))
return v;
auto it = aliases.find(v);
}
while (true) {
- if (v.isa<BlockArgument>())
+ if (isa<BlockArgument>(v))
return v;
if (auto alloc = dyn_cast_or_null<AllocOp>(v->getDefiningOp())) {
if (isStrided(alloc.getType()))
}
ForOp mlir::loop::getForInductionVarOwner(ValuePtr val) {
- auto ivArg = val.dyn_cast<BlockArgument>();
+ auto ivArg = dyn_cast<BlockArgument>(val);
if (!ivArg)
return ForOp();
assert(ivArg->getOwner() && "unlinked block argument");
<< "id = " << valueIDPair.second << ' ';
if (auto *op = val->getDefiningOp()) {
os << "from op '" << op->getName() << "'";
- } else if (auto arg = val.dyn_cast<BlockArgument>()) {
+ } else if (auto arg = dyn_cast<BlockArgument>(val)) {
Block *block = arg->getOwner();
os << "from argument of block " << block << ' ';
os << " in op '" << block->getParentOp()->getName() << "'";
void OperationPrinter::numberValuesInBlock(Block &block) {
auto setArgNameFn = [&](ValuePtr arg, StringRef name) {
assert(!valueIDs.count(arg) && "arg numbered multiple times");
- assert(arg.cast<BlockArgument>()->getOwner() == &block &&
+ assert(cast<BlockArgument>(arg)->getOwner() == &block &&
"arg not defined in 'block'");
setValueName(arg, name);
};
setValueName(result, name);
// Record the result number for groups not anchored at 0.
- if (int resultNo = result.cast<OpResult>()->getResultNumber())
+ if (int resultNo = cast<OpResult>(result)->getResultNumber())
resultGroups.push_back(resultNo);
};
// 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<OpResult>())
+ if (OpResultPtr result = dyn_cast<OpResult>(value))
getResultIDAndNumber(result, lookupValue, resultNo);
auto it = valueIDs.find(lookupValue);
//===----------------------------------------------------------------------===//
/// 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));
}
//===----------------------------------------------------------------------===//
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(); }
//===----------------------------------------------------------------------===//
BlockArgumentPtr Block::addArgument(Type type) {
- BlockArgument arg = BlockArgument::create(type, this);
+ auto *arg = new BlockArgument(type, this);
arguments.push_back(arg);
return arg;
}
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.
//===----------------------------------------------------------------------===//
/// 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
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();
getOperandStorage().~OperandStorage();
for (auto &result : getOpResults())
- result.destroy();
+ result.~OpResult();
// Explicitly run the destructors for the successors.
for (auto &successor : getBlockOperands())
//===----------------------------------------------------------------------===//
// ValueRange
-ValueRange::ValueRange(ArrayRef<Value> values)
+ValueRange::ValueRange(ArrayRef<ValuePtr> values)
: ValueRange(values.data(), values.size()) {}
ValueRange::ValueRange(OperandRange values)
: ValueRange(values.begin().getBase(), values.size()) {}
ptrdiff_t index) {
if (OpOperand *operand = owner.dyn_cast<OpOperand *>())
return operand + index;
- if (OpResult *result = owner.dyn_cast<OpResult *>())
+ if (OpResultPtr result = owner.dyn_cast<OpResultPtr>())
return result + index;
- return owner.get<const Value *>() + index;
+ return owner.get<ValuePtr const *>() + 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<OpOperand *>())
return operand[index].get();
// An OpResult is a value, so we can return it directly.
- if (OpResult *result = owner.dyn_cast<OpResult *>())
- return result[index];
+ if (OpResultPtr result = owner.dyn_cast<OpResultPtr>())
+ return &result[index];
// Otherwise, this is a raw value array so just index directly.
- return owner.get<const Value *>()[index];
+ return owner.get<ValuePtr const *>()[index];
}
return getElementTypeOrSelf(val->getType());
}
+Type mlir::getElementTypeOrSelf(ValueRef val) {
+ return getElementTypeOrSelf(val.getType());
+}
+
Type mlir::getElementTypeOrSelf(Attribute attr) {
return getElementTypeOrSelf(attr.getType());
}
/// If this value is the result of an Operation, return the operation that
/// defines it.
-Operation *Value::getDefiningOp() const {
- if (auto result = dyn_cast<OpResult>())
+Operation *Value::getDefiningOp() {
+ if (auto *result = dyn_cast<OpResult>())
return result->getOwner();
return nullptr;
}