[Mlir-commits] [mlir] 2f37cdd - [mlir][IR][NFC] Move a majority of the builtin attributes to ODS

River Riddle llvmlistbot at llvm.org
Thu Mar 4 13:04:16 PST 2021


Author: River Riddle
Date: 2021-03-04T13:04:06-08:00
New Revision: 2f37cdd5699f65cf6b9da615337cad6fdb012304

URL: https://github.com/llvm/llvm-project/commit/2f37cdd5699f65cf6b9da615337cad6fdb012304
DIFF: https://github.com/llvm/llvm-project/commit/2f37cdd5699f65cf6b9da615337cad6fdb012304.diff

LOG: [mlir][IR][NFC] Move a majority of the builtin attributes to ODS

Now that attributes can be generated using ODS, we can move the builtin attributes as well. This revision removes a majority of the builtin attributes with a few left for followup revisions. The attributes moved to ODS in this revision are: AffineMapAttr, ArrayAttr, DictionaryAttr, IntegerSetAttr, StringAttr, SymbolRefAttr, TypeAttr, and UnitAttr.

Differential Revision: https://reviews.llvm.org/D97591

Added: 
    mlir/include/mlir/IR/BuiltinAttributes.td

Modified: 
    mlir/include/mlir/IR/BuiltinAttributes.h
    mlir/include/mlir/IR/CMakeLists.txt
    mlir/lib/IR/AttributeDetail.h
    mlir/lib/IR/BuiltinAttributes.cpp
    mlir/lib/IR/CMakeLists.txt
    mlir/lib/IR/MLIRContext.cpp
    mlir/lib/IR/OperationSupport.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/IR/BuiltinAttributes.h b/mlir/include/mlir/IR/BuiltinAttributes.h
index ab9aa8d8fc89..99bb2b68cc62 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.h
+++ b/mlir/include/mlir/IR/BuiltinAttributes.h
@@ -16,21 +16,29 @@
 
 namespace mlir {
 class AffineMap;
+class FlatSymbolRefAttr;
 class FunctionType;
 class IntegerSet;
 class Location;
 class ShapedType;
+} // namespace mlir
+
+//===----------------------------------------------------------------------===//
+// Tablegen Attribute Declarations
+//===----------------------------------------------------------------------===//
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/IR/BuiltinAttributes.h.inc"
+
+//===----------------------------------------------------------------------===//
+// C++ Attribute Declarations
+//===----------------------------------------------------------------------===//
 
