summaryrefslogtreecommitdiff
path: root/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
AgeCommit message (Collapse)Author
2025-10-20[mlir][SCF] Fix UB adjustment during `scf.for` loop peelingddubov100
Currently when peeling the first iteration, any mentioning of UB within the loop body is replaced with the new UB in the peeled out first iteration. This introduces a bug in the following scenario: Operations inside of the loop that intentionally use the original UB are incorrectly updated.
2025-09-16[MLIR] Fix SCF loop specialization (peeling) to work on scf.for with ↵Mehdi Amini
non-index type (#158707) The current code would crash with integer. This is visible on this modified example (the original with index was incorrect)
2025-08-15[mlir][SCF] `scf.for`: Add support for unsigned integer comparison (#153379)Matthias Springer
Add a new unit attribute to allow for unsigned integer comparison. Example: ```mlir scf.for unsigned %iv_32 = %lb_32 to %ub_32 step %step_32 : i32 { // body } ``` Discussion: https://discourse.llvm.org/t/scf-should-scf-for-support-unsigned-comparison/84655
2025-07-24[mlir][NFC] update `mlir/Dialect` create APIs (20/n) (#149927)Maksim Levental
See https://github.com/llvm/llvm-project/pull/147168 for more info.
2025-07-14[mlir] Remove unused includes (NFC) (#148769)Kazu Hirata
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.
2024-12-20[mlir] Enable decoupling two kinds of greedy behavior. (#104649)Jacques Pienaar
The greedy rewriter is used in many different flows and it has a lot of convenience (work list management, debugging actions, tracing, etc). But it combines two kinds of greedy behavior 1) how ops are matched, 2) folding wherever it can. These are independent forms of greedy and leads to inefficiency. E.g., cases where one need to create different phases in lowering and is required to applying patterns in specific order split across different passes. Using the driver one ends up needlessly retrying folding/having multiple rounds of folding attempts, where one final run would have sufficed. Of course folks can locally avoid this behavior by just building their own, but this is also a common requested feature that folks keep on working around locally in suboptimal ways. For downstream users, there should be no behavioral change. Updating from the deprecated should just be a find and replace (e.g., `find ./ -type f -exec sed -i 's|applyPatternsAndFoldGreedily|applyPatternsGreedily|g' {} \;` variety) as the API arguments hasn't changed between the two.
2024-10-29[MLIR][SCF] Fix LoopPeelOp documentation (NFC) (#113179)Hugo Trachino
As an example, I added annotations to the peel_front unit test. ``` func.func @loop_peel_first_iter_op() { // CHECK: %[[C0:.+]] = arith.constant 0 // CHECK: %[[C41:.+]] = arith.constant 41 // CHECK: %[[C5:.+]] = arith.constant 5 // CHECK: %[[C5_0:.+]] = arith.constant 5 // CHECK: scf.for %{{.+}} = %[[C0]] to %[[C5_0]] step %[[C5]] // CHECK: arith.addi // CHECK: scf.for %{{.+}} = %[[C5_0]] to %[[C41]] step %[[C5]] // CHECK: arith.addi %0 = arith.constant 0 : index %1 = arith.constant 41 : index %2 = arith.constant 5 : index scf.for %i = %0 to %1 step %2 { arith.addi %i, %i : index } return } module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for"> %main_loop, %remainder = transform.loop.peel %1 {peel_front = true} : (!transform.op<"scf.for">) -> (!transform.op<"scf.for">, !transform.op<"scf.for">) transform.annotate %main_loop "main_loop" : !transform.op<"scf.for"> transform.annotate %remainder "remainder" : !transform.op<"scf.for"> transform.yield } } ``` Gives : ``` func.func @loop_peel_first_iter_op() { %c0 = arith.constant 0 : index %c41 = arith.constant 41 : index %c5 = arith.constant 5 : index %c5_0 = arith.constant 5 : index scf.for %arg0 = %c0 to %c5_0 step %c5 { %0 = arith.addi %arg0, %arg0 : index } {remainder} // The first iteration loop (second result) has been annotated remainder scf.for %arg0 = %c5_0 to %c41 step %c5 { %0 = arith.addi %arg0, %arg0 : index } {main_loop} // The main loop (first result) has been annotated main_loop return } ``` --------- Co-authored-by: Andrzej Warzyński <andrzej.warzynski@gmail.com>
2024-03-25Fix the condition for peeling the first iteration (#86350)Vivian
This PR fixes the condition used in loop peeling of the first iteration. Using ceilDiv instead of floorDiv when calculating the loop counts, so that the first iteration gets peeled as needed.
2024-01-17[mlir][IR] Rename "update root" to "modify op" in rewriter API (#78260)Matthias Springer
This commit renames 4 pattern rewriter API functions: * `updateRootInPlace` -> `modifyOpInPlace` * `startRootUpdate` -> `startOpModification` * `finalizeRootUpdate` -> `finalizeOpModification` * `cancelRootUpdate` -> `cancelOpModification` The term "root" is a misnomer. The root is the op that a rewrite pattern matches against (https://mlir.llvm.org/docs/PatternRewriter/#root-operation-name-optional). A rewriter must be notified of all in-place op modifications, not just in-place modifications of the root (https://mlir.llvm.org/docs/PatternRewriter/#pattern-rewriter). The old function names were confusing and have contributed to various broken rewrite patterns. Note: The new function names use the term "modify" instead of "update" for consistency with the `RewriterBase::Listener` terminology (`notifyOperationModified`).
2024-01-12[mlir][scf] Fix `for-loop-peeling` crash (#77697)Felix Schneider
Before applying the peeling patterns, it can happen that the `ForOp` gets a step of zero during folding. This leads to a division-by-zero down the line. This patch adds an additional check for a constant-zero step and a test. Fix https://github.com/llvm/llvm-project/issues/75758
2023-12-14[mlir][SCF] Add support for peeling the first iteration out of the loop (#74015)Vivian
There is a use case that we need to peel the first iteration out of the for loop so that the peeled forOp can be canonicalized away and the fillOp can be fused into the inner forall loop. For example, we have nested loops as below ``` linalg.fill ins(...) outs(...) scf.for %arg = %lb to %ub step %step scf.forall ... ``` After the peeling transform, it is expected to be ``` scf.forall ... linalg.fill ins(...) outs(...) scf.for %arg = %(lb + step) to %ub step %step scf.forall ... ``` This patch makes the most use of the existing peeling functions and adds support for peeling the first iteration out of the loop.
2023-11-16[mlir][SCF] Do not peel already peeled loops (#71900)Matthias Springer
Loop peeling is not beneficial if the step size already divides "ub - lb". There are currently some simple checks to prevent peeling in such cases when lb, ub, step are constants. This commit adds support for IR that is the result of loop peeling in the general case; i.e., lb, ub, step do not necessarily have to be constants. This change adds a new affine_map simplification rule for semi-affine maps that appear during loop peeling and are guaranteed to evaluate to a constant zero. Affine maps such as: ``` (1) affine_map<()[ub, step] -> ((ub - ub mod step) mod step) (2) affine_map<()[ub, lb, step] -> ((ub - (ub - lb) mod step - lb) mod step) (3) ^ may contain additional summands ``` Other affine maps with modulo expressions are not supported by the new simplification rule. This fixes #71469.
2023-11-14[mlir][affine][nfc] cleanup deprecated T.cast style functions (#71269)long.chen
detail see the docment: https://mlir.llvm.org/deprecation/ Not all changes are made manually, most of them are made through a clang tool I wrote https://github.com/lipracer/cpp-refactor.
2023-04-20[mlir][Affine][NFC] Wrap dialect in "affine" namespaceMatthias Springer
This cleanup aligns the affine dialect with all the other dialects. Differential Revision: https://reviews.llvm.org/D148687
2023-02-28[mlir][Linalg] NFC - Apply cleanups to transformsNicolas Vasilache
Depends on: D144656 Differential Revision: https://reviews.llvm.org/D144717
2023-02-27[mlir][SCF] Fix incorrect API usage in RewritePatternsMatthias Springer
Incorrect API usage was detected by D144552. Differential Revision: https://reviews.llvm.org/D144636
2023-01-12[mlir] Add operations to BlockAndValueMapping and rename it to IRMappingJeff Niu
The patch adds operations to `BlockAndValueMapping` and renames it to `IRMapping`. When operations are cloned, old operations are mapped to the cloned operations. This allows mapping from an operation to a cloned operation. Example: ``` Operation *opWithRegion = ... Operation *opInsideRegion = &opWithRegion->front().front(); IRMapping map Operation *newOpWithRegion = opWithRegion->clone(map); Operation *newOpInsideRegion = map.lookupOrNull(opInsideRegion); ``` Migration instructions: All includes to `mlir/IR/BlockAndValueMapping.h` should be replaced with `mlir/IR/IRMapping.h`. All uses of `BlockAndValueMapping` need to be renamed to `IRMapping`. Reviewed By: rriddle, mehdi_amini Differential Revision: https://reviews.llvm.org/D139665
2023-01-04[mlir][affine][NFC] Extract core functionality of `canonicalizeMinMaxOp`Matthias Springer
Move code from SCF to Affine: Add a new helper function `simplifyConstrainedMinMaxOp` to Affine/Analysis/Utils.h. `canonicalizeMinMaxOp` was originally designed for loop peeling, but it is not SCF-specific and can be used to simplify any affine.min/max ops. Various functions in SCF/Transforms are simplified by dropping unnecessary parameters. Differential Revision: https://reviews.llvm.org/D140962
2022-12-02[mlir] Remove support for non-prefixed accessorsRiver Riddle
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-09-29[mlir][arith] Change dialect name from Arithmetic to ArithJakub Kuderski
Suggested by @lattner in https://discourse.llvm.org/t/rfc-define-precise-arith-semantics/65507/22. Tested with: `ninja check-mlir check-mlir-integration check-mlir-mlir-spirv-cpu-runner check-mlir-mlir-vulkan-runner check-mlir-examples` and `bazel build --config=generic_clang @llvm-project//mlir:all`. Reviewed By: lattner, Mogball, rriddle, jpienaar, mehdi_amini Differential Revision: https://reviews.llvm.org/D134762
2022-08-31[MLIR] Update pass declarations to new autogenerated filesMichele Scuttari
The patch introduces the required changes to update the pass declarations and definitions to use the new autogenerated files and allow dropping the old infrastructure. Reviewed By: mehdi_amini, rriddle Differential Review: https://reviews.llvm.org/D132838
2022-08-30Revert "[MLIR] Update pass declarations to new autogenerated files"Michele Scuttari
This reverts commit 2be8af8f0e0780901213b6fd3013a5268ddc3359.
2022-08-30[MLIR] Update pass declarations to new autogenerated filesMichele Scuttari
The patch introduces the required changes to update the pass declarations and definitions to use the new autogenerated files and allow dropping the old infrastructure. Reviewed By: mehdi_amini, rriddle Differential Review: https://reviews.llvm.org/D132838
2022-06-28[mlir] Update flipped accessors (NFC)Jacques Pienaar
Follow up with memref flipped and flipping any intermediate changes made.
2022-06-26[mlir] Generalize SCF passes to not have to run on FuncOp.Stella Laurenzo
Seems to have been an accident of history and none of these had any reason to be restricted to FuncOp. Differential Revision: https://reviews.llvm.org/D128614
2022-06-20[mlir] move SCF headers to SCF/{IR,Transforms} respectivelyAlex Zinenko
This aligns the SCF dialect file layout with the majority of the dialects. Reviewed By: jpienaar Differential Revision: https://reviews.llvm.org/D128049
2022-04-18[mlir:NFC] Remove the forward declaration of FuncOp in the mlir namespaceRiver Riddle
FuncOp has been moved to the `func` namespace for a little over a month, the using directive can be dropped now.
2022-03-01[mlir] Trim a huge number of unnecessary dependencies on the Func dialectRiver Riddle
The Func has a large number of legacy dependencies carried over from the old Standard dialect, which was pervasive and contained a large number of varied operations. With the split of the standard dialect and its demise, a lot of lingering dead dependencies have survived to the Func dialect. This commit removes a large majority of then, greatly reducing the dependence surface area of the Func dialect.
2022-03-01[mlir] Rename the Standard dialect to the Func dialectRiver Riddle
The last remaining operations in the standard dialect all revolve around FuncOp/function related constructs. This patch simply handles the initial renaming (which by itself is already huge), but there are a large number of cleanups unlocked/necessary afterwards: * Removing a bunch of unnecessary dependencies on Func * Cleaning up the From/ToStandard conversion passes * Preparing for the move of FuncOp to the Func dialect See the discussion at https://discourse.llvm.org/t/standard-dialect-the-final-chapter/6061 Differential Revision: https://reviews.llvm.org/D120624
2022-01-28[mlir] Move SCF utils implementations to SCF/Utils.Adrian Kuegel
BEGIN_PUBLIC [mlir] Move SCF utils implementations to SCF/Utils. END_PUBLIC
2022-01-18[mlir][Pass] Deprecate FunctionPass in favor of OperationPass<FuncOp>River Riddle
The only benefit of FunctionPass is that it filters out function declarations. This isn't enough to justify carrying it around, as we can simplify filter out declarations when necessary within the pass. We can also explore with better scheduling primitives to filter out declarations at the pipeline level in the future. The definition of FunctionPass is left intact for now to allow time for downstream users to migrate. Differential Revision: https://reviews.llvm.org/D117182
2022-01-18[mlir:Analysis] Move the LoopAnalysis library to Dialect/Affine/AnalysisRiver Riddle
The current state of the top level Analysis/ directory is that it contains two libraries; a generic Analysis library (free from dialect dependencies), and a LoopAnalysis library that contains various analysis utilities that originated from Affine loop transformations. This commit moves the LoopAnalysis to the more appropriate home of `Dialect/Affine/Analysis/`, given the use and intention of the majority of the code within it. After the move, if there are generic utilities that would fit better in the top-level Analysis/ directory, we can move them. Differential Revision: https://reviews.llvm.org/D117351
2021-12-20[mlir] Switching accessors to prefixed form (NFC)Jacques Pienaar
Makes eventual prefixing flag flip smaller change.
2021-12-07[mlir][scf] NFC: create dedicated files for affine utilsLei Zhang
These functions are generic utility functions that operates on affine ops within SCF regions. Moving them to their own files for a better code structure, instead of mixing with loop specialization logic. Reviewed By: nicolasvasilache Differential Revision: https://reviews.llvm.org/D115245
2021-11-25Revert "[mlir][SCF] Further simplify affine maps during ↵Alexander Belyaev
`for-loop-canonicalization`" This reverts commit ee1bf186723abb933b2c337e589c5958167f3cbe. It breaks IREE lowering. Reverting the commit for now while we investigate what's going on.
2021-11-25[mlir][SCF] Further simplify affine maps during `for-loop-canonicalization`Matthias Springer
* Implement `FlatAffineConstraints::getConstantBound(EQ)`. * Inject a simpler constraint for loops that have at most 1 iteration. * Taking into account constant EQ bounds of FlatAffineConstraint dims/symbols during canonicalization of the resulting affine map in `canonicalizeMinMaxOp`. Differential Revision: https://reviews.llvm.org/D114138
2021-11-25[mlir][SCF] Fix off-by-one bug in affine analysisMatthias Springer
This change is NFC. There were two issues when passing/reading upper bounds into/from FlatAffineConstraints that negate each other, so the bug was not apparent. However, it made debugging harder because some constraints in the FlatAffineConstraints were off by one when dumping all constraints. Differential Revision: https://reviews.llvm.org/D114137
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-10[mlir][scf] Loop peeling: Use scf.for for partial iterationMatthias Springer
Generate an scf.for instead of an scf.if for the partial iteration. This is for consistency reasons: The peeling of linalg.tiled_loop also uses another loop for the partial iteration. Note: Canonicalizations patterns may rewrite partial iterations to scf.if afterwards. Differential Revision: https://reviews.llvm.org/D109568
2021-09-07[mlir][linalg] linalg.tiled_loop peelingMatthias Springer
Differential Revision: https://reviews.llvm.org/D108270
2021-08-30[mlir][SCF] Canonicalize dim(x) where x is an iter_argMatthias Springer
* Add `DimOfIterArgFolder`. * Move existing cross-dialect canonicalization patterns to `LoopCanonicalization.cpp`. * Rename `SCFAffineOpCanonicalization` pass to `SCFForLoopCanonicalization`. * Expand documentaton of scf.for: The type of loop-carried variables may not change with iterations. (Not even the dynamic type.) Differential Revision: https://reviews.llvm.org/D108806
2021-08-30[mlir][Analysis] Add batched version of FlatAffineConstraints::addIdMatthias Springer
* Add batched version of all `addId` variants, so that multiple IDs can be added at a time. * Rename `addId` and variants to `insertId` and `appendId`. Most external users call `appendId`. Splitting `addId` into two functions also makes it possible to provide batched version for both. (Otherwise, the overloads are ambigious when calling `addId`.) Differential Revision: https://reviews.llvm.org/D108532
2021-08-25[mlir][SCF] Generalize AffineMinSCFCanonicalization to min/max opsMatthias Springer
* Add support for affine.max ops to SCF loop peeling pattern. * Add support for affine.max ops to `AffineMinSCFCanonicalizationPattern`. * Rename `AffineMinSCFCanonicalizationPattern` to `AffineOpSCFCanonicalizationPattern`. * Rename `AffineMinSCFCanonicalization` pass to `SCFAffineOpCanonicalization`. Differential Revision: https://reviews.llvm.org/D108009
2021-08-25[mlir][scf] Add general affine.min canonicalization patternMatthias Springer
This canonicalization simplifies affine.min operations inside "for loop"-like operations (e.g., scf.for and scf.parallel) based on two invariants: * iv >= lb * iv < lb + step * ((ub - lb - 1) floorDiv step) + 1 This commit adds a new pass `canonicalize-scf-affine-min` (instead of being a canonicalization pattern) to avoid dependencies between the Affine dialect and the SCF dialect. Differential Revision: https://reviews.llvm.org/D107731
2021-08-24[mlir][SCF] Use symbols in loop peeling rewriteMatthias Springer
Use symbols in the affine map instead of dims. Dims should not be divided. Differential Revision: https://reviews.llvm.org/D108431
2021-08-23[mlir][SCF] Do not peel loops inside partial iterationsMatthias Springer
Do not apply loop peeling to loops that are contained in the partial iteration of an already peeled loop. This is to avoid code explosion when dealing with large loop nests. Can be controlled with a new pass option `skip-partial`. Differential Revision: https://reviews.llvm.org/D108542
2021-08-19[mlir][scf] Simplify affine.min ops after loop peelingMatthias Springer
Simplify affine.min ops, enabling various other canonicalizations inside the peeled loop body. affine.min ops such as: ``` map = affine_map<(d0)[s0, s1] -> (s0, -d0 + s1)> %r = affine.min #affine.min #map(%iv)[%step, %ub] ``` are rewritten them into (in the case the peeled loop): ``` %r = %step ``` To determine how an affine.min op should be rewritten and to prove its correctness, FlatAffineConstraints is utilized. Differential Revision: https://reviews.llvm.org/D107222
2021-08-10[mlir] NFC Replace some code snippets with equivalent method callsTres Popp
Replace some code snippets With scf::ForOp methods. Additionally, share a listener at one more point (although this pattern is still not safe to roll back currently) Differential Revision: https://reviews.llvm.org/D107754
2021-08-04[mlir][scf] Fix bug in peelForLoopMatthias Springer
Insertion point should be set before creating new operations. Differential Revision: https://reviews.llvm.org/D107326
2021-08-03[mlir][SCF] Peel scf.for loops for even step divisonMatthias Springer
Add ForLoopBoundSpecialization pass, which specializes scf.for loops into a "main loop" where `step` divides the iteration space evenly and into an scf.if that handles the last iteration. This transformation is useful for vectorization and loop tiling. E.g., when vectorizing loads/stores, programs will spend most of their time in the main loop, in which only unmasked loads/stores are used. Only the in the last iteration (scf.if), slower masked loads/stores are used. Subsequent commits will apply this transformation in the SparseDialect and in Linalg's loop tiling. Differential Revision: https://reviews.llvm.org/D105804