[Mlir-commits] [mlir] [MLIR][Transform] apply_registered_pass: support ListOptions as params (PR #144026)
Rolf Morel
llvmlistbot at llvm.org
Fri Jun 13 00:48:49 PDT 2025
https://github.com/rolfmorel updated https://github.com/llvm/llvm-project/pull/144026
>From 99e4520ee48c39360b03220297e6fb6f0f3e29db Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Fri, 13 Jun 2025 00:13:42 -0700
Subject: [PATCH 1/2] [MLIR][Transform] apply_registered_pass: support
ListOptions as params
Interpret the multiple values associated to a param as a
comma-separated list, i.e. as the analog of a ListOption on a pass.
---
.../lib/Dialect/Transform/IR/TransformOps.cpp | 28 +++++-----
.../Transform/test-pass-application.mlir | 52 ++++++++++++-------
2 files changed, 45 insertions(+), 35 deletions(-)
diff --git a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp
index 582d082153bef..bfe6416987629 100644
--- a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp
+++ b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp
@@ -791,6 +791,12 @@ transform::ApplyRegisteredPassOp::apply(transform::TransformRewriter &rewriter,
std::string options;
llvm::raw_string_ostream optionsStream(options); // For "printing" attrs.
+ auto appendValueAttr = [&](Attribute valueAttr) {
+ if (auto strAttr = dyn_cast<StringAttr>(valueAttr))
+ optionsStream << strAttr.getValue().str();
+ else
+ valueAttr.print(optionsStream, /*elideType=*/true);
+ };
OperandRange dynamicOptions = getDynamicOptions();
for (auto [idx, namedAttribute] : llvm::enumerate(getOptions())) {
@@ -799,7 +805,6 @@ transform::ApplyRegisteredPassOp::apply(transform::TransformRewriter &rewriter,
optionsStream << namedAttribute.getName().str(); // Append the key.
optionsStream << "="; // And the key-value separator.
- Attribute valueAttrToAppend;
if (auto paramOperandIndex =
dyn_cast<transform::ParamOperandAttr>(namedAttribute.getValue())) {
// The corresponding value attribute is passed in via a param.
@@ -810,22 +815,15 @@ transform::ApplyRegisteredPassOp::apply(transform::TransformRewriter &rewriter,
"should be the same as the number of options passed as params");
ArrayRef<Attribute> dynamicOption =
state.getParams(dynamicOptions[dynamicOptionIdx]);
- if (dynamicOption.size() != 1)
- return emitSilenceableError()
- << "options passed as a param must have "
- "a single value associated, param "
- << dynamicOptionIdx << " associates " << dynamicOption.size();
- valueAttrToAppend = dynamicOption[0];
+ // Append all attributes associated to the param, separated by commas.
+ for (auto [idx, associatedAttr] : llvm::enumerate(dynamicOption)) {
+ if (idx > 0)
+ optionsStream << ",";
+ appendValueAttr(associatedAttr);
+ }
} else {
// Value is a static attribute.
- valueAttrToAppend = namedAttribute.getValue();
- }
-
- // Append string representation of value attribute.
- if (auto strAttr = dyn_cast<StringAttr>(valueAttrToAppend)) {
- optionsStream << strAttr.getValue().str();
- } else {
- valueAttrToAppend.print(optionsStream, /*elideType=*/true);
+ appendValueAttr(namedAttribute.getValue());
}
}
optionsStream.flush();
diff --git a/mlir/test/Dialect/Transform/test-pass-application.mlir b/mlir/test/Dialect/Transform/test-pass-application.mlir
index 1d1be9eda3496..407dfa3823436 100644
--- a/mlir/test/Dialect/Transform/test-pass-application.mlir
+++ b/mlir/test/Dialect/Transform/test-pass-application.mlir
@@ -164,6 +164,38 @@ module attributes {transform.with_named_sequence} {
// -----
+// CHECK-LABEL: func private @valid_dynamic_pass_list_option()
+module {
+ func.func @valid_dynamic_pass_list_option() {
+ return
+ }
+
+ // CHECK: func @a()
+ func.func @a() {
+ return
+ }
+ // CHECK: func @b()
+ func.func @b() {
+ return
+ }
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
+ %1 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %2 = transform.get_parent_op %1 { deduplicate } : (!transform.any_op) -> !transform.any_op
+ %symbol_a = transform.param.constant "a" -> !transform.any_param
+ %symbol_b = transform.param.constant "b" -> !transform.any_param
+ %multiple_symbol_names = transform.merge_handles %symbol_a, %symbol_b : !transform.any_param
+ transform.apply_registered_pass "symbol-privatize"
+ with options = { exclude = %multiple_symbol_names } to %2
+ : (!transform.any_op, !transform.any_param) -> !transform.any_op
+ transform.yield
+ }
+}
+
+// -----
+
func.func @invalid_options_as_str() {
return
}
@@ -262,26 +294,6 @@ module attributes {transform.with_named_sequence} {
// -----
-func.func @too_many_pass_option_params() {
- return
-}
-
-module attributes {transform.with_named_sequence} {
- transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
- %1 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
- %x = transform.param.constant true -> !transform.any_param
- %y = transform.param.constant false -> !transform.any_param
- %topdown_options = transform.merge_handles %x, %y : !transform.any_param
- // expected-error @below {{options passed as a param must have a single value associated, param 0 associates 2}}
- transform.apply_registered_pass "canonicalize"
- with options = { "top-down" = %topdown_options } to %1
- : (!transform.any_op, !transform.any_param) -> !transform.any_op
- transform.yield
- }
-}
-
-// -----
-
module attributes {transform.with_named_sequence} {
// expected-error @below {{trying to schedule a pass on an unsupported operation}}
// expected-note @below {{target op}}
>From a54688e6a15b050a923ab2aaf9cb94748603fe16 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Fri, 13 Jun 2025 00:45:10 -0700
Subject: [PATCH 2/2] Also support passing in an ArrayAttr as a ListOption,
also through params
---
.../lib/Dialect/Transform/IR/TransformOps.cpp | 12 +++-
.../Transform/test-pass-application.mlir | 63 ++++++++++++++++++-
2 files changed, 70 insertions(+), 5 deletions(-)
diff --git a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp
index bfe6416987629..0538faf5b3ba8 100644
--- a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp
+++ b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp
@@ -791,11 +791,17 @@ transform::ApplyRegisteredPassOp::apply(transform::TransformRewriter &rewriter,
std::string options;
llvm::raw_string_ostream optionsStream(options); // For "printing" attrs.
- auto appendValueAttr = [&](Attribute valueAttr) {
- if (auto strAttr = dyn_cast<StringAttr>(valueAttr))
+ std::function<void(Attribute)> appendValueAttr = [&](Attribute valueAttr) {
+ if (auto arrayAttr = dyn_cast<ArrayAttr>(valueAttr)) {
+ for (auto [idx, eltAttr] : llvm::enumerate(arrayAttr)) {
+ appendValueAttr(eltAttr);
+ optionsStream << ",";
+ }
+ } else if (auto strAttr = dyn_cast<StringAttr>(valueAttr)) {
optionsStream << strAttr.getValue().str();
- else
+ } else {
valueAttr.print(optionsStream, /*elideType=*/true);
+ }
};
OperandRange dynamicOptions = getDynamicOptions();
diff --git a/mlir/test/Dialect/Transform/test-pass-application.mlir b/mlir/test/Dialect/Transform/test-pass-application.mlir
index 407dfa3823436..f7909f4c035d9 100644
--- a/mlir/test/Dialect/Transform/test-pass-application.mlir
+++ b/mlir/test/Dialect/Transform/test-pass-application.mlir
@@ -164,9 +164,9 @@ module attributes {transform.with_named_sequence} {
// -----
-// CHECK-LABEL: func private @valid_dynamic_pass_list_option()
+// CHECK-LABEL: func private @valid_multiple_params_as_list_option()
module {
- func.func @valid_dynamic_pass_list_option() {
+ func.func @valid_multiple_params_as_list_option() {
return
}
@@ -196,6 +196,65 @@ module attributes {transform.with_named_sequence} {
// -----
+// CHECK-LABEL: func private @valid_array_attr_as_list_option()
+module {
+ func.func @valid_array_attr_param_as_list_option() {
+ return
+ }
+
+ // CHECK: func @a()
+ func.func @a() {
+ return
+ }
+ // CHECK: func @b()
+ func.func @b() {
+ return
+ }
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
+ %1 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %2 = transform.get_parent_op %1 { deduplicate } : (!transform.any_op) -> !transform.any_op
+ transform.apply_registered_pass "symbol-privatize"
+ with options = { exclude = ["a", "b"] } to %2
+ : (!transform.any_op) -> !transform.any_op
+ transform.yield
+ }
+}
+
+// -----
+
+// CHECK-LABEL: func private @valid_array_attr_param_as_list_option()
+module {
+ func.func @valid_array_attr_param_as_list_option() {
+ return
+ }
+
+ // CHECK: func @a()
+ func.func @a() {
+ return
+ }
+ // CHECK: func @b()
+ func.func @b() {
+ return
+ }
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
+ %1 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+ %2 = transform.get_parent_op %1 { deduplicate } : (!transform.any_op) -> !transform.any_op
+ %multiple_symbol_names = transform.param.constant ["a","b"] -> !transform.any_param
+ transform.apply_registered_pass "symbol-privatize"
+ with options = { exclude = %multiple_symbol_names } to %2
+ : (!transform.any_op, !transform.any_param) -> !transform.any_op
+ transform.yield
+ }
+}
+
+// -----
+
func.func @invalid_options_as_str() {
return
}
More information about the Mlir-commits
mailing list