Commit Graph

183 Commits

Author SHA1 Message Date
Oleg Shyshkov
75ef84bf52 [mlir][bufferization] Make function boundary type convertion logic dynamic.
Having to choose from only static or dynamic layout for all function is limiting.

Differential Revision: https://reviews.llvm.org/D148074
2023-04-12 11:02:43 +02:00
Matthias Springer
9d80f17422 [mlir][bufferize] Fix tracking of erased ops
This is a workaround until D144193 has landed.

Differential Revision: https://reviews.llvm.org/D146868
2023-03-27 08:58:53 +02:00
Maya Amrami
8bb5ca5832 [mlir] Support bufferization of arith.constant to memref.global with memory space
Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D146381
2023-03-20 17:09:51 +02:00
Maya Amrami
4511128fc9 [mlir][bufferization] Consider defaultMemorySpace when bufferizing FuncOp
The function arguments and results type will have the default memory space.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D144539
2023-02-22 16:44:16 +02:00
Matthias Springer
c65328305e This change makes RewriterBase symmetric to OpBuilder.
```
  OpBuilder           OpBuilder::Listener
      ^                        ^
      |                        |
RewriterBase        RewriterBase::Listener
```

* Clients can listen to IR modifications with `RewriterBase::Listener`.
* `RewriterBase` no longer inherits from `OpBuilder::Listener`.
* Only a single listener can be registered at the moment (same as `OpBuilder`).

RFC: https://discourse.llvm.org/t/rfc-listeners-for-rewriterbase/68198

Differential Revision: https://reviews.llvm.org/D143339
2023-02-22 09:18:27 +01:00
Maya Amrami
ace6072bca [mlir] PromoteBuffersToStackPass - Copy attributes of original AllocOp
Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D143185
2023-02-16 17:06:45 +02: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
Uday Bondhugula
e6edc1bd69 [MLIR] Fix non-deterministic generation from buffer-deallocation pass
The buffer-deallocation pass generates a different output on each run
due to an unstable iteration order.

Fixes: https://github.com/llvm/llvm-project/issues/59118

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D143622
2023-02-10 04:51:59 +05:30
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
9fa6b3504b [mlir][bufferization] Improve aliasing OpOperand/OpResult property
`getAliasingOpOperands`/`getAliasingOpResults` now encodes OpOperand/OpResult, buffer relation and a degree of certainty. E.g.:
```
// aliasingOpOperands(%r) = {(%t, EQUIV, DEFINITE)}
// aliasingOpResults(%t) = {(%r, EQUIV, DEFINITE)}
%r = tensor.insert %f into %t[%idx] : tensor<?xf32>

// aliasingOpOperands(%r) = {(%t0, EQUIV, MAYBE), (%t1, EQUIV, MAYBE)}
// aliasingOpResults(%t0) = {(%r, EQUIV, MAYBE)}
// aliasingOpResults(%t1) = {(%r, EQUIV, MAYBE)}
%r = arith.select %c, %t0, %t1 : tensor<?xf32>
```

`BufferizableOpInterface::bufferRelation` is removed, as it is now part of `getAliasingOpOperands`/`getAliasingOpResults`.

This change allows for better analysis, in particular wrt. equivalence. This allows additional optimizations and better error checking (which is sometimes overly conservative). Examples:

* EmptyTensorElimination can eliminate `tensor.empty` inside `scf.if` blocks. This requires a modeling of equivalence: It is not a per-OpResult property anymore. Instead, it can be specified for each OpOperand and OpResult. This is important because `tensor.empty` may be eliminated only if all values on the SSA use-def chain to the final consumer (`tensor.insert_slice`) are equivalent.
* The detection of "returning allocs from a block" can be improved. (Addresses a TODO in `assertNoAllocsReturned`.) This allows us to bufferize IR such as "yielding a `tensor.extract_slice` result from an `scf.if` branch", which currently fails to bufferize because the alloc detection is too conservative.
* Better bufferization of loops. Aliases of the iter_arg can be yielded (even if they are not equivalent) without having to realloc and copy the entire buffer on each iteration.

The above-mentioned examples are not yet implemented with this change. This change just improves the BufferizableOpInterface, its implementations and related helper functions, so that better aliasing information is available for each op.

Differential Revision: https://reviews.llvm.org/D142129
2023-02-09 11:35:03 +01:00
Matthias Springer
2b5a020d3e [mlir][bufferization][NFC] Cache definitions of read tensors
This is to avoid unnecessary traversals of the IR.

Differential Revision: https://reviews.llvm.org/D143408
2023-02-09 09:27:39 +01:00
Matthias Springer
dc7ad194c7 [mlir][bufferize][NFC] Optimize read-only tensor detection
Check alias sets instead of traversing the IR.

Differential Revision: https://reviews.llvm.org/D143500
2023-02-09 09:07:14 +01:00
Matthias Springer
6d14b11018 [mlir][bufferize][NFC] OneShotAnalysis: Expose analysis hooks from AnalysisState
This is in preparation of reusing the same AnalysisState for tensor.empty elimination and One-Shot Bufferize (to address performance bottlenecks).

