[Mlir-commits] [mlir] [MLIR][Transform] apply_registered_pass: support ListOptions as params (PR #144026)

Rolf Morel llvmlistbot at llvm.org
Fri Jun 13 00:21:43 PDT 2025


https://github.com/rolfmorel created https://github.com/llvm/llvm-project/pull/144026

Interpret the multiple values associated to a param as a comma-separated list, i.e. as the analog of a ListOption on a pass.

>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] [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}}



More information about the Mlir-commits mailing list