summaryrefslogtreecommitdiff
path: root/mlir/lib/Transforms/Utils/FoldUtils.cpp
AgeCommit message (Collapse)Author
2025-09-27[MLIR] Improve in-place folding to iterate until fixed-point (#160615)Mehdi Amini
When executed in the context of canonicalization, the folders are invoked in a fixed-point iterative process. However in the context of an API like `createOrFold()` or in DialectConversion for example, we expect a "one-shot" call to fold to be as "folded" as possible. However, even when folders themselves are indempotent, folders on a given operation interact with each other. For example: ``` // X = 0 + Y %X = arith.addi %c_0, %Y : i32 ``` should fold to %Y, but the process actually involves first the folder provided by the IsCommutative trait to move the constant to the right. However this happens after attempting to fold the operation and the operation folder isn't attempt again after applying the trait folder. This commit makes sure we iterate until fixed point on folder applications. Fixes #159844
2025-08-05Avoid unnecessary erasing of constant Locs (#151573)Majid Dadashi
Do not erase location info when moving an op within the same block. Since #75415 , the FoldUtils.cpp erases the location information when moving an operation. This was being done even when an operation was moved to the front of a block it was already in. In TFLite, this location information is used to provide meaningful names for tensors, which aids in debugging and mapping compiled tensors back to their original layers. The aggressive erasure of location info caused many tensors in TFLite models to receive generic names (e.g., tfl.pseudo_qconst), making the models harder to inspect. This change modifies the logic to preserve the location of an operation when it is moved within the same block. The location is now only erased when the operation is moved from a different block entirely. This ensures that most tensor names are preserved, improving the debugging experience for TFLite models.
2025-01-11[mlir] Migrate away from PointerUnion::{is,get} (NFC) (#122591)Kazu Hirata
Note that PointerUnion::{is,get} have been soft deprecated in PointerUnion.h: // FIXME: Replace the uses of is(), get() and dyn_cast() with // isa<T>, cast<T> and the llvm::dyn_cast<T> I'm not touching PointerUnion::dyn_cast for now because it's a bit complicated; we could blindly migrate it to dyn_cast_if_present, but we should probably use dyn_cast when the operand is known to be non-null.
2024-11-08[mlir][IR][NFC] Cleanup insertion point API usage (#115415)Matthias Springer
Use `setInsertionPointToStart` / `setInsertionPointToEnd` when possible.
2023-12-21[MLIR] Erase location of folded constants (#75415)Billy Zhu
Follow up to the discussion from #75258, and serves as an alternate solution for #74670. Set the location to Unknown for deduplicated / moved / materialized constants by OperationFolder. This makes sure that the folded constants don't end up with an arbitrary location of one of the original ops that became it, and that hoisted ops don't confuse the stepping order.
2023-12-20[mlir] Require folders to produce Values of same type (#75887)Matthias Springer
This commit adds extra assertions to `OperationFolder` and `OpBuilder` to ensure that the types of the folded SSA values match with the result types of the op. There used to be checks that discard the folded results if the types do not match. This commit makes these checks stricter and turns them into assertions. Discarding folded results with the wrong type (without failing explicitly) can hide bugs in op folders. Two such bugs became apparent in MLIR (and some more in downstream projects) and are fixed with this change. Note: The existing type checks were introduced in https://reviews.llvm.org/D95991. Migration guide: If you see failing assertions (`folder produced value of incorrect type`; make sure to run with assertions enabled!), run with `-debug` or dump the operation right before the failing assertion. This will point you to the op that has the broken folder. A common mistake is a mismatch between static/dynamic dimensions (e.g., input has a static dimension but folded result has a dynamic dimension).
2023-12-13Revert "[MLIR] Fuse locations of merged constants (#74670)"Fangrui Song
This reverts commit 87e2e89019ec4405fa47c3b4585be4e67473b590. and its follow-ups 0d1490f09f23bf204b714c3c6ba5e0aaf4eeed9a (#75218) and 6fe3cd54670cae52dae92a38a6d28f450fe8f321 (#75312). We observed significant OOM/timeout issues due to #74670 to quite a few services including google-research/swirl-lm. The follow-up #75218 and #75312 do not address the issue. Perhaps this is worth more investigation.
2023-12-13[MLIR][NFC] Add fast path to fused loc flattening. (#75312)Benjamin Chetioui
This is a follow-up on [PR 75218](https://github.com/llvm/llvm-project/pull/75218) that avoids reconstructing a fused loc in the `FlattenFusedLocationRecursively` helper when there has been no change.
2023-12-12[MLIR] Flatten fused locations when merging constants. (#75218)Benjamin Chetioui
[PR 74670](https://github.com/llvm/llvm-project/pull/74670) added support for merging locations at constant folding time. We have discovered that in some cases, the number of locations grows so big as to cause a compilation process to OOM. In that case, many of the locations end up appearing several times in nested fused locations. We add here a helper that always flattens fused locations in order to eliminate duplicates in the case of nested fused locations.
2023-12-11[MLIR] Fuse locations of merged constants (#74670)Billy Zhu
When merging constants by the operation folder, the location of the op that remains should be updated to track the new meaning of this op. This way we do not lose track of all possible source locations that the constant op came from, and the final location of the op is less reliant on the order of folding. This will also help debuggers understand how to step these instructions. This PR introduces a helper for operation folder to fuse another location into the location of an op. When an op is deduplicated, fuse the location of the op to be removed into the op that is retained. The retained op now represents both original ops. The FusedLoc will have a string metadata to help understand the reason for the location fusion (motivated by the [example](https://github.com/llvm/llvm-project/blob/71be8f3c23497e28c86f1135f564b16106d8d6fb/mlir/include/mlir/IR/BuiltinLocationAttributes.td#L130) in the docstring of FusedLoc).
2023-07-20[mlir] Remove some code duplication between `Builders.cpp` and `FoldUtils.cpp`Matthias Springer
Also update the documentation of `Operation::fold`, which did not take into account in-place foldings. Differential Revision: https://reviews.llvm.org/D155691
2023-07-20[mlir][IR] Implement proper folder for `IsCommutative` traitMatthias Springer
Commutative ops were previously folded with a special rule in `OperationFolder`. This change turns the folding into a proper `OpTrait` folder. Differential Revision: https://reviews.llvm.org/D155687
2023-05-26[mlir] Move casting calls from methods to function callsTres Popp
The MLIR classes Type/Attribute/Operation/Op/Value support cast/dyn_cast/isa/dyn_cast_or_null functionality through llvm's doCast functionality in addition to defining methods with the same name. This change begins the migration of uses of the method to the corresponding function call as has been decided as more consistent. Note that there still exist classes that only define methods directly, such as AffineExpr, and this does not include work currently to support a functional cast/isa call. Context: - https://mlir.llvm.org/deprecation/ at "Use the free function variants for dyn_cast/cast/isa/…" - Original discussion at https://discourse.llvm.org/t/preferred-casting-style-going-forward/68443 Implementation: This patch updates all remaining uses of the deprecated functionality in mlir/. This was done with clang-tidy as described below and further modifications to GPUBase.td and OpenMPOpsInterfaces.td. Steps are described per line, as comments are removed by git: 0. Retrieve the change from the following to build clang-tidy with an additional check: main...tpopp:llvm-project:tidy-cast-check 1. Build clang-tidy 2. Run clang-tidy over your entire codebase while disabling all checks and enabling the one relevant one. Run on all header files also. 3. Delete .inc files that were also modified, so the next build rebuilds them to a pure state. ``` ninja -C $BUILD_DIR clang-tidy run-clang-tidy -clang-tidy-binary=$BUILD_DIR/bin/clang-tidy -checks='-*,misc-cast-functions'\ -header-filter=mlir/ mlir/* -fix rm -rf $BUILD_DIR/tools/mlir/**/*.inc ``` Differential Revision: https://reviews.llvm.org/D151542
2023-03-22[mlir][Transforms][NFC] Improve builder/listener API of OperationFolderMatthias Springer
The constructor of `OperationFolder` takes a listener. Therefore, the remaining API should not take any builder/rewriters. This could lead to double notifications in case a listener is attached to the builder/rewriter. As an internal cleanup, `OperationFolder` now has an `IRRewriter` instead of a `RewriterBase::Listener`. In most cases, `OperationFolder` no longer has to notify/deal with listeners. This is done by the rewriter. Differential Revision: https://reviews.llvm.org/D146134
2023-02-23[mlir][IR] Use Listener for IR callbacks in OperationFolderMatthias Springer
Remove the IR modification callbacks from `OperationFolder`. Instead, an optional `RewriterBase::Listener` can be specified. * `processGeneratedConstants` => `notifyOperationCreated` * `preReplaceAction` => `notifyOperationReplaced` This simplifies the GreedyPatternRewriterDriver because we no longer need special handling for IR modifications due to op folding. A folded operation is now enqueued on the GreedyPatternRewriteDriver's worklist if it was modified in-place. (There may be new patterns that apply after folding.) Also fixes a bug in `TestOpInPlaceFold::fold`. The folder could previously be applied over and over and did not return a "null" OpFoldResult if the IR was not modified. (This is similar to a pattern that returns `success` without modifying IR; it can trigger an infinite loop in the GreedyPatternRewriteDriver.) Differential Revision: https://reviews.llvm.org/D144463
2022-04-07Reland [GreedPatternRewriter] Preprocess constants while building worklist ↵River Riddle
when not processing top down Reland Note: Adds a fix to properly mark a commutative operation as folded if we change the order of its operands. This was uncovered by the fact that we no longer re-process constants. This avoids accidentally reversing the order of constants during successive application, e.g. when running the canonicalizer. This helps reduce the number of iterations, and also avoids unnecessary changes to input IR. Fixes #51892 Differential Revision: https://reviews.llvm.org/D122692
2022-04-01Revert "[GreedPatternRewriter] Preprocess constants while building worklist ↵Mehdi Amini
when not processing top down" This reverts commit 59bbc7a0851b6e0054bb3ed47df0958822f08880. This exposes an issue breaking the contract of `applyPatternsAndFoldGreedily` where we "converge" without applying remaining patterns.
2022-03-31[GreedPatternRewriter] Preprocess constants while building worklist when not ↵River Riddle
processing top down This avoids accidentally reversing the order of constants during successive application, e.g. when running the canonicalizer. This helps reduce the number of iterations, and also avoids unnecessary changes to input IR. Fixes #51892 Differential Revision: https://reviews.llvm.org/D122692
2021-12-20Fix clang-tidy issues in mlir/ (NFC)Mehdi Amini
Reviewed By: ftynse Differential Revision: https://reviews.llvm.org/D115956
2021-10-13[MLIR] Replace std ops with arith dialect opsMogball
Precursor: https://reviews.llvm.org/D110200 Removed redundant ops from the standard dialect that were moved to the `arith` or `math` dialects. Renamed all instances of operations in the codebase and in tests. Reviewed By: rriddle, jpienaar Differential Revision: https://reviews.llvm.org/D110797
2021-09-08[Canonicalize] Don't call isBeforeInBlock in OperationFolder::tryToFold.Chris Lattner
This patch (e4635e6328c8) fixed a bug where a newly generated/reused constant wouldn't dominate a folded operation. It did so by calling isBeforeInBlock to move the constant around on demand. This introduced a significant compile time regression, because "isBeforeInBlock" is O(n) in the size of a block the first time it is called, and the cache is invalidated any time canonicalize changes something big in the block. This fixes LLVM PR51738 and this CIRCT issue: https://github.com/llvm/circt/issues/1700 This does affect the order of constants left in the top of a block, I staged in the testsuite changes in rG42431b8207a5. Differential Revision: https://reviews.llvm.org/D109454
2021-08-23[mlir][FoldUtils] Ensure the created constant dominates the replaced opRiver Riddle
This revision fixes a bug where an operation would get replaced with a pre-existing constant that didn't dominate it. This can occur when a pattern inserts operations to be folded at the beginning of the constants insertion block. This revision fixes the bug by moving the existing constant before the replaced operation in such cases. This is fine because if a constant didn't already exist, a new one would have been inserted before this operation anyways. Differential Revision: https://reviews.llvm.org/D108498
2021-05-24[GreedyPatternRewriter] Introduce a config object that allows controlling ↵Chris Lattner
internal parameters. NFC. This exposes the iterations and top-down processing as flags, and also allows controlling whether region simplification is desirable for a client. This allows deleting some duplicated entrypoints to applyPatternsAndFoldGreedily. This also deletes the Constant Preprocessing pass, which isn't worth it on balance. All defaults are all kept the same, so no one should see a behavior change. Differential Revision: https://reviews.llvm.org/D102988
2021-05-17Merge with mainline.Chris Lattner
Differential Revision: https://reviews.llvm.org/D102636
2021-03-25Revert "[Canonicalizer] Process regions top-down instead of bottom up & ↵Uday Bondhugula
reuse existing constants." This reverts commit 361b7d125b438cda13fa45f13790767a62252be9 by Chris Lattner <clattner@nondot.org> dated Fri Mar 19 21:22:15 2021 -0700. The change to the greedy rewriter driver picking a different order was made without adequate analysis of the trade-offs and experimentation. A change like this has far reaching consequences on transformation pipelines, and a major impact upstream and downstream. For eg., one can’t be sure that it doesn’t slow down a large number of cases by small amounts or create other issues. More discussion here: https://llvm.discourse.group/t/speeding-up-canonicalize/3015/25 Reverting this so that improvements to the traversal order can be made on a clean slate, in bigger steps, and higher bar. Differential Revision: https://reviews.llvm.org/D99329
2021-03-20[Canonicalizer] Process regions top-down instead of bottom up & reuse ↵Chris Lattner
existing constants. This reapplies b5d9a3c / https://reviews.llvm.org/D98609 with a one line fix in processExistingConstants to skip() when erasing a constant we've already seen. Original commit message: 1) Change the canonicalizer to walk the function in top-down order instead of bottom-up order. This composes well with the "top down" nature of constant folding and simplification, reducing iterations and re-evaluation of ops in simple cases. 2) Explicitly enter existing constants into the OperationFolder table before canonicalizing. Previously we would "constant fold" them and rematerialize them, wastefully recreating a bunch fo constants, which lead to pointless memory traffic. Both changes together provide a 33% speedup for canonicalize on some mid-size CIRCT examples. One artifact of this change is that the constants generated in normal pattern application get inserted at the top of the function as the patterns are applied. Because of this, we get "inverted" constants more often, which is an aethetic change to the IR but does permute some testcases. Differential Revision: https://reviews.llvm.org/D99006
2021-03-15Revert "[Canonicalizer] Process regions top-down instead of bottom up & ↵Alex Zinenko
reuse existing constants." This reverts commit b5d9a3c92358349d5444ab28de8ab5b2bee33a01. The commit introduced a memory error in canonicalization/operation walking that is exposed when compiled with ASAN. It leads to crashes in some "release" configurations.
2021-03-14[m_Constant] Check #operands/results before hasTrait()Chris Lattner
We know that all ConstantLike operations have one result and no operands, so check this first before doing the trait check. This change speeds up Canonicalize on a CIRCT testcase by ~5%. Differential Revision: https://reviews.llvm.org/D98615
2021-03-14[Canonicalizer] Process regions top-down instead of bottom up & reuse ↵Chris Lattner
existing constants. Two changes: 1) Change the canonicalizer to walk the function in top-down order instead of bottom-up order. This composes well with the "top down" nature of constant folding and simplification, reducing iterations and re-evaluation of ops in simple cases. 2) Explicitly enter existing constants into the OperationFolder table before canonicalizing. Previously we would "constant fold" them and rematerialize them, wastefully recreating a bunch fo constants, which lead to pointless memory traffic. Both changes together provide a 33% speedup for canonicalize on some mid-size CIRCT examples. One artifact of this change is that the constants generated in normal pattern application get inserted at the top of the function as the patterns are applied. Because of this, we get "inverted" constants more often, which is an aethetic change to the IR but does permute some testcases. Differential Revision: https://reviews.llvm.org/D98609
2021-02-09[mlir][IR] Remove the concept of `OperationProperties`River Riddle
These properties were useful for a few things before traits had a better integration story, but don't really carry their weight well these days. Most of these properties are already checked via traits in most of the code. It is better to align the system around traits, and improve the performance/cost of traits in general. Differential Revision: https://reviews.llvm.org/D96088
2021-02-04Make the folder more robust against op fold() methods that generate a type ↵Mehdi Amini
mismatch We could extend this with an interface to allow dialect to perform a type conversion, but that would make the folder creating operation which isn't the case at the moment, and isn't necessarily always desirable. Reviewed By: rriddle Differential Revision: https://reviews.llvm.org/D95991
2021-01-08[mlir] NFC: fix trivial typosKazuaki Ishizaki
fix typo under include and lib directories Reviewed By: antiagainst Differential Revision: https://reviews.llvm.org/D94220
2020-12-11Revert "Revert "[mlir] Start splitting the `tensor` dialect out of `std`.""Sean Silva
This reverts commit 0d48d265db6633e4e575f81f9d3a52139b1dc5ca. This reapplies the following commit, with a fix for CAPI/ir.c: [mlir] Start splitting the `tensor` dialect out of `std`. This starts by moving `std.extract_element` to `tensor.extract` (this mirrors the naming of `vector.extract`). Curiously, `std.extract_element` supposedly works on vectors as well, and this patch removes that functionality. I would tend to do that in separate patch, but I couldn't find any downstream users relying on this, and the fact that we have `vector.extract` made it seem safe enough to lump in here. This also sets up the `tensor` dialect as a dependency of the `std` dialect, as some ops that currently live in `std` depend on `tensor.extract` via their canonicalization patterns. Part of RFC: https://llvm.discourse.group/t/rfc-split-the-tensor-dialect-from-std/2347/2 Differential Revision: https://reviews.llvm.org/D92991
2020-12-11Revert "[mlir] Start splitting the `tensor` dialect out of `std`."Sean Silva
This reverts commit cab8dda90f48e15ee94b0d55ceac5b6a812e4743. I mistakenly thought that CAPI/ir.c failure was unrelated to this change. Need to debug it.
2020-12-11[mlir] Start splitting the `tensor` dialect out of `std`.Sean Silva
This starts by moving `std.extract_element` to `tensor.extract` (this mirrors the naming of `vector.extract`). Curiously, `std.extract_element` supposedly works on vectors as well, and this patch removes that functionality. I would tend to do that in separate patch, but I couldn't find any downstream users relying on this, and the fact that we have `vector.extract` made it seem safe enough to lump in here. This also sets up the `tensor` dialect as a dependency of the `std` dialect, as some ops that currently live in `std` depend on `tensor.extract` via their canonicalization patterns. Part of RFC: https://llvm.discourse.group/t/rfc-split-the-tensor-dialect-from-std/2347/2 Differential Revision: https://reviews.llvm.org/D92991
2020-12-10[mlir] Remove the dependency on StandardOps from FoldUtilsRiver Riddle
OperationFolder currently uses ConstantOp as a backup when trying to materialize a constant after an operation is folded. This dependency isn't really useful or necessary given that dialects can/should provide a `materializeConstant` implementation. Fixes PR#44866 Differential Revision: https://reviews.llvm.org/D92980
2020-08-13Merge OpFolderDialectInterface with DialectFoldInterface (NFC)Mehdi Amini
Reviewed By: rriddle Differential Revision: https://reviews.llvm.org/D85823
2020-04-21[mlir][Transforms] Add pass to perform sparse conditional constant propagationRiver Riddle
This revision adds the initial pass for performing SCCP generically in MLIR. SCCP is an algorithm for propagating constants across control flow, and optimistically assumes all values to be constant unless proven otherwise. It currently supports branching control, with support for regions and inter-procedural propagation being added in followups. Differential Revision: https://reviews.llvm.org/D78397
2020-04-11[MLIR] Handle in-place folding properly in greedy pattern rewrite driverUday Bondhugula
OperatioFolder::tryToFold performs both true folding and in a few instances in-place updates through op rewrites. In the latter case, we should still be applying the supplied pattern rewrites in the same iteration; however this wasn't the case since tryToFold returned success() for both true folding and in-place updates, and the patterns for the in-place updated ops were being applied only in the next iteration of the driver's outer loop. This fix would make it converge faster. Differential Revision: https://reviews.llvm.org/D77485
2020-03-23[mlir] Fix unsafe create operation in GreedyPatternRewriterMaheshRavishankar
When trying to fold an operation during operation creation check that the operation folding succeeds before inserting the op. Differential Revision: https://reviews.llvm.org/D76415
2020-03-20[MLIR] Fix op folding to not run pre-replace when not constant foldingUday Bondhugula
OperationFolder::tryToFold was running the pre-replacement action even when there was no constant folding, i.e., when the operation was just being updated in place but was not going to be replaced. This led to nested ops being unnecessarily removed from the worklist and only being processed in the next outer iteration of the greedy pattern rewriter, which is also why this didn't affect the final output IR but only the convergence rate. It also led to an op's results' users to be unnecessarily added to the worklist. Signed-off-by: Uday Bondhugula <uday@polymagelabs.com> Differential Revision: https://reviews.llvm.org/D76268
2020-03-12[mlir][SideEffects] Replace HasNoSideEffect with the memory effect interfaces.River Riddle
HasNoSideEffect can now be implemented using the MemoryEffectInterface, removing the need to check multiple things for the same information. This also removes an easy foot-gun for users as 'Operation::hasNoSideEffect' would ignore operations that dynamically, or recursively, have no side effects. This also leads to an immediate improvement in some of the existing users, such as DCE, now that they have access to more information. Differential Revision: https://reviews.llvm.org/D76036
2020-03-12[mlir] Add a new `ConstantLike` trait to better identify operations that ↵River Riddle
represent a "constant". The current mechanism for identifying is a bit hacky and extremely adhoc, i.e. we explicit check 1-result, 0-operand, no side-effect, and always foldable and then assume that this is a constant. Adding a trait adds structure to this, and makes checking for a constant much more efficient as we can guarantee that all of these things have already been verified. Differential Revision: https://reviews.llvm.org/D76020
2020-02-21Move StandardOps/Ops.h to StandardOps/IR/Ops.hRob Suderman
Summary: NFC - Moved StandardOps/Ops.h to a StandardOps/IR dir to better match surrounding directories. This is to match other dialects, and prepare for moving StandardOps related transforms in out for Transforms and into StandardOps/Transforms. Differential Revision: https://reviews.llvm.org/D74940
2020-02-10[MLIR] Allow non-binary operations to be commutativeStephen Neuendorffer
NFC for binary operations. Differential Revision: https://reviews.llvm.org/D73670
2020-01-26Mass update the MLIR license header to mention "Part of the LLVM project"Mehdi Amini
This is an artifact from merging MLIR into LLVM, the file headers are now aligned with the rest of the project.
2020-01-11[mlir] NFC: Remove Value::operator* and Value::operator-> now that Value is ↵River Riddle
properly value-typed. Summary: These were temporary methods used to simplify the transition. Reviewed By: antiagainst Differential Revision: https://reviews.llvm.org/D72548
2019-12-23NFC: Replace ValuePtr with Value and remove it now that Value is value-typed.River Riddle
ValuePtr was a temporary typedef during the transition to a value-typed Value. PiperOrigin-RevId: 286945714
2019-12-23Adjust License.txt file to use the LLVM licenseMehdi Amini
PiperOrigin-RevId: 286906740
2019-12-22NFC: Introduce new ValuePtr/ValueRef typedefs to simplify the transition to ↵River Riddle
Value being value-typed. This is an initial step to refactoring the representation of OpResult as proposed in: https://groups.google.com/a/tensorflow.org/g/mlir/c/XXzzKhqqF_0/m/v6bKb08WCgAJ This change will make it much simpler to incrementally transition all of the existing code to use value-typed semantics. PiperOrigin-RevId: 286844725