Commit Graph

116 Commits

Author SHA1 Message Date
Matthias Springer
6ecebb496c [mlir][bufferization] Support unstructured control flow
This revision adds support for unstructured control flow to the bufferization infrastructure. In particular: regions with multiple blocks, `cf.br`, `cf.cond_br`.

Two helper templates are added to `BufferizableOpInterface.h`, which can be implemented by ops that supported unstructured control flow in their regions (e.g., `func.func`) and ops that branch to another block (e.g., `cf.br`).

A block signature is always bufferized together with the op that owns the block.

Differential Revision: https://reviews.llvm.org/D158094
2023-08-31 12:55:53 +02:00
Martin Erhart
950f0944c9 [mlir][bufferization] Factor out bufferization.dealloc lowering into separate pass
Moves the lowering of `bufferization.dealloc` to memref into a separate pass,
but still registers the pattern in the conversion pass.  This is helpful when
some tensor values (and thus `to_memref` or `to_tensor` operations) still
remain, e.g., when the function boundaries are not converted, or when constant
tensors are converted to memref.get_global at a later point.

However, it is still recommended to perform all bufferization before
deallocation to avoid memory leaks as all memref allocations inserted after the
deallocation pass was applied, have to be handled manually.

Note: The buffer deallocation pass assumes that memref values defined by
`bufferization.to_memref` don't return ownership and don't have to be
deallocated. `bufferization.to_tensor` operations are handled similarly to
`bufferization.clone` operations with the exception that the result value is
not handled because it's a tensor (not a memref).

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D159180
2023-08-31 07:10:31 +00:00
Martin Erhart
fff183050a [mlir][bufferization] Run the simple dealloc canonicalization patterns as part of BufferDeallocationSimplification
Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D158744
2023-08-28 08:04:03 +00:00
Martin Erhart
fea185d70d [mlir][bufferization] Add pattern to BufferDeallocationSimplification pass
This new pattern allows us to simplify the dealloc result value (by replacing
it with a constant 'true') and to trim the 'memref' operand list when we know
that all retained memrefs alias with one in the 'memref' list that has a
constant 'true' condition. Because the conditions of aliasing memrefs are
combined by disjunction, we know that once a single constant 'true' value is in
the disjunction the remaining elements don't matter anymore. This complements
the RemoveDeallocMemrefsContainedInRetained pattern which removes values from
the 'memref' list when static information is available for all retained values
by also allowing to remove values in the presence of may-aliases, but under
above mentioned condition instead.
The BufferDeallocation pass often adds dealloc operations where the memref and
retain lists are the same and all conditions are 'true'. If the operands are
all function arguments, for example, they are always determined to may-alias
which renders the other patterns invalid, but the op could still be trivially
optimized away. It would even be enough to directly compare the two operand
lists and check the conditions are all constant 'true' (plus checking for the
extract_strided_metadata operation), but this pattern is a bit more general and
still works when there are additional memrefs in the 'memref' list that actually
have to be deallocated (e.g., see regression test).

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D158518
2023-08-23 10:41:05 +00:00
Martin Erhart
765e82eeb6 [mlir][bufferization] Generalize dealloc simplification pattern
We are allowed to remove any values from the `memref` list for which there is no
memref in the `retained` list with a may-alias relation. Before removing, we
just have to make sure that the corresponding op results for all retained
memrefs with must-alias relation  are updated accordingly. This means, the the
condition operand has to become part of the disjunction the result value is
computed with.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D158395
2023-08-21 13:08:00 +00:00
Matthias Springer
a02ad6c177 [mlir][bufferization] Generalize getAliasingOpResults to getAliasingValues
This revision is needed to support bufferization of `cf.br`/`cf.cond_br`. It will also be useful for better analysis of loop ops.

This revision generalizes `getAliasingOpResults` to `getAliasingValues`. An OpOperand can now not only alias with OpResults but also with BlockArguments. In the case of `cf.br` (will be added in a later revision): a `cf.br` operand will alias with the corresponding argument of the destination block.

If an op does not implement the `BufferizableOpInterface`, the analysis in conservative. It previously assumed that an OpOperand may alias with each OpResult. It now assumes that an OpOperand may alias with each OpResult and each BlockArgument of the entry block.

Differential Revision: https://reviews.llvm.org/D157957
2023-08-15 15:02:47 +02:00
Martin Erhart
0bcae5e763 [mlir][bufferization] Add pattern to BufferDeallocationSimplification pass
Add a pattern that splits one dealloc operation into multiple dealloc operation
depending on static aliasing information of the values in the `memref` operand
list. This reduces the total number of aliasing checks required at runtime and
can enable futher canonicalizations of the new and simplified dealloc
operations.

