[Mlir-commits] [mlir] 213917b - [mlir][bufferization] Remove `buffer-deallocation` pass (#126366)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Feb 13 00:49:20 PST 2025
Author: Matthias Springer
Date: 2025-02-13T09:49:16+01:00
New Revision: 213917be82e3cd57c74afc836377a746be45dafd
URL: https://github.com/llvm/llvm-project/commit/213917be82e3cd57c74afc836377a746be45dafd
DIFF: https://github.com/llvm/llvm-project/commit/213917be82e3cd57c74afc836377a746be45dafd.diff
LOG: [mlir][bufferization] Remove `buffer-deallocation` pass (#126366)
The `-buffer-deallocation` pass is not compatible with One-Shot
Bufferize and has been replaced with the Ownership-based Buffer
Deallocation pass about 1.5 years ago. To clean up the code base, this
commit removes the deprecated `buffer-deallocation` pass. All uses of
this deprecated pass within MLIR have already been migrated.
Note for LLVM integration: If you depend on this pass, migrate to the
Ownership-based Buffer Deallocation pass or copy the pass to your
codebase. For details, see
https://discourse.llvm.org/t/psa-bufferization-new-buffer-deallocation-pipeline/73375.
Added:
Modified:
mlir/docs/OwnershipBasedBufferDeallocation.md
mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
mlir/test/Pass/pipeline-invalid.mlir
Removed:
mlir/docs/BufferDeallocationInternals.md
mlir/docs/includes/img/branch_example_post_move.svg
mlir/docs/includes/img/branch_example_pre_move.svg
mlir/docs/includes/img/nested_branch_example_post_move.svg
mlir/docs/includes/img/nested_branch_example_pre_move.svg
mlir/docs/includes/img/region_branch_example_pre_move.svg
mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocation.cpp
mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation.mlir
################################################################################
diff --git a/mlir/docs/BufferDeallocationInternals.md b/mlir/docs/BufferDeallocationInternals.md
deleted file mode 100644
index 00830ba9d2dc2..0000000000000
--- a/mlir/docs/BufferDeallocationInternals.md
+++ /dev/null
@@ -1,705 +0,0 @@
-# Buffer Deallocation - Internals
-
-**Note:** This pass is deprecated. Please use the ownership-based buffer
-deallocation pass instead.
-
-This section covers the internal functionality of the BufferDeallocation
-transformation. The transformation consists of several passes. The main pass
-called BufferDeallocation can be applied via “-buffer-deallocation” on MLIR
-programs.
-
-[TOC]
-
-## Requirements
-
-In order to use BufferDeallocation on an arbitrary dialect, several control-flow
-interfaces have to be implemented when using custom operations. This is
-particularly important to understand the implicit control-flow dependencies
-between
diff erent parts of the input program. Without implementing the following
-interfaces, control-flow relations cannot be discovered properly and the
-resulting program can become invalid:
-
-* Branch-like terminators should implement the `BranchOpInterface` to query
- and manipulate associated operands.
-* Operations involving structured control flow have to implement the
- `RegionBranchOpInterface` to model inter-region control flow.
-* Terminators yielding values to their parent operation (in particular in the
- scope of nested regions within `RegionBranchOpInterface`-based operations),
- should implement the `ReturnLike` trait to represent logical “value
- returns”.
-
-Example dialects that are fully compatible are the “std” and “scf” dialects with
-respect to all implemented interfaces.
-
-During Bufferization, we convert immutable value types (tensors) to mutable
-types (memref). This conversion is done in several steps and in all of these
-steps the IR has to fulfill SSA like properties. The usage of memref has to be
-in the following consecutive order: allocation, write-buffer, read- buffer. In
-this case, there are only buffer reads allowed after the initial full buffer
-write is done. In particular, there must be no partial write to a buffer after
-the initial write has been finished. However, partial writes in the initializing
-is allowed (fill buffer step by step in a loop e.g.). This means, all buffer
-writes needs to dominate all buffer reads.
-
-Example for breaking the invariant:
-
-```mlir
-func.func @condBranch(%arg0: i1, %arg1: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- cf.cond_br %arg0, ^bb1, ^bb2
-^bb1:
- cf.br ^bb3()
-^bb2:
- partial_write(%0, %0)
- cf.br ^bb3()
-^bb3():
- test.copy(%0, %arg1) : (memref<2xf32>, memref<2xf32>) -> ()
- return
-}
-```
-
-The maintenance of the SSA like properties is only needed in the bufferization
-process. Afterwards, for example in optimization processes, the property is no
-longer needed.
-
-## Detection of Buffer Allocations
-
-The first step of the BufferDeallocation transformation is to identify
-manageable allocation operations that implement the `SideEffects` interface.
-Furthermore, these ops need to apply the effect `MemoryEffects::Allocate` to a
-particular result value while not using the resource
-`SideEffects::AutomaticAllocationScopeResource` (since it is currently reserved
-for allocations, like `Alloca` that will be automatically deallocated by a
-parent scope). Allocations that have not been detected in this phase will not be
-tracked internally, and thus, not deallocated automatically. However,
-BufferDeallocation is fully compatible with “hybrid” setups in which tracked and
-untracked allocations are mixed:
-
-```mlir
-func.func @mixedAllocation(%arg0: i1) {
- %0 = memref.alloca() : memref<2xf32> // aliases: %2
- %1 = memref.alloc() : memref<2xf32> // aliases: %2
- cf.cond_br %arg0, ^bb1, ^bb2
-^bb1:
- use(%0)
- cf.br ^bb3(%0 : memref<2xf32>)
-^bb2:
- use(%1)
- cf.br ^bb3(%1 : memref<2xf32>)
-^bb3(%2: memref<2xf32>):
- ...
-}
-```
-
-Example of using a conditional branch with alloc and alloca. BufferDeallocation
-can detect and handle the
diff erent allocation types that might be intermixed.
-
-Note: the current version does not support allocation operations returning
-multiple result buffers.
-
-## Conversion from AllocOp to AllocaOp
-
-The PromoteBuffersToStack-pass converts AllocOps to AllocaOps, if possible. In
-some cases, it can be useful to use such stack-based buffers instead of
-heap-based buffers. The conversion is restricted to several constraints like:
-
-* Control flow
-* Buffer Size
-* Dynamic Size
-
-If a buffer is leaving a block, we are not allowed to convert it into an alloca.
-If the size of the buffer is large, we could convert it, but regarding stack
-overflow, it makes sense to limit the size of these buffers and only convert
-small ones. The size can be set via a pass option. The current default value is
-1KB. Furthermore, we can not convert buffers with dynamic size, since the
-dimension is not known a priori.
-
-## Movement and Placement of Allocations
-
-Using the buffer hoisting pass, all buffer allocations are moved as far upwards
-as possible in order to group them and make upcoming optimizations easier by
-limiting the search space. Such a movement is shown in the following graphs. In
-addition, we are able to statically free an alloc, if we move it into a
-dominator of all of its uses. This simplifies further optimizations (e.g. buffer
-fusion) in the future. However, movement of allocations is limited by external
-data dependencies (in particular in the case of allocations of dynamically
-shaped types). Furthermore, allocations can be moved out of nested regions, if
-necessary. In order to move allocations to valid locations with respect to their
-uses only, we leverage Liveness information.
-
-The following code snippets shows a conditional branch before running the
-BufferHoisting pass:
-
-
-
-```mlir
-func.func @condBranch(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- cf.cond_br %arg0, ^bb1, ^bb2
-^bb1:
- cf.br ^bb3(%arg1 : memref<2xf32>)
-^bb2:
- %0 = memref.alloc() : memref<2xf32> // aliases: %1
- use(%0)
- cf.br ^bb3(%0 : memref<2xf32>)
-^bb3(%1: memref<2xf32>): // %1 could be %0 or %arg1
- test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>) -> ()
- return
-}
-```
-
-Applying the BufferHoisting pass on this program results in the following piece
-of code:
-
-
-
-```mlir
-func.func @condBranch(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32> // moved to bb0
- cf.cond_br %arg0, ^bb1, ^bb2
-^bb1:
- cf.br ^bb3(%arg1 : memref<2xf32>)
-^bb2:
- use(%0)
- cf.br ^bb3(%0 : memref<2xf32>)
-^bb3(%1: memref<2xf32>):
- test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>) -> ()
- return
-}
-```
-
-The alloc is moved from bb2 to the beginning and it is passed as an argument to
-bb3.
-
-The following example demonstrates an allocation using dynamically shaped types.
-Due to the data dependency of the allocation to %0, we cannot move the
-allocation out of bb2 in this case:
-
-```mlir
-func.func @condBranchDynamicType(
- %arg0: i1,
- %arg1: memref<?xf32>,
- %arg2: memref<?xf32>,
- %arg3: index) {
- cf.cond_br %arg0, ^bb1, ^bb2(%arg3: index)
-^bb1:
- cf.br ^bb3(%arg1 : memref<?xf32>)
-^bb2(%0: index):
- %1 = memref.alloc(%0) : memref<?xf32> // cannot be moved upwards to the data
- // dependency to %0
- use(%1)
- cf.br ^bb3(%1 : memref<?xf32>)
-^bb3(%2: memref<?xf32>):
- test.copy(%2, %arg2) : (memref<?xf32>, memref<?xf32>) -> ()
- return
-}
-```
-
-## Introduction of Clones
-
-In order to guarantee that all allocated buffers are freed properly, we have to
-pay attention to the control flow and all potential aliases a buffer allocation
-can have. Since not all allocations can be safely freed with respect to their
-aliases (see the following code snippet), it is often required to introduce
-copies to eliminate them. Consider the following example in which the
-allocations have already been placed:
-
-```mlir
-func.func @branch(%arg0: i1) {
- %0 = memref.alloc() : memref<2xf32> // aliases: %2
- cf.cond_br %arg0, ^bb1, ^bb2
-^bb1:
- %1 = memref.alloc() : memref<2xf32> // resides here for demonstration purposes
- // aliases: %2
- cf.br ^bb3(%1 : memref<2xf32>)
-^bb2:
- use(%0)
- cf.br ^bb3(%0 : memref<2xf32>)
-^bb3(%2: memref<2xf32>):
- …
- return
-}
-```
-
-The first alloc can be safely freed after the live range of its post-dominator
-block (bb3). The alloc in bb1 has an alias %2 in bb3 that also keeps this buffer
-alive until the end of bb3. Since we cannot determine the actual branches that
-will be taken at runtime, we have to ensure that all buffers are freed correctly
-in bb3 regardless of the branches we will take to reach the exit block. This
-makes it necessary to introduce a copy for %2, which allows us to free %alloc0
-in bb0 and %alloc1 in bb1. Afterwards, we can continue processing all aliases of
-%2 (none in this case) and we can safely free %2 at the end of the sample
-program. This sample demonstrates that not all allocations can be safely freed
-in their associated post-dominator blocks. Instead, we have to pay attention to
-all of their aliases.
-
-Applying the BufferDeallocation pass to the program above yields the following
-result:
-
-```mlir
-func.func @branch(%arg0: i1) {
- %0 = memref.alloc() : memref<2xf32>
- cf.cond_br %arg0, ^bb1, ^bb2
-^bb1:
- %1 = memref.alloc() : memref<2xf32>
- %3 = bufferization.clone %1 : (memref<2xf32>) -> (memref<2xf32>)
- memref.dealloc %1 : memref<2xf32> // %1 can be safely freed here
- cf.br ^bb3(%3 : memref<2xf32>)
-^bb2:
- use(%0)
- %4 = bufferization.clone %0 : (memref<2xf32>) -> (memref<2xf32>)
- cf.br ^bb3(%4 : memref<2xf32>)
-^bb3(%2: memref<2xf32>):
- …
- memref.dealloc %2 : memref<2xf32> // free temp buffer %2
- memref.dealloc %0 : memref<2xf32> // %0 can be safely freed here
- return
-}
-```
-
-Note that a temporary buffer for %2 was introduced to free all allocations
-properly. Note further that the unnecessary allocation of %3 can be easily
-removed using one of the post-pass transformations or the canonicalization pass.
-
-The presented example also works with dynamically shaped types.
-
-BufferDeallocation performs a fix-point iteration taking all aliases of all
-tracked allocations into account. We initialize the general iteration process
-using all tracked allocations and their associated aliases. As soon as we
-encounter an alias that is not properly dominated by our allocation, we mark
-this alias as *critical* (needs to be freed and tracked by the internal
-fix-point iteration). The following sample demonstrates the presence of critical
-and non-critical aliases:
-
-
-
-```mlir
-func.func @condBranchDynamicTypeNested(
- %arg0: i1,
- %arg1: memref<?xf32>, // aliases: %3, %4
- %arg2: memref<?xf32>,
- %arg3: index) {
- cf.cond_br %arg0, ^bb1, ^bb2(%arg3: index)
-^bb1:
- cf.br ^bb6(%arg1 : memref<?xf32>)
-^bb2(%0: index):
- %1 = memref.alloc(%0) : memref<?xf32> // cannot be moved upwards due to the data
- // dependency to %0
- // aliases: %2, %3, %4
- use(%1)
- cf.cond_br %arg0, ^bb3, ^bb4
-^bb3:
- cf.br ^bb5(%1 : memref<?xf32>)
-^bb4:
- cf.br ^bb5(%1 : memref<?xf32>)
-^bb5(%2: memref<?xf32>): // non-crit. alias of %1, since %1 dominates %2
- cf.br ^bb6(%2 : memref<?xf32>)
-^bb6(%3: memref<?xf32>): // crit. alias of %arg1 and %2 (in other words %1)
- cf.br ^bb7(%3 : memref<?xf32>)
-^bb7(%4: memref<?xf32>): // non-crit. alias of %3, since %3 dominates %4
- test.copy(%4, %arg2) : (memref<?xf32>, memref<?xf32>) -> ()
- return
-}
-```
-
-Applying BufferDeallocation yields the following output:
-
-
-
-```mlir
-func.func @condBranchDynamicTypeNested(
- %arg0: i1,
- %arg1: memref<?xf32>,
- %arg2: memref<?xf32>,
- %arg3: index) {
- cf.cond_br %arg0, ^bb1, ^bb2(%arg3 : index)
-^bb1:
- // temp buffer required due to alias %3
- %5 = bufferization.clone %arg1 : (memref<?xf32>) -> (memref<?xf32>)
- cf.br ^bb6(%5 : memref<?xf32>)
-^bb2(%0: index):
- %1 = memref.alloc(%0) : memref<?xf32>
- use(%1)
- cf.cond_br %arg0, ^bb3, ^bb4
-^bb3:
- cf.br ^bb5(%1 : memref<?xf32>)
-^bb4:
- cf.br ^bb5(%1 : memref<?xf32>)
-^bb5(%2: memref<?xf32>):
- %6 = bufferization.clone %1 : (memref<?xf32>) -> (memref<?xf32>)
- memref.dealloc %1 : memref<?xf32>
- cf.br ^bb6(%6 : memref<?xf32>)
-^bb6(%3: memref<?xf32>):
- cf.br ^bb7(%3 : memref<?xf32>)
-^bb7(%4: memref<?xf32>):
- test.copy(%4, %arg2) : (memref<?xf32>, memref<?xf32>) -> ()
- memref.dealloc %3 : memref<?xf32> // free %3, since %4 is a non-crit. alias of %3
- return
-}
-```
-
-Since %3 is a critical alias, BufferDeallocation introduces an additional
-temporary copy in all predecessor blocks. %3 has an additional (non-critical)
-alias %4 that extends the live range until the end of bb7. Therefore, we can
-free %3 after its last use, while taking all aliases into account. Note that %4
-does not need to be freed, since we did not introduce a copy for it.
-
-The actual introduction of buffer copies is done after the fix-point iteration
-has been terminated and all critical aliases have been detected. A critical
-alias can be either a block argument or another value that is returned by an
-operation. Copies for block arguments are handled by analyzing all predecessor
-blocks. This is primarily done by querying the `BranchOpInterface` of the
-associated branch terminators that can jump to the current block. Consider the
-following example which involves a simple branch and the critical block argument
-%2:
-
-```mlir
- custom.br ^bb1(..., %0, : ...)
- ...
- custom.br ^bb1(..., %1, : ...)
- ...
-^bb1(%2: memref<2xf32>):
- ...
-```
-
-The `BranchOpInterface` allows us to determine the actual values that will be
-passed to block bb1 and its argument %2 by analyzing its predecessor blocks.
-Once we have resolved the values %0 and %1 (that are associated with %2 in this
-sample), we can introduce a temporary buffer and clone its contents into the new
-buffer. Afterwards, we rewire the branch operands to use the newly allocated
-buffer instead. However, blocks can have implicitly defined predecessors by
-parent ops that implement the `RegionBranchOpInterface`. This can be the case if
-this block argument belongs to the entry block of a region. In this setting, we
-have to identify all predecessor regions defined by the parent operation. For
-every region, we need to get all terminator operations implementing the
-`ReturnLike` trait, indicating that they can branch to our current block.
-Finally, we can use a similar functionality as described above to add the
-temporary copy. This time, we can modify the terminator operands directly
-without touching a high-level interface.
-
-Consider the following inner-region control-flow sample that uses an imaginary
-“custom.region_if” operation. It either executes the “then” or “else” region and
-always continues to the “join” region. The “custom.region_if_yield” operation
-returns a result to the parent operation. This sample demonstrates the use of
-the `RegionBranchOpInterface` to determine predecessors in order to infer the
-high-level control flow:
-
-```mlir
-func.func @inner_region_control_flow(
- %arg0 : index,
- %arg1 : index) -> memref<?x?xf32> {
- %0 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
- %1 = custom.region_if %0 : memref<?x?xf32> -> (memref<?x?xf32>)
- then(%arg2 : memref<?x?xf32>) { // aliases: %arg4, %1
- custom.region_if_yield %arg2 : memref<?x?xf32>
- } else(%arg3 : memref<?x?xf32>) { // aliases: %arg4, %1
- custom.region_if_yield %arg3 : memref<?x?xf32>
- } join(%arg4 : memref<?x?xf32>) { // aliases: %1
- custom.region_if_yield %arg4 : memref<?x?xf32>
- }
- return %1 : memref<?x?xf32>
-}
-```
-
-
-
-Non-block arguments (other values) can become aliases when they are returned by
-dialect-specific operations. BufferDeallocation supports this behavior via the
-`RegionBranchOpInterface`. Consider the following example that uses an “scf.if”
-operation to determine the value of %2 at runtime which creates an alias:
-
-```mlir
-func.func @nested_region_control_flow(%arg0 : index, %arg1 : index) -> memref<?x?xf32> {
- %0 = arith.cmpi "eq", %arg0, %arg1 : index
- %1 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
- %2 = scf.if %0 -> (memref<?x?xf32>) {
- scf.yield %1 : memref<?x?xf32> // %2 will be an alias of %1
- } else {
- %3 = memref.alloc(%arg0, %arg1) : memref<?x?xf32> // nested allocation in a div.
- // branch
- use(%3)
- scf.yield %1 : memref<?x?xf32> // %2 will be an alias of %1
- }
- return %2 : memref<?x?xf32>
-}
-```
-
-In this example, a dealloc is inserted to release the buffer within the else
-block since it cannot be accessed by the remainder of the program. Accessing the
-`RegionBranchOpInterface`, allows us to infer that %2 is a non-critical alias of
-%1 which does not need to be tracked.
-
-```mlir
-func.func @nested_region_control_flow(%arg0: index, %arg1: index) -> memref<?x?xf32> {
- %0 = arith.cmpi "eq", %arg0, %arg1 : index
- %1 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
- %2 = scf.if %0 -> (memref<?x?xf32>) {
- scf.yield %1 : memref<?x?xf32>
- } else {
- %3 = memref.alloc(%arg0, %arg1) : memref<?x?xf32>
- use(%3)
- memref.dealloc %3 : memref<?x?xf32> // %3 can be safely freed here
- scf.yield %1 : memref<?x?xf32>
- }
- return %2 : memref<?x?xf32>
-}
-```
-
-Analogous to the previous case, we have to detect all terminator operations in
-all attached regions of “scf.if” that provides a value to its parent operation
-(in this sample via scf.yield). Querying the `RegionBranchOpInterface` allows us
-to determine the regions that “return” a result to their parent operation. Like
-before, we have to update all `ReturnLike` terminators as described above.
-Reconsider a slightly adapted version of the “custom.region_if” example from
-above that uses a nested allocation:
-
-```mlir
-func.func @inner_region_control_flow_div(
- %arg0 : index,
- %arg1 : index) -> memref<?x?xf32> {
- %0 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
- %1 = custom.region_if %0 : memref<?x?xf32> -> (memref<?x?xf32>)
- then(%arg2 : memref<?x?xf32>) { // aliases: %arg4, %1
- custom.region_if_yield %arg2 : memref<?x?xf32>
- } else(%arg3 : memref<?x?xf32>) {
- %2 = memref.alloc(%arg0, %arg1) : memref<?x?xf32> // aliases: %arg4, %1
- custom.region_if_yield %2 : memref<?x?xf32>
- } join(%arg4 : memref<?x?xf32>) { // aliases: %1
- custom.region_if_yield %arg4 : memref<?x?xf32>
- }
- return %1 : memref<?x?xf32>
-}
-```
-
-Since the allocation %2 happens in a divergent branch and cannot be safely
-deallocated in a post-dominator, %arg4 will be considered a critical alias.
-Furthermore, %arg4 is returned to its parent operation and has an alias %1. This
-causes BufferDeallocation to introduce additional copies:
-
-```mlir
-func.func @inner_region_control_flow_div(
- %arg0 : index,
- %arg1 : index) -> memref<?x?xf32> {
- %0 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
- %1 = custom.region_if %0 : memref<?x?xf32> -> (memref<?x?xf32>)
- then(%arg2 : memref<?x?xf32>) {
- %4 = bufferization.clone %arg2 : (memref<?x?xf32>) -> (memref<?x?xf32>)
- custom.region_if_yield %4 : memref<?x?xf32>
- } else(%arg3 : memref<?x?xf32>) {
- %2 = memref.alloc(%arg0, %arg1) : memref<?x?xf32>
- %5 = bufferization.clone %2 : (memref<?x?xf32>) -> (memref<?x?xf32>)
- memref.dealloc %2 : memref<?x?xf32>
- custom.region_if_yield %5 : memref<?x?xf32>
- } join(%arg4: memref<?x?xf32>) {
- %4 = bufferization.clone %arg4 : (memref<?x?xf32>) -> (memref<?x?xf32>)
- memref.dealloc %arg4 : memref<?x?xf32>
- custom.region_if_yield %4 : memref<?x?xf32>
- }
- memref.dealloc %0 : memref<?x?xf32> // %0 can be safely freed here
- return %1 : memref<?x?xf32>
-}
-```
-
-## Placement of Deallocs
-
-After introducing allocs and copies, deallocs have to be placed to free
-allocated memory and avoid memory leaks. The deallocation needs to take place
-after the last use of the given value. The position can be determined by
-calculating the common post-dominator of all values using their remaining
-non-critical aliases. A special-case is the presence of back edges: since such
-edges can cause memory leaks when a newly allocated buffer flows back to another
-part of the program. In these cases, we need to free the associated buffer
-instances from the previous iteration by inserting additional deallocs.
-
-Consider the following “scf.for” use case containing a nested structured
-control-flow if:
-
-```mlir
-func.func @loop_nested_if(
- %lb: index,
- %ub: index,
- %step: index,
- %buf: memref<2xf32>,
- %res: memref<2xf32>) {
- %0 = scf.for %i = %lb to %ub step %step
- iter_args(%iterBuf = %buf) -> memref<2xf32> {
- %1 = arith.cmpi "eq", %i, %ub : index
- %2 = scf.if %1 -> (memref<2xf32>) {
- %3 = memref.alloc() : memref<2xf32> // makes %2 a critical alias due to a
- // divergent allocation
- use(%3)
- scf.yield %3 : memref<2xf32>
- } else {
- scf.yield %iterBuf : memref<2xf32>
- }
- scf.yield %2 : memref<2xf32>
- }
- test.copy(%0, %res) : (memref<2xf32>, memref<2xf32>) -> ()
- return
-}
-```
-
-In this example, the *then* branch of the nested “scf.if” operation returns a
-newly allocated buffer.
-
-Since this allocation happens in the scope of a divergent branch, %2 becomes a
-critical alias that needs to be handled. As before, we have to insert additional
-copies to eliminate this alias using copies of %3 and %iterBuf. This guarantees
-that %2 will be a newly allocated buffer that is returned in each iteration.
-However, “returning” %2 to its alias %iterBuf turns %iterBuf into a critical
-alias as well. In other words, we have to create a copy of %2 to pass it to
-%iterBuf. Since this jump represents a back edge, and %2 will always be a new
-buffer, we have to free the buffer from the previous iteration to avoid memory
-leaks:
-
-```mlir
-func.func @loop_nested_if(
- %lb: index,
- %ub: index,
- %step: index,
- %buf: memref<2xf32>,
- %res: memref<2xf32>) {
- %4 = bufferization.clone %buf : (memref<2xf32>) -> (memref<2xf32>)
- %0 = scf.for %i = %lb to %ub step %step
- iter_args(%iterBuf = %4) -> memref<2xf32> {
- %1 = arith.cmpi "eq", %i, %ub : index
- %2 = scf.if %1 -> (memref<2xf32>) {
- %3 = memref.alloc() : memref<2xf32> // makes %2 a critical alias
- use(%3)
- %5 = bufferization.clone %3 : (memref<2xf32>) -> (memref<2xf32>)
- memref.dealloc %3 : memref<2xf32>
- scf.yield %5 : memref<2xf32>
- } else {
- %6 = bufferization.clone %iterBuf : (memref<2xf32>) -> (memref<2xf32>)
- scf.yield %6 : memref<2xf32>
- }
- %7 = bufferization.clone %2 : (memref<2xf32>) -> (memref<2xf32>)
- memref.dealloc %2 : memref<2xf32>
- memref.dealloc %iterBuf : memref<2xf32> // free backedge iteration variable
- scf.yield %7 : memref<2xf32>
- }
- test.copy(%0, %res) : (memref<2xf32>, memref<2xf32>) -> ()
- memref.dealloc %0 : memref<2xf32> // free temp copy %0
- return
-}
-```
-
-Example for loop-like control flow. The CFG contains back edges that have to be
-handled to avoid memory leaks. The bufferization is able to free the backedge
-iteration variable %iterBuf.
-
-## Private Analyses Implementations
-
-The BufferDeallocation transformation relies on one primary control-flow
-analysis: BufferPlacementAliasAnalysis. Furthermore, we also use dominance and
-liveness to place and move nodes. The liveness analysis determines the live
-range of a given value. Within this range, a value is alive and can or will be
-used in the course of the program. After this range, the value is dead and can
-be discarded - in our case, the buffer can be freed. To place the allocs, we
-need to know from which position a value will be alive. The allocs have to be
-placed in front of this position. However, the most important analysis is the
-alias analysis that is needed to introduce copies and to place all
-deallocations.
-
-# Post Phase
-
-In order to limit the complexity of the BufferDeallocation transformation, some
-tiny code-polishing/optimization transformations are not applied on-the-fly
-during placement. Currently, a canonicalization pattern is added to the clone
-operation to reduce the appearance of unnecessary clones.
-
-Note: further transformations might be added to the post-pass phase in the
-future.
-
-## Clone Canonicalization
-
-During placement of clones it may happen, that unnecessary clones are inserted.
-If these clones appear with their corresponding dealloc operation within the
-same block, we can use the canonicalizer to remove these unnecessary operations.
-Note, that this step needs to take place after the insertion of clones and
-deallocs in the buffer deallocation step. The canonicalization inludes both, the
-newly created target value from the clone operation and the source operation.
-
-## Canonicalization of the Source Buffer of the Clone Operation
-
-In this case, the source of the clone operation can be used instead of its
-target. The unused allocation and deallocation operations that are defined for
-this clone operation are also removed. Here is a working example generated by
-the BufferDeallocation pass that allocates a buffer with dynamic size. A deeper
-analysis of this sample reveals that the highlighted operations are redundant
-and can be removed.
-
-```mlir
-func.func @dynamic_allocation(%arg0: index, %arg1: index) -> memref<?x?xf32> {
- %1 = memref.alloc(%arg0, %arg1) : memref<?x?xf32>
- %2 = bufferization.clone %1 : (memref<?x?xf32>) -> (memref<?x?xf32>)
- memref.dealloc %1 : memref<?x?xf32>
- return %2 : memref<?x?xf32>
-}
-```
-
-Will be transformed to:
-
-```mlir
-func.func @dynamic_allocation(%arg0: index, %arg1: index) -> memref<?x?xf32> {
- %1 = memref.alloc(%arg0, %arg1) : memref<?x?xf32>
- return %1 : memref<?x?xf32>
-}
-```
-
-In this case, the additional copy %2 can be replaced with its original source
-buffer %1. This also applies to the associated dealloc operation of %1.
-
-## Canonicalization of the Target Buffer of the Clone Operation
-
-In this case, the target buffer of the clone operation can be used instead of
-its source. The unused deallocation operation that is defined for this clone
-operation is also removed.
-
-Consider the following example where a generic test operation writes the result
-to %temp and then copies %temp to %result. However, these two operations can be
-merged into a single step. Canonicalization removes the clone operation and
-%temp, and replaces the uses of %temp with %result:
-
-```mlir
-func.func @reuseTarget(%arg0: memref<2xf32>, %result: memref<2xf32>){
- %temp = memref.alloc() : memref<2xf32>
- test.generic {
- args_in = 1 : i64,
- args_out = 1 : i64,
- indexing_maps = [#map0, #map0],
- iterator_types = ["parallel"]} %arg0, %temp {
- ^bb0(%gen2_arg0: f32, %gen2_arg1: f32):
- %tmp2 = math.exp %gen2_arg0 : f32
- test.yield %tmp2 : f32
- }: memref<2xf32>, memref<2xf32>
- %result = bufferization.clone %temp : (memref<2xf32>) -> (memref<2xf32>)
- memref.dealloc %temp : memref<2xf32>
- return
-}
-```
-
-Will be transformed to:
-
-```mlir
-func.func @reuseTarget(%arg0: memref<2xf32>, %result: memref<2xf32>){
- test.generic {
- args_in = 1 : i64,
- args_out = 1 : i64,
- indexing_maps = [#map0, #map0],
- iterator_types = ["parallel"]} %arg0, %result {
- ^bb0(%gen2_arg0: f32, %gen2_arg1: f32):
- %tmp2 = math.exp %gen2_arg0 : f32
- test.yield %tmp2 : f32
- }: memref<2xf32>, memref<2xf32>
- return
-}
-```
-
-## Known Limitations
-
-BufferDeallocation introduces additional clones from “memref” dialect
-(“bufferization.clone”). Analogous, all deallocations use the “memref”
-dialect-free operation “memref.dealloc”. The actual copy process is realized
-using “test.copy”. Furthermore, buffers are essentially immutable after their
-creation in a block. Another limitations are known in the case using
-unstructered control flow.
diff --git a/mlir/docs/OwnershipBasedBufferDeallocation.md b/mlir/docs/OwnershipBasedBufferDeallocation.md
index 9036c811c5daf..f5fa01c4c49cc 100644
--- a/mlir/docs/OwnershipBasedBufferDeallocation.md
+++ b/mlir/docs/OwnershipBasedBufferDeallocation.md
@@ -5,9 +5,7 @@
One-Shot Bufferize does not deallocate any buffers that it allocates. After
running One-Shot Bufferize, the resulting IR may have a number of `memref.alloc`
ops, but no `memref.dealloc` ops. Buffer dellocation is delegated to the
-`-ownership-based-buffer-deallocation` pass. This pass supersedes the now
-deprecated `-buffer-deallocation` pass, which does not work well with
-One-Shot Bufferize.
+`-ownership-based-buffer-deallocation` pass.
On a high level, buffers are "owned" by a basic block. Ownership materializes
as an `i1` SSA value and can be thought of as "responsibility to deallocate". It
diff --git a/mlir/docs/includes/img/branch_example_post_move.svg b/mlir/docs/includes/img/branch_example_post_move.svg
deleted file mode 100644
index 870df495a13c6..0000000000000
--- a/mlir/docs/includes/img/branch_example_post_move.svg
+++ /dev/null
@@ -1,419 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="199.99995mm"
- height="173.75687mm"
- viewBox="0 0 199.99995 173.75687"
- version="1.1"
- id="svg8"
- inkscape:version="1.0.1 (c497b03c, 2020-09-10)"
- sodipodi:docname="branch_hoisting_after.svg">
- <defs
- id="defs2">
- <rect
- x="18.139799"
- y="132.9565"
- width="42.875893"
- height="13.192582"
- id="rect1896" />
- <rect
- x="73.476562"
- y="69.033791"
- width="111.61496"
- height="41.205557"
- id="rect1370" />
- <rect
- x="88.85537"
- y="63.907516"
- width="32.124634"
- height="21.53034"
- id="rect3730" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679" />
- <rect
- x="41.227337"
- y="-14.998642"
- width="72.234138"
- height="11.239376"
- id="rect3669" />
- <marker
- style="overflow:visible"
- id="marker3503"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3501" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3443"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3441" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3389"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3387" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3341"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3339" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3141"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3139" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker2967"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lstart"
- inkscape:isstock="true">
- <path
- transform="matrix(0.8,0,0,0.8,10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2965" />
- </marker>
- <marker
- style="overflow:visible"
- id="Arrow1Send"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Send"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2664" />
- </marker>
- <marker
- style="overflow:visible"
- id="Arrow1Lstart"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lstart"
- inkscape:isstock="true">
- <path
- transform="matrix(0.8,0,0,0.8,10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2649" />
- </marker>
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679-2" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3692" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="1.2592908"
- inkscape:cx="377.95267"
- inkscape:cy="328.35943"
- inkscape:document-units="mm"
- inkscape:current-layer="layer1"
- inkscape:document-rotation="0"
- showgrid="false"
- inkscape:window-width="1680"
- inkscape:window-height="963"
- inkscape:window-x="0"
- inkscape:window-y="93"
- inkscape:window-maximized="1"
- showguides="true"
- fit-margin-top="0"
- fit-margin-left="0"
- fit-margin-right="0"
- fit-margin-bottom="0"
- lock-margins="false" />
- <metadata
- id="metadata5">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(60.000002,15.000516)"
- style="display:inline">
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837"
- width="79.741898"
- height="38.498253"
- x="0.12905283"
- y="0.129053"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9"
- width="79.741898"
- height="38.498253"
- x="-59.870949"
- y="60.129051"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect837-9-8"
- width="79.741898"
- height="38.498253"
- x="60.129051"
- y="60.129051"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9-8-9"
- width="79.741898"
- height="38.498253"
- x="0.12905283"
- y="120.12905"
- ry="6.741148" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker3141);paint-order:normal"
- d="M 59.249128,38.627306 80.750874,60.129051"
- id="path3329"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837"
- inkscape:connection-end="#rect837-9-8" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3341)"
- d="M 20.750874,38.627306 -0.75087247,60.129051"
- id="path3337"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837"
- inkscape:connection-end="#rect837-9" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3389)"
- d="M -0.75087304,98.627304 20.750875,120.12905"
- id="path3385"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9"
- inkscape:connection-end="#rect837-9-8-9" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3443)"
- d="M 80.750874,98.627304 59.249128,120.12905"
- id="path3439"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9-8"
- inkscape:connection-end="#rect837-9-8-9" />
- <path
- style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3503)"
- d="M 41.227338,-14.998642 41.386551,0.50922611"
- id="path3499"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0" />
- <text
- xml:space="preserve"
- id="text3667"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3669);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
- x="44.769436"
- y="-7.8602829"
- id="text3675"><tspan
- sodipodi:role="line"
- id="tspan3673"
- x="44.769436"
- y="-7.8602829"
- style="font-size:5.64444px;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none">in: %arg0, %arg1, %arg2</tspan></text>
- <text
- xml:space="preserve"
- id="text3677"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(25.051785,-8.0877048)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb0</tspan></tspan></text>
- <text
- xml:space="preserve"
- id="text3728"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3730);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="94.617386"
- y="66.288452"
- id="text3736"><tspan
- sodipodi:role="line"
- id="tspan3734"
- x="94.617386"
- y="66.288452"
- style="font-size:5.64444px;stroke-width:0.264583">bb2</tspan></text>
- <text
- xml:space="preserve"
- id="text3677-0"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679-2);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(-34.833839,51.912295)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb1
-</tspan></tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="26.288532"
- y="126.28845"
- id="text3736-6"><tspan
- sodipodi:role="line"
- id="tspan3734-5"
- x="26.288532"
- y="126.28845"
- style="font-size:5.64444px;stroke-width:0.264583">bb3 (%1)</tspan></text>
- <text
- xml:space="preserve"
- id="text1368"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect1370);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(9.8574558,-6.1666356)"><tspan
- x="73.476562"
- y="74.182797"><tspan
- style="font-size:5.64444px">
-</tspan></tspan><tspan
- x="73.476562"
- y="81.238347"><tspan
- style="font-size:5.64444px">use(%0)
-</tspan></tspan><tspan
- x="73.476562"
- y="88.293896"><tspan
- style="font-size:5.64444px">cf.br bb3(%0)</tspan></tspan></text>
- <text
- xml:space="preserve"
- id="text1894"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect1896);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="16.620224"
- y="137.49144"
- id="text1902"><tspan
- sodipodi:role="line"
- id="tspan1900"
- x="16.620224"
- y="137.49144"
- style="font-size:5.64444px;stroke-width:0.264583">copy (%1, arg2)</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="76.269608"
- y="111.63254"
- id="text3165"><tspan
- sodipodi:role="line"
- id="tspan3163"
- x="76.269608"
- y="111.63254"
- style="font-size:5.64444px;stroke-width:0.264583">%0</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-12.065383"
- y="111.08959"
- id="text3165-8"><tspan
- sodipodi:role="line"
- id="tspan3163-3"
- x="-12.065383"
- y="111.08959"
- style="font-size:5.64444px;stroke-width:0.264583">%arg1</tspan><tspan
- sodipodi:role="line"
- x="-12.065383"
- y="118.14514"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185" /></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="21.911886"
- y="15.884925"
- id="text3409"><tspan
- sodipodi:role="line"
- id="tspan3407"
- x="21.911886"
- y="15.884925"
- style="font-size:5.64444px;fill:#008000;stroke-width:0.264583">%0 = memref.alloc()</tspan></text>
- </g>
-</svg>
diff --git a/mlir/docs/includes/img/branch_example_pre_move.svg b/mlir/docs/includes/img/branch_example_pre_move.svg
deleted file mode 100644
index 5eb15fd13946e..0000000000000
--- a/mlir/docs/includes/img/branch_example_pre_move.svg
+++ /dev/null
@@ -1,409 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="199.99995mm"
- height="173.75687mm"
- viewBox="0 0 199.99995 173.75687"
- version="1.1"
- id="svg8"
- inkscape:version="1.0.1 (c497b03c, 2020-09-10)"
- sodipodi:docname="branch_hoisting_before.svg">
- <defs
- id="defs2">
- <rect
- x="18.139799"
- y="132.9565"
- width="42.875893"
- height="13.192582"
- id="rect1896" />
- <rect
- x="73.476562"
- y="69.033791"
- width="111.61496"
- height="41.205557"
- id="rect1370" />
- <rect
- x="88.85537"
- y="63.907516"
- width="32.124634"
- height="21.53034"
- id="rect3730" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679" />
- <rect
- x="41.227337"
- y="-14.998642"
- width="72.234138"
- height="11.239376"
- id="rect3669" />
- <marker
- style="overflow:visible"
- id="marker3503"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3501" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3443"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3441" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3389"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3387" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3341"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3339" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3141"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3139" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker2967"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lstart"
- inkscape:isstock="true">
- <path
- transform="matrix(0.8,0,0,0.8,10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2965" />
- </marker>
- <marker
- style="overflow:visible"
- id="Arrow1Send"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Send"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2664" />
- </marker>
- <marker
- style="overflow:visible"
- id="Arrow1Lstart"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lstart"
- inkscape:isstock="true">
- <path
- transform="matrix(0.8,0,0,0.8,10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2649" />
- </marker>
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679-2" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3692" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="1.2592908"
- inkscape:cx="377.95267"
- inkscape:cy="74.248148"
- inkscape:document-units="mm"
- inkscape:current-layer="layer1"
- inkscape:document-rotation="0"
- showgrid="false"
- inkscape:window-width="1680"
- inkscape:window-height="963"
- inkscape:window-x="0"
- inkscape:window-y="93"
- inkscape:window-maximized="1"
- showguides="true"
- fit-margin-top="0"
- fit-margin-left="0"
- fit-margin-right="0"
- fit-margin-bottom="0"
- lock-margins="false" />
- <metadata
- id="metadata5">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(60.000002,15.000516)"
- style="display:inline">
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837"
- width="79.741898"
- height="38.498253"
- x="0.12905283"
- y="0.129053"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9"
- width="79.741898"
- height="38.498253"
- x="-59.870949"
- y="60.129051"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect837-9-8"
- width="79.741898"
- height="38.498253"
- x="60.129051"
- y="60.129051"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9-8-9"
- width="79.741898"
- height="38.498253"
- x="0.12905283"
- y="120.12905"
- ry="6.741148" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker3141);paint-order:normal"
- d="M 59.249128,38.627306 80.750874,60.129051"
- id="path3329"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837"
- inkscape:connection-end="#rect837-9-8" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3341)"
- d="M 20.750874,38.627306 -0.75087247,60.129051"
- id="path3337"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837"
- inkscape:connection-end="#rect837-9" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3389)"
- d="M -0.75087304,98.627304 20.750875,120.12905"
- id="path3385"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9"
- inkscape:connection-end="#rect837-9-8-9" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3443)"
- d="M 80.750874,98.627304 59.249128,120.12905"
- id="path3439"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9-8"
- inkscape:connection-end="#rect837-9-8-9" />
- <path
- style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3503)"
- d="M 41.227338,-14.998642 41.386551,0.50922611"
- id="path3499"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0" />
- <text
- xml:space="preserve"
- id="text3667"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3669);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
- x="44.769436"
- y="-7.8602829"
- id="text3675"><tspan
- sodipodi:role="line"
- id="tspan3673"
- x="44.769436"
- y="-7.8602829"
- style="font-size:5.64444px;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none">in: %arg0, %arg1, %arg2</tspan></text>
- <text
- xml:space="preserve"
- id="text3677"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(25.051785,-8.0877048)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb0</tspan></tspan></text>
- <text
- xml:space="preserve"
- id="text3728"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3730);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="94.617386"
- y="66.288452"
- id="text3736"><tspan
- sodipodi:role="line"
- id="tspan3734"
- x="94.617386"
- y="66.288452"
- style="font-size:5.64444px;stroke-width:0.264583">bb2</tspan></text>
- <text
- xml:space="preserve"
- id="text3677-0"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679-2);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(-34.833839,51.912295)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb1
-</tspan></tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="26.288532"
- y="126.28845"
- id="text3736-6"><tspan
- sodipodi:role="line"
- id="tspan3734-5"
- x="26.288532"
- y="126.28845"
- style="font-size:5.64444px;stroke-width:0.264583">bb3 (%1)</tspan></text>
- <text
- xml:space="preserve"
- id="text1368"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect1370);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(8.4353227,-0.28369449)"><tspan
- x="73.476562"
- y="74.182797"><tspan
- style="fill:#d40000;fill-opacity:1">%0 = memref.alloc()</tspan><tspan
- style="font-size:5.64444px">
-</tspan></tspan><tspan
- x="73.476562"
- y="81.238347"><tspan
- style="font-size:5.64444px">use(%0)
-</tspan></tspan><tspan
- x="73.476562"
- y="88.293896"><tspan
- style="font-size:5.64444px">cf.br bb3(%0)</tspan></tspan></text>
- <text
- xml:space="preserve"
- id="text1894"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect1896);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="16.620224"
- y="137.49144"
- id="text1902"><tspan
- sodipodi:role="line"
- id="tspan1900"
- x="16.620224"
- y="137.49144"
- style="font-size:5.64444px;stroke-width:0.264583">copy (%1, arg2)</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="76.269608"
- y="111.63254"
- id="text3165"><tspan
- sodipodi:role="line"
- id="tspan3163"
- x="76.269608"
- y="111.63254"
- style="font-size:5.64444px;stroke-width:0.264583">%0</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-12.065383"
- y="111.08959"
- id="text3165-8"><tspan
- sodipodi:role="line"
- id="tspan3163-3"
- x="-12.065383"
- y="111.08959"
- style="font-size:5.64444px;stroke-width:0.264583">%arg1</tspan><tspan
- sodipodi:role="line"
- x="-12.065383"
- y="118.14514"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185" /></text>
- </g>
-</svg>
diff --git a/mlir/docs/includes/img/nested_branch_example_post_move.svg b/mlir/docs/includes/img/nested_branch_example_post_move.svg
deleted file mode 100644
index 27923627ad3d2..0000000000000
--- a/mlir/docs/includes/img/nested_branch_example_post_move.svg
+++ /dev/null
@@ -1,759 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="319.99994mm"
- height="354.75635mm"
- viewBox="0 0 319.99993 354.75636"
- version="1.1"
- id="svg8"
- inkscape:version="1.0.1 (c497b03c, 2020-09-10)"
- sodipodi:docname="copy_branch_hoisting_after.svg">
- <defs
- id="defs2">
- <rect
- x="-44.320522"
- y="314.26837"
- width="57.491421"
- height="11.257062"
- id="rect9344" />
- <rect
- x="133.78227"
- y="73.447647"
- width="53.069004"
- height="18.493744"
- id="rect9332" />
- <marker
- style="overflow:visible"
- id="marker8973"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8971" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8877"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8875" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8787"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8785" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8703"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8701" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8625"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8623" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8553"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8551" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8487"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8485" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8415"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8413" />
- </marker>
- <rect
- x="18.139799"
- y="132.9565"
- width="42.875893"
- height="13.192582"
- id="rect1896" />
- <rect
- x="73.476562"
- y="69.033791"
- width="111.61496"
- height="41.205559"
- id="rect1370" />
- <rect
- x="88.85537"
- y="63.907516"
- width="32.124634"
- height="21.53034"
- id="rect3730" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679" />
- <rect
- x="41.227337"
- y="-14.998642"
- width="72.234138"
- height="11.239376"
- id="rect3669" />
- <marker
- style="overflow:visible"
- id="marker3503"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3501" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3341"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3339" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker2967"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lstart"
- inkscape:isstock="true">
- <path
- transform="matrix(0.8,0,0,0.8,10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2965" />
- </marker>
- <marker
- style="overflow:visible"
- id="Arrow1Send"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Send"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2664" />
- </marker>
- <marker
- style="overflow:visible"
- id="Arrow1Lstart"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lstart"
- inkscape:isstock="true">
- <path
- transform="matrix(0.8,0,0,0.8,10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2649" />
- </marker>
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679-2" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3692" />
- <marker
- style="overflow:visible"
- id="marker3503-8"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3501-9" />
- </marker>
- <rect
- x="9.5690403"
- y="9.2272892"
- width="33.3377"
- height="13.439011"
- id="rect3679-0" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect7499" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679-2-4" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect7502" />
- <rect
- x="73.476562"
- y="69.033791"
- width="111.61496"
- height="41.205559"
- id="rect1370-5" />
- <rect
- x="73.476562"
- y="69.033791"
- width="111.61496"
- height="41.205559"
- id="rect7505" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.79269723"
- inkscape:cx="505.54239"
- inkscape:cy="988.76803"
- inkscape:document-units="mm"
- inkscape:current-layer="layer1"
- inkscape:document-rotation="0"
- showgrid="false"
- inkscape:window-width="1680"
- inkscape:window-height="963"
- inkscape:window-x="0"
- inkscape:window-y="93"
- inkscape:window-maximized="1"
- showguides="true"
- fit-margin-top="0"
- fit-margin-left="0"
- fit-margin-right="0"
- fit-margin-bottom="0"
- lock-margins="false" />
- <metadata
- id="metadata5">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(60.000002,15.000695)"
- style="display:inline">
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837"
- width="79.741898"
- height="38.498253"
- x="0.12905283"
- y="0.129053"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9"
- width="79.741898"
- height="38.498253"
- x="-59.870949"
- y="60.129051"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9-8-9"
- width="79.741898"
- height="38.498253"
- x="-59.870949"
- y="240.12854"
- ry="6.741148" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3341)"
- d="M 20.750874,38.627306 -0.75087247,60.129051"
- id="path3337"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837"
- inkscape:connection-end="#rect837-9" />
- <path
- style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3503)"
- d="M 41.227338,-14.998642 41.386551,0.50922611"
- id="path3499"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0" />
- <text
- xml:space="preserve"
- id="text3667"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3669);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
- x="44.769436"
- y="-7.8602829"
- id="text3675"><tspan
- sodipodi:role="line"
- id="tspan3673"
- x="44.769436"
- y="-7.8602829"
- style="font-size:5.64444px;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none">in: %arg0, %arg1, %arg2, %arg3</tspan></text>
- <text
- xml:space="preserve"
- id="text3677"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(25.051785,-8.0877048)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb0</tspan></tspan></text>
- <text
- xml:space="preserve"
- id="text3728"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3730);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- id="text3677-0"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679-2);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(-34.833839,51.912295)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb1
-</tspan></tspan></text>
- <text
- xml:space="preserve"
- id="text1894"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect1896);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-33.069748"
- y="171.81396"
- id="text3165-8"><tspan
- sodipodi:role="line"
- id="tspan3163-3"
- x="-33.069748"
- y="171.81396"
- style="font-size:5.64444px;stroke-width:0.264583">%5</tspan><tspan
- sodipodi:role="line"
- x="-33.069748"
- y="178.86952"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185" /></text>
- <rect
- style="display:inline;opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-4"
- width="79.741898"
- height="38.498253"
- x="120.12905"
- y="60.128536"
- ry="6.741148" />
- <rect
- style="display:inline;opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9-89"
- width="79.741898"
- height="38.498253"
- x="60.129051"
- y="120.12854"
- ry="6.741148" />
- <rect
- style="display:inline;opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect837-9-8"
- width="79.741898"
- height="38.498253"
- x="180.12904"
- y="120.12849"
- ry="6.741148" />
- <rect
- style="display:inline;opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9-8-9-8"
- width="79.741898"
- height="38.498253"
- x="120.12905"
- y="180.12854"
- ry="6.741148" />
- <text
- xml:space="preserve"
- id="text3677-6"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679-0);display:inline;fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(136.72017,51.911779)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb2 (%0)</tspan></tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="214.61739"
- y="126.28793"
- id="text3736"><tspan
- sodipodi:role="line"
- id="tspan3734"
- x="214.61739"
- y="126.28793"
- style="font-size:5.64444px;stroke-width:0.264583">bb4</tspan></text>
- <text
- xml:space="preserve"
- id="text3677-0-7"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679-2-4);display:inline;fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(85.166161,111.91178)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb3
-</tspan></tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="146.28853"
- y="186.28793"
- id="text3736-6"><tspan
- sodipodi:role="line"
- id="tspan3734-5"
- x="146.28853"
- y="186.28793"
- style="font-size:5.64444px;stroke-width:0.264583">bb5 (%2)</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="114.09232"
- y="171.63202"
- id="text3165-8-0"><tspan
- sodipodi:role="line"
- id="tspan3163-3-8"
- x="114.09232"
- y="171.63202"
- style="font-size:5.64444px;stroke-width:0.264583">%1</tspan><tspan
- sodipodi:role="line"
- x="114.09232"
- y="178.68758"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185-9" /></text>
- <rect
- style="display:inline;opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9-8-9-8-4"
- width="79.741898"
- height="38.498253"
- x="-59.870949"
- y="300.12836"
- ry="6.741148" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-33.711475"
- y="306.28775"
- id="text3736-6-7"><tspan
- sodipodi:role="line"
- id="tspan3734-5-8"
- x="-33.711475"
- y="306.28775"
- style="font-size:5.64444px;stroke-width:0.264583">bb7 (%4)</tspan></text>
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8415)"
- d="M 76.594903,37.675473 123.4051,61.080369"
- id="path8411"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837"
- inkscape:connection-end="#rect837-4" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8487)"
- d="m 179.24914,98.626789 21.50171,21.501701"
- id="path8483"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-4"
- inkscape:connection-end="#rect837-9-8" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8553)"
- d="M 140.75087,98.626789 119.24913,120.12854"
- id="path8549"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-4"
- inkscape:connection-end="#rect837-9-89" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8625)"
- d="m 119.24913,158.62679 21.50174,21.50175"
- id="path8621"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-end="#rect837-9-8-9-8"
- inkscape:connection-start="#rect837-9-89" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8703)"
- d="m 200.75089,158.62674 -21.50178,21.5018"
- id="path8699"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9-8"
- inkscape:connection-end="#rect837-9-8-9-8" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8787)"
- d="M 120.17193,212.65369 19.828068,246.10164"
- id="path8783"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-end="#rect837-9-8-9"
- inkscape:connection-start="#rect837-9-8-9-8" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8877)"
- d="M -20,98.627304 V 240.12854"
- id="path8873"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9"
- inkscape:connection-end="#rect837-9-8-9" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8973)"
- d="m -20,278.62679 v 21.50157"
- id="path8969"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9-8-9"
- inkscape:connection-end="#rect837-9-8-9-8-4" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-33.711472"
- y="246.28775"
- id="text3736-6-7-3"><tspan
- sodipodi:role="line"
- id="tspan3734-5-8-0"
- x="-33.711472"
- y="246.28775"
- style="font-size:5.64444px;stroke-width:0.264583">bb6 (%3)</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="194.1761"
- y="171.632"
- id="text3165-8-0-4"><tspan
- sodipodi:role="line"
- id="tspan3163-3-8-8"
- x="194.1761"
- y="171.632"
- style="font-size:5.64444px;stroke-width:0.264583">%1</tspan><tspan
- sodipodi:role="line"
- x="194.1761"
- y="178.68756"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185-9-0" /></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="64.926964"
- y="236.35626"
- id="text3165-8-0-0"><tspan
- sodipodi:role="line"
- id="tspan3163-3-8-0"
- x="64.926964"
- y="236.35626"
- style="font-size:5.64444px;stroke-width:0.264583">%6</tspan><tspan
- sodipodi:role="line"
- x="64.926964"
- y="243.41182"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185-9-6" /></text>
- <text
- xml:space="preserve"
- id="text9330"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect9332);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="137.07773"
- y="78.674141"
- id="text9338"><tspan
- sodipodi:role="line"
- id="tspan9336"
- x="137.07773"
- y="78.674141"
- style="font-size:5.64444px;fill:#999999;stroke-width:0.264583">%1 = memref.alloc(%0)</tspan><tspan
- sodipodi:role="line"
- x="137.07773"
- y="85.729691"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan9340">use(%1)</tspan></text>
- <text
- xml:space="preserve"
- id="text9342"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect9344);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-size:5.64444px;line-height:1.25;font-family:sans-serif;stroke-width:0.264583"
- x="-45.424786"
- y="321.90707"
- id="text9350"><tspan
- sodipodi:role="line"
- id="tspan9348"
- x="-45.424786"
- y="321.90707"
- style="stroke-width:0.264583">copy(%4, %arg2)</tspan><tspan
- sodipodi:role="line"
- x="-45.424786"
- y="328.96262"
- style="fill:#008000;stroke-width:0.264583"
- id="tspan9569">dealloc %3</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-15.402786"
- y="291.8205"
- id="text3165-8-0-0-4"><tspan
- sodipodi:role="line"
- id="tspan3163-3-8-0-1"
- x="-15.402786"
- y="291.8205"
- style="font-size:5.64444px;stroke-width:0.264583">%3</tspan><tspan
- sodipodi:role="line"
- x="-15.402786"
- y="298.87604"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185-9-6-6" /></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-45.424786"
- y="77.928955"
- id="text9338-9"><tspan
- sodipodi:role="line"
- id="tspan9336-0"
- x="-45.424786"
- y="77.928955"
- style="font-size:5.64444px;fill:#008000;stroke-width:0.264583">%5 = memref.alloc(%d0)</tspan><tspan
- sodipodi:role="line"
- x="-45.424786"
- y="84.984505"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan9340-6">copy(%arg1, %5)</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="135.37999"
- y="198.54033"
- id="text9338-8"><tspan
- sodipodi:role="line"
- id="tspan9336-2"
- x="135.37999"
- y="198.54033"
- style="font-size:5.64444px;fill:#008000;stroke-width:0.264583">%6 = memref.alloc(%d1)</tspan><tspan
- sodipodi:role="line"
- x="135.37999"
- y="205.59589"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan9340-1">copy(%1, %6)</tspan><tspan
- sodipodi:role="line"
- x="135.37999"
- y="212.65143"
- style="font-size:5.64444px;fill:#999999;stroke-width:0.264583"
- id="tspan9567">dealloc %1</tspan></text>
- </g>
-</svg>
diff --git a/mlir/docs/includes/img/nested_branch_example_pre_move.svg b/mlir/docs/includes/img/nested_branch_example_pre_move.svg
deleted file mode 100644
index 9f2c603511f84..0000000000000
--- a/mlir/docs/includes/img/nested_branch_example_pre_move.svg
+++ /dev/null
@@ -1,717 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="319.99994mm"
- height="354.75635mm"
- viewBox="0 0 319.99993 354.75636"
- version="1.1"
- id="svg8"
- inkscape:version="1.0.1 (c497b03c, 2020-09-10)"
- sodipodi:docname="copy_branch_hoisting_before.svg">
- <defs
- id="defs2">
- <rect
- x="-44.320522"
- y="314.26837"
- width="57.491421"
- height="11.257062"
- id="rect9344" />
- <rect
- x="133.78227"
- y="73.447647"
- width="53.069004"
- height="18.493744"
- id="rect9332" />
- <marker
- style="overflow:visible"
- id="marker8973"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8971" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8877"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8875" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8787"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8785" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8703"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8701" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8625"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8623" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8553"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8551" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8487"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8485" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker8415"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path8413" />
- </marker>
- <rect
- x="18.139799"
- y="132.9565"
- width="42.875893"
- height="13.192582"
- id="rect1896" />
- <rect
- x="73.476562"
- y="69.033791"
- width="111.61496"
- height="41.205559"
- id="rect1370" />
- <rect
- x="88.85537"
- y="63.907516"
- width="32.124634"
- height="21.53034"
- id="rect3730" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679" />
- <rect
- x="41.227337"
- y="-14.998642"
- width="72.234138"
- height="11.239376"
- id="rect3669" />
- <marker
- style="overflow:visible"
- id="marker3503"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3501" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3341"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3339" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker2967"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lstart"
- inkscape:isstock="true">
- <path
- transform="matrix(0.8,0,0,0.8,10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2965" />
- </marker>
- <marker
- style="overflow:visible"
- id="Arrow1Send"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Send"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2664" />
- </marker>
- <marker
- style="overflow:visible"
- id="Arrow1Lstart"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lstart"
- inkscape:isstock="true">
- <path
- transform="matrix(0.8,0,0,0.8,10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2649" />
- </marker>
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679-2" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3692" />
- <marker
- style="overflow:visible"
- id="marker3503-8"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3501-9" />
- </marker>
- <rect
- x="9.5690403"
- y="9.2272892"
- width="33.3377"
- height="13.439011"
- id="rect3679-0" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect7499" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679-2-4" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect7502" />
- <rect
- x="73.476562"
- y="69.033791"
- width="111.61496"
- height="41.205559"
- id="rect1370-5" />
- <rect
- x="73.476562"
- y="69.033791"
- width="111.61496"
- height="41.205559"
- id="rect7505" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.65810543"
- inkscape:cx="432.43428"
- inkscape:cy="876.48446"
- inkscape:document-units="mm"
- inkscape:current-layer="layer1"
- inkscape:document-rotation="0"
- showgrid="false"
- inkscape:window-width="1680"
- inkscape:window-height="963"
- inkscape:window-x="0"
- inkscape:window-y="93"
- inkscape:window-maximized="1"
- showguides="true"
- fit-margin-top="0"
- fit-margin-left="0"
- fit-margin-right="0"
- fit-margin-bottom="0"
- lock-margins="false" />
- <metadata
- id="metadata5">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(60.000002,15.000695)"
- style="display:inline">
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837"
- width="79.741898"
- height="38.498253"
- x="0.12905283"
- y="0.129053"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9"
- width="79.741898"
- height="38.498253"
- x="-59.870949"
- y="60.129051"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9-8-9"
- width="79.741898"
- height="38.498253"
- x="-59.870949"
- y="240.12854"
- ry="6.741148" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3341)"
- d="M 20.750874,38.627306 -0.75087247,60.129051"
- id="path3337"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837"
- inkscape:connection-end="#rect837-9" />
- <path
- style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3503)"
- d="M 41.227338,-14.998642 41.386551,0.50922611"
- id="path3499"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0" />
- <text
- xml:space="preserve"
- id="text3667"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3669);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
- x="44.769436"
- y="-7.8602829"
- id="text3675"><tspan
- sodipodi:role="line"
- id="tspan3673"
- x="44.769436"
- y="-7.8602829"
- style="font-size:5.64444px;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none">in: %arg0, %arg1, %arg2, %arg3</tspan></text>
- <text
- xml:space="preserve"
- id="text3677"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(25.051785,-8.0877048)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb0</tspan></tspan></text>
- <text
- xml:space="preserve"
- id="text3728"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3730);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- id="text3677-0"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679-2);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(-34.833839,51.912295)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb1
-</tspan></tspan></text>
- <text
- xml:space="preserve"
- id="text1894"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect1896);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-41.41415"
- y="171.27377"
- id="text3165-8"><tspan
- sodipodi:role="line"
- id="tspan3163-3"
- x="-41.41415"
- y="171.27377"
- style="font-size:5.64444px;stroke-width:0.264583">%arg1</tspan><tspan
- sodipodi:role="line"
- x="-41.41415"
- y="178.32933"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185" /></text>
- <rect
- style="display:inline;opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-4"
- width="79.741898"
- height="38.498253"
- x="120.12905"
- y="60.128536"
- ry="6.741148" />
- <rect
- style="display:inline;opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9-89"
- width="79.741898"
- height="38.498253"
- x="60.129051"
- y="120.12854"
- ry="6.741148" />
- <rect
- style="display:inline;opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect837-9-8"
- width="79.741898"
- height="38.498253"
- x="180.12904"
- y="120.12849"
- ry="6.741148" />
- <rect
- style="display:inline;opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9-8-9-8"
- width="79.741898"
- height="38.498253"
- x="120.12905"
- y="180.12854"
- ry="6.741148" />
- <text
- xml:space="preserve"
- id="text3677-6"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679-0);display:inline;fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(136.72017,51.911779)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb2 (%0)</tspan></tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="214.61739"
- y="126.28793"
- id="text3736"><tspan
- sodipodi:role="line"
- id="tspan3734"
- x="214.61739"
- y="126.28793"
- style="font-size:5.64444px;stroke-width:0.264583">bb4</tspan></text>
- <text
- xml:space="preserve"
- id="text3677-0-7"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679-2-4);display:inline;fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(85.166161,111.91178)"><tspan
- x="9.5683594"
- y="14.376156"><tspan
- style="font-size:5.64444px">bb3
-</tspan></tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="146.28853"
- y="186.28793"
- id="text3736-6"><tspan
- sodipodi:role="line"
- id="tspan3734-5"
- x="146.28853"
- y="186.28793"
- style="font-size:5.64444px;stroke-width:0.264583">bb5 (%2)</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="114.09232"
- y="171.63202"
- id="text3165-8-0"><tspan
- sodipodi:role="line"
- id="tspan3163-3-8"
- x="114.09232"
- y="171.63202"
- style="font-size:5.64444px;stroke-width:0.264583">%1</tspan><tspan
- sodipodi:role="line"
- x="114.09232"
- y="178.68758"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185-9" /></text>
- <rect
- style="display:inline;opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9-8-9-8-4"
- width="79.741898"
- height="38.498253"
- x="-59.870949"
- y="300.12836"
- ry="6.741148" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-33.711475"
- y="306.28775"
- id="text3736-6-7"><tspan
- sodipodi:role="line"
- id="tspan3734-5-8"
- x="-33.711475"
- y="306.28775"
- style="font-size:5.64444px;stroke-width:0.264583">bb7 (%4)</tspan></text>
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8415)"
- d="M 76.594903,37.675473 123.4051,61.080369"
- id="path8411"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837"
- inkscape:connection-end="#rect837-4" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8487)"
- d="m 179.24914,98.626789 21.50171,21.501701"
- id="path8483"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-4"
- inkscape:connection-end="#rect837-9-8" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8553)"
- d="M 140.75087,98.626789 119.24913,120.12854"
- id="path8549"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-4"
- inkscape:connection-end="#rect837-9-89" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8625)"
- d="m 119.24913,158.62679 21.50174,21.50175"
- id="path8621"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-end="#rect837-9-8-9-8"
- inkscape:connection-start="#rect837-9-89" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8703)"
- d="m 200.75089,158.62674 -21.50178,21.5018"
- id="path8699"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9-8"
- inkscape:connection-end="#rect837-9-8-9-8" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8787)"
- d="M 120.17193,212.65369 19.828068,246.10164"
- id="path8783"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-end="#rect837-9-8-9"
- inkscape:connection-start="#rect837-9-8-9-8" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8877)"
- d="M -20,98.627304 V 240.12854"
- id="path8873"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9"
- inkscape:connection-end="#rect837-9-8-9" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker8973)"
- d="m -20,278.62679 v 21.50157"
- id="path8969"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9-8-9"
- inkscape:connection-end="#rect837-9-8-9-8-4" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-33.711472"
- y="246.28775"
- id="text3736-6-7-3"><tspan
- sodipodi:role="line"
- id="tspan3734-5-8-0"
- x="-33.711472"
- y="246.28775"
- style="font-size:5.64444px;stroke-width:0.264583">bb6 (%3)</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="194.1761"
- y="171.632"
- id="text3165-8-0-4"><tspan
- sodipodi:role="line"
- id="tspan3163-3-8-8"
- x="194.1761"
- y="171.632"
- style="font-size:5.64444px;stroke-width:0.264583">%1</tspan><tspan
- sodipodi:role="line"
- x="194.1761"
- y="178.68756"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185-9-0" /></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="64.926964"
- y="236.35626"
- id="text3165-8-0-0"><tspan
- sodipodi:role="line"
- id="tspan3163-3-8-0"
- x="64.926964"
- y="236.35626"
- style="font-size:5.64444px;stroke-width:0.264583">%2</tspan><tspan
- sodipodi:role="line"
- x="64.926964"
- y="243.41182"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185-9-6" /></text>
- <text
- xml:space="preserve"
- id="text9330"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect9332);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="137.07773"
- y="78.674141"
- id="text9338"><tspan
- sodipodi:role="line"
- id="tspan9336"
- x="137.07773"
- y="78.674141"
- style="font-size:5.64444px;fill:#d40000;stroke-width:0.264583">%1 = memref.alloc(%0)</tspan><tspan
- sodipodi:role="line"
- x="137.07773"
- y="85.729691"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan9340">use(%0)</tspan></text>
- <text
- xml:space="preserve"
- id="text9342"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect9344);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-size:5.64444px;line-height:1.25;font-family:sans-serif;stroke-width:0.264583"
- x="-45.424786"
- y="321.90707"
- id="text9350"><tspan
- sodipodi:role="line"
- id="tspan9348"
- x="-45.424786"
- y="321.90707"
- style="stroke-width:0.264583">copy(%4, %arg2)</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-15.402786"
- y="291.8205"
- id="text3165-8-0-0-4"><tspan
- sodipodi:role="line"
- id="tspan3163-3-8-0-1"
- x="-15.402786"
- y="291.8205"
- style="font-size:5.64444px;stroke-width:0.264583">%3</tspan><tspan
- sodipodi:role="line"
- x="-15.402786"
- y="298.87604"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185-9-6-6" /></text>
- </g>
-</svg>
diff --git a/mlir/docs/includes/img/region_branch_example_pre_move.svg b/mlir/docs/includes/img/region_branch_example_pre_move.svg
deleted file mode 100644
index 79c83fbe35a9e..0000000000000
--- a/mlir/docs/includes/img/region_branch_example_pre_move.svg
+++ /dev/null
@@ -1,435 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="199.99995mm"
- height="191.75687mm"
- viewBox="0 0.7 199.99995 191.75687"
- version="1.1"
- id="svg8"
- inkscape:version="1.0.1 (c497b03c, 2020-09-10)"
- sodipodi:docname="region_branch_hoisting.svg">
- <defs
- id="defs2">
- <marker
- style="overflow:visible"
- id="marker3478"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3476" />
- </marker>
- <rect
- x="18.139799"
- y="132.9565"
- width="42.875893"
- height="13.192582"
- id="rect1896" />
- <rect
- x="73.476562"
- y="69.033791"
- width="111.61496"
- height="41.205559"
- id="rect1370" />
- <rect
- x="88.85537"
- y="63.907516"
- width="32.124634"
- height="21.53034"
- id="rect3730" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679" />
- <rect
- x="41.227337"
- y="-14.998642"
- width="72.234138"
- height="11.239376"
- id="rect3669" />
- <marker
- style="overflow:visible"
- id="marker3503"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3501" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3443"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3441" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3389"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3387" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3341"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3339" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker3141"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lend"
- inkscape:isstock="true"
- inkscape:collect="always">
- <path
- transform="matrix(-0.8,0,0,-0.8,-10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path3139" />
- </marker>
- <marker
- style="overflow:visible"
- id="marker2967"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lstart"
- inkscape:isstock="true">
- <path
- transform="matrix(0.8,0,0,0.8,10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2965" />
- </marker>
- <marker
- style="overflow:visible"
- id="Arrow1Send"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Send"
- inkscape:isstock="true">
- <path
- transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2664" />
- </marker>
- <marker
- style="overflow:visible"
- id="Arrow1Lstart"
- refX="0"
- refY="0"
- orient="auto"
- inkscape:stockid="Arrow1Lstart"
- inkscape:isstock="true">
- <path
- transform="matrix(0.8,0,0,0.8,10,0)"
- style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
- d="M 0,0 5,-5 -12.5,0 5,5 Z"
- id="path2649" />
- </marker>
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3679-2" />
- <rect
- x="9.5690403"
- y="9.2272892"
- width="20.163336"
- height="14.011809"
- id="rect3692" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.61285746"
- inkscape:cx="492.87186"
- inkscape:cy="475.23437"
- inkscape:document-units="mm"
- inkscape:current-layer="layer1"
- inkscape:document-rotation="0"
- showgrid="false"
- inkscape:window-width="1920"
- inkscape:window-height="1035"
- inkscape:window-x="1680"
- inkscape:window-y="23"
- inkscape:window-maximized="1"
- showguides="true"
- fit-margin-top="0"
- fit-margin-left="0"
- fit-margin-right="0"
- fit-margin-bottom="3.3"
- lock-margins="false"
- viewbox-y="1.8" />
- <metadata
- id="metadata5">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(60.000002,15.000516)"
- style="display:inline">
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837"
- width="79.741898"
- height="38.498253"
- x="0.12905283"
- y="0.129053"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9"
- width="79.741898"
- height="38.498253"
- x="-59.870949"
- y="60.129051"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect837-9-8"
- width="79.741898"
- height="38.498253"
- x="60.129051"
- y="60.129051"
- ry="6.741148" />
- <rect
- style="opacity:1;fill:#cfe2f3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.258106;stroke-opacity:1"
- id="rect837-9-8-9"
- width="79.741898"
- height="38.498253"
- x="0.12905283"
- y="120.12905"
- ry="6.741148" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker3141);paint-order:normal"
- d="M 59.249128,38.627306 80.750874,60.129051"
- id="path3329"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837"
- inkscape:connection-end="#rect837-9-8" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3341)"
- d="M 25.563156,38.627306 9.4368463,60.129051"
- id="path3337"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837"
- inkscape:connection-end="#rect837-9" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3389)"
- d="M -0.75087304,98.627304 20.750875,120.12905"
- id="path3385"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9"
- inkscape:connection-end="#rect837-9-8-9" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3443)"
- d="M 80.750874,98.627304 59.249128,120.12905"
- id="path3439"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0"
- inkscape:connection-start="#rect837-9-8"
- inkscape:connection-end="#rect837-9-8-9" />
- <path
- style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3503)"
- d="M 41.227338,-14.998642 41.386551,0.50922611"
- id="path3499"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0" />
- <text
- xml:space="preserve"
- id="text3667"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3669);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
- x="44.769436"
- y="-7.8602829"
- id="text3675"><tspan
- sodipodi:role="line"
- id="tspan3673"
- x="44.769436"
- y="-7.8602829"
- style="font-size:5.64444px;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none">%0</tspan></text>
- <text
- xml:space="preserve"
- id="text3677"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(28.330136,7.1600292)"><tspan
- x="9.5683594"
- y="14.376156"><tspan>if</tspan></tspan></text>
- <text
- xml:space="preserve"
- id="text3728"
- style="font-style:normal;font-weight:normal;font-size:10.58329999999999949px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3730);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- id="text3677-0"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3679-2);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(-35.776417,67.110418)"><tspan
- x="9.5683594"
- y="14.376156"><tspan>then</tspan></tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="42.775875"
- y="169.7245"
- id="text3736-6"><tspan
- sodipodi:role="line"
- id="tspan3734-5"
- x="42.775875"
- y="169.7245"
- style="font-size:5.64444px;stroke-width:0.264583">%1</tspan></text>
- <text
- xml:space="preserve"
- id="text1368"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect1370);fill:#000000;fill-opacity:1;stroke:none;"
- transform="translate(20.903802,7.3023994)"><tspan
- x="73.476562"
- y="74.182797"><tspan
- style="font-size:5.64444px">else</tspan></tspan></text>
- <text
- xml:space="preserve"
- id="text1894"
- style="font-style:normal;font-weight:normal;font-size:5.64444000000000035px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect1896);fill:#000000;fill-opacity:1;stroke:none;" />
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="35.081787"
- y="140.86095"
- id="text1902"><tspan
- sodipodi:role="line"
- id="tspan1900"
- x="35.081787"
- y="140.86095"
- style="font-size:5.64444px;stroke-width:0.264583">join</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="76.269608"
- y="111.63254"
- id="text3165"><tspan
- sodipodi:role="line"
- id="tspan3163"
- x="76.269608"
- y="111.63254"
- style="font-size:5.64444px;stroke-width:0.264583">%arg4</tspan></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-12.065383"
- y="111.08959"
- id="text3165-8"><tspan
- sodipodi:role="line"
- id="tspan3163-3"
- x="-12.065383"
- y="111.08959"
- style="font-size:5.64444px;stroke-width:0.264583">%arg4</tspan><tspan
- sodipodi:role="line"
- x="-12.065383"
- y="118.14514"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185" /></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="-5.6124902"
- y="51.136368"
- id="text3165-8-4"><tspan
- sodipodi:role="line"
- id="tspan3163-3-0"
- x="-5.6124902"
- y="51.136368"
- style="font-size:5.64444px;stroke-width:0.264583">%arg2</tspan><tspan
- sodipodi:role="line"
- x="-5.6124902"
- y="58.191917"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185-2" /></text>
- <text
- xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
- x="78.175652"
- y="51.089592"
- id="text3165-8-9"><tspan
- sodipodi:role="line"
- x="78.175652"
- y="51.089592"
- style="font-size:5.64444px;stroke-width:0.264583"
- id="tspan3185-9">%arg3</tspan></text>
- <path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3478)"
- d="m 40.011796,158.71197 0.01604,17.14766"
- id="path3474"
- inkscape:connector-type="polyline"
- inkscape:connector-curvature="0" />
- </g>
-</svg>
diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
index c8e456a1d7e38..c5d0853d6ff97 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
@@ -30,10 +30,6 @@ using DeallocHelperMap = llvm::DenseMap<Operation *, func::FuncOp>;
#define GEN_PASS_DECL
#include "mlir/Dialect/Bufferization/Transforms/Passes.h.inc"
-/// Creates an instance of the BufferDeallocation pass to free all allocated
-/// buffers.
-std::unique_ptr<Pass> createBufferDeallocationPass();
-
/// Creates an instance of the OwnershipBasedBufferDeallocation pass to free all
/// allocated buffers.
std::unique_ptr<Pass> createOwnershipBasedBufferDeallocationPass(
@@ -141,9 +137,6 @@ void populateBufferizationDeallocLoweringPattern(
func::FuncOp buildDeallocationLibraryFunction(OpBuilder &builder, Location loc,
SymbolTable &symbolTable);
-/// Run buffer deallocation.
-LogicalResult deallocateBuffers(Operation *op);
-
/// Run the ownership-based buffer deallocation.
LogicalResult deallocateBuffersOwnershipBased(FunctionOpInterface op,
DeallocationOptions options);
diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
index 3bcde8edde509..f20f177d8443b 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
@@ -11,79 +11,6 @@
include "mlir/Pass/PassBase.td"
-def BufferDeallocation : Pass<"buffer-deallocation", "func::FuncOp"> {
- let summary = "Adds all required dealloc operations for all allocations in "
- "the input program";
- let description = [{
- This pass implements an algorithm to automatically introduce all required
- deallocation operations for all buffers in the input program. This ensures
- that the resulting program does not have any memory leaks.
-
-
- Input
-
- ```mlir
- #map0 = affine_map<(d0) -> (d0)>
- module {
- func.func @condBranch(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- cf.cond_br %arg0, ^bb1, ^bb2
- ^bb1:
- cf.br ^bb3(%arg1 : memref<2xf32>)
- ^bb2:
- %0 = memref.alloc() : memref<2xf32>
- linalg.generic {
- indexing_maps = [#map0, #map0],
- iterator_types = ["parallel"]} %arg1, %0 {
- ^bb0(%gen1_arg0: f32, %gen1_arg1: f32):
- %tmp1 = exp %gen1_arg0 : f32
- linalg.yield %tmp1 : f32
- }: memref<2xf32>, memref<2xf32>
- cf.br ^bb3(%0 : memref<2xf32>)
- ^bb3(%1: memref<2xf32>):
- "memref.copy"(%1, %arg2) : (memref<2xf32>, memref<2xf32>) -> ()
- return
- }
- }
-
- ```
-
- Output
-
- ```mlir
- #map0 = affine_map<(d0) -> (d0)>
- module {
- func.func @condBranch(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- cf.cond_br %arg0, ^bb1, ^bb2
- ^bb1: // pred: ^bb0
- %0 = memref.alloc() : memref<2xf32>
- memref.copy(%arg1, %0) : memref<2xf32>, memref<2xf32>
- cf.br ^bb3(%0 : memref<2xf32>)
- ^bb2: // pred: ^bb0
- %1 = memref.alloc() : memref<2xf32>
- linalg.generic {
- indexing_maps = [#map0, #map0],
- iterator_types = ["parallel"]} %arg1, %1 {
- ^bb0(%arg3: f32, %arg4: f32):
- %4 = exp %arg3 : f32
- linalg.yield %4 : f32
- }: memref<2xf32>, memref<2xf32>
- %2 = memref.alloc() : memref<2xf32>
- memref.copy(%1, %2) : memref<2xf32>, memref<2xf32>
- dealloc %1 : memref<2xf32>
- cf.br ^bb3(%2 : memref<2xf32>)
- ^bb3(%3: memref<2xf32>): // 2 preds: ^bb1, ^bb2
- memref.copy(%3, %arg2) : memref<2xf32>, memref<2xf32>
- dealloc %3 : memref<2xf32>
- return
- }
-
- }
- ```
-
- }];
- let constructor = "mlir::bufferization::createBufferDeallocationPass()";
-}
-
def OwnershipBasedBufferDeallocation : Pass<
"ownership-based-buffer-deallocation"> {
let summary = "Adds all required dealloc operations for all allocations in "
@@ -390,8 +317,9 @@ def OneShotBufferize : Pass<"one-shot-bufferize", "ModuleOp"> {
results in a new buffer allocation.
One-Shot Bufferize does not deallocate any buffers that it allocates. The
- `-buffer-deallocation` pass should be run after One-Shot Bufferize to insert
- the deallocation operations necessary to eliminate memory leaks.
+ `-buffer-deallocation-pipeline` pipeline should be run after One-Shot
+ Bufferize to insert the deallocation operations necessary to eliminate
+ memory leaks.
One-Shot Bufferize will by default reject IR that contains non-bufferizable
op, i.e., ops that do not implemement BufferizableOpInterface. Such IR can
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocation.cpp b/mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocation.cpp
deleted file mode 100644
index a0a81d4add712..0000000000000
--- a/mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocation.cpp
+++ /dev/null
@@ -1,693 +0,0 @@
-//===- BufferDeallocation.cpp - the impl for buffer deallocation ----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements logic for computing correct alloc and dealloc positions.
-// Furthermore, buffer deallocation also adds required new clone operations to
-// ensure that all buffers are deallocated. The main class is the
-// BufferDeallocationPass class that implements the underlying algorithm. In
-// order to put allocations and deallocations at safe positions, it is
-// significantly important to put them into the correct blocks. However, the
-// liveness analysis does not pay attention to aliases, which can occur due to
-// branches (and their associated block arguments) in general. For this purpose,
-// BufferDeallocation firstly finds all possible aliases for a single value
-// (using the BufferViewFlowAnalysis class). Consider the following example:
-//
-// ^bb0(%arg0):
-// cf.cond_br %cond, ^bb1, ^bb2
-// ^bb1:
-// cf.br ^exit(%arg0)
-// ^bb2:
-// %new_value = ...
-// cf.br ^exit(%new_value)
-// ^exit(%arg1):
-// return %arg1;
-//
-// We should place the dealloc for %new_value in exit. However, we have to free
-// the buffer in the same block, because it cannot be freed in the post
-// dominator. However, this requires a new clone buffer for %arg1 that will
-// contain the actual contents. Using the class BufferViewFlowAnalysis, we
-// will find out that %new_value has a potential alias %arg1. In order to find
-// the dealloc position we have to find all potential aliases, iterate over
-// their uses and find the common post-dominator block (note that additional
-// clones and buffers remove potential aliases and will influence the placement
-// of the deallocs). In all cases, the computed block can be safely used to free
-// the %new_value buffer (may be exit or bb2) as it will die and we can use
-// liveness information to determine the exact operation after which we have to
-// insert the dealloc. However, the algorithm supports introducing clone buffers
-// and placing deallocs in safe locations to ensure that all buffers will be
-// freed in the end.
-//
-// TODO:
-// The current implementation does not support explicit-control-flow loops and
-// the resulting code will be invalid with respect to program semantics.
-// However, structured control-flow loops are fully supported. Furthermore, it
-// doesn't accept functions which return buffers already.
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Dialect/Bufferization/Transforms/Passes.h"
-
-#include "mlir/Dialect/Bufferization/IR/AllocationOpInterface.h"
-#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
-#include "mlir/Dialect/Bufferization/Transforms/BufferUtils.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/Dialect/MemRef/IR/MemRef.h"
-#include "llvm/ADT/SetOperations.h"
-
-namespace mlir {
-namespace bufferization {
-#define GEN_PASS_DEF_BUFFERDEALLOCATION
-#include "mlir/Dialect/Bufferization/Transforms/Passes.h.inc"
-} // namespace bufferization
-} // namespace mlir
-
-using namespace mlir;
-using namespace mlir::bufferization;
-
-/// Walks over all immediate return-like terminators in the given region.
-static LogicalResult walkReturnOperations(
- Region *region,
- llvm::function_ref<LogicalResult(RegionBranchTerminatorOpInterface)> func) {
- for (Block &block : *region) {
- Operation *terminator = block.getTerminator();
- // Skip non region-return-like terminators.
- if (auto regionTerminator =
- dyn_cast<RegionBranchTerminatorOpInterface>(terminator)) {
- if (failed(func(regionTerminator)))
- return failure();
- }
- }
- return success();
-}
-
-/// Checks if all operations that have at least one attached region implement
-/// the RegionBranchOpInterface. This is not required in edge cases, where we
-/// have a single attached region and the parent operation has no results.
-static bool validateSupportedControlFlow(Operation *op) {
- WalkResult result = op->walk([&](Operation *operation) {
- // Only check ops that are inside a function.
- if (!operation->getParentOfType<func::FuncOp>())
- return WalkResult::advance();
-
- auto regions = operation->getRegions();
- // Walk over all operations in a region and check if the operation has at
- // least one region and implements the RegionBranchOpInterface. If there
- // is an operation that does not fulfill this condition, we cannot apply
- // the deallocation steps. Furthermore, we accept cases, where we have a
- // region that returns no results, since, in that case, the intra-region
- // control flow does not affect the transformation.
- size_t size = regions.size();
- if (((size == 1 && !operation->getResults().empty()) || size > 1) &&
- !dyn_cast<RegionBranchOpInterface>(operation)) {
- operation->emitError("All operations with attached regions need to "
- "implement the RegionBranchOpInterface.");
- }
-
- return WalkResult::advance();
- });
- return !result.wasSkipped();
-}
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// Backedges analysis
-//===----------------------------------------------------------------------===//
-
-/// A straight-forward program analysis which detects loop backedges induced by
-/// explicit control flow.
-class Backedges {
-public:
- using BlockSetT = SmallPtrSet<Block *, 16>;
- using BackedgeSetT = llvm::DenseSet<std::pair<Block *, Block *>>;
-
-public:
- /// Constructs a new backedges analysis using the op provided.
- Backedges(Operation *op) { recurse(op); }
-
- /// Returns the number of backedges formed by explicit control flow.
- size_t size() const { return edgeSet.size(); }
-
- /// Returns the start iterator to loop over all backedges.
- BackedgeSetT::const_iterator begin() const { return edgeSet.begin(); }
-
- /// Returns the end iterator to loop over all backedges.
- BackedgeSetT::const_iterator end() const { return edgeSet.end(); }
-
-private:
- /// Enters the current block and inserts a backedge into the `edgeSet` if we
- /// have already visited the current block. The inserted edge links the given
- /// `predecessor` with the `current` block.
- bool enter(Block ¤t, Block *predecessor) {
- bool inserted = visited.insert(¤t).second;
- if (!inserted)
- edgeSet.insert(std::make_pair(predecessor, ¤t));
- return inserted;
- }
-
- /// Leaves the current block.
- void exit(Block ¤t) { visited.erase(¤t); }
-
- /// Recurses into the given operation while taking all attached regions into
- /// account.
- void recurse(Operation *op) {
- Block *current = op->getBlock();
- // If the current op implements the `BranchOpInterface`, there can be
- // cycles in the scope of all successor blocks.
- if (isa<BranchOpInterface>(op)) {
- for (Block *succ : current->getSuccessors())
- recurse(*succ, current);
- }
- // Recurse into all distinct regions and check for explicit control-flow
- // loops.
- for (Region ®ion : op->getRegions()) {
- if (!region.empty())
- recurse(region.front(), current);
- }
- }
-
- /// Recurses into explicit control-flow structures that are given by
- /// the successor relation defined on the block level.
- void recurse(Block &block, Block *predecessor) {
- // Try to enter the current block. If this is not possible, we are
- // currently processing this block and can safely return here.
- if (!enter(block, predecessor))
- return;
-
- // Recurse into all operations and successor blocks.
- for (Operation &op : block.getOperations())
- recurse(&op);
-
- // Leave the current block.
- exit(block);
- }
-
- /// Stores all blocks that are currently visited and on the processing stack.
- BlockSetT visited;
-
- /// Stores all backedges in the format (source, target).
- BackedgeSetT edgeSet;
-};
-
-//===----------------------------------------------------------------------===//
-// BufferDeallocation
-//===----------------------------------------------------------------------===//
-
-/// The buffer deallocation transformation which ensures that all allocs in the
-/// program have a corresponding de-allocation. As a side-effect, it might also
-/// introduce clones that in turn leads to additional deallocations.
-class BufferDeallocation : public BufferPlacementTransformationBase {
-public:
- using AliasAllocationMapT =
- llvm::DenseMap<Value, bufferization::AllocationOpInterface>;
-
- BufferDeallocation(Operation *op)
- : BufferPlacementTransformationBase(op), dominators(op),
- postDominators(op) {}
-
- /// Checks if all allocation operations either provide an already existing
- /// deallocation operation or implement the AllocationOpInterface. In
- /// addition, this method initializes the internal alias to
- /// AllocationOpInterface mapping in order to get compatible
- /// AllocationOpInterface implementations for aliases.
- LogicalResult prepare() {
- for (const BufferPlacementAllocs::AllocEntry &entry : allocs) {
- // Get the defining allocation operation.
- Value alloc = std::get<0>(entry);
- auto allocationInterface =
- alloc.getDefiningOp<bufferization::AllocationOpInterface>();
- // If there is no existing deallocation operation and no implementation of
- // the AllocationOpInterface, we cannot apply the BufferDeallocation pass.
- if (!std::get<1>(entry) && !allocationInterface) {
- return alloc.getDefiningOp()->emitError(
- "Allocation is not deallocated explicitly nor does the operation "
- "implement the AllocationOpInterface.");
- }
-
- // Register the current allocation interface implementation.
- aliasToAllocations[alloc] = allocationInterface;
-
- // Get the alias information for the current allocation node.
- for (Value alias : aliases.resolve(alloc)) {
- // TODO: check for incompatible implementations of the
- // AllocationOpInterface. This could be realized by promoting the
- // AllocationOpInterface to a DialectInterface.
- aliasToAllocations[alias] = allocationInterface;
- }
- }
- return success();
- }
-
- /// Performs the actual placement/creation of all temporary clone and dealloc
- /// nodes.
- LogicalResult deallocate() {
- // Add additional clones that are required.
- if (failed(introduceClones()))
- return failure();
-
- // Place deallocations for all allocation entries.
- return placeDeallocs();
- }
-
-private:
- /// Introduces required clone operations to avoid memory leaks.
- LogicalResult introduceClones() {
- // Initialize the set of values that require a dedicated memory free
- // operation since their operands cannot be safely deallocated in a post
- // dominator.
- SetVector<Value> valuesToFree;
- llvm::SmallDenseSet<std::tuple<Value, Block *>> visitedValues;
- SmallVector<std::tuple<Value, Block *>, 8> toProcess;
-
- // Check dominance relation for proper dominance properties. If the given
- // value node does not dominate an alias, we will have to create a clone in
- // order to free all buffers that can potentially leak into a post
- // dominator.
- auto findUnsafeValues = [&](Value source, Block *definingBlock) {
- auto it = aliases.find(source);
- if (it == aliases.end())
- return;
- for (Value value : it->second) {
- if (valuesToFree.count(value) > 0)
- continue;
- Block *parentBlock = value.getParentBlock();
- // Check whether we have to free this particular block argument or
- // generic value. We have to free the current alias if it is either
- // defined in a non-dominated block or it is defined in the same block
- // but the current value is not dominated by the source value.
- if (!dominators.dominates(definingBlock, parentBlock) ||
- (definingBlock == parentBlock && isa<BlockArgument>(value))) {
- toProcess.emplace_back(value, parentBlock);
- valuesToFree.insert(value);
- } else if (visitedValues.insert(std::make_tuple(value, definingBlock))
- .second)
- toProcess.emplace_back(value, definingBlock);
- }
- };
-
- // Detect possibly unsafe aliases starting from all allocations.
- for (BufferPlacementAllocs::AllocEntry &entry : allocs) {
- Value allocValue = std::get<0>(entry);
- findUnsafeValues(allocValue, allocValue.getDefiningOp()->getBlock());
- }
- // Try to find block arguments that require an explicit free operation
- // until we reach a fix point.
- while (!toProcess.empty()) {
- auto current = toProcess.pop_back_val();
- findUnsafeValues(std::get<0>(current), std::get<1>(current));
- }
-
- // Update buffer aliases to ensure that we free all buffers and block
- // arguments at the correct locations.
- aliases.remove(valuesToFree);
-
- // Add new allocs and additional clone operations.
- for (Value value : valuesToFree) {
- if (failed(isa<BlockArgument>(value)
- ? introduceBlockArgCopy(cast<BlockArgument>(value))
- : introduceValueCopyForRegionResult(value)))
- return failure();
-
- // Register the value to require a final dealloc. Note that we do not have
- // to assign a block here since we do not want to move the allocation node
- // to another location.
- allocs.registerAlloc(std::make_tuple(value, nullptr));
- }
- return success();
- }
-
- /// Introduces temporary clones in all predecessors and copies the source
- /// values into the newly allocated buffers.
- LogicalResult introduceBlockArgCopy(BlockArgument blockArg) {
- // Allocate a buffer for the current block argument in the block of
- // the associated value (which will be a predecessor block by
- // definition).
- Block *block = blockArg.getOwner();
- for (auto it = block->pred_begin(), e = block->pred_end(); it != e; ++it) {
- // Get the terminator and the value that will be passed to our
- // argument.
- Operation *terminator = (*it)->getTerminator();
- auto branchInterface = cast<BranchOpInterface>(terminator);
- SuccessorOperands operands =
- branchInterface.getSuccessorOperands(it.getSuccessorIndex());
-
- // Query the associated source value.
- Value sourceValue = operands[blockArg.getArgNumber()];
- if (!sourceValue) {
- return failure();
- }
- // Wire new clone and successor operand.
- // Create a new clone at the current location of the terminator.
- auto clone = introduceCloneBuffers(sourceValue, terminator);
- if (failed(clone))
- return failure();
- operands.slice(blockArg.getArgNumber(), 1).assign(*clone);
- }
-
- // Check whether the block argument has implicitly defined predecessors via
- // the RegionBranchOpInterface. This can be the case if the current block
- // argument belongs to the first block in a region and the parent operation
- // implements the RegionBranchOpInterface.
- Region *argRegion = block->getParent();
- Operation *parentOp = argRegion->getParentOp();
- RegionBranchOpInterface regionInterface;
- if (&argRegion->front() != block ||
- !(regionInterface = dyn_cast<RegionBranchOpInterface>(parentOp)))
- return success();
-
- if (failed(introduceClonesForRegionSuccessors(
- regionInterface, argRegion->getParentOp()->getRegions(), blockArg,
- [&](RegionSuccessor &successorRegion) {
- // Find a predecessor of our argRegion.
- return successorRegion.getSuccessor() == argRegion;
- })))
- return failure();
-
- // Check whether the block argument belongs to an entry region of the
- // parent operation. In this case, we have to introduce an additional clone
- // for buffer that is passed to the argument.
- SmallVector<RegionSuccessor, 2> successorRegions;
- regionInterface.getSuccessorRegions(/*point=*/RegionBranchPoint::parent(),
- successorRegions);
- auto *it =
- llvm::find_if(successorRegions, [&](RegionSuccessor &successorRegion) {
- return successorRegion.getSuccessor() == argRegion;
- });
- if (it == successorRegions.end())
- return success();
-
- // Determine the actual operand to introduce a clone for and rewire the
- // operand to point to the clone instead.
- auto operands = regionInterface.getEntrySuccessorOperands(argRegion);
- size_t operandIndex =
- llvm::find(it->getSuccessorInputs(), blockArg).getIndex() +
- operands.getBeginOperandIndex();
- Value operand = parentOp->getOperand(operandIndex);
- assert(operand ==
- operands[operandIndex - operands.getBeginOperandIndex()] &&
- "region interface operands don't match parentOp operands");
- auto clone = introduceCloneBuffers(operand, parentOp);
- if (failed(clone))
- return failure();
-
- parentOp->setOperand(operandIndex, *clone);
- return success();
- }
-
- /// Introduces temporary clones in front of all associated nested-region
- /// terminators and copies the source values into the newly allocated buffers.
- LogicalResult introduceValueCopyForRegionResult(Value value) {
- // Get the actual result index in the scope of the parent terminator.
- Operation *operation = value.getDefiningOp();
- auto regionInterface = cast<RegionBranchOpInterface>(operation);
- // Filter successors that return to the parent operation.
- auto regionPredicate = [&](RegionSuccessor &successorRegion) {
- // If the RegionSuccessor has no associated successor, it will return to
- // its parent operation.
- return !successorRegion.getSuccessor();
- };
- // Introduce a clone for all region "results" that are returned to the
- // parent operation. This is required since the parent's result value has
- // been considered critical. Therefore, the algorithm assumes that a clone
- // of a previously allocated buffer is returned by the operation (like in
- // the case of a block argument).
- return introduceClonesForRegionSuccessors(
- regionInterface, operation->getRegions(), value, regionPredicate);
- }
-
- /// Introduces buffer clones for all terminators in the given regions. The
- /// regionPredicate is applied to every successor region in order to restrict
- /// the clones to specific regions.
- template <typename TPredicate>
- LogicalResult introduceClonesForRegionSuccessors(
- RegionBranchOpInterface regionInterface, MutableArrayRef<Region> regions,
- Value argValue, const TPredicate ®ionPredicate) {
- for (Region ®ion : regions) {
- // Query the regionInterface to get all successor regions of the current
- // one.
- SmallVector<RegionSuccessor, 2> successorRegions;
- regionInterface.getSuccessorRegions(region, successorRegions);
- // Try to find a matching region successor.
- RegionSuccessor *regionSuccessor =
- llvm::find_if(successorRegions, regionPredicate);
- if (regionSuccessor == successorRegions.end())
- continue;
- // Get the operand index in the context of the current successor input
- // bindings.
- size_t operandIndex =
- llvm::find(regionSuccessor->getSuccessorInputs(), argValue)
- .getIndex();
-
- // Iterate over all immediate terminator operations to introduce
- // new buffer allocations. Thereby, the appropriate terminator operand
- // will be adjusted to point to the newly allocated buffer instead.
- if (failed(walkReturnOperations(
- ®ion, [&](RegionBranchTerminatorOpInterface terminator) {
- // Get the actual mutable operands for this terminator op.
- auto terminatorOperands =
- terminator.getMutableSuccessorOperands(*regionSuccessor);
- // Extract the source value from the current terminator.
- // This conversion needs to exist on a separate line due to a
- // bug in GCC conversion analysis.
- OperandRange immutableTerminatorOperands = terminatorOperands;
- Value sourceValue = immutableTerminatorOperands[operandIndex];
- // Create a new clone at the current location of the terminator.
- auto clone = introduceCloneBuffers(sourceValue, terminator);
- if (failed(clone))
- return failure();
- // Wire clone and terminator operand.
- terminatorOperands.slice(operandIndex, 1).assign(*clone);
- return success();
- })))
- return failure();
- }
- return success();
- }
-
- /// Creates a new memory allocation for the given source value and clones
- /// its content into the newly allocated buffer. The terminator operation is
- /// used to insert the clone operation at the right place.
- FailureOr<Value> introduceCloneBuffers(Value sourceValue,
- Operation *terminator) {
- // Avoid multiple clones of the same source value. This can happen in the
- // presence of loops when a branch acts as a backedge while also having
- // another successor that returns to its parent operation. Note: that
- // copying copied buffers can introduce memory leaks since the invariant of
- // BufferDeallocation assumes that a buffer will be only cloned once into a
- // temporary buffer. Hence, the construction of clone chains introduces
- // additional allocations that are not tracked automatically by the
- // algorithm.
- if (clonedValues.contains(sourceValue))
- return sourceValue;
- // Create a new clone operation that copies the contents of the old
- // buffer to the new one.
- auto clone = buildClone(terminator, sourceValue);
- if (succeeded(clone)) {
- // Remember the clone of original source value.
- clonedValues.insert(*clone);
- }
- return clone;
- }
-
- /// Finds correct dealloc positions according to the algorithm described at
- /// the top of the file for all alloc nodes and block arguments that can be
- /// handled by this analysis.
- LogicalResult placeDeallocs() {
- // Move or insert deallocs using the previously computed information.
- // These deallocations will be linked to their associated allocation nodes
- // since they don't have any aliases that can (potentially) increase their
- // liveness.
- for (const BufferPlacementAllocs::AllocEntry &entry : allocs) {
- Value alloc = std::get<0>(entry);
- auto aliasesSet = aliases.resolve(alloc);
- assert(!aliasesSet.empty() && "must contain at least one alias");
-
- // Determine the actual block to place the dealloc and get liveness
- // information.
- Block *placementBlock =
- findCommonDominator(alloc, aliasesSet, postDominators);
- const LivenessBlockInfo *livenessInfo =
- liveness.getLiveness(placementBlock);
-
- // We have to ensure that the dealloc will be after the last use of all
- // aliases of the given value. We first assume that there are no uses in
- // the placementBlock and that we can safely place the dealloc at the
- // beginning.
- Operation *endOperation = &placementBlock->front();
-
- // Iterate over all aliases and ensure that the endOperation will point
- // to the last operation of all potential aliases in the placementBlock.
- for (Value alias : aliasesSet) {
- // Ensure that the start operation is at least the defining operation of
- // the current alias to avoid invalid placement of deallocs for aliases
- // without any uses.
- Operation *beforeOp = endOperation;
- if (alias.getDefiningOp() &&
- !(beforeOp = placementBlock->findAncestorOpInBlock(
- *alias.getDefiningOp())))
- continue;
-
- Operation *aliasEndOperation =
- livenessInfo->getEndOperation(alias, beforeOp);
- // Check whether the aliasEndOperation lies in the desired block and
- // whether it is behind the current endOperation. If yes, this will be
- // the new endOperation.
- if (aliasEndOperation->getBlock() == placementBlock &&
- endOperation->isBeforeInBlock(aliasEndOperation))
- endOperation = aliasEndOperation;
- }
- // endOperation is the last operation behind which we can safely store
- // the dealloc taking all potential aliases into account.
-
- // If there is an existing dealloc, move it to the right place.
- Operation *deallocOperation = std::get<1>(entry);
- if (deallocOperation) {
- deallocOperation->moveAfter(endOperation);
- } else {
- // If the Dealloc position is at the terminator operation of the
- // block, then the value should escape from a deallocation.
- Operation *nextOp = endOperation->getNextNode();
- if (!nextOp)
- continue;
- // If there is no dealloc node, insert one in the right place.
- if (failed(buildDealloc(nextOp, alloc)))
- return failure();
- }
- }
- return success();
- }
-
- /// Builds a deallocation operation compatible with the given allocation
- /// value. If there is no registered AllocationOpInterface implementation for
- /// the given value (e.g. in the case of a function parameter), this method
- /// builds a memref::DeallocOp.
- LogicalResult buildDealloc(Operation *op, Value alloc) {
- OpBuilder builder(op);
- auto it = aliasToAllocations.find(alloc);
- if (it != aliasToAllocations.end()) {
- // Call the allocation op interface to build a supported and
- // compatible deallocation operation.
- auto dealloc = it->second.buildDealloc(builder, alloc);
- if (!dealloc)
- return op->emitError()
- << "allocations without compatible deallocations are "
- "not supported";
- } else {
- // Build a "default" DeallocOp for unknown allocation sources.
- builder.create<memref::DeallocOp>(alloc.getLoc(), alloc);
- }
- return success();
- }
-
- /// Builds a clone operation compatible with the given allocation value. If
- /// there is no registered AllocationOpInterface implementation for the given
- /// value (e.g. in the case of a function parameter), this method builds a
- /// bufferization::CloneOp.
- FailureOr<Value> buildClone(Operation *op, Value alloc) {
- OpBuilder builder(op);
- auto it = aliasToAllocations.find(alloc);
- if (it != aliasToAllocations.end()) {
- // Call the allocation op interface to build a supported and
- // compatible clone operation.
- auto clone = it->second.buildClone(builder, alloc);
- if (clone)
- return *clone;
- return (LogicalResult)(op->emitError()
- << "allocations without compatible clone ops "
- "are not supported");
- }
- // Build a "default" CloneOp for unknown allocation sources.
- return builder.create<bufferization::CloneOp>(alloc.getLoc(), alloc)
- .getResult();
- }
-
- /// The dominator info to find the appropriate start operation to move the
- /// allocs.
- DominanceInfo dominators;
-
- /// The post dominator info to move the dependent allocs in the right
- /// position.
- PostDominanceInfo postDominators;
-
- /// Stores already cloned buffers to avoid additional clones of clones.
- ValueSetT clonedValues;
-
- /// Maps aliases to their source allocation interfaces (inverse mapping).
- AliasAllocationMapT aliasToAllocations;
-};
-
-//===----------------------------------------------------------------------===//
-// BufferDeallocationPass
-//===----------------------------------------------------------------------===//
-
-/// The actual buffer deallocation pass that inserts and moves dealloc nodes
-/// into the right positions. Furthermore, it inserts additional clones if
-/// necessary. It uses the algorithm described at the top of the file.
-struct BufferDeallocationPass
- : public bufferization::impl::BufferDeallocationBase<
- BufferDeallocationPass> {
- void getDependentDialects(DialectRegistry ®istry) const override {
- registry.insert<bufferization::BufferizationDialect>();
- registry.insert<memref::MemRefDialect>();
- }
-
- void runOnOperation() override {
- func::FuncOp func = getOperation();
- if (func.isExternal())
- return;
-
- if (failed(deallocateBuffers(func)))
- signalPassFailure();
- }
-};
-
-} // namespace
-
-LogicalResult bufferization::deallocateBuffers(Operation *op) {
- if (isa<ModuleOp>(op)) {
- WalkResult result = op->walk([&](func::FuncOp funcOp) {
- if (failed(deallocateBuffers(funcOp)))
- return WalkResult::interrupt();
- return WalkResult::advance();
- });
- return success(!result.wasInterrupted());
- }
-
- // Ensure that there are supported loops only.
- Backedges backedges(op);
- if (backedges.size()) {
- op->emitError("Only structured control-flow loops are supported.");
- return failure();
- }
-
- // Check that the control flow structures are supported.
- if (!validateSupportedControlFlow(op))
- return failure();
-
- // Gather all required allocation nodes and prepare the deallocation phase.
- BufferDeallocation deallocation(op);
-
- // Check for supported AllocationOpInterface implementations and prepare the
- // internal deallocation pass.
- if (failed(deallocation.prepare()))
- return failure();
-
- // Place all required temporary clone and dealloc nodes.
- if (failed(deallocation.deallocate()))
- return failure();
-
- return success();
-}
-
-//===----------------------------------------------------------------------===//
-// BufferDeallocationPass construction
-//===----------------------------------------------------------------------===//
-
-std::unique_ptr<Pass> mlir::bufferization::createBufferDeallocationPass() {
- return std::make_unique<BufferDeallocationPass>();
-}
diff --git a/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
index 50104e8f8346b..7c38621be1bb5 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
@@ -1,6 +1,5 @@
add_mlir_dialect_library(MLIRBufferizationTransforms
Bufferize.cpp
- BufferDeallocation.cpp
BufferDeallocationSimplification.cpp
BufferOptimizations.cpp
BufferResultsToOutParams.cpp
diff --git a/mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation.mlir b/mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation.mlir
deleted file mode 100644
index 3fbe3913c6549..0000000000000
--- a/mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation.mlir
+++ /dev/null
@@ -1,1462 +0,0 @@
-// RUN: mlir-opt -verify-diagnostics -buffer-deallocation -split-input-file %s | FileCheck %s
-
-// This file checks the behaviour of BufferDeallocation pass for moving and
-// inserting missing DeallocOps in their correct positions. Furthermore,
-// copies and their corresponding AllocOps are inserted.
-
-// Test Case:
-// bb0
-// / \
-// bb1 bb2 <- Initial position of AllocOp
-// \ /
-// bb3
-// BufferDeallocation expected behavior: bb2 contains an AllocOp which is
-// passed to bb3. In the latter block, there should be an deallocation.
-// Since bb1 does not contain an adequate alloc and the alloc in bb2 is not
-// moved to bb0, we need to insert allocs and copies.
-
-// CHECK-LABEL: func @condBranch
-func.func @condBranch(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- cf.cond_br %arg0, ^bb1, ^bb2
-^bb1:
- cf.br ^bb3(%arg1 : memref<2xf32>)
-^bb2:
- %0 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
- cf.br ^bb3(%0 : memref<2xf32>)
-^bb3(%1: memref<2xf32>):
- test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: cf.cond_br
-// CHECK: %[[ALLOC0:.*]] = bufferization.clone
-// CHECK-NEXT: cf.br ^bb3(%[[ALLOC0]]
-// CHECK: %[[ALLOC1:.*]] = memref.alloc
-// CHECK-NEXT: test.buffer_based
-// CHECK-NEXT: %[[ALLOC2:.*]] = bufferization.clone %[[ALLOC1]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC1]]
-// CHECK-NEXT: cf.br ^bb3(%[[ALLOC2]]
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case:
-// bb0
-// / \
-// bb1 bb2 <- Initial position of AllocOp
-// \ /
-// bb3
-// BufferDeallocation expected behavior: The existing AllocOp has a dynamic
-// dependency to block argument %0 in bb2. Since the dynamic type is passed
-// to bb3 via the block argument %2, it is currently required to allocate a
-// temporary buffer for %2 that gets copies of %arg0 and %1 with their
-// appropriate shape dimensions. The copy buffer deallocation will be applied
-// to %2 in block bb3.
-
-// CHECK-LABEL: func @condBranchDynamicType
-func.func @condBranchDynamicType(
- %arg0: i1,
- %arg1: memref<?xf32>,
- %arg2: memref<?xf32>,
- %arg3: index) {
- cf.cond_br %arg0, ^bb1, ^bb2(%arg3: index)
-^bb1:
- cf.br ^bb3(%arg1 : memref<?xf32>)
-^bb2(%0: index):
- %1 = memref.alloc(%0) : memref<?xf32>
- test.buffer_based in(%arg1: memref<?xf32>) out(%1: memref<?xf32>)
- cf.br ^bb3(%1 : memref<?xf32>)
-^bb3(%2: memref<?xf32>):
- test.copy(%2, %arg2) : (memref<?xf32>, memref<?xf32>)
- return
-}
-
-// CHECK-NEXT: cf.cond_br
-// CHECK: %[[ALLOC0:.*]] = bufferization.clone
-// CHECK-NEXT: cf.br ^bb3(%[[ALLOC0]]
-// CHECK: ^bb2(%[[IDX:.*]]:{{.*}})
-// CHECK-NEXT: %[[ALLOC1:.*]] = memref.alloc(%[[IDX]])
-// CHECK-NEXT: test.buffer_based
-// CHECK-NEXT: %[[ALLOC2:.*]] = bufferization.clone
-// CHECK-NEXT: memref.dealloc %[[ALLOC1]]
-// CHECK-NEXT: cf.br ^bb3
-// CHECK-NEXT: ^bb3(%[[ALLOC3:.*]]:{{.*}})
-// CHECK: test.copy(%[[ALLOC3]],
-// CHECK-NEXT: memref.dealloc %[[ALLOC3]]
-// CHECK-NEXT: return
-
-// -----
-
-// Test case: See above.
-
-// CHECK-LABEL: func @condBranchUnrankedType
-func.func @condBranchUnrankedType(
- %arg0: i1,
- %arg1: memref<*xf32>,
- %arg2: memref<*xf32>,
- %arg3: index) {
- cf.cond_br %arg0, ^bb1, ^bb2(%arg3: index)
-^bb1:
- cf.br ^bb3(%arg1 : memref<*xf32>)
-^bb2(%0: index):
- %1 = memref.alloc(%0) : memref<?xf32>
- %2 = memref.cast %1 : memref<?xf32> to memref<*xf32>
- test.buffer_based in(%arg1: memref<*xf32>) out(%2: memref<*xf32>)
- cf.br ^bb3(%2 : memref<*xf32>)
-^bb3(%3: memref<*xf32>):
- test.copy(%3, %arg2) : (memref<*xf32>, memref<*xf32>)
- return
-}
-
-// CHECK-NEXT: cf.cond_br
-// CHECK: %[[ALLOC0:.*]] = bufferization.clone
-// CHECK-NEXT: cf.br ^bb3(%[[ALLOC0]]
-// CHECK: ^bb2(%[[IDX:.*]]:{{.*}})
-// CHECK-NEXT: %[[ALLOC1:.*]] = memref.alloc(%[[IDX]])
-// CHECK: test.buffer_based
-// CHECK-NEXT: %[[ALLOC2:.*]] = bufferization.clone
-// CHECK-NEXT: memref.dealloc %[[ALLOC1]]
-// CHECK-NEXT: cf.br ^bb3
-// CHECK-NEXT: ^bb3(%[[ALLOC3:.*]]:{{.*}})
-// CHECK: test.copy(%[[ALLOC3]],
-// CHECK-NEXT: memref.dealloc %[[ALLOC3]]
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case:
-// bb0
-// / \
-// bb1 bb2 <- Initial position of AllocOp
-// | / \
-// | bb3 bb4
-// | \ /
-// \ bb5
-// \ /
-// bb6
-// |
-// bb7
-// BufferDeallocation expected behavior: The existing AllocOp has a dynamic
-// dependency to block argument %0 in bb2. Since the dynamic type is passed to
-// bb5 via the block argument %2 and to bb6 via block argument %3, it is
-// currently required to allocate temporary buffers for %2 and %3 that gets
-// copies of %1 and %arg0 1 with their appropriate shape dimensions. The copy
-// buffer deallocations will be applied to %2 in block bb5 and to %3 in block
-// bb6. Furthermore, there should be no copy inserted for %4.
-
-// CHECK-LABEL: func @condBranchDynamicTypeNested
-func.func @condBranchDynamicTypeNested(
- %arg0: i1,
- %arg1: memref<?xf32>,
- %arg2: memref<?xf32>,
- %arg3: index) {
- cf.cond_br %arg0, ^bb1, ^bb2(%arg3: index)
-^bb1:
- cf.br ^bb6(%arg1 : memref<?xf32>)
-^bb2(%0: index):
- %1 = memref.alloc(%0) : memref<?xf32>
- test.buffer_based in(%arg1: memref<?xf32>) out(%1: memref<?xf32>)
- cf.cond_br %arg0, ^bb3, ^bb4
-^bb3:
- cf.br ^bb5(%1 : memref<?xf32>)
-^bb4:
- cf.br ^bb5(%1 : memref<?xf32>)
-^bb5(%2: memref<?xf32>):
- cf.br ^bb6(%2 : memref<?xf32>)
-^bb6(%3: memref<?xf32>):
- cf.br ^bb7(%3 : memref<?xf32>)
-^bb7(%4: memref<?xf32>):
- test.copy(%4, %arg2) : (memref<?xf32>, memref<?xf32>)
- return
-}
-
-// CHECK-NEXT: cf.cond_br{{.*}}
-// CHECK-NEXT: ^bb1
-// CHECK-NEXT: %[[ALLOC0:.*]] = bufferization.clone
-// CHECK-NEXT: cf.br ^bb6(%[[ALLOC0]]
-// CHECK: ^bb2(%[[IDX:.*]]:{{.*}})
-// CHECK-NEXT: %[[ALLOC1:.*]] = memref.alloc(%[[IDX]])
-// CHECK-NEXT: test.buffer_based
-// CHECK: cf.cond_br
-// CHECK: ^bb3:
-// CHECK-NEXT: cf.br ^bb5(%[[ALLOC1]]{{.*}})
-// CHECK: ^bb4:
-// CHECK-NEXT: cf.br ^bb5(%[[ALLOC1]]{{.*}})
-// CHECK-NEXT: ^bb5(%[[ALLOC2:.*]]:{{.*}})
-// CHECK-NEXT: %[[ALLOC3:.*]] = bufferization.clone %[[ALLOC2]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC1]]
-// CHECK-NEXT: cf.br ^bb6(%[[ALLOC3]]{{.*}})
-// CHECK-NEXT: ^bb6(%[[ALLOC4:.*]]:{{.*}})
-// CHECK-NEXT: cf.br ^bb7(%[[ALLOC4]]{{.*}})
-// CHECK-NEXT: ^bb7(%[[ALLOC5:.*]]:{{.*}})
-// CHECK: test.copy(%[[ALLOC5]],
-// CHECK-NEXT: memref.dealloc %[[ALLOC4]]
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case: Existing AllocOp with no users.
-// BufferDeallocation expected behavior: It should insert a DeallocOp right
-// before ReturnOp.
-
-// CHECK-LABEL: func @emptyUsesValue
-func.func @emptyUsesValue(%arg0: memref<4xf32>) {
- %0 = memref.alloc() : memref<4xf32>
- return
-}
-// CHECK-NEXT: %[[ALLOC:.*]] = memref.alloc()
-// CHECK-NEXT: memref.dealloc %[[ALLOC]]
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case:
-// bb0
-// / \
-// | bb1 <- Initial position of AllocOp
-// \ /
-// bb2
-// BufferDeallocation expected behavior: It should insert a DeallocOp at the
-// exit block after CopyOp since %1 is an alias for %0 and %arg1. Furthermore,
-// we have to insert a copy and an alloc in the beginning of the function.
-
-// CHECK-LABEL: func @criticalEdge
-func.func @criticalEdge(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- cf.cond_br %arg0, ^bb1, ^bb2(%arg1 : memref<2xf32>)
-^bb1:
- %0 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
- cf.br ^bb2(%0 : memref<2xf32>)
-^bb2(%1: memref<2xf32>):
- test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: %[[ALLOC0:.*]] = bufferization.clone
-// CHECK-NEXT: cf.cond_br
-// CHECK: %[[ALLOC1:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based
-// CHECK-NEXT: %[[ALLOC2:.*]] = bufferization.clone %[[ALLOC1]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC1]]
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case:
-// bb0 <- Initial position of AllocOp
-// / \
-// | bb1
-// \ /
-// bb2
-// BufferDeallocation expected behavior: It only inserts a DeallocOp at the
-// exit block after CopyOp since %1 is an alias for %0 and %arg1.
-
-// CHECK-LABEL: func @invCriticalEdge
-func.func @invCriticalEdge(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
- cf.cond_br %arg0, ^bb1, ^bb2(%arg1 : memref<2xf32>)
-^bb1:
- cf.br ^bb2(%0 : memref<2xf32>)
-^bb2(%1: memref<2xf32>):
- test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK: dealloc
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case:
-// bb0 <- Initial position of the first AllocOp
-// / \
-// bb1 bb2
-// \ /
-// bb3 <- Initial position of the second AllocOp
-// BufferDeallocation expected behavior: It only inserts two missing
-// DeallocOps in the exit block. %5 is an alias for %0. Therefore, the
-// DeallocOp for %0 should occur after the last BufferBasedOp. The Dealloc for
-// %7 should happen after CopyOp.
-
-// CHECK-LABEL: func @ifElse
-func.func @ifElse(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
- cf.cond_br %arg0,
- ^bb1(%arg1, %0 : memref<2xf32>, memref<2xf32>),
- ^bb2(%0, %arg1 : memref<2xf32>, memref<2xf32>)
-^bb1(%1: memref<2xf32>, %2: memref<2xf32>):
- cf.br ^bb3(%1, %2 : memref<2xf32>, memref<2xf32>)
-^bb2(%3: memref<2xf32>, %4: memref<2xf32>):
- cf.br ^bb3(%3, %4 : memref<2xf32>, memref<2xf32>)
-^bb3(%5: memref<2xf32>, %6: memref<2xf32>):
- %7 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%5: memref<2xf32>) out(%7: memref<2xf32>)
- test.copy(%7, %arg2) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: %[[FIRST_ALLOC:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based
-// CHECK: %[[SECOND_ALLOC:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based
-// CHECK: memref.dealloc %[[FIRST_ALLOC]]
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc %[[SECOND_ALLOC]]
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case: No users for buffer in if-else CFG
-// bb0 <- Initial position of AllocOp
-// / \
-// bb1 bb2
-// \ /
-// bb3
-// BufferDeallocation expected behavior: It only inserts a missing DeallocOp
-// in the exit block since %5 or %6 are the latest aliases of %0.
-
-// CHECK-LABEL: func @ifElseNoUsers
-func.func @ifElseNoUsers(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
- cf.cond_br %arg0,
- ^bb1(%arg1, %0 : memref<2xf32>, memref<2xf32>),
- ^bb2(%0, %arg1 : memref<2xf32>, memref<2xf32>)
-^bb1(%1: memref<2xf32>, %2: memref<2xf32>):
- cf.br ^bb3(%1, %2 : memref<2xf32>, memref<2xf32>)
-^bb2(%3: memref<2xf32>, %4: memref<2xf32>):
- cf.br ^bb3(%3, %4 : memref<2xf32>, memref<2xf32>)
-^bb3(%5: memref<2xf32>, %6: memref<2xf32>):
- test.copy(%arg1, %arg2) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: %[[FIRST_ALLOC:.*]] = memref.alloc()
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc %[[FIRST_ALLOC]]
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case:
-// bb0 <- Initial position of the first AllocOp
-// / \
-// bb1 bb2
-// | / \
-// | bb3 bb4
-// \ \ /
-// \ /
-// bb5 <- Initial position of the second AllocOp
-// BufferDeallocation expected behavior: Two missing DeallocOps should be
-// inserted in the exit block.
-
-// CHECK-LABEL: func @ifElseNested
-func.func @ifElseNested(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
- cf.cond_br %arg0,
- ^bb1(%arg1, %0 : memref<2xf32>, memref<2xf32>),
- ^bb2(%0, %arg1 : memref<2xf32>, memref<2xf32>)
-^bb1(%1: memref<2xf32>, %2: memref<2xf32>):
- cf.br ^bb5(%1, %2 : memref<2xf32>, memref<2xf32>)
-^bb2(%3: memref<2xf32>, %4: memref<2xf32>):
- cf.cond_br %arg0, ^bb3(%3 : memref<2xf32>), ^bb4(%4 : memref<2xf32>)
-^bb3(%5: memref<2xf32>):
- cf.br ^bb5(%5, %3 : memref<2xf32>, memref<2xf32>)
-^bb4(%6: memref<2xf32>):
- cf.br ^bb5(%3, %6 : memref<2xf32>, memref<2xf32>)
-^bb5(%7: memref<2xf32>, %8: memref<2xf32>):
- %9 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%7: memref<2xf32>) out(%9: memref<2xf32>)
- test.copy(%9, %arg2) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: %[[FIRST_ALLOC:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based
-// CHECK: %[[SECOND_ALLOC:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based
-// CHECK: memref.dealloc %[[FIRST_ALLOC]]
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc %[[SECOND_ALLOC]]
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case: Dead operations in a single block.
-// BufferDeallocation expected behavior: It only inserts the two missing
-// DeallocOps after the last BufferBasedOp.
-
-// CHECK-LABEL: func @redundantOperations
-func.func @redundantOperations(%arg0: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg0: memref<2xf32>) out(%0: memref<2xf32>)
- %1 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%0: memref<2xf32>) out(%1: memref<2xf32>)
- return
-}
-
-// CHECK: (%[[ARG0:.*]]: {{.*}})
-// CHECK-NEXT: %[[FIRST_ALLOC:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based in(%[[ARG0]]{{.*}}out(%[[FIRST_ALLOC]]
-// CHECK: %[[SECOND_ALLOC:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based in(%[[FIRST_ALLOC]]{{.*}}out(%[[SECOND_ALLOC]]
-// CHECK: dealloc
-// CHECK-NEXT: dealloc
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case:
-// bb0
-// / \
-// Initial pos of the 1st AllocOp -> bb1 bb2 <- Initial pos of the 2nd AllocOp
-// \ /
-// bb3
-// BufferDeallocation expected behavior: We need to introduce a copy for each
-// buffer since the buffers are passed to bb3. The both missing DeallocOps are
-// inserted in the respective block of the allocs. The copy is freed in the exit
-// block.
-
-// CHECK-LABEL: func @moving_alloc_and_inserting_missing_dealloc
-func.func @moving_alloc_and_inserting_missing_dealloc(
- %cond: i1,
- %arg0: memref<2xf32>,
- %arg1: memref<2xf32>) {
- cf.cond_br %cond, ^bb1, ^bb2
-^bb1:
- %0 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg0: memref<2xf32>) out(%0: memref<2xf32>)
- cf.br ^exit(%0 : memref<2xf32>)
-^bb2:
- %1 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg0: memref<2xf32>) out(%1: memref<2xf32>)
- cf.br ^exit(%1 : memref<2xf32>)
-^exit(%arg2: memref<2xf32>):
- test.copy(%arg2, %arg1) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: cf.cond_br{{.*}}
-// CHECK-NEXT: ^bb1
-// CHECK: %[[ALLOC0:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based
-// CHECK-NEXT: %[[ALLOC1:.*]] = bufferization.clone %[[ALLOC0]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC0]]
-// CHECK-NEXT: cf.br ^bb3(%[[ALLOC1]]
-// CHECK-NEXT: ^bb2
-// CHECK-NEXT: %[[ALLOC2:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based
-// CHECK-NEXT: %[[ALLOC3:.*]] = bufferization.clone %[[ALLOC2]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC2]]
-// CHECK-NEXT: cf.br ^bb3(%[[ALLOC3]]
-// CHECK-NEXT: ^bb3(%[[ALLOC4:.*]]:{{.*}})
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc %[[ALLOC4]]
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case: Invalid position of the DeallocOp. There is a user after
-// deallocation.
-// bb0
-// / \
-// bb1 bb2 <- Initial position of AllocOp
-// \ /
-// bb3
-// BufferDeallocation expected behavior: The existing DeallocOp should be
-// moved to exit block.
-
-// CHECK-LABEL: func @moving_invalid_dealloc_op_complex
-func.func @moving_invalid_dealloc_op_complex(
- %cond: i1,
- %arg0: memref<2xf32>,
- %arg1: memref<2xf32>) {
- %1 = memref.alloc() : memref<2xf32>
- cf.cond_br %cond, ^bb1, ^bb2
-^bb1:
- cf.br ^exit(%arg0 : memref<2xf32>)
-^bb2:
- test.buffer_based in(%arg0: memref<2xf32>) out(%1: memref<2xf32>)
- memref.dealloc %1 : memref<2xf32>
- cf.br ^exit(%1 : memref<2xf32>)
-^exit(%arg2: memref<2xf32>):
- test.copy(%arg2, %arg1) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: %[[ALLOC0:.*]] = memref.alloc()
-// CHECK-NEXT: cf.cond_br
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc %[[ALLOC0]]
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case: Inserting missing DeallocOp in a single block.
-
-// CHECK-LABEL: func @inserting_missing_dealloc_simple
-func.func @inserting_missing_dealloc_simple(
- %arg0 : memref<2xf32>,
- %arg1: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg0: memref<2xf32>) out(%0: memref<2xf32>)
- test.copy(%0, %arg1) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: %[[ALLOC0:.*]] = memref.alloc()
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc %[[ALLOC0]]
-
-// -----
-
-// Test Case: Moving invalid DeallocOp (there is a user after deallocation) in a
-// single block.
-
-// CHECK-LABEL: func @moving_invalid_dealloc_op
-func.func @moving_invalid_dealloc_op(%arg0 : memref<2xf32>, %arg1: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg0: memref<2xf32>) out(%0: memref<2xf32>)
- memref.dealloc %0 : memref<2xf32>
- test.copy(%0, %arg1) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: %[[ALLOC0:.*]] = memref.alloc()
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc %[[ALLOC0]]
-
-// -----
-
-// Test Case: Nested regions - This test defines a BufferBasedOp inside the
-// region of a RegionBufferBasedOp.
-// BufferDeallocation expected behavior: The AllocOp for the BufferBasedOp
-// should remain inside the region of the RegionBufferBasedOp and it should insert
-// the missing DeallocOp in the same region. The missing DeallocOp should be
-// inserted after CopyOp.
-
-// CHECK-LABEL: func @nested_regions_and_cond_branch
-func.func @nested_regions_and_cond_branch(
- %arg0: i1,
- %arg1: memref<2xf32>,
- %arg2: memref<2xf32>) {
- cf.cond_br %arg0, ^bb1, ^bb2
-^bb1:
- cf.br ^bb3(%arg1 : memref<2xf32>)
-^bb2:
- %0 = memref.alloc() : memref<2xf32>
- test.region_buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>) {
- ^bb0(%gen1_arg0: f32, %gen1_arg1: f32):
- %1 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg1: memref<2xf32>) out(%1: memref<2xf32>)
- %tmp1 = math.exp %gen1_arg0 : f32
- test.region_yield %tmp1 : f32
- }
- cf.br ^bb3(%0 : memref<2xf32>)
-^bb3(%1: memref<2xf32>):
- test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)
- return
-}
-// CHECK: (%[[cond:.*]]: {{.*}}, %[[ARG1:.*]]: {{.*}}, %{{.*}}: {{.*}})
-// CHECK-NEXT: cf.cond_br %[[cond]], ^[[BB1:.*]], ^[[BB2:.*]]
-// CHECK: %[[ALLOC0:.*]] = bufferization.clone %[[ARG1]]
-// CHECK: ^[[BB2]]:
-// CHECK: %[[ALLOC1:.*]] = memref.alloc()
-// CHECK-NEXT: test.region_buffer_based in(%[[ARG1]]{{.*}}out(%[[ALLOC1]]
-// CHECK: %[[ALLOC2:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based in(%[[ARG1]]{{.*}}out(%[[ALLOC2]]
-// CHECK: memref.dealloc %[[ALLOC2]]
-// CHECK-NEXT: %{{.*}} = math.exp
-// CHECK: %[[ALLOC3:.*]] = bufferization.clone %[[ALLOC1]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC1]]
-// CHECK: ^[[BB3:.*]]({{.*}}):
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc
-
-// -----
-
-// Test Case: buffer deallocation escaping
-// BufferDeallocation expected behavior: It must not dealloc %arg1 and %x
-// since they are operands of return operation and should escape from
-// deallocating. It should dealloc %y after CopyOp.
-
-// CHECK-LABEL: func @memref_in_function_results
-func.func @memref_in_function_results(
- %arg0: memref<5xf32>,
- %arg1: memref<10xf32>,
- %arg2: memref<5xf32>) -> (memref<10xf32>, memref<15xf32>) {
- %x = memref.alloc() : memref<15xf32>
- %y = memref.alloc() : memref<5xf32>
- test.buffer_based in(%arg0: memref<5xf32>) out(%y: memref<5xf32>)
- test.copy(%y, %arg2) : (memref<5xf32>, memref<5xf32>)
- return %arg1, %x : memref<10xf32>, memref<15xf32>
-}
-// CHECK: (%[[ARG0:.*]]: memref<5xf32>, %[[ARG1:.*]]: memref<10xf32>,
-// CHECK-SAME: %[[RESULT:.*]]: memref<5xf32>)
-// CHECK: %[[X:.*]] = memref.alloc()
-// CHECK: %[[Y:.*]] = memref.alloc()
-// CHECK: test.copy
-// CHECK: memref.dealloc %[[Y]]
-// CHECK: return %[[ARG1]], %[[X]]
-
-// -----
-
-// Test Case: nested region control flow
-// The alloc %1 flows through both if branches until it is finally returned.
-// Hence, it does not require a specific dealloc operation. However, %3
-// requires a dealloc.
-
-// CHECK-LABEL: func @nested_region_control_flow
-func.func @nested_region_control_flow(
- %arg0 : index,
- %arg1 : index) -> memref<?x?xf32> {
- %0 = arith.cmpi eq, %arg0, %arg1 : index
- %1 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
- %2 = scf.if %0 -> (memref<?x?xf32>) {
- scf.yield %1 : memref<?x?xf32>
- } else {
- %3 = memref.alloc(%arg0, %arg1) : memref<?x?xf32>
- scf.yield %1 : memref<?x?xf32>
- }
- return %2 : memref<?x?xf32>
-}
-
-// CHECK: %[[ALLOC0:.*]] = memref.alloc(%arg0, %arg0)
-// CHECK-NEXT: %[[ALLOC1:.*]] = scf.if
-// CHECK: scf.yield %[[ALLOC0]]
-// CHECK: %[[ALLOC2:.*]] = memref.alloc(%arg0, %arg1)
-// CHECK-NEXT: memref.dealloc %[[ALLOC2]]
-// CHECK-NEXT: scf.yield %[[ALLOC0]]
-// CHECK: return %[[ALLOC1]]
-
-// -----
-
-// Test Case: nested region control flow with a nested buffer allocation in a
-// divergent branch.
-// Buffer deallocation places a copy for both %1 and %3, since they are
-// returned in the end.
-
-// CHECK-LABEL: func @nested_region_control_flow_div
-func.func @nested_region_control_flow_div(
- %arg0 : index,
- %arg1 : index) -> memref<?x?xf32> {
- %0 = arith.cmpi eq, %arg0, %arg1 : index
- %1 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
- %2 = scf.if %0 -> (memref<?x?xf32>) {
- scf.yield %1 : memref<?x?xf32>
- } else {
- %3 = memref.alloc(%arg0, %arg1) : memref<?x?xf32>
- scf.yield %3 : memref<?x?xf32>
- }
- return %2 : memref<?x?xf32>
-}
-
-// CHECK: %[[ALLOC0:.*]] = memref.alloc(%arg0, %arg0)
-// CHECK-NEXT: %[[ALLOC1:.*]] = scf.if
-// CHECK-NEXT: %[[ALLOC2:.*]] = bufferization.clone %[[ALLOC0]]
-// CHECK: scf.yield %[[ALLOC2]]
-// CHECK: %[[ALLOC3:.*]] = memref.alloc(%arg0, %arg1)
-// CHECK-NEXT: %[[ALLOC4:.*]] = bufferization.clone %[[ALLOC3]]
-// CHECK: memref.dealloc %[[ALLOC3]]
-// CHECK: scf.yield %[[ALLOC4]]
-// CHECK: memref.dealloc %[[ALLOC0]]
-// CHECK-NEXT: return %[[ALLOC1]]
-
-// -----
-
-// Test Case: nested region control flow within a region interface.
-// No copies are required in this case since the allocation finally escapes
-// the method.
-
-// CHECK-LABEL: func @inner_region_control_flow
-func.func @inner_region_control_flow(%arg0 : index) -> memref<?x?xf32> {
- %0 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
- %1 = test.region_if %0 : memref<?x?xf32> -> (memref<?x?xf32>) then {
- ^bb0(%arg1 : memref<?x?xf32>):
- test.region_if_yield %arg1 : memref<?x?xf32>
- } else {
- ^bb0(%arg1 : memref<?x?xf32>):
- test.region_if_yield %arg1 : memref<?x?xf32>
- } join {
- ^bb0(%arg1 : memref<?x?xf32>):
- test.region_if_yield %arg1 : memref<?x?xf32>
- }
- return %1 : memref<?x?xf32>
-}
-
-// CHECK: %[[ALLOC0:.*]] = memref.alloc(%arg0, %arg0)
-// CHECK-NEXT: %[[ALLOC1:.*]] = test.region_if
-// CHECK-NEXT: ^bb0(%[[ALLOC2:.*]]:{{.*}}):
-// CHECK-NEXT: test.region_if_yield %[[ALLOC2]]
-// CHECK: ^bb0(%[[ALLOC3:.*]]:{{.*}}):
-// CHECK-NEXT: test.region_if_yield %[[ALLOC3]]
-// CHECK: ^bb0(%[[ALLOC4:.*]]:{{.*}}):
-// CHECK-NEXT: test.region_if_yield %[[ALLOC4]]
-// CHECK: return %[[ALLOC1]]
-
-// -----
-
-// CHECK-LABEL: func @subview
-func.func @subview(%arg0 : index, %arg1 : index, %arg2 : memref<?x?xf32>) {
- %0 = memref.alloc() : memref<64x4xf32, strided<[4, 1], offset: 0>>
- %1 = memref.subview %0[%arg0, %arg1][%arg0, %arg1][%arg0, %arg1] :
- memref<64x4xf32, strided<[4, 1], offset: 0>>
- to memref<?x?xf32, strided<[?, ?], offset: ?>>
- test.copy(%1, %arg2) :
- (memref<?x?xf32, strided<[?, ?], offset: ?>>, memref<?x?xf32>)
- return
-}
-
-// CHECK-NEXT: %[[ALLOC:.*]] = memref.alloc()
-// CHECK-NEXT: memref.subview
-// CHECK-NEXT: test.copy
-// CHECK-NEXT: memref.dealloc %[[ALLOC]]
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case: In the presence of AllocaOps only the AllocOps has top be freed.
-// Therefore, all allocas are not handled.
-
-// CHECK-LABEL: func @condBranchAlloca
-func.func @condBranchAlloca(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- cf.cond_br %arg0, ^bb1, ^bb2
-^bb1:
- cf.br ^bb3(%arg1 : memref<2xf32>)
-^bb2:
- %0 = memref.alloca() : memref<2xf32>
- test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
- cf.br ^bb3(%0 : memref<2xf32>)
-^bb3(%1: memref<2xf32>):
- test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: cf.cond_br
-// CHECK: %[[ALLOCA:.*]] = memref.alloca()
-// CHECK: cf.br ^bb3(%[[ALLOCA:.*]])
-// CHECK-NEXT: ^bb3
-// CHECK-NEXT: test.copy
-// CHECK-NEXT: return
-
-// -----
-
-// Test Case: In the presence of AllocaOps only the AllocOps has top be freed.
-// Therefore, all allocas are not handled. In this case, only alloc %0 has a
-// dealloc.
-
-// CHECK-LABEL: func @ifElseAlloca
-func.func @ifElseAlloca(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
- cf.cond_br %arg0,
- ^bb1(%arg1, %0 : memref<2xf32>, memref<2xf32>),
- ^bb2(%0, %arg1 : memref<2xf32>, memref<2xf32>)
-^bb1(%1: memref<2xf32>, %2: memref<2xf32>):
- cf.br ^bb3(%1, %2 : memref<2xf32>, memref<2xf32>)
-^bb2(%3: memref<2xf32>, %4: memref<2xf32>):
- cf.br ^bb3(%3, %4 : memref<2xf32>, memref<2xf32>)
-^bb3(%5: memref<2xf32>, %6: memref<2xf32>):
- %7 = memref.alloca() : memref<2xf32>
- test.buffer_based in(%5: memref<2xf32>) out(%7: memref<2xf32>)
- test.copy(%7, %arg2) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: %[[ALLOC:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based
-// CHECK: %[[ALLOCA:.*]] = memref.alloca()
-// CHECK-NEXT: test.buffer_based
-// CHECK: memref.dealloc %[[ALLOC]]
-// CHECK: test.copy
-// CHECK-NEXT: return
-
-// -----
-
-// CHECK-LABEL: func @ifElseNestedAlloca
-func.func @ifElseNestedAlloca(
- %arg0: i1,
- %arg1: memref<2xf32>,
- %arg2: memref<2xf32>) {
- %0 = memref.alloca() : memref<2xf32>
- test.buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>)
- cf.cond_br %arg0,
- ^bb1(%arg1, %0 : memref<2xf32>, memref<2xf32>),
- ^bb2(%0, %arg1 : memref<2xf32>, memref<2xf32>)
-^bb1(%1: memref<2xf32>, %2: memref<2xf32>):
- cf.br ^bb5(%1, %2 : memref<2xf32>, memref<2xf32>)
-^bb2(%3: memref<2xf32>, %4: memref<2xf32>):
- cf.cond_br %arg0, ^bb3(%3 : memref<2xf32>), ^bb4(%4 : memref<2xf32>)
-^bb3(%5: memref<2xf32>):
- cf.br ^bb5(%5, %3 : memref<2xf32>, memref<2xf32>)
-^bb4(%6: memref<2xf32>):
- cf.br ^bb5(%3, %6 : memref<2xf32>, memref<2xf32>)
-^bb5(%7: memref<2xf32>, %8: memref<2xf32>):
- %9 = memref.alloc() : memref<2xf32>
- test.buffer_based in(%7: memref<2xf32>) out(%9: memref<2xf32>)
- test.copy(%9, %arg2) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-NEXT: %[[ALLOCA:.*]] = memref.alloca()
-// CHECK-NEXT: test.buffer_based
-// CHECK: %[[ALLOC:.*]] = memref.alloc()
-// CHECK-NEXT: test.buffer_based
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc %[[ALLOC]]
-// CHECK-NEXT: return
-
-// -----
-
-// CHECK-LABEL: func @nestedRegionsAndCondBranchAlloca
-func.func @nestedRegionsAndCondBranchAlloca(
- %arg0: i1,
- %arg1: memref<2xf32>,
- %arg2: memref<2xf32>) {
- cf.cond_br %arg0, ^bb1, ^bb2
-^bb1:
- cf.br ^bb3(%arg1 : memref<2xf32>)
-^bb2:
- %0 = memref.alloc() : memref<2xf32>
- test.region_buffer_based in(%arg1: memref<2xf32>) out(%0: memref<2xf32>) {
- ^bb0(%gen1_arg0: f32, %gen1_arg1: f32):
- %1 = memref.alloca() : memref<2xf32>
- test.buffer_based in(%arg1: memref<2xf32>) out(%1: memref<2xf32>)
- %tmp1 = math.exp %gen1_arg0 : f32
- test.region_yield %tmp1 : f32
- }
- cf.br ^bb3(%0 : memref<2xf32>)
-^bb3(%1: memref<2xf32>):
- test.copy(%1, %arg2) : (memref<2xf32>, memref<2xf32>)
- return
-}
-// CHECK: (%[[cond:.*]]: {{.*}}, %[[ARG1:.*]]: {{.*}}, %{{.*}}: {{.*}})
-// CHECK-NEXT: cf.cond_br %[[cond]], ^[[BB1:.*]], ^[[BB2:.*]]
-// CHECK: ^[[BB1]]:
-// CHECK: %[[ALLOC0:.*]] = bufferization.clone
-// CHECK: ^[[BB2]]:
-// CHECK: %[[ALLOC1:.*]] = memref.alloc()
-// CHECK-NEXT: test.region_buffer_based in(%[[ARG1]]{{.*}}out(%[[ALLOC1]]
-// CHECK: %[[ALLOCA:.*]] = memref.alloca()
-// CHECK-NEXT: test.buffer_based in(%[[ARG1]]{{.*}}out(%[[ALLOCA]]
-// CHECK: %{{.*}} = math.exp
-// CHECK: %[[ALLOC2:.*]] = bufferization.clone %[[ALLOC1]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC1]]
-// CHECK: ^[[BB3:.*]]({{.*}}):
-// CHECK: test.copy
-// CHECK-NEXT: memref.dealloc
-
-// -----
-
-// CHECK-LABEL: func @nestedRegionControlFlowAlloca
-func.func @nestedRegionControlFlowAlloca(
- %arg0 : index,
- %arg1 : index) -> memref<?x?xf32> {
- %0 = arith.cmpi eq, %arg0, %arg1 : index
- %1 = memref.alloc(%arg0, %arg0) : memref<?x?xf32>
- %2 = scf.if %0 -> (memref<?x?xf32>) {
- scf.yield %1 : memref<?x?xf32>
- } else {
- %3 = memref.alloca(%arg0, %arg1) : memref<?x?xf32>
- scf.yield %1 : memref<?x?xf32>
- }
- return %2 : memref<?x?xf32>
-}
-
-// CHECK: %[[ALLOC0:.*]] = memref.alloc(%arg0, %arg0)
-// CHECK-NEXT: %[[ALLOC1:.*]] = scf.if
-// CHECK: scf.yield %[[ALLOC0]]
-// CHECK: %[[ALLOCA:.*]] = memref.alloca(%arg0, %arg1)
-// CHECK-NEXT: scf.yield %[[ALLOC0]]
-// CHECK: return %[[ALLOC1]]
-
-// -----
-
-// Test Case: structured control-flow loop using a nested alloc.
-// The iteration argument %iterBuf has to be freed before yielding %3 to avoid
-// memory leaks.
-
-// CHECK-LABEL: func @loop_alloc
-func.func @loop_alloc(
- %lb: index,
- %ub: index,
- %step: index,
- %buf: memref<2xf32>,
- %res: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- %1 = scf.for %i = %lb to %ub step %step
- iter_args(%iterBuf = %buf) -> memref<2xf32> {
- %2 = arith.cmpi eq, %i, %ub : index
- %3 = memref.alloc() : memref<2xf32>
- scf.yield %3 : memref<2xf32>
- }
- test.copy(%1, %res) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK: %[[ALLOC0:.*]] = memref.alloc()
-// CHECK-NEXT: memref.dealloc %[[ALLOC0]]
-// CHECK-NEXT: %[[ALLOC1:.*]] = bufferization.clone %arg3
-// CHECK: %[[ALLOC2:.*]] = scf.for {{.*}} iter_args
-// CHECK-SAME: (%[[IALLOC:.*]] = %[[ALLOC1]]
-// CHECK: arith.cmpi
-// CHECK: memref.dealloc %[[IALLOC]]
-// CHECK: %[[ALLOC3:.*]] = memref.alloc()
-// CHECK: %[[ALLOC4:.*]] = bufferization.clone %[[ALLOC3]]
-// CHECK: memref.dealloc %[[ALLOC3]]
-// CHECK: scf.yield %[[ALLOC4]]
-// CHECK: }
-// CHECK: test.copy(%[[ALLOC2]], %arg4)
-// CHECK-NEXT: memref.dealloc %[[ALLOC2]]
-
-// -----
-
-// Test Case: structured control-flow loop with a nested if operation.
-// The loop yields buffers that have been defined outside of the loop and the
-// backedges only use the iteration arguments (or one of its aliases).
-// Therefore, we do not have to (and are not allowed to) free any buffers
-// that are passed via the backedges.
-
-// CHECK-LABEL: func @loop_nested_if_no_alloc
-func.func @loop_nested_if_no_alloc(
- %lb: index,
- %ub: index,
- %step: index,
- %buf: memref<2xf32>,
- %res: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- %1 = scf.for %i = %lb to %ub step %step
- iter_args(%iterBuf = %buf) -> memref<2xf32> {
- %2 = arith.cmpi eq, %i, %ub : index
- %3 = scf.if %2 -> (memref<2xf32>) {
- scf.yield %0 : memref<2xf32>
- } else {
- scf.yield %iterBuf : memref<2xf32>
- }
- scf.yield %3 : memref<2xf32>
- }
- test.copy(%1, %res) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK: %[[ALLOC0:.*]] = memref.alloc()
-// CHECK-NEXT: %[[ALLOC1:.*]] = scf.for {{.*}} iter_args(%[[IALLOC:.*]] =
-// CHECK: %[[ALLOC2:.*]] = scf.if
-// CHECK: scf.yield %[[ALLOC0]]
-// CHECK: scf.yield %[[IALLOC]]
-// CHECK: scf.yield %[[ALLOC2]]
-// CHECK: test.copy(%[[ALLOC1]], %arg4)
-// CHECK: memref.dealloc %[[ALLOC0]]
-
-// -----
-
-// Test Case: structured control-flow loop with a nested if operation using
-// a deeply nested buffer allocation.
-// Since the innermost allocation happens in a divergent branch, we have to
-// introduce additional copies for the nested if operation. Since the loop's
-// yield operation "returns" %3, it will return a newly allocated buffer.
-// Therefore, we have to free the iteration argument %iterBuf before
-// "returning" %3.
-
-// CHECK-LABEL: func @loop_nested_if_alloc
-func.func @loop_nested_if_alloc(
- %lb: index,
- %ub: index,
- %step: index,
- %buf: memref<2xf32>) -> memref<2xf32> {
- %0 = memref.alloc() : memref<2xf32>
- %1 = scf.for %i = %lb to %ub step %step
- iter_args(%iterBuf = %buf) -> memref<2xf32> {
- %2 = arith.cmpi eq, %i, %ub : index
- %3 = scf.if %2 -> (memref<2xf32>) {
- %4 = memref.alloc() : memref<2xf32>
- scf.yield %4 : memref<2xf32>
- } else {
- scf.yield %0 : memref<2xf32>
- }
- scf.yield %3 : memref<2xf32>
- }
- return %1 : memref<2xf32>
-}
-
-// CHECK: %[[ALLOC0:.*]] = memref.alloc()
-// CHECK-NEXT: %[[ALLOC1:.*]] = bufferization.clone %arg3
-// CHECK-NEXT: %[[ALLOC2:.*]] = scf.for {{.*}} iter_args
-// CHECK-SAME: (%[[IALLOC:.*]] = %[[ALLOC1]]
-// CHECK: memref.dealloc %[[IALLOC]]
-// CHECK: %[[ALLOC3:.*]] = scf.if
-
-// CHECK: %[[ALLOC4:.*]] = memref.alloc()
-// CHECK-NEXT: %[[ALLOC5:.*]] = bufferization.clone %[[ALLOC4]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC4]]
-// CHECK-NEXT: scf.yield %[[ALLOC5]]
-
-// CHECK: %[[ALLOC6:.*]] = bufferization.clone %[[ALLOC0]]
-// CHECK-NEXT: scf.yield %[[ALLOC6]]
-
-// CHECK: %[[ALLOC7:.*]] = bufferization.clone %[[ALLOC3]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC3]]
-// CHECK-NEXT: scf.yield %[[ALLOC7]]
-
-// CHECK: memref.dealloc %[[ALLOC0]]
-// CHECK-NEXT: return %[[ALLOC2]]
-
-// -----
-
-// Test Case: several nested structured control-flow loops with a deeply nested
-// buffer allocation inside an if operation.
-// Same behavior is an loop_nested_if_alloc: we have to insert deallocations
-// before each yield in all loops recursively.
-
-// CHECK-LABEL: func @loop_nested_alloc
-func.func @loop_nested_alloc(
- %lb: index,
- %ub: index,
- %step: index,
- %buf: memref<2xf32>,
- %res: memref<2xf32>) {
- %0 = memref.alloc() : memref<2xf32>
- %1 = scf.for %i = %lb to %ub step %step
- iter_args(%iterBuf = %buf) -> memref<2xf32> {
- %2 = scf.for %i2 = %lb to %ub step %step
- iter_args(%iterBuf2 = %iterBuf) -> memref<2xf32> {
- %3 = scf.for %i3 = %lb to %ub step %step
- iter_args(%iterBuf3 = %iterBuf2) -> memref<2xf32> {
- %4 = memref.alloc() : memref<2xf32>
- %5 = arith.cmpi eq, %i, %ub : index
- %6 = scf.if %5 -> (memref<2xf32>) {
- %7 = memref.alloc() : memref<2xf32>
- scf.yield %7 : memref<2xf32>
- } else {
- scf.yield %iterBuf3 : memref<2xf32>
- }
- scf.yield %6 : memref<2xf32>
- }
- scf.yield %3 : memref<2xf32>
- }
- scf.yield %2 : memref<2xf32>
- }
- test.copy(%1, %res) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK: %[[ALLOC0:.*]] = memref.alloc()
-// CHECK-NEXT: memref.dealloc %[[ALLOC0]]
-// CHECK-NEXT: %[[ALLOC1:.*]] = bufferization.clone %arg3
-// CHECK-NEXT: %[[VAL_7:.*]] = scf.for {{.*}} iter_args
-// CHECK-SAME: (%[[IALLOC0:.*]] = %[[ALLOC1]])
-// CHECK-NEXT: %[[ALLOC2:.*]] = bufferization.clone %[[IALLOC0]]
-// CHECK-NEXT: memref.dealloc %[[IALLOC0]]
-// CHECK-NEXT: %[[ALLOC3:.*]] = scf.for {{.*}} iter_args
-// CHECK-SAME: (%[[IALLOC1:.*]] = %[[ALLOC2]])
-// CHECK-NEXT: %[[ALLOC5:.*]] = bufferization.clone %[[IALLOC1]]
-// CHECK-NEXT: memref.dealloc %[[IALLOC1]]
-
-// CHECK: %[[ALLOC6:.*]] = scf.for {{.*}} iter_args
-// CHECK-SAME: (%[[IALLOC2:.*]] = %[[ALLOC5]])
-// CHECK: %[[ALLOC8:.*]] = memref.alloc()
-// CHECK-NEXT: memref.dealloc %[[ALLOC8]]
-// CHECK: %[[ALLOC9:.*]] = scf.if
-
-// CHECK: %[[ALLOC11:.*]] = memref.alloc()
-// CHECK-NEXT: %[[ALLOC12:.*]] = bufferization.clone %[[ALLOC11]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC11]]
-// CHECK-NEXT: scf.yield %[[ALLOC12]]
-
-// CHECK: %[[ALLOC13:.*]] = bufferization.clone %[[IALLOC2]]
-// CHECK-NEXT: scf.yield %[[ALLOC13]]
-
-// CHECK: memref.dealloc %[[IALLOC2]]
-// CHECK-NEXT: %[[ALLOC10:.*]] = bufferization.clone %[[ALLOC9]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC9]]
-// CHECK-NEXT: scf.yield %[[ALLOC10]]
-
-// CHECK: %[[ALLOC7:.*]] = bufferization.clone %[[ALLOC6]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC6]]
-// CHECK-NEXT: scf.yield %[[ALLOC7]]
-
-// CHECK: %[[ALLOC4:.*]] = bufferization.clone %[[ALLOC3]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC3]]
-// CHECK-NEXT: scf.yield %[[ALLOC4]]
-
-// CHECK: test.copy(%[[VAL_7]], %arg4)
-// CHECK-NEXT: memref.dealloc %[[VAL_7]]
-
-// -----
-
-// CHECK-LABEL: func @affine_loop
-func.func @affine_loop() {
- %buffer = memref.alloc() : memref<1024xf32>
- %sum_init_0 = arith.constant 0.0 : f32
- %res = affine.for %i = 0 to 10 step 2 iter_args(%sum_iter = %sum_init_0) -> f32 {
- %t = affine.load %buffer[%i] : memref<1024xf32>
- %sum_next = arith.addf %sum_iter, %t : f32
- affine.yield %sum_next : f32
- }
- // CHECK: %[[M:.*]] = memref.alloc
- // CHECK: affine.for
- // CHECK: }
- // CHECK-NEXT: memref.dealloc %[[M]]
- 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 at +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 at +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
-}
-
-// -----
-
-// CHECK-LABEL: func @assumingOp(
-func.func @assumingOp(
- %arg0: !shape.witness,
- %arg2: memref<2xf32>,
- %arg3: memref<2xf32>) {
- // Confirm the alloc will be dealloc'ed in the block.
- %1 = shape.assuming %arg0 -> memref<2xf32> {
- %0 = memref.alloc() : memref<2xf32>
- shape.assuming_yield %arg2 : memref<2xf32>
- }
- // Confirm the alloc will be returned and dealloc'ed after its use.
- %3 = shape.assuming %arg0 -> memref<2xf32> {
- %2 = memref.alloc() : memref<2xf32>
- shape.assuming_yield %2 : memref<2xf32>
- }
- test.copy(%3, %arg3) : (memref<2xf32>, memref<2xf32>)
- return
-}
-
-// CHECK-SAME: %[[ARG0:.*]]: !shape.witness,
-// CHECK-SAME: %[[ARG1:.*]]: {{.*}},
-// CHECK-SAME: %[[ARG2:.*]]: {{.*}}
-// CHECK: %[[UNUSED_RESULT:.*]] = shape.assuming %[[ARG0]]
-// CHECK-NEXT: %[[ALLOC0:.*]] = memref.alloc()
-// CHECK-NEXT: memref.dealloc %[[ALLOC0]]
-// CHECK-NEXT: shape.assuming_yield %[[ARG1]]
-// CHECK: %[[ASSUMING_RESULT:.*]] = shape.assuming %[[ARG0]]
-// CHECK-NEXT: %[[TMP_ALLOC:.*]] = memref.alloc()
-// CHECK-NEXT: %[[RETURNING_ALLOC:.*]] = bufferization.clone %[[TMP_ALLOC]]
-// CHECK-NEXT: memref.dealloc %[[TMP_ALLOC]]
-// CHECK-NEXT: shape.assuming_yield %[[RETURNING_ALLOC]]
-// CHECK: test.copy(%[[ASSUMING_RESULT:.*]], %[[ARG2]])
-// CHECK-NEXT: memref.dealloc %[[ASSUMING_RESULT]]
-
-// -----
-
-// Test Case: The op "test.bar" does not implement the RegionBranchOpInterface.
-// This is not allowed in buffer deallocation.
-
-func.func @noRegionBranchOpInterface() {
-// expected-error at +1 {{All operations with attached regions need to implement the RegionBranchOpInterface.}}
- %0 = "test.bar"() ({
-// expected-error at +1 {{All operations with attached regions need to implement the RegionBranchOpInterface.}}
- %1 = "test.bar"() ({
- "test.yield"() : () -> ()
- }) : () -> (i32)
- "test.yield"() : () -> ()
- }) : () -> (i32)
- "test.terminator"() : () -> ()
-}
-
-// -----
-
-// CHECK-LABEL: func @dealloc_existing_clones
-// CHECK: (%[[ARG0:.*]]: memref<?x?xf64>, %[[ARG1:.*]]: memref<?x?xf64>)
-// CHECK: %[[RES0:.*]] = bufferization.clone %[[ARG0]]
-// CHECK: %[[RES1:.*]] = bufferization.clone %[[ARG1]]
-// CHECK-NOT: memref.dealloc %[[RES0]]
-// CHECK: memref.dealloc %[[RES1]]
-// CHECK: return %[[RES0]]
-func.func @dealloc_existing_clones(%arg0: memref<?x?xf64>, %arg1: memref<?x?xf64>) -> memref<?x?xf64> {
- %0 = bufferization.clone %arg0 : memref<?x?xf64> to memref<?x?xf64>
- %1 = bufferization.clone %arg1 : memref<?x?xf64> to memref<?x?xf64>
- return %0 : memref<?x?xf64>
-}
-
-// -----
-
-// CHECK-LABEL: func @while_two_arg
-func.func @while_two_arg(%arg0: index) {
- %a = memref.alloc(%arg0) : memref<?xf32>
-// CHECK: %[[WHILE:.*]]:2 = scf.while (%[[ARG1:.*]] = %[[ALLOC:.*]], %[[ARG2:.*]] = %[[CLONE:.*]])
- scf.while (%arg1 = %a, %arg2 = %a) : (memref<?xf32>, memref<?xf32>) -> (memref<?xf32>, memref<?xf32>) {
-// CHECK-NEXT: make_condition
- %0 = "test.make_condition"() : () -> i1
-// CHECK-NEXT: bufferization.clone %[[ARG2]]
-// CHECK-NEXT: memref.dealloc %[[ARG2]]
- scf.condition(%0) %arg1, %arg2 : memref<?xf32>, memref<?xf32>
- } do {
- ^bb0(%arg1: memref<?xf32>, %arg2: memref<?xf32>):
-// CHECK: %[[ALLOC2:.*]] = memref.alloc
- %b = memref.alloc(%arg0) : memref<?xf32>
-// CHECK: memref.dealloc %[[ARG2]]
-// CHECK: %[[CLONE2:.*]] = bufferization.clone %[[ALLOC2]]
-// CHECK: memref.dealloc %[[ALLOC2]]
- scf.yield %arg1, %b : memref<?xf32>, memref<?xf32>
- }
-// CHECK: }
-// CHECK-NEXT: memref.dealloc %[[WHILE]]#1
-// CHECK-NEXT: memref.dealloc %[[ALLOC]]
-// CHECK-NEXT: return
- return
-}
-
-// -----
-
-func.func @while_three_arg(%arg0: index) {
-// CHECK: %[[ALLOC:.*]] = memref.alloc
- %a = memref.alloc(%arg0) : memref<?xf32>
-// CHECK-NEXT: %[[CLONE1:.*]] = bufferization.clone %[[ALLOC]]
-// CHECK-NEXT: %[[CLONE2:.*]] = bufferization.clone %[[ALLOC]]
-// CHECK-NEXT: %[[CLONE3:.*]] = bufferization.clone %[[ALLOC]]
-// CHECK-NEXT: memref.dealloc %[[ALLOC]]
-// CHECK-NEXT: %[[WHILE:.*]]:3 = scf.while
-// FIXME: This is non-deterministic
-// CHECK-SAME-DAG: [[CLONE1]]
-// CHECK-SAME-DAG: [[CLONE2]]
-// CHECK-SAME-DAG: [[CLONE3]]
- scf.while (%arg1 = %a, %arg2 = %a, %arg3 = %a) : (memref<?xf32>, memref<?xf32>, memref<?xf32>) -> (memref<?xf32>, memref<?xf32>, memref<?xf32>) {
- %0 = "test.make_condition"() : () -> i1
- scf.condition(%0) %arg1, %arg2, %arg3 : memref<?xf32>, memref<?xf32>, memref<?xf32>
- } do {
- ^bb0(%arg1: memref<?xf32>, %arg2: memref<?xf32>, %arg3: memref<?xf32>):
- %b = memref.alloc(%arg0) : memref<?xf32>
- %q = memref.alloc(%arg0) : memref<?xf32>
- scf.yield %q, %b, %arg2: memref<?xf32>, memref<?xf32>, memref<?xf32>
- }
-// CHECK-DAG: memref.dealloc %[[WHILE]]#0
-// CHECK-DAG: memref.dealloc %[[WHILE]]#1
-// CHECK-DAG: memref.dealloc %[[WHILE]]#2
-// CHECK-NEXT: return
- return
-}
-
-// -----
-
-func.func @select_aliases(%arg0: index, %arg1: memref<?xi8>, %arg2: i1) {
- // CHECK: memref.alloc
- // CHECK: memref.alloc
- // CHECK: arith.select
- // CHECK: test.copy
- // CHECK: memref.dealloc
- // CHECK: memref.dealloc
- %0 = memref.alloc(%arg0) : memref<?xi8>
- %1 = memref.alloc(%arg0) : memref<?xi8>
- %2 = arith.select %arg2, %0, %1 : memref<?xi8>
- test.copy(%2, %arg1) : (memref<?xi8>, memref<?xi8>)
- return
-}
-
-// -----
-
-func.func @f(%arg0: memref<f64>) -> memref<f64> {
- return %arg0 : memref<f64>
-}
-
-// CHECK-LABEL: func @function_call
-// CHECK: memref.alloc
-// CHECK: memref.alloc
-// CHECK: call
-// CHECK: test.copy
-// CHECK: memref.dealloc
-// CHECK: memref.dealloc
-func.func @function_call() {
- %alloc = memref.alloc() : memref<f64>
- %alloc2 = memref.alloc() : memref<f64>
- %ret = call @f(%alloc) : (memref<f64>) -> memref<f64>
- test.copy(%ret, %alloc2) : (memref<f64>, memref<f64>)
- return
-}
-
-// -----
-
-// Memref allocated in `then` region and passed back to the parent if op.
-#set = affine_set<() : (0 >= 0)>
-// CHECK-LABEL: func @test_affine_if_1
-// CHECK-SAME: %[[ARG0:.*]]: memref<10xf32>) -> memref<10xf32> {
-func.func @test_affine_if_1(%arg0: memref<10xf32>) -> memref<10xf32> {
- %0 = affine.if #set() -> memref<10xf32> {
- %alloc = memref.alloc() : memref<10xf32>
- affine.yield %alloc : memref<10xf32>
- } else {
- affine.yield %arg0 : memref<10xf32>
- }
- return %0 : memref<10xf32>
-}
-// CHECK-NEXT: %[[IF:.*]] = affine.if
-// CHECK-NEXT: %[[MEMREF:.*]] = memref.alloc() : memref<10xf32>
-// CHECK-NEXT: %[[CLONED:.*]] = bufferization.clone %[[MEMREF]] : memref<10xf32> to memref<10xf32>
-// CHECK-NEXT: memref.dealloc %[[MEMREF]] : memref<10xf32>
-// CHECK-NEXT: affine.yield %[[CLONED]] : memref<10xf32>
-// CHECK-NEXT: } else {
-// CHECK-NEXT: %[[ARG0_CLONE:.*]] = bufferization.clone %[[ARG0]] : memref<10xf32> to memref<10xf32>
-// CHECK-NEXT: affine.yield %[[ARG0_CLONE]] : memref<10xf32>
-// CHECK-NEXT: }
-// CHECK-NEXT: return %[[IF]] : memref<10xf32>
-
-// -----
-
-// Memref allocated before parent IfOp and used in `then` region.
-// Expected result: deallocation should happen after affine.if op.
-#set = affine_set<() : (0 >= 0)>
-// CHECK-LABEL: func @test_affine_if_2() -> memref<10xf32> {
-func.func @test_affine_if_2() -> memref<10xf32> {
- %alloc0 = memref.alloc() : memref<10xf32>
- %0 = affine.if #set() -> memref<10xf32> {
- affine.yield %alloc0 : memref<10xf32>
- } else {
- %alloc = memref.alloc() : memref<10xf32>
- affine.yield %alloc : memref<10xf32>
- }
- return %0 : memref<10xf32>
-}
-// CHECK-NEXT: %[[ALLOC:.*]] = memref.alloc() : memref<10xf32>
-// CHECK-NEXT: %[[IF_RES:.*]] = affine.if {{.*}} -> memref<10xf32> {
-// CHECK-NEXT: %[[ALLOC_CLONE:.*]] = bufferization.clone %[[ALLOC]] : memref<10xf32> to memref<10xf32>
-// CHECK-NEXT: affine.yield %[[ALLOC_CLONE]] : memref<10xf32>
-// CHECK-NEXT: } else {
-// CHECK-NEXT: %[[ALLOC2:.*]] = memref.alloc() : memref<10xf32>
-// CHECK-NEXT: %[[ALLOC2_CLONE:.*]] = bufferization.clone %[[ALLOC2]] : memref<10xf32> to memref<10xf32>
-// CHECK-NEXT: memref.dealloc %[[ALLOC2]] : memref<10xf32>
-// CHECK-NEXT: affine.yield %[[ALLOC2_CLONE]] : memref<10xf32>
-// CHECK-NEXT: }
-// CHECK-NEXT: memref.dealloc %[[ALLOC]] : memref<10xf32>
-// CHECK-NEXT: return %[[IF_RES]] : memref<10xf32>
-
-// -----
-
-// Memref allocated before parent IfOp and used in `else` region.
-// Expected result: deallocation should happen after affine.if op.
-#set = affine_set<() : (0 >= 0)>
-// CHECK-LABEL: func @test_affine_if_3() -> memref<10xf32> {
-func.func @test_affine_if_3() -> memref<10xf32> {
- %alloc0 = memref.alloc() : memref<10xf32>
- %0 = affine.if #set() -> memref<10xf32> {
- %alloc = memref.alloc() : memref<10xf32>
- affine.yield %alloc : memref<10xf32>
- } else {
- affine.yield %alloc0 : memref<10xf32>
- }
- return %0 : memref<10xf32>
-}
-// CHECK-NEXT: %[[ALLOC:.*]] = memref.alloc() : memref<10xf32>
-// CHECK-NEXT: %[[IFRES:.*]] = affine.if {{.*}} -> memref<10xf32> {
-// CHECK-NEXT: memref.alloc
-// CHECK-NEXT: bufferization.clone
-// CHECK-NEXT: memref.dealloc
-// CHECK-NEXT: affine.yield
-// CHECK-NEXT: } else {
-// CHECK-NEXT: bufferization.clone
-// CHECK-NEXT: affine.yield
-// CHECK-NEXT: }
-// CHECK-NEXT: memref.dealloc %[[ALLOC]] : memref<10xf32>
-// CHECK-NEXT: return %[[IFRES]] : memref<10xf32>
-
-// -----
-
-// Memref allocated before parent IfOp and not used later.
-// Expected result: deallocation should happen before affine.if op.
-#set = affine_set<() : (0 >= 0)>
-// CHECK-LABEL: func @test_affine_if_4({{.*}}: memref<10xf32>) -> memref<10xf32> {
-func.func @test_affine_if_4(%arg0 : memref<10xf32>) -> memref<10xf32> {
- %alloc0 = memref.alloc() : memref<10xf32>
- %0 = affine.if #set() -> memref<10xf32> {
- affine.yield %arg0 : memref<10xf32>
- } else {
- %alloc = memref.alloc() : memref<10xf32>
- affine.yield %alloc : memref<10xf32>
- }
- return %0 : memref<10xf32>
-}
-// CHECK-NEXT: %[[ALLOC:.*]] = memref.alloc() : memref<10xf32>
-// CHECK-NEXT: memref.dealloc %[[ALLOC]] : memref<10xf32>
-// CHECK-NEXT: affine.if
-
-// -----
-
-// Ensure we free the realloc, not the alloc.
-
-// CHECK-LABEL: func @auto_dealloc()
-func.func @auto_dealloc() {
- %c10 = arith.constant 10 : index
- %c100 = arith.constant 100 : index
- %alloc = memref.alloc(%c10) : memref<?xi32>
- %realloc = memref.realloc %alloc(%c100) : memref<?xi32> to memref<?xi32>
- return
-}
-// CHECK-DAG: %[[C10:.*]] = arith.constant 10 : index
-// CHECK-DAG: %[[C100:.*]] = arith.constant 100 : index
-// CHECK-NEXT: %[[A:.*]] = memref.alloc(%[[C10]]) : memref<?xi32>
-// CHECK-NEXT: %[[R:.*]] = memref.realloc %alloc(%[[C100]]) : memref<?xi32> to memref<?xi32>
-// CHECK-NEXT: memref.dealloc %[[R]] : memref<?xi32>
-// CHECK-NEXT: return
-
-
diff --git a/mlir/test/Pass/pipeline-invalid.mlir b/mlir/test/Pass/pipeline-invalid.mlir
index f9dd4c29dd7f0..948a13384bc75 100644
--- a/mlir/test/Pass/pipeline-invalid.mlir
+++ b/mlir/test/Pass/pipeline-invalid.mlir
@@ -1,8 +1,8 @@
// RUN: mlir-opt --no-implicit-module \
-// RUN: --pass-pipeline='any(buffer-deallocation)' --verify-diagnostics \
+// RUN: --pass-pipeline='any(test-function-pass)' --verify-diagnostics \
// RUN: --split-input-file %s
-// Note: "buffer-deallocation" is a function pass. Any other function pass could
+// Note: "test-function-pass" is a function pass. Any other function pass could
// be used for this test.
// expected-error at below {{trying to schedule a pass on an operation not marked as 'IsolatedFromAbove'}}
More information about the Mlir-commits
mailing list