Add a new Buffer Deallocation pass with the intend to replace the old one. For now it is added as a separate pass alongside in order to allow downstream users to migrate over gradually. This new pass has the goal of inserting fewer clone operations and supporting additional use-cases. Please refer to the Buffer Deallocation section in the updated Bufferization.md file for more information on how this new pass works.
94 lines
2.8 KiB
MLIR
94 lines
2.8 KiB
MLIR
// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation -split-input-file %s
|
|
|
|
|
|
// Test Case: explicit control-flow loop with a dynamically allocated buffer.
|
|
// The BufferDeallocation transformation should fail on this explicit
|
|
// control-flow loop since they are not supported.
|
|
|
|
// expected-error@+1 {{Only structured control-flow loops are supported}}
|
|
func.func @loop_dynalloc(
|
|
%arg0 : i32,
|
|
%arg1 : i32,
|
|
%arg2: memref<?xf32>,
|
|
%arg3: memref<?xf32>) {
|
|
%const0 = arith.constant 0 : i32
|
|
cf.br ^loopHeader(%const0, %arg2 : i32, memref<?xf32>)
|
|
|
|
^loopHeader(%i : i32, %buff : memref<?xf32>):
|
|
%lessThan = arith.cmpi slt, %i, %arg1 : i32
|
|
cf.cond_br %lessThan,
|
|
^loopBody(%i, %buff : i32, memref<?xf32>),
|
|
^exit(%buff : memref<?xf32>)
|
|
|
|
^loopBody(%val : i32, %buff2: memref<?xf32>):
|
|
%const1 = arith.constant 1 : i32
|
|
%inc = arith.addi %val, %const1 : i32
|
|
%size = arith.index_cast %inc : i32 to index
|
|
%alloc1 = memref.alloc(%size) : memref<?xf32>
|
|
cf.br ^loopHeader(%inc, %alloc1 : i32, memref<?xf32>)
|
|
|
|
^exit(%buff3 : memref<?xf32>):
|
|
test.copy(%buff3, %arg3) : (memref<?xf32>, memref<?xf32>)
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test Case: explicit control-flow loop with a dynamically allocated buffer.
|
|
// The BufferDeallocation transformation should fail on this explicit
|
|
// control-flow loop since they are not supported.
|
|
|
|
// expected-error@+1 {{Only structured control-flow loops are supported}}
|
|
func.func @do_loop_alloc(
|
|
%arg0 : i32,
|
|
%arg1 : i32,
|
|
%arg2: memref<2xf32>,
|
|
%arg3: memref<2xf32>) {
|
|
%const0 = arith.constant 0 : i32
|
|
cf.br ^loopBody(%const0, %arg2 : i32, memref<2xf32>)
|
|
|
|
^loopBody(%val : i32, %buff2: memref<2xf32>):
|
|
%const1 = arith.constant 1 : i32
|
|
%inc = arith.addi %val, %const1 : i32
|
|
%alloc1 = memref.alloc() : memref<2xf32>
|
|
cf.br ^loopHeader(%inc, %alloc1 : i32, memref<2xf32>)
|
|
|
|
^loopHeader(%i : i32, %buff : memref<2xf32>):
|
|
%lessThan = arith.cmpi slt, %i, %arg1 : i32
|
|
cf.cond_br %lessThan,
|
|
^loopBody(%i, %buff : i32, memref<2xf32>),
|
|
^exit(%buff : memref<2xf32>)
|
|
|
|
^exit(%buff3 : memref<2xf32>):
|
|
test.copy(%buff3, %arg3) : (memref<2xf32>, memref<2xf32>)
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @free_effect() {
|
|
%alloc = memref.alloc() : memref<2xi32>
|
|
// expected-error @below {{memory free side-effect on MemRef value not supported!}}
|
|
%new_alloc = memref.realloc %alloc : memref<2xi32> to memref<4xi32>
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @free_effect() {
|
|
%alloc = memref.alloc() : memref<2xi32>
|
|
// expected-error @below {{memory free side-effect on MemRef value not supported!}}
|
|
memref.dealloc %alloc : memref<2xi32>
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @free_effect() {
|
|
%true = arith.constant true
|
|
%alloc = memref.alloc() : memref<2xi32>
|
|
// expected-error @below {{No deallocation operations must be present when running this pass!}}
|
|
bufferization.dealloc (%alloc : memref<2xi32>) if (%true)
|
|
return
|
|
}
|