Depends on D157407

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D157508
2023-08-15 12:39:57 +00:00
Martin Erhart
c5e8fbbf71 [mlir][bufferization] Add pattern to BufferDeallocationSimplification pass that removes unnecessary retain values
Adds a pattern that removes memrefs from the `retained` list which are
guaranteed to not alias any memref in the `memrefs` list. The corresponding
result value can be replaced with `false` in that case according to the
operation description.

When applied after BufferDeallocation, this can considerably reduce the
overhead that needs to be added during the lowering of the dealloc operation to
check for aliasing (especially when there is only one element in the `memref`
list and all `retained` values can be removed).

Depends on D157398

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D157407
2023-08-10 13:46:52 +00:00
Martin Erhart
87f2dee423 [mlir][bufferization] Add DeallocationSimplification pass
Adds a pass that can be run after buffer deallocation to simplify the deallocation operations.
In particular, there are patterns that need alias information and thus cannot be added as a regular canonicalization pattern.
This initial commit moves an incorrect canonicalization pattern from over to this new pass and fixes it by querying the alias analysis for the additional information it needs to be correct (there must not by any potential aliasing memref in the retain list other than the currently mached one).
Also, improves this pattern by considering the `extract_strided_metadata` operation which is inserted by the deallocation pass by default.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D157398
2023-08-10 12:45:38 +00:00
Matthias Springer
aba0ef7059 [mlir][bufferization] Support casts in EmptyTensorElimination
EmptyTensorElimination is a pre-bufferization transformation that replaces "tensor.empty" ops with "tensor.extract_slice" ops. This revision adds support for cases where the input IR contains "tensor.cast" ops.

Differential Revision: https://reviews.llvm.org/D156167
2023-07-31 15:20:00 +02:00
Matthias Springer
ba745eea40 [mlir][bufferization] Remove cleanup pipeline from bufferization pass
To keep the pass simple, users should apply cleanup passes manually when necessary. In particular, `-cse -canonicalize` are often desireable to fold away self-copies that are created by the bufferization.

This addresses a comment in D120191.

Differential Revision: https://reviews.llvm.org/D155923
2023-07-21 12:11:25 +02:00
Matthias Springer
98770ecd76 [mlir][bufferization] Add buffer_loop_hoisting transform op
This op hoists buffer allocation from loops.

Differential Revision: https://reviews.llvm.org/D155289
2023-07-14 17:09:38 +02:00
Matthias Springer
88f4292a16 [mlir][bufferization] OneShotBufferizeOp: Add options to use linalg.copy
This new option allows users to specify a custom memcpy op.

Differential Revision: https://reviews.llvm.org/D155280
2023-07-14 13:34:22 +02:00
Matthias Springer
8e72fbd616 [mlir][bufferization] Add read_only attribute to ToMemrefOp
This unit attribute indicates to the bufferization that the resulting buffer will not be written to by another op.

Differential Revision: https://reviews.llvm.org/D154967
2023-07-11 16:37:17 +02:00
Matthias Springer
88bc92e8fc [mlir][bufferization] Fix insertion point issue in EliminateEmptyTensors
The replacement op insertion point was off by one.

Differential Revision: https://reviews.llvm.org/D154608
2023-07-06 16:20:01 +02:00
Matthias Springer
d31a6dfbc0 [mlir][bufferization] Add bufferization.copy_tensor op
This operation is a "copy" operation on tensors. It is guaranteed to bufferize to a memcpy. This is different from "tensor.insert_slice", which may fold away.

Note: There is a symmetry between certain tensor, bufferization and memref ops:
* `tensor.empty`, `bufferization.alloc_tensor`, `memref.alloc`
* (none), `bufferization.dealloc_tensor`, `memref.dealloc`
* `tensor.insert_slice`, `bufferization.copy_tensor`, `memref.copy`

Tensor ops can generally canonicalize/fold away, while bufferization dialect ops can be used when a certain side effect is expected to materialize; so they do not fold away.

Differential Revision: https://reviews.llvm.org/D153552
2023-06-27 14:57:13 +02:00
Matthias Springer
4ef6028340 [mlir][bufferization] Allow to_memref ops in One-Shot Analysis
bufferization.to_memref ops are allowed in One-Shot Bufferize, but they are treated conservatively: in the absence of a memref analysis, we have to assume that the result buffer is read and written.

