9#ifndef MLIR_IR_PATTERNMATCH_H
10#define MLIR_IR_PATTERNMATCH_H
14#include "llvm/ADT/FunctionExtras.h"
15#include "llvm/Support/TypeName.h"
35 enum { ImpossibleToMatchSentinel = 65535 };
51 return representation ==
rhs.representation;
55 return representation <
rhs.representation;
62 unsigned short representation{ImpossibleToMatchSentinel};
95 if (rootKind == RootKind::OperationName)
104 if (rootKind == RootKind::InterfaceID)
113 if (rootKind == RootKind::TraitID)
130 return contextAndHasBoundedRecursion.getInt();
135 return contextAndHasBoundedRecursion.getPointer();
151 debugLabels.append(labels.begin(), labels.end());
188 Pattern(MatchInterfaceOpTypeTag tag, TypeID interfaceID,
189 PatternBenefit benefit, MLIRContext *context,
190 ArrayRef<StringRef> generatedNames = {});
198 MLIRContext *context, ArrayRef<StringRef> generatedNames = {});
203 contextAndHasBoundedRecursion.setInt(hasBoundedRecursionArg);
207 Pattern(
const void *rootValue, RootKind rootKind,
212 const void *rootValue;
220 llvm::PointerIntPair<MLIRContext *, 1, bool> contextAndHasBoundedRecursion;
253 template <
typename T,
typename... Args>
254 static std::unique_ptr<T>
create(Args &&...args) {
255 std::unique_ptr<T> pattern =
256 std::make_unique<T>(std::forward<Args>(args)...);
257 initializePattern<T>(*pattern);
260 if (pattern->getDebugName().empty())
261 pattern->setDebugName(llvm::getTypeName<T>());
271 template <
typename T,
typename... Args>
272 using has_initialize =
decltype(std::declval<T>().initialize());
273 template <
typename T>
274 using detect_has_initialize = llvm::is_detected<has_initialize, T>;
278 template <
typename T>
279 static void initializePattern(T &pattern) {
280 if constexpr (detect_has_initialize<T>::value)
281 pattern.initialize();
285 virtual void anchor();
292template <
typename SourceOp>
294 using RewritePattern::RewritePattern;
312template <
typename SourceOp>
324 :
mlir::
detail::OpOrInterfaceRewritePatternBase<SourceOp>(
325 SourceOp::getOperationName(), benefit, context, generatedNames) {}
331template <
typename SourceOp>
339 :
mlir::
detail::OpOrInterfaceRewritePatternBase<SourceOp>(
347template <
template <
typename>
class TraitType>
415 LogicalResult status) {}
433 : listener(listener),
439 listener->notifyOperationInserted(op, previous);
444 listener->notifyBlockInserted(block, previous, previousIt);
448 rewriteListener->notifyBlockErased(block);
452 rewriteListener->notifyOperationModified(op);
456 rewriteListener->notifyOperationReplaced(op, newOp);
461 rewriteListener->notifyOperationReplaced(op,
replacement);
465 rewriteListener->notifyOperationErased(op);
469 rewriteListener->notifyPatternBegin(pattern, op);
472 LogicalResult status)
override {
474 rewriteListener->notifyPatternEnd(pattern, status);
480 rewriteListener->notifyMatchFailure(loc, reasonCallback);
504 StringRef patternName;
528 template <
typename OpTy,
typename... Args>
530 auto builder =
static_cast<OpBuilder *
>(
this);
532 OpTy::create(*builder, op->
getLoc(), std::forward<Args>(args)...);
600 void moveOpBefore(Operation *op, Operation *existingOp);
609 void moveOpAfter(Operation *op, Operation *existingOp);
643 template <
typename CallableT>
665 assert(from.size() == to.size() &&
"incorrect number of replacements");
666 for (
auto it : llvm::zip(from, to))
686 bool *allUsesReplaced =
nullptr);
689 bool *allUsesReplaced =
nullptr);
695 bool *allUsesReplaced =
nullptr) {
704 Block *block,
bool *allUsesReplaced =
nullptr) {
708 return block->getParentOp()->isProperAncestor(use.
getOwner());
719 return user != exceptedUser;
730 template <
typename CallbackT>
731 std::enable_if_t<!std::is_convertible<CallbackT, Twine>::value, LogicalResult>
733 if (
auto *rewriteListener = dyn_cast_if_present<Listener>(
listener))
734 rewriteListener->notifyMatchFailure(
738 template <
typename CallbackT>
739 std::enable_if_t<!std::is_convertible<CallbackT, Twine>::value, LogicalResult>
741 if (
auto *rewriteListener = dyn_cast_if_present<Listener>(
listener))
742 rewriteListener->notifyMatchFailure(
746 template <
typename ArgT>
751 template <
typename ArgT>
823 using NativePatternListT = std::vector<std::unique_ptr<RewritePattern>>;
830 std::unique_ptr<RewritePattern> pattern)
832 nativePatterns.emplace_back(std::move(pattern));
835 : context(pattern.
getContext()), pdlPatterns(std::move(pattern)) {}
847 nativePatterns.clear();
858 template <
typename... Ts,
typename ConstructorArg,
859 typename... ConstructorArgs,
860 typename = std::enable_if_t<
sizeof...(Ts) != 0>>
864 (addImpl<Ts>({}, std::forward<ConstructorArg>(arg),
865 std::forward<ConstructorArgs>(args)...),
873 template <
typename... Ts,
typename ConstructorArg,
874 typename... ConstructorArgs,
875 typename = std::enable_if_t<
sizeof...(Ts) != 0>>
877 ConstructorArg &&arg,
878 ConstructorArgs &&...args) {
881 (addImpl<Ts>(debugLabels, std::forward<ConstructorArg>(arg),
882 std::forward<ConstructorArgs>(args)...),
889 template <
typename... Ts>
891 (addImpl<Ts>(), ...);
898 nativePatterns.emplace_back(std::move(pattern));
905 pdlPatterns.mergeIn(std::move(pattern));
910 template <
typename OpType>
921 LogicalResult matchAndRewrite(OpType op,
922 PatternRewriter &rewriter)
const override {
923 return implFn(op, rewriter);
927 LogicalResult (*implFn)(OpType, PatternRewriter &rewriter);
929 add(std::make_unique<FnPattern>(std::move(implFn),
getContext(), benefit,
943 template <
typename... Ts,
typename ConstructorArg,
944 typename... ConstructorArgs,
945 typename = std::enable_if_t<
sizeof...(Ts) != 0>>
949 (addImpl<Ts>({}, std::forward<ConstructorArg>(arg),
950 std::forward<ConstructorArgs>(args)...),
957 template <
typename... Ts>
959 (addImpl<Ts>(), ...);
966 nativePatterns.emplace_back(std::move(pattern));
973 pdlPatterns.mergeIn(std::move(pattern));
978 template <
typename OpType>
985 this->setDebugName(llvm::getTypeName<FnPattern>());
988 LogicalResult matchAndRewrite(OpType op,
990 return implFn(op, rewriter);
996 add(std::make_unique<FnPattern>(std::move(implFn),
getContext()));
1003 template <
typename T,
typename... Args>
1004 std::enable_if_t<std::is_base_of<RewritePattern, T>::value>
1006 std::unique_ptr<T> pattern =
1008 pattern->addDebugLabels(debugLabels);
1009 nativePatterns.emplace_back(std::move(pattern));
1012 template <
typename T,
typename... Args>
1013 std::enable_if_t<std::is_base_of<PDLPatternModule, T>::value>
1014 addImpl(ArrayRef<StringRef> debugLabels, Args &&...args) {
1017 pdlPatterns.mergeIn(T(std::forward<Args>(args)...));
1020 MLIRContext *
const context;
1021 NativePatternListT nativePatterns;
1025 PDLPatternModule pdlPatterns;
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be the output argument nBegin is set to its * replacement(set to `begin` if no invalidation happens). Since outgoing *copies could have been inserted at `end`
static std::string diag(const llvm::Value &value)
A block operand represents an operand that holds a reference to a Block, e.g.
Block represents an ordered list of Operations.
OpListType::iterator iterator
This class contains all of the information necessary to report a diagnostic to the DiagnosticEngine.
use_range getUses() const
Returns a range of all uses, which is useful for iterating over all uses.
IRRewriter(MLIRContext *ctx, OpBuilder::Listener *listener=nullptr)
IRRewriter(const OpBuilder &builder)
IRRewriter(Operation *op, OpBuilder::Listener *listener=nullptr)
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
This class represents a saved insertion point.
This class helps build Operations.
OpBuilder(MLIRContext *ctx, Listener *listener=nullptr)
Create a builder with the given context.
Listener * listener
The optional listener for events of this builder.
This class represents an operand of an operation.
OpTraitRewritePattern(MLIRContext *context, PatternBenefit benefit=1)
OpTraitRewritePattern Base
Type alias to allow derived classes to inherit constructors with using Base::Base;.
static OperationName getFromOpaquePointer(const void *pointer)
Operation is the basic unit of execution within MLIR.
Location getLoc()
The source location the operation was defined or derived from.
result_range getResults()
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
bool operator<(const PatternBenefit &rhs) const
bool operator==(const PatternBenefit &rhs) const
static PatternBenefit impossibleToMatch()
bool operator>=(const PatternBenefit &rhs) const
bool operator<=(const PatternBenefit &rhs) const
PatternBenefit & operator=(const PatternBenefit &)=default
PatternBenefit(const PatternBenefit &)=default
bool isImpossibleToMatch() const
bool operator!=(const PatternBenefit &rhs) const
bool operator>(const PatternBenefit &rhs) const
unsigned short getBenefit() const
If the corresponding pattern can match, return its benefit. If the.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
PatternRewriter(MLIRContext *ctx)
RewriterBase(MLIRContext *ctx, OpBuilder::Listener *listener=nullptr)
Initialize the builder.
virtual bool canRecoverFromRewriteFailure() const
A hook used to indicate if the pattern rewriter can recover from failure during the rewrite stage of ...
This class contains all of the data related to a pattern, but does not contain any methods or logic f...
Pattern(StringRef rootName, PatternBenefit benefit, MLIRContext *context, ArrayRef< StringRef > generatedNames={})
Construct a pattern with a certain benefit that matches the operation with the given root name.
MLIRContext * getContext() const
Return the MLIRContext used to create this pattern.
bool hasBoundedRewriteRecursion() const
Returns true if this pattern is known to result in recursive application, i.e.
void setHasBoundedRewriteRecursion(bool hasBoundedRecursionArg=true)
Set the flag detailing if this pattern has bounded rewrite recursion or not.
std::optional< TypeID > getRootInterfaceID() const
Return the interface ID used to match the root operation of this pattern.
PatternBenefit getBenefit() const
Return the benefit (the inverse of "cost") of matching this pattern.
std::optional< OperationName > getRootKind() const
Return the root node that this pattern matches.
ArrayRef< OperationName > getGeneratedOps() const
Return a list of operations that may be generated when rewriting an operation instance with this patt...
void setDebugName(StringRef name)
Set the human readable debug name used for this pattern.
void addDebugLabels(StringRef label)
void addDebugLabels(ArrayRef< StringRef > labels)
Add the provided debug labels to this pattern.
StringRef getDebugName() const
Return a readable name for this pattern.
std::optional< TypeID > getRootTraitID() const
Return the trait ID used to match the root operation of this pattern.
ArrayRef< StringRef > getDebugLabels() const
Return the set of debug labels attached to this pattern.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockListType::iterator iterator
NativePatternListT & getNativePatterns()
Return the native patterns held in this list.
RewritePatternSet & add(std::unique_ptr< RewritePattern > pattern)
Add the given native pattern to the pattern list.
PDLPatternModule & getPDLPatterns()
Return the PDL patterns held in this list.
RewritePatternSet(PDLPatternModule &&pattern)
RewritePatternSet & insert(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
RewritePatternSet & insert(std::unique_ptr< RewritePattern > pattern)
Add the given native pattern to the pattern list.
RewritePatternSet & add(LogicalResult(*implFn)(OpType, PatternRewriter &rewriter), PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})
void clear()
Clear out all of the held patterns in this list.
RewritePatternSet(MLIRContext *context)
RewritePatternSet & insert()
Add an instance of each of the pattern types 'Ts'.
RewritePatternSet & addWithLabel(ArrayRef< StringRef > debugLabels, ConstructorArg &&arg, ConstructorArgs &&...args)
An overload of the above add method that allows for attaching a set of debug labels to the attached p...
RewritePatternSet & insert(LogicalResult(*implFn)(OpType, PatternRewriter &rewriter))
MLIRContext * getContext() const
RewritePatternSet(MLIRContext *context, std::unique_ptr< RewritePattern > pattern)
Construct a RewritePatternSet populated with the given pattern.
RewritePatternSet & add()
Add an instance of each of the pattern types 'Ts'.
RewritePatternSet & add(PDLPatternModule &&pattern)
Add the given PDL pattern to the pattern list.
RewritePatternSet & insert(PDLPatternModule &&pattern)
Add the given PDL pattern to the pattern list.
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
RewritePattern is the common base class for all DAG to DAG replacements.
Pattern(StringRef rootName, PatternBenefit benefit, MLIRContext *context, ArrayRef< StringRef > generatedNames={})
Inherit the base constructors from Pattern.
virtual ~RewritePattern()=default
static std::unique_ptr< T > create(Args &&...args)
This method provides a convenient interface for creating and initializing derived rewrite patterns of...
virtual LogicalResult matchAndRewrite(Operation *op, PatternRewriter &rewriter) const =0
Attempt to match against code rooted at the specified operation, which is the same operation code as ...
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
void replaceOpUsesWithIf(Operation *from, ValueRange to, function_ref< bool(OpOperand &)> functor, bool *allUsesReplaced=nullptr)
virtual void eraseBlock(Block *block)
This method erases all operations in a block.
LogicalResult notifyMatchFailure(ArgT &&arg, const Twine &msg)
Block * splitBlock(Block *block, Block::iterator before)
Split the operations starting at "before" (inclusive) out of the given block into a new block,...
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
RewriterBase(const OpBuilder &otherBuilder)
void replaceAllUsesWith(ValueRange from, ValueRange to)
void moveBlockBefore(Block *block, Block *anotherBlock)
Unlink this block and insert it right before existingBlock.
virtual void finalizeOpModification(Operation *op)
This method is used to signal the end of an in-place modification of the given operation.
RewriterBase(Operation *op, OpBuilder::Listener *listener=nullptr)
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
Operation * eraseOpResults(Operation *op, const BitVector &eraseIndices)
Erase the specified results of the given operation.
virtual void cancelOpModification(Operation *op)
This method cancels a pending in-place modification.
void replaceAllUsesWith(Block *from, Block *to)
virtual void replaceUsesWithIf(Value from, Value to, function_ref< bool(OpOperand &)> functor, bool *allUsesReplaced=nullptr)
Find uses of from and replace them with to if the functor returns true.
void replaceAllUsesExcept(Value from, Value to, Operation *exceptedUser)
Find uses of from and replace them with to except if the user is exceptedUser.
RewriterBase(MLIRContext *ctx, OpBuilder::Listener *listener=nullptr)
Initialize the builder.
virtual void inlineBlockBefore(Block *source, Block *dest, Block::iterator before, ValueRange argValues={})
Inline the operations of block 'source' into block 'dest' before the given position.
void moveOpBefore(Operation *op, Operation *existingOp)
Unlink this operation from its current block and insert it right before existingOp which may be in th...
void mergeBlocks(Block *source, Block *dest, ValueRange argValues={})
Inline the operations of block 'source' into the end of block 'dest'.
LogicalResult notifyMatchFailure(ArgT &&arg, const char *msg)
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Operation *op, CallbackT &&reasonCallback)
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
void moveOpAfter(Operation *op, Operation *existingOp)
Unlink this operation from its current block and insert it right after existingOp which may be in the...
void inlineRegionBefore(Region ®ion, Region &parent, Region::iterator before)
Move the blocks that belong to "region" before the given position in another region "parent".
virtual void replaceAllUsesWith(Value from, Value to)
Find uses of from and replace them with to.
void replaceOpUsesWithinBlock(Operation *op, ValueRange newValues, Block *block, bool *allUsesReplaced=nullptr)
Find uses of from within block and replace them with to.
void replaceAllOpUsesWith(Operation *from, ValueRange to)
Find uses of from and replace them with to.
virtual void startOpModification(Operation *op)
This method is used to notify the rewriter that an in-place operation modification is about to happen...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
This class provides an efficient unique identifier for a specific C++ type.
static TypeID getFromOpaquePointer(const void *pointer)
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
use_range getUses() const
Returns a range of all uses, which is useful for iterating over all uses.
Operation * getOwner() const
Return the owner of this operand.
Include the generated interface declarations.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
llvm::function_ref< Fn > function_ref
Kind
The kind of listener.
@ RewriterBaseListener
RewriterBase::Listener or user-derived class.
This class represents a listener that may be used to hook into various actions within an OpBuilder.
OpInterfaceRewritePattern(MLIRContext *context, PatternBenefit benefit=1)
OpInterfaceRewritePattern Base
Type alias to allow derived classes to inherit constructors with using Base::Base;.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
OpRewritePattern Base
Type alias to allow derived classes to inherit constructors with using Base::Base;.
OpRewritePattern(MLIRContext *context, PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})
Patterns must specify the root operation name they match against, and can also specify the benefit of...
This class acts as a special tag that makes the desire to match "any" operation type explicit.
This class acts as a special tag that makes the desire to match any operation that implements a given...
This class acts as a special tag that makes the desire to match any operation that implements a given...
A listener that forwards all notifications to another listener.
void notifyMatchFailure(Location loc, function_ref< void(Diagnostic &)> reasonCallback) override
Notify the listener that the pattern failed to match, and provide a callback to populate a diagnostic...
void notifyOperationInserted(Operation *op, InsertPoint previous) override
Notify the listener that the specified operation was inserted.
void notifyPatternEnd(const Pattern &pattern, LogicalResult status) override
Notify the listener that a pattern application finished with the specified status.
void notifyOperationModified(Operation *op) override
Notify the listener that the specified operation was modified in-place.
void notifyPatternBegin(const Pattern &pattern, Operation *op) override
Notify the listener that the specified pattern is about to be applied at the specified root operation...
void notifyOperationReplaced(Operation *op, Operation *newOp) override
Notify the listener that all uses of the specified operation's results are about to be replaced with ...
void notifyOperationErased(Operation *op) override
Notify the listener that the specified operation is about to be erased.
void notifyBlockErased(Block *block) override
Notify the listener that the specified block is about to be erased.
ForwardingListener(OpBuilder::Listener *listener)
void notifyOperationReplaced(Operation *op, ValueRange replacement) override
Notify the listener that all uses of the specified operation's results are about to be replaced with ...
void notifyBlockInserted(Block *block, Region *previous, Region::iterator previousIt) override
Notify the listener that the specified block was inserted.
virtual void notifyMatchFailure(Location loc, function_ref< void(Diagnostic &)> reasonCallback)
Notify the listener that the pattern failed to match, and provide a callback to populate a diagnostic...
virtual void notifyOperationModified(Operation *op)
Notify the listener that the specified operation was modified in-place.
virtual void notifyOperationErased(Operation *op)
Notify the listener that the specified operation is about to be erased.
virtual void notifyOperationReplaced(Operation *op, Operation *replacement)
Notify the listener that all uses of the specified operation's results are about to be replaced with ...
virtual void notifyBlockErased(Block *block)
Notify the listener that the specified block is about to be erased.
virtual void notifyPatternEnd(const Pattern &pattern, LogicalResult status)
Notify the listener that a pattern application finished with the specified status.
virtual void notifyPatternBegin(const Pattern &pattern, Operation *op)
Notify the listener that the specified pattern is about to be applied at the specified root operation...
virtual void notifyOperationReplaced(Operation *op, ValueRange replacement)
Notify the listener that all uses of the specified operation's results are about to be replaced with ...
static bool classof(const OpBuilder::Listener *base)
void notifyOperationModified(Operation *op) override
Notify the listener that the specified operation was modified in-place.
void notifyOperationErased(Operation *op) override
Notify the listener that the specified operation is about to be erased.
PatternLoggingListener(OpBuilder::Listener *listener, StringRef patternName)
void notifyOperationReplaced(Operation *op, Operation *newOp) override
Notify the listener that all uses of the specified operation's results are about to be replaced with ...
void notifyOperationInserted(Operation *op, InsertPoint previous) override
Notify the listener that the specified operation was inserted.
void notifyPatternBegin(const Pattern &pattern, Operation *op) override
Notify the listener that the specified pattern is about to be applied at the specified root operation...
OpOrInterfaceRewritePatternBase is a wrapper around RewritePattern that allows for matching and rewri...
LogicalResult matchAndRewrite(Operation *op, PatternRewriter &rewriter) const final
Wrapper around the RewritePattern method that passes the derived op type.
virtual LogicalResult matchAndRewrite(SourceOp op, PatternRewriter &rewriter) const =0
Method that operates on the SourceOp type.