Skip to content

Commit e179532

Browse files
author
Jeff Niu
committed
[mlir] Remove types from attributes
This patch removes the `type` field from `Attribute` along with the `Attribute::getType` accessor. Going forward, this means that attributes in MLIR will no longer have types as a first-class concept. This patch lays the groundwork to incrementally remove or refactor code that relies on generic attributes being typed. The immediate impact will be on attributes that rely on `Attribute` containing a type, such as `IntegerAttr`, `DenseElementsAttr`, and `ml_program::ExternAttr`, which will now need to define a type parameter on their storage classes. This will save memory as all other attribute kinds will no longer contain a type. Moreover, it will not be possible to generically query the type of an attribute directly. This patch provides an attribute interface `TypedAttr` that implements only one method, `getType`, which can be used to generically query the types of attributes that implement the interface. This interface can be used to retain the concept of a "typed attribute". The ODS-generated accessor for a `type` parameter automatically implements this method. Next steps will be to refactor the assembly formats of certain operations that rely on `parseAttribute(type)` and `printAttributeWithoutType` to remove special handling of type elision until `type` can be removed from the dialect parsing hook entirely; and incrementally remove uses of `TypedAttr`. Reviewed By: lattner, rriddle, jpienaar Differential Revision: https://reviews.llvm.org/D130092
1 parent af1328e commit e179532

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+433
-332
lines changed

mlir/docs/AttributesAndTypes.md

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,9 @@ def My_IntegerAttr : MyDialect_Attr<"Integer", "int"> {
126126
An integer attribute is a literal attribute that represents an integral
127127
value of the specified integer type.
128128
}];
129-
/// Here we've defined two parameters, one is the `self` type of the attribute
130-
/// (i.e. the type of the Attribute itself), and the other is the integer value
131-
/// of the attribute.
129+
/// Here we've defined two parameters, one is a "self" type parameter, and the
130+
/// other is the integer value of the attribute. The self type parameter is
131+
/// specially handled by the assembly format.
132132
let parameters = (ins AttributeSelfTypeParameter<"">:$type, "APInt":$value);
133133
134134
/// Here we've defined a custom builder for the type, that removes the need to pass
@@ -146,6 +146,8 @@ def My_IntegerAttr : MyDialect_Attr<"Integer", "int"> {
146146
///
147147
/// #my.int<50> : !my.int<32> // a 32-bit integer of value 50.
148148
///
149+
/// Note that the self type parameter is not included in the assembly format.
150+
/// Its value is derived from the optional trailing type on all attributes.
149151
let assemblyFormat = "`<` $value `>`";
150152
151153
/// Indicate that our attribute will add additional verification to the parameters.
@@ -271,9 +273,8 @@ MLIR includes several specialized classes for common situations:
271273
- `ArrayRefOfSelfAllocationParameter<arrayOf, descriptionOfParam>` for arrays of
272274
objects which self-allocate as per the last specialization.
273275

274-
- `AttributeSelfTypeParameter` is a special AttrParameter that corresponds to
275-
the `Type` of the attribute. Only one parameter of the attribute may be of
276-
this parameter type.
276+
- `AttributeSelfTypeParameter` is a special `AttrParameter` that represents
277+
parameters derived from the optional trailing type on attributes.
277278

278279
### Traits
279280

@@ -702,6 +703,54 @@ available through `$_ctxt`. E.g.
702703
DefaultValuedParameter<"IntegerType", "IntegerType::get($_ctxt, 32)">
703704
```
704705

706+
The value of parameters that appear __before__ the default-valued parameter in
707+
the parameter declaration list are available as substitutions. E.g.
708+
709+
```tablegen
710+
let parameters = (ins
711+
"IntegerAttr":$value,
712+
DefaultValuedParameter<"Type", "$value.getType()">:$type
713+
);
714+
```
715+
716+
###### Attribute Self Type Parameter
717+
718+
An attribute optionally has a trailing type after the assembly format of the
719+
attribute value itself. MLIR parses over the attribute value and optionally
720+
parses a colon-type before passing the `Type` into the dialect parser hook.
721+
722+
```
723+
dialect-attribute ::= `#` dialect-namespace `<` attr-data `>`
724+
(`:` type)?
725+
| `#` alias-name pretty-dialect-sym-body? (`:` type)?
726+
```
727+
728+
`AttributeSelfTypeParameter` is an attribute parameter specially handled by the
729+
assembly format generator. Only one such parameter can be specified, and its
730+
value is derived from the trailing type. This parameter's default value is
731+
`NoneType::get($_ctxt)`.
732+
733+
In order for the type to be printed by
734+
MLIR, however, the attribute must implement `TypedAttrInterface`. For example,
735+
736+
```tablegen
737+
// This attribute has only a self type parameter.
738+
def MyExternAttr : AttrDef<MyDialect, "MyExtern", [TypedAttrInterface]> {
739+
let parameters = (AttributeSelfTypeParameter<"">:$type);
740+
let mnemonic = "extern";
741+
let assemblyFormat = "";
742+
}
743+
```
744+
745+
This attribute can look like:
746+
747+
```mlir
748+
#my_dialect.extern // none
749+
#my_dialect.extern : i32
750+
#my_dialect.extern : tensor<4xi32>
751+
#my_dialect.extern : !my_dialect.my_type
752+
```
753+
705754
##### Assembly Format Directives
706755

707756
Attribute and type assembly formats have the following directives:

mlir/include/mlir/Dialect/Arithmetic/IR/ArithmeticOps.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ include "mlir/Interfaces/InferIntRangeInterface.td"
1515
include "mlir/Interfaces/InferTypeOpInterface.td"
1616
include "mlir/Interfaces/SideEffectInterfaces.td"
1717
include "mlir/Interfaces/VectorInterfaces.td"
18+
include "mlir/IR/BuiltinAttributeInterfaces.td"
1819
include "mlir/IR/OpAsmInterface.td"
1920

2021
// Base class for Arithmetic dialect ops. Ops in this dialect have no side
@@ -147,7 +148,7 @@ def Arith_ConstantOp : Op<Arithmetic_Dialect, "constant",
147148
```
148149
}];
149150

