MLIR 24.0.0git
FrozenRewritePatternSet.cpp
Go to the documentation of this file.
1//===- FrozenRewritePatternSet.cpp - Frozen Pattern List -------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "ByteCode.h"
13#include <optional>
14
15using namespace mlir;
16
17// Include the PDL rewrite support.
18#if MLIR_ENABLE_PDL_IN_PATTERNMATCH
22
23static LogicalResult
24convertPDLToPDLInterp(ModuleOp pdlModule,
26 // Skip the conversion if the module doesn't contain pdl.
27 if (pdlModule.getOps<pdl::PatternOp>().empty())
28 return success();
29
30 // Simplify the provided PDL module. Note that we can't use the canonicalizer
31 // here because it would create a cyclic dependency.
32 auto simplifyFn = [](Operation *op) {
33 // TODO: Add folding here if ever necessary.
34 if (isOpTriviallyDead(op))
35 op->erase();
36 };
37 pdlModule.getBody()->walk(simplifyFn);
38
39 /// Lower the PDL pattern module to the interpreter dialect.
40 PassManager pdlPipeline(pdlModule->getName());
41#ifdef NDEBUG
42 // We don't want to incur the hit of running the verifier when in release
43 // mode.
44 pdlPipeline.enableVerifier(false);
45#endif
46 pdlPipeline.addPass(createConvertPDLToPDLInterpPass(configMap));
47 if (failed(pdlPipeline.run(pdlModule)))
48 return failure();
49
50 // Simplify again after running the lowering pipeline.
51 pdlModule.getBody()->walk(simplifyFn);
52 return success();
53}
54#endif // MLIR_ENABLE_PDL_IN_PATTERNMATCH
55
56//===----------------------------------------------------------------------===//
57// FrozenRewritePatternSet
58//===----------------------------------------------------------------------===//
59
61 : impl(std::make_shared<Impl>()) {}
62
64 RewritePatternSet &&patterns, ArrayRef<std::string> disabledPatternLabels,
65 ArrayRef<std::string> enabledPatternLabels)
66 : impl(std::make_shared<Impl>()) {
67 // Functor used to walk all of the operations registered in the context. This
68 // is useful for patterns that get applied to multiple operations, such as
69 // interface and trait based patterns.
70 std::vector<RegisteredOperationName> opInfos;
71 auto addToOpsWhen =
72 [&](std::unique_ptr<RewritePattern> &pattern,
74 if (opInfos.empty())
75 opInfos = pattern->getContext()->getRegisteredOperations();
76 for (RegisteredOperationName info : opInfos)
77 if (callbackFn(info))
78 impl->nativeOpSpecificPatternMap[info].push_back(pattern.get());
79 impl->nativeOpSpecificPatternList.push_back(std::move(pattern));
80 };
81
82 // Returns true if `label` (a pattern's debug name or one of its debug
83 // labels) matches any entry in `userLabels`. A user label matches on exact
84 // string equality; additionally, a user label that does not contain "::"
85 // matches against the suffix of `label` after its last "::", so users can
86 // write e.g. `disable-patterns=FooBar` instead of
87 // `disable-patterns=(anonymous namespace)::FooBar`. Note: an unqualified
88 // user label matches *any* pattern whose unqualified name is the same,
89 // regardless of namespace.
90 auto matchesAnyUserLabel = [](StringRef label,
91 ArrayRef<std::string> userLabels) {
92 size_t pos = label.rfind("::");
93 StringRef unqualified =
94 (pos == StringRef::npos) ? label : label.substr(pos + 2);
95 for (StringRef ul : userLabels) {
96 if (label == ul)
97 return true;
98 if (!ul.contains("::") && unqualified == ul)
99 return true;
100 }
101 return false;
102 };
103
104 for (std::unique_ptr<RewritePattern> &pat : patterns.getNativePatterns()) {
105 // Don't add patterns that haven't been enabled by the user.
106 if (!enabledPatternLabels.empty()) {
107 auto isEnabledFn = [&](StringRef label) {
108 return matchesAnyUserLabel(label, enabledPatternLabels);
109 };
110 if (!isEnabledFn(pat->getDebugName()) &&
111 llvm::none_of(pat->getDebugLabels(), isEnabledFn))
112 continue;
113 }
114 // Don't add patterns that have been disabled by the user.
115 if (!disabledPatternLabels.empty()) {
116 auto isDisabledFn = [&](StringRef label) {
117 return matchesAnyUserLabel(label, disabledPatternLabels);
118 };
119 if (isDisabledFn(pat->getDebugName()) ||
120 llvm::any_of(pat->getDebugLabels(), isDisabledFn))
121 continue;
122 }
123
124 if (std::optional<OperationName> rootName = pat->getRootKind()) {
125 impl->nativeOpSpecificPatternMap[*rootName].push_back(pat.get());
126 impl->nativeOpSpecificPatternList.push_back(std::move(pat));
127 continue;
128 }
129 if (std::optional<TypeID> interfaceID = pat->getRootInterfaceID()) {
130 addToOpsWhen(pat, [&](RegisteredOperationName info) {
131 return info.hasInterface(*interfaceID);
132 });
133 continue;
134 }
135 if (std::optional<TypeID> traitID = pat->getRootTraitID()) {
136 addToOpsWhen(pat, [&](RegisteredOperationName info) {
137 return info.hasTrait(*traitID);
138 });
139 continue;
140 }
141 impl->nativeAnyOpPatterns.push_back(std::move(pat));
142 }
143
144#if MLIR_ENABLE_PDL_IN_PATTERNMATCH
145 // Generate the bytecode for the PDL patterns if any were provided.
146 PDLPatternModule &pdlPatterns = patterns.getPDLPatterns();
147 ModuleOp pdlModule = pdlPatterns.getModule();
148 if (!pdlModule)
149 return;
151 pdlPatterns.takeConfigMap();
152 if (failed(convertPDLToPDLInterp(pdlModule, configMap)))
153 llvm::report_fatal_error(
154 "failed to lower PDL pattern module to the PDL Interpreter");
155
156 // Verify that the PDL module was actually lowered to the interpreter
157 // dialect. If the lowering pass was skipped (e.g., by a debug counter
158 // via --mlir-debug-counter), the matcher function will not be present and
159 // we skip bytecode construction. PDL patterns will not be applied in this
160 // case.
161 if (!pdlModule.lookupSymbol(
162 pdl_interp::PDLInterpDialect::getMatcherFunctionName()))
163 return;
164
165 // Generate the pdl bytecode.
166 impl->pdlByteCode = std::make_unique<detail::PDLByteCode>(
167 pdlModule, pdlPatterns.takeConfigs(), configMap,
168 pdlPatterns.takeConstraintFunctions(),
169 pdlPatterns.takeRewriteFunctions());
170#endif // MLIR_ENABLE_PDL_IN_PATTERNMATCH
171}
172
return success()
if(!isCopyOut)
bool hasTrait() const
Returns true if the operation was registered with a particular trait, e.g.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
The main pass manager and pipeline builder.
This is a "type erased" representation of a registered operation.
Attribute collections provide a dictionary-like interface.
Definition Traits.h:18
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:717
Include the generated interface declarations.
std::unique_ptr< OperationPass< ModuleOp > > createConvertPDLToPDLInterpPass(DenseMap< Operation *, PDLPatternConfigSet * > &configMap)
Creates and returns a pass to convert PDL ops to PDL interpreter ops.
bool isOpTriviallyDead(Operation *op)
Return true if the given operation is unused, and has no side effects on memory that prevent erasing.
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
Definition LLVM.h:120
llvm::function_ref< Fn > function_ref
Definition LLVM.h:147