-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[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
Conversation
@llvm/pr-subscribers-mlir @llvm/pr-subscribers-mlir-core Author: Jeremy Kun (j2kun) ChangesDescription of problem TBD. Full diff: https://github.com/llvm/llvm-project/pull/96667.diff 4 Files Affected:
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();
+ }
}
}
}
|
|
ea127d3
to
aaf89f3
Compare
585d354
to
26dc3a9
Compare
if constexpr (HasStaticDialectName<AttributeT>::value) { | ||
parser.getContext()->getOrLoadDialect(AttributeT::dialectName); | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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") { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
Co-authored-by: Oleksandr "Alex" Zinenko <[email protected]>
✅ With the latest revision this PR passed the C/C++ code formatter. |
@joker-eph @ftynse anything else needed here? |
There was a problem hiding this 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.
I will write a followup PR with the TypeID fix. |
#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 becauseRingAttr
usesOptionalParameter
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 overloadingFieldParser
for a particular type.This PR updates
FieldParser
for generic attributes to load the dialect on demand. This requiresmlir-tblgen
to emit adialectName
static field on the generated attribute class, and check for it with template metaprogramming, since not all attribute types go throughmlir-tblgen
.