Skip to content

Commit a6530cb

Browse files
[MLIR][TableGen] Add genMnemonicAlias field for OpAsm{Type,Attr}Interface
1 parent 0505e37 commit a6530cb

File tree

9 files changed

+117
-5
lines changed

9 files changed

+117
-5
lines changed

mlir/docs/DefiningDialects/AttributesAndTypes.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ def My_IntegerType : MyDialect_Type<"Integer", "int"> {
105105
106106
/// Indicate that our type will add additional verification to the parameters.
107107
let genVerifyDecl = 1;
108+
109+
/// Indicate that our type will use the mnemonic as alias in assembly.
110+
let genMnemonicAlias = 1;
108111
}
109112
```
110113

@@ -160,6 +163,9 @@ def My_IntegerAttr : MyDialect_Attr<"Integer", "int"> {
160163
/// Indicate to the ODS generator that we do not want the default builders,
161164
/// as we have defined our own simpler ones.
162165
let skipDefaultBuilders = 1;
166+
167+
/// Indicate that our attribute will use the mnemonic as alias in assembly.
168+
let genMnemonicAlias = 1;
163169
}
164170
```
165171

@@ -1189,6 +1195,13 @@ Note that these are mechanisms intended for long-tail cases by power users; for
11891195
not-yet-implemented widely-applicable cases, improving the infrastructure is
11901196
preferable.
11911197
1198+
### Mnemonic Alias in Assembly
1199+
1200+
Attribute and Type can use aliases in the assembly to reduce verbosity.
1201+
In such cases, `OpAsmAttrInterface` and `OpAsmTypeInterface` can be used to generate aliases.
1202+
Often, a simple mnemonic alias is enough; then enabling `genMnemonicAlias` automatically
1203+
generates an `getAlias` implementation using the Attribute or Type's mnemonic.
1204+
11921205
### Registering with the Dialect
11931206
11941207
Once the attributes and types have been defined, they must then be registered

mlir/include/mlir/IR/AttrTypeBase.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@ class AttrOrTypeDef<string valueType, string name, list<Trait> defTraits,
249249
// generated code is placed inside the class's C++ namespace. `$cppClass` is
250250
// replaced by the class name.
251251
code extraClassDefinition = [{}];
252+
253+
// Generate a default 'getAlias' method for OpAsm{Type,Attr}Interface.
254+
bit genMnemonicAlias = 0;
252255
}
253256

254257
// Define a new attribute, named `name`, belonging to `dialect` that inherits

mlir/include/mlir/TableGen/AttrOrTypeDef.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ class AttrOrTypeDef {
216216
/// Returns the def's extra class definition code.
217217
std::optional<StringRef> getExtraDefs() const;
218218

219+
/// Returns true if we need to generate a default 'getAlias' implementation
220+
/// using the mnemonic.
221+
bool genMnemonicAlias() const;
222+
219223
/// Get the code location (for error printing).
220224
ArrayRef<SMLoc> getLoc() const;
221225

mlir/lib/TableGen/AttrOrTypeDef.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ std::optional<StringRef> AttrOrTypeDef::getExtraDefs() const {
205205
return value.empty() ? std::optional<StringRef>() : value;
206206
}
207207

208+
bool AttrOrTypeDef::genMnemonicAlias() const {
209+
return def->getValueAsBit("genMnemonicAlias");
210+
}
211+
208212
ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); }
209213

210214
bool AttrOrTypeDef::skipDefaultBuilders() const {

mlir/test/IR/op-asm-interface.mlir

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ func.func @alias_from_op_asm_type_interface() {
7171

7272
// -----
7373

74+
// CHECK: !op_asm_type_interface_tablegen_default =
75+
!type = !test.op_asm_type_interface_tablegen_default
76+
77+
func.func @alias_from_op_asm_type_interface_tablegen_default() {
78+
%0 = "test.result_name_from_type"() : () -> !type
79+
return
80+
}
81+
82+
// -----
83+
7484
//===----------------------------------------------------------------------===//
7585
// Test OpAsmAttrInterface
7686
//===----------------------------------------------------------------------===//
@@ -82,3 +92,13 @@ func.func @test_op_asm_attr_interface() {
8292
%1 = "test.result_name_from_type"() {attr = #attr} : () -> !test.op_asm_type_interface
8393
return
8494
}
95+
96+
// -----
97+
98+
// CHECK: #op_asm_attr_interface_tablegen_default
99+
#attr = #test.op_asm_attr_interface_tablegen_default<value = "test">
100+
101+
func.func @test_op_asm_attr_interface() {
102+
%1 = "test.result_name_from_type"() {attr = #attr} : () -> !test.op_asm_type_interface
103+
return
104+
}

mlir/test/lib/Dialect/Test/TestAttrDefs.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,4 +424,15 @@ def TestOpAsmAttrInterfaceAttr : Test_Attr<"TestOpAsmAttrInterface",
424424
}];
425425
}
426426

427+
// Test OpAsmAttrInterface from tablegen genMnemonicAlias option.
428+
def TestOpAsmAttrInterfaceTablegenDefaultAttr : Test_Attr<"TestOpAsmAttrInterfaceTablegenDefault"> {
429+
let mnemonic = "op_asm_attr_interface_tablegen_default";
430+
let parameters = (ins "mlir::StringAttr":$value);
431+
let assemblyFormat = [{
432+
`<` struct(params) `>`
433+
}];
434+
435+
let genMnemonicAlias = 1;
436+
}
437+
427438
#endif // TEST_ATTRDEFS

mlir/test/lib/Dialect/Test/TestTypeDefs.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,11 @@ def TestTypeOpAsmTypeInterface : Test_Type<"TestTypeOpAsmTypeInterface",
404404
let mnemonic = "op_asm_type_interface";
405405
}
406406