+namespace mlir {
 namespace detail {
 
-struct AffineMapAttributeStorage;
-struct ArrayAttributeStorage;
-struct DictionaryAttributeStorage;
 struct IntegerAttributeStorage;
-struct IntegerSetAttributeStorage;
 struct FloatAttributeStorage;
-struct OpaqueAttributeStorage;
-struct StringAttributeStorage;
 struct SymbolRefAttributeStorage;
 struct TypeAttributeStorage;
 
@@ -41,139 +49,6 @@ struct OpaqueElementsAttributeStorage;
 struct SparseElementsAttributeStorage;
 } // namespace detail
 
-//===----------------------------------------------------------------------===//
-// AffineMapAttr
-//===----------------------------------------------------------------------===//
-
-class AffineMapAttr
-    : public Attribute::AttrBase<AffineMapAttr, Attribute,
-                                 detail::AffineMapAttributeStorage> {
-public:
-  using Base::Base;
-  using ValueType = AffineMap;
-
-  static AffineMapAttr get(AffineMap value);
-
-  AffineMap getValue() const;
-};
-
-//===----------------------------------------------------------------------===//
-// ArrayAttr
-//===----------------------------------------------------------------------===//
-
-/// 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>;
-
-  static ArrayAttr get(MLIRContext *context, ArrayRef<Attribute> value);
-
-  ArrayRef<Attribute> getValue() const;
-  Attribute operator[](unsigned idx) const;
-
-  /// 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(); }
-  bool empty() const { return size() == 0; }
-
-private:
-  /// Class for underlying value iterator support.
-  template <typename AttrTy>
-  class attr_value_iterator final
-      : public llvm::mapped_iterator<ArrayAttr::iterator,
-                                     AttrTy (*)(Attribute)> {
-  public:
-    explicit attr_value_iterator(ArrayAttr::iterator it)
-        : llvm::mapped_iterator<ArrayAttr::iterator, AttrTy (*)(Attribute)>(
-              it, [](Attribute attr) { return attr.cast<AttrTy>(); }) {}
-    AttrTy operator*() const { return (*this->I).template cast<AttrTy>(); }
-  };
-
-public:
-  template <typename AttrTy>
-  iterator_range<attr_value_iterator<AttrTy>> getAsRange() {
-    return llvm::make_range(attr_value_iterator<AttrTy>(begin()),
-                            attr_value_iterator<AttrTy>(end()));
-  }
-  template <typename AttrTy, typename UnderlyingTy = typename AttrTy::ValueType>
-  auto getAsValueRange() {
-    return llvm::map_range(getAsRange<AttrTy>(), [](AttrTy attr) {
-      return static_cast<UnderlyingTy>(attr.getValue());
-    });
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// DictionaryAttr
-//===----------------------------------------------------------------------===//
-
-/// 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 = ArrayRef<NamedAttribute>;
-
-  /// Construct a dictionary attribute with the provided list of named
-  /// attributes. This method assumes that the provided list is unordered. If
-  /// the caller can guarantee that the attributes are ordered by name,
-  /// getWithSorted should be used instead.
-  static DictionaryAttr get(MLIRContext *context,
-                            ArrayRef<NamedAttribute> value);
-
-  /// Construct a dictionary with an array of values that is known to already be
-  /// sorted by name and uniqued.
-  static DictionaryAttr getWithSorted(ArrayRef<NamedAttribute> value,
-                                      MLIRContext *context);
-
-  ArrayRef<NamedAttribute> getValue() const;
-
-  /// Return the specified attribute if present, null otherwise.
-  Attribute get(StringRef name) const;
-  Attribute get(Identifier name) const;
-
-  /// Return the specified named attribute if present, None otherwise.
-  Optional<NamedAttribute> getNamed(StringRef name) const;
-  Optional<NamedAttribute> getNamed(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;
-
-  /// Sorts the NamedAttributes in the array ordered by name as expected by
-  /// getWithSorted and returns whether the values were sorted.
-  /// Requires: uniquely named attributes.
-  static bool sort(ArrayRef<NamedAttribute> values,
-                   SmallVectorImpl<NamedAttribute> &storage);
-
-  /// Sorts the NamedAttributes in the array ordered by name as expected by
-  /// getWithSorted in place on an array and returns whether the values needed
-  /// to be sorted.
-  /// Requires: uniquely named attributes.
-  static bool sortInPlace(SmallVectorImpl<NamedAttribute> &array);
-
-  /// Returns an entry with a duplicate name in `array`, if it exists, else
-  /// returns llvm::None. If `isSorted` is true, the array is assumed to be
-  /// sorted else it will be sorted in place before finding the duplicate entry.
-  static Optional<NamedAttribute>
-  findDuplicate(SmallVectorImpl<NamedAttribute> &array, bool isSorted);
-
-private:
-  /// Return empty dictionary.
-  static DictionaryAttr getEmpty(MLIRContext *context);
-};
-
 //===----------------------------------------------------------------------===//
 // FloatAttr
 //===----------------------------------------------------------------------===//
@@ -267,110 +142,9 @@ class BoolAttr : public Attribute {
 };
 
 //===----------------------------------------------------------------------===//
-// IntegerSetAttr
-//===----------------------------------------------------------------------===//
-
-class IntegerSetAttr
-    : public Attribute::AttrBase<IntegerSetAttr, Attribute,
-                                 detail::IntegerSetAttributeStorage> {
-public:
-  using Base::Base;
-  using ValueType = IntegerSet;
-
-  static IntegerSetAttr get(IntegerSet value);
-
-  IntegerSet getValue() const;
-};
-
-//===----------------------------------------------------------------------===//
-// OpaqueAttr
-//===----------------------------------------------------------------------===//
-
-/// 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 Base::getChecked;
-
-  /// Get or create a new OpaqueAttr with the provided dialect and string data.
-  static OpaqueAttr get(Identifier dialect, StringRef attrData, Type type);
-
-  /// 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(function_ref<InFlightDiagnostic()> emitError,
-                               Identifier dialect, StringRef attrData,
-                               Type type);
-
-  /// 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 verify(function_ref<InFlightDiagnostic()> emitError,
-                              Identifier dialect, StringRef attrData,
-                              Type type);
-};
-
-//===----------------------------------------------------------------------===//
-// StringAttr
-//===----------------------------------------------------------------------===//
-
-class StringAttr : public Attribute::AttrBase<StringAttr, Attribute,
-                                              detail::StringAttributeStorage> {
-public:
-  using Base::Base;
-  using ValueType = StringRef;
-
-  /// Get an instance of a StringAttr with the given string.
-  static StringAttr get(MLIRContext *context, StringRef bytes);
-
-  /// Get an instance of a StringAttr with the given string and Type.
-  static StringAttr get(StringRef bytes, Type type);
-
-  StringRef getValue() const;
-};
-
-//===----------------------------------------------------------------------===//
-// SymbolRefAttr
+// FlatSymbolRefAttr
 //===----------------------------------------------------------------------===//
 
