[Mlir-commits] [mlir] [MLIR][Bufferization] Fix IdentityLayoutMap allocation at function boundaries (PR #227253)

Aaditya Agarwal llvmlistbot at llvm.org
Tue Sep 29 12:55:10 PDT 2026


https://github.com/aaditya8979 updated https://github.com/llvm/llvm-project/pull/227253

>From 7b83b2f8fca16a6fbbef2233c76535a8e74debbe Mon Sep 17 00:00:00 2001
From: openhands <openhands at all-hands.dev>
Date: Tue, 29 Sep 2026 15:13:13 +0530
Subject: [PATCH] [MLIR][Bufferization] Fix IdentityLayoutMap allocation at
 function boundaries

Resolves silent data corruption where `memref.cast` strips non-unit stride
layouts from subviews during function boundary bufferization under
`IdentityLayoutMap`. Injects explicit allocation and `memref.copy` for
non-identity to identity layout transitions.

Fixes #83276
---
 .../FuncBufferizableOpInterfaceImpl.cpp       | 31 ++++++++++++++++---
 .../Transforms/one-shot-module-bufferize.mlir | 23 ++++++++++++++
 2 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
index e76b51aa8015db..db29920055539c 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
@@ -13,6 +13,7 @@
 #include "mlir/Dialect/Bufferization/Transforms/Bufferize.h"
 #include "mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h"
 #include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
 #include "mlir/IR/Dialect.h"
 #include "mlir/IR/Operation.h"
 #include <optional>
@@ -322,11 +323,31 @@ struct CallOpInterface
         auto memrefDstType = dyn_cast<MemRefType>(bufferType);
         assert(memrefDstType &&
                "buffer layout not supported on unranked tensors");
-        FailureOr<Value> replacement = bufferization::castOrReallocMemRefValue(
-            rewriter, buffer, memrefDstType, options);
-        if (failed(replacement))
-          return failure();
-        buffer = *replacement;
+        auto memrefSrcType = dyn_cast<MemRefType>(buffer.getType());
+        if (memrefSrcType && !memrefSrcType.getLayout().isIdentity() &&
+            memrefDstType.getLayout().isIdentity()) {
+          SmallVector<Value, 4> dynamicOperands;
+          for (int64_t i = 0, e = memrefDstType.getRank(); i < e; ++i) {
+            if (memrefDstType.getShape()[i] != ShapedType::kDynamic)
+              continue;
+            dynamicOperands.push_back(
+                rewriter.create<memref::DimOp>(callOp.getLoc(), buffer, i));
+          }
+          FailureOr<Value> alloc = options.allocationFn(
+              rewriter, callOp.getLoc(), memrefDstType, dynamicOperands,
+              options.bufferAlignment);
+          if (failed(alloc))
+            return failure();
+          if (failed(options.memCpyFn(rewriter, callOp.getLoc(), buffer, *alloc)))
+            return failure();
+          buffer = *alloc;
+        } else {
+          FailureOr<Value> replacement = bufferization::castOrReallocMemRefValue(
+              rewriter, buffer, memrefDstType, options);
+          if (failed(replacement))
+            return failure();
+          buffer = *replacement;
+        }
       }
       newOperands.push_back(buffer);
     }
diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
index dbe44cba4d98f7..fdc11d152a9df4 100644
--- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
+++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
@@ -852,3 +852,26 @@ func.func @ranked_return_via_unranked_call(%arg0: tensor<64x20x40xf32>) -> tenso
   return %b : tensor<64x20x40xf32>
 }
 func.func private @relu_unranked(tensor<*xf32>) -> tensor<*xf32>
+
+
+// -----
+
+// CHECK-LABEL: func.func @caller
+// CHECK:       %[[SUBVIEW:.*]] = memref.subview
+// CHECK-SAME:    strided<[1], offset: ?>
+// CHECK-NOT:   memref.cast %[[SUBVIEW]]
+// CHECK:       %[[ALLOC:.*]] = memref.alloc
+// CHECK:       memref.copy %[[SUBVIEW]], %[[ALLOC]]
+// CHECK:       call @callee(%[[ALLOC]])
+func.func @caller(%arg0: tensor<5xf32>, %offset: index, %size: index) -> (f32) {
+    %extracted_slice = tensor.extract_slice %arg0[%offset] [%size] [1]
+        : tensor<5xf32> to tensor<?xf32>
+    %result = func.call @callee(%extracted_slice) : (tensor<?xf32>) -> (f32)
+    return %result : f32
+}
+func.func private @callee(%arg0: tensor<?xf32>) -> (f32) {
+    %0 = arith.constant 0 : index
+    %extracted = tensor.extract %arg0[%0] : tensor<?xf32>
+    return %extracted : f32
+}
+



More information about the Mlir-commits mailing list