Note: to_memref cannot introduce any future aliases that would have to be considered during One-Shot Bufferize, because only to_tensor ops with the `restrict` attribute are supported. Such tensors are guaranteed to not alias with any other buffer after bufferization.

Differential Revision: https://reviews.llvm.org/D153365
2023-06-21 08:42:25 +02:00
Matthias Springer
aa90948302 [mlir][bufferization] Fix bug in findValueInReverseUseDefChain
This bug was recently introduced in D143927 and manifests as a dominance violation.

Differential Revision: https://reviews.llvm.org/D151077
2023-05-23 15:30:08 +02:00
Kai Sasaki
6cd7b655d8 [mlir][bufferization] Prevent crash in one shot bufferization with unranked tensor cast
One shot bufferization does not support bufferizing the cast between unranked tensors. To prevent the crash, we can check the compatibility of the result type in advance. Reported in https://github.com/llvm/llvm-project/issues/62369.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D149239
2023-05-19 08:54:43 +09:00
Alex Zinenko
2f3ac28cb2 [mlir] don't hardcode PDL_Operation in Transform dialect extensions
Update operations in Transform dialect extensions defined in the Affine,
GPU, MemRef and Tensor dialects to use the more generic
`TransformHandleTypeInterface` type constraint instead of hardcoding
`PDL_Operation`. See
https://discourse.llvm.org/t/rfc-type-system-for-the-transform-dialect/65702
for motivation.

Remove the dependency on PDLDialect from these extensions.

Update tests to use `!transform.any_op` instead of `!pdl.operation`.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D150781
2023-05-17 15:10:12 +00:00
Matthias Springer
ae8cb64372 [mlir][scf][bufferize] Fix bug in WhileOp analysis verification
Block arguments and yielded values are not equivalent if there are not enough block arguments. This fixes #59442.

Differential Revision: https://reviews.llvm.org/D145575
2023-05-15 15:42:56 +02:00
Matthias Springer
bb9d1b551a [mlir][bufferization] Add option to dump alias sets
This is useful for debugging.

Differential Revision: https://reviews.llvm.org/D143314
2023-05-15 15:38:20 +02:00
Matthias Springer
38bef47655 [mlir][bufferization] Fix unknown ops in BufferViewFlowAnalysis
If an op is unknown to the analysis, it must be treated conservatively: assume that every operand aliases with every result.

Differential Revision: https://reviews.llvm.org/D150546
2023-05-15 14:33:06 +02:00
Matthias Springer
1ccd8cd6e6 [mlir][bufferization] Add bufferization.eliminate_empty_tensors transform op
Differential Revision: https://reviews.llvm.org/D144401
2023-04-06 14:22:47 +09:00
Matthias Springer
3f7959ea3d [mlir][bufferize] Simplify one_shot_bufferize transform op
Restrict the op to functions and modules. Such ops are modified in-place. The transform now consumes the handle and produces a new handle. The `target_is_module` attribute is no longer needed because a result handle is produced in either case.

Differential Revision: https://reviews.llvm.org/D147446
2023-04-06 12:59:35 +09:00
Matthias Springer
fdb9e6a3a8 [mlir][bufferization] Fix crash in EmptyTensorElimination
Differential Revision: https://reviews.llvm.org/D144389
2023-02-20 16:41:02 +01:00
Alexander Belyaev
eb2f946e78 [mlir][scf] Rename ForeachThreadOp->ForallOp, PerformConcurrentlyOp->InParallelOp.
Differential Revision: https://reviews.llvm.org/D144242
2023-02-17 09:59:39 +01:00
Matthias Springer
e44f405bb4 [mlir][bufferization] Fix bug in findValueInReverseUseDefChain
`alwaysIncludeLeaves` was not respected by all code paths.

Differential Revision: https://reviews.llvm.org/D144187
2023-02-16 16:12:31 +01:00
Matthias Springer
8f7e7400b7 [mlir][bufferization] Add restrict and writable attrs to to_tensor
`restrict` is similar to the C++ restrict keyword. Results of `to_tensor` that have the `restrict` attribute are guaranteed to not alias any other `to_tensor` result (after bufferization).

Note: Since `to_memref` ops are not supported by One-Shot Bufferize and all bufferizable ops follow DPS rules (i.e., the buffer of the result is the buffer of an operand or an alias thereof), the buffer of a `to_tensor` op that has the `restrict` attribute is always an entirely "new" buffer that is not aliasing with the future buffer of any tensor value in the entire program. This makes such `to_tensor` ops "safe" from a bufferization perspective; they cannot cause RaW conflicts.

