[Mlir-commits] [mlir] [MLIR][BufferResultsToOutParamsPass] Add Option to Modify Public Function's Signature (PR #167248)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sun Nov 9 12:55:00 PST 2025


https://github.com/veera-sivarajan created https://github.com/llvm/llvm-project/pull/167248

Since https://github.com/llvm/llvm-project/pull/162441, `buffer-results-to-out-params` transforms `private` functions only.

But, as mentioned in https://github.com/llvm/llvm-project/pull/162441#issuecomment-3404195242, this is a breaking change for pipelines compiling C code. Our pipeline @EfficientComputer is also affected by this breaking change.

Therefore, this PR adds a opt-in flag to allow `public` functions to be transformed by `BufferResultsToOutParamsPass`.

>From e908cc0d6990377c4015aa7193a50ed65ea720b6 Mon Sep 17 00:00:00 2001
From: Veera <sveera.2001 at gmail.com>
Date: Sun, 9 Nov 2025 19:49:38 +0000
Subject: [PATCH 1/2] Add Test

---
 ...to-out-params-modify-public-functions.mlir | 36 +++++++++++++++++++
 1 file changed, 36 insertions(+)
 create mode 100644 mlir/test/Transforms/buffer-results-to-out-params-modify-public-functions.mlir

diff --git a/mlir/test/Transforms/buffer-results-to-out-params-modify-public-functions.mlir b/mlir/test/Transforms/buffer-results-to-out-params-modify-public-functions.mlir
new file mode 100644
index 0000000000000..a2462bffeee25
--- /dev/null
+++ b/mlir/test/Transforms/buffer-results-to-out-params-modify-public-functions.mlir
@@ -0,0 +1,36 @@
+// RUN: mlir-opt -buffer-results-to-out-params  %s | FileCheck %s
+
+// Test if `public` functions' return values are transformed into out parameters
+// when `buffer-results-to-out-params` is invoked with `modifyPublicFunctions`.
+
+
+// CHECK-LABEL:   func.func @basic() -> memref<f32> {
+// CHECK:           %[[VAL_0:.*]] = "test.source"() : () -> memref<f32>
+// CHECK:           return %[[VAL_0]] : memref<f32>
+// CHECK:         }
+func.func @basic() -> (memref<f32>) {
+  %0 = "test.source"() : () -> (memref<f32>)
+  return %0 : memref<f32>
+}
+
+// CHECK-LABEL:   func.func @presence_of_existing_arguments(
+// CHECK-SAME:      %[[ARG0:.*]]: memref<1xf32>) -> memref<2xf32> {
+// CHECK:           %[[VAL_0:.*]] = "test.source"() : () -> memref<2xf32>
+// CHECK:           return %[[VAL_0]] : memref<2xf32>
+// CHECK:         }
+func.func @presence_of_existing_arguments(%arg0: memref<1xf32>) -> (memref<2xf32>) {
+  %0 = "test.source"() : () -> (memref<2xf32>)
+  return %0 : memref<2xf32>
+}
+
+// CHECK-LABEL:   func.func @multiple_results() -> (memref<1xf32>, memref<2xf32>) {
+// CHECK:           %[[VAL_0:.*]]:2 = "test.source"() : () -> (memref<1xf32>, memref<2xf32>)
+// CHECK:           return %[[VAL_0]]#0, %[[VAL_0]]#1 : memref<1xf32>, memref<2xf32>
+// CHECK:         }
+func.func @multiple_results() -> (memref<1xf32>, memref<2xf32>) {
+  %0, %1 = "test.source"() : () -> (memref<1xf32>, memref<2xf32>)
+  return %0, %1 : memref<1xf32>, memref<2xf32>
+}
+
+
+

>From d22137e5569045c74bb65c2e7e92a883b74bdbcb Mon Sep 17 00:00:00 2001
From: Veera <sveera.2001 at gmail.com>
Date: Sun, 9 Nov 2025 20:25:05 +0000
Subject: [PATCH 2/2] [MLIR][BufferResultsToOutParamsPass] Add Option to Modify
 Public Function's Signature

---
 .../Dialect/Bufferization/Transforms/Passes.h |  3 +++
 .../Bufferization/Transforms/Passes.td        |  3 +++
 .../Transforms/BufferResultsToOutParams.cpp   | 10 +++++--
 ...to-out-params-modify-public-functions.mlir | 26 +++++++++++--------
 4 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
index 67ac487d8226d..ea158914e445b 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
@@ -171,6 +171,9 @@ struct BufferResultsToOutParamsOpts {
   /// If true, the pass eliminates the memref.alloc and memcpy if the returned
   /// memref is allocated in the current function and has dynamic shape.
   bool hoistDynamicAllocs = false;
+
+  /// If true, the pass modifies the function signatures of public functions.
+  bool modifyPublicFunctions = false;
 };
 
 /// Replace buffers that are returned from a function with an out parameter.
diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
index cad44cb15f479..1eb692586bcfc 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
@@ -258,6 +258,9 @@ def BufferResultsToOutParamsPass
               /*default=*/"false", "Hoist static allocations to call sites.">,
        Option<"hoistDynamicAllocs", "hoist-dynamic-allocs", "bool",
               /*default=*/"false", "Hoist dynamic allocations to call sites.">,