-class FlatSymbolRefAttr;
-
-/// A symbol reference attribute represents a symbolic reference to another
-/// operation.
-class SymbolRefAttr
-    : public Attribute::AttrBase<SymbolRefAttr, Attribute,
-                                 detail::SymbolRefAttributeStorage> {
-public:
-  using Base::Base;
-
-  /// Construct a symbol reference for the given value name.
-  static FlatSymbolRefAttr get(MLIRContext *ctx, StringRef value);
-
-  /// Construct a symbol reference for the given value name, and a set of nested
-  /// references that are further resolve to a nested symbol.
-  static SymbolRefAttr get(MLIRContext *ctx, StringRef value,
-                           ArrayRef<FlatSymbolRefAttr> references);
-
-  /// Returns the name of the top level symbol reference, i.e. the root of the
-  /// reference path.
-  StringRef getRootReference() const;
-
-  /// Returns the name of the fully resolved symbol, i.e. the leaf of the
-  /// reference path.
-  StringRef getLeafReference() const;
-
-  /// Returns the set of nested references representing the path to the symbol
-  /// nested under the root reference.
-  ArrayRef<FlatSymbolRefAttr> getNestedReferences() const;
-};
-
 /// A symbol reference with a reference path containing a single element. This
 /// is used to refer to an operation within the current symbol table.
 class FlatSymbolRefAttr : public SymbolRefAttr {
@@ -397,35 +171,6 @@ class FlatSymbolRefAttr : public SymbolRefAttr {
   using SymbolRefAttr::getNestedReferences;
 };
 
-//===----------------------------------------------------------------------===//
-// Type
-//===----------------------------------------------------------------------===//
-
-class TypeAttr : public Attribute::AttrBase<TypeAttr, Attribute,
-                                            detail::TypeAttributeStorage> {
-public:
-  using Base::Base;
-  using ValueType = Type;
-
-  static TypeAttr get(Type value);
-
-  Type getValue() const;
-};
-
-//===----------------------------------------------------------------------===//
-// UnitAttr
-//===----------------------------------------------------------------------===//
-
-/// Unit attributes are attributes that hold no specific value and are given
-/// meaning by their existence.
-class UnitAttr
-    : public Attribute::AttrBase<UnitAttr, Attribute, AttributeStorage> {
-public:
-  using Base::Base;
-
-  static UnitAttr get(MLIRContext *context);
-};
-
 //===----------------------------------------------------------------------===//
 // Elements Attributes
 //===----------------------------------------------------------------------===//
@@ -1460,6 +1205,10 @@ auto ElementsAttr::getValues() const -> iterator_range<T> {
 
 } // end namespace mlir.
 
+//===----------------------------------------------------------------------===//
+// Attribute Utilities
+//===----------------------------------------------------------------------===//
+
 namespace llvm {
 
 template <>

diff  --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td
new file mode 100644
index 000000000000..c9911e5b9717
--- /dev/null
+++ b/mlir/include/mlir/IR/BuiltinAttributes.td
@@ -0,0 +1,448 @@
+//===- BuiltinAttributes.td - Builtin attr definitions -----*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the set of builtin MLIR types, or the set of types necessary for the
+// validity of and defining the IR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef BUILTIN_ATTRIBUTES
+#define BUILTIN_ATTRIBUTES
+
+include "mlir/IR/BuiltinDialect.td"
+
+// TODO: Currently the attributes defined in this file are prefixed with
+// `Builtin_`.  This is to 
diff erentiate the attributes here with the ones in
+// OpBase.td. We should remove the definitions in OpBase.td, and repoint users
+// to this file instead.
+
+// Base class for Builtin dialect attributes.
+class Builtin_Attr<string name> : AttrDef<Builtin_Dialect, name> {
+  let mnemonic = ?;
+}
+
+//===----------------------------------------------------------------------===//
+// AffineMapAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_AffineMapAttr : Builtin_Attr<"AffineMap"> {
+  let summary = "An Attribute containing an AffineMap object";
+  let description = [{
+    Syntax:
+
+    ```
+    affine-map-attribute ::= `affine_map` `<` affine-map `>`
+    ```
+
+    Examples:
+
+    ```mlir
+    affine_map<(d0) -> (d0)>
+    affine_map<(d0, d1, d2) -> (d0, d1)>
+    ```
+  }];
+  let parameters = (ins "AffineMap":$value);
+  let builders = [
+    AttrBuilderWithInferredContext<(ins "AffineMap":$value), [{
+      return $_get(value.getContext(), value);
+    }]>
+  ];
+  let extraClassDeclaration = "using ValueType = AffineMap;";
+  let skipDefaultBuilders = 1;
+  let typeBuilder = "IndexType::get($_value.getContext())";
+}
+
+//===----------------------------------------------------------------------===//
+// ArrayAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_ArrayAttr : Builtin_Attr<"Array"> {
+  let summary = "A collection of other Attribute values";
+  let description = [{
+    Syntax:
+
+    ```
+    array-attribute ::= `[` (attribute-value (`,` attribute-value)*)? `]`
+    ```
+
+    An array attribute is an attribute that represents a collection of attribute
+    values.
+
+    Examples:
+
+    ```mlir
+    []
+    [10, i32]
+    [affine_map<(d0, d1, d2) -> (d0, d1)>, i32, "string attribute"]
+    ```
+  }];
+  let parameters = (ins ArrayRefParameter<"Attribute", "">:$value);
+  let extraClassDeclaration = [{
+    using ValueType = ArrayRef<Attribute>;
+
+    /// Return the element at the given index.
+    Attribute operator[](unsigned idx) const {
+      assert(idx < size() && "index out of bounds");
+      return getValue()[idx];
+    }
+
+    /// 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(); }
+    bool empty() const { return size() == 0; }
+
+  private:
+    /// Class for underlying value iterator support.
+    template <typename AttrTy>
+    class attr_value_iterator final
+        : public llvm::mapped_iterator<ArrayAttr::iterator,
+                                       AttrTy (*)(Attribute)> {
+    public:
+      explicit attr_value_iterator(ArrayAttr::iterator it)
+          : llvm::mapped_iterator<ArrayAttr::iterator, AttrTy (*)(Attribute)>(
+                it, [](Attribute attr) { return attr.cast<AttrTy>(); }) {}
+      AttrTy operator*() const { return (*this->I).template cast<AttrTy>(); }
+    };
+
+  public:
+    template <typename AttrTy>
+    iterator_range<attr_value_iterator<AttrTy>> getAsRange() {
+      return llvm::make_range(attr_value_iterator<AttrTy>(begin()),
+                              attr_value_iterator<AttrTy>(end()));
+    }
+    template <typename AttrTy,
+              typename UnderlyingTy = typename AttrTy::ValueType>
+    auto getAsValueRange() {
+      return llvm::map_range(getAsRange<AttrTy>(), [](AttrTy attr) {
+        return static_cast<UnderlyingTy>(attr.getValue());
+      });
+    }
+  }];
+}
+
+//===----------------------------------------------------------------------===//
+// DictionaryAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_DictionaryAttr : Builtin_Attr<"Dictionary"> {
+  let summary = "An dictionary of named Attribute values";
+  let description = [{
+    Syntax:
+
+    ```
+    dictionary-attribute ::= `{` (attribute-entry (`,` attribute-entry)*)? `}`
+    ```
+
+    A 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.
+
+    Examples:
+
+    ```mlir
+    {}
+    {attr_name = "string attribute"}
+    {int_attr = 10, "string attr name" = "string attribute"}
+    ```
+  }];
+  let parameters = (ins ArrayRefParameter<"NamedAttribute", "">:$value);
+  let builders = [
+    AttrBuilder<(ins "ArrayRef<NamedAttribute>":$value)>
+  ];
+  let extraClassDeclaration = [{
+    using ValueType = ArrayRef<NamedAttribute>;
+
+    /// Construct a dictionary with an array of values that is known to already
+    /// be sorted by name and uniqued.
+    static DictionaryAttr getWithSorted(MLIRContext *context,
+                                        ArrayRef<NamedAttribute> value);
+
+    /// Return the specified attribute if present, null otherwise.
+    Attribute get(StringRef name) const;
+    Attribute get(Identifier name) const;
+
+    /// Return the specified named attribute if present, None otherwise.
+    Optional<NamedAttribute> getNamed(StringRef name) const;
+    Optional<NamedAttribute> getNamed(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;
+
+    /// Sorts the NamedAttributes in the array ordered by name as expected by
+    /// getWithSorted and returns whether the values were sorted.
+    /// Requires: uniquely named attributes.
+    static bool sort(ArrayRef<NamedAttribute> values,
+                     SmallVectorImpl<NamedAttribute> &storage);
+
+    /// Sorts the NamedAttributes in the array ordered by name as expected by
+    /// getWithSorted in place on an array and returns whether the values needed
+    /// to be sorted.
+    /// Requires: uniquely named attributes.
+    static bool sortInPlace(SmallVectorImpl<NamedAttribute> &array);
+
+    /// Returns an entry with a duplicate name in `array`, if it exists, else
+    /// returns llvm::None. If `isSorted` is true, the array is assumed to be
+    /// sorted else it will be sorted in place before finding the duplicate entry.
+    static Optional<NamedAttribute>
+    findDuplicate(SmallVectorImpl<NamedAttribute> &array, bool isSorted);
+
+  private:
+    /// Return empty dictionary.
+    static DictionaryAttr getEmpty(MLIRContext *context);
+
+    /// Return empty dictionary. This is a special variant of the above method
+    /// that is used by the MLIRContext to cache the empty dictionary instance.
+    static DictionaryAttr getEmptyUnchecked(MLIRContext *context);
+
+    /// Allow access to `getEmptyUnchecked`.
+    friend MLIRContext;
+
+  public:
+  }];
+  let skipDefaultBuilders = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// IntegerSetAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_IntegerSetAttr : Builtin_Attr<"IntegerSet"> {
+  let summary = "An Attribute containing an IntegerSet object";
+  let description = [{
+    Syntax:
+
+    ```
+    integer-set-attribute ::= `affine_set` `<` integer-set `>`
+    ```
+
+    Examples:
+
+    ```mlir
+    affine_set<(d0) : (d0 - 2 >= 0)>
+    ```
+  }];
+  let parameters = (ins "IntegerSet":$value);
+  let builders = [
+    AttrBuilderWithInferredContext<(ins "IntegerSet":$value), [{
+      return $_get(value.getContext(), value);
+    }]>
+  ];
+  let extraClassDeclaration = "using ValueType = IntegerSet;";
+  let skipDefaultBuilders = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// OpaqueAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_OpaqueAttr : Builtin_Attr<"Opaque"> {
+  let summary = "An opaque representation of another Attribute";
+  let description = [{
+    Syntax:
+
+    ```
+    opaque-attribute ::= dialect-namespace `<` attr-data `>`
+    ```
+
+    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.
+
+    Examples:
+
+    ```mlir
+    #dialect<"opaque attribute data">
+    ```
+  }];
+  let parameters = (ins "Identifier":$dialectNamespace,
+                        StringRefParameter<"">:$attrData,
+                        AttributeSelfTypeParameter<"">:$type);
+  let builders = [
+    AttrBuilderWithInferredContext<(ins "Identifier":$dialect,
+                                        "StringRef":$attrData,
+                                        "Type":$type), [{
+      return $_get(dialect.getContext(), dialect, attrData, type);
+    }]>
+  ];
+  bit genVerifyDecl = 1;
+  // let skipDefaultBuilders = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// StringAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_StringAttr : Builtin_Attr<"String"> {
+  let summary = "An Attribute containing a string";
+  let description = [{
+    Syntax:
+
+    ```
+    string-attribute ::= string-literal (`:` type)?
+    ```
+
+    A string attribute is an attribute that represents a string literal value.
+
+    Examples:
+
+    ```mlir
+    "An important string"
+    "string with a type" : !dialect.string
+    ```
+  }];
+  let parameters = (ins StringRefParameter<"">:$value,
+                        AttributeSelfTypeParameter<"">:$type);
+  let builders = [
+    AttrBuilderWithInferredContext<(ins "StringRef":$bytes,
+                                        "Type":$type), [{
+      return $_get(type.getContext(), bytes, type);
+    }]>,
+    AttrBuilder<(ins "StringRef":$bytes), [{
+      return $_get($_ctxt, bytes, NoneType::get($_ctxt));
+    }]>
+  ];
+  let extraClassDeclaration = "using ValueType = StringRef;";
+  let skipDefaultBuilders = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// SymbolRefAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_SymbolRefAttr : Builtin_Attr<"SymbolRef"> {
+  let summary = "An Attribute containing a symbolic reference to an Operation";
+  let description = [{
+    Syntax:
+
+    ```
+    symbol-ref-attribute ::= symbol-ref-id (`::` symbol-ref-id)*
+    ```
+
+    A symbol reference attribute is a literal attribute that represents a named
+    reference to an operation that is nested within an operation with the
+    `OpTrait::SymbolTable` trait. As such, this reference is given meaning by
+    the nearest parent operation containing the `OpTrait::SymbolTable` trait. It
+    may optionally contain a set of nested references that further resolve to a
+    symbol nested within a 
diff erent symbol table.
+
+    This attribute can only be held internally by
+    [array attributes](#array-attribute) and
+    [dictionary attributes](#dictionary-attribute)(including the top-level
+    operation attribute dictionary), i.e. no other attribute kinds such as
+    Locations or extended attribute kinds.
+
+    **Rationale:** Identifying accesses to global data is critical to
+    enabling efficient multi-threaded compilation. Restricting global
+    data access to occur through symbols and limiting the places that can
+    legally hold a symbol reference simplifies reasoning about these data
+    accesses.
+
+    See [`Symbols And SymbolTables`](SymbolsAndSymbolTables.md) for more
+    information.
+
+    Examples:
+
+    ```mlir
+    @flat_reference
+    @parent_reference::@nested_reference
+    ```
+  }];
+  let parameters = (ins
+    StringRefParameter<"">:$rootReference,
+    ArrayRefParameter<"FlatSymbolRefAttr", "">:$nestedReferences
+  );
+  let extraClassDeclaration = [{
+    static FlatSymbolRefAttr get(MLIRContext *ctx, StringRef value);
+
+    /// Returns the name of the fully resolved symbol, i.e. the leaf of the
+    /// reference path.
+    StringRef getLeafReference() const;
+  }];
+}
+
+//===----------------------------------------------------------------------===//
+// TypeAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_TypeAttr : Builtin_Attr<"Type"> {
+  let summary = "An Attribute containing a Type";
+  let description = [{
+    Syntax:
+
+    ```
+    type-attribute ::= type
+    ```
+
+    A type attribute is an attribute that represents a
+    [type object](#type-system).
+
+    Examples:
+
+    ```mlir
+    i32
+    !dialect.type
+    ```
+  }];
+  let parameters = (ins "Type":$value);
+  let builders = [
+    AttrBuilderWithInferredContext<(ins "Type":$type), [{
+      return $_get(type.getContext(), type);
+    }]>,
+  ];
+  let extraClassDeclaration = "using ValueType = Type;";
+  let skipDefaultBuilders = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// UnitAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_UnitAttr : Builtin_Attr<"Unit"> {
+  let summary = "An Attribute value of `unit` type";
+  let description = [{
+    Syntax:
+
+    ```
+    unit-attribute ::= `unit`
+    ```
+
+    A unit attribute is an attribute that represents a value of `unit` type. The
+    `unit` type allows only one value forming a singleton set. This attribute
+    value is used to represent attributes that only have meaning from their
+    existence.
+
+    One example of such an attribute could be the `swift.self` attribute. This
+    attribute indicates that a function parameter is the self/context parameter.
+    It could be represented as a [boolean attribute](#boolean-attribute)(true or
+    false), but a value of false doesn't really bring any value. The parameter
+    either is the self/context or it isn't.
+
+
+    Examples:
+
+    ```mlir
+    // A unit attribute defined with the `unit` value specifier.
+    func @verbose_form() attributes {dialectName.unitAttr = unit}
+
+    // A unit attribute in an attribute dictionary can also be defined without
+    // the value specifier.
+    func @simple_form() attributes {dialectName.unitAttr}
+    ```
+  }];
+  let extraClassDeclaration = [{
+    static UnitAttr get(MLIRContext *context);
+  }];
+}
+
+#endif // BUILTIN_ATTRIBUTES

diff  --git a/mlir/include/mlir/IR/CMakeLists.txt b/mlir/include/mlir/IR/CMakeLists.txt
index 3b7ddbaf2338..fd598f3a3a66 100644
--- a/mlir/include/mlir/IR/CMakeLists.txt
+++ b/mlir/include/mlir/IR/CMakeLists.txt
@@ -2,6 +2,11 @@ add_mlir_interface(OpAsmInterface)
 add_mlir_interface(SymbolInterfaces)
 add_mlir_interface(RegionKindInterface)
 
+set(LLVM_TARGET_DEFINITIONS BuiltinAttributes.td)
+mlir_tablegen(BuiltinAttributes.h.inc -gen-attrdef-decls)
+mlir_tablegen(BuiltinAttributes.cpp.inc -gen-attrdef-defs)
+add_public_tablegen_target(MLIRBuiltinAttributesIncGen)
+
 set(LLVM_TARGET_DEFINITIONS BuiltinDialect.td)
 mlir_tablegen(BuiltinDialect.h.inc -gen-dialect-decls)
 add_public_tablegen_target(MLIRBuiltinDialectIncGen)

diff  --git a/mlir/lib/IR/AttributeDetail.h b/mlir/lib/IR/AttributeDetail.h
index db86d7a1c27b..9499a0f84c84 100644
--- a/mlir/lib/IR/AttributeDetail.h
+++ b/mlir/lib/IR/AttributeDetail.h
@@ -26,91 +26,6 @@
 
 namespace mlir {
 namespace detail {
-// An attribute representing a reference to an affine map.
-struct AffineMapAttributeStorage : public AttributeStorage {
-  using KeyTy = AffineMap;
-
-  AffineMapAttributeStorage(AffineMap value)
-      : AttributeStorage(IndexType::get(value.getContext())), value(value) {}
-
-  /// 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);
-  }
-
-  AffineMap 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));
-  }
-
-  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 *
-  construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
-    auto size = DictionaryAttributeStorage::totalSizeToAlloc<NamedAttribute>(
-        key.size());
-    auto rawMem = allocator.allocate(size, alignof(DictionaryAttributeStorage));
-
-    // 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;
-  }
-
-  /// 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;
-  }
-  DictionaryAttributeStorage(unsigned numElements) : numElements(numElements) {}
-
-  /// This is the number of attributes.
-  const unsigned numElements;
-};
 
 /// An attribute representing a floating point value.
 struct FloatAttributeStorage final