Differential Revision: https://reviews.llvm.org/D144021
2023-02-15 10:04:54 +01:00
Ingo Müller
dc700f1e4d [mlir][bufferization] Restrict function boundary buffer. to func.call.
The current bufferization on function boundaries works on `func.func`
and any call op implementing `CallOpInterface`. Then, an error is thrown
if there is a `CallOpInterface` op that is not `func.call`. This is
unnecessary and breaks the pass whenever such an op occurs (such as
`llvm.call`). This PR simply restricts the handling of call ops to
`func.call`.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D143724
2023-02-10 11:59:06 +00:00
Matthias Springer
2441c07306 [mlir][bufferization] Support multiple leaves in EmptyTensorElimination
Support cases where a source tensor can be traced back to multiple possible tensor.empty ops.

Differential Revision: https://reviews.llvm.org/D142130
2023-02-10 09:38:47 +01:00
Aart Bik
e379b4e047 [mlir][memref] annotate operand and result of realloc with proper memory attributes
Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D143599
2023-02-09 12:05:51 -08:00
Matthias Springer
1fdf06d6d7 [mlir][bufferization] Reads from tensors with undefined data are not a conflict
Reading from tensor.empty or bufferization.alloc_tensor (without copy) cannot cause a conflict because these ops do not specify the contents of their result tensors.

Differential Revision: https://reviews.llvm.org/D143183
2023-02-06 16:11:13 +01:00
Maya Amrami
ac64c54649 [mlir][bufferization] Fix failing lit test
Checks were too strict and by the time the patch was submitted,
the output of the test changed.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D142969
2023-01-31 13:11:25 +02:00
Maya Amrami
060c8be51b [mlir][OneShotModuleBufferize] Add a new flag: no-analysis-func-filter
OneShotModuleBufferize fails if the input IR cannot be analyzed.
One can set CopyBeforeWrite=true in order to skip analysis.
In that case, a buffer copy is inserted on every write.
This leads to many copies, also in FuncOps that could be analyzed.

This change aims to copy buffers only when it is a must.
When running OneShotModuleBufferize with CopyBeforeWrite=false,
FuncOps whose names are specified in noAnalysisFuncFilter will not be
analyzed. Ops in these FuncOps will not be analyzed as well.
They will be bufferized with CopyBeforeWrite=true,
while the other ops will be bufferized with CopyBeforeWrite=false.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D142631
2023-01-31 11:26:15 +02:00
Matthias Springer
d7f72d4bb4 [mlir][bufferization] Better handling of unranked tensors in resolveTensorOpOperandConflicts
Unranked tensors can currently not be copied. They are forced to always bufferize in-place. There is typically some other OpOperand that can bufferize out-of-place instead if needed.

Note: There is IR that cannot be bufferized with One-Shot Bufferize at the moment (see invalid test case). But it is unclear if we need to support such cases. We do not have a use case at the moment. This restriction could be loosened in the future if needed.

