[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.
This commit is contained in:
parent
9b2fc66830
commit
213917be82
@ -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 different 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 different 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.
|
@ -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
|
||||
|
@ -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>
|
Before Width: | Height: | Size: 15 KiB |
@ -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>
|
Before Width: | Height: | Size: 15 KiB |
@ -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>
|
Before Width: | Height: | Size: 28 KiB |
@ -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>
|
Before Width: | Height: | Size: 26 KiB |
@ -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>
|
Before Width: | Height: | Size: 16 KiB |
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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>();
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
add_mlir_dialect_library(MLIRBufferizationTransforms
|
||||
Bufferize.cpp
|
||||
BufferDeallocation.cpp
|
||||
BufferDeallocationSimplification.cpp
|
||||
BufferOptimizations.cpp
|
||||
BufferResultsToOutParams.cpp
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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@below {{trying to schedule a pass on an operation not marked as 'IsolatedFromAbove'}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user