@@ -219,131 +134,6 @@ struct IntegerAttributeStorage final
   size_t numObjects;
 };
 
-// An attribute representing a reference to an integer set.
-struct IntegerSetAttributeStorage : public AttributeStorage {
-  using KeyTy = IntegerSet;
-
-  IntegerSetAttributeStorage(IntegerSet 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);
-  }
-
-  IntegerSet value;
-};
-
-/// Opaque Attribute Storage and Uniquing.
-struct OpaqueAttributeStorage : public AttributeStorage {
-  OpaqueAttributeStorage(Identifier dialectNamespace, StringRef attrData,
-                         Type type)
-      : AttributeStorage(type), dialectNamespace(dialectNamespace),
-        attrData(attrData) {}
-
-  /// The hash key used for uniquing.
-  using KeyTy = std::tuple<Identifier, StringRef, Type>;
-  bool operator==(const KeyTy &key) const {
-    return key == KeyTy(dialectNamespace, attrData, getType());
-  }
-
-  static OpaqueAttributeStorage *construct(AttributeStorageAllocator &allocator,
-                                           const KeyTy &key) {
-    return new (allocator.allocate<OpaqueAttributeStorage>())
-        OpaqueAttributeStorage(std::get<0>(key),
-                               allocator.copyInto(std::get<1>(key)),
-                               std::get<2>(key));
-  }
-
-  // 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 = std::pair<StringRef, Type>;
-
-  StringAttributeStorage(StringRef value, Type type)
-      : AttributeStorage(type), value(value) {}
-
-  /// Key equality function.
-  bool operator==(const KeyTy &key) const {
-    return key == KeyTy(value, getType());
-  }
-
-  /// Construct a new storage instance.
-  static StringAttributeStorage *construct(AttributeStorageAllocator &allocator,
-                                           const KeyTy &key) {
-    return new (allocator.allocate<StringAttributeStorage>())
-        StringAttributeStorage(allocator.copyInto(key.first), key.second);
-  }
-
-  StringRef value;
-};
-
-/// An attribute representing a symbol reference.
-struct SymbolRefAttributeStorage final
-    : public AttributeStorage,
-      public llvm::TrailingObjects<SymbolRefAttributeStorage,
-                                   FlatSymbolRefAttr> {
-  using KeyTy = std::pair<StringRef, ArrayRef<FlatSymbolRefAttr>>;
-
-  SymbolRefAttributeStorage(StringRef value, size_t numNestedRefs)
-      : value(value), numNestedRefs(numNestedRefs) {}
-
-  /// Key equality function.
-  bool operator==(const KeyTy &key) const {
-    return key == KeyTy(value, getNestedRefs());
-  }
-
-  /// Construct a new storage instance.
-  static SymbolRefAttributeStorage *
-  construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
-    auto size = SymbolRefAttributeStorage::totalSizeToAlloc<FlatSymbolRefAttr>(
-        key.second.size());
-    auto rawMem = allocator.allocate(size, alignof(SymbolRefAttributeStorage));
-    auto result = ::new (rawMem) SymbolRefAttributeStorage(
-        allocator.copyInto(key.first), key.second.size());
-    std::uninitialized_copy(key.second.begin(), key.second.end(),
-                            result->getTrailingObjects<FlatSymbolRefAttr>());
-    return result;
-  }
-
-  /// Returns the set of nested references.
-  ArrayRef<FlatSymbolRefAttr> getNestedRefs() const {
-    return {getTrailingObjects<FlatSymbolRefAttr>(), numNestedRefs};
-  }
-
-  StringRef value;
-  size_t numNestedRefs;
-};
-
-/// An attribute representing a reference to a type.
-struct TypeAttributeStorage : public AttributeStorage {
-  using KeyTy = Type;
-
-  TypeAttributeStorage(Type value) : value(value) {}
-
-  /// Key equality function.
-  bool operator==(const KeyTy &key) const { return key == value; }
-
-  /// Construct a new storage instance.
-  static TypeAttributeStorage *construct(AttributeStorageAllocator &allocator,
-                                         KeyTy key) {
-    return new (allocator.allocate<TypeAttributeStorage>())
-        TypeAttributeStorage(key);
-  }
-
-  Type value;
-};
-
 //===----------------------------------------------------------------------===//
 // Elements Attributes
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp
index cccef6c76818..1d76122996de 100644
--- a/mlir/lib/IR/BuiltinAttributes.cpp
+++ b/mlir/lib/IR/BuiltinAttributes.cpp
@@ -22,29 +22,11 @@ using namespace mlir;
 using namespace mlir::detail;
 
 //===----------------------------------------------------------------------===//