This change improves error handling when bufferizing IR where an unranked tensor would be copied. It also disables an optimization where an OpResult was copied instead of an OpOperand in case the OpResult is an unranked tensor (Github #60187).

Differential Revision: https://reviews.llvm.org/D142331
2023-01-30 10:20:10 +01:00
Matthias Springer
f3483c23ce [mlir][bufferization] Fix getAliasingOpOperand/OpResult for non-bufferizable ops
Also enable analysis of unknown ops.

Differential Revision: https://reviews.llvm.org/D142006
2023-01-30 10:10:43 +01:00
Nicolas Vasilache
e1c5cbc09c [mlir][Linalg] Put a proper type on transform.structured.match op
This allows much better verification messages in consuming ops that properly declare
`TransformHandleTypeInterface` on their operands.

Downstream tests can be updated with a command resembling:

```
 git grep -l "structured\.match" mlir/test | xargs -i sed -i {} -e  "s/\(structured.match.*\)/\1 : (\!pdl.operation) -> \!pdl.operation/g"
```

Differential Revision: https://reviews.llvm.org/D142643
2023-01-26 08:51:34 -08:00
Will Dietz
cc50625fed [mlir] Gate test checking statistics on their availability.
Fixes #59620.
2022-12-21 18:49:35 -06:00
Lorenzo Chelini
e7d0cc76d7 [MLIR][Bufferization] Introduce EmptyTensorToAllocTensorOp
Introduce a new transform operation to replace `tensor.empty` with
`alloc_tensor` operations. The operation is a pass-through if the target
operation is already a `alloc_tensor`; otherwise, it expects a
`tensor.empty` as a target. Currently, it does not return any results.

The operation is expected to run before `one_shot_bufferize` as
`one_shot_bufferize` rejects `tensor.empty`.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D140026
2022-12-19 09:12:10 +01:00
Matthias Springer
ae05bd99d3 [mlir][bufferize][NFC] Add statistics to OneShotBufferizePass
Print statistics about the number of alloc/deallocs and in-place/out-of-place bufferization.

Differential Revision: https://reviews.llvm.org/D139538
2022-12-15 18:02:51 +01:00
Benjamin Chetioui
a6c8f06f55 [mlir] Clean up typos in FileCheck directives in various tests.
Reviewed By: tpopp

Differential Revision: https://reviews.llvm.org/D139698
2022-12-12 09:29:14 +01:00
Matthias Springer
4002eaaa01 [mlir][bufferize] Improve analysis of external functions
External functions have no body, so they cannot be analyzed. Assume conservatively that each tensor bbArg may be aliasing with each tensor result. Furthermore, assume that each function arg is read and written-to after bufferization. This default behavior can be controlled with `bufferization.access` (similar to `bufferization.memory_layout`) in test cases.

Also fix a bug in the dialect attribute verifier, which did not run for region argument attributes.

Differential Revision: https://reviews.llvm.org/D139517
2022-12-09 14:36:33 +01:00
Emilio Cota
72d76a2403 [mlir][bufferize] lower allocation alignment from 128 to 64 bytes
While it is unlikely to matter in practice, there is no reason
for this value to be larger than it should be. 64 bytes is the
size of a cache line in most machines, and we can fit a full
512-bit vector in it.

Reviewed By: springerm
Differential Revision: https://reviews.llvm.org/D139434
2022-12-07 11:12:46 -05:00
Matthias Springer
0abf513d0f [mlir][bufferize] Support parallel_insert_slice in EmptyTensorElimination
Differential Revision: https://reviews.llvm.org/D139431
2022-12-07 11:39:12 +01:00
Matthias Springer
c1fef4e88a [mlir][bufferization] Make TensorCopyInsertionPass a test pass
TensorCopyInsertion should not have been exposed as a pass. This was a flaw in the original design. It is a preparation step for bufferization and certain transforms (that would otherwise be legal) are illegal between TensorCopyInsertion and actual rewrite to MemRef ops. Therefore, even if broken down as two separate steps internally, they should be exposed as a single pass.

This change affects the sparse compiler, which uses `TensorCopyInsertionPass`. A new `SparsificationAndBufferizationPass` is added to replace all passes in the sparse tensor pipeline from `TensorCopyInsertionPass` until the actual bufferization (rewrite to memref/non-tensor). It is generally unsafe to run arbitrary passes in-between, in particular passes that hoist tensor ops out of loops or change SSA use-def chains along tensor ops.

Differential Revision: https://reviews.llvm.org/D138915
2022-12-02 15:38:02 +01:00
Matthias Springer
c069feb89c [mlir][bufferize] Improve error message when returning allocs
The previous error message was confusing. Also improve code documentation and some minor code cleanups.

Differential Revision: https://reviews.llvm.org/D138902
2022-11-30 09:28:12 +01:00
Akshay Baviskar
7fbdee3e29 Add RegionBranchOpInterface for AffineIf Op
Adds RegionBranchOpInterface for AffineIf Op and tests it
using buffer deallocation pass.

Reviewed By: bondhugula

Differential Revision: https://reviews.llvm.org/D130962
2022-11-23 14:19:22 +05:30
Lei Zhang
9bb633741a [mlir][bufferization] Support general Attribute as memory space
MemRef has been accepting a general Attribute as memory space for
a long time. This commits updates bufferization side to catch up,
which allows downstream users to plugin customized symbolic memory
space. This also eliminates quite a few `getMemorySpaceAsInt`
calls, which is deprecated.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D138330
2022-11-21 09:40:50 -05:00
Lorenzo Chelini
c780184a84 [MLIR][Transform] Expose map layout option in OneShotBufferizeOp
Expose `function-boundary-type-conversion` in `OneShotBufferizeOp`. To
reuse options between passes and transform operations, create a
`BufferizationEnums.td`.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D137833
2022-11-14 18:09:54 +01:00