class IntegerSet;
class Location;
class MLIRContext;
-class Type;
class ShapedType;
+class Type;
namespace detail {
-struct OpaqueAttributeStorage;
+struct AffineMapAttributeStorage;
+struct ArrayAttributeStorage;
struct BoolAttributeStorage;
struct DictionaryAttributeStorage;
struct IntegerAttributeStorage;
+struct IntegerSetAttributeStorage;
struct FloatAttributeStorage;
+struct OpaqueAttributeStorage;
struct StringAttributeStorage;
-struct ArrayAttributeStorage;
-struct AffineMapAttributeStorage;
-struct IntegerSetAttributeStorage;
struct TypeAttributeStorage;
+
+/// Elements Attributes.
struct DenseElementsAttributeStorage;
struct OpaqueElementsAttributeStorage;
struct SparseElementsAttributeStorage;
namespace StandardAttributes {
enum Kind {
- Unit = Attribute::FIRST_STANDARD_ATTR,
- Opaque,
+ AffineMap = Attribute::FIRST_STANDARD_ATTR,
+ Array,
Bool,
Dictionary,
- Integer,
Float,
+ Function,
+ Integer,
+ IntegerSet,
+ Opaque,
String,
Type,
- Array,
- AffineMap,
- IntegerSet,
- Function,
+ Unit,
+ /// Elements Attributes.
DenseElements,
OpaqueElements,
SparseElements,
};
} // namespace StandardAttributes
-/// Unit attributes are attributes that hold no specific value and are given
-/// meaning by their existence.
-class UnitAttr : public Attribute::AttrBase<UnitAttr> {
+class AffineMapAttr
+ : public Attribute::AttrBase<AffineMapAttr, Attribute,
+ detail::AffineMapAttributeStorage> {
public:
using Base::Base;
+ using ValueType = AffineMap;
- static UnitAttr get(MLIRContext *context) {
- return Base::get(context, StandardAttributes::Unit);
- }
+ static AffineMapAttr get(AffineMap value);
- static bool kindof(unsigned kind) { return kind == StandardAttributes::Unit; }
+ AffineMap getValue() const;
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast.
+ static bool kindof(unsigned kind) {
+ return kind == StandardAttributes::AffineMap;
+ }
};
-/// Opaque attributes represent attributes of non-registered dialects. These are
-/// attribute represented in their raw string form, and can only usefully be
-/// tested for attribute equality.
-class OpaqueAttr : public Attribute::AttrBase<OpaqueAttr, Attribute,
- detail::OpaqueAttributeStorage> {
+/// Array attributes are lists of other attributes. They are not necessarily
+/// type homogenous given that attributes don't, in general, carry types.
+class ArrayAttr : public Attribute::AttrBase<ArrayAttr, Attribute,
+ detail::ArrayAttributeStorage> {
public:
using Base::Base;
+ using ValueType = ArrayRef<Attribute>;
- /// Get or create a new OpaqueAttr with the provided dialect and string data.
- static OpaqueAttr get(Identifier dialect, StringRef attrData,
- MLIRContext *context);
-
- /// Get or create a new OpaqueAttr with the provided dialect and string data.
- /// If the given identifier is not a valid namespace for a dialect, then a
- /// null attribute is returned.
- static OpaqueAttr getChecked(Identifier dialect, StringRef attrData,
- MLIRContext *context, Location location);
-
- /// Returns the dialect namespace of the opaque attribute.
- Identifier getDialectNamespace() const;
+ static ArrayAttr get(ArrayRef<Attribute> value, MLIRContext *context);
- /// Returns the raw attribute data of the opaque attribute.
- StringRef getAttrData() const;
+ ArrayRef<Attribute> getValue() const;
- /// Verify the construction of an opaque attribute.
- static LogicalResult
- verifyConstructionInvariants(llvm::Optional<Location> loc,
- MLIRContext *context, Identifier dialect,
- StringRef attrData);
+ /// Support range iteration.
+ using iterator = llvm::ArrayRef<Attribute>::iterator;
+ iterator begin() const { return getValue().begin(); }
+ iterator end() const { return getValue().end(); }
+ size_t size() const { return getValue().size(); }
+ /// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool kindof(unsigned kind) {
- return kind == StandardAttributes::Opaque;
+ return kind == StandardAttributes::Array;
}
};
static bool kindof(unsigned kind) { return kind == StandardAttributes::Bool; }
};
-class IntegerAttr
- : public Attribute::AttrBase<IntegerAttr, Attribute,
- detail::IntegerAttributeStorage> {
+/// NamedAttribute is used for dictionary attributes, it holds an identifier for
+/// the name and a value for the attribute. The attribute pointer should always
+/// be non-null.
+using NamedAttribute = std::pair<Identifier, Attribute>;
+
+/// Dictionary attribute is an attribute that represents a sorted collection of
+/// named attribute values. The elements are sorted by name, and each name must
+/// be unique within the collection.
+class DictionaryAttr
+ : public Attribute::AttrBase<DictionaryAttr, Attribute,
+ detail::DictionaryAttributeStorage> {
public:
using Base::Base;
- using ValueType = APInt;
+ using ValueType = ArrayRef<NamedAttribute>;
- static IntegerAttr get(Type type, int64_t value);
- static IntegerAttr get(Type type, const APInt &value);
+ static DictionaryAttr get(ArrayRef<NamedAttribute> value,
+ MLIRContext *context);
- APInt getValue() const;
- // TODO(jpienaar): Change callers to use getValue instead.
- int64_t getInt() const;
+ ArrayRef<NamedAttribute> getValue() const;
- /// Methods for support type inquiry through isa, cast, and dyn_cast.
+ /// Return the specified attribute if present, null otherwise.
+ Attribute get(StringRef name) const;
+ Attribute get(Identifier name) const;
+
+ /// Support range iteration.
+ using iterator = llvm::ArrayRef<NamedAttribute>::iterator;
+ iterator begin() const;
+ iterator end() const;
+ bool empty() const { return size() == 0; }
+ size_t size() const;
+
+ /// Methods for supporting type inquiry through isa, cast, and dyn_cast.
static bool kindof(unsigned kind) {
- return kind == StandardAttributes::Integer;
+ return kind == StandardAttributes::Dictionary;
}
};
Type type, const APFloat &value);
};
-class StringAttr : public Attribute::AttrBase<StringAttr, Attribute,
- detail::StringAttributeStorage> {
+/// A function attribute represents a reference to a function object.
+class FunctionAttr
+ : public Attribute::AttrBase<FunctionAttr, Attribute,
+ detail::StringAttributeStorage> {
public:
using Base::Base;
- using ValueType = StringRef;
+ using ValueType = Function *;
- static StringAttr get(StringRef bytes, MLIRContext *context);
+ static FunctionAttr get(Function *value);
+ static FunctionAttr get(StringRef value, MLIRContext *ctx);
+ /// Returns the name of the held function reference.
StringRef getValue() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool kindof(unsigned kind) {
- return kind == StandardAttributes::String;
+ return kind == StandardAttributes::Function;
}
};
-/// Array attributes are lists of other attributes. They are not necessarily
-/// type homogenous given that attributes don't, in general, carry types.
-class ArrayAttr : public Attribute::AttrBase<ArrayAttr, Attribute,
- detail::ArrayAttributeStorage> {
+class IntegerAttr
+ : public Attribute::AttrBase<IntegerAttr, Attribute,
+ detail::IntegerAttributeStorage> {
public:
using Base::Base;
- using ValueType = ArrayRef<Attribute>;
-
- static ArrayAttr get(ArrayRef<Attribute> value, MLIRContext *context);
+ using ValueType = APInt;
- ArrayRef<Attribute> getValue() const;
+ static IntegerAttr get(Type type, int64_t value);
+ static IntegerAttr get(Type type, const APInt &value);
- /// Support range iteration.
- using iterator = llvm::ArrayRef<Attribute>::iterator;
- iterator begin() const { return getValue().begin(); }
- iterator end() const { return getValue().end(); }
- size_t size() const { return getValue().size(); }
+ APInt getValue() const;
+ // TODO(jpienaar): Change callers to use getValue instead.
+ int64_t getInt() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool kindof(unsigned kind) {
- return kind == StandardAttributes::Array;
+ return kind == StandardAttributes::Integer;
}
};
-/// NamedAttribute is used for dictionary attributes, it holds an identifier for
-/// the name and a value for the attribute. The attribute pointer should always
-/// be non-null.
-using NamedAttribute = std::pair<Identifier, Attribute>;
-
-/// Dictionary attribute is an attribute that represents a sorted collection of
-/// named attribute values. The elements are sorted by name, and each name must
-/// be unique within the collection.
-class DictionaryAttr
- : public Attribute::AttrBase<DictionaryAttr, Attribute,
- detail::DictionaryAttributeStorage> {
+class IntegerSetAttr
+ : public Attribute::AttrBase<IntegerSetAttr, Attribute,
+ detail::IntegerSetAttributeStorage> {
public:
using Base::Base;
- using ValueType = ArrayRef<NamedAttribute>;
-
- static DictionaryAttr get(ArrayRef<NamedAttribute> value,
- MLIRContext *context);
-
- ArrayRef<NamedAttribute> getValue() const;
+ using ValueType = IntegerSet;
- /// Return the specified attribute if present, null otherwise.
- Attribute get(StringRef name) const;
- Attribute get(Identifier name) const;
+ static IntegerSetAttr get(IntegerSet value);
- /// Support range iteration.
- using iterator = llvm::ArrayRef<NamedAttribute>::iterator;
- iterator begin() const;
- iterator end() const;
- bool empty() const { return size() == 0; }
- size_t size() const;
+ IntegerSet getValue() const;
- /// Methods for supporting type inquiry through isa, cast, and dyn_cast.
+ /// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool kindof(unsigned kind) {
- return kind == StandardAttributes::Dictionary;
+ return kind == StandardAttributes::IntegerSet;
}
};
-class AffineMapAttr
- : public Attribute::AttrBase<AffineMapAttr, Attribute,
- detail::AffineMapAttributeStorage> {
+/// Opaque attributes represent attributes of non-registered dialects. These are
+/// attribute represented in their raw string form, and can only usefully be
+/// tested for attribute equality.
+class OpaqueAttr : public Attribute::AttrBase<OpaqueAttr, Attribute,
+ detail::OpaqueAttributeStorage> {
public:
using Base::Base;
- using ValueType = AffineMap;
- static AffineMapAttr get(AffineMap value);
+ /// Get or create a new OpaqueAttr with the provided dialect and string data.
+ static OpaqueAttr get(Identifier dialect, StringRef attrData,
+ MLIRContext *context);
- AffineMap getValue() const;
+ /// Get or create a new OpaqueAttr with the provided dialect and string data.
+ /// If the given identifier is not a valid namespace for a dialect, then a
+ /// null attribute is returned.
+ static OpaqueAttr getChecked(Identifier dialect, StringRef attrData,
+ MLIRContext *context, Location location);
+
+ /// Returns the dialect namespace of the opaque attribute.
+ Identifier getDialectNamespace() const;
+
+ /// Returns the raw attribute data of the opaque attribute.
+ StringRef getAttrData() const;
+
+ /// Verify the construction of an opaque attribute.
+ static LogicalResult
+ verifyConstructionInvariants(llvm::Optional<Location> loc,
+ MLIRContext *context, Identifier dialect,
+ StringRef attrData);
- /// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool kindof(unsigned kind) {
- return kind == StandardAttributes::AffineMap;
+ return kind == StandardAttributes::Opaque;
}
};
-class IntegerSetAttr
- : public Attribute::AttrBase<IntegerSetAttr, Attribute,
- detail::IntegerSetAttributeStorage> {
+class StringAttr : public Attribute::AttrBase<StringAttr, Attribute,
+ detail::StringAttributeStorage> {
public:
using Base::Base;
- using ValueType = IntegerSet;
+ using ValueType = StringRef;
- static IntegerSetAttr get(IntegerSet value);
+ static StringAttr get(StringRef bytes, MLIRContext *context);
- IntegerSet getValue() const;
+ StringRef getValue() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool kindof(unsigned kind) {
- return kind == StandardAttributes::IntegerSet;
+ return kind == StandardAttributes::String;
}
};
static bool kindof(unsigned kind) { return kind == StandardAttributes::Type; }
};
-/// A function attribute represents a reference to a function object.
-class FunctionAttr
- : public Attribute::AttrBase<FunctionAttr, Attribute,
- detail::StringAttributeStorage> {
+/// Unit attributes are attributes that hold no specific value and are given
+/// meaning by their existence.
+class UnitAttr : public Attribute::AttrBase<UnitAttr> {
public:
using Base::Base;
- using ValueType = Function *;
-
- static FunctionAttr get(Function *value);
- static FunctionAttr get(StringRef value, MLIRContext *ctx);
- /// Returns the name of the held function reference.
- StringRef getValue() const;
-
- /// Methods for support type inquiry through isa, cast, and dyn_cast.
- static bool kindof(unsigned kind) {
- return kind == StandardAttributes::Function;
+ static UnitAttr get(MLIRContext *context) {
+ return Base::get(context, StandardAttributes::Unit);
}
+
+ static bool kindof(unsigned kind) { return kind == StandardAttributes::Unit; }
};
+//===----------------------------------------------------------------------===//
+// Elements Attributes
+//===----------------------------------------------------------------------===//
+
/// A base attribute that represents a reference to a static shaped tensor or
/// vector constant.
class ElementsAttr : public Attribute {
bool isValidIntOrFloat(int64_t dataEltSize, bool isInt) const;
};
-/// An attribute that represents a reference to a dense integer vector or tensor
-/// object.
-class DenseIntElementsAttr : public DenseElementsAttr {
-public:
- /// DenseIntElementsAttr iterates on APInt, so we can use the raw element
- /// iterator directly.
- using iterator = DenseElementsAttr::IntElementIterator;
-
- using DenseElementsAttr::DenseElementsAttr;
-
- /// Generates a new DenseElementsAttr by mapping each value attribute, and
- /// constructing the DenseElementsAttr given the new element type.
- DenseElementsAttr
- mapValues(Type newElementType,
- llvm::function_ref<APInt(const APInt &)> mapping) const;
-
- /// Iterator access to the integer element values.
- iterator begin() const { return raw_int_begin(); }
- iterator end() const { return raw_int_end(); }
-
- /// Method for supporting type inquiry through isa, cast and dyn_cast.
- static bool classof(Attribute attr);
-};
-
/// An attribute that represents a reference to a dense float vector or tensor
/// object. Each element is stored as a double.
class DenseFPElementsAttr : public DenseElementsAttr {
static bool classof(Attribute attr);
};
-/// An attribute that represents a reference to a splat vector or tensor
-/// constant, meaning all of the elements have the same value.
-class SplatElementsAttr : public DenseElementsAttr {
+/// An attribute that represents a reference to a dense integer vector or tensor
+/// object.
+class DenseIntElementsAttr : public DenseElementsAttr {
public:
- using DenseElementsAttr::DenseElementsAttr;
- using ValueType = Attribute;
+ /// DenseIntElementsAttr iterates on APInt, so we can use the raw element
+ /// iterator directly.
+ using iterator = DenseElementsAttr::IntElementIterator;
- /// 'type' must be a vector or tensor with static shape.
- static SplatElementsAttr get(ShapedType type, Attribute elt);
- Attribute getValue() const { return getSplatValue(); }
+ using DenseElementsAttr::DenseElementsAttr;
- /// Generates a new SplatElementsAttr by mapping each int value to a new
- /// underlying APInt. The new values can represent either a integer or float.
- /// This ElementsAttr should contain integers.
- SplatElementsAttr
+ /// Generates a new DenseElementsAttr by mapping each value attribute, and
+ /// constructing the DenseElementsAttr given the new element type.
+ DenseElementsAttr
mapValues(Type newElementType,
llvm::function_ref<APInt(const APInt &)> mapping) const;
- /// Generates a new SplatElementsAttr by mapping each float value to a new
- /// underlying APInt. The new values can represent either a integer or float.
- /// This ElementsAttr should contain floats.
- SplatElementsAttr
- mapValues(Type newElementType,
- llvm::function_ref<APInt(const APFloat &)> mapping) const;
+ /// Iterator access to the integer element values.
+ iterator begin() const { return raw_int_begin(); }
+ iterator end() const { return raw_int_end(); }
- /// Method for support type inquiry through isa, cast and dyn_cast.
- static bool classof(Attribute attr) {
- auto denseAttr = attr.dyn_cast<DenseElementsAttr>();
- return denseAttr && denseAttr.isSplat();
- }
+ /// Method for supporting type inquiry through isa, cast and dyn_cast.
+ static bool classof(Attribute attr);
};
/// An opaque attribute that represents a reference to a vector or tensor
}
};
+/// An attribute that represents a reference to a splat vector or tensor
+/// constant, meaning all of the elements have the same value.
+class SplatElementsAttr : public DenseElementsAttr {
+public:
+ using DenseElementsAttr::DenseElementsAttr;
+ using ValueType = Attribute;
+
+ /// 'type' must be a vector or tensor with static shape.
+ static SplatElementsAttr get(ShapedType type, Attribute elt);
+ Attribute getValue() const { return getSplatValue(); }
+
+ /// Generates a new SplatElementsAttr by mapping each int value to a new
+ /// underlying APInt. The new values can represent either a integer or float.
+ /// This ElementsAttr should contain integers.
+ SplatElementsAttr
+ mapValues(Type newElementType,
+ llvm::function_ref<APInt(const APInt &)> mapping) const;
+
+ /// Generates a new SplatElementsAttr by mapping each float value to a new
+ /// underlying APInt. The new values can represent either a integer or float.
+ /// This ElementsAttr should contain floats.
+ SplatElementsAttr
+ mapValues(Type newElementType,
+ llvm::function_ref<APInt(const APFloat &)> mapping) const;
+
+ /// Method for support type inquiry through isa, cast and dyn_cast.
+ static bool classof(Attribute attr) {
+ auto denseAttr = attr.dyn_cast<DenseElementsAttr>();
+ return denseAttr && denseAttr.isSplat();
+ }
+};
+
template <typename U> bool Attribute::isa() const {
assert(impl && "isa<> used on a null attribute.");
return U::classof(*this);
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Attributes.h"
-#include "mlir/IR/Function.h"
#include "mlir/IR/Identifier.h"
#include "mlir/IR/IntegerSet.h"
#include "mlir/IR/MLIRContext.h"
namespace mlir {
namespace detail {
-/// Opaque Attribute Storage and Uniquing.
-struct OpaqueAttributeStorage : public AttributeStorage {
- OpaqueAttributeStorage(Identifier dialectNamespace, StringRef attrData)
- : dialectNamespace(dialectNamespace), attrData(attrData) {}
+// An attribute representing a reference to an affine map.
+struct AffineMapAttributeStorage : public AttributeStorage {
+ using KeyTy = AffineMap;
- /// The hash key used for uniquing.
- using KeyTy = std::pair<Identifier, StringRef>;
- bool operator==(const KeyTy &key) const {
- return key == KeyTy(dialectNamespace, attrData);
- }
+ AffineMapAttributeStorage(AffineMap value)
+ : AttributeStorage(IndexType::get(value.getContext())), value(value) {}
- static OpaqueAttributeStorage *construct(AttributeStorageAllocator &allocator,
- const KeyTy &key) {
- return new (allocator.allocate<OpaqueAttributeStorage>())
- OpaqueAttributeStorage(key.first, allocator.copyInto(key.second));
+ /// Key equality function.
+ bool operator==(const KeyTy &key) const { return key == value; }
+
+ /// Construct a new storage instance.
+ static AffineMapAttributeStorage *
+ construct(AttributeStorageAllocator &allocator, KeyTy key) {
+ return new (allocator.allocate<AffineMapAttributeStorage>())
+ AffineMapAttributeStorage(key);
}
- // The dialect namespace.
- Identifier dialectNamespace;
+ AffineMap value;
+};
- // The parser attribute data for this opaque attribute.
- StringRef attrData;
+/// An attribute representing an array of other attributes.
+struct ArrayAttributeStorage : public AttributeStorage {
+ using KeyTy = ArrayRef<Attribute>;
+
+ ArrayAttributeStorage(ArrayRef<Attribute> value) : value(value) {}
+
+ /// Key equality function.
+ bool operator==(const KeyTy &key) const { return key == value; }
+
+ /// Construct a new storage instance.
+ static ArrayAttributeStorage *construct(AttributeStorageAllocator &allocator,
+ const KeyTy &key) {
+ return new (allocator.allocate<ArrayAttributeStorage>())
+ ArrayAttributeStorage(allocator.copyInto(key));
+ }
+
+ ArrayRef<Attribute> value;
};
/// An attribute representing a boolean value.
bool value;
};
-/// An attribute representing a integral value.
-struct IntegerAttributeStorage final
+/// An attribute representing a dictionary of sorted named attributes.
+struct DictionaryAttributeStorage final
: public AttributeStorage,
- public llvm::TrailingObjects<IntegerAttributeStorage, uint64_t> {
- using KeyTy = std::pair<Type, APInt>;
+ private llvm::TrailingObjects<DictionaryAttributeStorage,
+ NamedAttribute> {
+ using KeyTy = ArrayRef<NamedAttribute>;
- IntegerAttributeStorage(Type type, size_t numObjects)
- : AttributeStorage(type), numObjects(numObjects) {
- assert((type.isIndex() || type.isa<IntegerType>()) && "invalid type");
- }
+ /// Given a list of NamedAttribute's, canonicalize the list (sorting
+ /// by name) and return the unique'd result.
+ static DictionaryAttributeStorage *get(ArrayRef<NamedAttribute> attrs);
- /// Key equality and hash functions.
- bool operator==(const KeyTy &key) const {
- return key == KeyTy(getType(), getValue());
- }
- static unsigned hashKey(const KeyTy &key) {
- return llvm::hash_combine(key.first, llvm::hash_value(key.second));
- }
+ /// Key equality function.
+ bool operator==(const KeyTy &key) const { return key == getElements(); }
/// Construct a new storage instance.
- static IntegerAttributeStorage *
+ static DictionaryAttributeStorage *
construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
- Type type;
- APInt value;
- std::tie(type, value) = key;
+ auto size = DictionaryAttributeStorage::totalSizeToAlloc<NamedAttribute>(
+ key.size());
+ auto rawMem = allocator.allocate(size, alignof(NamedAttribute));
- auto elements = ArrayRef<uint64_t>(value.getRawData(), value.getNumWords());
- auto size =
- IntegerAttributeStorage::totalSizeToAlloc<uint64_t>(elements.size());
- auto rawMem = allocator.allocate(size, alignof(IntegerAttributeStorage));
- auto result = ::new (rawMem) IntegerAttributeStorage(type, elements.size());
- std::uninitialized_copy(elements.begin(), elements.end(),
- result->getTrailingObjects<uint64_t>());
+ // Initialize the storage and trailing attribute list.
+ auto result = ::new (rawMem) DictionaryAttributeStorage(key.size());
+ std::uninitialized_copy(key.begin(), key.end(),
+ result->getTrailingObjects<NamedAttribute>());
return result;
}
- /// Returns an APInt representing the stored value.
- APInt getValue() const {
- if (getType().isIndex())
- return APInt(64, {getTrailingObjects<uint64_t>(), numObjects});
- return APInt(getType().getIntOrFloatBitWidth(),
- {getTrailingObjects<uint64_t>(), numObjects});
+ /// Return the elements of this dictionary attribute.
+ ArrayRef<NamedAttribute> getElements() const {
+ return {getTrailingObjects<NamedAttribute>(), numElements};
}
- size_t numObjects;
+private:
+ friend class llvm::TrailingObjects<DictionaryAttributeStorage,
+ NamedAttribute>;
+
+ // This is used by the llvm::TrailingObjects base class.
+ size_t numTrailingObjects(OverloadToken<NamedAttribute>) const {
+ return numElements;
+ }
+ DictionaryAttributeStorage(unsigned numElements) : numElements(numElements) {}
+
+ /// This is the number of attributes.
+ const unsigned numElements;
};
/// An attribute representing a floating point value.
size_t numObjects;
};
-/// An attribute representing a string value.
-struct StringAttributeStorage : public AttributeStorage {
- using KeyTy = StringRef;
-
- StringAttributeStorage(StringRef value) : value(value) {}
-
- /// Key equality function.
- bool operator==(const KeyTy &key) const { return key == value; }
+/// An attribute representing a integral value.
+struct IntegerAttributeStorage final
+ : public AttributeStorage,
+ public llvm::TrailingObjects<IntegerAttributeStorage, uint64_t> {
+ using KeyTy = std::pair<Type, APInt>;
- /// Construct a new storage instance.
- static StringAttributeStorage *construct(AttributeStorageAllocator &allocator,
- const KeyTy &key) {
- return new (allocator.allocate<StringAttributeStorage>())
- StringAttributeStorage(allocator.copyInto(key));
+ IntegerAttributeStorage(Type type, size_t numObjects)
+ : AttributeStorage(type), numObjects(numObjects) {
+ assert((type.isIndex() || type.isa<IntegerType>()) && "invalid type");
}
- StringRef value;
-};
-
-/// An attribute representing an array of other attributes.
-struct ArrayAttributeStorage : public AttributeStorage {
- using KeyTy = ArrayRef<Attribute>;
-
- ArrayAttributeStorage(ArrayRef<Attribute> value) : value(value) {}
-
- /// Key equality function.
- bool operator==(const KeyTy &key) const { return key == value; }
-
- /// Construct a new storage instance.
- static ArrayAttributeStorage *construct(AttributeStorageAllocator &allocator,
- const KeyTy &key) {
- return new (allocator.allocate<ArrayAttributeStorage>())
- ArrayAttributeStorage(allocator.copyInto(key));
+ /// Key equality and hash functions.
+ bool operator==(const KeyTy &key) const {
+ return key == KeyTy(getType(), getValue());
+ }
+ static unsigned hashKey(const KeyTy &key) {
+ return llvm::hash_combine(key.first, llvm::hash_value(key.second));
}
-
- ArrayRef<Attribute> value;
-};
-
-/// An attribute representing a dictionary of sorted named attributes.
-struct DictionaryAttributeStorage final
- : public AttributeStorage,
- private llvm::TrailingObjects<DictionaryAttributeStorage,
- NamedAttribute> {
- using KeyTy = ArrayRef<NamedAttribute>;
-
- /// Given a list of NamedAttribute's, canonicalize the list (sorting
- /// by name) and return the unique'd result.
- static DictionaryAttributeStorage *get(ArrayRef<NamedAttribute> attrs);
-
- /// Key equality function.
- bool operator==(const KeyTy &key) const { return key == getElements(); }
/// Construct a new storage instance.
- static DictionaryAttributeStorage *
+ static IntegerAttributeStorage *
construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
- auto size = DictionaryAttributeStorage::totalSizeToAlloc<NamedAttribute>(
- key.size());
- auto rawMem = allocator.allocate(size, alignof(NamedAttribute));
+ Type type;
+ APInt value;
+ std::tie(type, value) = key;
- // Initialize the storage and trailing attribute list.
- auto result = ::new (rawMem) DictionaryAttributeStorage(key.size());
- std::uninitialized_copy(key.begin(), key.end(),
- result->getTrailingObjects<NamedAttribute>());
+ auto elements = ArrayRef<uint64_t>(value.getRawData(), value.getNumWords());
+ auto size =
+ IntegerAttributeStorage::totalSizeToAlloc<uint64_t>(elements.size());
+ auto rawMem = allocator.allocate(size, alignof(IntegerAttributeStorage));
+ auto result = ::new (rawMem) IntegerAttributeStorage(type, elements.size());
+ std::uninitialized_copy(elements.begin(), elements.end(),
+ result->getTrailingObjects<uint64_t>());
return result;
}
- /// Return the elements of this dictionary attribute.
- ArrayRef<NamedAttribute> getElements() const {
- return {getTrailingObjects<NamedAttribute>(), numElements};
- }
-
-private:
- friend class llvm::TrailingObjects<DictionaryAttributeStorage,
- NamedAttribute>;
-
- // This is used by the llvm::TrailingObjects base class.
- size_t numTrailingObjects(OverloadToken<NamedAttribute>) const {
- return numElements;
+ /// Returns an APInt representing the stored value.
+ APInt getValue() const {
+ if (getType().isIndex())
+ return APInt(64, {getTrailingObjects<uint64_t>(), numObjects});
+ return APInt(getType().getIntOrFloatBitWidth(),
+ {getTrailingObjects<uint64_t>(), numObjects});
}
- DictionaryAttributeStorage(unsigned numElements) : numElements(numElements) {}
- /// This is the number of attributes.
- const unsigned numElements;
+ size_t numObjects;
};
-// An attribute representing a reference to an affine map.
-struct AffineMapAttributeStorage : public AttributeStorage {
- using KeyTy = AffineMap;
+// An attribute representing a reference to an integer set.
+struct IntegerSetAttributeStorage : public AttributeStorage {
+ using KeyTy = IntegerSet;
- AffineMapAttributeStorage(AffineMap value)
- : AttributeStorage(IndexType::get(value.getContext())), value(value) {}
+ IntegerSetAttributeStorage(IntegerSet value) : value(value) {}
/// Key equality function.
bool operator==(const KeyTy &key) const { return key == value; }
/// Construct a new storage instance.
- static AffineMapAttributeStorage *
+ static IntegerSetAttributeStorage *
construct(AttributeStorageAllocator &allocator, KeyTy key) {
- return new (allocator.allocate<AffineMapAttributeStorage>())
- AffineMapAttributeStorage(key);
+ return new (allocator.allocate<IntegerSetAttributeStorage>())
+ IntegerSetAttributeStorage(key);
}
- AffineMap value;
+ IntegerSet value;
};
-// An attribute representing a reference to an integer set.
-struct IntegerSetAttributeStorage : public AttributeStorage {
- using KeyTy = IntegerSet;
+/// Opaque Attribute Storage and Uniquing.
+struct OpaqueAttributeStorage : public AttributeStorage {
+ OpaqueAttributeStorage(Identifier dialectNamespace, StringRef attrData)
+ : dialectNamespace(dialectNamespace), attrData(attrData) {}
- IntegerSetAttributeStorage(IntegerSet value) : value(value) {}
+ /// The hash key used for uniquing.
+ using KeyTy = std::pair<Identifier, StringRef>;
+ bool operator==(const KeyTy &key) const {
+ return key == KeyTy(dialectNamespace, attrData);
+ }
+
+ static OpaqueAttributeStorage *construct(AttributeStorageAllocator &allocator,
+ const KeyTy &key) {
+ return new (allocator.allocate<OpaqueAttributeStorage>())
+ OpaqueAttributeStorage(key.first, allocator.copyInto(key.second));
+ }
+
+ // The dialect namespace.
+ Identifier dialectNamespace;
+
+ // The parser attribute data for this opaque attribute.
+ StringRef attrData;
+};
+
+/// An attribute representing a string value.
+struct StringAttributeStorage : public AttributeStorage {
+ using KeyTy = StringRef;
+
+ StringAttributeStorage(StringRef value) : value(value) {}
/// Key equality function.
bool operator==(const KeyTy &key) const { return key == value; }
/// Construct a new storage instance.
- static IntegerSetAttributeStorage *
- construct(AttributeStorageAllocator &allocator, KeyTy key) {
- return new (allocator.allocate<IntegerSetAttributeStorage>())
- IntegerSetAttributeStorage(key);
+ static StringAttributeStorage *construct(AttributeStorageAllocator &allocator,
+ const KeyTy &key) {
+ return new (allocator.allocate<StringAttributeStorage>())
+ StringAttributeStorage(allocator.copyInto(key));
}
- IntegerSet value;
+ StringRef value;
};
/// An attribute representing a reference to a type.
Type value;
};
-/// An attribute representing a reference to a vector or tensor constant,
-/// inwhich all elements have the same value.
-struct SplatElementsAttributeStorage : public AttributeStorage {
- using KeyTy = std::pair<Type, Attribute>;
-
- SplatElementsAttributeStorage(Type type, Attribute elt)
- : AttributeStorage(type), elt(elt) {}
-
- /// Key equality and hash functions.
- bool operator==(const KeyTy &key) const {
- return key == std::make_pair(getType(), elt);
- }
-
- /// Construct a new storage instance.
- static SplatElementsAttributeStorage *
- construct(AttributeStorageAllocator &allocator, KeyTy key) {
- return new (allocator.allocate<SplatElementsAttributeStorage>())
- SplatElementsAttributeStorage(key.first, key.second);
- }
-
- Attribute elt;
-};
+//===----------------------------------------------------------------------===//
+// Elements Attributes
+//===----------------------------------------------------------------------===//
/// An attribute representing a reference to a dense vector or tensor object.
struct DenseElementsAttributeStorage : public AttributeStorage {
Dialect &Attribute::getDialect() const { return impl->getDialect(); }
//===----------------------------------------------------------------------===//
-// OpaqueAttr
+// AffineMapAttr
//===----------------------------------------------------------------------===//
-OpaqueAttr OpaqueAttr::get(Identifier dialect, StringRef attrData,
- MLIRContext *context) {
- return Base::get(context, StandardAttributes::Opaque, dialect, attrData);
-}
-
-OpaqueAttr OpaqueAttr::getChecked(Identifier dialect, StringRef attrData,
- MLIRContext *context, Location location) {
- return Base::getChecked(location, context, StandardAttributes::Opaque,
- dialect, attrData);
+AffineMapAttr AffineMapAttr::get(AffineMap value) {
+ return Base::get(value.getResult(0).getContext(),
+ StandardAttributes::AffineMap, value);
}
-/// Returns the dialect namespace of the opaque attribute.
-Identifier OpaqueAttr::getDialectNamespace() const {
- return getImpl()->dialectNamespace;
-}
+AffineMap AffineMapAttr::getValue() const { return getImpl()->value; }
-/// Returns the raw attribute data of the opaque attribute.
-StringRef OpaqueAttr::getAttrData() const { return getImpl()->attrData; }
+//===----------------------------------------------------------------------===//
+// ArrayAttr
+//===----------------------------------------------------------------------===//
-/// Verify the construction of an opaque attribute.
-LogicalResult OpaqueAttr::verifyConstructionInvariants(
- llvm::Optional<Location> loc, MLIRContext *context, Identifier dialect,
- StringRef attrData) {
- if (!Dialect::isValidNamespace(dialect.strref())) {
- if (loc)
- context->emitError(*loc)
- << "invalid dialect namespace '" << dialect << "'";
- return failure();
- }
- return success();
+ArrayAttr ArrayAttr::get(ArrayRef<Attribute> value, MLIRContext *context) {
+ return Base::get(context, StandardAttributes::Array, value);
}
+ArrayRef<Attribute> ArrayAttr::getValue() const { return getImpl()->value; }
+
//===----------------------------------------------------------------------===//
// BoolAttr
//===----------------------------------------------------------------------===//
}
size_t DictionaryAttr::size() const { return getValue().size(); }
-//===----------------------------------------------------------------------===//
-// IntegerAttr
-//===----------------------------------------------------------------------===//
-
-IntegerAttr IntegerAttr::get(Type type, const APInt &value) {
- return Base::get(type.getContext(), StandardAttributes::Integer, type, value);
-}
-
-IntegerAttr IntegerAttr::get(Type type, int64_t value) {
- // This uses 64 bit APInts by default for index type.
- if (type.isIndex())
- return get(type, APInt(64, value));
-
- auto intType = type.cast<IntegerType>();
- return get(type, APInt(intType.getWidth(), value));
-}
-
-APInt IntegerAttr::getValue() const { return getImpl()->getValue(); }
-
-int64_t IntegerAttr::getInt() const { return getValue().getSExtValue(); }
-
//===----------------------------------------------------------------------===//
// FloatAttr
//===----------------------------------------------------------------------===//
}
//===----------------------------------------------------------------------===//
-// StringAttr
+// FunctionAttr
//===----------------------------------------------------------------------===//
-StringAttr StringAttr::get(StringRef bytes, MLIRContext *context) {
- return Base::get(context, StandardAttributes::String, bytes);
+FunctionAttr FunctionAttr::get(Function *value) {
+ assert(value && "Cannot get FunctionAttr for a null function");
+ return get(value->getName(), value->getContext());
}
-StringRef StringAttr::getValue() const { return getImpl()->value; }
+FunctionAttr FunctionAttr::get(StringRef value, MLIRContext *ctx) {
+ return Base::get(ctx, StandardAttributes::Function, value);
+}
+
+StringRef FunctionAttr::getValue() const { return getImpl()->value; }
//===----------------------------------------------------------------------===//
-// ArrayAttr
+// IntegerAttr
//===----------------------------------------------------------------------===//
-ArrayAttr ArrayAttr::get(ArrayRef<Attribute> value, MLIRContext *context) {
- return Base::get(context, StandardAttributes::Array, value);
+IntegerAttr IntegerAttr::get(Type type, const APInt &value) {
+ return Base::get(type.getContext(), StandardAttributes::Integer, type, value);
}
-ArrayRef<Attribute> ArrayAttr::getValue() const { return getImpl()->value; }
-
-//===----------------------------------------------------------------------===//
-// AffineMapAttr
-//===----------------------------------------------------------------------===//
+IntegerAttr IntegerAttr::get(Type type, int64_t value) {
+ // This uses 64 bit APInts by default for index type.
+ if (type.isIndex())
+ return get(type, APInt(64, value));
-AffineMapAttr AffineMapAttr::get(AffineMap value) {
- return Base::get(value.getResult(0).getContext(),
- StandardAttributes::AffineMap, value);
+ auto intType = type.cast<IntegerType>();
+ return get(type, APInt(intType.getWidth(), value));
}
-AffineMap AffineMapAttr::getValue() const { return getImpl()->value; }
+APInt IntegerAttr::getValue() const { return getImpl()->getValue(); }
+
+int64_t IntegerAttr::getInt() const { return getValue().getSExtValue(); }
//===----------------------------------------------------------------------===//
// IntegerSetAttr
IntegerSet IntegerSetAttr::getValue() const { return getImpl()->value; }
//===----------------------------------------------------------------------===//
-// TypeAttr
+// OpaqueAttr
//===----------------------------------------------------------------------===//
-TypeAttr TypeAttr::get(Type value) {
- return Base::get(value.getContext(), StandardAttributes::Type, value);
+OpaqueAttr OpaqueAttr::get(Identifier dialect, StringRef attrData,
+ MLIRContext *context) {
+ return Base::get(context, StandardAttributes::Opaque, dialect, attrData);
}
-Type TypeAttr::getValue() const { return getImpl()->value; }
+OpaqueAttr OpaqueAttr::getChecked(Identifier dialect, StringRef attrData,
+ MLIRContext *context, Location location) {
+ return Base::getChecked(location, context, StandardAttributes::Opaque,
+ dialect, attrData);
+}
+
+/// Returns the dialect namespace of the opaque attribute.
+Identifier OpaqueAttr::getDialectNamespace() const {
+ return getImpl()->dialectNamespace;
+}
+
+/// Returns the raw attribute data of the opaque attribute.
+StringRef OpaqueAttr::getAttrData() const { return getImpl()->attrData; }
+
+/// Verify the construction of an opaque attribute.
+LogicalResult OpaqueAttr::verifyConstructionInvariants(
+ llvm::Optional<Location> loc, MLIRContext *context, Identifier dialect,
+ StringRef attrData) {
+ if (!Dialect::isValidNamespace(dialect.strref())) {
+ if (loc)
+ context->emitError(*loc)
+ << "invalid dialect namespace '" << dialect << "'";
+ return failure();
+ }
+ return success();
+}
//===----------------------------------------------------------------------===//
-// FunctionAttr
+// StringAttr
//===----------------------------------------------------------------------===//
-FunctionAttr FunctionAttr::get(Function *value) {
- assert(value && "Cannot get FunctionAttr for a null function");
- return get(value->getName(), value->getContext());
+StringAttr StringAttr::get(StringRef bytes, MLIRContext *context) {
+ return Base::get(context, StandardAttributes::String, bytes);
}
-FunctionAttr FunctionAttr::get(StringRef value, MLIRContext *ctx) {
- return Base::get(ctx, StandardAttributes::Function, value);
+StringRef StringAttr::getValue() const { return getImpl()->value; }
+
+//===----------------------------------------------------------------------===//
+// TypeAttr
+//===----------------------------------------------------------------------===//
+
+TypeAttr TypeAttr::get(Type value) {
+ return Base::get(value.getContext(), StandardAttributes::Type, value);
}
-StringRef FunctionAttr::getValue() const { return getImpl()->value; }
+Type TypeAttr::getValue() const { return getImpl()->value; }
//===----------------------------------------------------------------------===//
// ElementsAttr
}
}
-//===----------------------------------------------------------------------===//
-// SplatElementsAttr
-//===----------------------------------------------------------------------===//
-
-SplatElementsAttr SplatElementsAttr::get(ShapedType type, Attribute elt) {
- return DenseElementsAttr::get(type, elt).cast<SplatElementsAttr>();
-}
-
-SplatElementsAttr SplatElementsAttr::mapValues(
- Type newElementType,
- llvm::function_ref<APInt(const APInt &)> mapping) const {
- return DenseElementsAttr::mapValues(newElementType, mapping)
- .cast<SplatElementsAttr>();
-}
-
-SplatElementsAttr SplatElementsAttr::mapValues(
- Type newElementType,
- llvm::function_ref<APInt(const APFloat &)> mapping) const {
- return DenseElementsAttr::mapValues(newElementType, mapping)
- .cast<SplatElementsAttr>();
-}
-
//===----------------------------------------------------------------------===//
// DenseElementAttr Utilities
//===----------------------------------------------------------------------===//
}
//===----------------------------------------------------------------------===//
-// DenseIntElementsAttr
+// DenseFPElementsAttr
//===----------------------------------------------------------------------===//
template <typename Fn, typename Attr>
return newArrayType;
}
-DenseElementsAttr DenseIntElementsAttr::mapValues(
+DenseElementsAttr DenseFPElementsAttr::mapValues(
Type newElementType,
- llvm::function_ref<APInt(const APInt &)> mapping) const {
+ llvm::function_ref<APInt(const APFloat &)> mapping) const {
llvm::SmallVector<char, 8> elementData;
auto newArrayType =
mappingHelper(mapping, *this, getType(), newElementType, elementData);
}
/// Method for supporting type inquiry through isa, cast and dyn_cast.
-bool DenseIntElementsAttr::classof(Attribute attr) {
+bool DenseFPElementsAttr::classof(Attribute attr) {
return attr.isa<DenseElementsAttr>() &&
- attr.getType().cast<ShapedType>().getElementType().isa<IntegerType>();
+ attr.getType().cast<ShapedType>().getElementType().isa<FloatType>();
}
//===----------------------------------------------------------------------===//
-// DenseFPElementsAttr
+// DenseIntElementsAttr
//===----------------------------------------------------------------------===//
-DenseElementsAttr DenseFPElementsAttr::mapValues(
+DenseElementsAttr DenseIntElementsAttr::mapValues(
Type newElementType,
- llvm::function_ref<APInt(const APFloat &)> mapping) const {
+ llvm::function_ref<APInt(const APInt &)> mapping) const {
llvm::SmallVector<char, 8> elementData;
auto newArrayType =
mappingHelper(mapping, *this, getType(), newElementType, elementData);
}
/// Method for supporting type inquiry through isa, cast and dyn_cast.
-bool DenseFPElementsAttr::classof(Attribute attr) {
+bool DenseIntElementsAttr::classof(Attribute attr) {
return attr.isa<DenseElementsAttr>() &&
- attr.getType().cast<ShapedType>().getElementType().isa<FloatType>();
+ attr.getType().cast<ShapedType>().getElementType().isa<IntegerType>();
}
//===----------------------------------------------------------------------===//
return getValues().getValue(it->second);
}
+//===----------------------------------------------------------------------===//
+// SplatElementsAttr
+//===----------------------------------------------------------------------===//
+
+SplatElementsAttr SplatElementsAttr::get(ShapedType type, Attribute elt) {
+ return DenseElementsAttr::get(type, elt).cast<SplatElementsAttr>();
+}
+
+SplatElementsAttr SplatElementsAttr::mapValues(
+ Type newElementType,
+ llvm::function_ref<APInt(const APInt &)> mapping) const {
+ return DenseElementsAttr::mapValues(newElementType, mapping)
+ .cast<SplatElementsAttr>();
+}
+
+SplatElementsAttr SplatElementsAttr::mapValues(
+ Type newElementType,
+ llvm::function_ref<APInt(const APFloat &)> mapping) const {
+ return DenseElementsAttr::mapValues(newElementType, mapping)
+ .cast<SplatElementsAttr>();
+}
+
//===----------------------------------------------------------------------===//
// NamedAttributeList
//===----------------------------------------------------------------------===//