Skip to content

[mlir] load dialect in parser for optional parameters #96667

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 7, 2024

Conversation

j2kun
Copy link
Contributor

@j2kun j2kun commented Jun 25, 2024

#96242 fixed an issue where the auto-generated parsers were not loading dialects whose namespaces are not present in the textual IR. This required the attribute parameter to be a tablegen def with its dialect information attached.

This fails when using parameter wrapper classes like OptionalParameter. This came up because RingAttr uses OptionalParameter for its second and third attributes. OptionalParameter takes as input the C++ type as a string instead of the tablegen def, and so it doesn't have a dialect member value to trigger the fix from #96242. The docs on this topic say the appropriate solution as overloading FieldParser for a particular type.

This PR updates FieldParser for generic attributes to load the dialect on demand. This requires mlir-tblgen to emit a dialectName static field on the generated attribute class, and check for it with template metaprogramming, since not all attribute types go through mlir-tblgen.

@j2kun j2kun requested review from joker-eph and removed request for joker-eph June 25, 2024 17:01
@llvmbot llvmbot added mlir:core MLIR Core Infrastructure mlir labels Jun 25, 2024
@j2kun j2kun marked this pull request as draft June 25, 2024 17:01
@llvmbot
Copy link
Member

llvmbot commented Jun 25, 2024

@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-mlir-core

Author: Jeremy Kun (j2kun)

Changes

Description of problem TBD.


Full diff: https://github.com/llvm/llvm-project/pull/96667.diff

4 Files Affected:

  • (modified) mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp (+15)
  • (modified) mlir/test/IR/parser.mlir (+1-1)
  • (modified) mlir/test/lib/Dialect/Test/TestAttrDefs.td (+2-2)
  • (modified) mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp (+5-3)
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index cc7d3172b1a1d..c13073e807adc 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -205,4 +205,19 @@ Attribute FloatPolynomialAttr::parse(AsmParser &parser, Type type) {
 }
 
 } // namespace polynomial
+
+/// Specialize FieldParser for parsing IntPolynomialAttr. This is required to
+/// support using IntPolynomialAttr in an OptionalParameter.
+template <>
+struct FieldParser<polynomial::IntPolynomialAttr> {
+  static FailureOr<polynomial::IntPolynomialAttr> parse(AsmParser &parser) {
+    parser.getContext()
+        ->getOrLoadDialect<mlir::polynomial::PolynomialDialect>();
+    Attribute polynomialAttr = polynomial::IntPolynomialAttr::parse(parser, {});
+    if (!polynomialAttr)
+      return failure();
+    return cast<polynomial::IntPolynomialAttr>(polynomialAttr);
+  }
+};
+
 } // namespace mlir
diff --git a/mlir/test/IR/parser.mlir b/mlir/test/IR/parser.mlir
index e0d7f2a5dd0cb..dfdfe069d1914 100644
--- a/mlir/test/IR/parser.mlir
+++ b/mlir/test/IR/parser.mlir
@@ -1470,7 +1470,7 @@ test.format_optional_result_d_op : f80
 
 // This is a testing that a non-qualified attribute in a custom format
 // correctly preload the dialect before creating the attribute.
-#attr = #test.nested_polynomial<<1 + x**2>>
+#attr = #test.nested_polynomial<poly=<1 + x**2>>
 // CHECK-lABLE: @parse_correctly
 llvm.func @parse_correctly() {
   test.containing_int_polynomial_attr #attr
diff --git a/mlir/test/lib/Dialect/Test/TestAttrDefs.td b/mlir/test/lib/Dialect/Test/TestAttrDefs.td
index 9e25acf5f5ba4..471b78e489532 100644
--- a/mlir/test/lib/Dialect/Test/TestAttrDefs.td
+++ b/mlir/test/lib/Dialect/Test/TestAttrDefs.td
@@ -354,9 +354,9 @@ def TestCustomFloatAttr : Test_Attr<"TestCustomFloat"> {
 
 def NestedPolynomialAttr : Test_Attr<"NestedPolynomialAttr"> {
   let mnemonic = "nested_polynomial";
-  let parameters = (ins Polynomial_IntPolynomialAttr:$poly);
+  let parameters = (ins OptionalParameter<"::mlir::polynomial::IntPolynomialAttr">:$poly);
   let assemblyFormat = [{
-    `<` $poly `>`
+    `<` struct(params) `>`
   }];
 }
 
diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
index 50378feeb14ed..91c4ce35889b5 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
@@ -424,9 +424,11 @@ void DefFormat::genVariableParser(ParameterElement *el, FmtContext &ctx,
         Dialect dialect(dialectInit->getDef());
         auto cppNamespace = dialect.getCppNamespace();
         std::string name = dialect.getCppClassName();
-        dialectLoading = ("\nodsParser.getContext()->getOrLoadDialect<" +
-                          cppNamespace + "::" + name + ">();")
-                             .str();
+        if (name != "BuiltinDialect" || cppNamespace != "::mlir") {
+          dialectLoading = ("\nodsParser.getContext()->getOrLoadDialect<" +
+                            cppNamespace + "::" + name + ">();")
+                               .str();
+        }
       }
     }
   }

