aboutsummaryrefslogtreecommitdiff
path: root/mlir/lib/IR/PatternMatch.cpp
AgeCommit message (Collapse)AuthorFilesLines
7 days[mlir][IR] Set insertion point when erasing an operation (#146955)Matthias Springer1-0/+10
Erasing the operation to which the current insertion point is set, leaves the insertion point in an invalid state. This commit resets the insertion point to the following operation. Also adjust the insertion point when inlining a block.
10 days[mlir] Remove unused includes (NFC) (#150476)Kazu Hirata1-2/+0
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-03-31[MLIR][NFC] Fix incomplete boundary comments. (#133516)Han-Chung Wang1-0/+5
I observed that we have the boundary comments in the codebase like: ``` //===----------------------------------------------------------------------===// // ... //===----------------------------------------------------------------------===// ``` I also observed that there are incomplete boundary comments. The revision is generated by a script that completes the boundary comments. ``` //===----------------------------------------------------------------------===// // ... ... ``` Signed-off-by: hanhanW <hanhan0912@gmail.com>
2025-03-06[mlir][IR] Move `match` and `rewrite` functions into separate class (#129861)Matthias Springer1-9/+0
The vast majority of rewrite / conversion patterns uses a combined `matchAndRewrite` instead of separate `match` and `rewrite` functions. This PR optimizes the code base for the most common case where users implement a combined `matchAndRewrite`. There are no longer any `match` and `rewrite` functions in `RewritePattern`, `ConversionPattern` and their derived classes. Instead, there is a `SplitMatchAndRewriteImpl` class that implements `matchAndRewrite` in terms of `match` and `rewrite`. Details: * The `RewritePattern` and `ConversionPattern` classes are simpler (fewer functions). Especially the `ConversionPattern` class, which now has 5 fewer functions. (There were various `rewrite` overloads to account for 1:1 / 1:N patterns.) * There is a new class `SplitMatchAndRewriteImpl` that derives from `RewritePattern` / `OpRewritePatern` / ..., along with a type alias `RewritePattern::SplitMatchAndRewrite` for convenience. * Fewer `llvm_unreachable` are needed throughout the code base. Instead, we can use pure virtual functions. (In cases where users previously had to implement `rewrite` or `matchAndRewrite`, etc.) * This PR may also improve the number of [`-Woverload-virtual` warnings](https://discourse.llvm.org/t/matchandrewrite-hiding-virtual-functions/84933) that are produced by GCC. (To be confirmed...) Note for LLVM integration: Patterns with separate `match` / `rewrite` implementations, must derive from `X::SplitMatchAndRewrite` instead of `X`. --------- Co-authored-by: River Riddle <riddleriver@gmail.com>
2024-04-04[mlir][SCF] Modernize `coalesceLoops` method to handle `scf.for` loops with ↵MaheshRavishankar1-0/+9
iter_args (#87019) As part of this extension this change also does some general cleanup 1) Make all the methods take `RewriterBase` as arguments instead of creating their own builders that tend to crash when used within pattern rewrites 2) Split `coalesePerfectlyNestedLoops` into two separate methods, one for `scf.for` and other for `affine.for`. The templatization didnt seem to be buying much there. Also general clean up of tests.
2024-04-02[mlir][IR] Trigger `notifyOperationReplaced` on `replaceAllOpUsesWith` (#84721)Matthias Springer1-8/+16
Before this change: `notifyOperationReplaced` was triggered when calling `RewriteBase::replaceOp`. After this change: `notifyOperationReplaced` is triggered when `RewriterBase::replaceAllOpUsesWith` or `RewriterBase::replaceOp` is called. Until now, every `notifyOperationReplaced` was always sent together with a `notifyOperationErased`, which made that `notifyOperationErased` callback irrelevant. More importantly, when a user called `RewriterBase::replaceAllOpUsesWith`+`RewriterBase::eraseOp` instead of `RewriterBase::replaceOp`, no `notifyOperationReplaced` callback was sent, even though the two notations are semantically equivalent. As an example, this can be a problem when applying patterns with the transform dialect because the `TrackingListener` will only see the `notifyOperationErased` callback and the payload op is dropped from the mappings. Note: It is still possible to write semantically equivalent code that does not trigger a `notifyOperationReplaced` (e.g., when op results are replaced one-by-one), but this commit already improves the situation a lot.
2024-03-11[mlir][IR] Fix overload resolution on MSVC build (#84589)Matthias Springer1-2/+2
#82629 added additional overloads to `replaceAllUsesWith` and `replaceUsesWithIf`. This caused a build breakage with MSVC when called with ops that can implicitly convert to `Value`. ``` external/llvm-project/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp(881): error C2666: 'mlir::RewriterBase::replaceAllUsesWith': 2 overloads have similar conversions external/llvm-project/mlir/include\mlir/IR/PatternMatch.h(631): note: could be 'void mlir::RewriterBase::replaceAllUsesWith(mlir::Operation *,mlir::ValueRange)' external/llvm-project/mlir/include\mlir/IR/PatternMatch.h(626): note: or 'void mlir::RewriterBase::replaceAllUsesWith(mlir::ValueRange,mlir::ValueRange)' external/llvm-project/mlir/include\mlir/IR/PatternMatch.h(616): note: or 'void mlir::RewriterBase::replaceAllUsesWith(mlir::Value,mlir::Value)' external/llvm-project/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp(882): note: while trying to match the argument list '(mlir::tensor::ExtractSliceOp, T)' with [ T=mlir::Value ] ``` Note: The LLVM build bots (Linux and Windows) did not break, this seems to be an issue with `Tools\MSVC\14.29.30133\bin\HostX64\x64\cl.exe`. This change renames the newly added overloads to `replaceAllOpUsesWith` and `replaceOpUsesWithIf`.
2024-03-07[mlir][IR] Make `replaceOp` / `replaceAllUsesWith` API consistent (#82629)Matthias Springer1-46/+27
* `replaceOp` replaces all uses of the original op and erases the old op. * `replaceAllUsesWith` replaces all uses of the original op/value/block. It does not erase any IR. This commit renames `replaceOpWithIf` to `replaceUsesWithIf`. `replaceOpWithIf` was a misnomer because the function never erases the original op. Similarly, `replaceOpWithinBlock` is renamed to `replaceUsesWithinBlock`. (No "operation replaced" is sent because the op is not erased.) Also improve comments.
2024-03-05[mlir]use correct iterator when eraseOp (#83444)Congcong Cai1-1/+4
#66771 introduce `llvm::post_order(&r.front())` which is equal to `r.front().getSuccessor(...)`. It will visit the succ block of current block. But actually here need to visit all block of region in reverse order. Fixes: #77420.
2024-02-20[mlir][IR][NFC] Rename `notify*Removed` to `notify*Erased` (#82253)Matthias Springer1-2/+2
Rename listener callback names: * `notifyOperationRemoved` -> `notifyOperationErased` * `notifyBlockRemoved` -> `notifyBlockErased` The current callback names are misnomers. The callbacks are triggered when an operation/block is erased, not when it is removed (unlinked). E.g.: ```c++ /// Notify the listener that the specified operation is about to be erased. /// At this point, the operation has zero uses. /// /// Note: This notification is not triggered when unlinking an operation. virtual void notifyOperationErased(Operation *op) {} ``` This change is in preparation of adding listener support to the dialect conversion. The dialect conversion internally unlinks IR before erasing it at a later point of time. There is an important difference between "remove" and "erase". Lister callback names should be accurate to avoid confusion.
2024-02-02[mlir][IR] Send notifications for `cloneRegionBefore` (#66871)Matthias Springer1-18/+0
Similar to `OpBuilder::clone`, operation/block insertion notifications should be sent when cloning the contents of a region. E.g., this is to ensure that the newly created operations are put on the worklist of the greedy pattern rewriter driver. Also move `cloneRegionBefore` from `RewriterBase` to `OpBuilder`. It only creates new IR, so it should be part of the builder API (like `clone(Operation &)`). The function does not have to be virtual. Now that notifications are properly sent, the override in the dialect conversion is no longer needed.
2024-01-31[mlir][IR] Send missing notification when splitting a block (#79597)Matthias Springer1-1/+19
When a block is split with `RewriterBase::splitBlock`, a `notifyBlockInserted` notification, followed by `notifyOperationInserted` notifications (for moving over the operations into the new block) should be sent. This commit adds those notifications.
2024-01-31[mlir][IR] Send missing notifications when inlining a block (#79593)Matthias Springer1-1/+10
When a block is inlined into another block, the nested operations are moved into another block and the `notifyOperationInserted` callback should be triggered. This commit adds the missing notifications for: * `RewriterBase::inlineBlockBefore` * `RewriterBase::mergeBlocks`
2024-01-31[mlir][IR] Add `RewriterBase::moveBlockBefore` and fix bug in `moveOpBefore` ↵Matthias Springer1-13/+21
(#79579) This commit adds a new method to the rewriter API: `moveBlockBefore`. This op is utilized by `inlineRegionBefore` and covered by dialect conversion test cases. Also fixes a bug in `moveOpBefore`, where the previous op location was not passed correctly. Adds a test case to `test-strict-pattern-driver.mlir`.
2024-01-26[mlir][IR] Change `notifyBlockCreated` to `notifyBlockInserted` (#79472)Matthias Springer1-1/+12
This change makes the callback consistent with `notifyOperationInserted`: both now notify about IR insertion, not IR creation. See also #78988. This change also simplifies the dialect conversion: it is no longer necessary to override the `inlineRegionBefore` method. All information that is necessary for rollback is provided with the `notifyBlockInserted` callback.
2024-01-25[mlir][IR] Add rewriter API for moving operations (#78988)Matthias Springer1-0/+28
The pattern rewriter documentation states that "*all* IR mutations [...] are required to be performed via the `PatternRewriter`." This commit adds two functions that were missing from the rewriter API: `moveOpBefore` and `moveOpAfter`. After an operation was moved, the `notifyOperationInserted` callback is triggered. This allows listeners such as the greedy pattern rewrite driver to react to IR changes. This commit narrows the discrepancy between the kind of IR modification that can be performed and the kind of IR modifications that can be listened to.
2024-01-21[mlir][IR] Add `notifyBlockRemoved` callback to listener (#78306)Matthias Springer1-2/+9
There is already a "block inserted" notification (in `OpBuilder::Listener`), so there should also be a "block removed" notification. The purpose of this change is to make the listener API more mature. There is currently a gap between what kind of IR changes can be made and what IR changes can be listened to. At the moment, the only way to inform listeners about "block removal" is to send a manual `notifyOperationModified` for the parent op (e.g., by wrapping the `eraseBlock(b)` method call in `updateRootInPlace(b->getParentOp())`). This tells the listener that *something* has changed, but it is somewhat of an API abuse.
2024-01-17[mlir][IR] Rename "update root" to "modify op" in rewriter API (#78260)Matthias Springer1-2/+2
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-03[mlir] Add config for PDL (#69927)Jacques Pienaar1-118/+1
Make it so that PDL in pattern rewrites can be optionally disabled. PDL is still enabled by default and not optional bazel. So this should be a NOP for most folks, while enabling other to disable. This only works with tests disabled. With tests enabled this still compiles but tests fail as there is no lit config to disable tests that depend on PDL rewrites yet.
2024-01-03Revert "[mlir] Add config for PDL (#69927)"max1-1/+118
This reverts commit 5930725c891b60f5fb94058c6c08a55a2e03d83e.
2024-01-03[mlir] Add config for PDL (#69927)Jacques Pienaar1-118/+1
Make it so that PDL in pattern rewrites can be optionally disabled. PDL is still enabled by default and not optional bazel. So this should be a NOP for most folks, while enabling other to disable. This is piped through mlir-tblgen invocation and that could be changed/avoided by splitting up the passes file instead. This only works with tests disabled. With tests enabled this still compiles but tests fail as there is no lit config to disable tests that depend on PDL rewrites yet.
2023-09-20[mlir][IR] Trigger `notifyOperationRemoved` callback for nested ops (#66771)Matthias Springer1-4/+68
When cloning an op, the `notifyOperationInserted` callback is triggered for all nested ops. Similarly, the `notifyOperationRemoved` callback should be triggered for all nested ops when removing an op. Listeners may inspect the IR during a `notifyOperationRemoved` callback. Therefore, when multiple ops are removed in a single `RewriterBase::eraseOp` call, the notifications must be triggered in an order in which the ops could have been removed one-by-one: * Op removals must be interleaved with `notifyOperationRemoved` callbacks. A callback is triggered right before the respective op is removed. * Ops are removed post-order and in reverse order. Other traversal orders could delete an op that still has uses. (This is not avoidable in graph regions and with cyclic block graphs.) Differential Revision: Imported from https://reviews.llvm.org/D144193.
2023-06-14[mlir][IR] Improve listener notifications for ops without resultsMatthias Springer1-15/+23
`RewriterBase::Listener::notifyOperationReplaced` notifies observers that an op is about to be replaced with a range of values. This notification is not very useful for ops without results, because it does not specify the replacement op (and it cannot be deduced from the replacement values). It provides no additional information over the `notifyOperationRemoved` notification. This revision adds an additional notification when a rewriter replaces an op with another op. By default, this notification triggers the original "op replaced with values" notification, so there is no functional change for existing code. This new API is useful for the transform dialect, which needs to track op replacements. (Updated in a subsequent revision.) Also includes minor documentation improvements. Differential Revision: https://reviews.llvm.org/D152814
2023-03-06[mlir][IR] Clean up mergeBlockBefore and mergeBlocksMatthias Springer1-38/+37
* `RewriterBase::mergeBlocks` is simplified: it is implemented in terms of `mergeBlockBefore`. * The signature of `mergeBlockBefore` is consistent with other API (such as `inlineRegionBefore`): an overload for a `Block::iterator` is added. * Additional safety checks are added to `mergeBlockBefore`: detect cases where the resulting IR could be invalid (no more `dropAllUses`) or partly unreachable (likely a case of incorrect API usage). * Rename `mergeBlockBefore` to `inlineBlockBefore`. Differential Revision: https://reviews.llvm.org/D144969
2023-03-06[mlir][IR] Trigger notifyOperationModified for replacementsMatthias Springer1-10/+12
Each user of the original value is modified in-place. Therefore, the corresponding notification should be triggered. Also fixes a bug where `RewriterBase::mergeBlocks` did not notify the GreedyPatternRewriteDriver when replacing uses of block arguments. This function does not trigger "operation replaced" notifications, so the GreedyPatternRewriteDriver was not made aware of such IR changes. Differential Revision: https://reviews.llvm.org/D144549
2023-02-22[mlir][IR][NFC] Rename RewriterBase::replaceUseIf to replaceUsesWithIfMatthias Springer1-1/+1
This is for consistency with `Value::replaceUsesWithIf`. Differential Revision: https://reviews.llvm.org/D144547
2023-02-22[mlir] RewriterBase::Listener: Add notifyOperationModified callbackMatthias Springer1-0/+6
This callback is triggered by `finalizeRootUpdate`. This allows listeners to listen for in-place op modifications without creating a new RewriterBase subclass. Differential Revision: https://reviews.llvm.org/D143380
2023-02-22This change makes `RewriterBase` symmetric to `OpBuilder`.Matthias Springer1-4/+12
``` 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-15[mlir] Add RewriterBase::replaceAllUsesWith for Blocks.Ingo Müller1-8/+0
When changing IR in a RewriterPattern, all changes must go through the rewriter. There are several convenience functions in RewriterBase that help with high-level modifications, such as replaceAllUsesWith for Values, but there is currently none to do the same task for Blocks. Reviewed By: mehdi_amini, ingomueller-net Differential Revision: https://reviews.llvm.org/D142525
2023-01-16[mlir] Add a method to `RewriteBase` to replace a `Value` selectively.Mahesh Ravishankar1-8/+8
This method allows to selectively control from the caller when to replace the uses of a `Value`. Still notifies the rewriter that the user is updated in-place. Differential Revision: https://reviews.llvm.org/D141026
2023-01-12[mlir] Add operations to BlockAndValueMapping and rename it to IRMappingJeff Niu1-3/+3
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
2022-12-06[mlir] Add `replaceAllUsesExcept` to rewriterDiego Caballero1-0/+12
This patch adds `replaceAllUsesExcept` to the rewriter class. The implementation is copy-pasted from Value + calling `updateRootInPlace` to notify the listeners about the corresponding IR changes. Reviewed By: Mogball Differential Revision: https://reviews.llvm.org/D139382
2022-11-16[mlir] Introduce `replaceUsesOfWith` to `RewriterBase`Guray Ozen1-0/+8
Finding uses of a value and replacing them with a new one is a common method. I have not seen an safe and easy shortcut that does that. This revision attempts to address that by intoroducing `replaceUsesOfWith` to `RewriterBase`. Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D138110
2022-11-08[mlir:PDL] Add support for DialectConversion with pattern configurationsRiver Riddle1-1/+17
Up until now PDL(L) has not supported dialect conversion because we had no way of remapping values or integrating with type conversions. This commit rectifies that by adding a new "pattern configuration" concept to PDL. This essentially allows for attaching external configurations to patterns, which can hook into pattern events (for now just the scope of a rewrite, but we could also pass configs to native rewrites as well). This allows for injecting the type converter into the conversion pattern rewriter. Differential Revision: https://reviews.llvm.org/D133142
2022-09-27[mlir] specify the values when notifying about op replacementAlex Zinenko1-2/+2
It is useful for PatternRewriter listeners to know the values that are replacing the op in addition to only the fact of the op being replaced for being able to keep track of changes or for debugging. Reviewed By: Mogball Differential Revision: https://reviews.llvm.org/D134748
2021-12-10[mlir:PDL] Fix bugs in PDLPatternModule mergingRiver Riddle1-16/+17
* Constraints/Rewrites registered before a pattern was added were dropped * Constraints/Rewrites may be registered multiple times (if different pattern sets depend on them) * ModuleOp no longer has a terminator, so we shouldn't be removing the terminator from it Differential Revision: https://reviews.llvm.org/D114816
2021-11-26Introduced iterative bytecode execution.Stanislav Funiak1-0/+23
This is commit 2 of 4 for the multi-root matching in PDL, discussed in https://llvm.discourse.group/t/rfc-multi-root-pdl-patterns-for-kernel-matching/4148 (topic flagged for review). This commit implements the features needed for the execution of the new operations pdl_interp.get_accepting_ops, pdl_interp.choose_op: 1. The implementation of the generation and execution of the two ops. 2. The addition of Stack of bytecode positions within the ByteCodeExecutor. This is needed because in pdl_interp.choose_op, we iterate over the values returned by pdl_interp.get_accepting_ops until we reach finalize. When we reach finalize, we need to return back to the position marked in the stack. 3. The functionality to extend the lifetime of values that cross the nondeterministic choice. The existing bytecode generator allocates the values to memory positions by representing the liveness of values as a collection of disjoint intervals over the matcher positions. This is akin to register allocation, and substantially reduces the footprint of the bytecode executor. However, because with iterative operation pdl_interp.choose_op, execution "returns" back, so any values whose original liveness cross the nondeterminstic choice must have their lifetime executed until finalize. Testing: pdl-bytecode.mlir test Reviewed By: rriddle, Mogball Differential Revision: https://reviews.llvm.org/D108547
2021-03-23[mlir][Pattern] Add better support for using interfaces/traits to match root ↵River Riddle1-15/+41
operations in rewrite patterns To match an interface or trait, users currently have to use the `MatchAny` tag. This tag can be quite problematic for compile time for things like the canonicalizer, as the `MatchAny` patterns may get applied to *every* operation. This revision adds better support by bucketing interface/trait patterns based on which registered operations have them registered. This means that moving forward we will only attempt to match these patterns to operations that have this interface registered. Two simplify defining patterns that match traits and interfaces, two new utility classes have been added: OpTraitRewritePattern and OpInterfaceRewritePattern. Differential Revision: https://reviews.llvm.org/D98986
2021-03-16[mlir][PDL] Add support for variadic operands and results in the PDL byte codeRiver Riddle1-13/+22
Supporting ranges in the byte code requires additional complexity, given that a range can't be easily representable as an opaque void *, as is possible with the existing bytecode value types (Attribute, Type, Value, etc.). To enable representing a range with void *, an auxillary storage is used for the actual range itself, with the pointer being passed around in the normal byte code memory. For type ranges, a TypeRange is stored. For value ranges, a ValueRange is stored. The above problem represents a majority of the complexity involved in this revision, the rest is adapting/adding byte code operations to support the changes made to the PDL interpreter in the parent revision. After this revision, PDL will have initial end-to-end support for variadic operands/results. Differential Revision: https://reviews.llvm.org/D95723
2021-03-16[mlir][pdl] Remove CreateNativeOp in favor of a more general ↵River Riddle1-10/+1
ApplyNativeRewriteOp. This has a numerous amount of benefits, given the overly clunky nature of CreateNativeOp: * Users can now call into arbitrary rewrite functions from inside of PDL, allowing for more natural interleaving of PDL/C++ and enabling for more of the pattern to be in PDL. * Removes the need for an additional set of C++ functions/registry/etc. The new ApplyNativeRewriteOp will use the same PDLRewriteFunction as the existing RewriteOp. This reduces the API surface area exposed to users. This revision also introduces a new PDLResultList class. This class is used to provide results of native rewrite functions back to PDL. We introduce a new class instead of using a SmallVector to simplify the work necessary for variadics, given that ranges will require some changes to the structure of PDLValue. Differential Revision: https://reviews.llvm.org/D95720
2021-02-02[mlir][Pattern] Create a new IRRewriter class to enable sharing code with ↵River Riddle1-29/+27
pattern rewrites This revision adds two new classes, RewriterBase and IRRewriter. RewriterBase is a new shared base class between IRRewriter and PatternRewriter. PatternRewriter will continue to be the base class used to perform rewrites within a rewrite pattern. IRRewriter on the other hand, is a new class that allows for tracking IR rewrites from outside of a rewrite pattern. In this revision all of the old API from PatternRewriter is moved to RewriterBase, but the distinction between IRRewriter and PatternRewriter is kept on the chance that a necessary API divergence happens in the future. Currently if you want to have some utility that transforms a piece of IR and share it between pattern and non-pattern code, you have to duplicate it. This revision enables the creation of utilities that can be invoked from rewrite patterns and normal transformation code: ```c++ void someSharedUtility(RewriterBase &rewriter, ...) { // Some interesting IR mutation here. } // Some RewritePattern LogicalResult MyPattern::matchAndRewrite(Operation *op, PatternRewriter &rewriter) { ... someSharedUtility(rewriter, ...); ... } // Some Pass void MyPass::runOnOperation() { ... IRRewriter rewriter(...); someSharedUtility(rewriter, ...); } ``` Differential Revision: https://reviews.llvm.org/D94638
2021-01-14[mlir][PatternRewriter] Add a new hook to selectively replace uses of an ↵River Riddle1-0/+35
operation This revision adds a new `replaceOpWithIf` hook that replaces uses of an operation that satisfy a given functor. If all uses are replaced, the operation gets erased in a similar manner to `replaceOp`. DialectConversion support will be added in a followup as this requires adjusting how replacements are tracked there. Differential Revision: https://reviews.llvm.org/D94632
2020-12-01[mlir][PDL] Add support for PDL bytecode and expose PDL support to ↵River Riddle1-0/+78
OwningRewritePatternList PDL patterns are now supported via a new `PDLPatternModule` class. This class contains a ModuleOp with the pdl::PatternOp operations representing the patterns, as well as a collection of registered C++ functions for native constraints/creations/rewrites/etc. that may be invoked via the pdl patterns. Instances of this class are added to an OwningRewritePatternList in the same fashion as C++ RewritePatterns, i.e. via the `insert` method. The PDL bytecode is an in-memory representation of the PDL interpreter dialect that can be efficiently interpreted/executed. The representation of the bytecode boils down to a code array(for opcodes/memory locations/etc) and a memory buffer(for storing attributes/operations/values/any other data necessary). The bytecode operations are effectively a 1-1 mapping to the PDLInterp dialect operations, with a few exceptions in cases where the in-memory representation of the bytecode can be more efficient than the MLIR representation. For example, a generic `AreEqual` bytecode op can be used to represent AreEqualOp, CheckAttributeOp, and CheckTypeOp. The execution of the bytecode is split into two phases: matching and rewriting. When matching, all of the matched patterns are collected to avoid the overhead of re-running parts of the matcher. These matched patterns are then considered alongside the native C++ patterns, which rewrite immediately in-place via `RewritePattern::matchAndRewrite`, for the given root operation. When a PDL pattern is matched and has the highest benefit, it is passed back to the bytecode to execute its rewriter. Differential Revision: https://reviews.llvm.org/D89107
2020-10-29[mlir] NFC: fix trivial typosKazuaki Ishizaki1-1/+1
fix typos in comments and documents Reviewed By: jpienaar Differential Revision: https://reviews.llvm.org/D90089
2020-10-26[mlir][NFC] Move around the code related to PatternRewriting to improve layeringRiver Riddle1-137/+0
There are several pieces of pattern rewriting infra in IR/ that really shouldn't be there. This revision moves those pieces to a better location such that they are easier to evolve in the future(e.g. with PDL). More concretely this revision does the following: * Create a Transforms/GreedyPatternRewriteDriver.h and move the apply*andFold methods there. The definitions for these methods are already in Transforms/ so it doesn't make sense for the declarations to be in IR. * Create a new lib/Rewrite library and move PatternApplicator there. This new library will be focused on applying rewrites, and will also include compiling rewrites with PDL. Differential Revision: https://reviews.llvm.org/D89103
2020-10-26[mlir][Pattern] Refactor the Pattern class into a "metadata only" classRiver Riddle1-33/+38
The Pattern class was originally intended to be used for solely matching operations, but that use never materialized. All of the pattern infrastructure uses RewritePattern, and the infrastructure for pure matching(Matchers.h) is implemented inline. This means that this class isn't a useful abstraction at the moment, so this revision refactors it to solely encapsulate the "metadata" of a pattern. The metadata includes the various state describing a pattern; benefit, root operation, etc. The API on PatternApplicator is updated to now operate on `Pattern`s as nothing special from `RewritePattern` is necessary. This refactoring is also necessary for the upcoming use of PDL patterns alongside C++ rewrite patterns. Differential Revision: https://reviews.llvm.org/D86258
2020-09-09[MLIR] Add debug support for ignored patternsFrederik Gossen1-3/+24
The rewrite engine's cost model may determine some patterns to be irrelevant ahead of their application. These patterns were silently ignored previously and now cause a message in `--debug` mode. Differential Revision: https://reviews.llvm.org/D87290
2020-08-19[MLIR] Add PatternRewriter::mergeBlockBefore() to merge a block in the ↵Rahul Joshi1-0/+22
middle of another block. - This utility to merge a block anywhere into another one can help inline single block regions into other blocks. - Modified patterns test to use the new function. Differential Revision: https://reviews.llvm.org/D86251
2020-06-18[mlir] Allow for patterns to match any root kind.River Riddle1-28/+78
Traditionally patterns have always had the root operation kind hardcoded to a specific operation name. This has worked well for quite some time, but it has certain limitations that make it undesirable. For example, some lowering have the same implementation for many different operations types with a few lowering entire dialects using the same pattern implementation. This problem has led to several "solutions": a) Provide a template implementation to the user so that they can instantiate it for each operation combination, generally requiring the inclusion of the auto-generated operation definition file. b) Use a non-templated pattern that allows for providing the name of the operation to match - No one ever does this, because enumerating operation names can be cumbersome and so this quickly devolves into solution a. This revision removes the restriction that patterns have a hardcoded root type, and allows for a class patterns that could match "any" operation type. The major downside of root-agnostic patterns is that they make certain pattern analyses more difficult, so it is still very highly encouraged that an operation specific pattern be used whenever possible. Differential Revision: https://reviews.llvm.org/D82066
2020-06-18[mlir] Refactor RewritePatternMatcher into a new PatternApplicator class.River Riddle1-21/+61
This class enables for abstracting more of the details for the rewrite process, and will allow for clients to apply specific cost models to the pattern list. This allows for DialectConversion and the GreedyPatternRewriter to share the same underlying matcher implementation. This also simplifies the plumbing necessary to support dynamic patterns. Differential Revision: https://reviews.llvm.org/D81985