MLIR  18.0.0git
ByteCode.h
Go to the documentation of this file.
1 //===- ByteCode.h - Pattern byte-code interpreter ---------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares a byte-code and interpreter for pattern rewrites in MLIR.
10 // The byte-code is constructed from the PDL Interpreter dialect.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_REWRITE_BYTECODE_H_
15 #define MLIR_REWRITE_BYTECODE_H_
16 
17 #include "mlir/IR/PatternMatch.h"
18 
19 namespace mlir {
20 namespace pdl_interp {
21 class RecordMatchOp;
22 } // namespace pdl_interp
23 
24 namespace detail {
25 class PDLByteCode;
26 
27 /// Use generic bytecode types. ByteCodeField refers to the actual bytecode
28 /// entries. ByteCodeAddr refers to size of indices into the bytecode.
29 using ByteCodeField = uint16_t;
30 using ByteCodeAddr = uint32_t;
31 using OwningOpRange = llvm::OwningArrayRef<Operation *>;
32 
33 //===----------------------------------------------------------------------===//
34 // PDLByteCodePattern
35 //===----------------------------------------------------------------------===//
36 
37 /// All of the data pertaining to a specific pattern within the bytecode.
38 class PDLByteCodePattern : public Pattern {
39 public:
40  static PDLByteCodePattern create(pdl_interp::RecordMatchOp matchOp,
41  PDLPatternConfigSet *configSet,
42  ByteCodeAddr rewriterAddr);
43 
44  /// Return the bytecode address of the rewriter for this pattern.
45  ByteCodeAddr getRewriterAddr() const { return rewriterAddr; }
46 
47  /// Return the configuration set for this pattern, or null if there is none.
48  PDLPatternConfigSet *getConfigSet() const { return configSet; }
49 
50 private:
51  template <typename... Args>
52  PDLByteCodePattern(ByteCodeAddr rewriterAddr, PDLPatternConfigSet *configSet,
53  Args &&...patternArgs)
54  : Pattern(std::forward<Args>(patternArgs)...), rewriterAddr(rewriterAddr),
55  configSet(configSet) {}
56 
57  /// The address of the rewriter for this pattern.
58  ByteCodeAddr rewriterAddr;
59 
60  /// The optional config set for this pattern.
61  PDLPatternConfigSet *configSet;
62 };
63 
64 //===----------------------------------------------------------------------===//
65 // PDLByteCodeMutableState
66 //===----------------------------------------------------------------------===//
67 
68 /// This class contains the mutable state of a bytecode instance. This allows
69 /// for a bytecode instance to be cached and reused across various different
70 /// threads/drivers.
72 public:
73  /// Set the new benefit for a bytecode pattern. The `patternIndex` corresponds
74  /// to the position of the pattern within the range returned by
75  /// `PDLByteCode::getPatterns`.
76  void updatePatternBenefit(unsigned patternIndex, PatternBenefit benefit);
77 
78  /// Cleanup any allocated state after a match/rewrite has been completed. This
79  /// method should be called irregardless of whether the match+rewrite was a
80  /// success or not.
82 
83 private:
84  /// Allow access to data fields.
85  friend class PDLByteCode;
86 
87  /// The mutable block of memory used during the matching and rewriting phases
88  /// of the bytecode.
89  std::vector<const void *> memory;
90 
91  /// A mutable block of memory used during the matching and rewriting phase of
92  /// the bytecode to store ranges of operations. These are always stored by
93  /// owning references, because at no point in the execution of the byte code
94  /// we get an indexed range (view) of operations.
95  std::vector<OwningOpRange> opRangeMemory;
96 
97  /// A mutable block of memory used during the matching and rewriting phase of
98  /// the bytecode to store ranges of types.
99  std::vector<TypeRange> typeRangeMemory;
100  /// A set of type ranges that have been allocated by the byte code interpreter
101  /// to provide a guaranteed lifetime.
102  std::vector<llvm::OwningArrayRef<Type>> allocatedTypeRangeMemory;
103 
104  /// A mutable block of memory used during the matching and rewriting phase of
105  /// the bytecode to store ranges of values.
106  std::vector<ValueRange> valueRangeMemory;
107  /// A set of value ranges that have been allocated by the byte code
108  /// interpreter to provide a guaranteed lifetime.
109  std::vector<llvm::OwningArrayRef<Value>> allocatedValueRangeMemory;
110 
111  /// The current index of ranges being iterated over for each level of nesting.
112  /// These are always maintained at 0 for the loops that are not active, so we
113  /// do not need to have a separate initialization phase for each loop.
114  std::vector<unsigned> loopIndex;
115 
116  /// The up-to-date benefits of the patterns held by the bytecode. The order
117  /// of this array corresponds 1-1 with the array of patterns in `PDLByteCode`.
118  std::vector<PatternBenefit> currentPatternBenefits;
119 };
120 
121 //===----------------------------------------------------------------------===//
122 // PDLByteCode
123 //===----------------------------------------------------------------------===//
124 
125 /// The bytecode class is also the interpreter. Contains the bytecode itself,
126 /// the static info, addresses of the rewriter functions, the interpreter
127 /// memory buffer, and the execution context.
128 class PDLByteCode {
129 public:
130  /// Each successful match returns a MatchResult, which contains information
131  /// necessary to execute the rewriter and indicates the originating pattern.
132  struct MatchResult {
135  : location(loc), pattern(&pattern), benefit(benefit) {}
136  MatchResult(const MatchResult &) = delete;
137  MatchResult &operator=(const MatchResult &) = delete;
138  MatchResult(MatchResult &&other) = default;
140 
141  /// The location of operations to be replaced.
143  /// Memory values defined in the matcher that are passed to the rewriter.
145  /// Memory used for the range input values.
148 
149  /// The originating pattern that was matched. This is always non-null, but
150  /// represented with a pointer to allow for assignment.
152  /// The current benefit of the pattern that was matched.
154  };
155 
156  /// Create a ByteCode instance from the given module containing operations in
157  /// the PDL interpreter dialect.
158  PDLByteCode(ModuleOp module,
159  SmallVector<std::unique_ptr<PDLPatternConfigSet>> configs,
161  llvm::StringMap<PDLConstraintFunction> constraintFns,
162  llvm::StringMap<PDLRewriteFunction> rewriteFns);
163 
164  /// Return the patterns held by the bytecode.
165  ArrayRef<PDLByteCodePattern> getPatterns() const { return patterns; }
166 
167  /// Initialize the given state such that it can be used to execute the current
168  /// bytecode.
170 
171  /// Run the pattern matcher on the given root operation, collecting the
172  /// matched patterns in `matches`.
173  void match(Operation *op, PatternRewriter &rewriter,
175  PDLByteCodeMutableState &state) const;
176 
177  /// Run the rewriter of the given pattern that was previously matched in
178  /// `match`. Returns if a failure was encountered during the rewrite.
179  LogicalResult rewrite(PatternRewriter &rewriter, const MatchResult &match,
180  PDLByteCodeMutableState &state) const;
181 
182 private:
183  /// Execute the given byte code starting at the provided instruction `inst`.
184  /// `matches` is an optional field provided when this function is executed in
185  /// a matching context.
186  void executeByteCode(const ByteCodeField *inst, PatternRewriter &rewriter,
188  SmallVectorImpl<MatchResult> *matches) const;
189 
190  /// The set of pattern configs referenced within the bytecode.
192 
193  /// A vector containing pointers to uniqued data. The storage is intentionally
194  /// opaque such that we can store a wide range of data types. The types of
195  /// data stored here include:
196  /// * Attribute, OperationName, Type
197  std::vector<const void *> uniquedData;
198 
199  /// A vector containing the generated bytecode for the matcher.
200  SmallVector<ByteCodeField, 64> matcherByteCode;
201 
202  /// A vector containing the generated bytecode for all of the rewriters.
203  SmallVector<ByteCodeField, 64> rewriterByteCode;
204 
205  /// The set of patterns contained within the bytecode.
207 
208  /// A set of user defined functions invoked via PDL.
209  std::vector<PDLConstraintFunction> constraintFunctions;
210  std::vector<PDLRewriteFunction> rewriteFunctions;
211 
212  /// The maximum memory index used by a value.
213  ByteCodeField maxValueMemoryIndex = 0;
214 
215  /// The maximum number of different types of ranges.
216  ByteCodeField maxOpRangeCount = 0;
217  ByteCodeField maxTypeRangeCount = 0;
218  ByteCodeField maxValueRangeCount = 0;
219 
220  /// The maximum number of nested loops.
221  ByteCodeField maxLoopLevel = 0;
222 };
223 
224 } // namespace detail
225 } // namespace mlir
226 
227 #endif // MLIR_REWRITE_BYTECODE_H_
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
This class contains a set of configurations for a specific pattern.
Definition: PatternMatch.h:979
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
Definition: PatternMatch.h:33
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
Definition: PatternMatch.h:727
This class contains all of the data related to a pattern, but does not contain any methods or logic f...
Definition: PatternMatch.h:72
This class contains the mutable state of a bytecode instance.
Definition: ByteCode.h:71
void updatePatternBenefit(unsigned patternIndex, PatternBenefit benefit)
Set the new benefit for a bytecode pattern.
Definition: ByteCode.cpp:64
void cleanupAfterMatchAndRewrite()
Cleanup any allocated state after a match/rewrite has been completed.
Definition: ByteCode.cpp:72
All of the data pertaining to a specific pattern within the bytecode.
Definition: ByteCode.h:38
ByteCodeAddr getRewriterAddr() const
Return the bytecode address of the rewriter for this pattern.
Definition: ByteCode.h:45
PDLPatternConfigSet * getConfigSet() const
Return the configuration set for this pattern, or null if there is none.
Definition: ByteCode.h:48
static PDLByteCodePattern create(pdl_interp::RecordMatchOp matchOp, PDLPatternConfigSet *configSet, ByteCodeAddr rewriterAddr)
Definition: ByteCode.cpp:37
The bytecode class is also the interpreter.
Definition: ByteCode.h:128
ArrayRef< PDLByteCodePattern > getPatterns() const
Return the patterns held by the bytecode.
Definition: ByteCode.h:165
void match(Operation *op, PatternRewriter &rewriter, SmallVectorImpl< MatchResult > &matches, PDLByteCodeMutableState &state) const
Run the pattern matcher on the given root operation, collecting the matched patterns in matches.
Definition: ByteCode.cpp:2273
PDLByteCode(ModuleOp module, SmallVector< std::unique_ptr< PDLPatternConfigSet >> configs, const DenseMap< Operation *, PDLPatternConfigSet * > &configMap, llvm::StringMap< PDLConstraintFunction > constraintFns, llvm::StringMap< PDLRewriteFunction > rewriteFns)
Create a ByteCode instance from the given module containing operations in the PDL interpreter dialect...
Definition: ByteCode.cpp:1043
void initializeMutableState(PDLByteCodeMutableState &state) const
Initialize the given state such that it can be used to execute the current bytecode.
Definition: ByteCode.cpp:1064
LogicalResult rewrite(PatternRewriter &rewriter, const MatchResult &match, PDLByteCodeMutableState &state) const
Run the rewriter of the given pattern that was previously matched in match.
Definition: ByteCode.cpp:2297
uint32_t ByteCodeAddr
Definition: ByteCode.h:30
uint16_t ByteCodeField
Use generic bytecode types.
Definition: ByteCode.h:29
llvm::OwningArrayRef< Operation * > OwningOpRange
Definition: ByteCode.h:31
This header declares functions that assist transformations in the MemRef dialect.
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
Each successful match returns a MatchResult, which contains information necessary to execute the rewr...
Definition: ByteCode.h:132
MatchResult & operator=(const MatchResult &)=delete
PatternBenefit benefit
The current benefit of the pattern that was matched.
Definition: ByteCode.h:153
const PDLByteCodePattern * pattern
The originating pattern that was matched.
Definition: ByteCode.h:151
SmallVector< TypeRange, 0 > typeRangeValues
Memory used for the range input values.
Definition: ByteCode.h:146
MatchResult(Location loc, const PDLByteCodePattern &pattern, PatternBenefit benefit)
Definition: ByteCode.h:133
SmallVector< ValueRange, 0 > valueRangeValues
Definition: ByteCode.h:147
MatchResult & operator=(MatchResult &&)=default
SmallVector< const void * > values
Memory values defined in the matcher that are passed to the rewriter.
Definition: ByteCode.h:144
Location location
The location of operations to be replaced.
Definition: ByteCode.h:142
MatchResult(MatchResult &&other)=default
MatchResult(const MatchResult &)=delete