The buffer deallocation pass checks the IR ("operation preconditions")
to make sure that there is no IR that is unsupported. In such a case,
the pass signals a failure.
The pass now rejects all ops with unknown memory effects. We do not know
whether such an op allocates memory or not. Therefore, the buffer
deallocation pass does not know whether a deallocation op should be
inserted or not.
Memory effects are queried from the `MemoryEffectOpInterface` interface.
Ops that do not implement this interface but have the
`RecursiveMemoryEffects` trait do not have any side effects (apart from
the ones that their nested ops may have).
Unregistered ops are now rejected by the pass because they do not
implement the `MemoryEffectOpInterface` and neither do we know if they
have `RecursiveMemoryEffects` or not. All test cases that currently have
unregistered ops are updated to use registered ops.
41 lines
1.6 KiB
MLIR
41 lines
1.6 KiB
MLIR
// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation \
|
|
// RUN: --buffer-deallocation-simplification -canonicalize -split-input-file %s | FileCheck %s
|
|
|
|
// No ownership is assumed for ops that do not implement any interface and have
|
|
// no memref operands.
|
|
|
|
// CHECK-LABEL: func private @no_interface_no_operands(
|
|
// CHECK-NEXT: %[[m:.*]] = bufferization.to_memref
|
|
// CHECK-NEXT: %[[clone:.*]] = bufferization.clone %[[m]]
|
|
// CHECK-NEXT: return %[[clone]]
|
|
func.func private @no_interface_no_operands(%t : tensor<?x?x?xf16>) -> memref<?x?x?xf16> {
|
|
%0 = bufferization.to_memref %t : memref<?x?x?xf16>
|
|
return %0 : memref<?x?x?xf16>
|
|
}
|
|
|
|
// -----
|
|
|
|
// If an op does not implement any interface but has memref operands, the
|
|
// ownership of the memref results is computed from the operands.
|
|
|
|
// CHECK-LABEL: func private @no_interface(
|
|
// CHECK: %[[true:.*]] = arith.constant true
|
|
// CHECK: %[[alloc:.*]] = memref.alloc
|
|
// CHECK: %[[foo:.*]] = "test.forward_buffer"(%[[alloc]])
|
|
// CHECK: %[[r:.*]] = bufferization.dealloc (%[[alloc]] : {{.*}}) if (%[[true]]) retain (%[[foo]] : {{.*}})
|
|
// CHECK: return %[[foo]]
|
|
func.func private @no_interface() -> memref<5xf32> {
|
|
%0 = memref.alloc() : memref<5xf32>
|
|
%1 = "test.forward_buffer"(%0) : (memref<5xf32>) -> (memref<5xf32>)
|
|
return %1 : memref<5xf32>
|
|
}
|
|
|
|
// -----
|
|
|
|
func.func @no_side_effects() {
|
|
%0 = memref.alloc() : memref<5xf32>
|
|
// expected-error @below{{ops with unknown memory side effects are not supported}}
|
|
"test.unregistered_op_foo"(%0) : (memref<5xf32>) -> ()
|
|
return
|
|
}
|