[Mlir-commits] [mlir] [MLIR][TableGen] Add genMnemonicAlias field for OpAsm{Type, Attr}Interface (PR #131504)
Hongren Zheng
llvmlistbot at llvm.org
Fri Apr 11 06:56:31 PDT 2025
https://github.com/ZenithalHourlyRate updated https://github.com/llvm/llvm-project/pull/131504
>From 9e32afec73309133cc1278d58bd4959bb2ee3ef7 Mon Sep 17 00:00:00 2001
From: Zenithal <i at zenithal.me>
Date: Sun, 16 Mar 2025 06:44:20 +0000
Subject: [PATCH] [MLIR][TableGen] Add genMnemonicAlias field for
OpAsm{Type,Attr}Interface
---
.../DefiningDialects/AttributesAndTypes.md | 14 ++++++
mlir/include/mlir/IR/AttrTypeBase.td | 3 ++
mlir/include/mlir/TableGen/AttrOrTypeDef.h | 4 ++
mlir/lib/TableGen/AttrOrTypeDef.cpp | 4 ++
mlir/test/mlir-tblgen/attrdefs.td | 14 ++++++
mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp | 48 +++++++++++++++++--
6 files changed, 82 insertions(+), 5 deletions(-)
diff --git a/mlir/docs/DefiningDialects/AttributesAndTypes.md b/mlir/docs/DefiningDialects/AttributesAndTypes.md
index 44be4c8ed3dcc..3612d4dc9d051 100644
--- a/mlir/docs/DefiningDialects/AttributesAndTypes.md
+++ b/mlir/docs/DefiningDialects/AttributesAndTypes.md
@@ -105,6 +105,9 @@ def My_IntegerType : MyDialect_Type<"Integer", "int"> {
/// Indicate that our type will add additional verification to the parameters.
let genVerifyDecl = 1;
+
+ /// Indicate that our type will use the mnemonic as alias in assembly.
+ let genMnemonicAlias = 1;
}
```
@@ -160,6 +163,9 @@ def My_IntegerAttr : MyDialect_Attr<"Integer", "int"> {
/// Indicate to the ODS generator that we do not want the default builders,
/// as we have defined our own simpler ones.
let skipDefaultBuilders = 1;
+
+ /// Indicate that our attribute will use the mnemonic as alias in assembly.
+ let genMnemonicAlias = 1;
}
```
@@ -1182,6 +1188,14 @@ Note that these are mechanisms intended for long-tail cases by power users; for
not-yet-implemented widely-applicable cases, improving the infrastructure is
preferable.
+### Mnemonic Alias in Assembly
+
+Attribute and Type might want to use aliases in the assembly to reduce verbosity.
+In such cases, `OpAsmAttrInterface` and `OpAsmTypeInterface` could be used to
+generate aliases. In many cases, a simple mnemonic alias is enough, then
+`genMnemonicAlias` could be turned on to automatically generate
+an `getAlias` implementation using the `mnemonic` of the Attribute or Type.
+
### Registering with the Dialect
Once the attributes and types have been defined, they must then be registered
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..adec90dc5a371 100644
--- a/mlir/test/mlir-tblgen/attrdefs.td
+++ b/mlir/test/mlir-tblgen/attrdefs.td
@@ -172,3 +172,17 @@ 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-SAME: ::mlir::OpAsmAttrInterface::Trait
+// 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 cf0d827942949..a5df8a69463fe 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())
@@ -229,11 +238,24 @@ void DefGen::createParentWithTraits() {
? strfmt("{0}::{1}", def.getStorageNamespace(),
def.getStorageClassName())
: strfmt("::mlir::{0}Storage", valueType));
- for (auto &trait : def.getTraits()) {
- defParent.addTemplateParam(
- isa<NativeTrait>(&trait)
- ? cast<NativeTrait>(&trait)->getFullyQualifiedTraitName()
- : cast<InterfaceTrait>(&trait)->getFullyQualifiedTraitName());
+ SmallVector<std::string> traitNames =
+ llvm::to_vector(llvm::map_range(def.getTraits(), [](auto &trait) {
+ return isa<NativeTrait>(&trait)
+ ? cast<NativeTrait>(&trait)->getFullyQualifiedTraitName()
+ : cast<InterfaceTrait>(&trait)->getFullyQualifiedTraitName();
+ }));
+ llvm::for_each(traitNames, [&](auto &traitName) {
+ defParent.addTemplateParam(traitName);
+ });
+
+ // Add OpAsmInterface::Trait if we automatically generate mnemonic alias
+ // method.
+ std::string opAsmInterfaceTraitName =
+ strfmt("::mlir::OpAsm{0}Interface::Trait", defType);
+ if (def.genMnemonicAlias() && llvm::none_of(traitNames, [&](auto &traitName) {
+ return traitName == opAsmInterfaceTraitName;
+ })) {
+ defParent.addTemplateParam(opAsmInterfaceTraitName);
}
defCls.addParent(std::move(defParent));
}
@@ -577,6 +599,22 @@ 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
//===----------------------------------------------------------------------===//
More information about the Mlir-commits
mailing list