Skip to content

Commit 5109cb2

Browse files
[mlir][bufferization] Make buffer deallocation pipeline op type independent (#67546)
The buffer deallocation pipeline now works on modules and functions. Also add extra test cases that run the buffer deallocation pipeline on modules and functions. (Test cases that insert a helper function.)
1 parent 6e1dcc9 commit 5109cb2

File tree

5 files changed

+61
-15
lines changed

5 files changed

+61
-15
lines changed

mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def BufferDeallocation : Pass<"buffer-deallocation", "func::FuncOp"> {
8989
}
9090

9191
def OwnershipBasedBufferDeallocation : Pass<
92-
"ownership-based-buffer-deallocation", "func::FuncOp"> {
92+
"ownership-based-buffer-deallocation"> {
9393
let summary = "Adds all required dealloc operations for all allocations in "
9494
"the input program";
9595
let description = [{
@@ -233,7 +233,7 @@ def OwnershipBasedBufferDeallocation : Pass<
233233
}
234234

235235
def BufferDeallocationSimplification :
236-
Pass<"buffer-deallocation-simplification", "func::FuncOp"> {
236+
Pass<"buffer-deallocation-simplification"> {
237237
let summary = "Optimizes `bufferization.dealloc` operation for more "
238238
"efficient codegen";
239239
let description = [{

mlir/lib/Dialect/Bufferization/Pipelines/BufferizationPipelines.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,15 @@
2020

2121
void mlir::bufferization::buildBufferDeallocationPipeline(
2222
OpPassManager &pm, const BufferDeallocationPipelineOptions &options) {
23-
pm.addNestedPass<func::FuncOp>(
24-
memref::createExpandReallocPass(/*emitDeallocs=*/false));
25-
pm.addNestedPass<func::FuncOp>(createCanonicalizerPass());
26-
pm.addNestedPass<func::FuncOp>(createOwnershipBasedBufferDeallocationPass(
23+
pm.addPass(memref::createExpandReallocPass(/*emitDeallocs=*/false));
24+
pm.addPass(createCanonicalizerPass());
25+
pm.addPass(createOwnershipBasedBufferDeallocationPass(
2726
options.privateFunctionDynamicOwnership.getValue()));
28-
pm.addNestedPass<func::FuncOp>(createCanonicalizerPass());
29-
pm.addNestedPass<func::FuncOp>(createBufferDeallocationSimplificationPass());
27+
pm.addPass(createCanonicalizerPass());
28+
pm.addPass(createBufferDeallocationSimplificationPass());
3029
pm.addPass(createLowerDeallocationsPass());
31-
pm.addNestedPass<func::FuncOp>(createCSEPass());
32-
pm.addNestedPass<func::FuncOp>(createCanonicalizerPass());
30+
pm.addPass(createCSEPass());
31+
pm.addPass(createCanonicalizerPass());
3332
}
3433

3534
//===----------------------------------------------------------------------===//

mlir/lib/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -983,12 +983,17 @@ struct OwnershipBasedBufferDeallocationPass
983983
this->privateFuncDynamicOwnership.setValue(privateFuncDynamicOwnership);
984984
}
985985
void runOnOperation() override {
986-
func::FuncOp func = getOperation();
987-
if (func.isExternal())
988-
return;
986+
auto status = getOperation()->walk([&](func::FuncOp func) {
987+
if (func.isExternal())
988+
return WalkResult::skip();
989+
990+
if (failed(deallocateBuffersOwnershipBased(func,
991+
privateFuncDynamicOwnership)))
992+
return WalkResult::interrupt();
989993

990-
if (failed(
991-
deallocateBuffersOwnershipBased(func, privateFuncDynamicOwnership)))
994+
return WalkResult::advance();
995+
});
996+
if (status.wasInterrupted())
992997
signalPassFailure();
993998
}
994999
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: mlir-opt %s --pass-pipeline="builtin.module(func.func(buffer-deallocation-pipeline))" -verify-diagnostics
2+
3+
// Test case requires a helper function but is run on a function.
4+
5+
// CHECK-LABEL: func.func @test(
6+
// CHECK: func.call @[[helper:.*]]({{.*}}) : ({{.*}}) -> ()
7+
func.func @test(%lb : index, %ub: index) -> (memref<5xf32>, memref<5xf32>) {
8+
%0 = memref.alloc() : memref<5xf32>
9+
%1 = memref.alloc() : memref<5xf32>
10+
%c1 = arith.constant 1 : index
11+
%a, %b = scf.for %iv = %lb to %ub step %c1 iter_args(%c = %0, %d = %1)
12+
-> (memref<5xf32>, memref<5xf32>) {
13+
// expected-error @below{{library function required for generic lowering, but cannot be automatically inserted when operating on functions}}
14+
// expected-error @below{{failed to legalize operation 'bufferization.dealloc' that was explicitly marked illegal}}
15+
scf.yield %d, %c : memref<5xf32>, memref<5xf32>
16+
}
17+
return %a, %b : memref<5xf32>, memref<5xf32>
18+
}
19+
20+
// CHECK: func.func @[[helper]](
21+
// CHECK-SAME: %{{.*}}: memref<?xindex>, %{{.*}}: memref<?xindex>, %{{.*}}: memref<?xi1>, %{{.*}}: memref<?xi1>, %{{.*}}: memref<?xi1>)
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: mlir-opt %s -buffer-deallocation-pipeline | FileCheck %s
2+
// RUN: mlir-opt %s --pass-pipeline="builtin.module(buffer-deallocation-pipeline)" | FileCheck %s
3+
4+
// Test case requires a helper function.
5+
6+
// CHECK-LABEL: func.func @test(
7+
// CHECK: func.call @[[helper:.*]]({{.*}}) : ({{.*}}) -> ()
8+
func.func @test(%lb : index, %ub: index) -> (memref<5xf32>, memref<5xf32>) {
9+
%0 = memref.alloc() : memref<5xf32>
10+
%1 = memref.alloc() : memref<5xf32>
11+
%c1 = arith.constant 1 : index
12+
%a, %b = scf.for %iv = %lb to %ub step %c1 iter_args(%c = %0, %d = %1)
13+
-> (memref<5xf32>, memref<5xf32>) {
14+
scf.yield %d, %c : memref<5xf32>, memref<5xf32>
15+
}
16+
return %a, %b : memref<5xf32>, memref<5xf32>
17+
}
18+
19+
// CHECK: func.func private @[[helper]](
20+
// CHECK-SAME: %{{.*}}: memref<?xindex>, %{{.*}}: memref<?xindex>, %{{.*}}: memref<?xi1>, %{{.*}}: memref<?xi1>, %{{.*}}: memref<?xi1>)

0 commit comments

Comments
 (0)