+       Option<"modifyPublicFunctions", "modify-public-functions", "bool",
+              /*default=*/"false", "Modify function signatures of public "
+              "functions.">,
   ];
   let dependentDialects = ["memref::MemRefDialect"];
 }
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/BufferResultsToOutParams.cpp b/mlir/lib/Dialect/Bufferization/Transforms/BufferResultsToOutParams.cpp
index b9ee0a4d401f3..d0742ec27ed60 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/BufferResultsToOutParams.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/BufferResultsToOutParams.cpp
@@ -217,7 +217,9 @@ updateCalls(ModuleOp module, const AllocDynamicSizesMap &map,
     }
     if (!options.filterFn(&callee))
       return;
-    if (callee.isExternal() || callee.isPublic())
+    if (callee.isPublic() && !options.modifyPublicFunctions)
+      return;
+    if (callee.isExternal())
       return;
 
     SmallVector<Value, 6> replaceWithNewCallResults;
@@ -295,7 +297,9 @@ LogicalResult mlir::bufferization::promoteBufferResultsToOutParams(
   // function.
   AllocDynamicSizesMap map;
   for (auto func : module.getOps<func::FuncOp>()) {
-    if (func.isExternal() || func.isPublic())
+    if (func.isPublic() && !options.modifyPublicFunctions)
+      continue;
+    if (func.isExternal())
       continue;
     if (!options.filterFn(&func))
       continue;
@@ -326,6 +330,8 @@ struct BufferResultsToOutParamsPass
       options.hoistStaticAllocs = true;
     if (hoistDynamicAllocs)
       options.hoistDynamicAllocs = true;
+    if (modifyPublicFunctions)
+      options.modifyPublicFunctions = true;
 
     if (failed(bufferization::promoteBufferResultsToOutParams(getOperation(),
                                                               options)))
diff --git a/mlir/test/Transforms/buffer-results-to-out-params-modify-public-functions.mlir b/mlir/test/Transforms/buffer-results-to-out-params-modify-public-functions.mlir
index a2462bffeee25..c99bde3f34986 100644
--- a/mlir/test/Transforms/buffer-results-to-out-params-modify-public-functions.mlir
+++ b/mlir/test/Transforms/buffer-results-to-out-params-modify-public-functions.mlir
@@ -1,12 +1,13 @@
-// RUN: mlir-opt -buffer-results-to-out-params  %s | FileCheck %s
+// RUN: mlir-opt -p 'builtin.module(buffer-results-to-out-params{modify-public-functions})' %s | FileCheck %s
 
 // Test if `public` functions' return values are transformed into out parameters
 // when `buffer-results-to-out-params` is invoked with `modifyPublicFunctions`.
 
-
-// CHECK-LABEL:   func.func @basic() -> memref<f32> {
+// CHECK-LABEL:   func.func @basic(
+// CHECK-SAME:                     %[[ARG0:.*]]: memref<f32>) {
 // CHECK:           %[[VAL_0:.*]] = "test.source"() : () -> memref<f32>
-// CHECK:           return %[[VAL_0]] : memref<f32>
+// CHECK:           memref.copy %[[VAL_0]], %[[ARG0]] : memref<f32> to memref<f32>
+// CHECK:           return
 // CHECK:         }
 func.func @basic() -> (memref<f32>) {
   %0 = "test.source"() : () -> (memref<f32>)
@@ -14,23 +15,26 @@ func.func @basic() -> (memref<f32>) {
 }
 
 // CHECK-LABEL:   func.func @presence_of_existing_arguments(
-// CHECK-SAME:      %[[ARG0:.*]]: memref<1xf32>) -> memref<2xf32> {
+// CHECK-SAME:      %[[ARG0:.*]]: memref<1xf32>,
+// CHECK-SAME:      %[[ARG1:.*]]: memref<2xf32>) {
 // CHECK:           %[[VAL_0:.*]] = "test.source"() : () -> memref<2xf32>
-// CHECK:           return %[[VAL_0]] : memref<2xf32>
+// CHECK:           memref.copy %[[VAL_0]], %[[ARG1]] : memref<2xf32> to memref<2xf32>
+// CHECK:           return
 // CHECK:         }
 func.func @presence_of_existing_arguments(%arg0: memref<1xf32>) -> (memref<2xf32>) {
   %0 = "test.source"() : () -> (memref<2xf32>)
   return %0 : memref<2xf32>
 }
 
-// CHECK-LABEL:   func.func @multiple_results() -> (memref<1xf32>, memref<2xf32>) {
+// CHECK-LABEL:   func.func @multiple_results(
+// CHECK-SAME:      %[[ARG0:.*]]: memref<1xf32>,
+// CHECK-SAME:      %[[ARG1:.*]]: memref<2xf32>) {
 // CHECK:           %[[VAL_0:.*]]:2 = "test.source"() : () -> (memref<1xf32>, memref<2xf32>)
-// CHECK:           return %[[VAL_0]]#0, %[[VAL_0]]#1 : memref<1xf32>, memref<2xf32>
+// CHECK:           memref.copy %[[VAL_0]]#0, %[[ARG0]] : memref<1xf32> to memref<1xf32>
+// CHECK:           memref.copy %[[VAL_0]]#1, %[[ARG1]] : memref<2xf32> to memref<2xf32>
+// CHECK:           return
 // CHECK:         }
 func.func @multiple_results() -> (memref<1xf32>, memref<2xf32>) {
   %0, %1 = "test.source"() : () -> (memref<1xf32>, memref<2xf32>)
   return %0, %1 : memref<1xf32>, memref<2xf32>
 }
-
-
-



More information about the Mlir-commits mailing list