Copy link

⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo.
Please turn off Keep my email addresses private setting in your account.
See LLVM Discourse for more information.

@j2kun j2kun changed the title try fixing optional parameter for dialect loading [mlir] load dialect in parser for optional parameters Jun 25, 2024
@j2kun j2kun force-pushed the polynomial-remove-optional branch from ea127d3 to aaf89f3 Compare June 25, 2024 22:30
@j2kun j2kun marked this pull request as ready for review June 25, 2024 23:00
@j2kun j2kun requested review from joker-eph and ftynse June 25, 2024 23:00
@j2kun j2kun force-pushed the polynomial-remove-optional branch from 585d354 to 26dc3a9 Compare June 28, 2024 17:48
Comment on lines +81 to +83
if constexpr (HasStaticDialectName<AttributeT>::value) {
parser.getContext()->getOrLoadDialect(AttributeT::dialectName);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we complain when the field is missing? This would be the case for attributes defined outside tablegen.

Copy link
Contributor Author

@j2kun j2kun Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean a diagnostic? It seems that quite a few builtin attributes would trigger it (BoolAttr, e.g.,), so I'm not sure what one could do if they saw such a diagnostic... If we want to ensure all attributes have a dialectName string for this purpose, we could add it as a virtual method on Attribute. I don't have a strong opinion, I just tried to do the least invasive solution I could manage.

@@ -112,6 +130,9 @@ struct FieldParser<
std::enable_if_t<std::is_base_of<Attribute, AttributeT>::value,
std::optional<AttributeT>>> {
static FailureOr<std::optional<AttributeT>> parse(AsmParser &parser) {
if constexpr (HasStaticDialectName<AttributeT>::value) {
parser.getContext()->getOrLoadDialect(AttributeT::dialectName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it would be possible to get the TypeID of the attribute class (there should be a static method) and somehow use it to find the dialect instead of relying on the textual name. Not sure if it is possible, I suspect we populate attribute TypeID maps when loading the dialect and here the dialect hasn't been loaded yet...

Copy link
Contributor Author

@j2kun j2kun Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT TypeID is not static on Attribute, nor part of the mlir-tblgen generated code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way you get TypeID is through TypeID::get<DialectClass>().
I would think that if you can generate a dialectName field, you could generate a TypeID one instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I had a generated TypeID, I'm still not sure how I would use it to get the dialect. This method seems to still need the dialect namespace as a string.

dialectLoading = ("\nodsParser.getContext()->getOrLoadDialect<" +
cppNamespace + "::" + name + ">();")
.str();
if (name != "BuiltinDialect" || cppNamespace != "::mlir") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand the second part of the condition. Why don't we want to load the dialect if its namespace starts with ::mlir? These shouldn't be anyhow special.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this condition is the logical negation of name == "BuiltinDialect" && namespace == "::mlir". For some unholy reason, someone might make an out-of-tree dialect called BuiltinDialect in a different namespace. In that case, we would still want to load it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could also alternatively have getOrLoadDialect be aware of BuiltinDialect and handle it specially.

Copy link

github-actions bot commented Jul 3, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@j2kun
Copy link
Contributor Author

j2kun commented Jul 6, 2024

@joker-eph @ftynse anything else needed here?

Copy link
Collaborator

@joker-eph joker-eph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeID would be better than String lookup, but this isn't in the critical path of anything so string may be acceptable here.

@j2kun j2kun merged commit 07c157a into llvm:main Jul 7, 2024
7 checks passed
@j2kun
Copy link
Contributor Author

j2kun commented Jul 8, 2024

I will write a followup PR with the TypeID fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mlir:core MLIR Core Infrastructure mlir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants