1abfd1a8bSRiver Riddle //===- ByteCode.cpp - Pattern ByteCode Interpreter ------------------------===//
2abfd1a8bSRiver Riddle //
3abfd1a8bSRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4abfd1a8bSRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
5abfd1a8bSRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6abfd1a8bSRiver Riddle //
7abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
8abfd1a8bSRiver Riddle //
9abfd1a8bSRiver Riddle // This file implements MLIR to byte-code generation and the interpreter.
10abfd1a8bSRiver Riddle //
11abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
12abfd1a8bSRiver Riddle 
13abfd1a8bSRiver Riddle #include "ByteCode.h"
14abfd1a8bSRiver Riddle #include "mlir/Analysis/Liveness.h"
15abfd1a8bSRiver Riddle #include "mlir/Dialect/PDL/IR/PDLTypes.h"
16abfd1a8bSRiver Riddle #include "mlir/Dialect/PDLInterp/IR/PDLInterp.h"
17e66c2e25SRiver Riddle #include "mlir/IR/BuiltinOps.h"
18abfd1a8bSRiver Riddle #include "mlir/IR/RegionGraphTraits.h"
19abfd1a8bSRiver Riddle #include "llvm/ADT/IntervalMap.h"
20abfd1a8bSRiver Riddle #include "llvm/ADT/PostOrderIterator.h"
21abfd1a8bSRiver Riddle #include "llvm/ADT/TypeSwitch.h"
22abfd1a8bSRiver Riddle #include "llvm/Support/Debug.h"
2385ab413bSRiver Riddle #include "llvm/Support/Format.h"
2485ab413bSRiver Riddle #include "llvm/Support/FormatVariadic.h"
2585ab413bSRiver Riddle #include <numeric>
26abfd1a8bSRiver Riddle 
27abfd1a8bSRiver Riddle #define DEBUG_TYPE "pdl-bytecode"
28abfd1a8bSRiver Riddle 
29abfd1a8bSRiver Riddle using namespace mlir;
30abfd1a8bSRiver Riddle using namespace mlir::detail;
31abfd1a8bSRiver Riddle 
32abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
33abfd1a8bSRiver Riddle // PDLByteCodePattern
34abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
35abfd1a8bSRiver Riddle 
36abfd1a8bSRiver Riddle PDLByteCodePattern PDLByteCodePattern::create(pdl_interp::RecordMatchOp matchOp,
37abfd1a8bSRiver Riddle                                               ByteCodeAddr rewriterAddr) {
38abfd1a8bSRiver Riddle   SmallVector<StringRef, 8> generatedOps;
39abfd1a8bSRiver Riddle   if (ArrayAttr generatedOpsAttr = matchOp.generatedOpsAttr())
40abfd1a8bSRiver Riddle     generatedOps =
41abfd1a8bSRiver Riddle         llvm::to_vector<8>(generatedOpsAttr.getAsValueRange<StringAttr>());
42abfd1a8bSRiver Riddle 
43abfd1a8bSRiver Riddle   PatternBenefit benefit = matchOp.benefit();
44abfd1a8bSRiver Riddle   MLIRContext *ctx = matchOp.getContext();
45abfd1a8bSRiver Riddle 
46abfd1a8bSRiver Riddle   // Check to see if this is pattern matches a specific operation type.
47abfd1a8bSRiver Riddle   if (Optional<StringRef> rootKind = matchOp.rootKind())
4876f3c2f3SRiver Riddle     return PDLByteCodePattern(rewriterAddr, *rootKind, benefit, ctx,
4976f3c2f3SRiver Riddle                               generatedOps);
5076f3c2f3SRiver Riddle   return PDLByteCodePattern(rewriterAddr, MatchAnyOpTypeTag(), benefit, ctx,
5176f3c2f3SRiver Riddle                             generatedOps);
52abfd1a8bSRiver Riddle }
53abfd1a8bSRiver Riddle 
54abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
55abfd1a8bSRiver Riddle // PDLByteCodeMutableState
56abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
57abfd1a8bSRiver Riddle 
58abfd1a8bSRiver Riddle /// Set the new benefit for a bytecode pattern. The `patternIndex` corresponds
59abfd1a8bSRiver Riddle /// to the position of the pattern within the range returned by
60abfd1a8bSRiver Riddle /// `PDLByteCode::getPatterns`.
61abfd1a8bSRiver Riddle void PDLByteCodeMutableState::updatePatternBenefit(unsigned patternIndex,
62abfd1a8bSRiver Riddle                                                    PatternBenefit benefit) {
63abfd1a8bSRiver Riddle   currentPatternBenefits[patternIndex] = benefit;
64abfd1a8bSRiver Riddle }
65abfd1a8bSRiver Riddle 
6685ab413bSRiver Riddle /// Cleanup any allocated state after a full match/rewrite has been completed.
6785ab413bSRiver Riddle /// This method should be called irregardless of whether the match+rewrite was a
6885ab413bSRiver Riddle /// success or not.
6985ab413bSRiver Riddle void PDLByteCodeMutableState::cleanupAfterMatchAndRewrite() {
7085ab413bSRiver Riddle   allocatedTypeRangeMemory.clear();
7185ab413bSRiver Riddle   allocatedValueRangeMemory.clear();
7285ab413bSRiver Riddle }
7385ab413bSRiver Riddle 
74abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
75abfd1a8bSRiver Riddle // Bytecode OpCodes
76abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
77abfd1a8bSRiver Riddle 
78abfd1a8bSRiver Riddle namespace {
79abfd1a8bSRiver Riddle enum OpCode : ByteCodeField {
80abfd1a8bSRiver Riddle   /// Apply an externally registered constraint.
81abfd1a8bSRiver Riddle   ApplyConstraint,
82abfd1a8bSRiver Riddle   /// Apply an externally registered rewrite.
83abfd1a8bSRiver Riddle   ApplyRewrite,
84abfd1a8bSRiver Riddle   /// Check if two generic values are equal.
85abfd1a8bSRiver Riddle   AreEqual,
8685ab413bSRiver Riddle   /// Check if two ranges are equal.
8785ab413bSRiver Riddle   AreRangesEqual,
88abfd1a8bSRiver Riddle   /// Unconditional branch.
89abfd1a8bSRiver Riddle   Branch,
90abfd1a8bSRiver Riddle   /// Compare the operand count of an operation with a constant.
91abfd1a8bSRiver Riddle   CheckOperandCount,
92abfd1a8bSRiver Riddle   /// Compare the name of an operation with a constant.
93abfd1a8bSRiver Riddle   CheckOperationName,
94abfd1a8bSRiver Riddle   /// Compare the result count of an operation with a constant.
95abfd1a8bSRiver Riddle   CheckResultCount,
9685ab413bSRiver Riddle   /// Compare a range of types to a constant range of types.
9785ab413bSRiver Riddle   CheckTypes,
983eb1647aSStanislav Funiak   /// Continue to the next iteration of a loop.
993eb1647aSStanislav Funiak   Continue,
100abfd1a8bSRiver Riddle   /// Create an operation.
101abfd1a8bSRiver Riddle   CreateOperation,
10285ab413bSRiver Riddle   /// Create a range of types.
10385ab413bSRiver Riddle   CreateTypes,
104abfd1a8bSRiver Riddle   /// Erase an operation.
105abfd1a8bSRiver Riddle   EraseOp,
1063eb1647aSStanislav Funiak   /// Extract the op from a range at the specified index.
1073eb1647aSStanislav Funiak   ExtractOp,
1083eb1647aSStanislav Funiak   /// Extract the type from a range at the specified index.
1093eb1647aSStanislav Funiak   ExtractType,
1103eb1647aSStanislav Funiak   /// Extract the value from a range at the specified index.
1113eb1647aSStanislav Funiak   ExtractValue,
112abfd1a8bSRiver Riddle   /// Terminate a matcher or rewrite sequence.
113abfd1a8bSRiver Riddle   Finalize,
1143eb1647aSStanislav Funiak   /// Iterate over a range of values.
1153eb1647aSStanislav Funiak   ForEach,
116abfd1a8bSRiver Riddle   /// Get a specific attribute of an operation.
117abfd1a8bSRiver Riddle   GetAttribute,
118abfd1a8bSRiver Riddle   /// Get the type of an attribute.
119abfd1a8bSRiver Riddle   GetAttributeType,
120abfd1a8bSRiver Riddle   /// Get the defining operation of a value.
121abfd1a8bSRiver Riddle   GetDefiningOp,
122abfd1a8bSRiver Riddle   /// Get a specific operand of an operation.
123abfd1a8bSRiver Riddle   GetOperand0,
124abfd1a8bSRiver Riddle   GetOperand1,
125abfd1a8bSRiver Riddle   GetOperand2,
126abfd1a8bSRiver Riddle   GetOperand3,
127abfd1a8bSRiver Riddle   GetOperandN,
12885ab413bSRiver Riddle   /// Get a specific operand group of an operation.
12985ab413bSRiver Riddle   GetOperands,
130abfd1a8bSRiver Riddle   /// Get a specific result of an operation.
131abfd1a8bSRiver Riddle   GetResult0,
132abfd1a8bSRiver Riddle   GetResult1,
133abfd1a8bSRiver Riddle   GetResult2,
134abfd1a8bSRiver Riddle   GetResult3,
135abfd1a8bSRiver Riddle   GetResultN,
13685ab413bSRiver Riddle   /// Get a specific result group of an operation.
13785ab413bSRiver Riddle   GetResults,
1383eb1647aSStanislav Funiak   /// Get the users of a value or a range of values.
1393eb1647aSStanislav Funiak   GetUsers,
140abfd1a8bSRiver Riddle   /// Get the type of a value.
141abfd1a8bSRiver Riddle   GetValueType,
14285ab413bSRiver Riddle   /// Get the types of a value range.
14385ab413bSRiver Riddle   GetValueRangeTypes,
144abfd1a8bSRiver Riddle   /// Check if a generic value is not null.
145abfd1a8bSRiver Riddle   IsNotNull,
146abfd1a8bSRiver Riddle   /// Record a successful pattern match.
147abfd1a8bSRiver Riddle   RecordMatch,
148abfd1a8bSRiver Riddle   /// Replace an operation.
149abfd1a8bSRiver Riddle   ReplaceOp,
150abfd1a8bSRiver Riddle   /// Compare an attribute with a set of constants.
151abfd1a8bSRiver Riddle   SwitchAttribute,
152abfd1a8bSRiver Riddle   /// Compare the operand count of an operation with a set of constants.
153abfd1a8bSRiver Riddle   SwitchOperandCount,
154abfd1a8bSRiver Riddle   /// Compare the name of an operation with a set of constants.
155abfd1a8bSRiver Riddle   SwitchOperationName,
156abfd1a8bSRiver Riddle   /// Compare the result count of an operation with a set of constants.
157abfd1a8bSRiver Riddle   SwitchResultCount,
158abfd1a8bSRiver Riddle   /// Compare a type with a set of constants.
159abfd1a8bSRiver Riddle   SwitchType,
16085ab413bSRiver Riddle   /// Compare a range of types with a set of constants.
16185ab413bSRiver Riddle   SwitchTypes,
162abfd1a8bSRiver Riddle };
163be0a7e9fSMehdi Amini } // namespace
164abfd1a8bSRiver Riddle 
165abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
166abfd1a8bSRiver Riddle // ByteCode Generation
167abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
168abfd1a8bSRiver Riddle 
169abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
170abfd1a8bSRiver Riddle // Generator
171abfd1a8bSRiver Riddle 
172abfd1a8bSRiver Riddle namespace {
1733eb1647aSStanislav Funiak struct ByteCodeLiveRange;
174abfd1a8bSRiver Riddle struct ByteCodeWriter;
175abfd1a8bSRiver Riddle 
1763eb1647aSStanislav Funiak /// Check if the given class `T` can be converted to an opaque pointer.
1773eb1647aSStanislav Funiak template <typename T, typename... Args>
1783eb1647aSStanislav Funiak using has_pointer_traits = decltype(std::declval<T>().getAsOpaquePointer());
1793eb1647aSStanislav Funiak 
180abfd1a8bSRiver Riddle /// This class represents the main generator for the pattern bytecode.
181abfd1a8bSRiver Riddle class Generator {
182abfd1a8bSRiver Riddle public:
183abfd1a8bSRiver Riddle   Generator(MLIRContext *ctx, std::vector<const void *> &uniquedData,
184abfd1a8bSRiver Riddle             SmallVectorImpl<ByteCodeField> &matcherByteCode,
185abfd1a8bSRiver Riddle             SmallVectorImpl<ByteCodeField> &rewriterByteCode,
186abfd1a8bSRiver Riddle             SmallVectorImpl<PDLByteCodePattern> &patterns,
187abfd1a8bSRiver Riddle             ByteCodeField &maxValueMemoryIndex,
1883eb1647aSStanislav Funiak             ByteCodeField &maxOpRangeMemoryIndex,
18985ab413bSRiver Riddle             ByteCodeField &maxTypeRangeMemoryIndex,
19085ab413bSRiver Riddle             ByteCodeField &maxValueRangeMemoryIndex,
1913eb1647aSStanislav Funiak             ByteCodeField &maxLoopLevel,
192abfd1a8bSRiver Riddle             llvm::StringMap<PDLConstraintFunction> &constraintFns,
193abfd1a8bSRiver Riddle             llvm::StringMap<PDLRewriteFunction> &rewriteFns)
194abfd1a8bSRiver Riddle       : ctx(ctx), uniquedData(uniquedData), matcherByteCode(matcherByteCode),
195abfd1a8bSRiver Riddle         rewriterByteCode(rewriterByteCode), patterns(patterns),
19685ab413bSRiver Riddle         maxValueMemoryIndex(maxValueMemoryIndex),
1973eb1647aSStanislav Funiak         maxOpRangeMemoryIndex(maxOpRangeMemoryIndex),
19885ab413bSRiver Riddle         maxTypeRangeMemoryIndex(maxTypeRangeMemoryIndex),
1993eb1647aSStanislav Funiak         maxValueRangeMemoryIndex(maxValueRangeMemoryIndex),
2003eb1647aSStanislav Funiak         maxLoopLevel(maxLoopLevel) {
201*e4853be2SMehdi Amini     for (const auto &it : llvm::enumerate(constraintFns))
202abfd1a8bSRiver Riddle       constraintToMemIndex.try_emplace(it.value().first(), it.index());
203*e4853be2SMehdi Amini     for (const auto &it : llvm::enumerate(rewriteFns))
204abfd1a8bSRiver Riddle       externalRewriterToMemIndex.try_emplace(it.value().first(), it.index());
205abfd1a8bSRiver Riddle   }
206abfd1a8bSRiver Riddle 
207abfd1a8bSRiver Riddle   /// Generate the bytecode for the given PDL interpreter module.
208abfd1a8bSRiver Riddle   void generate(ModuleOp module);
209abfd1a8bSRiver Riddle 
210abfd1a8bSRiver Riddle   /// Return the memory index to use for the given value.
211abfd1a8bSRiver Riddle   ByteCodeField &getMemIndex(Value value) {
212abfd1a8bSRiver Riddle     assert(valueToMemIndex.count(value) &&
213abfd1a8bSRiver Riddle            "expected memory index to be assigned");
214abfd1a8bSRiver Riddle     return valueToMemIndex[value];
215abfd1a8bSRiver Riddle   }
216abfd1a8bSRiver Riddle 
21785ab413bSRiver Riddle   /// Return the range memory index used to store the given range value.
21885ab413bSRiver Riddle   ByteCodeField &getRangeStorageIndex(Value value) {
21985ab413bSRiver Riddle     assert(valueToRangeIndex.count(value) &&
22085ab413bSRiver Riddle            "expected range index to be assigned");
22185ab413bSRiver Riddle     return valueToRangeIndex[value];
22285ab413bSRiver Riddle   }
22385ab413bSRiver Riddle 
224abfd1a8bSRiver Riddle   /// Return an index to use when referring to the given data that is uniqued in
225abfd1a8bSRiver Riddle   /// the MLIR context.
226abfd1a8bSRiver Riddle   template <typename T>
227abfd1a8bSRiver Riddle   std::enable_if_t<!std::is_convertible<T, Value>::value, ByteCodeField &>
228abfd1a8bSRiver Riddle   getMemIndex(T val) {
229abfd1a8bSRiver Riddle     const void *opaqueVal = val.getAsOpaquePointer();
230abfd1a8bSRiver Riddle 
231abfd1a8bSRiver Riddle     // Get or insert a reference to this value.
232abfd1a8bSRiver Riddle     auto it = uniquedDataToMemIndex.try_emplace(
233abfd1a8bSRiver Riddle         opaqueVal, maxValueMemoryIndex + uniquedData.size());
234abfd1a8bSRiver Riddle     if (it.second)
235abfd1a8bSRiver Riddle       uniquedData.push_back(opaqueVal);
236abfd1a8bSRiver Riddle     return it.first->second;
237abfd1a8bSRiver Riddle   }
238abfd1a8bSRiver Riddle 
239abfd1a8bSRiver Riddle private:
240abfd1a8bSRiver Riddle   /// Allocate memory indices for the results of operations within the matcher
241abfd1a8bSRiver Riddle   /// and rewriters.
242abfd1a8bSRiver Riddle   void allocateMemoryIndices(FuncOp matcherFunc, ModuleOp rewriterModule);
243abfd1a8bSRiver Riddle 
244abfd1a8bSRiver Riddle   /// Generate the bytecode for the given operation.
2453eb1647aSStanislav Funiak   void generate(Region *region, ByteCodeWriter &writer);
246abfd1a8bSRiver Riddle   void generate(Operation *op, ByteCodeWriter &writer);
247abfd1a8bSRiver Riddle   void generate(pdl_interp::ApplyConstraintOp op, ByteCodeWriter &writer);
248abfd1a8bSRiver Riddle   void generate(pdl_interp::ApplyRewriteOp op, ByteCodeWriter &writer);
249abfd1a8bSRiver Riddle   void generate(pdl_interp::AreEqualOp op, ByteCodeWriter &writer);
250abfd1a8bSRiver Riddle   void generate(pdl_interp::BranchOp op, ByteCodeWriter &writer);
251abfd1a8bSRiver Riddle   void generate(pdl_interp::CheckAttributeOp op, ByteCodeWriter &writer);
252abfd1a8bSRiver Riddle   void generate(pdl_interp::CheckOperandCountOp op, ByteCodeWriter &writer);
253abfd1a8bSRiver Riddle   void generate(pdl_interp::CheckOperationNameOp op, ByteCodeWriter &writer);
254abfd1a8bSRiver Riddle   void generate(pdl_interp::CheckResultCountOp op, ByteCodeWriter &writer);
255abfd1a8bSRiver Riddle   void generate(pdl_interp::CheckTypeOp op, ByteCodeWriter &writer);
25685ab413bSRiver Riddle   void generate(pdl_interp::CheckTypesOp op, ByteCodeWriter &writer);
2573eb1647aSStanislav Funiak   void generate(pdl_interp::ContinueOp op, ByteCodeWriter &writer);
258abfd1a8bSRiver Riddle   void generate(pdl_interp::CreateAttributeOp op, ByteCodeWriter &writer);
259abfd1a8bSRiver Riddle   void generate(pdl_interp::CreateOperationOp op, ByteCodeWriter &writer);
260abfd1a8bSRiver Riddle   void generate(pdl_interp::CreateTypeOp op, ByteCodeWriter &writer);
26185ab413bSRiver Riddle   void generate(pdl_interp::CreateTypesOp op, ByteCodeWriter &writer);
262abfd1a8bSRiver Riddle   void generate(pdl_interp::EraseOp op, ByteCodeWriter &writer);
2633eb1647aSStanislav Funiak   void generate(pdl_interp::ExtractOp op, ByteCodeWriter &writer);
264abfd1a8bSRiver Riddle   void generate(pdl_interp::FinalizeOp op, ByteCodeWriter &writer);
2653eb1647aSStanislav Funiak   void generate(pdl_interp::ForEachOp op, ByteCodeWriter &writer);
266abfd1a8bSRiver Riddle   void generate(pdl_interp::GetAttributeOp op, ByteCodeWriter &writer);
267abfd1a8bSRiver Riddle   void generate(pdl_interp::GetAttributeTypeOp op, ByteCodeWriter &writer);
268abfd1a8bSRiver Riddle   void generate(pdl_interp::GetDefiningOpOp op, ByteCodeWriter &writer);
269abfd1a8bSRiver Riddle   void generate(pdl_interp::GetOperandOp op, ByteCodeWriter &writer);
27085ab413bSRiver Riddle   void generate(pdl_interp::GetOperandsOp op, ByteCodeWriter &writer);
271abfd1a8bSRiver Riddle   void generate(pdl_interp::GetResultOp op, ByteCodeWriter &writer);
27285ab413bSRiver Riddle   void generate(pdl_interp::GetResultsOp op, ByteCodeWriter &writer);
2733eb1647aSStanislav Funiak   void generate(pdl_interp::GetUsersOp op, ByteCodeWriter &writer);
274abfd1a8bSRiver Riddle   void generate(pdl_interp::GetValueTypeOp op, ByteCodeWriter &writer);
2753a833a0eSRiver Riddle   void generate(pdl_interp::InferredTypesOp op, ByteCodeWriter &writer);
276abfd1a8bSRiver Riddle   void generate(pdl_interp::IsNotNullOp op, ByteCodeWriter &writer);
277abfd1a8bSRiver Riddle   void generate(pdl_interp::RecordMatchOp op, ByteCodeWriter &writer);
278abfd1a8bSRiver Riddle   void generate(pdl_interp::ReplaceOp op, ByteCodeWriter &writer);
279abfd1a8bSRiver Riddle   void generate(pdl_interp::SwitchAttributeOp op, ByteCodeWriter &writer);
280abfd1a8bSRiver Riddle   void generate(pdl_interp::SwitchTypeOp op, ByteCodeWriter &writer);
28185ab413bSRiver Riddle   void generate(pdl_interp::SwitchTypesOp op, ByteCodeWriter &writer);
282abfd1a8bSRiver Riddle   void generate(pdl_interp::SwitchOperandCountOp op, ByteCodeWriter &writer);
283abfd1a8bSRiver Riddle   void generate(pdl_interp::SwitchOperationNameOp op, ByteCodeWriter &writer);
284abfd1a8bSRiver Riddle   void generate(pdl_interp::SwitchResultCountOp op, ByteCodeWriter &writer);
285abfd1a8bSRiver Riddle 
286abfd1a8bSRiver Riddle   /// Mapping from value to its corresponding memory index.
287abfd1a8bSRiver Riddle   DenseMap<Value, ByteCodeField> valueToMemIndex;
288abfd1a8bSRiver Riddle 
28985ab413bSRiver Riddle   /// Mapping from a range value to its corresponding range storage index.
29085ab413bSRiver Riddle   DenseMap<Value, ByteCodeField> valueToRangeIndex;
29185ab413bSRiver Riddle 
292abfd1a8bSRiver Riddle   /// Mapping from the name of an externally registered rewrite to its index in
293abfd1a8bSRiver Riddle   /// the bytecode registry.
294abfd1a8bSRiver Riddle   llvm::StringMap<ByteCodeField> externalRewriterToMemIndex;
295abfd1a8bSRiver Riddle 
296abfd1a8bSRiver Riddle   /// Mapping from the name of an externally registered constraint to its index
297abfd1a8bSRiver Riddle   /// in the bytecode registry.
298abfd1a8bSRiver Riddle   llvm::StringMap<ByteCodeField> constraintToMemIndex;
299abfd1a8bSRiver Riddle 
300abfd1a8bSRiver Riddle   /// Mapping from rewriter function name to the bytecode address of the
301abfd1a8bSRiver Riddle   /// rewriter function in byte.
302abfd1a8bSRiver Riddle   llvm::StringMap<ByteCodeAddr> rewriterToAddr;
303abfd1a8bSRiver Riddle 
304abfd1a8bSRiver Riddle   /// Mapping from a uniqued storage object to its memory index within
305abfd1a8bSRiver Riddle   /// `uniquedData`.
306abfd1a8bSRiver Riddle   DenseMap<const void *, ByteCodeField> uniquedDataToMemIndex;
307abfd1a8bSRiver Riddle 
3083eb1647aSStanislav Funiak   /// The current level of the foreach loop.
3093eb1647aSStanislav Funiak   ByteCodeField curLoopLevel = 0;
3103eb1647aSStanislav Funiak 
311abfd1a8bSRiver Riddle   /// The current MLIR context.
312abfd1a8bSRiver Riddle   MLIRContext *ctx;
313abfd1a8bSRiver Riddle 
3143eb1647aSStanislav Funiak   /// Mapping from block to its address.
3153eb1647aSStanislav Funiak   DenseMap<Block *, ByteCodeAddr> blockToAddr;
3163eb1647aSStanislav Funiak 
317abfd1a8bSRiver Riddle   /// Data of the ByteCode class to be populated.
318abfd1a8bSRiver Riddle   std::vector<const void *> &uniquedData;
319abfd1a8bSRiver Riddle   SmallVectorImpl<ByteCodeField> &matcherByteCode;
320abfd1a8bSRiver Riddle   SmallVectorImpl<ByteCodeField> &rewriterByteCode;
321abfd1a8bSRiver Riddle   SmallVectorImpl<PDLByteCodePattern> &patterns;
322abfd1a8bSRiver Riddle   ByteCodeField &maxValueMemoryIndex;
3233eb1647aSStanislav Funiak   ByteCodeField &maxOpRangeMemoryIndex;
32485ab413bSRiver Riddle   ByteCodeField &maxTypeRangeMemoryIndex;
32585ab413bSRiver Riddle   ByteCodeField &maxValueRangeMemoryIndex;
3263eb1647aSStanislav Funiak   ByteCodeField &maxLoopLevel;
327abfd1a8bSRiver Riddle };
328abfd1a8bSRiver Riddle 
329abfd1a8bSRiver Riddle /// This class provides utilities for writing a bytecode stream.
330abfd1a8bSRiver Riddle struct ByteCodeWriter {
331abfd1a8bSRiver Riddle   ByteCodeWriter(SmallVectorImpl<ByteCodeField> &bytecode, Generator &generator)
332abfd1a8bSRiver Riddle       : bytecode(bytecode), generator(generator) {}
333abfd1a8bSRiver Riddle 
334abfd1a8bSRiver Riddle   /// Append a field to the bytecode.
335abfd1a8bSRiver Riddle   void append(ByteCodeField field) { bytecode.push_back(field); }
336fa20ab7bSRiver Riddle   void append(OpCode opCode) { bytecode.push_back(opCode); }
337abfd1a8bSRiver Riddle 
338abfd1a8bSRiver Riddle   /// Append an address to the bytecode.
339abfd1a8bSRiver Riddle   void append(ByteCodeAddr field) {
340abfd1a8bSRiver Riddle     static_assert((sizeof(ByteCodeAddr) / sizeof(ByteCodeField)) == 2,
341abfd1a8bSRiver Riddle                   "unexpected ByteCode address size");
342abfd1a8bSRiver Riddle 
343abfd1a8bSRiver Riddle     ByteCodeField fieldParts[2];
344abfd1a8bSRiver Riddle     std::memcpy(fieldParts, &field, sizeof(ByteCodeAddr));
345abfd1a8bSRiver Riddle     bytecode.append({fieldParts[0], fieldParts[1]});
346abfd1a8bSRiver Riddle   }
347abfd1a8bSRiver Riddle 
3483eb1647aSStanislav Funiak   /// Append a single successor to the bytecode, the exact address will need to
349abfd1a8bSRiver Riddle   /// be resolved later.
3503eb1647aSStanislav Funiak   void append(Block *successor) {
3513eb1647aSStanislav Funiak     // Add back a reference to the successor so that the address can be resolved
3523eb1647aSStanislav Funiak     // later.
353abfd1a8bSRiver Riddle     unresolvedSuccessorRefs[successor].push_back(bytecode.size());
354abfd1a8bSRiver Riddle     append(ByteCodeAddr(0));
355abfd1a8bSRiver Riddle   }
3563eb1647aSStanislav Funiak 
3573eb1647aSStanislav Funiak   /// Append a successor range to the bytecode, the exact address will need to
3583eb1647aSStanislav Funiak   /// be resolved later.
3593eb1647aSStanislav Funiak   void append(SuccessorRange successors) {
3603eb1647aSStanislav Funiak     for (Block *successor : successors)
3613eb1647aSStanislav Funiak       append(successor);
362abfd1a8bSRiver Riddle   }
363abfd1a8bSRiver Riddle 
364abfd1a8bSRiver Riddle   /// Append a range of values that will be read as generic PDLValues.
365abfd1a8bSRiver Riddle   void appendPDLValueList(OperandRange values) {
366abfd1a8bSRiver Riddle     bytecode.push_back(values.size());
36785ab413bSRiver Riddle     for (Value value : values)
36885ab413bSRiver Riddle       appendPDLValue(value);
36985ab413bSRiver Riddle   }
37085ab413bSRiver Riddle 
37185ab413bSRiver Riddle   /// Append a value as a PDLValue.
37285ab413bSRiver Riddle   void appendPDLValue(Value value) {
37385ab413bSRiver Riddle     appendPDLValueKind(value);
374abfd1a8bSRiver Riddle     append(value);
375abfd1a8bSRiver Riddle   }
37685ab413bSRiver Riddle 
37785ab413bSRiver Riddle   /// Append the PDLValue::Kind of the given value.
3783eb1647aSStanislav Funiak   void appendPDLValueKind(Value value) { appendPDLValueKind(value.getType()); }
3793eb1647aSStanislav Funiak 
3803eb1647aSStanislav Funiak   /// Append the PDLValue::Kind of the given type.
3813eb1647aSStanislav Funiak   void appendPDLValueKind(Type type) {
38285ab413bSRiver Riddle     PDLValue::Kind kind =
3833eb1647aSStanislav Funiak         TypeSwitch<Type, PDLValue::Kind>(type)
38485ab413bSRiver Riddle             .Case<pdl::AttributeType>(
38585ab413bSRiver Riddle                 [](Type) { return PDLValue::Kind::Attribute; })
38685ab413bSRiver Riddle             .Case<pdl::OperationType>(
38785ab413bSRiver Riddle                 [](Type) { return PDLValue::Kind::Operation; })
38885ab413bSRiver Riddle             .Case<pdl::RangeType>([](pdl::RangeType rangeTy) {
38985ab413bSRiver Riddle               if (rangeTy.getElementType().isa<pdl::TypeType>())
39085ab413bSRiver Riddle                 return PDLValue::Kind::TypeRange;
39185ab413bSRiver Riddle               return PDLValue::Kind::ValueRange;
39285ab413bSRiver Riddle             })
39385ab413bSRiver Riddle             .Case<pdl::TypeType>([](Type) { return PDLValue::Kind::Type; })
39485ab413bSRiver Riddle             .Case<pdl::ValueType>([](Type) { return PDLValue::Kind::Value; });
39585ab413bSRiver Riddle     bytecode.push_back(static_cast<ByteCodeField>(kind));
396abfd1a8bSRiver Riddle   }
397abfd1a8bSRiver Riddle 
398abfd1a8bSRiver Riddle   /// Append a value that will be stored in a memory slot and not inline within
399abfd1a8bSRiver Riddle   /// the bytecode.
400abfd1a8bSRiver Riddle   template <typename T>
401abfd1a8bSRiver Riddle   std::enable_if_t<llvm::is_detected<has_pointer_traits, T>::value ||
402abfd1a8bSRiver Riddle                    std::is_pointer<T>::value>
403abfd1a8bSRiver Riddle   append(T value) {
404abfd1a8bSRiver Riddle     bytecode.push_back(generator.getMemIndex(value));
405abfd1a8bSRiver Riddle   }
406abfd1a8bSRiver Riddle 
407abfd1a8bSRiver Riddle   /// Append a range of values.
408abfd1a8bSRiver Riddle   template <typename T, typename IteratorT = llvm::detail::IterOfRange<T>>
409abfd1a8bSRiver Riddle   std::enable_if_t<!llvm::is_detected<has_pointer_traits, T>::value>
410abfd1a8bSRiver Riddle   append(T range) {
411abfd1a8bSRiver Riddle     bytecode.push_back(llvm::size(range));
412abfd1a8bSRiver Riddle     for (auto it : range)
413abfd1a8bSRiver Riddle       append(it);
414abfd1a8bSRiver Riddle   }
415abfd1a8bSRiver Riddle 
416abfd1a8bSRiver Riddle   /// Append a variadic number of fields to the bytecode.
417abfd1a8bSRiver Riddle   template <typename FieldTy, typename Field2Ty, typename... FieldTys>
418abfd1a8bSRiver Riddle   void append(FieldTy field, Field2Ty field2, FieldTys... fields) {
419abfd1a8bSRiver Riddle     append(field);
420abfd1a8bSRiver Riddle     append(field2, fields...);
421abfd1a8bSRiver Riddle   }
422abfd1a8bSRiver Riddle 
423d35f1190SStanislav Funiak   /// Appends a value as a pointer, stored inline within the bytecode.
424d35f1190SStanislav Funiak   template <typename T>
425d35f1190SStanislav Funiak   std::enable_if_t<llvm::is_detected<has_pointer_traits, T>::value>
426d35f1190SStanislav Funiak   appendInline(T value) {
427d35f1190SStanislav Funiak     constexpr size_t numParts = sizeof(const void *) / sizeof(ByteCodeField);
428d35f1190SStanislav Funiak     const void *pointer = value.getAsOpaquePointer();
429d35f1190SStanislav Funiak     ByteCodeField fieldParts[numParts];
430d35f1190SStanislav Funiak     std::memcpy(fieldParts, &pointer, sizeof(const void *));
431d35f1190SStanislav Funiak     bytecode.append(fieldParts, fieldParts + numParts);
432d35f1190SStanislav Funiak   }
433d35f1190SStanislav Funiak 
434abfd1a8bSRiver Riddle   /// Successor references in the bytecode that have yet to be resolved.
435abfd1a8bSRiver Riddle   DenseMap<Block *, SmallVector<unsigned, 4>> unresolvedSuccessorRefs;
436abfd1a8bSRiver Riddle 
437abfd1a8bSRiver Riddle   /// The underlying bytecode buffer.
438abfd1a8bSRiver Riddle   SmallVectorImpl<ByteCodeField> &bytecode;
439abfd1a8bSRiver Riddle 
440abfd1a8bSRiver Riddle   /// The main generator producing PDL.
441abfd1a8bSRiver Riddle   Generator &generator;
442abfd1a8bSRiver Riddle };
44385ab413bSRiver Riddle 
44485ab413bSRiver Riddle /// This class represents a live range of PDL Interpreter values, containing
44585ab413bSRiver Riddle /// information about when values are live within a match/rewrite.
44685ab413bSRiver Riddle struct ByteCodeLiveRange {
4473eb1647aSStanislav Funiak   using Set = llvm::IntervalMap<uint64_t, char, 16>;
44885ab413bSRiver Riddle   using Allocator = Set::Allocator;
44985ab413bSRiver Riddle 
4503eb1647aSStanislav Funiak   ByteCodeLiveRange(Allocator &alloc) : liveness(new Set(alloc)) {}
45185ab413bSRiver Riddle 
45285ab413bSRiver Riddle   /// Union this live range with the one provided.
45385ab413bSRiver Riddle   void unionWith(const ByteCodeLiveRange &rhs) {
4543eb1647aSStanislav Funiak     for (auto it = rhs.liveness->begin(), e = rhs.liveness->end(); it != e;
4553eb1647aSStanislav Funiak          ++it)
4563eb1647aSStanislav Funiak       liveness->insert(it.start(), it.stop(), /*dummyValue*/ 0);
45785ab413bSRiver Riddle   }
45885ab413bSRiver Riddle 
45985ab413bSRiver Riddle   /// Returns true if this range overlaps with the one provided.
46085ab413bSRiver Riddle   bool overlaps(const ByteCodeLiveRange &rhs) const {
4613eb1647aSStanislav Funiak     return llvm::IntervalMapOverlaps<Set, Set>(*liveness, *rhs.liveness)
4623eb1647aSStanislav Funiak         .valid();
46385ab413bSRiver Riddle   }
46485ab413bSRiver Riddle 
46585ab413bSRiver Riddle   /// A map representing the ranges of the match/rewrite that a value is live in
46685ab413bSRiver Riddle   /// the interpreter.
4673eb1647aSStanislav Funiak   ///
4683eb1647aSStanislav Funiak   /// We use std::unique_ptr here, because IntervalMap does not provide a
4693eb1647aSStanislav Funiak   /// correct copy or move constructor. We can eliminate the pointer once
4703eb1647aSStanislav Funiak   /// https://reviews.llvm.org/D113240 lands.
4713eb1647aSStanislav Funiak   std::unique_ptr<llvm::IntervalMap<uint64_t, char, 16>> liveness;
4723eb1647aSStanislav Funiak 
4733eb1647aSStanislav Funiak   /// The operation range storage index for this range.
4743eb1647aSStanislav Funiak   Optional<unsigned> opRangeIndex;
47585ab413bSRiver Riddle 
47685ab413bSRiver Riddle   /// The type range storage index for this range.
47785ab413bSRiver Riddle   Optional<unsigned> typeRangeIndex;
47885ab413bSRiver Riddle 
47985ab413bSRiver Riddle   /// The value range storage index for this range.
48085ab413bSRiver Riddle   Optional<unsigned> valueRangeIndex;
48185ab413bSRiver Riddle };
482be0a7e9fSMehdi Amini } // namespace
483abfd1a8bSRiver Riddle 
484abfd1a8bSRiver Riddle void Generator::generate(ModuleOp module) {
485abfd1a8bSRiver Riddle   FuncOp matcherFunc = module.lookupSymbol<FuncOp>(
486abfd1a8bSRiver Riddle       pdl_interp::PDLInterpDialect::getMatcherFunctionName());
487abfd1a8bSRiver Riddle   ModuleOp rewriterModule = module.lookupSymbol<ModuleOp>(
488abfd1a8bSRiver Riddle       pdl_interp::PDLInterpDialect::getRewriterModuleName());
489abfd1a8bSRiver Riddle   assert(matcherFunc && rewriterModule && "invalid PDL Interpreter module");
490abfd1a8bSRiver Riddle 
491abfd1a8bSRiver Riddle   // Allocate memory indices for the results of operations within the matcher
492abfd1a8bSRiver Riddle   // and rewriters.
493abfd1a8bSRiver Riddle   allocateMemoryIndices(matcherFunc, rewriterModule);
494abfd1a8bSRiver Riddle 
495abfd1a8bSRiver Riddle   // Generate code for the rewriter functions.
496abfd1a8bSRiver Riddle   ByteCodeWriter rewriterByteCodeWriter(rewriterByteCode, *this);
497abfd1a8bSRiver Riddle   for (FuncOp rewriterFunc : rewriterModule.getOps<FuncOp>()) {
498abfd1a8bSRiver Riddle     rewriterToAddr.try_emplace(rewriterFunc.getName(), rewriterByteCode.size());
499abfd1a8bSRiver Riddle     for (Operation &op : rewriterFunc.getOps())
500abfd1a8bSRiver Riddle       generate(&op, rewriterByteCodeWriter);
501abfd1a8bSRiver Riddle   }
502abfd1a8bSRiver Riddle   assert(rewriterByteCodeWriter.unresolvedSuccessorRefs.empty() &&
503abfd1a8bSRiver Riddle          "unexpected branches in rewriter function");
504abfd1a8bSRiver Riddle 
505abfd1a8bSRiver Riddle   // Generate code for the matcher function.
506abfd1a8bSRiver Riddle   ByteCodeWriter matcherByteCodeWriter(matcherByteCode, *this);
5073eb1647aSStanislav Funiak   generate(&matcherFunc.getBody(), matcherByteCodeWriter);
508abfd1a8bSRiver Riddle 
509abfd1a8bSRiver Riddle   // Resolve successor references in the matcher.
510abfd1a8bSRiver Riddle   for (auto &it : matcherByteCodeWriter.unresolvedSuccessorRefs) {
511abfd1a8bSRiver Riddle     ByteCodeAddr addr = blockToAddr[it.first];
512abfd1a8bSRiver Riddle     for (unsigned offsetToFix : it.second)
513abfd1a8bSRiver Riddle       std::memcpy(&matcherByteCode[offsetToFix], &addr, sizeof(ByteCodeAddr));
514abfd1a8bSRiver Riddle   }
515abfd1a8bSRiver Riddle }
516abfd1a8bSRiver Riddle 
517abfd1a8bSRiver Riddle void Generator::allocateMemoryIndices(FuncOp matcherFunc,
518abfd1a8bSRiver Riddle                                       ModuleOp rewriterModule) {
519abfd1a8bSRiver Riddle   // Rewriters use simplistic allocation scheme that simply assigns an index to
520abfd1a8bSRiver Riddle   // each result.
521abfd1a8bSRiver Riddle   for (FuncOp rewriterFunc : rewriterModule.getOps<FuncOp>()) {
52285ab413bSRiver Riddle     ByteCodeField index = 0, typeRangeIndex = 0, valueRangeIndex = 0;
52385ab413bSRiver Riddle     auto processRewriterValue = [&](Value val) {
52485ab413bSRiver Riddle       valueToMemIndex.try_emplace(val, index++);
52585ab413bSRiver Riddle       if (pdl::RangeType rangeType = val.getType().dyn_cast<pdl::RangeType>()) {
52685ab413bSRiver Riddle         Type elementTy = rangeType.getElementType();
52785ab413bSRiver Riddle         if (elementTy.isa<pdl::TypeType>())
52885ab413bSRiver Riddle           valueToRangeIndex.try_emplace(val, typeRangeIndex++);
52985ab413bSRiver Riddle         else if (elementTy.isa<pdl::ValueType>())
53085ab413bSRiver Riddle           valueToRangeIndex.try_emplace(val, valueRangeIndex++);
53185ab413bSRiver Riddle       }
53285ab413bSRiver Riddle     };
53385ab413bSRiver Riddle 
534abfd1a8bSRiver Riddle     for (BlockArgument arg : rewriterFunc.getArguments())
53585ab413bSRiver Riddle       processRewriterValue(arg);
536abfd1a8bSRiver Riddle     rewriterFunc.getBody().walk([&](Operation *op) {
537abfd1a8bSRiver Riddle       for (Value result : op->getResults())
53885ab413bSRiver Riddle         processRewriterValue(result);
539abfd1a8bSRiver Riddle     });
540abfd1a8bSRiver Riddle     if (index > maxValueMemoryIndex)
541abfd1a8bSRiver Riddle       maxValueMemoryIndex = index;
54285ab413bSRiver Riddle     if (typeRangeIndex > maxTypeRangeMemoryIndex)
54385ab413bSRiver Riddle       maxTypeRangeMemoryIndex = typeRangeIndex;
54485ab413bSRiver Riddle     if (valueRangeIndex > maxValueRangeMemoryIndex)
54585ab413bSRiver Riddle       maxValueRangeMemoryIndex = valueRangeIndex;
546abfd1a8bSRiver Riddle   }
547abfd1a8bSRiver Riddle 
548abfd1a8bSRiver Riddle   // The matcher function uses a more sophisticated numbering that tries to
549abfd1a8bSRiver Riddle   // minimize the number of memory indices assigned. This is done by determining
550abfd1a8bSRiver Riddle   // a live range of the values within the matcher, then the allocation is just
551abfd1a8bSRiver Riddle   // finding the minimal number of overlapping live ranges. This is essentially
552abfd1a8bSRiver Riddle   // a simplified form of register allocation where we don't necessarily have a
553abfd1a8bSRiver Riddle   // limited number of registers, but we still want to minimize the number used.
5543eb1647aSStanislav Funiak   DenseMap<Operation *, unsigned> opToIndex;
555abfd1a8bSRiver Riddle   matcherFunc.getBody().walk([&](Operation *op) {
556abfd1a8bSRiver Riddle     opToIndex.insert(std::make_pair(op, opToIndex.size()));
557abfd1a8bSRiver Riddle   });
558abfd1a8bSRiver Riddle 
559abfd1a8bSRiver Riddle   // Liveness info for each of the defs within the matcher.
56085ab413bSRiver Riddle   ByteCodeLiveRange::Allocator allocator;
56185ab413bSRiver Riddle   DenseMap<Value, ByteCodeLiveRange> valueDefRanges;
562abfd1a8bSRiver Riddle 
563abfd1a8bSRiver Riddle   // Assign the root operation being matched to slot 0.
564abfd1a8bSRiver Riddle   BlockArgument rootOpArg = matcherFunc.getArgument(0);
565abfd1a8bSRiver Riddle   valueToMemIndex[rootOpArg] = 0;
566abfd1a8bSRiver Riddle 
567abfd1a8bSRiver Riddle   // Walk each of the blocks, computing the def interval that the value is used.
568abfd1a8bSRiver Riddle   Liveness matcherLiveness(matcherFunc);
5693eb1647aSStanislav Funiak   matcherFunc->walk([&](Block *block) {
5703eb1647aSStanislav Funiak     const LivenessBlockInfo *info = matcherLiveness.getLiveness(block);
571abfd1a8bSRiver Riddle     assert(info && "expected liveness info for block");
572abfd1a8bSRiver Riddle     auto processValue = [&](Value value, Operation *firstUseOrDef) {
573abfd1a8bSRiver Riddle       // We don't need to process the root op argument, this value is always
574abfd1a8bSRiver Riddle       // assigned to the first memory slot.
575abfd1a8bSRiver Riddle       if (value == rootOpArg)
576abfd1a8bSRiver Riddle         return;
577abfd1a8bSRiver Riddle 
578abfd1a8bSRiver Riddle       // Set indices for the range of this block that the value is used.
579abfd1a8bSRiver Riddle       auto defRangeIt = valueDefRanges.try_emplace(value, allocator).first;
5803eb1647aSStanislav Funiak       defRangeIt->second.liveness->insert(
581abfd1a8bSRiver Riddle           opToIndex[firstUseOrDef],
582abfd1a8bSRiver Riddle           opToIndex[info->getEndOperation(value, firstUseOrDef)],
583abfd1a8bSRiver Riddle           /*dummyValue*/ 0);
58485ab413bSRiver Riddle 
58585ab413bSRiver Riddle       // Check to see if this value is a range type.
58685ab413bSRiver Riddle       if (auto rangeTy = value.getType().dyn_cast<pdl::RangeType>()) {
58785ab413bSRiver Riddle         Type eleType = rangeTy.getElementType();
5883eb1647aSStanislav Funiak         if (eleType.isa<pdl::OperationType>())
5893eb1647aSStanislav Funiak           defRangeIt->second.opRangeIndex = 0;
5903eb1647aSStanislav Funiak         else if (eleType.isa<pdl::TypeType>())
59185ab413bSRiver Riddle           defRangeIt->second.typeRangeIndex = 0;
59285ab413bSRiver Riddle         else if (eleType.isa<pdl::ValueType>())
59385ab413bSRiver Riddle           defRangeIt->second.valueRangeIndex = 0;
59485ab413bSRiver Riddle       }
595abfd1a8bSRiver Riddle     };
596abfd1a8bSRiver Riddle 
597abfd1a8bSRiver Riddle     // Process the live-ins of this block.
5983eb1647aSStanislav Funiak     for (Value liveIn : info->in()) {
5993eb1647aSStanislav Funiak       // Only process the value if it has been defined in the current region.
6003eb1647aSStanislav Funiak       // Other values that span across pdl_interp.foreach will be added higher
6013eb1647aSStanislav Funiak       // up. This ensures that the we keep them alive for the entire duration
6023eb1647aSStanislav Funiak       // of the loop.
6033eb1647aSStanislav Funiak       if (liveIn.getParentRegion() == block->getParent())
6043eb1647aSStanislav Funiak         processValue(liveIn, &block->front());
6053eb1647aSStanislav Funiak     }
6063eb1647aSStanislav Funiak 
6073eb1647aSStanislav Funiak     // Process the block arguments for the entry block (those are not live-in).
6083eb1647aSStanislav Funiak     if (block->isEntryBlock()) {
6093eb1647aSStanislav Funiak       for (Value argument : block->getArguments())
6103eb1647aSStanislav Funiak         processValue(argument, &block->front());
6113eb1647aSStanislav Funiak     }
612abfd1a8bSRiver Riddle 
613abfd1a8bSRiver Riddle     // Process any new defs within this block.
6143eb1647aSStanislav Funiak     for (Operation &op : *block)
615abfd1a8bSRiver Riddle       for (Value result : op.getResults())
616abfd1a8bSRiver Riddle         processValue(result, &op);
6173eb1647aSStanislav Funiak   });
618abfd1a8bSRiver Riddle 
619abfd1a8bSRiver Riddle   // Greedily allocate memory slots using the computed def live ranges.
62085ab413bSRiver Riddle   std::vector<ByteCodeLiveRange> allocatedIndices;
6213eb1647aSStanislav Funiak 
6223eb1647aSStanislav Funiak   // The number of memory indices currently allocated (and its next value).
6233eb1647aSStanislav Funiak   // Recall that the root gets allocated memory index 0.
6243eb1647aSStanislav Funiak   ByteCodeField numIndices = 1;
6253eb1647aSStanislav Funiak 
6263eb1647aSStanislav Funiak   // The number of memory ranges of various types (and their next values).
6273eb1647aSStanislav Funiak   ByteCodeField numOpRanges = 0, numTypeRanges = 0, numValueRanges = 0;
6283eb1647aSStanislav Funiak 
629abfd1a8bSRiver Riddle   for (auto &defIt : valueDefRanges) {
630abfd1a8bSRiver Riddle     ByteCodeField &memIndex = valueToMemIndex[defIt.first];
63185ab413bSRiver Riddle     ByteCodeLiveRange &defRange = defIt.second;
632abfd1a8bSRiver Riddle 
633abfd1a8bSRiver Riddle     // Try to allocate to an existing index.
634*e4853be2SMehdi Amini     for (const auto &existingIndexIt : llvm::enumerate(allocatedIndices)) {
63585ab413bSRiver Riddle       ByteCodeLiveRange &existingRange = existingIndexIt.value();
63685ab413bSRiver Riddle       if (!defRange.overlaps(existingRange)) {
63785ab413bSRiver Riddle         existingRange.unionWith(defRange);
638abfd1a8bSRiver Riddle         memIndex = existingIndexIt.index() + 1;
63985ab413bSRiver Riddle 
6403eb1647aSStanislav Funiak         if (defRange.opRangeIndex) {
6413eb1647aSStanislav Funiak           if (!existingRange.opRangeIndex)
6423eb1647aSStanislav Funiak             existingRange.opRangeIndex = numOpRanges++;
6433eb1647aSStanislav Funiak           valueToRangeIndex[defIt.first] = *existingRange.opRangeIndex;
6443eb1647aSStanislav Funiak         } else if (defRange.typeRangeIndex) {
64585ab413bSRiver Riddle           if (!existingRange.typeRangeIndex)
64685ab413bSRiver Riddle             existingRange.typeRangeIndex = numTypeRanges++;
64785ab413bSRiver Riddle           valueToRangeIndex[defIt.first] = *existingRange.typeRangeIndex;
64885ab413bSRiver Riddle         } else if (defRange.valueRangeIndex) {
64985ab413bSRiver Riddle           if (!existingRange.valueRangeIndex)
65085ab413bSRiver Riddle             existingRange.valueRangeIndex = numValueRanges++;
65185ab413bSRiver Riddle           valueToRangeIndex[defIt.first] = *existingRange.valueRangeIndex;
65285ab413bSRiver Riddle         }
65385ab413bSRiver Riddle         break;
65485ab413bSRiver Riddle       }
655abfd1a8bSRiver Riddle     }
656abfd1a8bSRiver Riddle 
657abfd1a8bSRiver Riddle     // If no existing index could be used, add a new one.
658abfd1a8bSRiver Riddle     if (memIndex == 0) {
659abfd1a8bSRiver Riddle       allocatedIndices.emplace_back(allocator);
66085ab413bSRiver Riddle       ByteCodeLiveRange &newRange = allocatedIndices.back();
66185ab413bSRiver Riddle       newRange.unionWith(defRange);
66285ab413bSRiver Riddle 
6633eb1647aSStanislav Funiak       // Allocate an index for op/type/value ranges.
6643eb1647aSStanislav Funiak       if (defRange.opRangeIndex) {
6653eb1647aSStanislav Funiak         newRange.opRangeIndex = numOpRanges;
6663eb1647aSStanislav Funiak         valueToRangeIndex[defIt.first] = numOpRanges++;
6673eb1647aSStanislav Funiak       } else if (defRange.typeRangeIndex) {
66885ab413bSRiver Riddle         newRange.typeRangeIndex = numTypeRanges;
66985ab413bSRiver Riddle         valueToRangeIndex[defIt.first] = numTypeRanges++;
67085ab413bSRiver Riddle       } else if (defRange.valueRangeIndex) {
67185ab413bSRiver Riddle         newRange.valueRangeIndex = numValueRanges;
67285ab413bSRiver Riddle         valueToRangeIndex[defIt.first] = numValueRanges++;
67385ab413bSRiver Riddle       }
67485ab413bSRiver Riddle 
675abfd1a8bSRiver Riddle       memIndex = allocatedIndices.size();
67685ab413bSRiver Riddle       ++numIndices;
677abfd1a8bSRiver Riddle     }
678abfd1a8bSRiver Riddle   }
679abfd1a8bSRiver Riddle 
6803eb1647aSStanislav Funiak   // Print the index usage and ensure that we did not run out of index space.
6813eb1647aSStanislav Funiak   LLVM_DEBUG({
6823eb1647aSStanislav Funiak     llvm::dbgs() << "Allocated " << allocatedIndices.size() << " indices "
6833eb1647aSStanislav Funiak                  << "(down from initial " << valueDefRanges.size() << ").\n";
6843eb1647aSStanislav Funiak   });
6853eb1647aSStanislav Funiak   assert(allocatedIndices.size() <= std::numeric_limits<ByteCodeField>::max() &&
6863eb1647aSStanislav Funiak          "Ran out of memory for allocated indices");
6873eb1647aSStanislav Funiak 
688abfd1a8bSRiver Riddle   // Update the max number of indices.
68985ab413bSRiver Riddle   if (numIndices > maxValueMemoryIndex)
69085ab413bSRiver Riddle     maxValueMemoryIndex = numIndices;
6913eb1647aSStanislav Funiak   if (numOpRanges > maxOpRangeMemoryIndex)
6923eb1647aSStanislav Funiak     maxOpRangeMemoryIndex = numOpRanges;
69385ab413bSRiver Riddle   if (numTypeRanges > maxTypeRangeMemoryIndex)
69485ab413bSRiver Riddle     maxTypeRangeMemoryIndex = numTypeRanges;
69585ab413bSRiver Riddle   if (numValueRanges > maxValueRangeMemoryIndex)
69685ab413bSRiver Riddle     maxValueRangeMemoryIndex = numValueRanges;
697abfd1a8bSRiver Riddle }
698abfd1a8bSRiver Riddle 
6993eb1647aSStanislav Funiak void Generator::generate(Region *region, ByteCodeWriter &writer) {
7003eb1647aSStanislav Funiak   llvm::ReversePostOrderTraversal<Region *> rpot(region);
7013eb1647aSStanislav Funiak   for (Block *block : rpot) {
7023eb1647aSStanislav Funiak     // Keep track of where this block begins within the matcher function.
7033eb1647aSStanislav Funiak     blockToAddr.try_emplace(block, matcherByteCode.size());
7043eb1647aSStanislav Funiak     for (Operation &op : *block)
7053eb1647aSStanislav Funiak       generate(&op, writer);
7063eb1647aSStanislav Funiak   }
7073eb1647aSStanislav Funiak }
7083eb1647aSStanislav Funiak 
709abfd1a8bSRiver Riddle void Generator::generate(Operation *op, ByteCodeWriter &writer) {
710d35f1190SStanislav Funiak   LLVM_DEBUG({
711d35f1190SStanislav Funiak     // The following list must contain all the operations that do not
712d35f1190SStanislav Funiak     // produce any bytecode.
713d35f1190SStanislav Funiak     if (!isa<pdl_interp::CreateAttributeOp, pdl_interp::CreateTypeOp,
714d35f1190SStanislav Funiak              pdl_interp::InferredTypesOp>(op))
715d35f1190SStanislav Funiak       writer.appendInline(op->getLoc());
716d35f1190SStanislav Funiak   });
717abfd1a8bSRiver Riddle   TypeSwitch<Operation *>(op)
718abfd1a8bSRiver Riddle       .Case<pdl_interp::ApplyConstraintOp, pdl_interp::ApplyRewriteOp,
719abfd1a8bSRiver Riddle             pdl_interp::AreEqualOp, pdl_interp::BranchOp,
720abfd1a8bSRiver Riddle             pdl_interp::CheckAttributeOp, pdl_interp::CheckOperandCountOp,
721abfd1a8bSRiver Riddle             pdl_interp::CheckOperationNameOp, pdl_interp::CheckResultCountOp,
72285ab413bSRiver Riddle             pdl_interp::CheckTypeOp, pdl_interp::CheckTypesOp,
7233eb1647aSStanislav Funiak             pdl_interp::ContinueOp, pdl_interp::CreateAttributeOp,
7243eb1647aSStanislav Funiak             pdl_interp::CreateOperationOp, pdl_interp::CreateTypeOp,
7253eb1647aSStanislav Funiak             pdl_interp::CreateTypesOp, pdl_interp::EraseOp,
7263eb1647aSStanislav Funiak             pdl_interp::ExtractOp, pdl_interp::FinalizeOp,
7273eb1647aSStanislav Funiak             pdl_interp::ForEachOp, pdl_interp::GetAttributeOp,
7283eb1647aSStanislav Funiak             pdl_interp::GetAttributeTypeOp, pdl_interp::GetDefiningOpOp,
7293eb1647aSStanislav Funiak             pdl_interp::GetOperandOp, pdl_interp::GetOperandsOp,
7303eb1647aSStanislav Funiak             pdl_interp::GetResultOp, pdl_interp::GetResultsOp,
7313eb1647aSStanislav Funiak             pdl_interp::GetUsersOp, pdl_interp::GetValueTypeOp,
7323a833a0eSRiver Riddle             pdl_interp::InferredTypesOp, pdl_interp::IsNotNullOp,
73302c4c0d5SRiver Riddle             pdl_interp::RecordMatchOp, pdl_interp::ReplaceOp,
73402c4c0d5SRiver Riddle             pdl_interp::SwitchAttributeOp, pdl_interp::SwitchTypeOp,
73585ab413bSRiver Riddle             pdl_interp::SwitchTypesOp, pdl_interp::SwitchOperandCountOp,
73685ab413bSRiver Riddle             pdl_interp::SwitchOperationNameOp, pdl_interp::SwitchResultCountOp>(
737abfd1a8bSRiver Riddle           [&](auto interpOp) { this->generate(interpOp, writer); })
738abfd1a8bSRiver Riddle       .Default([](Operation *) {
739abfd1a8bSRiver Riddle         llvm_unreachable("unknown `pdl_interp` operation");
740abfd1a8bSRiver Riddle       });
741abfd1a8bSRiver Riddle }
742abfd1a8bSRiver Riddle 
743abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::ApplyConstraintOp op,
744abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
745abfd1a8bSRiver Riddle   assert(constraintToMemIndex.count(op.name()) &&
746abfd1a8bSRiver Riddle          "expected index for constraint function");
747abfd1a8bSRiver Riddle   writer.append(OpCode::ApplyConstraint, constraintToMemIndex[op.name()],
748abfd1a8bSRiver Riddle                 op.constParamsAttr());
749abfd1a8bSRiver Riddle   writer.appendPDLValueList(op.args());
750abfd1a8bSRiver Riddle   writer.append(op.getSuccessors());
751abfd1a8bSRiver Riddle }
752abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::ApplyRewriteOp op,
753abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
754abfd1a8bSRiver Riddle   assert(externalRewriterToMemIndex.count(op.name()) &&
755abfd1a8bSRiver Riddle          "expected index for rewrite function");
756abfd1a8bSRiver Riddle   writer.append(OpCode::ApplyRewrite, externalRewriterToMemIndex[op.name()],
75702c4c0d5SRiver Riddle                 op.constParamsAttr());
758abfd1a8bSRiver Riddle   writer.appendPDLValueList(op.args());
75902c4c0d5SRiver Riddle 
76085ab413bSRiver Riddle   ResultRange results = op.results();
76185ab413bSRiver Riddle   writer.append(ByteCodeField(results.size()));
76285ab413bSRiver Riddle   for (Value result : results) {
76385ab413bSRiver Riddle     // In debug mode we also record the expected kind of the result, so that we
76485ab413bSRiver Riddle     // can provide extra verification of the native rewrite function.
76502c4c0d5SRiver Riddle #ifndef NDEBUG
76685ab413bSRiver Riddle     writer.appendPDLValueKind(result);
76702c4c0d5SRiver Riddle #endif
76885ab413bSRiver Riddle 
76985ab413bSRiver Riddle     // Range results also need to append the range storage index.
77085ab413bSRiver Riddle     if (result.getType().isa<pdl::RangeType>())
77185ab413bSRiver Riddle       writer.append(getRangeStorageIndex(result));
77202c4c0d5SRiver Riddle     writer.append(result);
773abfd1a8bSRiver Riddle   }
77485ab413bSRiver Riddle }
775abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::AreEqualOp op, ByteCodeWriter &writer) {
77685ab413bSRiver Riddle   Value lhs = op.lhs();
77785ab413bSRiver Riddle   if (lhs.getType().isa<pdl::RangeType>()) {
77885ab413bSRiver Riddle     writer.append(OpCode::AreRangesEqual);
77985ab413bSRiver Riddle     writer.appendPDLValueKind(lhs);
78085ab413bSRiver Riddle     writer.append(op.lhs(), op.rhs(), op.getSuccessors());
78185ab413bSRiver Riddle     return;
78285ab413bSRiver Riddle   }
78385ab413bSRiver Riddle 
78485ab413bSRiver Riddle   writer.append(OpCode::AreEqual, lhs, op.rhs(), op.getSuccessors());
785abfd1a8bSRiver Riddle }
786abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::BranchOp op, ByteCodeWriter &writer) {
7878affe881SRiver Riddle   writer.append(OpCode::Branch, SuccessorRange(op.getOperation()));
788abfd1a8bSRiver Riddle }
789abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::CheckAttributeOp op,
790abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
791abfd1a8bSRiver Riddle   writer.append(OpCode::AreEqual, op.attribute(), op.constantValue(),
792abfd1a8bSRiver Riddle                 op.getSuccessors());
793abfd1a8bSRiver Riddle }
794abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::CheckOperandCountOp op,
795abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
796abfd1a8bSRiver Riddle   writer.append(OpCode::CheckOperandCount, op.operation(), op.count(),
79785ab413bSRiver Riddle                 static_cast<ByteCodeField>(op.compareAtLeast()),
798abfd1a8bSRiver Riddle                 op.getSuccessors());
799abfd1a8bSRiver Riddle }
800abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::CheckOperationNameOp op,
801abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
802abfd1a8bSRiver Riddle   writer.append(OpCode::CheckOperationName, op.operation(),
803abfd1a8bSRiver Riddle                 OperationName(op.name(), ctx), op.getSuccessors());
804abfd1a8bSRiver Riddle }
805abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::CheckResultCountOp op,
806abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
807abfd1a8bSRiver Riddle   writer.append(OpCode::CheckResultCount, op.operation(), op.count(),
80885ab413bSRiver Riddle                 static_cast<ByteCodeField>(op.compareAtLeast()),
809abfd1a8bSRiver Riddle                 op.getSuccessors());
810abfd1a8bSRiver Riddle }
811abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::CheckTypeOp op, ByteCodeWriter &writer) {
812abfd1a8bSRiver Riddle   writer.append(OpCode::AreEqual, op.value(), op.type(), op.getSuccessors());
813abfd1a8bSRiver Riddle }
81485ab413bSRiver Riddle void Generator::generate(pdl_interp::CheckTypesOp op, ByteCodeWriter &writer) {
81585ab413bSRiver Riddle   writer.append(OpCode::CheckTypes, op.value(), op.types(), op.getSuccessors());
81685ab413bSRiver Riddle }
8173eb1647aSStanislav Funiak void Generator::generate(pdl_interp::ContinueOp op, ByteCodeWriter &writer) {
8183eb1647aSStanislav Funiak   assert(curLoopLevel > 0 && "encountered pdl_interp.continue at top level");
8193eb1647aSStanislav Funiak   writer.append(OpCode::Continue, ByteCodeField(curLoopLevel - 1));
8203eb1647aSStanislav Funiak }
821abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::CreateAttributeOp op,
822abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
823abfd1a8bSRiver Riddle   // Simply repoint the memory index of the result to the constant.
824abfd1a8bSRiver Riddle   getMemIndex(op.attribute()) = getMemIndex(op.value());
825abfd1a8bSRiver Riddle }
826abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::CreateOperationOp op,
827abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
828abfd1a8bSRiver Riddle   writer.append(OpCode::CreateOperation, op.operation(),
82985ab413bSRiver Riddle                 OperationName(op.name(), ctx));
83085ab413bSRiver Riddle   writer.appendPDLValueList(op.operands());
831abfd1a8bSRiver Riddle 
832abfd1a8bSRiver Riddle   // Add the attributes.
833abfd1a8bSRiver Riddle   OperandRange attributes = op.attributes();
834abfd1a8bSRiver Riddle   writer.append(static_cast<ByteCodeField>(attributes.size()));
835195730a6SRiver Riddle   for (auto it : llvm::zip(op.attributeNames(), op.attributes()))
836195730a6SRiver Riddle     writer.append(std::get<0>(it), std::get<1>(it));
83785ab413bSRiver Riddle   writer.appendPDLValueList(op.types());
838abfd1a8bSRiver Riddle }
839abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::CreateTypeOp op, ByteCodeWriter &writer) {
840abfd1a8bSRiver Riddle   // Simply repoint the memory index of the result to the constant.
841abfd1a8bSRiver Riddle   getMemIndex(op.result()) = getMemIndex(op.value());
842abfd1a8bSRiver Riddle }
84385ab413bSRiver Riddle void Generator::generate(pdl_interp::CreateTypesOp op, ByteCodeWriter &writer) {
84485ab413bSRiver Riddle   writer.append(OpCode::CreateTypes, op.result(),
84585ab413bSRiver Riddle                 getRangeStorageIndex(op.result()), op.value());
84685ab413bSRiver Riddle }
847abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::EraseOp op, ByteCodeWriter &writer) {
848abfd1a8bSRiver Riddle   writer.append(OpCode::EraseOp, op.operation());
849abfd1a8bSRiver Riddle }
8503eb1647aSStanislav Funiak void Generator::generate(pdl_interp::ExtractOp op, ByteCodeWriter &writer) {
8513eb1647aSStanislav Funiak   OpCode opCode =
8523eb1647aSStanislav Funiak       TypeSwitch<Type, OpCode>(op.result().getType())
8533eb1647aSStanislav Funiak           .Case([](pdl::OperationType) { return OpCode::ExtractOp; })
8543eb1647aSStanislav Funiak           .Case([](pdl::ValueType) { return OpCode::ExtractValue; })
8553eb1647aSStanislav Funiak           .Case([](pdl::TypeType) { return OpCode::ExtractType; })
8563eb1647aSStanislav Funiak           .Default([](Type) -> OpCode {
8573eb1647aSStanislav Funiak             llvm_unreachable("unsupported element type");
8583eb1647aSStanislav Funiak           });
8593eb1647aSStanislav Funiak   writer.append(opCode, op.range(), op.index(), op.result());
8603eb1647aSStanislav Funiak }
861abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::FinalizeOp op, ByteCodeWriter &writer) {
862abfd1a8bSRiver Riddle   writer.append(OpCode::Finalize);
863abfd1a8bSRiver Riddle }
8643eb1647aSStanislav Funiak void Generator::generate(pdl_interp::ForEachOp op, ByteCodeWriter &writer) {
8653eb1647aSStanislav Funiak   BlockArgument arg = op.getLoopVariable();
8663eb1647aSStanislav Funiak   writer.append(OpCode::ForEach, getRangeStorageIndex(op.values()), arg);
8673eb1647aSStanislav Funiak   writer.appendPDLValueKind(arg.getType());
8683eb1647aSStanislav Funiak   writer.append(curLoopLevel, op.successor());
8693eb1647aSStanislav Funiak   ++curLoopLevel;
8703eb1647aSStanislav Funiak   if (curLoopLevel > maxLoopLevel)
8713eb1647aSStanislav Funiak     maxLoopLevel = curLoopLevel;
8723eb1647aSStanislav Funiak   generate(&op.region(), writer);
8733eb1647aSStanislav Funiak   --curLoopLevel;
8743eb1647aSStanislav Funiak }
875abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::GetAttributeOp op,
876abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
877abfd1a8bSRiver Riddle   writer.append(OpCode::GetAttribute, op.attribute(), op.operation(),
878195730a6SRiver Riddle                 op.nameAttr());
879abfd1a8bSRiver Riddle }
880abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::GetAttributeTypeOp op,
881abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
882abfd1a8bSRiver Riddle   writer.append(OpCode::GetAttributeType, op.result(), op.value());
883abfd1a8bSRiver Riddle }
884abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::GetDefiningOpOp op,
885abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
88685ab413bSRiver Riddle   writer.append(OpCode::GetDefiningOp, op.operation());
88785ab413bSRiver Riddle   writer.appendPDLValue(op.value());
888abfd1a8bSRiver Riddle }
889abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::GetOperandOp op, ByteCodeWriter &writer) {
890abfd1a8bSRiver Riddle   uint32_t index = op.index();
891abfd1a8bSRiver Riddle   if (index < 4)
892abfd1a8bSRiver Riddle     writer.append(static_cast<OpCode>(OpCode::GetOperand0 + index));
893abfd1a8bSRiver Riddle   else
894abfd1a8bSRiver Riddle     writer.append(OpCode::GetOperandN, index);
895abfd1a8bSRiver Riddle   writer.append(op.operation(), op.value());
896abfd1a8bSRiver Riddle }
89785ab413bSRiver Riddle void Generator::generate(pdl_interp::GetOperandsOp op, ByteCodeWriter &writer) {
89885ab413bSRiver Riddle   Value result = op.value();
89985ab413bSRiver Riddle   Optional<uint32_t> index = op.index();
90085ab413bSRiver Riddle   writer.append(OpCode::GetOperands,
90185ab413bSRiver Riddle                 index.getValueOr(std::numeric_limits<uint32_t>::max()),
90285ab413bSRiver Riddle                 op.operation());
90385ab413bSRiver Riddle   if (result.getType().isa<pdl::RangeType>())
90485ab413bSRiver Riddle     writer.append(getRangeStorageIndex(result));
90585ab413bSRiver Riddle   else
90685ab413bSRiver Riddle     writer.append(std::numeric_limits<ByteCodeField>::max());
90785ab413bSRiver Riddle   writer.append(result);
90885ab413bSRiver Riddle }
909abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::GetResultOp op, ByteCodeWriter &writer) {
910abfd1a8bSRiver Riddle   uint32_t index = op.index();
911abfd1a8bSRiver Riddle   if (index < 4)
912abfd1a8bSRiver Riddle     writer.append(static_cast<OpCode>(OpCode::GetResult0 + index));
913abfd1a8bSRiver Riddle   else
914abfd1a8bSRiver Riddle     writer.append(OpCode::GetResultN, index);
915abfd1a8bSRiver Riddle   writer.append(op.operation(), op.value());
916abfd1a8bSRiver Riddle }
91785ab413bSRiver Riddle void Generator::generate(pdl_interp::GetResultsOp op, ByteCodeWriter &writer) {
91885ab413bSRiver Riddle   Value result = op.value();
91985ab413bSRiver Riddle   Optional<uint32_t> index = op.index();
92085ab413bSRiver Riddle   writer.append(OpCode::GetResults,
92185ab413bSRiver Riddle                 index.getValueOr(std::numeric_limits<uint32_t>::max()),
92285ab413bSRiver Riddle                 op.operation());
92385ab413bSRiver Riddle   if (result.getType().isa<pdl::RangeType>())
92485ab413bSRiver Riddle     writer.append(getRangeStorageIndex(result));
92585ab413bSRiver Riddle   else
92685ab413bSRiver Riddle     writer.append(std::numeric_limits<ByteCodeField>::max());
92785ab413bSRiver Riddle   writer.append(result);
92885ab413bSRiver Riddle }
9293eb1647aSStanislav Funiak void Generator::generate(pdl_interp::GetUsersOp op, ByteCodeWriter &writer) {
9303eb1647aSStanislav Funiak   Value operations = op.operations();
9313eb1647aSStanislav Funiak   ByteCodeField rangeIndex = getRangeStorageIndex(operations);
9323eb1647aSStanislav Funiak   writer.append(OpCode::GetUsers, operations, rangeIndex);
9333eb1647aSStanislav Funiak   writer.appendPDLValue(op.value());
9343eb1647aSStanislav Funiak }
935abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::GetValueTypeOp op,
936abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
93785ab413bSRiver Riddle   if (op.getType().isa<pdl::RangeType>()) {
93885ab413bSRiver Riddle     Value result = op.result();
93985ab413bSRiver Riddle     writer.append(OpCode::GetValueRangeTypes, result,
94085ab413bSRiver Riddle                   getRangeStorageIndex(result), op.value());
94185ab413bSRiver Riddle   } else {
942abfd1a8bSRiver Riddle     writer.append(OpCode::GetValueType, op.result(), op.value());
943abfd1a8bSRiver Riddle   }
94485ab413bSRiver Riddle }
94585ab413bSRiver Riddle 
9463a833a0eSRiver Riddle void Generator::generate(pdl_interp::InferredTypesOp op,
947abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
9483a833a0eSRiver Riddle   // InferType maps to a null type as a marker for inferring result types.
949abfd1a8bSRiver Riddle   getMemIndex(op.type()) = getMemIndex(Type());
950abfd1a8bSRiver Riddle }
951abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::IsNotNullOp op, ByteCodeWriter &writer) {
952abfd1a8bSRiver Riddle   writer.append(OpCode::IsNotNull, op.value(), op.getSuccessors());
953abfd1a8bSRiver Riddle }
954abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::RecordMatchOp op, ByteCodeWriter &writer) {
955abfd1a8bSRiver Riddle   ByteCodeField patternIndex = patterns.size();
956abfd1a8bSRiver Riddle   patterns.emplace_back(PDLByteCodePattern::create(
95741d4aa7dSChris Lattner       op, rewriterToAddr[op.rewriter().getLeafReference().getValue()]));
9588affe881SRiver Riddle   writer.append(OpCode::RecordMatch, patternIndex,
95985ab413bSRiver Riddle                 SuccessorRange(op.getOperation()), op.matchedOps());
96085ab413bSRiver Riddle   writer.appendPDLValueList(op.inputs());
961abfd1a8bSRiver Riddle }
962abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::ReplaceOp op, ByteCodeWriter &writer) {
96385ab413bSRiver Riddle   writer.append(OpCode::ReplaceOp, op.operation());
96485ab413bSRiver Riddle   writer.appendPDLValueList(op.replValues());
965abfd1a8bSRiver Riddle }
966abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::SwitchAttributeOp op,
967abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
968abfd1a8bSRiver Riddle   writer.append(OpCode::SwitchAttribute, op.attribute(), op.caseValuesAttr(),
969abfd1a8bSRiver Riddle                 op.getSuccessors());
970abfd1a8bSRiver Riddle }
971abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::SwitchOperandCountOp op,
972abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
973abfd1a8bSRiver Riddle   writer.append(OpCode::SwitchOperandCount, op.operation(), op.caseValuesAttr(),
974abfd1a8bSRiver Riddle                 op.getSuccessors());
975abfd1a8bSRiver Riddle }
976abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::SwitchOperationNameOp op,
977abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
978abfd1a8bSRiver Riddle   auto cases = llvm::map_range(op.caseValuesAttr(), [&](Attribute attr) {
979abfd1a8bSRiver Riddle     return OperationName(attr.cast<StringAttr>().getValue(), ctx);
980abfd1a8bSRiver Riddle   });
981abfd1a8bSRiver Riddle   writer.append(OpCode::SwitchOperationName, op.operation(), cases,
982abfd1a8bSRiver Riddle                 op.getSuccessors());
983abfd1a8bSRiver Riddle }
984abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::SwitchResultCountOp op,
985abfd1a8bSRiver Riddle                          ByteCodeWriter &writer) {
986abfd1a8bSRiver Riddle   writer.append(OpCode::SwitchResultCount, op.operation(), op.caseValuesAttr(),
987abfd1a8bSRiver Riddle                 op.getSuccessors());
988abfd1a8bSRiver Riddle }
989abfd1a8bSRiver Riddle void Generator::generate(pdl_interp::SwitchTypeOp op, ByteCodeWriter &writer) {
990abfd1a8bSRiver Riddle   writer.append(OpCode::SwitchType, op.value(), op.caseValuesAttr(),
991abfd1a8bSRiver Riddle                 op.getSuccessors());
992abfd1a8bSRiver Riddle }
99385ab413bSRiver Riddle void Generator::generate(pdl_interp::SwitchTypesOp op, ByteCodeWriter &writer) {
99485ab413bSRiver Riddle   writer.append(OpCode::SwitchTypes, op.value(), op.caseValuesAttr(),
99585ab413bSRiver Riddle                 op.getSuccessors());
99685ab413bSRiver Riddle }
997abfd1a8bSRiver Riddle 
998abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
999abfd1a8bSRiver Riddle // PDLByteCode
1000abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
1001abfd1a8bSRiver Riddle 
1002abfd1a8bSRiver Riddle PDLByteCode::PDLByteCode(ModuleOp module,
1003abfd1a8bSRiver Riddle                          llvm::StringMap<PDLConstraintFunction> constraintFns,
1004abfd1a8bSRiver Riddle                          llvm::StringMap<PDLRewriteFunction> rewriteFns) {
1005abfd1a8bSRiver Riddle   Generator generator(module.getContext(), uniquedData, matcherByteCode,
1006abfd1a8bSRiver Riddle                       rewriterByteCode, patterns, maxValueMemoryIndex,
10073eb1647aSStanislav Funiak                       maxOpRangeCount, maxTypeRangeCount, maxValueRangeCount,
10083eb1647aSStanislav Funiak                       maxLoopLevel, constraintFns, rewriteFns);
1009abfd1a8bSRiver Riddle   generator.generate(module);
1010abfd1a8bSRiver Riddle 
1011abfd1a8bSRiver Riddle   // Initialize the external functions.
1012abfd1a8bSRiver Riddle   for (auto &it : constraintFns)
1013abfd1a8bSRiver Riddle     constraintFunctions.push_back(std::move(it.second));
1014abfd1a8bSRiver Riddle   for (auto &it : rewriteFns)
1015abfd1a8bSRiver Riddle     rewriteFunctions.push_back(std::move(it.second));
1016abfd1a8bSRiver Riddle }
1017abfd1a8bSRiver Riddle 
1018abfd1a8bSRiver Riddle /// Initialize the given state such that it can be used to execute the current
1019abfd1a8bSRiver Riddle /// bytecode.
1020abfd1a8bSRiver Riddle void PDLByteCode::initializeMutableState(PDLByteCodeMutableState &state) const {
1021abfd1a8bSRiver Riddle   state.memory.resize(maxValueMemoryIndex, nullptr);
10223eb1647aSStanislav Funiak   state.opRangeMemory.resize(maxOpRangeCount);
102385ab413bSRiver Riddle   state.typeRangeMemory.resize(maxTypeRangeCount, TypeRange());
102485ab413bSRiver Riddle   state.valueRangeMemory.resize(maxValueRangeCount, ValueRange());
10253eb1647aSStanislav Funiak   state.loopIndex.resize(maxLoopLevel, 0);
1026abfd1a8bSRiver Riddle   state.currentPatternBenefits.reserve(patterns.size());
1027abfd1a8bSRiver Riddle   for (const PDLByteCodePattern &pattern : patterns)
1028abfd1a8bSRiver Riddle     state.currentPatternBenefits.push_back(pattern.getBenefit());
1029abfd1a8bSRiver Riddle }
1030abfd1a8bSRiver Riddle 
1031abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
1032abfd1a8bSRiver Riddle // ByteCode Execution
1033abfd1a8bSRiver Riddle 
1034abfd1a8bSRiver Riddle namespace {
1035abfd1a8bSRiver Riddle /// This class provides support for executing a bytecode stream.
1036abfd1a8bSRiver Riddle class ByteCodeExecutor {
1037abfd1a8bSRiver Riddle public:
103885ab413bSRiver Riddle   ByteCodeExecutor(
103985ab413bSRiver Riddle       const ByteCodeField *curCodeIt, MutableArrayRef<const void *> memory,
10403eb1647aSStanislav Funiak       MutableArrayRef<llvm::OwningArrayRef<Operation *>> opRangeMemory,
104185ab413bSRiver Riddle       MutableArrayRef<TypeRange> typeRangeMemory,
104285ab413bSRiver Riddle       std::vector<llvm::OwningArrayRef<Type>> &allocatedTypeRangeMemory,
104385ab413bSRiver Riddle       MutableArrayRef<ValueRange> valueRangeMemory,
104485ab413bSRiver Riddle       std::vector<llvm::OwningArrayRef<Value>> &allocatedValueRangeMemory,
10453eb1647aSStanislav Funiak       MutableArrayRef<unsigned> loopIndex, ArrayRef<const void *> uniquedMemory,
10463eb1647aSStanislav Funiak       ArrayRef<ByteCodeField> code,
1047abfd1a8bSRiver Riddle       ArrayRef<PatternBenefit> currentPatternBenefits,
1048abfd1a8bSRiver Riddle       ArrayRef<PDLByteCodePattern> patterns,
1049abfd1a8bSRiver Riddle       ArrayRef<PDLConstraintFunction> constraintFunctions,
1050abfd1a8bSRiver Riddle       ArrayRef<PDLRewriteFunction> rewriteFunctions)
10513eb1647aSStanislav Funiak       : curCodeIt(curCodeIt), memory(memory), opRangeMemory(opRangeMemory),
10523eb1647aSStanislav Funiak         typeRangeMemory(typeRangeMemory),
105385ab413bSRiver Riddle         allocatedTypeRangeMemory(allocatedTypeRangeMemory),
105485ab413bSRiver Riddle         valueRangeMemory(valueRangeMemory),
105585ab413bSRiver Riddle         allocatedValueRangeMemory(allocatedValueRangeMemory),
10563eb1647aSStanislav Funiak         loopIndex(loopIndex), uniquedMemory(uniquedMemory), code(code),
105785ab413bSRiver Riddle         currentPatternBenefits(currentPatternBenefits), patterns(patterns),
105885ab413bSRiver Riddle         constraintFunctions(constraintFunctions),
105902c4c0d5SRiver Riddle         rewriteFunctions(rewriteFunctions) {}
1060abfd1a8bSRiver Riddle 
1061abfd1a8bSRiver Riddle   /// Start executing the code at the current bytecode index. `matches` is an
1062abfd1a8bSRiver Riddle   /// optional field provided when this function is executed in a matching
1063abfd1a8bSRiver Riddle   /// context.
1064abfd1a8bSRiver Riddle   void execute(PatternRewriter &rewriter,
1065abfd1a8bSRiver Riddle                SmallVectorImpl<PDLByteCode::MatchResult> *matches = nullptr,
1066abfd1a8bSRiver Riddle                Optional<Location> mainRewriteLoc = {});
1067abfd1a8bSRiver Riddle 
1068abfd1a8bSRiver Riddle private:
1069154cabe7SRiver Riddle   /// Internal implementation of executing each of the bytecode commands.
1070154cabe7SRiver Riddle   void executeApplyConstraint(PatternRewriter &rewriter);
1071154cabe7SRiver Riddle   void executeApplyRewrite(PatternRewriter &rewriter);
1072154cabe7SRiver Riddle   void executeAreEqual();
107385ab413bSRiver Riddle   void executeAreRangesEqual();
1074154cabe7SRiver Riddle   void executeBranch();
1075154cabe7SRiver Riddle   void executeCheckOperandCount();
1076154cabe7SRiver Riddle   void executeCheckOperationName();
1077154cabe7SRiver Riddle   void executeCheckResultCount();
107885ab413bSRiver Riddle   void executeCheckTypes();
10793eb1647aSStanislav Funiak   void executeContinue();
1080154cabe7SRiver Riddle   void executeCreateOperation(PatternRewriter &rewriter,
1081154cabe7SRiver Riddle                               Location mainRewriteLoc);
108285ab413bSRiver Riddle   void executeCreateTypes();
1083154cabe7SRiver Riddle   void executeEraseOp(PatternRewriter &rewriter);
10843eb1647aSStanislav Funiak   template <typename T, typename Range, PDLValue::Kind kind>
10853eb1647aSStanislav Funiak   void executeExtract();
10863eb1647aSStanislav Funiak   void executeFinalize();
10873eb1647aSStanislav Funiak   void executeForEach();
1088154cabe7SRiver Riddle   void executeGetAttribute();
1089154cabe7SRiver Riddle   void executeGetAttributeType();
1090154cabe7SRiver Riddle   void executeGetDefiningOp();
1091154cabe7SRiver Riddle   void executeGetOperand(unsigned index);
109285ab413bSRiver Riddle   void executeGetOperands();
1093154cabe7SRiver Riddle   void executeGetResult(unsigned index);
109485ab413bSRiver Riddle   void executeGetResults();
10953eb1647aSStanislav Funiak   void executeGetUsers();
1096154cabe7SRiver Riddle   void executeGetValueType();
109785ab413bSRiver Riddle   void executeGetValueRangeTypes();
1098154cabe7SRiver Riddle   void executeIsNotNull();
1099154cabe7SRiver Riddle   void executeRecordMatch(PatternRewriter &rewriter,
1100154cabe7SRiver Riddle                           SmallVectorImpl<PDLByteCode::MatchResult> &matches);
1101154cabe7SRiver Riddle   void executeReplaceOp(PatternRewriter &rewriter);
1102154cabe7SRiver Riddle   void executeSwitchAttribute();
1103154cabe7SRiver Riddle   void executeSwitchOperandCount();
1104154cabe7SRiver Riddle   void executeSwitchOperationName();
1105154cabe7SRiver Riddle   void executeSwitchResultCount();
1106154cabe7SRiver Riddle   void executeSwitchType();
110785ab413bSRiver Riddle   void executeSwitchTypes();
1108154cabe7SRiver Riddle 
11093eb1647aSStanislav Funiak   /// Pushes a code iterator to the stack.
11103eb1647aSStanislav Funiak   void pushCodeIt(const ByteCodeField *it) { resumeCodeIt.push_back(it); }
11113eb1647aSStanislav Funiak 
11123eb1647aSStanislav Funiak   /// Pops a code iterator from the stack, returning true on success.
11133eb1647aSStanislav Funiak   void popCodeIt() {
11143eb1647aSStanislav Funiak     assert(!resumeCodeIt.empty() && "attempt to pop code off empty stack");
11153eb1647aSStanislav Funiak     curCodeIt = resumeCodeIt.back();
11163eb1647aSStanislav Funiak     resumeCodeIt.pop_back();
11173eb1647aSStanislav Funiak   }
11183eb1647aSStanislav Funiak 
1119d35f1190SStanislav Funiak   /// Return the bytecode iterator at the start of the current op code.
1120d35f1190SStanislav Funiak   const ByteCodeField *getPrevCodeIt() const {
1121d35f1190SStanislav Funiak     LLVM_DEBUG({
1122d35f1190SStanislav Funiak       // Account for the op code and the Location stored inline.
1123d35f1190SStanislav Funiak       return curCodeIt - 1 - sizeof(const void *) / sizeof(ByteCodeField);
1124d35f1190SStanislav Funiak     });
1125d35f1190SStanislav Funiak 
1126d35f1190SStanislav Funiak     // Account for the op code only.
1127d35f1190SStanislav Funiak     return curCodeIt - 1;
1128d35f1190SStanislav Funiak   }
1129d35f1190SStanislav Funiak 
1130abfd1a8bSRiver Riddle   /// Read a value from the bytecode buffer, optionally skipping a certain
1131abfd1a8bSRiver Riddle   /// number of prefix values. These methods always update the buffer to point
1132abfd1a8bSRiver Riddle   /// to the next field after the read data.
1133abfd1a8bSRiver Riddle   template <typename T = ByteCodeField>
1134abfd1a8bSRiver Riddle   T read(size_t skipN = 0) {
1135abfd1a8bSRiver Riddle     curCodeIt += skipN;
1136abfd1a8bSRiver Riddle     return readImpl<T>();
1137abfd1a8bSRiver Riddle   }
1138abfd1a8bSRiver Riddle   ByteCodeField read(size_t skipN = 0) { return read<ByteCodeField>(skipN); }
1139abfd1a8bSRiver Riddle 
1140abfd1a8bSRiver Riddle   /// Read a list of values from the bytecode buffer.
1141abfd1a8bSRiver Riddle   template <typename ValueT, typename T>
1142abfd1a8bSRiver Riddle   void readList(SmallVectorImpl<T> &list) {
1143abfd1a8bSRiver Riddle     list.clear();
1144abfd1a8bSRiver Riddle     for (unsigned i = 0, e = read(); i != e; ++i)
1145abfd1a8bSRiver Riddle       list.push_back(read<ValueT>());
1146abfd1a8bSRiver Riddle   }
1147abfd1a8bSRiver Riddle 
114885ab413bSRiver Riddle   /// Read a list of values from the bytecode buffer. The values may be encoded
114985ab413bSRiver Riddle   /// as either Value or ValueRange elements.
115085ab413bSRiver Riddle   void readValueList(SmallVectorImpl<Value> &list) {
115185ab413bSRiver Riddle     for (unsigned i = 0, e = read(); i != e; ++i) {
115285ab413bSRiver Riddle       if (read<PDLValue::Kind>() == PDLValue::Kind::Value) {
115385ab413bSRiver Riddle         list.push_back(read<Value>());
115485ab413bSRiver Riddle       } else {
115585ab413bSRiver Riddle         ValueRange *values = read<ValueRange *>();
115685ab413bSRiver Riddle         list.append(values->begin(), values->end());
115785ab413bSRiver Riddle       }
115885ab413bSRiver Riddle     }
115985ab413bSRiver Riddle   }
116085ab413bSRiver Riddle 
1161d35f1190SStanislav Funiak   /// Read a value stored inline as a pointer.
1162d35f1190SStanislav Funiak   template <typename T>
1163d35f1190SStanislav Funiak   std::enable_if_t<llvm::is_detected<has_pointer_traits, T>::value, T>
1164d35f1190SStanislav Funiak   readInline() {
1165d35f1190SStanislav Funiak     const void *pointer;
1166d35f1190SStanislav Funiak     std::memcpy(&pointer, curCodeIt, sizeof(const void *));
1167d35f1190SStanislav Funiak     curCodeIt += sizeof(const void *) / sizeof(ByteCodeField);
1168d35f1190SStanislav Funiak     return T::getFromOpaquePointer(pointer);
1169d35f1190SStanislav Funiak   }
1170d35f1190SStanislav Funiak 
1171abfd1a8bSRiver Riddle   /// Jump to a specific successor based on a predicate value.
1172abfd1a8bSRiver Riddle   void selectJump(bool isTrue) { selectJump(size_t(isTrue ? 0 : 1)); }
1173abfd1a8bSRiver Riddle   /// Jump to a specific successor based on a destination index.
1174abfd1a8bSRiver Riddle   void selectJump(size_t destIndex) {
1175abfd1a8bSRiver Riddle     curCodeIt = &code[read<ByteCodeAddr>(destIndex * 2)];
1176abfd1a8bSRiver Riddle   }
1177abfd1a8bSRiver Riddle 
1178abfd1a8bSRiver Riddle   /// Handle a switch operation with the provided value and cases.
117985ab413bSRiver Riddle   template <typename T, typename RangeT, typename Comparator = std::equal_to<T>>
118085ab413bSRiver Riddle   void handleSwitch(const T &value, RangeT &&cases, Comparator cmp = {}) {
1181abfd1a8bSRiver Riddle     LLVM_DEBUG({
1182abfd1a8bSRiver Riddle       llvm::dbgs() << "  * Value: " << value << "\n"
1183abfd1a8bSRiver Riddle                    << "  * Cases: ";
1184abfd1a8bSRiver Riddle       llvm::interleaveComma(cases, llvm::dbgs());
1185154cabe7SRiver Riddle       llvm::dbgs() << "\n";
1186abfd1a8bSRiver Riddle     });
1187abfd1a8bSRiver Riddle 
1188abfd1a8bSRiver Riddle     // Check to see if the attribute value is within the case list. Jump to
1189abfd1a8bSRiver Riddle     // the correct successor index based on the result.
1190f80b6304SRiver Riddle     for (auto it = cases.begin(), e = cases.end(); it != e; ++it)
119185ab413bSRiver Riddle       if (cmp(*it, value))
1192f80b6304SRiver Riddle         return selectJump(size_t((it - cases.begin()) + 1));
1193f80b6304SRiver Riddle     selectJump(size_t(0));
1194abfd1a8bSRiver Riddle   }
1195abfd1a8bSRiver Riddle 
11963eb1647aSStanislav Funiak   /// Store a pointer to memory.
11973eb1647aSStanislav Funiak   void storeToMemory(unsigned index, const void *value) {
11983eb1647aSStanislav Funiak     memory[index] = value;
11993eb1647aSStanislav Funiak   }
12003eb1647aSStanislav Funiak 
12013eb1647aSStanislav Funiak   /// Store a value to memory as an opaque pointer.
12023eb1647aSStanislav Funiak   template <typename T>
12033eb1647aSStanislav Funiak   std::enable_if_t<llvm::is_detected<has_pointer_traits, T>::value>
12043eb1647aSStanislav Funiak   storeToMemory(unsigned index, T value) {
12053eb1647aSStanislav Funiak     memory[index] = value.getAsOpaquePointer();
12063eb1647aSStanislav Funiak   }
12073eb1647aSStanislav Funiak 
1208abfd1a8bSRiver Riddle   /// Internal implementation of reading various data types from the bytecode
1209abfd1a8bSRiver Riddle   /// stream.
1210abfd1a8bSRiver Riddle   template <typename T>
1211abfd1a8bSRiver Riddle   const void *readFromMemory() {
1212abfd1a8bSRiver Riddle     size_t index = *curCodeIt++;
1213abfd1a8bSRiver Riddle 
1214abfd1a8bSRiver Riddle     // If this type is an SSA value, it can only be stored in non-const memory.
121585ab413bSRiver Riddle     if (llvm::is_one_of<T, Operation *, TypeRange *, ValueRange *,
121685ab413bSRiver Riddle                         Value>::value ||
121785ab413bSRiver Riddle         index < memory.size())
1218abfd1a8bSRiver Riddle       return memory[index];
1219abfd1a8bSRiver Riddle 
1220abfd1a8bSRiver Riddle     // Otherwise, if this index is not inbounds it is uniqued.
1221abfd1a8bSRiver Riddle     return uniquedMemory[index - memory.size()];
1222abfd1a8bSRiver Riddle   }
1223abfd1a8bSRiver Riddle   template <typename T>
1224abfd1a8bSRiver Riddle   std::enable_if_t<std::is_pointer<T>::value, T> readImpl() {
1225abfd1a8bSRiver Riddle     return reinterpret_cast<T>(const_cast<void *>(readFromMemory<T>()));
1226abfd1a8bSRiver Riddle   }
1227abfd1a8bSRiver Riddle   template <typename T>
1228abfd1a8bSRiver Riddle   std::enable_if_t<std::is_class<T>::value && !std::is_same<PDLValue, T>::value,
1229abfd1a8bSRiver Riddle                    T>
1230abfd1a8bSRiver Riddle   readImpl() {
1231abfd1a8bSRiver Riddle     return T(T::getFromOpaquePointer(readFromMemory<T>()));
1232abfd1a8bSRiver Riddle   }
1233abfd1a8bSRiver Riddle   template <typename T>
1234abfd1a8bSRiver Riddle   std::enable_if_t<std::is_same<PDLValue, T>::value, T> readImpl() {
123585ab413bSRiver Riddle     switch (read<PDLValue::Kind>()) {
123685ab413bSRiver Riddle     case PDLValue::Kind::Attribute:
1237abfd1a8bSRiver Riddle       return read<Attribute>();
123885ab413bSRiver Riddle     case PDLValue::Kind::Operation:
1239abfd1a8bSRiver Riddle       return read<Operation *>();
124085ab413bSRiver Riddle     case PDLValue::Kind::Type:
1241abfd1a8bSRiver Riddle       return read<Type>();
124285ab413bSRiver Riddle     case PDLValue::Kind::Value:
1243abfd1a8bSRiver Riddle       return read<Value>();
124485ab413bSRiver Riddle     case PDLValue::Kind::TypeRange:
124585ab413bSRiver Riddle       return read<TypeRange *>();
124685ab413bSRiver Riddle     case PDLValue::Kind::ValueRange:
124785ab413bSRiver Riddle       return read<ValueRange *>();
1248abfd1a8bSRiver Riddle     }
124985ab413bSRiver Riddle     llvm_unreachable("unhandled PDLValue::Kind");
1250abfd1a8bSRiver Riddle   }
1251abfd1a8bSRiver Riddle   template <typename T>
1252abfd1a8bSRiver Riddle   std::enable_if_t<std::is_same<T, ByteCodeAddr>::value, T> readImpl() {
1253abfd1a8bSRiver Riddle     static_assert((sizeof(ByteCodeAddr) / sizeof(ByteCodeField)) == 2,
1254abfd1a8bSRiver Riddle                   "unexpected ByteCode address size");
1255abfd1a8bSRiver Riddle     ByteCodeAddr result;
1256abfd1a8bSRiver Riddle     std::memcpy(&result, curCodeIt, sizeof(ByteCodeAddr));
1257abfd1a8bSRiver Riddle     curCodeIt += 2;
1258abfd1a8bSRiver Riddle     return result;
1259abfd1a8bSRiver Riddle   }
1260abfd1a8bSRiver Riddle   template <typename T>
1261abfd1a8bSRiver Riddle   std::enable_if_t<std::is_same<T, ByteCodeField>::value, T> readImpl() {
1262abfd1a8bSRiver Riddle     return *curCodeIt++;
1263abfd1a8bSRiver Riddle   }
126485ab413bSRiver Riddle   template <typename T>
126585ab413bSRiver Riddle   std::enable_if_t<std::is_same<T, PDLValue::Kind>::value, T> readImpl() {
126685ab413bSRiver Riddle     return static_cast<PDLValue::Kind>(readImpl<ByteCodeField>());
126785ab413bSRiver Riddle   }
1268abfd1a8bSRiver Riddle 
1269abfd1a8bSRiver Riddle   /// The underlying bytecode buffer.
1270abfd1a8bSRiver Riddle   const ByteCodeField *curCodeIt;
1271abfd1a8bSRiver Riddle 
12723eb1647aSStanislav Funiak   /// The stack of bytecode positions at which to resume operation.
12733eb1647aSStanislav Funiak   SmallVector<const ByteCodeField *> resumeCodeIt;
12743eb1647aSStanislav Funiak 
1275abfd1a8bSRiver Riddle   /// The current execution memory.
1276abfd1a8bSRiver Riddle   MutableArrayRef<const void *> memory;
12773eb1647aSStanislav Funiak   MutableArrayRef<OwningOpRange> opRangeMemory;
127885ab413bSRiver Riddle   MutableArrayRef<TypeRange> typeRangeMemory;
127985ab413bSRiver Riddle   std::vector<llvm::OwningArrayRef<Type>> &allocatedTypeRangeMemory;
128085ab413bSRiver Riddle   MutableArrayRef<ValueRange> valueRangeMemory;
128185ab413bSRiver Riddle   std::vector<llvm::OwningArrayRef<Value>> &allocatedValueRangeMemory;
1282abfd1a8bSRiver Riddle 
12833eb1647aSStanislav Funiak   /// The current loop indices.
12843eb1647aSStanislav Funiak   MutableArrayRef<unsigned> loopIndex;
12853eb1647aSStanislav Funiak 
1286abfd1a8bSRiver Riddle   /// References to ByteCode data necessary for execution.
1287abfd1a8bSRiver Riddle   ArrayRef<const void *> uniquedMemory;
1288abfd1a8bSRiver Riddle   ArrayRef<ByteCodeField> code;
1289abfd1a8bSRiver Riddle   ArrayRef<PatternBenefit> currentPatternBenefits;
1290abfd1a8bSRiver Riddle   ArrayRef<PDLByteCodePattern> patterns;
1291abfd1a8bSRiver Riddle   ArrayRef<PDLConstraintFunction> constraintFunctions;
1292abfd1a8bSRiver Riddle   ArrayRef<PDLRewriteFunction> rewriteFunctions;
1293abfd1a8bSRiver Riddle };
129402c4c0d5SRiver Riddle 
129502c4c0d5SRiver Riddle /// This class is an instantiation of the PDLResultList that provides access to
129602c4c0d5SRiver Riddle /// the returned results. This API is not on `PDLResultList` to avoid
129702c4c0d5SRiver Riddle /// overexposing access to information specific solely to the ByteCode.
129802c4c0d5SRiver Riddle class ByteCodeRewriteResultList : public PDLResultList {
129902c4c0d5SRiver Riddle public:
130085ab413bSRiver Riddle   ByteCodeRewriteResultList(unsigned maxNumResults)
130185ab413bSRiver Riddle       : PDLResultList(maxNumResults) {}
130285ab413bSRiver Riddle 
130302c4c0d5SRiver Riddle   /// Return the list of PDL results.
130402c4c0d5SRiver Riddle   MutableArrayRef<PDLValue> getResults() { return results; }
130585ab413bSRiver Riddle 
130685ab413bSRiver Riddle   /// Return the type ranges allocated by this list.
130785ab413bSRiver Riddle   MutableArrayRef<llvm::OwningArrayRef<Type>> getAllocatedTypeRanges() {
130885ab413bSRiver Riddle     return allocatedTypeRanges;
130985ab413bSRiver Riddle   }
131085ab413bSRiver Riddle 
131185ab413bSRiver Riddle   /// Return the value ranges allocated by this list.
131285ab413bSRiver Riddle   MutableArrayRef<llvm::OwningArrayRef<Value>> getAllocatedValueRanges() {
131385ab413bSRiver Riddle     return allocatedValueRanges;
131485ab413bSRiver Riddle   }
131502c4c0d5SRiver Riddle };
1316be0a7e9fSMehdi Amini } // namespace
1317abfd1a8bSRiver Riddle 
1318154cabe7SRiver Riddle void ByteCodeExecutor::executeApplyConstraint(PatternRewriter &rewriter) {
1319abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing ApplyConstraint:\n");
1320abfd1a8bSRiver Riddle   const PDLConstraintFunction &constraintFn = constraintFunctions[read()];
1321abfd1a8bSRiver Riddle   ArrayAttr constParams = read<ArrayAttr>();
1322abfd1a8bSRiver Riddle   SmallVector<PDLValue, 16> args;
1323abfd1a8bSRiver Riddle   readList<PDLValue>(args);
1324154cabe7SRiver Riddle 
1325abfd1a8bSRiver Riddle   LLVM_DEBUG({
1326abfd1a8bSRiver Riddle     llvm::dbgs() << "  * Arguments: ";
1327abfd1a8bSRiver Riddle     llvm::interleaveComma(args, llvm::dbgs());
1328154cabe7SRiver Riddle     llvm::dbgs() << "\n  * Parameters: " << constParams << "\n";
1329abfd1a8bSRiver Riddle   });
1330abfd1a8bSRiver Riddle 
1331abfd1a8bSRiver Riddle   // Invoke the constraint and jump to the proper destination.
1332abfd1a8bSRiver Riddle   selectJump(succeeded(constraintFn(args, constParams, rewriter)));
1333abfd1a8bSRiver Riddle }
1334154cabe7SRiver Riddle 
1335154cabe7SRiver Riddle void ByteCodeExecutor::executeApplyRewrite(PatternRewriter &rewriter) {
1336abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing ApplyRewrite:\n");
1337abfd1a8bSRiver Riddle   const PDLRewriteFunction &rewriteFn = rewriteFunctions[read()];
1338abfd1a8bSRiver Riddle   ArrayAttr constParams = read<ArrayAttr>();
1339abfd1a8bSRiver Riddle   SmallVector<PDLValue, 16> args;
1340abfd1a8bSRiver Riddle   readList<PDLValue>(args);
1341abfd1a8bSRiver Riddle 
1342abfd1a8bSRiver Riddle   LLVM_DEBUG({
134302c4c0d5SRiver Riddle     llvm::dbgs() << "  * Arguments: ";
1344abfd1a8bSRiver Riddle     llvm::interleaveComma(args, llvm::dbgs());
1345154cabe7SRiver Riddle     llvm::dbgs() << "\n  * Parameters: " << constParams << "\n";
1346abfd1a8bSRiver Riddle   });
134785ab413bSRiver Riddle 
134885ab413bSRiver Riddle   // Execute the rewrite function.
134985ab413bSRiver Riddle   ByteCodeField numResults = read();
135085ab413bSRiver Riddle   ByteCodeRewriteResultList results(numResults);
135102c4c0d5SRiver Riddle   rewriteFn(args, constParams, rewriter, results);
1352154cabe7SRiver Riddle 
135385ab413bSRiver Riddle   assert(results.getResults().size() == numResults &&
135402c4c0d5SRiver Riddle          "native PDL rewrite function returned unexpected number of results");
135502c4c0d5SRiver Riddle 
135602c4c0d5SRiver Riddle   // Store the results in the bytecode memory.
135702c4c0d5SRiver Riddle   for (PDLValue &result : results.getResults()) {
135802c4c0d5SRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "  * Result: " << result << "\n");
135985ab413bSRiver Riddle 
136085ab413bSRiver Riddle // In debug mode we also verify the expected kind of the result.
136185ab413bSRiver Riddle #ifndef NDEBUG
136285ab413bSRiver Riddle     assert(result.getKind() == read<PDLValue::Kind>() &&
136385ab413bSRiver Riddle            "native PDL rewrite function returned an unexpected type of result");
136485ab413bSRiver Riddle #endif
136585ab413bSRiver Riddle 
136685ab413bSRiver Riddle     // If the result is a range, we need to copy it over to the bytecodes
136785ab413bSRiver Riddle     // range memory.
136885ab413bSRiver Riddle     if (Optional<TypeRange> typeRange = result.dyn_cast<TypeRange>()) {
136985ab413bSRiver Riddle       unsigned rangeIndex = read();
137085ab413bSRiver Riddle       typeRangeMemory[rangeIndex] = *typeRange;
137185ab413bSRiver Riddle       memory[read()] = &typeRangeMemory[rangeIndex];
137285ab413bSRiver Riddle     } else if (Optional<ValueRange> valueRange =
137385ab413bSRiver Riddle                    result.dyn_cast<ValueRange>()) {
137485ab413bSRiver Riddle       unsigned rangeIndex = read();
137585ab413bSRiver Riddle       valueRangeMemory[rangeIndex] = *valueRange;
137685ab413bSRiver Riddle       memory[read()] = &valueRangeMemory[rangeIndex];
137785ab413bSRiver Riddle     } else {
137802c4c0d5SRiver Riddle       memory[read()] = result.getAsOpaquePointer();
137902c4c0d5SRiver Riddle     }
1380abfd1a8bSRiver Riddle   }
1381154cabe7SRiver Riddle 
138285ab413bSRiver Riddle   // Copy over any underlying storage allocated for result ranges.
138385ab413bSRiver Riddle   for (auto &it : results.getAllocatedTypeRanges())
138485ab413bSRiver Riddle     allocatedTypeRangeMemory.push_back(std::move(it));
138585ab413bSRiver Riddle   for (auto &it : results.getAllocatedValueRanges())
138685ab413bSRiver Riddle     allocatedValueRangeMemory.push_back(std::move(it));
138785ab413bSRiver Riddle }
138885ab413bSRiver Riddle 
1389154cabe7SRiver Riddle void ByteCodeExecutor::executeAreEqual() {
1390abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing AreEqual:\n");
1391abfd1a8bSRiver Riddle   const void *lhs = read<const void *>();
1392abfd1a8bSRiver Riddle   const void *rhs = read<const void *>();
1393abfd1a8bSRiver Riddle 
1394154cabe7SRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * " << lhs << " == " << rhs << "\n");
1395abfd1a8bSRiver Riddle   selectJump(lhs == rhs);
1396abfd1a8bSRiver Riddle }
1397154cabe7SRiver Riddle 
139885ab413bSRiver Riddle void ByteCodeExecutor::executeAreRangesEqual() {
139985ab413bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing AreRangesEqual:\n");
140085ab413bSRiver Riddle   PDLValue::Kind valueKind = read<PDLValue::Kind>();
140185ab413bSRiver Riddle   const void *lhs = read<const void *>();
140285ab413bSRiver Riddle   const void *rhs = read<const void *>();
140385ab413bSRiver Riddle 
140485ab413bSRiver Riddle   switch (valueKind) {
140585ab413bSRiver Riddle   case PDLValue::Kind::TypeRange: {
140685ab413bSRiver Riddle     const TypeRange *lhsRange = reinterpret_cast<const TypeRange *>(lhs);
140785ab413bSRiver Riddle     const TypeRange *rhsRange = reinterpret_cast<const TypeRange *>(rhs);
140885ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "  * " << lhs << " == " << rhs << "\n\n");
140985ab413bSRiver Riddle     selectJump(*lhsRange == *rhsRange);
141085ab413bSRiver Riddle     break;
141185ab413bSRiver Riddle   }
141285ab413bSRiver Riddle   case PDLValue::Kind::ValueRange: {
141385ab413bSRiver Riddle     const auto *lhsRange = reinterpret_cast<const ValueRange *>(lhs);
141485ab413bSRiver Riddle     const auto *rhsRange = reinterpret_cast<const ValueRange *>(rhs);
141585ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "  * " << lhs << " == " << rhs << "\n\n");
141685ab413bSRiver Riddle     selectJump(*lhsRange == *rhsRange);
141785ab413bSRiver Riddle     break;
141885ab413bSRiver Riddle   }
141985ab413bSRiver Riddle   default:
142085ab413bSRiver Riddle     llvm_unreachable("unexpected `AreRangesEqual` value kind");
142185ab413bSRiver Riddle   }
142285ab413bSRiver Riddle }
142385ab413bSRiver Riddle 
1424154cabe7SRiver Riddle void ByteCodeExecutor::executeBranch() {
1425154cabe7SRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing Branch\n");
1426abfd1a8bSRiver Riddle   curCodeIt = &code[read<ByteCodeAddr>()];
1427abfd1a8bSRiver Riddle }
1428154cabe7SRiver Riddle 
1429154cabe7SRiver Riddle void ByteCodeExecutor::executeCheckOperandCount() {
1430abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing CheckOperandCount:\n");
1431abfd1a8bSRiver Riddle   Operation *op = read<Operation *>();
1432abfd1a8bSRiver Riddle   uint32_t expectedCount = read<uint32_t>();
143385ab413bSRiver Riddle   bool compareAtLeast = read();
1434abfd1a8bSRiver Riddle 
1435abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Found: " << op->getNumOperands() << "\n"
143685ab413bSRiver Riddle                           << "  * Expected: " << expectedCount << "\n"
143785ab413bSRiver Riddle                           << "  * Comparator: "
143885ab413bSRiver Riddle                           << (compareAtLeast ? ">=" : "==") << "\n");
143985ab413bSRiver Riddle   if (compareAtLeast)
144085ab413bSRiver Riddle     selectJump(op->getNumOperands() >= expectedCount);
144185ab413bSRiver Riddle   else
1442abfd1a8bSRiver Riddle     selectJump(op->getNumOperands() == expectedCount);
1443abfd1a8bSRiver Riddle }
1444154cabe7SRiver Riddle 
1445154cabe7SRiver Riddle void ByteCodeExecutor::executeCheckOperationName() {
1446abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing CheckOperationName:\n");
1447abfd1a8bSRiver Riddle   Operation *op = read<Operation *>();
1448abfd1a8bSRiver Riddle   OperationName expectedName = read<OperationName>();
1449abfd1a8bSRiver Riddle 
1450154cabe7SRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Found: \"" << op->getName() << "\"\n"
1451154cabe7SRiver Riddle                           << "  * Expected: \"" << expectedName << "\"\n");
1452abfd1a8bSRiver Riddle   selectJump(op->getName() == expectedName);
1453abfd1a8bSRiver Riddle }
1454154cabe7SRiver Riddle 
1455154cabe7SRiver Riddle void ByteCodeExecutor::executeCheckResultCount() {
1456abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing CheckResultCount:\n");
1457abfd1a8bSRiver Riddle   Operation *op = read<Operation *>();
1458abfd1a8bSRiver Riddle   uint32_t expectedCount = read<uint32_t>();
145985ab413bSRiver Riddle   bool compareAtLeast = read();
1460abfd1a8bSRiver Riddle 
1461abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Found: " << op->getNumResults() << "\n"
146285ab413bSRiver Riddle                           << "  * Expected: " << expectedCount << "\n"
146385ab413bSRiver Riddle                           << "  * Comparator: "
146485ab413bSRiver Riddle                           << (compareAtLeast ? ">=" : "==") << "\n");
146585ab413bSRiver Riddle   if (compareAtLeast)
146685ab413bSRiver Riddle     selectJump(op->getNumResults() >= expectedCount);
146785ab413bSRiver Riddle   else
1468abfd1a8bSRiver Riddle     selectJump(op->getNumResults() == expectedCount);
1469abfd1a8bSRiver Riddle }
1470154cabe7SRiver Riddle 
147185ab413bSRiver Riddle void ByteCodeExecutor::executeCheckTypes() {
147285ab413bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing AreEqual:\n");
147385ab413bSRiver Riddle   TypeRange *lhs = read<TypeRange *>();
147485ab413bSRiver Riddle   Attribute rhs = read<Attribute>();
147585ab413bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * " << lhs << " == " << rhs << "\n\n");
147685ab413bSRiver Riddle 
147785ab413bSRiver Riddle   selectJump(*lhs == rhs.cast<ArrayAttr>().getAsValueRange<TypeAttr>());
147885ab413bSRiver Riddle }
147985ab413bSRiver Riddle 
14803eb1647aSStanislav Funiak void ByteCodeExecutor::executeContinue() {
14813eb1647aSStanislav Funiak   ByteCodeField level = read();
14823eb1647aSStanislav Funiak   LLVM_DEBUG(llvm::dbgs() << "Executing Continue\n"
14833eb1647aSStanislav Funiak                           << "  * Level: " << level << "\n");
14843eb1647aSStanislav Funiak   ++loopIndex[level];
14853eb1647aSStanislav Funiak   popCodeIt();
14863eb1647aSStanislav Funiak }
14873eb1647aSStanislav Funiak 
148885ab413bSRiver Riddle void ByteCodeExecutor::executeCreateTypes() {
148985ab413bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing CreateTypes:\n");
149085ab413bSRiver Riddle   unsigned memIndex = read();
149185ab413bSRiver Riddle   unsigned rangeIndex = read();
149285ab413bSRiver Riddle   ArrayAttr typesAttr = read<Attribute>().cast<ArrayAttr>();
149385ab413bSRiver Riddle 
149485ab413bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Types: " << typesAttr << "\n\n");
149585ab413bSRiver Riddle 
149685ab413bSRiver Riddle   // Allocate a buffer for this type range.
149785ab413bSRiver Riddle   llvm::OwningArrayRef<Type> storage(typesAttr.size());
149885ab413bSRiver Riddle   llvm::copy(typesAttr.getAsValueRange<TypeAttr>(), storage.begin());
149985ab413bSRiver Riddle   allocatedTypeRangeMemory.emplace_back(std::move(storage));
150085ab413bSRiver Riddle 
150185ab413bSRiver Riddle   // Assign this to the range slot and use the range as the value for the
150285ab413bSRiver Riddle   // memory index.
150385ab413bSRiver Riddle   typeRangeMemory[rangeIndex] = allocatedTypeRangeMemory.back();
150485ab413bSRiver Riddle   memory[memIndex] = &typeRangeMemory[rangeIndex];
150585ab413bSRiver Riddle }
150685ab413bSRiver Riddle 
1507154cabe7SRiver Riddle void ByteCodeExecutor::executeCreateOperation(PatternRewriter &rewriter,
1508154cabe7SRiver Riddle                                               Location mainRewriteLoc) {
1509abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing CreateOperation:\n");
1510abfd1a8bSRiver Riddle 
1511abfd1a8bSRiver Riddle   unsigned memIndex = read();
1512154cabe7SRiver Riddle   OperationState state(mainRewriteLoc, read<OperationName>());
151385ab413bSRiver Riddle   readValueList(state.operands);
1514abfd1a8bSRiver Riddle   for (unsigned i = 0, e = read(); i != e; ++i) {
1515195730a6SRiver Riddle     StringAttr name = read<StringAttr>();
1516abfd1a8bSRiver Riddle     if (Attribute attr = read<Attribute>())
1517abfd1a8bSRiver Riddle       state.addAttribute(name, attr);
1518abfd1a8bSRiver Riddle   }
1519abfd1a8bSRiver Riddle 
1520abfd1a8bSRiver Riddle   for (unsigned i = 0, e = read(); i != e; ++i) {
152185ab413bSRiver Riddle     if (read<PDLValue::Kind>() == PDLValue::Kind::Type) {
152285ab413bSRiver Riddle       state.types.push_back(read<Type>());
152385ab413bSRiver Riddle       continue;
152485ab413bSRiver Riddle     }
152585ab413bSRiver Riddle 
152685ab413bSRiver Riddle     // If we find a null range, this signals that the types are infered.
152785ab413bSRiver Riddle     if (TypeRange *resultTypes = read<TypeRange *>()) {
152885ab413bSRiver Riddle       state.types.append(resultTypes->begin(), resultTypes->end());
152985ab413bSRiver Riddle       continue;
1530abfd1a8bSRiver Riddle     }
1531abfd1a8bSRiver Riddle 
1532abfd1a8bSRiver Riddle     // Handle the case where the operation has inferred types.
1533abfd1a8bSRiver Riddle     InferTypeOpInterface::Concept *concept =
1534edc6c0ecSRiver Riddle         state.name.getRegisteredInfo()->getInterface<InferTypeOpInterface>();
1535abfd1a8bSRiver Riddle 
1536abfd1a8bSRiver Riddle     // TODO: Handle failure.
15373a833a0eSRiver Riddle     state.types.clear();
1538abfd1a8bSRiver Riddle     if (failed(concept->inferReturnTypes(
1539abfd1a8bSRiver Riddle             state.getContext(), state.location, state.operands,
1540154cabe7SRiver Riddle             state.attributes.getDictionary(state.getContext()), state.regions,
15413a833a0eSRiver Riddle             state.types)))
1542abfd1a8bSRiver Riddle       return;
154385ab413bSRiver Riddle     break;
1544abfd1a8bSRiver Riddle   }
154585ab413bSRiver Riddle 
1546abfd1a8bSRiver Riddle   Operation *resultOp = rewriter.createOperation(state);
1547abfd1a8bSRiver Riddle   memory[memIndex] = resultOp;
1548abfd1a8bSRiver Riddle 
1549abfd1a8bSRiver Riddle   LLVM_DEBUG({
1550abfd1a8bSRiver Riddle     llvm::dbgs() << "  * Attributes: "
1551abfd1a8bSRiver Riddle                  << state.attributes.getDictionary(state.getContext())
1552abfd1a8bSRiver Riddle                  << "\n  * Operands: ";
1553abfd1a8bSRiver Riddle     llvm::interleaveComma(state.operands, llvm::dbgs());
1554abfd1a8bSRiver Riddle     llvm::dbgs() << "\n  * Result Types: ";
1555abfd1a8bSRiver Riddle     llvm::interleaveComma(state.types, llvm::dbgs());
1556154cabe7SRiver Riddle     llvm::dbgs() << "\n  * Result: " << *resultOp << "\n";
1557abfd1a8bSRiver Riddle   });
1558abfd1a8bSRiver Riddle }
1559154cabe7SRiver Riddle 
1560154cabe7SRiver Riddle void ByteCodeExecutor::executeEraseOp(PatternRewriter &rewriter) {
1561abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing EraseOp:\n");
1562abfd1a8bSRiver Riddle   Operation *op = read<Operation *>();
1563abfd1a8bSRiver Riddle 
1564154cabe7SRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Operation: " << *op << "\n");
1565abfd1a8bSRiver Riddle   rewriter.eraseOp(op);
1566abfd1a8bSRiver Riddle }
1567154cabe7SRiver Riddle 
15683eb1647aSStanislav Funiak template <typename T, typename Range, PDLValue::Kind kind>
15693eb1647aSStanislav Funiak void ByteCodeExecutor::executeExtract() {
15703eb1647aSStanislav Funiak   LLVM_DEBUG(llvm::dbgs() << "Executing Extract" << kind << ":\n");
15713eb1647aSStanislav Funiak   Range *range = read<Range *>();
15723eb1647aSStanislav Funiak   unsigned index = read<uint32_t>();
15733eb1647aSStanislav Funiak   unsigned memIndex = read();
15743eb1647aSStanislav Funiak 
15753eb1647aSStanislav Funiak   if (!range) {
15763eb1647aSStanislav Funiak     memory[memIndex] = nullptr;
15773eb1647aSStanislav Funiak     return;
15783eb1647aSStanislav Funiak   }
15793eb1647aSStanislav Funiak 
15803eb1647aSStanislav Funiak   T result = index < range->size() ? (*range)[index] : T();
15813eb1647aSStanislav Funiak   LLVM_DEBUG(llvm::dbgs() << "  * " << kind << "s(" << range->size() << ")\n"
15823eb1647aSStanislav Funiak                           << "  * Index: " << index << "\n"
15833eb1647aSStanislav Funiak                           << "  * Result: " << result << "\n");
15843eb1647aSStanislav Funiak   storeToMemory(memIndex, result);
15853eb1647aSStanislav Funiak }
15863eb1647aSStanislav Funiak 
15873eb1647aSStanislav Funiak void ByteCodeExecutor::executeFinalize() {
15883eb1647aSStanislav Funiak   LLVM_DEBUG(llvm::dbgs() << "Executing Finalize\n");
15893eb1647aSStanislav Funiak }
15903eb1647aSStanislav Funiak 
15913eb1647aSStanislav Funiak void ByteCodeExecutor::executeForEach() {
15923eb1647aSStanislav Funiak   LLVM_DEBUG(llvm::dbgs() << "Executing ForEach:\n");
1593d35f1190SStanislav Funiak   const ByteCodeField *prevCodeIt = getPrevCodeIt();
15943eb1647aSStanislav Funiak   unsigned rangeIndex = read();
15953eb1647aSStanislav Funiak   unsigned memIndex = read();
15963eb1647aSStanislav Funiak   const void *value = nullptr;
15973eb1647aSStanislav Funiak 
15983eb1647aSStanislav Funiak   switch (read<PDLValue::Kind>()) {
15993eb1647aSStanislav Funiak   case PDLValue::Kind::Operation: {
16003eb1647aSStanislav Funiak     unsigned &index = loopIndex[read()];
16013eb1647aSStanislav Funiak     ArrayRef<Operation *> array = opRangeMemory[rangeIndex];
16023eb1647aSStanislav Funiak     assert(index <= array.size() && "iterated past the end");
16033eb1647aSStanislav Funiak     if (index < array.size()) {
16043eb1647aSStanislav Funiak       LLVM_DEBUG(llvm::dbgs() << "  * Result: " << array[index] << "\n");
16053eb1647aSStanislav Funiak       value = array[index];
16063eb1647aSStanislav Funiak       break;
16073eb1647aSStanislav Funiak     }
16083eb1647aSStanislav Funiak 
16093eb1647aSStanislav Funiak     LLVM_DEBUG(llvm::dbgs() << "  * Done\n");
16103eb1647aSStanislav Funiak     index = 0;
16113eb1647aSStanislav Funiak     selectJump(size_t(0));
16123eb1647aSStanislav Funiak     return;
16133eb1647aSStanislav Funiak   }
16143eb1647aSStanislav Funiak   default:
16153eb1647aSStanislav Funiak     llvm_unreachable("unexpected `ForEach` value kind");
16163eb1647aSStanislav Funiak   }
16173eb1647aSStanislav Funiak 
16183eb1647aSStanislav Funiak   // Store the iterate value and the stack address.
16193eb1647aSStanislav Funiak   memory[memIndex] = value;
1620d35f1190SStanislav Funiak   pushCodeIt(prevCodeIt);
16213eb1647aSStanislav Funiak 
16223eb1647aSStanislav Funiak   // Skip over the successor (we will enter the body of the loop).
16233eb1647aSStanislav Funiak   read<ByteCodeAddr>();
16243eb1647aSStanislav Funiak }
16253eb1647aSStanislav Funiak 
1626154cabe7SRiver Riddle void ByteCodeExecutor::executeGetAttribute() {
1627abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing GetAttribute:\n");
1628abfd1a8bSRiver Riddle   unsigned memIndex = read();
1629abfd1a8bSRiver Riddle   Operation *op = read<Operation *>();
1630195730a6SRiver Riddle   StringAttr attrName = read<StringAttr>();
1631abfd1a8bSRiver Riddle   Attribute attr = op->getAttr(attrName);
1632abfd1a8bSRiver Riddle 
1633abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Operation: " << *op << "\n"
1634abfd1a8bSRiver Riddle                           << "  * Attribute: " << attrName << "\n"
1635154cabe7SRiver Riddle                           << "  * Result: " << attr << "\n");
1636abfd1a8bSRiver Riddle   memory[memIndex] = attr.getAsOpaquePointer();
1637abfd1a8bSRiver Riddle }
1638154cabe7SRiver Riddle 
1639154cabe7SRiver Riddle void ByteCodeExecutor::executeGetAttributeType() {
1640abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing GetAttributeType:\n");
1641abfd1a8bSRiver Riddle   unsigned memIndex = read();
1642abfd1a8bSRiver Riddle   Attribute attr = read<Attribute>();
1643154cabe7SRiver Riddle   Type type = attr ? attr.getType() : Type();
1644abfd1a8bSRiver Riddle 
1645abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Attribute: " << attr << "\n"
1646154cabe7SRiver Riddle                           << "  * Result: " << type << "\n");
1647154cabe7SRiver Riddle   memory[memIndex] = type.getAsOpaquePointer();
1648abfd1a8bSRiver Riddle }
1649154cabe7SRiver Riddle 
1650154cabe7SRiver Riddle void ByteCodeExecutor::executeGetDefiningOp() {
1651abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing GetDefiningOp:\n");
1652abfd1a8bSRiver Riddle   unsigned memIndex = read();
165385ab413bSRiver Riddle   Operation *op = nullptr;
165485ab413bSRiver Riddle   if (read<PDLValue::Kind>() == PDLValue::Kind::Value) {
1655abfd1a8bSRiver Riddle     Value value = read<Value>();
165685ab413bSRiver Riddle     if (value)
165785ab413bSRiver Riddle       op = value.getDefiningOp();
165885ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "  * Value: " << value << "\n");
165985ab413bSRiver Riddle   } else {
166085ab413bSRiver Riddle     ValueRange *values = read<ValueRange *>();
166185ab413bSRiver Riddle     if (values && !values->empty()) {
166285ab413bSRiver Riddle       op = values->front().getDefiningOp();
166385ab413bSRiver Riddle     }
166485ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "  * Values: " << values << "\n");
166585ab413bSRiver Riddle   }
1666abfd1a8bSRiver Riddle 
166785ab413bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Result: " << op << "\n");
1668abfd1a8bSRiver Riddle   memory[memIndex] = op;
1669abfd1a8bSRiver Riddle }
1670154cabe7SRiver Riddle 
1671154cabe7SRiver Riddle void ByteCodeExecutor::executeGetOperand(unsigned index) {
1672abfd1a8bSRiver Riddle   Operation *op = read<Operation *>();
1673abfd1a8bSRiver Riddle   unsigned memIndex = read();
1674abfd1a8bSRiver Riddle   Value operand =
1675abfd1a8bSRiver Riddle       index < op->getNumOperands() ? op->getOperand(index) : Value();
1676abfd1a8bSRiver Riddle 
1677abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Operation: " << *op << "\n"
1678abfd1a8bSRiver Riddle                           << "  * Index: " << index << "\n"
1679154cabe7SRiver Riddle                           << "  * Result: " << operand << "\n");
1680abfd1a8bSRiver Riddle   memory[memIndex] = operand.getAsOpaquePointer();
1681abfd1a8bSRiver Riddle }
1682154cabe7SRiver Riddle 
168385ab413bSRiver Riddle /// This function is the internal implementation of `GetResults` and
168485ab413bSRiver Riddle /// `GetOperands` that provides support for extracting a value range from the
168585ab413bSRiver Riddle /// given operation.
168685ab413bSRiver Riddle template <template <typename> class AttrSizedSegmentsT, typename RangeT>
168785ab413bSRiver Riddle static void *
168885ab413bSRiver Riddle executeGetOperandsResults(RangeT values, Operation *op, unsigned index,
168985ab413bSRiver Riddle                           ByteCodeField rangeIndex, StringRef attrSizedSegments,
16903eb1647aSStanislav Funiak                           MutableArrayRef<ValueRange> valueRangeMemory) {
169185ab413bSRiver Riddle   // Check for the sentinel index that signals that all values should be
169285ab413bSRiver Riddle   // returned.
169385ab413bSRiver Riddle   if (index == std::numeric_limits<uint32_t>::max()) {
169485ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "  * Getting all values\n");
169585ab413bSRiver Riddle     // `values` is already the full value range.
169685ab413bSRiver Riddle 
169785ab413bSRiver Riddle     // Otherwise, check to see if this operation uses AttrSizedSegments.
169885ab413bSRiver Riddle   } else if (op->hasTrait<AttrSizedSegmentsT>()) {
169985ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs()
170085ab413bSRiver Riddle                << "  * Extracting values from `" << attrSizedSegments << "`\n");
170185ab413bSRiver Riddle 
170285ab413bSRiver Riddle     auto segmentAttr = op->getAttrOfType<DenseElementsAttr>(attrSizedSegments);
170385ab413bSRiver Riddle     if (!segmentAttr || segmentAttr.getNumElements() <= index)
170485ab413bSRiver Riddle       return nullptr;
170585ab413bSRiver Riddle 
170685ab413bSRiver Riddle     auto segments = segmentAttr.getValues<int32_t>();
170785ab413bSRiver Riddle     unsigned startIndex =
170885ab413bSRiver Riddle         std::accumulate(segments.begin(), segments.begin() + index, 0);
170985ab413bSRiver Riddle     values = values.slice(startIndex, *std::next(segments.begin(), index));
171085ab413bSRiver Riddle 
171185ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "  * Extracting range[" << startIndex << ", "
171285ab413bSRiver Riddle                             << *std::next(segments.begin(), index) << "]\n");
171385ab413bSRiver Riddle 
171485ab413bSRiver Riddle     // Otherwise, assume this is the last operand group of the operation.
171585ab413bSRiver Riddle     // FIXME: We currently don't support operations with
171685ab413bSRiver Riddle     // SameVariadicOperandSize/SameVariadicResultSize here given that we don't
171785ab413bSRiver Riddle     // have a way to detect it's presence.
171885ab413bSRiver Riddle   } else if (values.size() >= index) {
171985ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs()
172085ab413bSRiver Riddle                << "  * Treating values as trailing variadic range\n");
172185ab413bSRiver Riddle     values = values.drop_front(index);
172285ab413bSRiver Riddle 
172385ab413bSRiver Riddle     // If we couldn't detect a way to compute the values, bail out.
172485ab413bSRiver Riddle   } else {
172585ab413bSRiver Riddle     return nullptr;
172685ab413bSRiver Riddle   }
172785ab413bSRiver Riddle 
172885ab413bSRiver Riddle   // If the range index is valid, we are returning a range.
172985ab413bSRiver Riddle   if (rangeIndex != std::numeric_limits<ByteCodeField>::max()) {
173085ab413bSRiver Riddle     valueRangeMemory[rangeIndex] = values;
173185ab413bSRiver Riddle     return &valueRangeMemory[rangeIndex];
173285ab413bSRiver Riddle   }
173385ab413bSRiver Riddle 
173485ab413bSRiver Riddle   // If a range index wasn't provided, the range is required to be non-variadic.
173585ab413bSRiver Riddle   return values.size() != 1 ? nullptr : values.front().getAsOpaquePointer();
173685ab413bSRiver Riddle }
173785ab413bSRiver Riddle 
173885ab413bSRiver Riddle void ByteCodeExecutor::executeGetOperands() {
173985ab413bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing GetOperands:\n");
174085ab413bSRiver Riddle   unsigned index = read<uint32_t>();
174185ab413bSRiver Riddle   Operation *op = read<Operation *>();
174285ab413bSRiver Riddle   ByteCodeField rangeIndex = read();
174385ab413bSRiver Riddle 
174485ab413bSRiver Riddle   void *result = executeGetOperandsResults<OpTrait::AttrSizedOperandSegments>(
174585ab413bSRiver Riddle       op->getOperands(), op, index, rangeIndex, "operand_segment_sizes",
174685ab413bSRiver Riddle       valueRangeMemory);
174785ab413bSRiver Riddle   if (!result)
174885ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "  * Invalid operand range\n");
174985ab413bSRiver Riddle   memory[read()] = result;
175085ab413bSRiver Riddle }
175185ab413bSRiver Riddle 
1752154cabe7SRiver Riddle void ByteCodeExecutor::executeGetResult(unsigned index) {
1753abfd1a8bSRiver Riddle   Operation *op = read<Operation *>();
1754abfd1a8bSRiver Riddle   unsigned memIndex = read();
1755abfd1a8bSRiver Riddle   OpResult result =
1756abfd1a8bSRiver Riddle       index < op->getNumResults() ? op->getResult(index) : OpResult();
1757abfd1a8bSRiver Riddle 
1758abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Operation: " << *op << "\n"
1759abfd1a8bSRiver Riddle                           << "  * Index: " << index << "\n"
1760154cabe7SRiver Riddle                           << "  * Result: " << result << "\n");
1761abfd1a8bSRiver Riddle   memory[memIndex] = result.getAsOpaquePointer();
1762abfd1a8bSRiver Riddle }
1763154cabe7SRiver Riddle 
176485ab413bSRiver Riddle void ByteCodeExecutor::executeGetResults() {
176585ab413bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing GetResults:\n");
176685ab413bSRiver Riddle   unsigned index = read<uint32_t>();
176785ab413bSRiver Riddle   Operation *op = read<Operation *>();
176885ab413bSRiver Riddle   ByteCodeField rangeIndex = read();
176985ab413bSRiver Riddle 
177085ab413bSRiver Riddle   void *result = executeGetOperandsResults<OpTrait::AttrSizedResultSegments>(
177185ab413bSRiver Riddle       op->getResults(), op, index, rangeIndex, "result_segment_sizes",
177285ab413bSRiver Riddle       valueRangeMemory);
177385ab413bSRiver Riddle   if (!result)
177485ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "  * Invalid result range\n");
177585ab413bSRiver Riddle   memory[read()] = result;
177685ab413bSRiver Riddle }
177785ab413bSRiver Riddle 
17783eb1647aSStanislav Funiak void ByteCodeExecutor::executeGetUsers() {
17793eb1647aSStanislav Funiak   LLVM_DEBUG(llvm::dbgs() << "Executing GetUsers:\n");
17803eb1647aSStanislav Funiak   unsigned memIndex = read();
17813eb1647aSStanislav Funiak   unsigned rangeIndex = read();
17823eb1647aSStanislav Funiak   OwningOpRange &range = opRangeMemory[rangeIndex];
17833eb1647aSStanislav Funiak   memory[memIndex] = &range;
17843eb1647aSStanislav Funiak 
17853eb1647aSStanislav Funiak   range = OwningOpRange();
17863eb1647aSStanislav Funiak   if (read<PDLValue::Kind>() == PDLValue::Kind::Value) {
17873eb1647aSStanislav Funiak     // Read the value.
17883eb1647aSStanislav Funiak     Value value = read<Value>();
17893eb1647aSStanislav Funiak     if (!value)
17903eb1647aSStanislav Funiak       return;
17913eb1647aSStanislav Funiak     LLVM_DEBUG(llvm::dbgs() << "  * Value: " << value << "\n");
17923eb1647aSStanislav Funiak 
17933eb1647aSStanislav Funiak     // Extract the users of a single value.
17943eb1647aSStanislav Funiak     range = OwningOpRange(std::distance(value.user_begin(), value.user_end()));
17953eb1647aSStanislav Funiak     llvm::copy(value.getUsers(), range.begin());
17963eb1647aSStanislav Funiak   } else {
17973eb1647aSStanislav Funiak     // Read a range of values.
17983eb1647aSStanislav Funiak     ValueRange *values = read<ValueRange *>();
17993eb1647aSStanislav Funiak     if (!values)
18003eb1647aSStanislav Funiak       return;
18013eb1647aSStanislav Funiak     LLVM_DEBUG({
18023eb1647aSStanislav Funiak       llvm::dbgs() << "  * Values (" << values->size() << "): ";
18033eb1647aSStanislav Funiak       llvm::interleaveComma(*values, llvm::dbgs());
18043eb1647aSStanislav Funiak       llvm::dbgs() << "\n";
18053eb1647aSStanislav Funiak     });
18063eb1647aSStanislav Funiak 
18073eb1647aSStanislav Funiak     // Extract all the users of a range of values.
18083eb1647aSStanislav Funiak     SmallVector<Operation *> users;
18093eb1647aSStanislav Funiak     for (Value value : *values)
18103eb1647aSStanislav Funiak       users.append(value.user_begin(), value.user_end());
18113eb1647aSStanislav Funiak     range = OwningOpRange(users.size());
18123eb1647aSStanislav Funiak     llvm::copy(users, range.begin());
18133eb1647aSStanislav Funiak   }
18143eb1647aSStanislav Funiak 
18153eb1647aSStanislav Funiak   LLVM_DEBUG(llvm::dbgs() << "  * Result: " << range.size() << " operations\n");
18163eb1647aSStanislav Funiak }
18173eb1647aSStanislav Funiak 
1818154cabe7SRiver Riddle void ByteCodeExecutor::executeGetValueType() {
1819abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing GetValueType:\n");
1820abfd1a8bSRiver Riddle   unsigned memIndex = read();
1821abfd1a8bSRiver Riddle   Value value = read<Value>();
1822154cabe7SRiver Riddle   Type type = value ? value.getType() : Type();
1823abfd1a8bSRiver Riddle 
1824abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Value: " << value << "\n"
1825154cabe7SRiver Riddle                           << "  * Result: " << type << "\n");
1826154cabe7SRiver Riddle   memory[memIndex] = type.getAsOpaquePointer();
1827abfd1a8bSRiver Riddle }
1828154cabe7SRiver Riddle 
182985ab413bSRiver Riddle void ByteCodeExecutor::executeGetValueRangeTypes() {
183085ab413bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing GetValueRangeTypes:\n");
183185ab413bSRiver Riddle   unsigned memIndex = read();
183285ab413bSRiver Riddle   unsigned rangeIndex = read();
183385ab413bSRiver Riddle   ValueRange *values = read<ValueRange *>();
183485ab413bSRiver Riddle   if (!values) {
183585ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "  * Values: <NULL>\n\n");
183685ab413bSRiver Riddle     memory[memIndex] = nullptr;
183785ab413bSRiver Riddle     return;
183885ab413bSRiver Riddle   }
183985ab413bSRiver Riddle 
184085ab413bSRiver Riddle   LLVM_DEBUG({
184185ab413bSRiver Riddle     llvm::dbgs() << "  * Values (" << values->size() << "): ";
184285ab413bSRiver Riddle     llvm::interleaveComma(*values, llvm::dbgs());
184385ab413bSRiver Riddle     llvm::dbgs() << "\n  * Result: ";
184485ab413bSRiver Riddle     llvm::interleaveComma(values->getType(), llvm::dbgs());
184585ab413bSRiver Riddle     llvm::dbgs() << "\n";
184685ab413bSRiver Riddle   });
184785ab413bSRiver Riddle   typeRangeMemory[rangeIndex] = values->getType();
184885ab413bSRiver Riddle   memory[memIndex] = &typeRangeMemory[rangeIndex];
184985ab413bSRiver Riddle }
185085ab413bSRiver Riddle 
1851154cabe7SRiver Riddle void ByteCodeExecutor::executeIsNotNull() {
1852abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing IsNotNull:\n");
1853abfd1a8bSRiver Riddle   const void *value = read<const void *>();
1854abfd1a8bSRiver Riddle 
1855154cabe7SRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Value: " << value << "\n");
1856abfd1a8bSRiver Riddle   selectJump(value != nullptr);
1857abfd1a8bSRiver Riddle }
1858154cabe7SRiver Riddle 
1859154cabe7SRiver Riddle void ByteCodeExecutor::executeRecordMatch(
1860154cabe7SRiver Riddle     PatternRewriter &rewriter,
1861154cabe7SRiver Riddle     SmallVectorImpl<PDLByteCode::MatchResult> &matches) {
1862abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing RecordMatch:\n");
1863abfd1a8bSRiver Riddle   unsigned patternIndex = read();
1864abfd1a8bSRiver Riddle   PatternBenefit benefit = currentPatternBenefits[patternIndex];
1865abfd1a8bSRiver Riddle   const ByteCodeField *dest = &code[read<ByteCodeAddr>()];
1866abfd1a8bSRiver Riddle 
1867abfd1a8bSRiver Riddle   // If the benefit of the pattern is impossible, skip the processing of the
1868abfd1a8bSRiver Riddle   // rest of the pattern.
1869abfd1a8bSRiver Riddle   if (benefit.isImpossibleToMatch()) {
1870154cabe7SRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "  * Benefit: Impossible To Match\n");
1871abfd1a8bSRiver Riddle     curCodeIt = dest;
1872154cabe7SRiver Riddle     return;
1873abfd1a8bSRiver Riddle   }
1874abfd1a8bSRiver Riddle 
1875abfd1a8bSRiver Riddle   // Create a fused location containing the locations of each of the
1876abfd1a8bSRiver Riddle   // operations used in the match. This will be used as the location for
1877abfd1a8bSRiver Riddle   // created operations during the rewrite that don't already have an
1878abfd1a8bSRiver Riddle   // explicit location set.
1879abfd1a8bSRiver Riddle   unsigned numMatchLocs = read();
1880abfd1a8bSRiver Riddle   SmallVector<Location, 4> matchLocs;
1881abfd1a8bSRiver Riddle   matchLocs.reserve(numMatchLocs);
1882abfd1a8bSRiver Riddle   for (unsigned i = 0; i != numMatchLocs; ++i)
1883abfd1a8bSRiver Riddle     matchLocs.push_back(read<Operation *>()->getLoc());
1884abfd1a8bSRiver Riddle   Location matchLoc = rewriter.getFusedLoc(matchLocs);
1885abfd1a8bSRiver Riddle 
1886abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Benefit: " << benefit.getBenefit() << "\n"
1887154cabe7SRiver Riddle                           << "  * Location: " << matchLoc << "\n");
1888154cabe7SRiver Riddle   matches.emplace_back(matchLoc, patterns[patternIndex], benefit);
188985ab413bSRiver Riddle   PDLByteCode::MatchResult &match = matches.back();
189085ab413bSRiver Riddle 
189185ab413bSRiver Riddle   // Record all of the inputs to the match. If any of the inputs are ranges, we
189285ab413bSRiver Riddle   // will also need to remap the range pointer to memory stored in the match
189385ab413bSRiver Riddle   // state.
189485ab413bSRiver Riddle   unsigned numInputs = read();
189585ab413bSRiver Riddle   match.values.reserve(numInputs);
189685ab413bSRiver Riddle   match.typeRangeValues.reserve(numInputs);
189785ab413bSRiver Riddle   match.valueRangeValues.reserve(numInputs);
189885ab413bSRiver Riddle   for (unsigned i = 0; i < numInputs; ++i) {
189985ab413bSRiver Riddle     switch (read<PDLValue::Kind>()) {
190085ab413bSRiver Riddle     case PDLValue::Kind::TypeRange:
190185ab413bSRiver Riddle       match.typeRangeValues.push_back(*read<TypeRange *>());
190285ab413bSRiver Riddle       match.values.push_back(&match.typeRangeValues.back());
190385ab413bSRiver Riddle       break;
190485ab413bSRiver Riddle     case PDLValue::Kind::ValueRange:
190585ab413bSRiver Riddle       match.valueRangeValues.push_back(*read<ValueRange *>());
190685ab413bSRiver Riddle       match.values.push_back(&match.valueRangeValues.back());
190785ab413bSRiver Riddle       break;
190885ab413bSRiver Riddle     default:
190985ab413bSRiver Riddle       match.values.push_back(read<const void *>());
191085ab413bSRiver Riddle       break;
191185ab413bSRiver Riddle     }
191285ab413bSRiver Riddle   }
1913abfd1a8bSRiver Riddle   curCodeIt = dest;
1914abfd1a8bSRiver Riddle }
1915154cabe7SRiver Riddle 
1916154cabe7SRiver Riddle void ByteCodeExecutor::executeReplaceOp(PatternRewriter &rewriter) {
1917abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing ReplaceOp:\n");
1918abfd1a8bSRiver Riddle   Operation *op = read<Operation *>();
1919abfd1a8bSRiver Riddle   SmallVector<Value, 16> args;
192085ab413bSRiver Riddle   readValueList(args);
1921abfd1a8bSRiver Riddle 
1922abfd1a8bSRiver Riddle   LLVM_DEBUG({
1923abfd1a8bSRiver Riddle     llvm::dbgs() << "  * Operation: " << *op << "\n"
1924abfd1a8bSRiver Riddle                  << "  * Values: ";
1925abfd1a8bSRiver Riddle     llvm::interleaveComma(args, llvm::dbgs());
1926154cabe7SRiver Riddle     llvm::dbgs() << "\n";
1927abfd1a8bSRiver Riddle   });
1928abfd1a8bSRiver Riddle   rewriter.replaceOp(op, args);
1929abfd1a8bSRiver Riddle }
1930154cabe7SRiver Riddle 
1931154cabe7SRiver Riddle void ByteCodeExecutor::executeSwitchAttribute() {
1932abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing SwitchAttribute:\n");
1933abfd1a8bSRiver Riddle   Attribute value = read<Attribute>();
1934abfd1a8bSRiver Riddle   ArrayAttr cases = read<ArrayAttr>();
1935abfd1a8bSRiver Riddle   handleSwitch(value, cases);
1936abfd1a8bSRiver Riddle }
1937154cabe7SRiver Riddle 
1938154cabe7SRiver Riddle void ByteCodeExecutor::executeSwitchOperandCount() {
1939abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing SwitchOperandCount:\n");
1940abfd1a8bSRiver Riddle   Operation *op = read<Operation *>();
1941abfd1a8bSRiver Riddle   auto cases = read<DenseIntOrFPElementsAttr>().getValues<uint32_t>();
1942abfd1a8bSRiver Riddle 
1943abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Operation: " << *op << "\n");
1944abfd1a8bSRiver Riddle   handleSwitch(op->getNumOperands(), cases);
1945abfd1a8bSRiver Riddle }
1946154cabe7SRiver Riddle 
1947154cabe7SRiver Riddle void ByteCodeExecutor::executeSwitchOperationName() {
1948abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing SwitchOperationName:\n");
1949abfd1a8bSRiver Riddle   OperationName value = read<Operation *>()->getName();
1950abfd1a8bSRiver Riddle   size_t caseCount = read();
1951abfd1a8bSRiver Riddle 
1952abfd1a8bSRiver Riddle   // The operation names are stored in-line, so to print them out for
1953abfd1a8bSRiver Riddle   // debugging purposes we need to read the array before executing the
1954abfd1a8bSRiver Riddle   // switch so that we can display all of the possible values.
1955abfd1a8bSRiver Riddle   LLVM_DEBUG({
1956abfd1a8bSRiver Riddle     const ByteCodeField *prevCodeIt = curCodeIt;
1957abfd1a8bSRiver Riddle     llvm::dbgs() << "  * Value: " << value << "\n"
1958abfd1a8bSRiver Riddle                  << "  * Cases: ";
1959abfd1a8bSRiver Riddle     llvm::interleaveComma(
1960abfd1a8bSRiver Riddle         llvm::map_range(llvm::seq<size_t>(0, caseCount),
1961154cabe7SRiver Riddle                         [&](size_t) { return read<OperationName>(); }),
1962abfd1a8bSRiver Riddle         llvm::dbgs());
1963154cabe7SRiver Riddle     llvm::dbgs() << "\n";
1964abfd1a8bSRiver Riddle     curCodeIt = prevCodeIt;
1965abfd1a8bSRiver Riddle   });
1966abfd1a8bSRiver Riddle 
1967abfd1a8bSRiver Riddle   // Try to find the switch value within any of the cases.
1968abfd1a8bSRiver Riddle   for (size_t i = 0; i != caseCount; ++i) {
1969abfd1a8bSRiver Riddle     if (read<OperationName>() == value) {
1970abfd1a8bSRiver Riddle       curCodeIt += (caseCount - i - 1);
1971154cabe7SRiver Riddle       return selectJump(i + 1);
1972abfd1a8bSRiver Riddle     }
1973abfd1a8bSRiver Riddle   }
1974154cabe7SRiver Riddle   selectJump(size_t(0));
1975abfd1a8bSRiver Riddle }
1976154cabe7SRiver Riddle 
1977154cabe7SRiver Riddle void ByteCodeExecutor::executeSwitchResultCount() {
1978abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing SwitchResultCount:\n");
1979abfd1a8bSRiver Riddle   Operation *op = read<Operation *>();
1980abfd1a8bSRiver Riddle   auto cases = read<DenseIntOrFPElementsAttr>().getValues<uint32_t>();
1981abfd1a8bSRiver Riddle 
1982abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "  * Operation: " << *op << "\n");
1983abfd1a8bSRiver Riddle   handleSwitch(op->getNumResults(), cases);
1984abfd1a8bSRiver Riddle }
1985154cabe7SRiver Riddle 
1986154cabe7SRiver Riddle void ByteCodeExecutor::executeSwitchType() {
1987abfd1a8bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing SwitchType:\n");
1988abfd1a8bSRiver Riddle   Type value = read<Type>();
1989abfd1a8bSRiver Riddle   auto cases = read<ArrayAttr>().getAsValueRange<TypeAttr>();
1990abfd1a8bSRiver Riddle   handleSwitch(value, cases);
1991154cabe7SRiver Riddle }
1992154cabe7SRiver Riddle 
199385ab413bSRiver Riddle void ByteCodeExecutor::executeSwitchTypes() {
199485ab413bSRiver Riddle   LLVM_DEBUG(llvm::dbgs() << "Executing SwitchTypes:\n");
199585ab413bSRiver Riddle   TypeRange *value = read<TypeRange *>();
199685ab413bSRiver Riddle   auto cases = read<ArrayAttr>().getAsRange<ArrayAttr>();
199785ab413bSRiver Riddle   if (!value) {
199885ab413bSRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "Types: <NULL>\n");
199985ab413bSRiver Riddle     return selectJump(size_t(0));
200085ab413bSRiver Riddle   }
200185ab413bSRiver Riddle   handleSwitch(*value, cases, [](ArrayAttr caseValue, const TypeRange &value) {
200285ab413bSRiver Riddle     return value == caseValue.getAsValueRange<TypeAttr>();
200385ab413bSRiver Riddle   });
200485ab413bSRiver Riddle }
200585ab413bSRiver Riddle 
2006154cabe7SRiver Riddle void ByteCodeExecutor::execute(
2007154cabe7SRiver Riddle     PatternRewriter &rewriter,
2008154cabe7SRiver Riddle     SmallVectorImpl<PDLByteCode::MatchResult> *matches,
2009154cabe7SRiver Riddle     Optional<Location> mainRewriteLoc) {
2010154cabe7SRiver Riddle   while (true) {
2011d35f1190SStanislav Funiak     // Print the location of the operation being executed.
2012d35f1190SStanislav Funiak     LLVM_DEBUG(llvm::dbgs() << readInline<Location>() << "\n");
2013d35f1190SStanislav Funiak 
2014154cabe7SRiver Riddle     OpCode opCode = static_cast<OpCode>(read());
2015154cabe7SRiver Riddle     switch (opCode) {
2016154cabe7SRiver Riddle     case ApplyConstraint:
2017154cabe7SRiver Riddle       executeApplyConstraint(rewriter);
2018154cabe7SRiver Riddle       break;
2019154cabe7SRiver Riddle     case ApplyRewrite:
2020154cabe7SRiver Riddle       executeApplyRewrite(rewriter);
2021154cabe7SRiver Riddle       break;
2022154cabe7SRiver Riddle     case AreEqual:
2023154cabe7SRiver Riddle       executeAreEqual();
2024154cabe7SRiver Riddle       break;
202585ab413bSRiver Riddle     case AreRangesEqual:
202685ab413bSRiver Riddle       executeAreRangesEqual();
202785ab413bSRiver Riddle       break;
2028154cabe7SRiver Riddle     case Branch:
2029154cabe7SRiver Riddle       executeBranch();
2030154cabe7SRiver Riddle       break;
2031154cabe7SRiver Riddle     case CheckOperandCount:
2032154cabe7SRiver Riddle       executeCheckOperandCount();
2033154cabe7SRiver Riddle       break;
2034154cabe7SRiver Riddle     case CheckOperationName:
2035154cabe7SRiver Riddle       executeCheckOperationName();
2036154cabe7SRiver Riddle       break;
2037154cabe7SRiver Riddle     case CheckResultCount:
2038154cabe7SRiver Riddle       executeCheckResultCount();
2039154cabe7SRiver Riddle       break;
204085ab413bSRiver Riddle     case CheckTypes:
204185ab413bSRiver Riddle       executeCheckTypes();
204285ab413bSRiver Riddle       break;
20433eb1647aSStanislav Funiak     case Continue:
20443eb1647aSStanislav Funiak       executeContinue();
20453eb1647aSStanislav Funiak       break;
2046154cabe7SRiver Riddle     case CreateOperation:
2047154cabe7SRiver Riddle       executeCreateOperation(rewriter, *mainRewriteLoc);
2048154cabe7SRiver Riddle       break;
204985ab413bSRiver Riddle     case CreateTypes:
205085ab413bSRiver Riddle       executeCreateTypes();
205185ab413bSRiver Riddle       break;
2052154cabe7SRiver Riddle     case EraseOp:
2053154cabe7SRiver Riddle       executeEraseOp(rewriter);
2054154cabe7SRiver Riddle       break;
20553eb1647aSStanislav Funiak     case ExtractOp:
20563eb1647aSStanislav Funiak       executeExtract<Operation *, OwningOpRange, PDLValue::Kind::Operation>();
20573eb1647aSStanislav Funiak       break;
20583eb1647aSStanislav Funiak     case ExtractType:
20593eb1647aSStanislav Funiak       executeExtract<Type, TypeRange, PDLValue::Kind::Type>();
20603eb1647aSStanislav Funiak       break;
20613eb1647aSStanislav Funiak     case ExtractValue:
20623eb1647aSStanislav Funiak       executeExtract<Value, ValueRange, PDLValue::Kind::Value>();
20633eb1647aSStanislav Funiak       break;
2064154cabe7SRiver Riddle     case Finalize:
20653eb1647aSStanislav Funiak       executeFinalize();
20663eb1647aSStanislav Funiak       LLVM_DEBUG(llvm::dbgs() << "\n");
2067154cabe7SRiver Riddle       return;
20683eb1647aSStanislav Funiak     case ForEach:
20693eb1647aSStanislav Funiak       executeForEach();
20703eb1647aSStanislav Funiak       break;
2071154cabe7SRiver Riddle     case GetAttribute:
2072154cabe7SRiver Riddle       executeGetAttribute();
2073154cabe7SRiver Riddle       break;
2074154cabe7SRiver Riddle     case GetAttributeType:
2075154cabe7SRiver Riddle       executeGetAttributeType();
2076154cabe7SRiver Riddle       break;
2077154cabe7SRiver Riddle     case GetDefiningOp:
2078154cabe7SRiver Riddle       executeGetDefiningOp();
2079154cabe7SRiver Riddle       break;
2080154cabe7SRiver Riddle     case GetOperand0:
2081154cabe7SRiver Riddle     case GetOperand1:
2082154cabe7SRiver Riddle     case GetOperand2:
2083154cabe7SRiver Riddle     case GetOperand3: {
2084154cabe7SRiver Riddle       unsigned index = opCode - GetOperand0;
2085154cabe7SRiver Riddle       LLVM_DEBUG(llvm::dbgs() << "Executing GetOperand" << index << ":\n");
20861fff7c89SFrederik Gossen       executeGetOperand(index);
2087abfd1a8bSRiver Riddle       break;
2088abfd1a8bSRiver Riddle     }
2089154cabe7SRiver Riddle     case GetOperandN:
2090154cabe7SRiver Riddle       LLVM_DEBUG(llvm::dbgs() << "Executing GetOperandN:\n");
2091154cabe7SRiver Riddle       executeGetOperand(read<uint32_t>());
2092154cabe7SRiver Riddle       break;
209385ab413bSRiver Riddle     case GetOperands:
209485ab413bSRiver Riddle       executeGetOperands();
209585ab413bSRiver Riddle       break;
2096154cabe7SRiver Riddle     case GetResult0:
2097154cabe7SRiver Riddle     case GetResult1:
2098154cabe7SRiver Riddle     case GetResult2:
2099154cabe7SRiver Riddle     case GetResult3: {
2100154cabe7SRiver Riddle       unsigned index = opCode - GetResult0;
2101154cabe7SRiver Riddle       LLVM_DEBUG(llvm::dbgs() << "Executing GetResult" << index << ":\n");
21021fff7c89SFrederik Gossen       executeGetResult(index);
2103154cabe7SRiver Riddle       break;
2104abfd1a8bSRiver Riddle     }
2105154cabe7SRiver Riddle     case GetResultN:
2106154cabe7SRiver Riddle       LLVM_DEBUG(llvm::dbgs() << "Executing GetResultN:\n");
2107154cabe7SRiver Riddle       executeGetResult(read<uint32_t>());
2108154cabe7SRiver Riddle       break;
210985ab413bSRiver Riddle     case GetResults:
211085ab413bSRiver Riddle       executeGetResults();
211185ab413bSRiver Riddle       break;
21123eb1647aSStanislav Funiak     case GetUsers:
21133eb1647aSStanislav Funiak       executeGetUsers();
21143eb1647aSStanislav Funiak       break;
2115154cabe7SRiver Riddle     case GetValueType:
2116154cabe7SRiver Riddle       executeGetValueType();
2117154cabe7SRiver Riddle       break;
211885ab413bSRiver Riddle     case GetValueRangeTypes:
211985ab413bSRiver Riddle       executeGetValueRangeTypes();
212085ab413bSRiver Riddle       break;
2121154cabe7SRiver Riddle     case IsNotNull:
2122154cabe7SRiver Riddle       executeIsNotNull();
2123154cabe7SRiver Riddle       break;
2124154cabe7SRiver Riddle     case RecordMatch:
2125154cabe7SRiver Riddle       assert(matches &&
2126154cabe7SRiver Riddle              "expected matches to be provided when executing the matcher");
2127154cabe7SRiver Riddle       executeRecordMatch(rewriter, *matches);
2128154cabe7SRiver Riddle       break;
2129154cabe7SRiver Riddle     case ReplaceOp:
2130154cabe7SRiver Riddle       executeReplaceOp(rewriter);
2131154cabe7SRiver Riddle       break;
2132154cabe7SRiver Riddle     case SwitchAttribute:
2133154cabe7SRiver Riddle       executeSwitchAttribute();
2134154cabe7SRiver Riddle       break;
2135154cabe7SRiver Riddle     case SwitchOperandCount:
2136154cabe7SRiver Riddle       executeSwitchOperandCount();
2137154cabe7SRiver Riddle       break;
2138154cabe7SRiver Riddle     case SwitchOperationName:
2139154cabe7SRiver Riddle       executeSwitchOperationName();
2140154cabe7SRiver Riddle       break;
2141154cabe7SRiver Riddle     case SwitchResultCount:
2142154cabe7SRiver Riddle       executeSwitchResultCount();
2143154cabe7SRiver Riddle       break;
2144154cabe7SRiver Riddle     case SwitchType:
2145154cabe7SRiver Riddle       executeSwitchType();
2146154cabe7SRiver Riddle       break;
214785ab413bSRiver Riddle     case SwitchTypes:
214885ab413bSRiver Riddle       executeSwitchTypes();
214985ab413bSRiver Riddle       break;
2150154cabe7SRiver Riddle     }
2151154cabe7SRiver Riddle     LLVM_DEBUG(llvm::dbgs() << "\n");
2152abfd1a8bSRiver Riddle   }
2153abfd1a8bSRiver Riddle }
2154abfd1a8bSRiver Riddle 
2155abfd1a8bSRiver Riddle /// Run the pattern matcher on the given root operation, collecting the matched
2156abfd1a8bSRiver Riddle /// patterns in `matches`.
2157abfd1a8bSRiver Riddle void PDLByteCode::match(Operation *op, PatternRewriter &rewriter,
2158abfd1a8bSRiver Riddle                         SmallVectorImpl<MatchResult> &matches,
2159abfd1a8bSRiver Riddle                         PDLByteCodeMutableState &state) const {
2160abfd1a8bSRiver Riddle   // The first memory slot is always the root operation.
2161abfd1a8bSRiver Riddle   state.memory[0] = op;
2162abfd1a8bSRiver Riddle 
2163abfd1a8bSRiver Riddle   // The matcher function always starts at code address 0.
216485ab413bSRiver Riddle   ByteCodeExecutor executor(
21653eb1647aSStanislav Funiak       matcherByteCode.data(), state.memory, state.opRangeMemory,
21663eb1647aSStanislav Funiak       state.typeRangeMemory, state.allocatedTypeRangeMemory,
21673eb1647aSStanislav Funiak       state.valueRangeMemory, state.allocatedValueRangeMemory, state.loopIndex,
21683eb1647aSStanislav Funiak       uniquedData, matcherByteCode, state.currentPatternBenefits, patterns,
21693eb1647aSStanislav Funiak       constraintFunctions, rewriteFunctions);
2170abfd1a8bSRiver Riddle   executor.execute(rewriter, &matches);
2171abfd1a8bSRiver Riddle 
2172abfd1a8bSRiver Riddle   // Order the found matches by benefit.
2173abfd1a8bSRiver Riddle   std::stable_sort(matches.begin(), matches.end(),
2174abfd1a8bSRiver Riddle                    [](const MatchResult &lhs, const MatchResult &rhs) {
2175abfd1a8bSRiver Riddle                      return lhs.benefit > rhs.benefit;
2176abfd1a8bSRiver Riddle                    });
2177abfd1a8bSRiver Riddle }
2178abfd1a8bSRiver Riddle 
2179abfd1a8bSRiver Riddle /// Run the rewriter of the given pattern on the root operation `op`.
2180abfd1a8bSRiver Riddle void PDLByteCode::rewrite(PatternRewriter &rewriter, const MatchResult &match,
2181abfd1a8bSRiver Riddle                           PDLByteCodeMutableState &state) const {
2182abfd1a8bSRiver Riddle   // The arguments of the rewrite function are stored at the start of the
2183abfd1a8bSRiver Riddle   // memory buffer.
2184abfd1a8bSRiver Riddle   llvm::copy(match.values, state.memory.begin());
2185abfd1a8bSRiver Riddle 
218685ab413bSRiver Riddle   ByteCodeExecutor executor(
218785ab413bSRiver Riddle       &rewriterByteCode[match.pattern->getRewriterAddr()], state.memory,
21883eb1647aSStanislav Funiak       state.opRangeMemory, state.typeRangeMemory,
21893eb1647aSStanislav Funiak       state.allocatedTypeRangeMemory, state.valueRangeMemory,
21903eb1647aSStanislav Funiak       state.allocatedValueRangeMemory, state.loopIndex, uniquedData,
219185ab413bSRiver Riddle       rewriterByteCode, state.currentPatternBenefits, patterns,
219202c4c0d5SRiver Riddle       constraintFunctions, rewriteFunctions);
2193abfd1a8bSRiver Riddle   executor.execute(rewriter, /*matches=*/nullptr, match.location);
2194abfd1a8bSRiver Riddle }
2195