From 13896b6ce9b791db6d1ac40c6a05eb893405fcd7 Mon Sep 17 00:00:00 2001 From: Matthias Springer Date: Mon, 10 Jun 2024 08:07:24 +0200 Subject: [PATCH] [mlir][bufferization] Fix handling of indirect function calls (#94896) This commit fixes a crash in the ownership-based buffer deallocation pass when indirectly calling a function via SSA value. Such functions must be conservatively assumed to be public. Fixes #94780. --- .../OwnershipBasedBufferDeallocation.cpp | 7 ++++--- .../dealloc-callop-interface.mlir | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp index a8ec111f8c304b..bd5c4d47692169 100644 --- a/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp @@ -822,10 +822,11 @@ FailureOr BufferDeallocation::handleInterface(CallOpInterface op) { // Lookup the function operation and check if it has private visibility. If // the function is referenced by SSA value instead of a Symbol, it's assumed - // to be always private. + // to be public. (And we cannot easily change the type of the SSA value + // anyway.) Operation *funcOp = op.resolveCallable(state.getSymbolTable()); - bool isPrivate = true; - if (auto symbol = dyn_cast(funcOp)) + bool isPrivate = false; + if (auto symbol = dyn_cast_or_null(funcOp)) isPrivate = symbol.isPrivate() && !symbol.isDeclaration(); // If the private-function-dynamic-ownership option is enabled and we are diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir index 63947150c23b30..a77442dfe40e5b 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-callop-interface.mlir @@ -131,3 +131,22 @@ func.func @g(%arg0: memref) -> memref { // CHECK-DYNAMIC-LABEL: func private @f // CHECK-DYNAMIC-SAME: (memref) -> memref // CHECK-DYNAMIC: call @f({{.*}}) : (memref) -> memref + +// ----- + +func.func @func_call_indirect(%m: memref, %f: (memref) -> (memref)) { + %0 = func.call_indirect %f(%m) : (memref) -> (memref) + return +} + +// CHECK-LABEL: func @func_call_indirect( +// CHECK: %[[true:.*]] = arith.constant true +// CHECK: %[[call:.*]] = call_indirect {{.*}} : (memref) -> memref +// CHECK: %[[base_call:.*]], %{{.*}}, %{{.*}}, %{{.*}} = memref.extract_strided_metadata %[[call]] +// CHECK: bufferization.dealloc (%[[base_call]] : {{.*}}) if (%[[true]]) + +// CHECK-DYNAMIC-LABEL: func @func_call_indirect( +// CHECK-DYNAMIC: %[[true:.*]] = arith.constant true +// CHECK-DYNAMIC: %[[call:.*]] = call_indirect {{.*}} : (memref) -> memref +// CHECK-DYNAMIC: %[[base_call:.*]], %{{.*}}, %{{.*}}, %{{.*}} = memref.extract_strided_metadata %[[call]] +// CHECK-DYNAMIC: bufferization.dealloc (%[[base_call]] : {{.*}}) if (%[[true]])