150-
let arguments = (ins AnyAttr:$value);
151+
let arguments = (ins TypedAttrInterface:$value);
151152
// TODO: Disallow arith.constant to return anything other than a signless
152153
// integer or float like. Downstream users of Arithmetic should only be
153154
// working with signless integers, floats, or vectors/tensors thereof.

mlir/include/mlir/Dialect/CommonFolders.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ Attribute constFoldBinaryOpConditional(ArrayRef<Attribute> operands,
3232
assert(operands.size() == 2 && "binary op takes two operands");
3333
if (!operands[0] || !operands[1])
3434
return {};
35-
if (operands[0].getType() != operands[1].getType())
36-
return {};
3735

3836
if (operands[0].isa<AttrElementT>() && operands[1].isa<AttrElementT>()) {
3937
auto lhs = operands[0].cast<AttrElementT>();
4038
auto rhs = operands[1].cast<AttrElementT>();
39+
if (lhs.getType() != rhs.getType())
40+
return {};
4141

4242
auto calRes = calculate(lhs.getValue(), rhs.getValue());
4343

@@ -53,6 +53,8 @@ Attribute constFoldBinaryOpConditional(ArrayRef<Attribute> operands,
5353
// just fold based on the splat value.
5454
auto lhs = operands[0].cast<SplatElementsAttr>();
5555
auto rhs = operands[1].cast<SplatElementsAttr>();
56+
if (lhs.getType() != rhs.getType())
57+
return {};
5658

5759
auto elementResult = calculate(lhs.getSplatValue<ElementValueT>(),
5860
rhs.getSplatValue<ElementValueT>());
@@ -66,6 +68,8 @@ Attribute constFoldBinaryOpConditional(ArrayRef<Attribute> operands,
6668
// expanding the values.
6769
auto lhs = operands[0].cast<ElementsAttr>();
6870
auto rhs = operands[1].cast<ElementsAttr>();
71+
if (lhs.getType() != rhs.getType())
72+
return {};
6973

7074
auto lhsIt = lhs.value_begin<ElementValueT>();
7175
auto rhsIt = rhs.value_begin<ElementValueT>();

mlir/include/mlir/Dialect/Complex/IR/ComplexAttributes.td

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,21 @@
1010
#define COMPLEX_ATTRIBUTE
1111

1212
include "mlir/IR/AttrTypeBase.td"
13+
include "mlir/IR/BuiltinAttributeInterfaces.td"
1314
include "mlir/Dialect/Complex/IR/ComplexBase.td"
1415

1516
//===----------------------------------------------------------------------===//
1617
// Complex Attributes.
1718
//===----------------------------------------------------------------------===//
1819

19-
class Complex_Attr<string attrName, string attrMnemonic>
20-
: AttrDef<Complex_Dialect, attrName> {
20+
class Complex_Attr<string attrName, string attrMnemonic,
21+
list<Trait> traits = []>
22+
: AttrDef<Complex_Dialect, attrName, traits> {
2123
let mnemonic = attrMnemonic;
2224
}
2325

24-
def Complex_NumberAttr : Complex_Attr<"Number", "number"> {
26+
def Complex_NumberAttr : Complex_Attr<"Number", "number",
27+
[TypedAttrInterface]> {
2528
let summary = "A complex number attribute";
2629

2730
let description = [{

mlir/include/mlir/Dialect/EmitC/IR/EmitC.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def EmitC_ConstantOp : EmitC_Op<"constant", [ConstantLike]> {
139139
```
140140
}];
141141

142-
let arguments = (ins AnyAttr:$value);
142+
let arguments = (ins TypedAttrInterface:$value);
143143
let results = (outs AnyType);
144144

145145
let hasFolder = 1;
@@ -212,7 +212,7 @@ def EmitC_VariableOp : EmitC_Op<"variable", []> {
212212
```
213213
}];
214214

215-
let arguments = (ins AnyAttr:$value);
215+
let arguments = (ins TypedAttrInterface:$value);
216216
let results = (outs AnyType);
217217

218218
let hasVerifier = 1;

mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,19 @@
1414
#define MLIR_DIALECT_EMITC_IR_EMITCATTRIBUTES
1515

1616
include "mlir/IR/AttrTypeBase.td"
17+
include "mlir/IR/BuiltinAttributeInterfaces.td"
1718
include "mlir/Dialect/EmitC/IR/EmitCBase.td"
1819

1920
//===----------------------------------------------------------------------===//
2021
// EmitC attribute definitions
2122
//===----------------------------------------------------------------------===//
2223

23-
class EmitC_Attr<string name, string attrMnemonic>
24-
: AttrDef<EmitC_Dialect, name> {
24+
class EmitC_Attr<string name, string attrMnemonic, list<Trait> traits = []>
25+
: AttrDef<EmitC_Dialect, name, traits> {
2526
let mnemonic = attrMnemonic;
2627
}
2728

28-
def EmitC_OpaqueAttr : EmitC_Attr<"Opaque", "opaque"> {
29+
def EmitC_OpaqueAttr : EmitC_Attr<"Opaque", "opaque", [TypedAttrInterface]> {
2930
let summary = "An opaque attribute";
3031

3132
let description = [{
@@ -40,8 +41,9 @@ def EmitC_OpaqueAttr : EmitC_Attr<"Opaque", "opaque"> {
4041
```
4142
}];
4243

43-
let parameters = (ins StringRefParameter<"the opaque value">:$value);
44-
44+
let parameters = (ins "Type":$type,
45+
StringRefParameter<"the opaque value">:$value);
46+
4547
let hasCustomAssemblyFormat = 1;
4648
}
4749

mlir/include/mlir/Dialect/MLProgram/IR/MLProgramAttributes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define MLIR_DIALECT_MLPROGRAM_IR_MLPROGRAMATTRIBUTES_H_
1111

1212
#include "mlir/IR/Attributes.h"
13+
#include "mlir/IR/BuiltinAttributeInterfaces.h"
1314

1415
//===----------------------------------------------------------------------===//
1516
// Tablegen Attribute Declarations

mlir/include/mlir/Dialect/MLProgram/IR/MLProgramAttributes.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define MLPROGRAM_ATTRIBUTES
1111

1212
include "mlir/IR/AttrTypeBase.td"
13+
include "mlir/IR/BuiltinAttributeInterfaces.td"
1314
include "mlir/Dialect/MLProgram/IR/MLProgramBase.td"
1415

1516
// Base class for MLProgram dialect attributes.
@@ -22,7 +23,7 @@ class MLProgram_Attr<string name, list<Trait> traits = []>
2223
// ExternAttr
2324
//===----------------------------------------------------------------------===//
2425

25-
def MLProgram_ExternAttr : MLProgram_Attr<"Extern"> {
26+
def MLProgram_ExternAttr : MLProgram_Attr<"Extern", [TypedAttrInterface]> {
2627
let summary = "Value used for a global signalling external resolution";
2728
let description = [{
2829
When used as the value for a GlobalOp, this indicates that the actual

mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define MLIR_DIALECT_SPIRV_IR_STRUCTURE_OPS
1717

1818
include "mlir/Dialect/SPIRV/IR/SPIRVBase.td"
19+
include "mlir/IR/BuiltinAttributeInterfaces.td"
1920
include "mlir/IR/FunctionInterfaces.td"
2021
include "mlir/IR/OpAsmInterface.td"
2122
include "mlir/IR/SymbolInterfaces.td"
@@ -600,7 +601,7 @@ def SPV_SpecConstantOp : SPV_Op<"SpecConstant", [InModuleScope, Symbol]> {
600601

601602
let arguments = (ins
602603
StrAttr:$sym_name,
603-
AnyAttr:$default_value
604+
TypedAttrInterface:$default_value
604605
);
605606

606607
let results = (outs);

mlir/include/mlir/IR/AttrTypeBase.td

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -257,14 +257,6 @@ class AttrDef<Dialect dialect, string name, list<Trait> traits = [],
257257
let convertFromStorage = "$_self.cast<" # dialect.cppNamespace #
258258
"::" # cppClassName # ">()";
259259

260-
// A code block used to build the value 'Type' of an Attribute when
261-
// initializing its storage instance. This field is optional, and if not
262-
// present the attribute will have its value type set to `NoneType`. This code
263-
// block may reference any of the attributes parameters via
264-
// `$_<parameter-name`. If one of the parameters of the attribute is of type
265-
// `AttributeSelfTypeParameter`, this field is ignored.
266-
code typeBuilder = ?;
267-
268260
// The predicate for when this def is used as a constraint.
269261
let predicate = CPred<"$_self.isa<" # dialect.cppNamespace #
270262
"::" # cppClassName # ">()">;
@@ -334,7 +326,7 @@ class AttrOrTypeParameter<string type, string desc, string accessorType = ""> {
334326
// which by default is the C++ equality operator. The current MLIR context is
335327
// made available through `$_ctxt`, e.g., for constructing default values for
336328
// attributes and types.
337-
string defaultValue = ?;
329+
string defaultValue = "";
338330
}
339331
class AttrParameter<string type, string desc, string accessorType = "">
340332
: AttrOrTypeParameter<type, desc, accessorType>;
@@ -392,11 +384,21 @@ class DefaultValuedParameter<string type, string value, string desc = ""> :
392384
let defaultValue = value;
393385
}
394386

395-
// This is a special parameter used for AttrDefs that represents a `mlir::Type`
396-
// that is also used as the value `Type` of the attribute. Only one parameter
397-
// of the attribute may be of this type.
387+
// This is a special attribute parameter that represents the "self" type of the
388+
// attribute. It is specially handled by the assembly format generator to derive
389+
// its value from the optional trailing type after each attribute.
390+
//
391+
// By default, the self type parameter is optional and has a default value of
392+
// `none`. If a derived type other than `::mlir::Type` is specified, the
393+
// parameter loses its default value unless another one is specified by
394+
// `typeBuilder`.
398395
class AttributeSelfTypeParameter<string desc,
399-
string derivedType = "::mlir::Type"> :
400-
AttrOrTypeParameter<derivedType, desc> {}
396+
string derivedType = "::mlir::Type",
397+
string typeBuilder = ""> :
398+
AttrOrTypeParameter<derivedType, desc> {
399+
let defaultValue = !if(!and(!empty(typeBuilder),
400+
!eq(derivedType, "::mlir::Type")),
401+
"::mlir::NoneType::get($_ctxt)", typeBuilder);
402+
}
401403

402404
#endif // ATTRTYPEBASE_TD

mlir/include/mlir/IR/AttributeSupport.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -129,25 +129,13 @@ class alignas(8) AttributeStorage : public StorageUniquer::BaseStorage {
129129
friend StorageUniquer;
130130

131131
public:
132-
/// Get the type of this attribute.
133-
Type getType() const { return type; }
134-
135132
/// Return the abstract descriptor for this attribute.
136133
const AbstractAttribute &getAbstractAttribute() const {
137134
assert(abstractAttribute && "Malformed attribute storage object.");
138135
return *abstractAttribute;
139136
}
140137

141138
protected:
142-
/// Construct a new attribute storage instance with the given type.
143-
/// Note: All attributes require a valid type. If no type is provided here,
144-
/// the type of the attribute will automatically default to NoneType
145-
/// upon initialization in the uniquer.
146-
AttributeStorage(Type type = nullptr) : type(type) {}
147-
148-
/// Set the type of this attribute.
149-
void setType(Type newType) { type = newType; }
150-
151139
/// Set the abstract attribute for this storage instance. This is used by the
152140
/// AttributeUniquer when initializing a newly constructed storage object.
153141
void initializeAbstractAttribute(const AbstractAttribute &abstractAttr) {
@@ -159,9 +147,6 @@ class alignas(8) AttributeStorage : public StorageUniquer::BaseStorage {
159147
void initialize(MLIRContext *context) {}
160148

161149
private:
162-
/// The type of the attribute value.
163-
Type type;
164-
165150
/// The abstract descriptor for this attribute.
166151
const AbstractAttribute *abstractAttribute = nullptr;
167152
};

mlir/include/mlir/IR/Attributes.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,6 @@ class Attribute {
6666
/// to support dynamic type casting.
6767
TypeID getTypeID() { return impl->getAbstractAttribute().getTypeID(); }
6868

69-
/// Return the type of this attribute.
70-
Type getType() const { return impl->getType(); }
71-
7269
/// Return the context this attribute belongs to.
7370
MLIRContext *getContext() const;
7471

mlir/include/mlir/IR/BuiltinAttributeInterfaces.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111

1212
#include "mlir/IR/AffineMap.h"
1313
#include "mlir/IR/Attributes.h"
14+
#include "mlir/IR/BuiltinTypeInterfaces.h"
1415
#include "mlir/IR/Types.h"
1516
#include "mlir/Support/LogicalResult.h"
1617
#include "llvm/ADT/Any.h"
1718
#include "llvm/Support/raw_ostream.h"
1819
#include <complex>
1920

2021
namespace mlir {
21-
class ShapedType;
2222

2323
//===----------------------------------------------------------------------===//
2424
// ElementsAttr
@@ -237,10 +237,10 @@ class ElementsAttrRange : public llvm::iterator_range<IteratorT> {
237237
public:
238238
using reference = typename IteratorT::reference;
239239

240-
ElementsAttrRange(Type shapeType,
240+
ElementsAttrRange(ShapedType shapeType,
241241
const llvm::iterator_range<IteratorT> &range)
242242
: llvm::iterator_range<IteratorT>(range), shapeType(shapeType) {}
243-
ElementsAttrRange(Type shapeType, IteratorT beginIt, IteratorT endIt)
243+
ElementsAttrRange(ShapedType shapeType, IteratorT beginIt, IteratorT endIt)
244244
: ElementsAttrRange(shapeType, llvm::make_range(beginIt, endIt)) {}
245245

246246
/// Return the value at the given index.
@@ -254,7 +254,7 @@ class ElementsAttrRange : public llvm::iterator_range<IteratorT> {
254254

255255
private:
256256
/// The shaped type of the parent ElementsAttr.
257-
Type shapeType;
257+
ShapedType shapeType;
258258
};
259259

260260
} // namespace detail

0 commit comments

Comments
 (0)