[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