407+
def TestTypeOpAsmTypeInterfaceTablegenDefault : Test_Type<"TestTypeOpAsmTypeInterfaceTablegenDefault"> {
408+
let mnemonic = "op_asm_type_interface_tablegen_default";
409+
let genMnemonicAlias = 1;
410+
}
411+
407412
def TestTensorType : Test_Type<"TestTensor",
408413
[Bufferization_TensorLikeTypeInterface, ShapedTypeInterface]> {
409414
let mnemonic = "test_tensor";

mlir/test/mlir-tblgen/attrdefs.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,17 @@ def H_TestExtraClassAttr : TestAttr<"TestExtraClass"> {
172172
// DEF-LABEL: int TestExtraClassAttr::getFoo(int i) {
173173
// DEF: return i+1;
174174
// DEF-NEXT: }
175+
176+
def I_TestGenMnemonicAliasAttr : TestAttr<"TestGenMnemonicAlias"> {
177+
let mnemonic = "test_gen_mnemonic_alias";
178+
let genMnemonicAlias = 1;
179+
}
180+
181+
// DECL-LABEL: class TestGenMnemonicAliasAttr : public ::mlir::Attribute
182+
// DECL-SAME: ::mlir::OpAsmAttrInterface::Trait
183+
// DECL: ::mlir::OpAsmAliasResult getAlias(::llvm::raw_ostream &os) const;
184+
185+
// DEF-LABEL: ::mlir::OpAsmAliasResult TestGenMnemonicAliasAttr::getAlias(::llvm::raw_ostream &os) const {
186+
// DEF-NEXT: os << "test_gen_mnemonic_alias";
187+
// DEF-NEXT: return ::mlir::OpAsmAliasResult::OverridableAlias;
188+
// DEF-NEXT: }

mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ class DefGen {
130130
/// Emit a trait method.
131131
void emitTraitMethod(const InterfaceMethod &method);
132132

133+
//===--------------------------------------------------------------------===//
134+
// OpAsm{Type,Attr}Interface Default Method Emission
135+
136+
/// Emit 'getAlias' method using mnemonic as alias.
137+
void emitMnemonicAliasMethod();
138+
133139
//===--------------------------------------------------------------------===//
134140
// Storage Class Emission
135141
void emitStorageClass();
@@ -215,6 +221,9 @@ DefGen::DefGen(const AttrOrTypeDef &def)
215221
emitAccessors();
216222
// Emit trait interface methods
217223
emitInterfaceMethods();
224+
// Emit OpAsm{Type,Attr}Interface default methods
225+
if (def.genMnemonicAlias())
226+
emitMnemonicAliasMethod();
218227
defCls.finalize();
219228
// Emit a storage class if one is needed
220229
if (storageCls && def.genStorageClass())
@@ -229,11 +238,24 @@ void DefGen::createParentWithTraits() {
229238
? strfmt("{0}::{1}", def.getStorageNamespace(),
230239
def.getStorageClassName())
231240
: strfmt("::mlir::{0}Storage", valueType));
232-
for (auto &trait : def.getTraits()) {
233-
defParent.addTemplateParam(
234-
isa<NativeTrait>(&trait)
235-
? cast<NativeTrait>(&trait)->getFullyQualifiedTraitName()
236-
: cast<InterfaceTrait>(&trait)->getFullyQualifiedTraitName());
241+
SmallVector<std::string> traitNames =
242+
llvm::to_vector(llvm::map_range(def.getTraits(), [](auto &trait) {
243+
return isa<NativeTrait>(&trait)
244+
? cast<NativeTrait>(&trait)->getFullyQualifiedTraitName()
245+
: cast<InterfaceTrait>(&trait)->getFullyQualifiedTraitName();
246+
}));
247+
llvm::for_each(traitNames, [&](auto &traitName) {
248+
defParent.addTemplateParam(traitName);
249+
});
250+
251+
// Add OpAsmInterface::Trait if we automatically generate mnemonic alias
252+
// method.
253+
std::string opAsmInterfaceTraitName =
254+
strfmt("::mlir::OpAsm{0}Interface::Trait", defType);
255+
if (def.genMnemonicAlias() && llvm::none_of(traitNames, [&](auto &traitName) {
256+
return traitName == opAsmInterfaceTraitName;
257+
})) {
258+
defParent.addTemplateParam(opAsmInterfaceTraitName);
237259
}
238260
defCls.addParent(std::move(defParent));
239261
}
@@ -577,6 +599,22 @@ void DefGen::emitTraitMethod(const InterfaceMethod &method) {
577599
std::move(params));
578600
}
579601

602+
//===----------------------------------------------------------------------===//
603+
// OpAsm{Type,Attr}Interface Default Method Emission
604+
605+
void DefGen::emitMnemonicAliasMethod() {
606+
// If the mnemonic is not set, there is nothing to do.
607+
if (!def.getMnemonic())
608+
return;
609+
610+
// Emit the mnemonic alias method.
611+
SmallVector<MethodParameter> params{{"::llvm::raw_ostream &", "os"}};
612+
Method *m = defCls.addMethod<Method::Const>("::mlir::OpAsmAliasResult",
613+
"getAlias", std::move(params));
614+
m->body().indent() << strfmt("os << \"{0}\";\n", *def.getMnemonic())
615+
<< "return ::mlir::OpAsmAliasResult::OverridableAlias;\n";
616+
}
617+
580618
//===----------------------------------------------------------------------===//
581619
// Storage Class Emission
582620
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)