406 Commits

Author SHA1 Message Date
Adam Siemieniuk
9a767dce95
[mlir][bufferization] Drop equivalent buffer results - modify public functions option (#177589)
Adds an option to allow modification of public functions to the drop
equivalent buffer results API and the respective pass.
A new standalone test for the pass is also added.

https://github.com/llvm/llvm-project/pull/163001 modified the default
behavior by disallowing rewriting public function. This PR preserves the
new behavior and only adds an opt-in flag to reenable changing public
function.

The extra flag aligns dropping equivalent function results with another
bufferization API `promoteBufferResultsToOutParams` which also allows
opt-in public function rewriting.
2026-02-02 15:12:32 +01:00
Jakub Kuderski
9aaf0b89f5
[mlir] Apply clang-tidy check llvm-use-vector-utils. NFC. (#178526) 2026-01-29 02:19:00 +00:00
Prathamesh Tagore
39a9e659de
[mlir][bufferization] Cache SymbolTableCollection for CallOp types (#176909)
Use the BufferizationState symbol table cache when resolving CallOp
callee types in getBufferType(), avoiding repeated SymbolTableCollection
creation. Add a const accessor (backed by a mutable cache) so const
state can reuse the same tables. Completes a marked TODO.
2026-01-23 11:58:53 +01:00
Matthias Springer
f76433761a
[mlir][Interfaces] Split successor inputs from region successor (#175815)
This commit simplifies the design of the `RegionBranchOpInterface`. The
property of being a successor input is now independent of the region
branch point.

There is a new API for querying successor inputs:
`RegionBranchOpInterface::getSuccessorInputs(RegionSuccessor)`. Note
that this function does **not** take a `RegionBranchPoint` as parameter.

The `RegionSuccessor` API is now also simpler: it no longer stores
successor inputs. A region successor is simply `Region *`, wrapped
around a convenience API.

Note: This commit is mostly mechanical. Analyses / transformations that
build on top of the `RegionBranchOpInterface` (e.g.,
`visitNonControlFlowArguments` API) can likely be simplified in
follow-up commits.

Note for LLVM integration: Split
`RegionBranchOpInterface::getSuccessorRegion` implementations into two
functions: `getSuccessorRegion` and `getSuccessorInputs. (There are many
examples in this commit.)

RFC:
https://discourse.llvm.org/t/rfc-simplify-regionbranchopinterface-separate-successor-inputs-from-region-successor/89420/7
2026-01-16 10:16:53 +01:00
Matthias Springer
5f3b40ec7a
[mlir][Interfaces][NFC] Simplify and align RegionSuccessor design / API (#174945)
Simplify the design of `RegionSuccessor`. There is no need to store the
`Operation *` pointer when branching out of the region branch op (to the
parent). There is no API to even access the `Operation *` pointer.

Add a new helper function `RegionSuccessor::parent` to construct a
region successor that points to the parent. This aligns the
`RegionSuccessor` design and API with `RegionBranchPoint`:
* Both classes now have a `parent()` helper function.
`ClassName::parent()` can be used in documentation to precisely describe
the source/target of a region branch.
* Both classes now use `nullptr` internally to represent "parent".

This API change also protects against incorrect API usage: users can no
longer pass an incorrect parent op. If a region successor is not a
region of the region branch op, it *must* branch out of region branch op
itself ("parent"). However, the previous API allowed passing other
operations. There was one such API violation in a [test
case](https://github.com/llvm/llvm-project/pull/174945/files#diff-d5717e4a8d7344b2ff77762b8fa480bcfec0eeee97a86195c787d791a6217e13L71).

Also clean up the documentation to use the correct terminology (such as
"successor operands", "successor inputs") consistently.

Note: This PR effectively rolls back some changes from #161575. That PR
introduced `llvm::PointerUnion<Region *, Operation *>
successor{nullptr};`. It is unclear from the commit message why that
change was made.

Note for LLVM integration: You may have to slightly modify
`getSuccessorRegion` implementations: Replace
`RegionSuccessor(getOperation(), getOperation()->getResults())` with
`RegionSuccessor::parent(getResults())`.
2026-01-14 10:57:22 +01:00
Matthias Springer
0b24580a26
[mlir][Interfaces][NFC] Add RegionBranchOpInterface helper for forwarded values (#173981)
Add a helper function to compute a mapping of successor operands to
successor inputs. This mapping is computed in various places. Also add a
helper function to gather all region branch points.

This commit is in preparation of a bug fix / partial redesign of
`-remove-dead-values`. This commit also removes some duplicate code in
various places.
2026-01-01 11:56:05 +01:00
Suriyaa MM
d5d49b8d73
[mlir][bufferization] Return early in aliasing analysis (#173529)
Fix for [mlir-opt crashes in OneShotModuleBufferize.cpp:139
#173371](https://github.com/llvm/llvm-project/issues/173371#issue-3757290676).

It just returns `failure()` if there is no `func.return` op.
2025-12-26 12:12:05 +00:00
Quinn Dawkins
bb17dfa7d1
[mlir][bufferization] Enable moving dependent values in eliminate-empty-tensors (#169718)
Currently empty tensor elimination by constructing a SubsetExtractionOp
to match a SubsetInsertionOp at the end of a DPS chain will fail if any
operands required by the insertion op don't dominate the insertion point
for the extraction op.

This change improves the transformation by attempting to move all pure
producers of required operands to the insertion point of the extraction
op. In the process this improves a number of tests for empty tensor
elimination.
2025-12-05 14:40:08 -05:00
Kazu Hirata
edbf9e4c30
[mlir] Remove a redundant cast (NFC) (#168241)
llvm::all_of already returns bool.

Identified with readability-redundant-casting.
2025-11-15 15:00:54 -08:00
Veera
996639d6eb
[MLIR][BufferResultsToOutParamsPass] Add Option to Modify Public Function's Signature (#167248)
Since https://github.com/llvm/llvm-project/pull/162441,
`buffer-results-to-out-params` transforms `private` functions only.

But, as mentioned in
https://github.com/llvm/llvm-project/pull/162441#issuecomment-3404195242,
this is a breaking change for pipelines handling C code. Our pipeline
@EfficientComputer is also affected by this breaking change.

Therefore, this PR adds an opt-in flag to allow `public` functions to be
transformed by `BufferResultsToOutParamsPass`.
2025-11-09 21:08:22 -08:00
lonely eagle
3d42b48d5d
[mlir][bufferize] Use resolveCallableInTable to cleanup getCalledFunction (NFC) (#165658)
Simplify the implementation of `getCalledFunction` using
`resolveCallableInTable`.
2025-10-31 03:07:21 +08:00
lonely eagle
2dca1881e0
[mlir][bufferize] Use the flag of skipRegions to print op (NFC) (#165516) 2025-10-30 02:03:10 +08:00
Mehdi Amini
41f65666f6
[MLIR] Revamp RegionBranchOpInterface (#165429)
This is still somehow a WIP, we have some issues with this interface
that are not trivial to solve. This patch tries to make the concepts of
RegionBranchPoint and RegionSuccessor more robust and aligned with their
definition:
- A `RegionBranchPoint` is either the parent (`RegionBranchOpInterface`)
op or a `RegionBranchTerminatorOpInterface` operation in a nested
region.
- A `RegionSuccessor` is either one of the nested region or the parent
`RegionBranchOpInterface`

Some new methods with reasonnable default implementation are added to
help resolving the flow of values across the RegionBranchOpInterface.

It is still not trivial in the current state to walk the def-use chain
backward with this interface. For example when you have the 3rd block
argument in the entry block of a for-loop, finding the matching operands
requires to know about the hidden loop iterator block argument and where
the iterargs start. The API is designed around forward-tracking of the
chain unfortunately.

Try to reland #161575 ; I suspect a buildbot incremental build issue.
2025-10-28 09:53:56 -07:00
Mehdi Amini
e3c547179f
Revert " [MLIR] Revamp RegionBranchOpInterface " (#165356)
Reverts llvm/llvm-project#161575

Broke Windows on ARM buildbot build, needs investigations.
2025-10-28 01:06:14 -07:00
Mehdi Amini
ab1fd21b54
[MLIR] Revamp RegionBranchOpInterface (#161575)
This is still somehow a WIP, we have some issues with this interface
that are not trivial to solve. This patch tries to make the concepts of
RegionBranchPoint and RegionSuccessor more robust and aligned with their
definition:
- A `RegionBranchPoint` is either the parent (`RegionBranchOpInterface`)
op or a `RegionBranchTerminatorOpInterface` operation in a nested
region.
- A `RegionSuccessor` is either one of the nested region or the parent
`RegionBranchOpInterface`

Some new methods with reasonnable default implementation are added to
help resolving the flow of values across the RegionBranchOpInterface.

It is still not trivial in the current state to walk the def-use chain
backward with this interface. For example when you have the 3rd block
argument in the entry block of a for-loop, finding the matching operands
requires to know about the hidden loop iterator block argument and where
the iterargs start. The API is designed around forward-tracking of the
chain unfortunately.
2025-10-28 07:47:26 +00:00
lonely eagle
d43b06709c
[mlir][bufferize] Cleanup TensorCopyInsertion.cpp (NFC) (#164541) 2025-10-23 21:41:19 +08:00
lonely eagle
50d65a5675
[mlir][bufferize] Make drop-equivalent-buffer-results support mult blocks (#163388)
Enable Make drop-equivalent-buffer-results to handle return ops in
multiple blocks within a function.
2025-10-17 17:51:40 +08:00
lonely eagle
3f99d2fc9a
[mlir][bufferize] Make drop-equivalent-buffer-results only support functions that are neither public nor extern (#163001)
The callers of public or extern functions are unknown, so their function
signatures cannot be changed.
2025-10-14 18:27:30 +08:00
lonely eagle
5a05fa1f7d
[mlir][bufferize] Delete getCalledFunction in drop-equivalent-buffer-results pass (NFC) (#162432)
Use resolveCallable replace getCalledFunction.
2025-10-11 16:12:27 +08:00
lonely eagle
71586a6a73
[mlir][bufferize] Make buffer-results-to-out-params support only functions that are neither public nor extern (#162441)
The callers of public or extern functions are unknown, so their function
signatures cannot be changed.
2025-10-08 16:54:02 +08:00
lonely eagle
1087c1079f
[mlir][bufferize] Add hoist-dynamic-allocs-option to buffer-results-to-out-params (#160985)
Add hoist-dynamic-allocs-option to buffer-results-to-out-params. This PR
supported that obtain the size of the dynamic shape memref through the
caller-callee relationship.
2025-10-06 17:05:21 +08:00
Andrei Golubev
ff4c4997ee
[mlir][bufferization] Support custom types at function boundaries (#159766)
Support custom types (3/N): allow custom tensor and buffer types in
function signatures and at call-sites. This is one of the major building
blocks to move in the direction of module-level one-shot-bufferization
support.

To achieve this, `BufferizationOptions::FunctionArgTypeConverterFn`
callback is converted to work with tensor-like and buffer-like types,
instead of the builtin counterparts. The default behavior for builtins
remains unchanged, while custom types by default go through
`TensorLikeType::getBufferType()` which is a general conversion
interface.
2025-09-24 13:09:27 +02:00
Mehdi Amini
e46942ac81 [MLIR] Apply clang-tidy fixes for llvm-qualified-auto in OptimizeAllocationLiveness.cpp (NFC) 2025-09-06 01:20:33 -07:00
donald chen
5af7263d42
[mlir] add getViewDest method to viewLikeOpInterface (#154524)
The viewLikeOpInterface abstracts the behavior of an operation view one
buffer as another. However, the current interface only includes a
"getViewSource" method and lacks a "getViewDest" method.

Previously, it was generally assumed that viewLikeOpInterface operations
would have only one return value, which was the view dest. This
assumption was broken by memref.extract_strided_metadata, and more
operations may break these silent conventions in the future. Calling
"viewLikeInterface->getResult(0)" may lead to a core dump at runtime.
Therefore, we need 'getViewDest' method to standardize our behavior.

This patch adds the getViewDest function to viewLikeOpInterface and
modifies the usage points of viewLikeOpInterface to standardize its use.
2025-08-21 20:09:52 +08:00
Mehdi Amini
5683baea6d
[MLIR] Adopt LDBG() debug macro in bufferization (NFC) (#154614) 2025-08-20 21:14:02 +00:00
Matthias Springer
0499d3a8cf
[mlir][Interfaces] Add hasUnknownEffects helper function (#154523)
I have seen misuse of the `hasEffect` API in downstream projects: users
sometimes think that `hasEffect == false` indicates that the operation
does not have a certain memory effect. That's not necessarily the case.
When the op does not implement the `MemoryEffectsOpInterface`, it is
unknown whether it has the specified effect. "false" can also mean
"maybe".

This commit clarifies the semantics in the documentation. Also adds
`hasUnknownEffects` and `mightHaveEffect` convenience functions. Also
simplifies a few call sites.
2025-08-20 15:24:53 +00:00
Evan Liu
e654d4e8fd
[mlir] Generalize OneShotModuleBufferize to operate on any Operation (#148327)
As part of 2646c36a864aa6a62bc1280e9a8cd2bcd2695349,
`OneShotModuleBufferize` no longer descends into nested symbol tables,
recommending users who wish to do this should do so in a pass
pipeline/custom pass. This did not support the use case of ops that
weren't ModuleOps. The patch updates `OneShotModuleBufferize` to work on
any general op.
2025-07-28 19:29:18 -07:00
Maksim Levental
c090ed53fb
[mlir][NFC] update mlir/Dialect create APIs (33/n) (#150659)
See https://github.com/llvm/llvm-project/pull/147168 for more info.
2025-07-25 16:13:55 -04:00
Jacques Pienaar
07967d4af8
[mlir] Switch to new LDBG macro (#150616)
Change local variants to use new central one.
2025-07-25 18:22:46 +02:00
Maksim Levental
2f5312563f
[mlir][NFC] update mlir/Dialect create APIs (15/n) (#149921)
See https://github.com/llvm/llvm-project/pull/147168 for more info.
2025-07-24 15:34:56 -05:00
Kazu Hirata
0925d7572a
[mlir] Remove unused includes (NFC) (#150266)
These are identified by misc-include-cleaner.  I've filtered out those
that break builds.  Also, I'm staying away from llvm-config.h,
config.h, and Compiler.h, which likely cause platform- or
compiler-specific build failures.
2025-07-23 15:18:53 -07:00
Kazu Hirata
57d2d89241
[mlir] Remove unused includes (NFC) (#147549)
These are identified by misc-include-cleaner.  I've filtered out those
that break builds.  Also, I'm staying away from llvm-config.h,
config.h, and Compiler.h, which likely cause platform- or
compiler-specific build failures.
2025-07-08 12:47:30 -07:00
Jakub Kuderski
6512ca7ddb
[mlir] Add isStatic* size check for ShapedTypes. NFCI. (#147085)
The motivation is to avoid having to negate `isDynamic*` checks, avoid
double negations, and allow for `ShapedType::isStaticDim` to be used in
ADT functions without having to wrap it in a lambda performing the
negation.

Also add the new functions to C and Python bindings.
2025-07-07 14:57:27 -04:00
Andrei Golubev
a63f572628
[mlir][bufferization] Return BufferLikeType in BufferizableOpInterface (#144867)
Support custom types (2/N): allow value-owning operations (e.g.
allocation ops) to bufferize custom tensors into custom buffers. This
requires BufferizableOpInterface::getBufferType() to return
BufferLikeType instead of BaseMemRefType.

Affected implementors of the interface are updated accordingly.

Relates to ee070d08163ac09842d9bf0c1315f311df39faf1.
2025-07-02 11:27:35 -07:00
Kazu Hirata
dec93ae454
[mlir] Migrate away from ValueRange(std::nullopt) (NFC) (#145210)
ArrayRef has a constructor that accepts std::nullopt.  This
constructor dates back to the days when we still had llvm::Optional.

Since the use of std::nullopt outside the context of std::optional is
kind of abuse and not intuitive to new comers, I would like to move
away from the constructor and eventually remove it.

One of the common uses of std::nullopt is in one of the constructors
for ValueRange.  This patch takes care of the migration where we need
ValueRange() to facilitate perfect forwarding.  Note that {} would be
ambiguous for perfecting forwarding to work.
2025-06-22 06:30:17 -07:00
Andrei Golubev
ee070d0816
[mlir][bufferization] Support custom types (1/N) (#142986)
Following the addition of TensorLike and BufferLike type interfaces (see
00eaff3e9c897c263a879416d0f151d7ca7eeaff), introduce minimal changes
required to bufferize a custom tensor operation into a custom buffer
operation.

To achieve this, new interface methods are added to TensorLike type
interface that abstract away the differences between existing (tensor ->
memref) and custom conversions.

The scope of the changes is intentionally limited (for example,
BufferizableOpInterface is untouched) in order to first understand the
basics and reach consensus design-wise.

---
Notable changes:
* mlir::bufferization::getBufferType() returns BufferLikeType (instead
of BaseMemRefType)
* ToTensorOp / ToBufferOp operate on TensorLikeType / BufferLikeType.
Operation argument "memref" renamed to "buffer"
* ToTensorOp's tensor type inferring builder is dropped (users now need
to provide the tensor type explicitly)
2025-06-18 16:18:12 +02:00
Andrei Golubev
a1c2a71293
[mlir][bufferization] Use Type instead of Value in unknown conversion (#144658)
Generally, bufferization should be able to create a memref from a tensor
without needing to know more than just a mlir::Type. Thus, change
BufferizationOptions::UnknownTypeConverterFn to accept just a type
(mlir::TensorType for now) instead of mlir::Value. Additionally, apply
the same rationale to getMemRefType() helper function.

Both changes are prerequisites to enable custom types support in
one-shot bufferization.
2025-06-18 14:38:58 +02:00
Michele Scuttari
f849866fc5
[MLIR] Reduce complexity of searching circular function calls in bufferization (#142099)
The current algorithm searching for circular function calls scales quadratically due to the linear scan of the functions vector that is performed for each element of the vector itself. The PR replaces such algorithm with an O(V + E) version based on the Khan's algorithm for topological sorting, where V is the number of functions and E is the number of function calls.
2025-06-06 10:35:58 +02:00
Michele Scuttari
aaec9e5f5b
[MLIR] Keep cached symbol tables across buffer deallocation insertions (#141956)
The `DeallocationState` class has been modified to keep a reference to an externally owned `SymbolTableCollection` class, to preserve the cached symbol tables across multiple insertions of deallocation instructions.
2025-06-06 07:22:35 +02:00
Michele Scuttari
9289604cf6
[MLIR] Use cached symbol tables in getFuncOpsOrderedByCalls (#141967)
Address TODO regarding the recomputation of symbol tables. The signature of the `getFuncOpsOrderedByCalls` function is modified to receive the collection of cached symbol tables.
2025-06-03 11:29:02 +02:00
Michele Scuttari
63cb6af782
[MLIR] Add bufferization state to getBufferType and resolveConflicts interface methods (#141466)
The PR continues the work started in #141019 by adding the `BufferizationState` class also to the `getBufferType` and `resolveConflicts` interface methods, together with the additional support functions that are used throughout the bufferization infrastructure.
2025-05-28 10:35:23 +02:00
Michele Scuttari
03f4fe1397
[MLIR] Use cached symbol tables to get the called function during bufferization (#141341)
Avoid recomputing the symbol tables by using the `BufferizationState` class introduced in #141019.
There is also one similar TODO remaining within the `getBufferType` function, but that requires more reasoning and one more API change.
2025-05-26 08:57:43 +02:00
Michele Scuttari
61d5fdf50c
[MLIR] Add bufferization state class to OneShotBufferization pass (#141019)
Follow-up on #138143, which was reverted due to a missing update a method signature (more specifically, the bufferization interface for `tensor::ConcatOp`) that was not catched before merging. The old PR description is reported in the next lines.

This PR is a follow-up on https://github.com/llvm/llvm-project/pull/138125, and adds a bufferization state class providing information about the IR. The information currently consists of a cached list of symbol tables, which aims to solve the quadratic scaling of the bufferization task with respect to the number of symbols. The PR breaks API compatibility: the bufferize method of the BufferizableOpInterface has been enriched with a reference to a BufferizationState object.

The bufferization state must be kept in a valid state by the interface implementations. For example, if an operation with the Symbol trait is inserted or replaced, its parent SymbolTable must be updated accordingly (see, for example, the bufferization of arith::ConstantOp, where the symbol table of the module gets the new global symbol inserted). Similarly, the invalidation of a symbol table must be performed if an operation with the SymbolTable trait is removed (this can be performed using the invalidateSymbolTable method, introduced in https://github.com/llvm/llvm-project/pull/138014).
2025-05-23 09:21:35 +02:00
Michele Scuttari
72a8893689
Revert "[MLIR] Add bufferization state class to OneShotBufferization pass" (#141012)
Reverts llvm/llvm-project#138143

The PR for the BufferizationState is temporarily reverted due to API incompatibilities that have been initially missed during the update and were not catched by PR checks.
2025-05-22 09:25:07 +02:00
Michele Scuttari
67fc1660d9
[MLIR] Add bufferization state class to OneShotBufferization pass (#138143)
This PR is a follow-up on #138125, and adds a bufferization state class providing information about the IR. The information currently consists of a cached list of symbol tables, which aims to solve the quadratic scaling of the bufferization task with respect to the number of symbols. The PR breaks API compatibility: the `bufferize` method of the `BufferizableOpInterface` has been enriched with a reference to a `BufferizationState` object.

The bufferization state must be kept in a valid state by the interface implementations. For example, if an operation with the `Symbol` trait is inserted or replaced, its parent `SymbolTable` must be updated accordingly (see, for example, the bufferization of `arith::ConstantOp`, where the symbol table of the module gets the new global symbol inserted). Similarly, the invalidation of a symbol table must be performed if an operation with the `SymbolTable` trait is removed (this can be performed using the `invalidateSymbolTable` method, introduced in #138014).
2025-05-22 08:53:38 +02:00
Andrei Golubev
8f91b108df
[mlir][bufferization][NFC] Rename to_memref to to_buffer (#137180)
As part of the work on transitioning bufferization dialect, ops, and
associated logic to operate on newly added type interfaces (see
00eaff3e9c897c263a879416d0f151d7ca7eeaff), rename the
bufferization.to_memref to highlight the generic nature of the op.

Bufferization process produces buffers while memref is a builtin type
rather than a generic term.

Preserve the current API (to_buffer still produces a memref), however,
as the new type interfaces are not used yet.
2025-05-14 11:17:09 +02:00
Michele Scuttari
0bda492ba1
[MLIR] Cache symbol tables during OneShotBufferization analyses (#138125)
During bufferization, the callee of each `func::CallOp` / `CallableOpInterface` operation is retrieved by means of a symbol table that is temporarily built for the lookup purpose. The creation of the symbol table requires a linear scan of the operation body (e.g., a linear scan of the `ModuleOp` body). Considering that functions are typically called at least once, this leads to a scaling behavior that is quadratic with respect to the number of symbols. The problem is described in the following Discourse topic: https://discourse.llvm.org/t/quadratic-scaling-of-bufferization/86122/
This patch aims to partially address this scaling issue by leveraging the `SymbolTableCollection` class, whose instance is added to the `FuncAnalysisState` extension. Later modifications are also expected to address the problem in other methods required by `BufferizableOpInterface` (e.g., `bufferize` and `getBufferType`), which suffer of the same problem but do not provide access to any bufferization state.
2025-05-14 09:39:11 +02:00
Krzysztof Drewniak
6fc092fc41
[mlir][bufferization] Let bufferization.tensor_layout be any layout attr (#138567)
The bufferization.tensor_layout is unnecessarily restricted to affine
map attributes when it could reasonably be any implementor of
MemRefLayoutAttrInterface.
2025-05-06 11:21:52 -05:00
Oleksandr "Alex" Zinenko
7318074168
[mlir] allow function type cloning to fail (#137130)
`FunctionOpInterface` assumed the fact that the function type (attribute
of the operation) can be cloned with arbirary lists of function
arguments and results to support argument and result list mutation. This
is not always correct, in particular, LLVM dialect functions require
exactly one result making it impossible to erase the result.

Allow function type cloning to fail and propagate this failure through
various APIs that use it. The common assumption is that existing IR has
not been modified.

Fixes #131142.

Reland a8c7ecdcbc3e89b493b495c6831cc93671c3b844 / #136300.
2025-04-30 09:26:42 +02:00
Oleksandr "Alex" Zinenko
0c61b24337
[mlir] add a fluent API to GreedyRewriterConfig (#137122)
This is similar to other configuration objects used across MLIR.

Rename some fields to better reflect that they are no longer booleans.

Reland 04d261101b4f229189463136a794e3e362a793af / #132253.
2025-04-24 09:51:42 +02:00