[Mlir-commits] [mlir] 83af810 - [mlir][Bufferization] Don't assert in foldMemRefCasts on a func body without func.return (#217515)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Fri Aug 21 01:46:33 PDT 2026


Author: Aman Singh
Date: 2026-08-21T10:46:28+02:00
New Revision: 83af810fa5190d779413ed16fb3eec6e80db39db

URL: https://github.com/llvm/llvm-project/commit/83af810fa5190d779413ed16fb3eec6e80db39db
DIFF: https://github.com/llvm/llvm-project/commit/83af810fa5190d779413ed16fb3eec6e80db39db.diff

LOG: [mlir][Bufferization] Don't assert in foldMemRefCasts on a func body without func.return (#217515)

`foldMemRefCasts` (used by One-Shot Module Bufferize when inferring
function result layouts) assumes every `func.func` body with a region
ends in a `func::ReturnOp`, and asserts if `getReturnOps()` finds
none. That assumption does not hold: `func.func`'s verifier only
requires the region to end in some terminator, not specifically
`func::ReturnOp`, so a body ending in e.g. a different dialect's
terminator parses and verifies fine but crashes this pass. This code
path is normally reached through
`insertTensorCopies`/`analyzeModuleOp`, which already reports this
case gracefully via `emitError` — but that analysis is skipped
entirely when `copy-before-write=1` is set, going straight to
`bufferizeModuleOp` and hitting the unguarded assert.

Fix by bailing out of `foldMemRefCasts` (nothing to fold) when there
are no `func::ReturnOp`s, mirroring how the rest of the file already
tolerates an empty `getReturnOps()` result.

Verified: reverting this fix reproduces the reported crash; with the
fix, `mlir-opt -one-shot-bufferize='bufferize-function-boundaries=1
copy-before-write=1'` on the reported reproducer succeeds, and

`mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-non-func-return.mlir`
passes.

Fixes #217227

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Added: 
    

Modified: 
    mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp
    mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-call-copy-before-write.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp
index 4d044bbb74df1..5552246427188 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp
@@ -435,6 +435,11 @@ static void foldMemRefCasts(func::FuncOp funcOp) {
 
   // Compute the common result types of all return ops.
   SmallVector<func::ReturnOp> returnOps = getReturnOps(funcOp);
+  // There is nothing to fold if the function body does not end in a
+  // func::ReturnOp (e.g., the terminator is from a 
diff erent dialect). Bail
+  // out gracefully instead of asserting inside `getReturnTypes`.
+  if (returnOps.empty())
+    return;
   SmallVector<Type> resultTypes = getReturnTypes(returnOps);
 
   // Remove direct casts.

diff  --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-call-copy-before-write.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-call-copy-before-write.mlir
index 7addca2c9d6a5..d44a0b043757d 100644
--- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-call-copy-before-write.mlir
+++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-call-copy-before-write.mlir
@@ -14,3 +14,20 @@ func.func @caller(%A : tensor<64xf32>) {
   call @callee(%A) : (tensor<64xf32>) -> ()
   return
 }
+
+// -----
+
+// Regression test for https://github.com/llvm/llvm-project/issues/217227:
+// this function does not have a `func.return` terminator (it uses
+// `spirv.Return` instead, which is a valid terminator for `func.func` since
+// the verifier only requires the region to end in some terminator, not
+// specifically a `func.return`). One-Shot Module Bufferize must not crash on
+// such IR; it has no tensors to bufferize, so it should simply leave the
+// function unchanged.
+
+// CHECK-LABEL: func.func private @non_func_return(
+// CHECK-SAME:      %{{.*}}: memref<4xi32>)
+// CHECK-NEXT:    spirv.Return
+func.func private @non_func_return(%arg0: memref<4xi32>) {
+  spirv.Return
+}


        


More information about the Mlir-commits mailing list