[Mlir-commits] [mlir] [MLIR][TableGen] Add genMnemonicAlias field for OpAsm{Type, Attr}Interface (PR #131504)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sun Mar 16 00:27:23 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-ods
@llvm/pr-subscribers-mlir
Author: Hongren Zheng (ZenithalHourlyRate)
<details>
<summary>Changes</summary>
Since the introduction of `OpAsm{Type,Attr}Interface` (#<!-- -->121187), it is possible to generate alias in AsmPrinter solely from the type/attribute itself without consulting the `OpAsmDialectInterface`. This means the behavior can be put in tablegen file near the type/attribute definition.
A common pattern is to just use the type/attr mnemonic as the alias. Previously, like #<!-- -->130479/#<!-- -->130481/#<!-- -->130483, this means adding a default implementation to `extraClassDeclaration` in `LLVM_Attr` base class. However, as attribute definition may override `extraClassDeclaration`, it might be preferred to have a new field in tablegen to specify this behavior.
This commit adds a `genMnemonicAlias` field to `AttrOrTypeDef`, when enabled, makes `mlir-tblgen` emit a default implementation of `getAlias` using mnemonic.
For users wanting other alias behavior, they can ignore such field and still use `extraClassDeclaration` way.
One caveat is that to make it actually work, user like `LLVM_Attr` still need to specify `OpAsmAttrInterface` in its trait list. I could not find an elegant way to append the trait conditionally in `AttrOrTypeDef`. One trial is
```diff
- list<Trait> traits = defTraits;
+ list<Trait> traits = defTraits #
+ !if(!eq(genMnemonicAlias, 1),
+ !if(!eq(valueType, "Attr"),
+ [NativeTrait<"OpAsmAttrInterface", "OpAsmAttrInterface">],
+ [NativeTrait<"OpAsmTypeInterface", "OpAsmTypeInterface">]),
+ []);
```
but it did not work.
I think the requirement of dialect users adding the `OpAsmAttrInterface` manually to its trait list is acceptable enough as they already need to enable `genMnemonicAlias`.
Another question might be, why not making the default implementation in `OpAsmInterface.td`. They reason is that mnemonic alias behavior should be opt-in. For `OpAsmTypeInterface`, it has two methods `getAsmName` and `getAlias`. If such behavior is the default, users may only want `getAsmName` method then accidentally find MLIR also generates alias for them.
---
Full diff: https://github.com/llvm/llvm-project/pull/131504.diff
5 Files Affected:
- (modified) mlir/include/mlir/IR/AttrTypeBase.td (+3)
- (modified) mlir/include/mlir/TableGen/AttrOrTypeDef.h (+4)
- (modified) mlir/lib/TableGen/AttrOrTypeDef.cpp (+4)
- (modified) mlir/test/mlir-tblgen/attrdefs.td (+13)
- (modified) mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp (+26)
``````````diff
diff --git a/mlir/include/mlir/IR/AttrTypeBase.td b/mlir/include/mlir/IR/AttrTypeBase.td
index 38d38cf098df3..7ea82879bfdcd 100644
--- a/mlir/include/mlir/IR/AttrTypeBase.td
+++ b/mlir/include/mlir/IR/AttrTypeBase.td
@@ -249,6 +249,9 @@ class AttrOrTypeDef<string valueType, string name, list<Trait> defTraits,
// generated code is placed inside the class's C++ namespace. `$cppClass` is
// replaced by the class name.
code extraClassDefinition = [{}];
+
+ // Generate a default 'getAlias' method for OpAsm{Type,Attr}Interface.
+ bit genMnemonicAlias = 0;
}
// Define a new attribute, named `name`, belonging to `dialect` that inherits
diff --git a/mlir/include/mlir/TableGen/AttrOrTypeDef.h b/mlir/include/mlir/TableGen/AttrOrTypeDef.h
index c3d730e42ef70..dd811557c065e 100644
--- a/mlir/include/mlir/TableGen/AttrOrTypeDef.h
+++ b/mlir/include/mlir/TableGen/AttrOrTypeDef.h
@@ -212,6 +212,10 @@ class AttrOrTypeDef {
/// Returns the def's extra class definition code.
std::optional<StringRef> getExtraDefs() const;
+ /// Returns true if we need to generate a default 'getAlias' implementation
+ /// using the mnemonic.
+ bool genMnemonicAlias() const;
+
/// Get the code location (for error printing).
ArrayRef<SMLoc> getLoc() const;
diff --git a/mlir/lib/TableGen/AttrOrTypeDef.cpp b/mlir/lib/TableGen/AttrOrTypeDef.cpp
index 9e8f789d71b5e..5f77e413c9368 100644
--- a/mlir/lib/TableGen/AttrOrTypeDef.cpp
+++ b/mlir/lib/TableGen/AttrOrTypeDef.cpp
@@ -205,6 +205,10 @@ std::optional<StringRef> AttrOrTypeDef::getExtraDefs() const {
return value.empty() ? std::optional<StringRef>() : value;
}
+bool AttrOrTypeDef::genMnemonicAlias() const {
+ return def->getValueAsBit("genMnemonicAlias");
+}
+
ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); }
bool AttrOrTypeDef::skipDefaultBuilders() const {
diff --git a/mlir/test/mlir-tblgen/attrdefs.td b/mlir/test/mlir-tblgen/attrdefs.td
index 35d2c49619ee6..95a53a4aade48 100644
--- a/mlir/test/mlir-tblgen/attrdefs.td
+++ b/mlir/test/mlir-tblgen/attrdefs.td
@@ -172,3 +172,16 @@ def H_TestExtraClassAttr : TestAttr<"TestExtraClass"> {
// DEF-LABEL: int TestExtraClassAttr::getFoo(int i) {
// DEF: return i+1;
// DEF-NEXT: }
+
+def I_TestGenMnemonicAliasAttr : TestAttr<"TestGenMnemonicAlias"> {
+ let mnemonic = "test_gen_mnemonic_alias";
+ let genMnemonicAlias = 1;
+}
+
+// DECL-LABEL: class TestGenMnemonicAliasAttr : public ::mlir::Attribute
+// DECL: ::mlir::OpAsmAliasResult getAlias(::llvm::raw_ostream &os) const;
+
+// DEF-LABEL: ::mlir::OpAsmAliasResult TestGenMnemonicAliasAttr::getAlias(::llvm::raw_ostream &os) const {
+// DEF-NEXT: os << "test_gen_mnemonic_alias";
+// DEF-NEXT: return ::mlir::OpAsmAliasResult::OverridableAlias;
+// DEF-NEXT: }
diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
index 6a39424bd463f..ad6e3daa8fa40 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
@@ -130,6 +130,12 @@ class DefGen {
/// Emit a trait method.
void emitTraitMethod(const InterfaceMethod &method);
+ //===--------------------------------------------------------------------===//
+ // OpAsm{Type,Attr}Interface Default Method Emission
+
+ /// Emit 'getAlias' method using mnemonic as alias.
+ void emitMnemonicAliasMethod();
+
//===--------------------------------------------------------------------===//
// Storage Class Emission
void emitStorageClass();
@@ -215,6 +221,9 @@ DefGen::DefGen(const AttrOrTypeDef &def)
emitAccessors();
// Emit trait interface methods
emitInterfaceMethods();
+ // Emit OpAsm{Type,Attr}Interface default methods
+ if (def.genMnemonicAlias())
+ emitMnemonicAliasMethod();
defCls.finalize();
// Emit a storage class if one is needed
if (storageCls && def.genStorageClass())
@@ -576,6 +585,23 @@ void DefGen::emitTraitMethod(const InterfaceMethod &method) {
std::move(params));
}
+//===----------------------------------------------------------------------===//
+// OpAsm{Type,Attr}Interface Default Method Emission
+
+void DefGen::emitMnemonicAliasMethod() {
+ // If the mnemonic is not set, there is nothing to do.
+ if (!def.getMnemonic()) {
+ return;
+ }
+
+ // Emit the mnemonic alias method.
+ SmallVector<MethodParameter> params{{"::llvm::raw_ostream &", "os"}};
+ Method *m = defCls.addMethod<Method::Const>("::mlir::OpAsmAliasResult",
+ "getAlias", std::move(params));
+ m->body().indent() << strfmt("os << \"{0}\";\n", *def.getMnemonic())
+ << "return ::mlir::OpAsmAliasResult::OverridableAlias;\n";
+}
+
//===----------------------------------------------------------------------===//
// Storage Class Emission
``````````
</details>
https://github.com/llvm/llvm-project/pull/131504
More information about the Mlir-commits
mailing list