-// AffineMapAttr
+/// Tablegen Attribute Definitions
 //===----------------------------------------------------------------------===//
 
-AffineMapAttr AffineMapAttr::get(AffineMap value) {
-  return Base::get(value.getContext(), value);
-}
-
-AffineMap AffineMapAttr::getValue() const { return getImpl()->value; }
-
-//===----------------------------------------------------------------------===//
-// ArrayAttr
-//===----------------------------------------------------------------------===//
-
-ArrayAttr ArrayAttr::get(MLIRContext *context, ArrayRef<Attribute> value) {
-  return Base::get(context, value);
-}
-
-ArrayRef<Attribute> ArrayAttr::getValue() const { return getImpl()->value; }
-
-Attribute ArrayAttr::operator[](unsigned idx) const {
-  assert(idx < size() && "index out of bounds");
-  return getValue()[idx];
-}
+#define GET_ATTRDEF_CLASSES
+#include "mlir/IR/BuiltinAttributes.cpp.inc"
 
 //===----------------------------------------------------------------------===//
 // DictionaryAttr
@@ -152,8 +134,8 @@ DictionaryAttr DictionaryAttr::get(MLIRContext *context,
 }
 /// Construct a dictionary with an array of values that is known to already be
 /// sorted by name and uniqued.
-DictionaryAttr DictionaryAttr::getWithSorted(ArrayRef<NamedAttribute> value,
-                                             MLIRContext *context) {
+DictionaryAttr DictionaryAttr::getWithSorted(MLIRContext *context,
+                                             ArrayRef<NamedAttribute> value) {
   if (value.empty())
     return DictionaryAttr::getEmpty(context);
   // Ensure that the attribute elements are unique and sorted.
@@ -167,10 +149,6 @@ DictionaryAttr DictionaryAttr::getWithSorted(ArrayRef<NamedAttribute> value,
   return Base::get(context, value);
 }
 
-ArrayRef<NamedAttribute> DictionaryAttr::getValue() const {
-  return getImpl()->getElements();
-}
-
 /// Return the specified attribute if present, null otherwise.
 Attribute DictionaryAttr::get(StringRef name) const {
   Optional<NamedAttribute> attr = getNamed(name);
@@ -203,6 +181,10 @@ DictionaryAttr::iterator DictionaryAttr::end() const {
 }
 size_t DictionaryAttr::size() const { return getValue().size(); }
 
+DictionaryAttr DictionaryAttr::getEmptyUnchecked(MLIRContext *context) {
+  return Base::get(context, ArrayRef<NamedAttribute>());
+}
+
 //===----------------------------------------------------------------------===//
 // FloatAttr
 //===----------------------------------------------------------------------===//
@@ -272,25 +254,14 @@ LogicalResult FloatAttr::verify(function_ref<InFlightDiagnostic()> emitError,
 //===----------------------------------------------------------------------===//
 
 FlatSymbolRefAttr SymbolRefAttr::get(MLIRContext *ctx, StringRef value) {
-  return Base::get(ctx, value, llvm::None).cast<FlatSymbolRefAttr>();
+  return get(ctx, value, llvm::None).cast<FlatSymbolRefAttr>();
 }
 
-SymbolRefAttr SymbolRefAttr::get(MLIRContext *ctx, StringRef value,
-                                 ArrayRef<FlatSymbolRefAttr> nestedReferences) {
-  return Base::get(ctx, value, nestedReferences);
-}
-
-StringRef SymbolRefAttr::getRootReference() const { return getImpl()->value; }
-
 StringRef SymbolRefAttr::getLeafReference() const {
   ArrayRef<FlatSymbolRefAttr> nestedRefs = getNestedReferences();
   return nestedRefs.empty() ? getRootReference() : nestedRefs.back().getValue();
 }
 
-ArrayRef<FlatSymbolRefAttr> SymbolRefAttr::getNestedReferences() const {
-  return getImpl()->getNestedRefs();
-}
-
 //===----------------------------------------------------------------------===//
 // IntegerAttr
 //===----------------------------------------------------------------------===//
@@ -368,40 +339,10 @@ bool BoolAttr::classof(Attribute attr) {
   return intAttr && intAttr.getType().isSignlessInteger(1);
 }
 
-//===----------------------------------------------------------------------===//
-// IntegerSetAttr
-//===----------------------------------------------------------------------===//
-
-IntegerSetAttr IntegerSetAttr::get(IntegerSet value) {
-  return Base::get(value.getConstraint(0).getContext(), value);
-}
-
-IntegerSet IntegerSetAttr::getValue() const { return getImpl()->value; }
-
 //===----------------------------------------------------------------------===//
 // OpaqueAttr
 //===----------------------------------------------------------------------===//
 
-OpaqueAttr OpaqueAttr::get(Identifier dialect, StringRef attrData, Type type) {
-  return Base::get(dialect.getContext(), dialect, attrData, type);
-}
-
-OpaqueAttr OpaqueAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
-                                  Identifier dialect, StringRef attrData,
-                                  Type type) {
-  return Base::getChecked(emitError, dialect.getContext(), dialect, attrData,
-                          type);
-}
-
-/// 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::verify(function_ref<InFlightDiagnostic()> emitError,
                                  Identifier dialect, StringRef attrData,
                                  Type type) {
@@ -410,31 +351,6 @@ LogicalResult OpaqueAttr::verify(function_ref<InFlightDiagnostic()> emitError,
   return success();
 }
 
-//===----------------------------------------------------------------------===//
-// StringAttr
-//===----------------------------------------------------------------------===//
-
-StringAttr StringAttr::get(MLIRContext *context, StringRef bytes) {
-  return get(bytes, NoneType::get(context));
-}
-
-/// Get an instance of a StringAttr with the given string and Type.
-StringAttr StringAttr::get(StringRef bytes, Type type) {
-  return Base::get(type.getContext(), bytes, type);
-}
-
-StringRef StringAttr::getValue() const { return getImpl()->value; }
-
-//===----------------------------------------------------------------------===//
-// TypeAttr
-//===----------------------------------------------------------------------===//
-
-TypeAttr TypeAttr::get(Type value) {
-  return Base::get(value.getContext(), value);
-}
-
-Type TypeAttr::getValue() const { return getImpl()->value; }
-
 //===----------------------------------------------------------------------===//
 // ElementsAttr
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/lib/IR/CMakeLists.txt b/mlir/lib/IR/CMakeLists.txt
index f9ab7033eb48..49911c9e2ce5 100644
--- a/mlir/lib/IR/CMakeLists.txt
+++ b/mlir/lib/IR/CMakeLists.txt
@@ -33,6 +33,7 @@ add_mlir_library(MLIRIR
   ${MLIR_MAIN_INCLUDE_DIR}/mlir/IR
 
   DEPENDS
+  MLIRBuiltinAttributesIncGen
   MLIRBuiltinDialectIncGen
   MLIRBuiltinOpsIncGen
   MLIRBuiltinTypesIncGen

diff  --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp
index c42041208491..7a4aac1f947c 100644
--- a/mlir/lib/IR/MLIRContext.cpp
+++ b/mlir/lib/IR/MLIRContext.cpp
@@ -403,8 +403,7 @@ MLIRContext::MLIRContext(const DialectRegistry &registry)
   /// Unknown Location Attribute.
   impl->unknownLocAttr = AttributeUniquer::get<UnknownLoc>(this);
   /// The empty dictionary attribute.
-  impl->emptyDictionaryAttr =
-      AttributeUniquer::get<DictionaryAttr>(this, ArrayRef<NamedAttribute>());
+  impl->emptyDictionaryAttr = DictionaryAttr::getEmptyUnchecked(this);
 
   // Register the affine storage objects with the uniquer.
   impl->affineUniquer

diff  --git a/mlir/lib/IR/OperationSupport.cpp b/mlir/lib/IR/OperationSupport.cpp
index b939c5304e75..28acdc2fcb29 100644
--- a/mlir/lib/IR/OperationSupport.cpp
+++ b/mlir/lib/IR/OperationSupport.cpp
@@ -54,7 +54,7 @@ DictionaryAttr NamedAttrList::getDictionary(MLIRContext *context) const {
     dictionarySorted.setPointerAndInt(nullptr, true);
   }
   if (!dictionarySorted.getPointer())
-    dictionarySorted.setPointer(DictionaryAttr::getWithSorted(attrs, context));
+    dictionarySorted.setPointer(DictionaryAttr::getWithSorted(context, attrs));
   return dictionarySorted.getPointer().cast<DictionaryAttr>();
 }
 


        


More information about the Mlir-commits mailing list