NFC: Reorder the attribute classes alphabetically to improve readability.
authorRiver Riddle <riverriddle@google.com>
Tue, 18 Jun 2019 23:41:00 +0000 (16:41 -0700)
committerMehdi Amini <joker.eph@gmail.com>
Thu, 20 Jun 2019 06:07:24 +0000 (23:07 -0700)
PiperOrigin-RevId: 253894445

mlir/include/mlir/IR/Attributes.h
mlir/lib/IR/AttributeDetail.h
mlir/lib/IR/Attributes.cpp

index cf1bb9e4f36dd9f67965e656c7623d2af7d79c05..76e57e527e4b8983528486be7ddce93f42b6bb81 100644 (file)
@@ -30,21 +30,23 @@ class Identifier;
 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;
@@ -137,19 +139,20 @@ inline raw_ostream &operator<<(raw_ostream &os, Attribute attr) {
 
 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,
@@ -158,51 +161,44 @@ enum Kind {
 };
 } // 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;
   }
 };
 
@@ -220,23 +216,40 @@ public:
   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;
   }
 };
 
@@ -277,114 +290,111 @@ public:
                                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;
   }
 };
 
@@ -402,26 +412,23 @@ public:
   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 {
@@ -686,30 +693,6 @@ protected:
   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 {
@@ -732,36 +715,28 @@ public:
   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
@@ -840,6 +815,38 @@ public:
   }
 };
 
+/// 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);
index f164f505f33798f8f815729c63600bfd67dc7d70..0fe07a9791694c818143e751dde11d46300e078b 100644 (file)
@@ -24,7 +24,6 @@
 
 #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.
@@ -82,51 +96,51 @@ struct BoolAttributeStorage : public AttributeStorage {
   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.
@@ -191,128 +205,113 @@ struct FloatAttributeStorage final
   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.
@@ -334,28 +333,9 @@ struct TypeAttributeStorage : public AttributeStorage {
   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 {
index bbf8995821302a86487d5f0536b6c3f2f9ecd21f..ce33508830c51299e4d6db7bc4b5b9b5ce7d3a49 100644 (file)
@@ -57,41 +57,26 @@ MLIRContext *Attribute::getContext() const { return getType().getContext(); }
 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
 //===----------------------------------------------------------------------===//
@@ -195,27 +180,6 @@ DictionaryAttr::iterator DictionaryAttr::end() const {
 }
 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
 //===----------------------------------------------------------------------===//
@@ -287,35 +251,40 @@ FloatAttr::verifyConstructionInvariants(llvm::Optional<Location> loc,
 }
 
 //===----------------------------------------------------------------------===//
-// 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
@@ -329,29 +298,60 @@ IntegerSetAttr IntegerSetAttr::get(IntegerSet value) {
 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
@@ -398,28 +398,6 @@ ElementsAttr ElementsAttr::mapValues(
   }
 }
 
-//===----------------------------------------------------------------------===//
-// 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
 //===----------------------------------------------------------------------===//
@@ -787,7 +765,7 @@ DenseElementsAttr DenseElementsAttr::mapValues(
 }
 
 //===----------------------------------------------------------------------===//
-// DenseIntElementsAttr
+// DenseFPElementsAttr
 //===----------------------------------------------------------------------===//
 
 template <typename Fn, typename Attr>
@@ -820,9 +798,9 @@ static ShapedType mappingHelper(Fn mapping, Attr &attr, ShapedType inType,
   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);
@@ -831,18 +809,18 @@ DenseElementsAttr DenseIntElementsAttr::mapValues(
 }
 
 /// 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);
@@ -851,9 +829,9 @@ DenseElementsAttr DenseFPElementsAttr::mapValues(
 }
 
 /// 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>();
 }
 
 //===----------------------------------------------------------------------===//
@@ -962,6 +940,28 @@ Attribute SparseElementsAttr::getValue(ArrayRef<uint64_t> index) const {
   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
 //===----------------------------------------------------------------------===//