22#include "llvm/ADT/DenseSet.h"
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/Support/DebugLog.h"
25#include "llvm/Support/ErrorHandling.h"
27#define DEBUG_TYPE "walk-rewriter"
36 reachableBlocks.insert(entryBlock);
39 while (!worklist.empty()) {
40 Block *block = worklist.pop_back_val();
43 if (reachableBlocks.contains(successor))
45 worklist.push_back(successor);
46 reachableBlocks.insert(successor);
52struct WalkAndApplyPatternsAction final
53 : tracing::ActionImpl<WalkAndApplyPatternsAction> {
55 using ActionImpl::ActionImpl;
56 static constexpr StringLiteral tag =
"walk-and-apply-patterns";
60#if MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
70 using RewriterBase::ForwardingListener::ForwardingListener;
72 void notifyOperationInserted(Operation *op,
73 OpBuilder::InsertPoint previous)
override {
75 newlyCreatedOps.insert(op);
76 ForwardingListener::notifyOperationInserted(op, previous);
79 void notifyBlockInserted(Block *block, Region *previous,
80 Region::iterator previousIt)
override {
82 newlyCreatedBlocks.insert(block);
83 ForwardingListener::notifyBlockInserted(block, previous, previousIt);
86 void notifyOperationErased(Operation *op)
override {
87 if (!newlyCreatedOps.contains(op))
89 newlyCreatedOps.erase(op);
90 ForwardingListener::notifyOperationErased(op);
93 void notifyBlockErased(Block *block)
override {
94 if (!newlyCreatedBlocks.contains(block))
95 checkErasure(block->getParentOp());
96 newlyCreatedBlocks.erase(block);
97 ForwardingListener::notifyBlockErased(block);
100 void checkErasure(Operation *op)
const {
101 Operation *ancestorOp = op;
102 while (ancestorOp && ancestorOp != visitedOp)
103 ancestorOp = ancestorOp->getParentOp();
105 if (ancestorOp != visitedOp)
106 llvm::report_fatal_error(
107 "unsupported erasure in WalkPatternRewriter; "
108 "erasure is only supported for matched ops and their descendants");
111 Operation *visitedOp =
nullptr;
113 DenseSet<Operation *> newlyCreatedOps;
114 DenseSet<Block *> newlyCreatedBlocks;
122#if MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
124 llvm::report_fatal_error(
"walk pattern rewriter input IR failed to verify");
129#if MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
130 ErasedOpsListener erasedListener(listener);
142 struct RegionReachableOpIterator {
143 RegionReachableOpIterator(
Region *region) : region(region) {
144 regionIt = region->
begin();
145 if (regionIt != region->
end())
146 blockIt = regionIt->begin();
147 if (!llvm::hasSingleElement(*region))
152 assert(regionIt != region->
end());
153 hasVisitedRegions =
false;
154 if (blockIt == regionIt->end()) {
156 while (regionIt != region->
end() &&
157 !reachableBlocks.contains(&*regionIt))
159 if (regionIt != region->
end())
160 blockIt = regionIt->begin();
164 if (blockIt != regionIt->end()) {
165 LDBG() <<
"Incrementing block iterator, next op: "
178 bool hasVisitedRegions =
false;
184 LDBG() <<
"Starting walk-based pattern rewrite driver";
190 assert(worklist.empty());
195 worklist.push_back({®ion});
196 while (!worklist.empty()) {
197 RegionReachableOpIterator &it = worklist.back();
198 if (it.regionIt == it.region->end()) {
203 if (it.blockIt == it.regionIt->end()) {
211 if (!it.hasVisitedRegions) {
212 it.hasVisitedRegions =
true;
214 if (nestedRegion.empty())
216 worklist.push_back({&nestedRegion});
222 if (&it != &worklist.back())
229 LDBG() <<
"Visiting op: "
231#if MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
232 erasedListener.visitedOp = op;
233 erasedListener.newlyCreatedOps.clear();
234 erasedListener.newlyCreatedBlocks.clear();
237 LDBG() <<
"\tOp matched and rewritten";
243#if MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS
245 llvm::report_fatal_error(
246 "walk pattern rewriter result IR failed to verify");
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
#define MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CLASS_NAME)
Block represents an ordered list of Operations.
OpListType::iterator iterator
This class represents a frozen set of patterns that can be processed by a pattern applicator.
MLIRContext is the top-level object for a collection of MLIR operations.
void executeAction(function_ref< void()> actionFn, const tracing::Action &action)
Dispatch the provided action to the handler if any, or just execute it.
void setListener(Listener *newListener)
Sets the listener of this builder to the one provided.
Set of flags used to control the behavior of the various IR print methods (e.g.
A wrapper class that allows for printing an operation with a set of flags, useful to act as a "stream...
Operation is the basic unit of execution within MLIR.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
SuccessorRange getSuccessors()
MLIRContext * getContext()
Return the context this operation is associated with.
This class manages the application of a group of rewrite patterns, with a user-provided cost model.
LogicalResult matchAndRewrite(Operation *op, PatternRewriter &rewriter, function_ref< bool(const Pattern &)> canApply={}, function_ref< void(const Pattern &)> onFailure={}, function_ref< LogicalResult(const Pattern &)> onSuccess={})
Attempt to match and rewrite the given op with any pattern, allowing a predicate to decide if a patte...
void applyDefaultCostModel()
Apply the default cost model that solely uses the pattern's static benefit.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockListType::iterator iterator
Include the generated interface declarations.
static void findReachableBlocks(Region ®ion, DenseSet< Block * > &reachableBlocks)
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
void walkAndApplyPatterns(Operation *op, const FrozenRewritePatternSet &patterns, RewriterBase::Listener *listener=nullptr)
A fast walk-based pattern rewrite driver.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
A listener that forwards all notifications to another listener.