Differential Revision: https://reviews.llvm.org/D143379
2023-02-08 09:28:08 +01:00
Matthias Springer
cf2d374e99 [mlir][bufferize][NFC] Merge AnalysisState and BufferizationAliasInfo
There is no longer a need to keep the two separate. This is in preparation of reusing the same AnalysisState for tensor.empty elimination and One-Shot Bufferize (to address performance bottlenecks).

Differential Revision: https://reviews.llvm.org/D143313
2023-02-08 09:12:09 +01:00
Maya Amrami
9cf96850c3 [mlir][bufferize] Add noAnalysisFuncFilter to OneShotBufferizationOptions struct
This change is needed in order to set the flag when running the pass not via the command line.
It also allows simplifying the signature of some functions.

Reviewed By: springerm

Differential Revision: https://reviews.llvm.org/D143416
2023-02-07 12:38:30 +02:00
Matthias Springer
c89c31a230 [mlir][bufferization] Fix bufferization of repetitive regions
The previous strategy was too complex and faulty. Op dominance cannot be used to rule out RaW conflicts due to op ordering if the reading op and the conflicting writing op are in a sub repetitive region of the closest enclosing repetitive region of the definition of the read value.

Differential Revision: https://reviews.llvm.org/D143087
2023-02-06 16:23:08 +01: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
Matthias Springer
1ac248e485 [mlir][bufferization][NFC] Rename getAliasingOpOperand/getAliasingOpResult
* `getAliasingOpOperand` => `getAliasingOpOperands`
* `getAliasingOpResult` => `getAliasingOpResults`

Also a few minor code cleanups and better documentation.

Differential Revision: https://reviews.llvm.org/D142979
2023-02-01 10:07:41 +01: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
199f368e35 [mlir][vector][bufferize] Bufferize vector.mask and vector.yield
The masked op can currently not bufferize out-of-place. Such IR would be rejected by the One-Shot Bufferize because it would mean that a new buffer allocation is yielded from a block. Furthermore, only one operation is currently allowed inside `vector.mask`.

Differential Revision: https://reviews.llvm.org/D141686
2023-01-31 09:02:27 +01:00
Matthias Springer
148432ea84 [mlir][bufferization][NFC] Rename BufferRelation::None to BufferRelation::Unknown
The previous name was incorrect. `None` does not mean that there is no buffer relation between two buffers (seems to imply that they do not alias for sure); instead it means that there is no further information available.

Differential Revision: https://reviews.llvm.org/D142870
2023-01-30 11:09:28 +01:00
Matthias Springer
b7858f85f5 [mlir][bufferization][NFC] Simplify func bufferization state
The analysis previous kept track of OpOperand -> OpResult and OpResult -> OpOperand aliasing mappings. Only one mapping is needed, the other one can be inferred.

Differential Revision: https://reviews.llvm.org/D142128
2023-01-30 10:14: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
Matthias Springer
1840d18a10 [mlir][bufferization][NFC] Rename: "last-write" -> "definition"
The previous lingo was confusing. There are no writes on tensors. There are only definitions.

Also some minor cleanup and better documentation.

Differential Revision: https://reviews.llvm.org/D141790
2023-01-30 09:51:53 +01:00
Matthias Springer
34d65e81e8 [mlir][bufferization] Generalize and rename isMemoryWrite
The name of the method was confusing. It is bufferizesToMemoryWrite, but from the perspective of OpResults.

`bufferizesToMemoryWrite(OpResult)` now supports ops with regions that do not have aliasing OpOperands (such as `scf.if`). These ops no longer need to implement `isMemoryWrite`.

Differential Revision: https://reviews.llvm.org/D141684
2023-01-30 09:34:04 +01:00
Kazu Hirata
91682b2631 Remove redundant initialization of std::optional (NFC) 2023-01-14 14:06:18 -08:00
Kazu Hirata
0a81ace004 [mlir] Use std::optional instead of llvm::Optional (NFC)
This patch replaces (llvm::|)Optional< with std::optional<.  I'll post
a separate patch to remove #include "llvm/ADT/Optional.h".

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2023-01-14 01:25:58 -08:00
Kazu Hirata
a1fe1f5f77 [mlir] Add #include <optional> (NFC)
This patch adds #include <optional> to those files containing
llvm::Optional<...> or Optional<...>.

I'll post a separate patch to actually replace llvm::Optional with
std::optional.

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2023-01-13 21:05:06 -08:00
Matthias Springer
45cd0e453d [mlir][bufferization][NFC] Make getEnclosingRepetitiveRegion public
These functions are generally useful and not specific to One-Shot Analysis. Move them to `BufferizableOpInterface.h` and make them public.

Differential Revision: https://reviews.llvm.org/D141685
2023-01-13 16:39:41 +01:00
Ramkumar Ramachandra
e8bcc37fff mlir/{SPIRV,Bufferization}: use std::optional in .td files (NFC)
This is part of an effort to migrate from llvm::Optional to
std::optional. 22426110c5 changed the way mlir-tblgen generates .inc
files, emitting std::optional when an Optional attribute is specified in
a .td file. It also changed several .td files hard-coding llvm::Optional
to use std::optional. However, the patch excluded a few .td files in
SPIRV and Bufferization hard-coding llvm::Optional. This patch fixes
that defect, and after this patch, references to llvm::Optional in .cpp
and .h files can be replaced mechanically.

