[Mlir-commits] [mlir] [mlir] Populate properties before parser-time inferReturnTypes (PR #194658)
Zmicier Prybysh
llvmlistbot at llvm.org
Wed May 6 08:19:49 PDT 2026
https://github.com/dimp-pl updated https://github.com/llvm/llvm-project/pull/194658
>From a33e691e0141d4685d0176e2a7352fa0223828fe Mon Sep 17 00:00:00 2001
From: Zmicier Prybysh <zprybysh at baylibre.com>
Date: Wed, 6 May 2026 17:13:09 +0200
Subject: [PATCH] [MLIR] Populate properties from attr-dict at parse time
Fixes #193284.
It's possible to segfault inferReturnTypes when accessing an
attribute that's stored as property under specific conditions:
- Attribute must be inherent.
- `DeclareOpInterfaceMethods<InferTypeOpInterface, ["inferReturnTypes"]>`.
- Attribute is read in `inferReturnTypes` via `Adaptor`.
- Op omits `type($result)` from assembly format.
The fix works by emitting an additional setInherentAttr per each
attribute in `attr-dict` parser after erification step.
---
mlir/test/lib/Dialect/Test/TestOpDefs.cpp | 13 +++++++++++++
mlir/test/lib/Dialect/Test/TestOps.td | 9 +++++++++
mlir/test/mlir-tblgen/op-format.mlir | 4 ++++
mlir/tools/mlir-tblgen/OpFormatGen.cpp | 12 ++++++++++++
4 files changed, 38 insertions(+)
diff --git a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
index 340b44b14dd96..38177d22c8bd0 100644
--- a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
+++ b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
@@ -1295,6 +1295,19 @@ LogicalResult TestOpWithPropertiesAndInferredType::inferReturnTypes(
return success();
}
+//===----------------------------------------------------------------------===//
+// TestOpWithAttrInferredType
+//===----------------------------------------------------------------------===//
+
+LogicalResult TestOpWithAttrInferredType::inferReturnTypes(
+ MLIRContext *context, std::optional<Location>, ValueRange operands,
+ DictionaryAttr attributes, PropertyRef properties, RegionRange regions,
+ SmallVectorImpl<Type> &inferredReturnTypes) {
+ Adaptor adaptor(operands, attributes, properties, regions);
+ inferredReturnTypes.push_back(IntegerType::get(context, adaptor.getLhs()));
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// LoopBlockOp
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td
index 348ff5d7f4ea0..5ac64ada612f7 100644
--- a/mlir/test/lib/Dialect/Test/TestOps.td
+++ b/mlir/test/lib/Dialect/Test/TestOps.td
@@ -3527,6 +3527,15 @@ def TestOpWithPropertiesAndInferredType
let results = (outs AnyType:$result);
}
+def TestOpWithAttrInferredType
+ : TEST_Op<"with_attr_inferred_type", [
+ DeclareOpInterfaceMethods<InferTypeOpInterface, ["inferReturnTypes"]>
+ ]> {
+ let assemblyFormat = "$input attr-dict `:` type($input)";
+ let arguments = (ins I32:$input, I32Attr:$lhs);
+ let results = (outs AnyType:$output);
+}
+
// Demonstrate how to wrap an existing C++ class named MyPropStruct.
def MyStructProperty : Property<"MyPropStruct"> {
let convertToAttribute = "return $_storage.asAttribute($_ctxt);";
diff --git a/mlir/test/mlir-tblgen/op-format.mlir b/mlir/test/mlir-tblgen/op-format.mlir
index 7ff9091d5500d..3e8ee9ed330b4 100644
--- a/mlir/test/mlir-tblgen/op-format.mlir
+++ b/mlir/test/mlir-tblgen/op-format.mlir
@@ -534,6 +534,10 @@ test.with_properties_and_attr 16 <{rhs = 16 : i64}>
// Assert through the verifier that its inferred as i32.
test.format_all_types_match_var %should_be_i32, %i32 : i32
+// CHECK: test.with_attr_inferred_type %[[I32]] {lhs = 32 : i32} : i32
+%attr_inferred_i32 = test.with_attr_inferred_type %i32 {lhs = 32 : i32} : i32
+test.format_all_types_match_var %attr_inferred_i32, %i32 : i32
+
// CHECK: test.using_property_in_custom_and_other [1, 4, 20] <{other = 16 : i64}>
test.using_property_in_custom_and_other [1, 4, 20] <{other = 16 : i64}>
diff --git a/mlir/tools/mlir-tblgen/OpFormatGen.cpp b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
index cbcbc8e9bc102..6f70ce0a42489 100644
--- a/mlir/tools/mlir-tblgen/OpFormatGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
@@ -676,6 +676,17 @@ const char *const inferReturnTypesParserCode = R"(
result.addTypes(inferredReturnTypes);
)";
+/// The code snippet used to copy inherent attributes from
+/// `result.attributes` into the inline properties storage.
+///
+/// {0}: The operation class name.
+const char *const attrDictPopulatePropertiesCode = R"(
+auto &odsAttrDictProps = result.getOrAddProperties<{0}::Properties>();
+for (const ::mlir::NamedAttribute &namedAttr : result.attributes)
+ {0}::setInherentAttr(odsAttrDictProps, namedAttr.getName().getValue(),
+ namedAttr.getValue());
+)";
+
/// The code snippet used to generate a parser call for a region list.
///
/// {0}: The name for the region list.
@@ -1640,6 +1651,7 @@ void OperationFormat::genElementParser(FormatElement *element, MethodBody &body,
"result.name.getStringRef() << \"' op \";\n"
<< " })))\n"
<< " return ::mlir::failure();\n";
+ body << formatv(attrDictPopulatePropertiesCode, opCppClassName);
}
body.unindent() << "}\n";
body.unindent();
More information about the Mlir-commits
mailing list