1 | //===-- mlir-c/Rewrite.h - Helpers for C API to Rewrites ----------*- C -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM |
4 | // Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This header declares the registration and creation method for |
11 | // rewrite patterns. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef MLIR_C_REWRITE_H |
16 | #define MLIR_C_REWRITE_H |
17 | |
18 | #include "mlir-c/IR.h" |
19 | #include "mlir-c/Support.h" |
20 | #include "mlir/Config/mlir-config.h" |
21 | |
22 | #ifdef __cplusplus |
23 | extern "C" { |
24 | #endif |
25 | |
26 | //===----------------------------------------------------------------------===// |
27 | /// Opaque type declarations (see mlir-c/IR.h for more details). |
28 | //===----------------------------------------------------------------------===// |
29 | |
30 | #define DEFINE_C_API_STRUCT(name, storage) \ |
31 | struct name { \ |
32 | storage *ptr; \ |
33 | }; \ |
34 | typedef struct name name |
35 | |
36 | DEFINE_C_API_STRUCT(MlirRewriterBase, void); |
37 | DEFINE_C_API_STRUCT(MlirFrozenRewritePatternSet, void); |
38 | DEFINE_C_API_STRUCT(MlirGreedyRewriteDriverConfig, void); |
39 | DEFINE_C_API_STRUCT(MlirRewritePatternSet, void); |
40 | |
41 | //===----------------------------------------------------------------------===// |
42 | /// RewriterBase API inherited from OpBuilder |
43 | //===----------------------------------------------------------------------===// |
44 | |
45 | /// Get the MLIR context referenced by the rewriter. |
46 | MLIR_CAPI_EXPORTED MlirContext |
47 | mlirRewriterBaseGetContext(MlirRewriterBase rewriter); |
48 | |
49 | //===----------------------------------------------------------------------===// |
50 | /// Insertion points methods |
51 | //===----------------------------------------------------------------------===// |
52 | |
53 | // These do not include functions using Block::iterator or Region::iterator, as |
54 | // they are not exposed by the C API yet. Similarly for methods using |
55 | // `InsertPoint` directly. |
56 | |
57 | /// Reset the insertion point to no location. Creating an operation without a |
58 | /// set insertion point is an error, but this can still be useful when the |
59 | /// current insertion point a builder refers to is being removed. |
60 | MLIR_CAPI_EXPORTED void |
61 | mlirRewriterBaseClearInsertionPoint(MlirRewriterBase rewriter); |
62 | |
63 | /// Sets the insertion point to the specified operation, which will cause |
64 | /// subsequent insertions to go right before it. |
65 | MLIR_CAPI_EXPORTED void |
66 | mlirRewriterBaseSetInsertionPointBefore(MlirRewriterBase rewriter, |
67 | MlirOperation op); |
68 | |
69 | /// Sets the insertion point to the node after the specified operation, which |
70 | /// will cause subsequent insertions to go right after it. |
71 | MLIR_CAPI_EXPORTED void |
72 | mlirRewriterBaseSetInsertionPointAfter(MlirRewriterBase rewriter, |
73 | MlirOperation op); |
74 | |
75 | /// Sets the insertion point to the node after the specified value. If value |
76 | /// has a defining operation, sets the insertion point to the node after such |
77 | /// defining operation. This will cause subsequent insertions to go right |
78 | /// after it. Otherwise, value is a BlockArgument. Sets the insertion point to |
79 | /// the start of its block. |
80 | MLIR_CAPI_EXPORTED void |
81 | mlirRewriterBaseSetInsertionPointAfterValue(MlirRewriterBase rewriter, |
82 | MlirValue value); |
83 | |
84 | /// Sets the insertion point to the start of the specified block. |
85 | MLIR_CAPI_EXPORTED void |
86 | mlirRewriterBaseSetInsertionPointToStart(MlirRewriterBase rewriter, |
87 | MlirBlock block); |
88 | |
89 | /// Sets the insertion point to the end of the specified block. |
90 | MLIR_CAPI_EXPORTED void |
91 | mlirRewriterBaseSetInsertionPointToEnd(MlirRewriterBase rewriter, |
92 | MlirBlock block); |
93 | |
94 | /// Return the block the current insertion point belongs to. Note that the |
95 | /// insertion point is not necessarily the end of the block. |
96 | MLIR_CAPI_EXPORTED MlirBlock |
97 | mlirRewriterBaseGetInsertionBlock(MlirRewriterBase rewriter); |
98 | |
99 | /// Returns the current block of the rewriter. |
100 | MLIR_CAPI_EXPORTED MlirBlock |
101 | mlirRewriterBaseGetBlock(MlirRewriterBase rewriter); |
102 | |
103 | //===----------------------------------------------------------------------===// |
104 | /// Block and operation creation/insertion/cloning |
105 | //===----------------------------------------------------------------------===// |
106 | |
107 | // These functions do not include the IRMapper, as it is not yet exposed by the |
108 | // C API. |
109 | |
110 | /// Add new block with 'argTypes' arguments and set the insertion point to the |
111 | /// end of it. The block is placed before 'insertBefore'. `locs` contains the |
112 | /// locations of the inserted arguments, and should match the size of |
113 | /// `argTypes`. |
114 | MLIR_CAPI_EXPORTED MlirBlock mlirRewriterBaseCreateBlockBefore( |
115 | MlirRewriterBase rewriter, MlirBlock insertBefore, intptr_t nArgTypes, |
116 | MlirType const *argTypes, MlirLocation const *locations); |
117 | |
118 | /// Insert the given operation at the current insertion point and return it. |
119 | MLIR_CAPI_EXPORTED MlirOperation |
120 | mlirRewriterBaseInsert(MlirRewriterBase rewriter, MlirOperation op); |
121 | |
122 | /// Creates a deep copy of the specified operation. |
123 | MLIR_CAPI_EXPORTED MlirOperation |
124 | mlirRewriterBaseClone(MlirRewriterBase rewriter, MlirOperation op); |
125 | |
126 | /// Creates a deep copy of this operation but keep the operation regions |
127 | /// empty. |
128 | MLIR_CAPI_EXPORTED MlirOperation mlirRewriterBaseCloneWithoutRegions( |
129 | MlirRewriterBase rewriter, MlirOperation op); |
130 | |
131 | /// Clone the blocks that belong to "region" before the given position in |
132 | /// another region "parent". |
133 | MLIR_CAPI_EXPORTED void |
134 | mlirRewriterBaseCloneRegionBefore(MlirRewriterBase rewriter, MlirRegion region, |
135 | MlirBlock before); |
136 | |
137 | //===----------------------------------------------------------------------===// |
138 | /// RewriterBase API |
139 | //===----------------------------------------------------------------------===// |
140 | |
141 | /// Move the blocks that belong to "region" before the given position in |
142 | /// another region "parent". The two regions must be different. The caller |
143 | /// is responsible for creating or updating the operation transferring flow |
144 | /// of control to the region and passing it the correct block arguments. |
145 | MLIR_CAPI_EXPORTED void |
146 | mlirRewriterBaseInlineRegionBefore(MlirRewriterBase rewriter, MlirRegion region, |
147 | MlirBlock before); |
148 | |
149 | /// Replace the results of the given (original) operation with the specified |
150 | /// list of values (replacements). The result types of the given op and the |
151 | /// replacements must match. The original op is erased. |
152 | MLIR_CAPI_EXPORTED void |
153 | mlirRewriterBaseReplaceOpWithValues(MlirRewriterBase rewriter, MlirOperation op, |
154 | intptr_t nValues, MlirValue const *values); |
155 | |
156 | /// Replace the results of the given (original) operation with the specified |
157 | /// new op (replacement). The result types of the two ops must match. The |
158 | /// original op is erased. |
159 | MLIR_CAPI_EXPORTED void |
160 | mlirRewriterBaseReplaceOpWithOperation(MlirRewriterBase rewriter, |
161 | MlirOperation op, MlirOperation newOp); |
162 | |
163 | /// Erases an operation that is known to have no uses. |
164 | MLIR_CAPI_EXPORTED void mlirRewriterBaseEraseOp(MlirRewriterBase rewriter, |
165 | MlirOperation op); |
166 | |
167 | /// Erases a block along with all operations inside it. |
168 | MLIR_CAPI_EXPORTED void mlirRewriterBaseEraseBlock(MlirRewriterBase rewriter, |
169 | MlirBlock block); |
170 | |
171 | /// Inline the operations of block 'source' before the operation 'op'. The |
172 | /// source block will be deleted and must have no uses. 'argValues' is used to |
173 | /// replace the block arguments of 'source' |
174 | /// |
175 | /// The source block must have no successors. Otherwise, the resulting IR |
176 | /// would have unreachable operations. |
177 | MLIR_CAPI_EXPORTED void |
178 | mlirRewriterBaseInlineBlockBefore(MlirRewriterBase rewriter, MlirBlock source, |
179 | MlirOperation op, intptr_t nArgValues, |
180 | MlirValue const *argValues); |
181 | |
182 | /// Inline the operations of block 'source' into the end of block 'dest'. The |
183 | /// source block will be deleted and must have no uses. 'argValues' is used to |
184 | /// replace the block arguments of 'source' |
185 | /// |
186 | /// The dest block must have no successors. Otherwise, the resulting IR would |
187 | /// have unreachable operation. |
188 | MLIR_CAPI_EXPORTED void mlirRewriterBaseMergeBlocks(MlirRewriterBase rewriter, |
189 | MlirBlock source, |
190 | MlirBlock dest, |
191 | intptr_t nArgValues, |
192 | MlirValue const *argValues); |
193 | |
194 | /// Unlink this operation from its current block and insert it right before |
195 | /// `existingOp` which may be in the same or another block in the same |
196 | /// function. |
197 | MLIR_CAPI_EXPORTED void mlirRewriterBaseMoveOpBefore(MlirRewriterBase rewriter, |
198 | MlirOperation op, |
199 | MlirOperation existingOp); |
200 | |
201 | /// Unlink this operation from its current block and insert it right after |
202 | /// `existingOp` which may be in the same or another block in the same |
203 | /// function. |
204 | MLIR_CAPI_EXPORTED void mlirRewriterBaseMoveOpAfter(MlirRewriterBase rewriter, |
205 | MlirOperation op, |
206 | MlirOperation existingOp); |
207 | |
208 | /// Unlink this block and insert it right before `existingBlock`. |
209 | MLIR_CAPI_EXPORTED void |
210 | mlirRewriterBaseMoveBlockBefore(MlirRewriterBase rewriter, MlirBlock block, |
211 | MlirBlock existingBlock); |
212 | |
213 | /// This method is used to notify the rewriter that an in-place operation |
214 | /// modification is about to happen. A call to this function *must* be |
215 | /// followed by a call to either `finalizeOpModification` or |
216 | /// `cancelOpModification`. This is a minor efficiency win (it avoids creating |
217 | /// a new operation and removing the old one) but also often allows simpler |
218 | /// code in the client. |
219 | MLIR_CAPI_EXPORTED void |
220 | mlirRewriterBaseStartOpModification(MlirRewriterBase rewriter, |
221 | MlirOperation op); |
222 | |
223 | /// This method is used to signal the end of an in-place modification of the |
224 | /// given operation. This can only be called on operations that were provided |
225 | /// to a call to `startOpModification`. |
226 | MLIR_CAPI_EXPORTED void |
227 | mlirRewriterBaseFinalizeOpModification(MlirRewriterBase rewriter, |
228 | MlirOperation op); |
229 | |
230 | /// This method cancels a pending in-place modification. This can only be |
231 | /// called on operations that were provided to a call to |
232 | /// `startOpModification`. |
233 | MLIR_CAPI_EXPORTED void |
234 | mlirRewriterBaseCancelOpModification(MlirRewriterBase rewriter, |
235 | MlirOperation op); |
236 | |
237 | /// Find uses of `from` and replace them with `to`. Also notify the listener |
238 | /// about every in-place op modification (for every use that was replaced). |
239 | MLIR_CAPI_EXPORTED void |
240 | mlirRewriterBaseReplaceAllUsesWith(MlirRewriterBase rewriter, MlirValue from, |
241 | MlirValue to); |
242 | |
243 | /// Find uses of `from` and replace them with `to`. Also notify the listener |
244 | /// about every in-place op modification (for every use that was replaced). |
245 | MLIR_CAPI_EXPORTED void mlirRewriterBaseReplaceAllValueRangeUsesWith( |
246 | MlirRewriterBase rewriter, intptr_t nValues, MlirValue const *from, |
247 | MlirValue const *to); |
248 | |
249 | /// Find uses of `from` and replace them with `to`. Also notify the listener |
250 | /// about every in-place op modification (for every use that was replaced) |
251 | /// and that the `from` operation is about to be replaced. |
252 | MLIR_CAPI_EXPORTED void |
253 | mlirRewriterBaseReplaceAllOpUsesWithValueRange(MlirRewriterBase rewriter, |
254 | MlirOperation from, intptr_t nTo, |
255 | MlirValue const *to); |
256 | |
257 | /// Find uses of `from` and replace them with `to`. Also notify the listener |
258 | /// about every in-place op modification (for every use that was replaced) |
259 | /// and that the `from` operation is about to be replaced. |
260 | MLIR_CAPI_EXPORTED void mlirRewriterBaseReplaceAllOpUsesWithOperation( |
261 | MlirRewriterBase rewriter, MlirOperation from, MlirOperation to); |
262 | |
263 | /// Find uses of `from` within `block` and replace them with `to`. Also notify |
264 | /// the listener about every in-place op modification (for every use that was |
265 | /// replaced). The optional `allUsesReplaced` flag is set to "true" if all |
266 | /// uses were replaced. |
267 | MLIR_CAPI_EXPORTED void mlirRewriterBaseReplaceOpUsesWithinBlock( |
268 | MlirRewriterBase rewriter, MlirOperation op, intptr_t nNewValues, |
269 | MlirValue const *newValues, MlirBlock block); |
270 | |
271 | /// Find uses of `from` and replace them with `to` except if the user is |
272 | /// `exceptedUser`. Also notify the listener about every in-place op |
273 | /// modification (for every use that was replaced). |
274 | MLIR_CAPI_EXPORTED void |
275 | mlirRewriterBaseReplaceAllUsesExcept(MlirRewriterBase rewriter, MlirValue from, |
276 | MlirValue to, MlirOperation exceptedUser); |
277 | |
278 | //===----------------------------------------------------------------------===// |
279 | /// IRRewriter API |
280 | //===----------------------------------------------------------------------===// |
281 | |
282 | /// Create an IRRewriter and transfer ownership to the caller. |
283 | MLIR_CAPI_EXPORTED MlirRewriterBase mlirIRRewriterCreate(MlirContext context); |
284 | |
285 | /// Create an IRRewriter and transfer ownership to the caller. Additionally |
286 | /// set the insertion point before the operation. |
287 | MLIR_CAPI_EXPORTED MlirRewriterBase |
288 | mlirIRRewriterCreateFromOp(MlirOperation op); |
289 | |
290 | /// Takes an IRRewriter owned by the caller and destroys it. It is the |
291 | /// responsibility of the user to only pass an IRRewriter class. |
292 | MLIR_CAPI_EXPORTED void mlirIRRewriterDestroy(MlirRewriterBase rewriter); |
293 | |
294 | //===----------------------------------------------------------------------===// |
295 | /// FrozenRewritePatternSet API |
296 | //===----------------------------------------------------------------------===// |
297 | |
298 | MLIR_CAPI_EXPORTED MlirFrozenRewritePatternSet |
299 | mlirFreezeRewritePattern(MlirRewritePatternSet op); |
300 | |
301 | MLIR_CAPI_EXPORTED void |
302 | mlirFrozenRewritePatternSetDestroy(MlirFrozenRewritePatternSet op); |
303 | |
304 | MLIR_CAPI_EXPORTED MlirLogicalResult mlirApplyPatternsAndFoldGreedily( |
305 | MlirModule op, MlirFrozenRewritePatternSet patterns, |
306 | MlirGreedyRewriteDriverConfig); |
307 | |
308 | //===----------------------------------------------------------------------===// |
309 | /// PDLPatternModule API |
310 | //===----------------------------------------------------------------------===// |
311 | |
312 | #if MLIR_ENABLE_PDL_IN_PATTERNMATCH |
313 | DEFINE_C_API_STRUCT(MlirPDLPatternModule, void); |
314 | |
315 | MLIR_CAPI_EXPORTED MlirPDLPatternModule |
316 | mlirPDLPatternModuleFromModule(MlirModule op); |
317 | |
318 | MLIR_CAPI_EXPORTED void mlirPDLPatternModuleDestroy(MlirPDLPatternModule op); |
319 | |
320 | MLIR_CAPI_EXPORTED MlirRewritePatternSet |
321 | mlirRewritePatternSetFromPDLPatternModule(MlirPDLPatternModule op); |
322 | #endif // MLIR_ENABLE_PDL_IN_PATTERNMATCH |
323 | |
324 | #undef DEFINE_C_API_STRUCT |
325 | |
326 | #ifdef __cplusplus |
327 | } |
328 | #endif |
329 | |
330 | #endif // MLIR_C_REWRITE_H |
331 | |