See also: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716

Signed-off-by: Ramkumar Ramachandra <r@artagnon.com>

Differential Revision: https://reviews.llvm.org/D140329
2022-12-20 09:23:58 +01:00
Ramkumar Ramachandra
22426110c5 mlir/tblgen: use std::optional in generation
This is part of an effort to migrate from llvm::Optional to
std::optional. This patch changes the way mlir-tblgen generates .inc
files, and modifies tests and documentation appropriately. It is a "no
compromises" patch, and doesn't leave the user with an unpleasant mix of
llvm::Optional and std::optional.

A non-trivial change has been made to ControlFlowInterfaces to split one
constructor into two, relating to a build failure on Windows.

See also: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716

Signed-off-by: Ramkumar Ramachandra <r@artagnon.com>

Differential Revision: https://reviews.llvm.org/D138934
2022-12-17 11:13:26 +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
Matthias Springer
1742882a34 [mlir][bufferize] Fix typo in EmptyTensorElimination
The structure of the code has changed a while ago and the code was not updated properly.

There is no test case for this because we do currently not have an op
that could trigger this bug.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D139838
2022-12-12 14:31:38 +01:00
Matthias Springer
be630f07de [mlir][bufferize] Implement BufferizableOpInterface for tensor.empty
The op is not bufferizable but should be analyzable (for `EliminateEmptyTensors`, which uses the bufferization infrastructure).

Also improve debugging functionality and error messages.

Also adds a missing pass to the sparse pipeline. (tensor.empty should be replaced with bufferization.alloc_tensor, but it sometimes used to work without depending on how the tensor.empty is used. Now we always fail explicitly.)
2022-12-12 14:19:38 +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
Matthias Springer
5d04f0c937 [mlir][bufferize] Update remaining getMemorySpaceAsInt API uses
D138330 updated the deprecated `getMemorySpaceAsInt` uses to `getMemorySpace`. There are few uses that were missed.

Differential Revision: https://reviews.llvm.org/D139526
2022-12-07 12:28:14 +01: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
Kazu Hirata
1a36588ec6 [mlir] Use std::nullopt instead of None (NFC)
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated.  The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-03 18:50:27 -08:00
Peiming Liu
c7a9e5e5d2 [mlir][sparse][bufferization] cleanup bufferization attributes after SparsificationAndBufferizationPass
Reviewed By: aartbik, springerm

Differential Revision: https://reviews.llvm.org/D139218
2022-12-02 23:03:54 +00:00
River Riddle
b74192b7ae [mlir] Remove support for non-prefixed accessors
This finishes off a year long pursuit to LLVMify the generated
operation accessors, prefixing them with get/set. Support for
any other accessor naming is fully removed after this commit.

https://discourse.llvm.org/t/psa-raw-accessors-are-being-removed/65629

Differential Revision: https://reviews.llvm.org/D136727
2022-12-02 13:32:36 -08: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
Matthias Springer
7cdfc843b5 [mlir][bufferize][NFC] Minor code and comment cleanups
Differential Revision: https://reviews.llvm.org/D135056
2022-11-22 17:04:09 +01:00
Matthias Springer
faa9be75ee [mlir][bufferize][NFC] Rename DialectAnalysisState and move to OneShotAnalysis
`DialectAnalysisState` is now `OneShotAnalysisState::Extension`.

This state extension mechanism is needed only for One-Shot Analysis, so it is moved from `BufferizableOpInterface.h` to `OneShotAnalysis.h`.

Extensions are now identified via TypeIDs instead of StringRefs. The API of state extensions is cleaned up and follows the same pattern as other extension mechanisms in MLIR (e.g., `transform::TransformState::Extension`).

Also delete some dead code.

Differential Revision: https://reviews.llvm.org/D135051
2022-11-22 14:34:55 +01:00
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
Aliia Khasanova
399638f98c Merge kDynamicSize and kDynamicSentinel into one constant.
resolve conflicts

Differential Revision: https://reviews.llvm.org/D138282
2022-11-21 13:01:26 +00:00
Mahesh Ravishankar
fc367dfa67 [mlir] Remove Transforms/SideEffectUtils.h and move the methods into Interface/SideEffectInterfaces.h.
The methods in `SideEffectUtils.h` (and their implementations in
`SideEffectUtils.cpp`) seem to have similar intent to methods already
existing in `SideEffectInterfaces.h`. Move the decleration (and
implementation) from `SideEffectUtils.h` (and `SideEffectUtils.cpp`)
into `SideEffectInterfaces.h` (and `SideEffectInterface.cpp`).

Also drop the `SideEffectInterface::hasNoEffect` method in favor of
`mlir::isMemoryEffectFree` which actually recurses into the operation
instead of just relying on the `hasRecursiveMemoryEffectTrait`
exclusively.

Differential Revision: https://reviews.llvm.org/D137857
2022-11-15 20:07:35 +00: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