File: | build/source/mlir/include/mlir/IR/OpDefinition.h |
Warning: | line 114, column 5 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- SuperVectorize.cpp - Vectorize Pass Impl ---------------------------===// | ||||
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 implements vectorization of loops, operations and data types to | ||||
10 | // a target-independent, n-D super-vector abstraction. | ||||
11 | // | ||||
12 | //===----------------------------------------------------------------------===// | ||||
13 | |||||
14 | #include "mlir/Dialect/Affine/Passes.h" | ||||
15 | |||||
16 | #include "mlir/Analysis/SliceAnalysis.h" | ||||
17 | #include "mlir/Dialect/Affine/Analysis/AffineAnalysis.h" | ||||
18 | #include "mlir/Dialect/Affine/Analysis/LoopAnalysis.h" | ||||
19 | #include "mlir/Dialect/Affine/Analysis/NestedMatcher.h" | ||||
20 | #include "mlir/Dialect/Affine/IR/AffineOps.h" | ||||
21 | #include "mlir/Dialect/Affine/Utils.h" | ||||
22 | #include "mlir/Dialect/Arith/IR/Arith.h" | ||||
23 | #include "mlir/Dialect/Func/IR/FuncOps.h" | ||||
24 | #include "mlir/Dialect/Vector/IR/VectorOps.h" | ||||
25 | #include "mlir/Dialect/Vector/Utils/VectorUtils.h" | ||||
26 | #include "mlir/IR/IRMapping.h" | ||||
27 | #include "mlir/Pass/Pass.h" | ||||
28 | #include "mlir/Support/LLVM.h" | ||||
29 | #include "llvm/ADT/STLExtras.h" | ||||
30 | #include "llvm/Support/Debug.h" | ||||
31 | #include <optional> | ||||
32 | |||||
33 | namespace mlir { | ||||
34 | namespace affine { | ||||
35 | #define GEN_PASS_DEF_AFFINEVECTORIZE | ||||
36 | #include "mlir/Dialect/Affine/Passes.h.inc" | ||||
37 | } // namespace affine | ||||
38 | } // namespace mlir | ||||
39 | |||||
40 | using namespace mlir; | ||||
41 | using namespace affine; | ||||
42 | using namespace vector; | ||||
43 | |||||
44 | /// | ||||
45 | /// Implements a high-level vectorization strategy on a Function. | ||||
46 | /// The abstraction used is that of super-vectors, which provide a single, | ||||
47 | /// compact, representation in the vector types, information that is expected | ||||
48 | /// to reduce the impact of the phase ordering problem | ||||
49 | /// | ||||
50 | /// Vector granularity: | ||||
51 | /// =================== | ||||
52 | /// This pass is designed to perform vectorization at a super-vector | ||||
53 | /// granularity. A super-vector is loosely defined as a vector type that is a | ||||
54 | /// multiple of a "good" vector size so the HW can efficiently implement a set | ||||
55 | /// of high-level primitives. Multiple is understood along any dimension; e.g. | ||||
56 | /// both vector<16xf32> and vector<2x8xf32> are valid super-vectors for a | ||||
57 | /// vector<8xf32> HW vector. Note that a "good vector size so the HW can | ||||
58 | /// efficiently implement a set of high-level primitives" is not necessarily an | ||||
59 | /// integer multiple of actual hardware registers. We leave details of this | ||||
60 | /// distinction unspecified for now. | ||||
61 | /// | ||||
62 | /// Some may prefer the terminology a "tile of HW vectors". In this case, one | ||||
63 | /// should note that super-vectors implement an "always full tile" abstraction. | ||||
64 | /// They guarantee no partial-tile separation is necessary by relying on a | ||||
65 | /// high-level copy-reshape abstraction that we call vector.transfer. This | ||||
66 | /// copy-reshape operations is also responsible for performing layout | ||||
67 | /// transposition if necessary. In the general case this will require a scoped | ||||
68 | /// allocation in some notional local memory. | ||||
69 | /// | ||||
70 | /// Whatever the mental model one prefers to use for this abstraction, the key | ||||
71 | /// point is that we burn into a single, compact, representation in the vector | ||||
72 | /// types, information that is expected to reduce the impact of the phase | ||||
73 | /// ordering problem. Indeed, a vector type conveys information that: | ||||
74 | /// 1. the associated loops have dependency semantics that do not prevent | ||||
75 | /// vectorization; | ||||
76 | /// 2. the associate loops have been sliced in chunks of static sizes that are | ||||
77 | /// compatible with vector sizes (i.e. similar to unroll-and-jam); | ||||
78 | /// 3. the inner loops, in the unroll-and-jam analogy of 2, are captured by | ||||
79 | /// the | ||||
80 | /// vector type and no vectorization hampering transformations can be | ||||
81 | /// applied to them anymore; | ||||
82 | /// 4. the underlying memrefs are accessed in some notional contiguous way | ||||
83 | /// that allows loading into vectors with some amount of spatial locality; | ||||
84 | /// In other words, super-vectorization provides a level of separation of | ||||
85 | /// concern by way of opacity to subsequent passes. This has the effect of | ||||
86 | /// encapsulating and propagating vectorization constraints down the list of | ||||
87 | /// passes until we are ready to lower further. | ||||
88 | /// | ||||
89 | /// For a particular target, a notion of minimal n-d vector size will be | ||||
90 | /// specified and vectorization targets a multiple of those. In the following | ||||
91 | /// paragraph, let "k ." represent "a multiple of", to be understood as a | ||||
92 | /// multiple in the same dimension (e.g. vector<16 x k . 128> summarizes | ||||
93 | /// vector<16 x 128>, vector<16 x 256>, vector<16 x 1024>, etc). | ||||
94 | /// | ||||
95 | /// Some non-exhaustive notable super-vector sizes of interest include: | ||||
96 | /// - CPU: vector<k . HW_vector_size>, | ||||
97 | /// vector<k' . core_count x k . HW_vector_size>, | ||||
98 | /// vector<socket_count x k' . core_count x k . HW_vector_size>; | ||||
99 | /// - GPU: vector<k . warp_size>, | ||||
100 | /// vector<k . warp_size x float2>, | ||||
101 | /// vector<k . warp_size x float4>, | ||||
102 | /// vector<k . warp_size x 4 x 4x 4> (for tensor_core sizes). | ||||
103 | /// | ||||
104 | /// Loops and operations are emitted that operate on those super-vector shapes. | ||||
105 | /// Subsequent lowering passes will materialize to actual HW vector sizes. These | ||||
106 | /// passes are expected to be (gradually) more target-specific. | ||||
107 | /// | ||||
108 | /// At a high level, a vectorized load in a loop will resemble: | ||||
109 | /// ```mlir | ||||
110 | /// affine.for %i = ? to ? step ? { | ||||
111 | /// %v_a = vector.transfer_read A[%i] : memref<?xf32>, vector<128xf32> | ||||
112 | /// } | ||||
113 | /// ``` | ||||
114 | /// It is the responsibility of the implementation of vector.transfer_read to | ||||
115 | /// materialize vector registers from the original scalar memrefs. A later (more | ||||
116 | /// target-dependent) lowering pass will materialize to actual HW vector sizes. | ||||
117 | /// This lowering may be occur at different times: | ||||
118 | /// 1. at the MLIR level into a combination of loops, unrolling, DmaStartOp + | ||||
119 | /// DmaWaitOp + vectorized operations for data transformations and shuffle; | ||||
120 | /// thus opening opportunities for unrolling and pipelining. This is an | ||||
121 | /// instance of library call "whiteboxing"; or | ||||
122 | /// 2. later in the a target-specific lowering pass or hand-written library | ||||
123 | /// call; achieving full separation of concerns. This is an instance of | ||||
124 | /// library call; or | ||||
125 | /// 3. a mix of both, e.g. based on a model. | ||||
126 | /// In the future, these operations will expose a contract to constrain the | ||||
127 | /// search on vectorization patterns and sizes. | ||||
128 | /// | ||||
129 | /// Occurrence of super-vectorization in the compiler flow: | ||||
130 | /// ======================================================= | ||||
131 | /// This is an active area of investigation. We start with 2 remarks to position | ||||
132 | /// super-vectorization in the context of existing ongoing work: LLVM VPLAN | ||||
133 | /// and LLVM SLP Vectorizer. | ||||
134 | /// | ||||
135 | /// LLVM VPLAN: | ||||
136 | /// ----------- | ||||
137 | /// The astute reader may have noticed that in the limit, super-vectorization | ||||
138 | /// can be applied at a similar time and with similar objectives than VPLAN. | ||||
139 | /// For instance, in the case of a traditional, polyhedral compilation-flow (for | ||||
140 | /// instance, the PPCG project uses ISL to provide dependence analysis, | ||||
141 | /// multi-level(scheduling + tiling), lifting footprint to fast memory, | ||||
142 | /// communication synthesis, mapping, register optimizations) and before | ||||
143 | /// unrolling. When vectorization is applied at this *late* level in a typical | ||||
144 | /// polyhedral flow, and is instantiated with actual hardware vector sizes, | ||||
145 | /// super-vectorization is expected to match (or subsume) the type of patterns | ||||
146 | /// that LLVM's VPLAN aims at targeting. The main difference here is that MLIR | ||||
147 | /// is higher level and our implementation should be significantly simpler. Also | ||||
148 | /// note that in this mode, recursive patterns are probably a bit of an overkill | ||||
149 | /// although it is reasonable to expect that mixing a bit of outer loop and | ||||
150 | /// inner loop vectorization + unrolling will provide interesting choices to | ||||
151 | /// MLIR. | ||||
152 | /// | ||||
153 | /// LLVM SLP Vectorizer: | ||||
154 | /// -------------------- | ||||
155 | /// Super-vectorization however is not meant to be usable in a similar fashion | ||||
156 | /// to the SLP vectorizer. The main difference lies in the information that | ||||
157 | /// both vectorizers use: super-vectorization examines contiguity of memory | ||||
158 | /// references along fastest varying dimensions and loops with recursive nested | ||||
159 | /// patterns capturing imperfectly-nested loop nests; the SLP vectorizer, on | ||||
160 | /// the other hand, performs flat pattern matching inside a single unrolled loop | ||||
161 | /// body and stitches together pieces of load and store operations into full | ||||
162 | /// 1-D vectors. We envision that the SLP vectorizer is a good way to capture | ||||
163 | /// innermost loop, control-flow dependent patterns that super-vectorization may | ||||
164 | /// not be able to capture easily. In other words, super-vectorization does not | ||||
165 | /// aim at replacing the SLP vectorizer and the two solutions are complementary. | ||||
166 | /// | ||||
167 | /// Ongoing investigations: | ||||
168 | /// ----------------------- | ||||
169 | /// We discuss the following *early* places where super-vectorization is | ||||
170 | /// applicable and touch on the expected benefits and risks . We list the | ||||
171 | /// opportunities in the context of the traditional polyhedral compiler flow | ||||
172 | /// described in PPCG. There are essentially 6 places in the MLIR pass pipeline | ||||
173 | /// we expect to experiment with super-vectorization: | ||||
174 | /// 1. Right after language lowering to MLIR: this is the earliest time where | ||||
175 | /// super-vectorization is expected to be applied. At this level, all the | ||||
176 | /// language/user/library-level annotations are available and can be fully | ||||
177 | /// exploited. Examples include loop-type annotations (such as parallel, | ||||
178 | /// reduction, scan, dependence distance vector, vectorizable) as well as | ||||
179 | /// memory access annotations (such as non-aliasing writes guaranteed, | ||||
180 | /// indirect accesses that are permutations by construction) accesses or | ||||
181 | /// that a particular operation is prescribed atomic by the user. At this | ||||
182 | /// level, anything that enriches what dependence analysis can do should be | ||||
183 | /// aggressively exploited. At this level we are close to having explicit | ||||
184 | /// vector types in the language, except we do not impose that burden on the | ||||
185 | /// programmer/library: we derive information from scalar code + annotations. | ||||
186 | /// 2. After dependence analysis and before polyhedral scheduling: the | ||||
187 | /// information that supports vectorization does not need to be supplied by a | ||||
188 | /// higher level of abstraction. Traditional dependence analysis is available | ||||
189 | /// in MLIR and will be used to drive vectorization and cost models. | ||||
190 | /// | ||||
191 | /// Let's pause here and remark that applying super-vectorization as described | ||||
192 | /// in 1. and 2. presents clear opportunities and risks: | ||||
193 | /// - the opportunity is that vectorization is burned in the type system and | ||||
194 | /// is protected from the adverse effect of loop scheduling, tiling, loop | ||||
195 | /// interchange and all passes downstream. Provided that subsequent passes are | ||||
196 | /// able to operate on vector types; the vector shapes, associated loop | ||||
197 | /// iterator properties, alignment, and contiguity of fastest varying | ||||
198 | /// dimensions are preserved until we lower the super-vector types. We expect | ||||
199 | /// this to significantly rein in on the adverse effects of phase ordering. | ||||
200 | /// - the risks are that a. all passes after super-vectorization have to work | ||||
201 | /// on elemental vector types (not that this is always true, wherever | ||||
202 | /// vectorization is applied) and b. that imposing vectorization constraints | ||||
203 | /// too early may be overall detrimental to loop fusion, tiling and other | ||||
204 | /// transformations because the dependence distances are coarsened when | ||||
205 | /// operating on elemental vector types. For this reason, the pattern | ||||
206 | /// profitability analysis should include a component that also captures the | ||||
207 | /// maximal amount of fusion available under a particular pattern. This is | ||||
208 | /// still at the stage of rough ideas but in this context, search is our | ||||
209 | /// friend as the Tensor Comprehensions and auto-TVM contributions | ||||
210 | /// demonstrated previously. | ||||
211 | /// Bottom-line is we do not yet have good answers for the above but aim at | ||||
212 | /// making it easy to answer such questions. | ||||
213 | /// | ||||
214 | /// Back to our listing, the last places where early super-vectorization makes | ||||
215 | /// sense are: | ||||
216 | /// 3. right after polyhedral-style scheduling: PLUTO-style algorithms are known | ||||
217 | /// to improve locality, parallelism and be configurable (e.g. max-fuse, | ||||
218 | /// smart-fuse etc). They can also have adverse effects on contiguity | ||||
219 | /// properties that are required for vectorization but the vector.transfer | ||||
220 | /// copy-reshape-pad-transpose abstraction is expected to help recapture | ||||
221 | /// these properties. | ||||
222 | /// 4. right after polyhedral-style scheduling+tiling; | ||||
223 | /// 5. right after scheduling+tiling+rescheduling: points 4 and 5 represent | ||||
224 | /// probably the most promising places because applying tiling achieves a | ||||
225 | /// separation of concerns that allows rescheduling to worry less about | ||||
226 | /// locality and more about parallelism and distribution (e.g. min-fuse). | ||||
227 | /// | ||||
228 | /// At these levels the risk-reward looks different: on one hand we probably | ||||
229 | /// lost a good deal of language/user/library-level annotation; on the other | ||||
230 | /// hand we gained parallelism and locality through scheduling and tiling. | ||||
231 | /// However we probably want to ensure tiling is compatible with the | ||||
232 | /// full-tile-only abstraction used in super-vectorization or suffer the | ||||
233 | /// consequences. It is too early to place bets on what will win but we expect | ||||
234 | /// super-vectorization to be the right abstraction to allow exploring at all | ||||
235 | /// these levels. And again, search is our friend. | ||||
236 | /// | ||||
237 | /// Lastly, we mention it again here: | ||||
238 | /// 6. as a MLIR-based alternative to VPLAN. | ||||
239 | /// | ||||
240 | /// Lowering, unrolling, pipelining: | ||||
241 | /// ================================ | ||||
242 | /// TODO: point to the proper places. | ||||
243 | /// | ||||
244 | /// Algorithm: | ||||
245 | /// ========== | ||||
246 | /// The algorithm proceeds in a few steps: | ||||
247 | /// 1. defining super-vectorization patterns and matching them on the tree of | ||||
248 | /// AffineForOp. A super-vectorization pattern is defined as a recursive | ||||
249 | /// data structures that matches and captures nested, imperfectly-nested | ||||
250 | /// loops that have a. conformable loop annotations attached (e.g. parallel, | ||||
251 | /// reduction, vectorizable, ...) as well as b. all contiguous load/store | ||||
252 | /// operations along a specified minor dimension (not necessarily the | ||||
253 | /// fastest varying) ; | ||||
254 | /// 2. analyzing those patterns for profitability (TODO: and | ||||
255 | /// interference); | ||||
256 | /// 3. then, for each pattern in order: | ||||
257 | /// a. applying iterative rewriting of the loops and all their nested | ||||
258 | /// operations in topological order. Rewriting is implemented by | ||||
259 | /// coarsening the loops and converting operations and operands to their | ||||
260 | /// vector forms. Processing operations in topological order is relatively | ||||
261 | /// simple due to the structured nature of the control-flow | ||||
262 | /// representation. This order ensures that all the operands of a given | ||||
263 | /// operation have been vectorized before the operation itself in a single | ||||
264 | /// traversal, except for operands defined outside of the loop nest. The | ||||
265 | /// algorithm can convert the following operations to their vector form: | ||||
266 | /// * Affine load and store operations are converted to opaque vector | ||||
267 | /// transfer read and write operations. | ||||
268 | /// * Scalar constant operations/operands are converted to vector | ||||
269 | /// constant operations (splat). | ||||
270 | /// * Uniform operands (only induction variables of loops not mapped to | ||||
271 | /// a vector dimension, or operands defined outside of the loop nest | ||||
272 | /// for now) are broadcasted to a vector. | ||||
273 | /// TODO: Support more uniform cases. | ||||
274 | /// * Affine for operations with 'iter_args' are vectorized by | ||||
275 | /// vectorizing their 'iter_args' operands and results. | ||||
276 | /// TODO: Support more complex loops with divergent lbs and/or ubs. | ||||
277 | /// * The remaining operations in the loop nest are vectorized by | ||||
278 | /// widening their scalar types to vector types. | ||||
279 | /// b. if everything under the root AffineForOp in the current pattern | ||||
280 | /// is vectorized properly, we commit that loop to the IR and remove the | ||||
281 | /// scalar loop. Otherwise, we discard the vectorized loop and keep the | ||||
282 | /// original scalar loop. | ||||
283 | /// c. vectorization is applied on the next pattern in the list. Because | ||||
284 | /// pattern interference avoidance is not yet implemented and that we do | ||||
285 | /// not support further vectorizing an already vector load we need to | ||||
286 | /// re-verify that the pattern is still vectorizable. This is expected to | ||||
287 | /// make cost models more difficult to write and is subject to improvement | ||||
288 | /// in the future. | ||||
289 | /// | ||||
290 | /// Choice of loop transformation to support the algorithm: | ||||
291 | /// ======================================================= | ||||
292 | /// The choice of loop transformation to apply for coarsening vectorized loops | ||||
293 | /// is still subject to exploratory tradeoffs. In particular, say we want to | ||||
294 | /// vectorize by a factor 128, we want to transform the following input: | ||||
295 | /// ```mlir | ||||
296 | /// affine.for %i = %M to %N { | ||||
297 | /// %a = affine.load %A[%i] : memref<?xf32> | ||||
298 | /// } | ||||
299 | /// ``` | ||||
300 | /// | ||||
301 | /// Traditionally, one would vectorize late (after scheduling, tiling, | ||||
302 | /// memory promotion etc) say after stripmining (and potentially unrolling in | ||||
303 | /// the case of LLVM's SLP vectorizer): | ||||
304 | /// ```mlir | ||||
305 | /// affine.for %i = floor(%M, 128) to ceil(%N, 128) { | ||||
306 | /// affine.for %ii = max(%M, 128 * %i) to min(%N, 128*%i + 127) { | ||||
307 | /// %a = affine.load %A[%ii] : memref<?xf32> | ||||
308 | /// } | ||||
309 | /// } | ||||
310 | /// ``` | ||||
311 | /// | ||||
312 | /// Instead, we seek to vectorize early and freeze vector types before | ||||
313 | /// scheduling, so we want to generate a pattern that resembles: | ||||
314 | /// ```mlir | ||||
315 | /// affine.for %i = ? to ? step ? { | ||||
316 | /// %v_a = vector.transfer_read %A[%i] : memref<?xf32>, vector<128xf32> | ||||
317 | /// } | ||||
318 | /// ``` | ||||
319 | /// | ||||
320 | /// i. simply dividing the lower / upper bounds by 128 creates issues | ||||
321 | /// when representing expressions such as ii + 1 because now we only | ||||
322 | /// have access to original values that have been divided. Additional | ||||
323 | /// information is needed to specify accesses at below-128 granularity; | ||||
324 | /// ii. another alternative is to coarsen the loop step but this may have | ||||
325 | /// consequences on dependence analysis and fusability of loops: fusable | ||||
326 | /// loops probably need to have the same step (because we don't want to | ||||
327 | /// stripmine/unroll to enable fusion). | ||||
328 | /// As a consequence, we choose to represent the coarsening using the loop | ||||
329 | /// step for now and reevaluate in the future. Note that we can renormalize | ||||
330 | /// loop steps later if/when we have evidence that they are problematic. | ||||
331 | /// | ||||
332 | /// For the simple strawman example above, vectorizing for a 1-D vector | ||||
333 | /// abstraction of size 128 returns code similar to: | ||||
334 | /// ```mlir | ||||
335 | /// affine.for %i = %M to %N step 128 { | ||||
336 | /// %v_a = vector.transfer_read %A[%i] : memref<?xf32>, vector<128xf32> | ||||
337 | /// } | ||||
338 | /// ``` | ||||
339 | /// | ||||
340 | /// Unsupported cases, extensions, and work in progress (help welcome :-) ): | ||||
341 | /// ======================================================================== | ||||
342 | /// 1. lowering to concrete vector types for various HW; | ||||
343 | /// 2. reduction support for n-D vectorization and non-unit steps; | ||||
344 | /// 3. non-effecting padding during vector.transfer_read and filter during | ||||
345 | /// vector.transfer_write; | ||||
346 | /// 4. misalignment support vector.transfer_read / vector.transfer_write | ||||
347 | /// (hopefully without read-modify-writes); | ||||
348 | /// 5. control-flow support; | ||||
349 | /// 6. cost-models, heuristics and search; | ||||
350 | /// 7. Op implementation, extensions and implication on memref views; | ||||
351 | /// 8. many TODOs left around. | ||||
352 | /// | ||||
353 | /// Examples: | ||||
354 | /// ========= | ||||
355 | /// Consider the following Function: | ||||
356 | /// ```mlir | ||||
357 | /// func @vector_add_2d(%M : index, %N : index) -> f32 { | ||||
358 | /// %A = alloc (%M, %N) : memref<?x?xf32, 0> | ||||
359 | /// %B = alloc (%M, %N) : memref<?x?xf32, 0> | ||||
360 | /// %C = alloc (%M, %N) : memref<?x?xf32, 0> | ||||
361 | /// %f1 = arith.constant 1.0 : f32 | ||||
362 | /// %f2 = arith.constant 2.0 : f32 | ||||
363 | /// affine.for %i0 = 0 to %M { | ||||
364 | /// affine.for %i1 = 0 to %N { | ||||
365 | /// // non-scoped %f1 | ||||
366 | /// affine.store %f1, %A[%i0, %i1] : memref<?x?xf32, 0> | ||||
367 | /// } | ||||
368 | /// } | ||||
369 | /// affine.for %i2 = 0 to %M { | ||||
370 | /// affine.for %i3 = 0 to %N { | ||||
371 | /// // non-scoped %f2 | ||||
372 | /// affine.store %f2, %B[%i2, %i3] : memref<?x?xf32, 0> | ||||
373 | /// } | ||||
374 | /// } | ||||
375 | /// affine.for %i4 = 0 to %M { | ||||
376 | /// affine.for %i5 = 0 to %N { | ||||
377 | /// %a5 = affine.load %A[%i4, %i5] : memref<?x?xf32, 0> | ||||
378 | /// %b5 = affine.load %B[%i4, %i5] : memref<?x?xf32, 0> | ||||
379 | /// %s5 = arith.addf %a5, %b5 : f32 | ||||
380 | /// // non-scoped %f1 | ||||
381 | /// %s6 = arith.addf %s5, %f1 : f32 | ||||
382 | /// // non-scoped %f2 | ||||
383 | /// %s7 = arith.addf %s5, %f2 : f32 | ||||
384 | /// // diamond dependency. | ||||
385 | /// %s8 = arith.addf %s7, %s6 : f32 | ||||
386 | /// affine.store %s8, %C[%i4, %i5] : memref<?x?xf32, 0> | ||||
387 | /// } | ||||
388 | /// } | ||||
389 | /// %c7 = arith.constant 7 : index | ||||
390 | /// %c42 = arith.constant 42 : index | ||||
391 | /// %res = load %C[%c7, %c42] : memref<?x?xf32, 0> | ||||
392 | /// return %res : f32 | ||||
393 | /// } | ||||
394 | /// ``` | ||||
395 | /// | ||||
396 | /// The -affine-super-vectorize pass with the following arguments: | ||||
397 | /// ``` | ||||
398 | /// -affine-super-vectorize="virtual-vector-size=256 test-fastest-varying=0" | ||||
399 | /// ``` | ||||
400 | /// | ||||
401 | /// produces this standard innermost-loop vectorized code: | ||||
402 | /// ```mlir | ||||
403 | /// func @vector_add_2d(%arg0 : index, %arg1 : index) -> f32 { | ||||
404 | /// %0 = memref.alloc(%arg0, %arg1) : memref<?x?xf32> | ||||
405 | /// %1 = memref.alloc(%arg0, %arg1) : memref<?x?xf32> | ||||
406 | /// %2 = memref.alloc(%arg0, %arg1) : memref<?x?xf32> | ||||
407 | /// %cst = arith.constant 1.0 : f32 | ||||
408 | /// %cst_0 = arith.constant 2.0 : f32 | ||||
409 | /// affine.for %i0 = 0 to %arg0 { | ||||
410 | /// affine.for %i1 = 0 to %arg1 step 256 { | ||||
411 | /// %cst_1 = arith.constant dense<vector<256xf32>, 1.0> : | ||||
412 | /// vector<256xf32> | ||||
413 | /// vector.transfer_write %cst_1, %0[%i0, %i1] : | ||||
414 | /// vector<256xf32>, memref<?x?xf32> | ||||
415 | /// } | ||||
416 | /// } | ||||
417 | /// affine.for %i2 = 0 to %arg0 { | ||||
418 | /// affine.for %i3 = 0 to %arg1 step 256 { | ||||
419 | /// %cst_2 = arith.constant dense<vector<256xf32>, 2.0> : | ||||
420 | /// vector<256xf32> | ||||
421 | /// vector.transfer_write %cst_2, %1[%i2, %i3] : | ||||
422 | /// vector<256xf32>, memref<?x?xf32> | ||||
423 | /// } | ||||
424 | /// } | ||||
425 | /// affine.for %i4 = 0 to %arg0 { | ||||
426 | /// affine.for %i5 = 0 to %arg1 step 256 { | ||||
427 | /// %3 = vector.transfer_read %0[%i4, %i5] : | ||||
428 | /// memref<?x?xf32>, vector<256xf32> | ||||
429 | /// %4 = vector.transfer_read %1[%i4, %i5] : | ||||
430 | /// memref<?x?xf32>, vector<256xf32> | ||||
431 | /// %5 = arith.addf %3, %4 : vector<256xf32> | ||||
432 | /// %cst_3 = arith.constant dense<vector<256xf32>, 1.0> : | ||||
433 | /// vector<256xf32> | ||||
434 | /// %6 = arith.addf %5, %cst_3 : vector<256xf32> | ||||
435 | /// %cst_4 = arith.constant dense<vector<256xf32>, 2.0> : | ||||
436 | /// vector<256xf32> | ||||
437 | /// %7 = arith.addf %5, %cst_4 : vector<256xf32> | ||||
438 | /// %8 = arith.addf %7, %6 : vector<256xf32> | ||||
439 | /// vector.transfer_write %8, %2[%i4, %i5] : | ||||
440 | /// vector<256xf32>, memref<?x?xf32> | ||||
441 | /// } | ||||
442 | /// } | ||||
443 | /// %c7 = arith.constant 7 : index | ||||
444 | /// %c42 = arith.constant 42 : index | ||||
445 | /// %9 = load %2[%c7, %c42] : memref<?x?xf32> | ||||
446 | /// return %9 : f32 | ||||
447 | /// } | ||||
448 | /// ``` | ||||
449 | /// | ||||
450 | /// The -affine-super-vectorize pass with the following arguments: | ||||
451 | /// ``` | ||||
452 | /// -affine-super-vectorize="virtual-vector-size=32,256 \ | ||||
453 | /// test-fastest-varying=1,0" | ||||
454 | /// ``` | ||||
455 | /// | ||||
456 | /// produces this more interesting mixed outer-innermost-loop vectorized code: | ||||
457 | /// ```mlir | ||||
458 | /// func @vector_add_2d(%arg0 : index, %arg1 : index) -> f32 { | ||||
459 | /// %0 = memref.alloc(%arg0, %arg1) : memref<?x?xf32> | ||||
460 | /// %1 = memref.alloc(%arg0, %arg1) : memref<?x?xf32> | ||||
461 | /// %2 = memref.alloc(%arg0, %arg1) : memref<?x?xf32> | ||||
462 | /// %cst = arith.constant 1.0 : f32 | ||||
463 | /// %cst_0 = arith.constant 2.0 : f32 | ||||
464 | /// affine.for %i0 = 0 to %arg0 step 32 { | ||||
465 | /// affine.for %i1 = 0 to %arg1 step 256 { | ||||
466 | /// %cst_1 = arith.constant dense<vector<32x256xf32>, 1.0> : | ||||
467 | /// vector<32x256xf32> | ||||
468 | /// vector.transfer_write %cst_1, %0[%i0, %i1] : | ||||
469 | /// vector<32x256xf32>, memref<?x?xf32> | ||||
470 | /// } | ||||
471 | /// } | ||||
472 | /// affine.for %i2 = 0 to %arg0 step 32 { | ||||
473 | /// affine.for %i3 = 0 to %arg1 step 256 { | ||||
474 | /// %cst_2 = arith.constant dense<vector<32x256xf32>, 2.0> : | ||||
475 | /// vector<32x256xf32> | ||||
476 | /// vector.transfer_write %cst_2, %1[%i2, %i3] : | ||||
477 | /// vector<32x256xf32>, memref<?x?xf32> | ||||
478 | /// } | ||||
479 | /// } | ||||
480 | /// affine.for %i4 = 0 to %arg0 step 32 { | ||||
481 | /// affine.for %i5 = 0 to %arg1 step 256 { | ||||
482 | /// %3 = vector.transfer_read %0[%i4, %i5] : | ||||
483 | /// memref<?x?xf32> vector<32x256xf32> | ||||
484 | /// %4 = vector.transfer_read %1[%i4, %i5] : | ||||
485 | /// memref<?x?xf32>, vector<32x256xf32> | ||||
486 | /// %5 = arith.addf %3, %4 : vector<32x256xf32> | ||||
487 | /// %cst_3 = arith.constant dense<vector<32x256xf32>, 1.0> : | ||||
488 | /// vector<32x256xf32> | ||||
489 | /// %6 = arith.addf %5, %cst_3 : vector<32x256xf32> | ||||
490 | /// %cst_4 = arith.constant dense<vector<32x256xf32>, 2.0> : | ||||
491 | /// vector<32x256xf32> | ||||
492 | /// %7 = arith.addf %5, %cst_4 : vector<32x256xf32> | ||||
493 | /// %8 = arith.addf %7, %6 : vector<32x256xf32> | ||||
494 | /// vector.transfer_write %8, %2[%i4, %i5] : | ||||
495 | /// vector<32x256xf32>, memref<?x?xf32> | ||||
496 | /// } | ||||
497 | /// } | ||||
498 | /// %c7 = arith.constant 7 : index | ||||
499 | /// %c42 = arith.constant 42 : index | ||||
500 | /// %9 = load %2[%c7, %c42] : memref<?x?xf32> | ||||
501 | /// return %9 : f32 | ||||
502 | /// } | ||||
503 | /// ``` | ||||
504 | /// | ||||
505 | /// Of course, much more intricate n-D imperfectly-nested patterns can be | ||||
506 | /// vectorized too and specified in a fully declarative fashion. | ||||
507 | /// | ||||
508 | /// Reduction: | ||||
509 | /// ========== | ||||
510 | /// Vectorizing reduction loops along the reduction dimension is supported if: | ||||
511 | /// - the reduction kind is supported, | ||||
512 | /// - the vectorization is 1-D, and | ||||
513 | /// - the step size of the loop equals to one. | ||||
514 | /// | ||||
515 | /// Comparing to the non-vector-dimension case, two additional things are done | ||||
516 | /// during vectorization of such loops: | ||||
517 | /// - The resulting vector returned from the loop is reduced to a scalar using | ||||
518 | /// `vector.reduce`. | ||||
519 | /// - In some cases a mask is applied to the vector yielded at the end of the | ||||
520 | /// loop to prevent garbage values from being written to the accumulator. | ||||
521 | /// | ||||
522 | /// Reduction vectorization is switched off by default, it can be enabled by | ||||
523 | /// passing a map from loops to reductions to utility functions, or by passing | ||||
524 | /// `vectorize-reductions=true` to the vectorization pass. | ||||
525 | /// | ||||
526 | /// Consider the following example: | ||||
527 | /// ```mlir | ||||
528 | /// func @vecred(%in: memref<512xf32>) -> f32 { | ||||
529 | /// %cst = arith.constant 0.000000e+00 : f32 | ||||
530 | /// %sum = affine.for %i = 0 to 500 iter_args(%part_sum = %cst) -> (f32) { | ||||
531 | /// %ld = affine.load %in[%i] : memref<512xf32> | ||||
532 | /// %cos = math.cos %ld : f32 | ||||
533 | /// %add = arith.addf %part_sum, %cos : f32 | ||||
534 | /// affine.yield %add : f32 | ||||
535 | /// } | ||||
536 | /// return %sum : f32 | ||||
537 | /// } | ||||
538 | /// ``` | ||||
539 | /// | ||||
540 | /// The -affine-super-vectorize pass with the following arguments: | ||||
541 | /// ``` | ||||
542 | /// -affine-super-vectorize="virtual-vector-size=128 test-fastest-varying=0 \ | ||||
543 | /// vectorize-reductions=true" | ||||
544 | /// ``` | ||||
545 | /// produces the following output: | ||||
546 | /// ```mlir | ||||
547 | /// #map = affine_map<(d0) -> (-d0 + 500)> | ||||
548 | /// func @vecred(%arg0: memref<512xf32>) -> f32 { | ||||
549 | /// %cst = arith.constant 0.000000e+00 : f32 | ||||
550 | /// %cst_0 = arith.constant dense<0.000000e+00> : vector<128xf32> | ||||
551 | /// %0 = affine.for %arg1 = 0 to 500 step 128 iter_args(%arg2 = %cst_0) | ||||
552 | /// -> (vector<128xf32>) { | ||||
553 | /// // %2 is the number of iterations left in the original loop. | ||||
554 | /// %2 = affine.apply #map(%arg1) | ||||
555 | /// %3 = vector.create_mask %2 : vector<128xi1> | ||||
556 | /// %cst_1 = arith.constant 0.000000e+00 : f32 | ||||
557 | /// %4 = vector.transfer_read %arg0[%arg1], %cst_1 : | ||||
558 | /// memref<512xf32>, vector<128xf32> | ||||
559 | /// %5 = math.cos %4 : vector<128xf32> | ||||
560 | /// %6 = arith.addf %arg2, %5 : vector<128xf32> | ||||
561 | /// // We filter out the effect of last 12 elements using the mask. | ||||
562 | /// %7 = select %3, %6, %arg2 : vector<128xi1>, vector<128xf32> | ||||
563 | /// affine.yield %7 : vector<128xf32> | ||||
564 | /// } | ||||
565 | /// %1 = vector.reduction <add>, %0 : vector<128xf32> into f32 | ||||
566 | /// return %1 : f32 | ||||
567 | /// } | ||||
568 | /// ``` | ||||
569 | /// | ||||
570 | /// Note that because of loop misalignment we needed to apply a mask to prevent | ||||
571 | /// last 12 elements from affecting the final result. The mask is full of ones | ||||
572 | /// in every iteration except for the last one, in which it has the form | ||||
573 | /// `11...100...0` with 116 ones and 12 zeros. | ||||
574 | |||||
575 | #define DEBUG_TYPE"early-vect" "early-vect" | ||||
576 | |||||
577 | using llvm::dbgs; | ||||
578 | |||||
579 | /// Forward declaration. | ||||
580 | static FilterFunctionType | ||||
581 | isVectorizableLoopPtrFactory(const DenseSet<Operation *> ¶llelLoops, | ||||
582 | int fastestVaryingMemRefDimension); | ||||
583 | |||||
584 | /// Creates a vectorization pattern from the command line arguments. | ||||
585 | /// Up to 3-D patterns are supported. | ||||
586 | /// If the command line argument requests a pattern of higher order, returns an | ||||
587 | /// empty pattern list which will conservatively result in no vectorization. | ||||
588 | static std::optional<NestedPattern> | ||||
589 | makePattern(const DenseSet<Operation *> ¶llelLoops, int vectorRank, | ||||
590 | ArrayRef<int64_t> fastestVaryingPattern) { | ||||
591 | using affine::matcher::For; | ||||
592 | int64_t d0 = fastestVaryingPattern.empty() ? -1 : fastestVaryingPattern[0]; | ||||
593 | int64_t d1 = fastestVaryingPattern.size() < 2 ? -1 : fastestVaryingPattern[1]; | ||||
594 | int64_t d2 = fastestVaryingPattern.size() < 3 ? -1 : fastestVaryingPattern[2]; | ||||
595 | switch (vectorRank) { | ||||
596 | case 1: | ||||
597 | return For(isVectorizableLoopPtrFactory(parallelLoops, d0)); | ||||
598 | case 2: | ||||
599 | return For(isVectorizableLoopPtrFactory(parallelLoops, d0), | ||||
600 | For(isVectorizableLoopPtrFactory(parallelLoops, d1))); | ||||
601 | case 3: | ||||
602 | return For(isVectorizableLoopPtrFactory(parallelLoops, d0), | ||||
603 | For(isVectorizableLoopPtrFactory(parallelLoops, d1), | ||||
604 | For(isVectorizableLoopPtrFactory(parallelLoops, d2)))); | ||||
605 | default: { | ||||
606 | return std::nullopt; | ||||
607 | } | ||||
608 | } | ||||
609 | } | ||||
610 | |||||
611 | static NestedPattern &vectorTransferPattern() { | ||||
612 | static auto pattern = affine::matcher::Op([](Operation &op) { | ||||
613 | return isa<vector::TransferReadOp, vector::TransferWriteOp>(op); | ||||
614 | }); | ||||
615 | return pattern; | ||||
616 | } | ||||
617 | |||||
618 | namespace { | ||||
619 | |||||
620 | /// Base state for the vectorize pass. | ||||
621 | /// Command line arguments are preempted by non-empty pass arguments. | ||||
622 | struct Vectorize : public affine::impl::AffineVectorizeBase<Vectorize> { | ||||
623 | using Base::Base; | ||||
624 | |||||
625 | void runOnOperation() override; | ||||
626 | }; | ||||
627 | |||||
628 | } // namespace | ||||
629 | |||||
630 | static void vectorizeLoopIfProfitable(Operation *loop, unsigned depthInPattern, | ||||
631 | unsigned patternDepth, | ||||
632 | VectorizationStrategy *strategy) { | ||||
633 | assert(patternDepth > depthInPattern &&(static_cast <bool> (patternDepth > depthInPattern && "patternDepth is greater than depthInPattern") ? void (0) : __assert_fail ("patternDepth > depthInPattern && \"patternDepth is greater than depthInPattern\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 634 , __extension__ __PRETTY_FUNCTION__)) | ||||
634 | "patternDepth is greater than depthInPattern")(static_cast <bool> (patternDepth > depthInPattern && "patternDepth is greater than depthInPattern") ? void (0) : __assert_fail ("patternDepth > depthInPattern && \"patternDepth is greater than depthInPattern\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 634 , __extension__ __PRETTY_FUNCTION__)); | ||||
635 | if (patternDepth - depthInPattern > strategy->vectorSizes.size()) { | ||||
636 | // Don't vectorize this loop | ||||
637 | return; | ||||
638 | } | ||||
639 | strategy->loopToVectorDim[loop] = | ||||
640 | strategy->vectorSizes.size() - (patternDepth - depthInPattern); | ||||
641 | } | ||||
642 | |||||
643 | /// Implements a simple strawman strategy for vectorization. | ||||
644 | /// Given a matched pattern `matches` of depth `patternDepth`, this strategy | ||||
645 | /// greedily assigns the fastest varying dimension ** of the vector ** to the | ||||
646 | /// innermost loop in the pattern. | ||||
647 | /// When coupled with a pattern that looks for the fastest varying dimension in | ||||
648 | /// load/store MemRefs, this creates a generic vectorization strategy that works | ||||
649 | /// for any loop in a hierarchy (outermost, innermost or intermediate). | ||||
650 | /// | ||||
651 | /// TODO: In the future we should additionally increase the power of the | ||||
652 | /// profitability analysis along 3 directions: | ||||
653 | /// 1. account for loop extents (both static and parametric + annotations); | ||||
654 | /// 2. account for data layout permutations; | ||||
655 | /// 3. account for impact of vectorization on maximal loop fusion. | ||||
656 | /// Then we can quantify the above to build a cost model and search over | ||||
657 | /// strategies. | ||||
658 | static LogicalResult analyzeProfitability(ArrayRef<NestedMatch> matches, | ||||
659 | unsigned depthInPattern, | ||||
660 | unsigned patternDepth, | ||||
661 | VectorizationStrategy *strategy) { | ||||
662 | for (auto m : matches) { | ||||
663 | if (failed(analyzeProfitability(m.getMatchedChildren(), depthInPattern + 1, | ||||
664 | patternDepth, strategy))) { | ||||
665 | return failure(); | ||||
666 | } | ||||
667 | vectorizeLoopIfProfitable(m.getMatchedOperation(), depthInPattern, | ||||
668 | patternDepth, strategy); | ||||
669 | } | ||||
670 | return success(); | ||||
671 | } | ||||
672 | |||||
673 | ///// end TODO: Hoist to a VectorizationStrategy.cpp when appropriate ///// | ||||
674 | |||||
675 | namespace { | ||||
676 | |||||
677 | struct VectorizationState { | ||||
678 | |||||
679 | VectorizationState(MLIRContext *context) : builder(context) {} | ||||
680 | |||||
681 | /// Registers the vector replacement of a scalar operation and its result | ||||
682 | /// values. Both operations must have the same number of results. | ||||
683 | /// | ||||
684 | /// This utility is used to register the replacement for the vast majority of | ||||
685 | /// the vectorized operations. | ||||
686 | /// | ||||
687 | /// Example: | ||||
688 | /// * 'replaced': %0 = arith.addf %1, %2 : f32 | ||||
689 | /// * 'replacement': %0 = arith.addf %1, %2 : vector<128xf32> | ||||
690 | void registerOpVectorReplacement(Operation *replaced, Operation *replacement); | ||||
691 | |||||
692 | /// Registers the vector replacement of a scalar value. The replacement | ||||
693 | /// operation should have a single result, which replaces the scalar value. | ||||
694 | /// | ||||
695 | /// This utility is used to register the vector replacement of block arguments | ||||
696 | /// and operation results which are not directly vectorized (i.e., their | ||||
697 | /// scalar version still exists after vectorization), like uniforms. | ||||
698 | /// | ||||
699 | /// Example: | ||||
700 | /// * 'replaced': block argument or operation outside of the vectorized | ||||
701 | /// loop. | ||||
702 | /// * 'replacement': %0 = vector.broadcast %1 : f32 to vector<128xf32> | ||||
703 | void registerValueVectorReplacement(Value replaced, Operation *replacement); | ||||
704 | |||||
705 | /// Registers the vector replacement of a block argument (e.g., iter_args). | ||||
706 | /// | ||||
707 | /// Example: | ||||
708 | /// * 'replaced': 'iter_arg' block argument. | ||||
709 | /// * 'replacement': vectorized 'iter_arg' block argument. | ||||
710 | void registerBlockArgVectorReplacement(BlockArgument replaced, | ||||
711 | BlockArgument replacement); | ||||
712 | |||||
713 | /// Registers the scalar replacement of a scalar value. 'replacement' must be | ||||
714 | /// scalar. Both values must be block arguments. Operation results should be | ||||
715 | /// replaced using the 'registerOp*' utilitites. | ||||
716 | /// | ||||
717 | /// This utility is used to register the replacement of block arguments | ||||
718 | /// that are within the loop to be vectorized and will continue being scalar | ||||
719 | /// within the vector loop. | ||||
720 | /// | ||||
721 | /// Example: | ||||
722 | /// * 'replaced': induction variable of a loop to be vectorized. | ||||
723 | /// * 'replacement': new induction variable in the new vector loop. | ||||
724 | void registerValueScalarReplacement(BlockArgument replaced, | ||||
725 | BlockArgument replacement); | ||||
726 | |||||
727 | /// Registers the scalar replacement of a scalar result returned from a | ||||
728 | /// reduction loop. 'replacement' must be scalar. | ||||
729 | /// | ||||
730 | /// This utility is used to register the replacement for scalar results of | ||||
731 | /// vectorized reduction loops with iter_args. | ||||
732 | /// | ||||
733 | /// Example 2: | ||||
734 | /// * 'replaced': %0 = affine.for %i = 0 to 512 iter_args(%x = ...) -> (f32) | ||||
735 | /// * 'replacement': %1 = vector.reduction <add>, %0 : vector<4xf32> into | ||||
736 | /// f32 | ||||
737 | void registerLoopResultScalarReplacement(Value replaced, Value replacement); | ||||
738 | |||||
739 | /// Returns in 'replacedVals' the scalar replacement for values in | ||||
740 | /// 'inputVals'. | ||||
741 | void getScalarValueReplacementsFor(ValueRange inputVals, | ||||
742 | SmallVectorImpl<Value> &replacedVals); | ||||
743 | |||||
744 | /// Erases the scalar loop nest after its successful vectorization. | ||||
745 | void finishVectorizationPattern(AffineForOp rootLoop); | ||||
746 | |||||
747 | // Used to build and insert all the new operations created. The insertion | ||||
748 | // point is preserved and updated along the vectorization process. | ||||
749 | OpBuilder builder; | ||||
750 | |||||
751 | // Maps input scalar operations to their vector counterparts. | ||||
752 | DenseMap<Operation *, Operation *> opVectorReplacement; | ||||
753 | // Maps input scalar values to their vector counterparts. | ||||
754 | IRMapping valueVectorReplacement; | ||||
755 | // Maps input scalar values to their new scalar counterparts in the vector | ||||
756 | // loop nest. | ||||
757 | IRMapping valueScalarReplacement; | ||||
758 | // Maps results of reduction loops to their new scalar counterparts. | ||||
759 | DenseMap<Value, Value> loopResultScalarReplacement; | ||||
760 | |||||
761 | // Maps the newly created vector loops to their vector dimension. | ||||
762 | DenseMap<Operation *, unsigned> vecLoopToVecDim; | ||||
763 | |||||
764 | // Maps the new vectorized loops to the corresponding vector masks if it is | ||||
765 | // required. | ||||
766 | DenseMap<Operation *, Value> vecLoopToMask; | ||||
767 | |||||
768 | // The strategy drives which loop to vectorize by which amount. | ||||
769 | const VectorizationStrategy *strategy = nullptr; | ||||
770 | |||||
771 | private: | ||||
772 | /// Internal implementation to map input scalar values to new vector or scalar | ||||
773 | /// values. | ||||
774 | void registerValueVectorReplacementImpl(Value replaced, Value replacement); | ||||
775 | void registerValueScalarReplacementImpl(Value replaced, Value replacement); | ||||
776 | }; | ||||
777 | |||||
778 | } // namespace | ||||
779 | |||||
780 | /// Registers the vector replacement of a scalar operation and its result | ||||
781 | /// values. Both operations must have the same number of results. | ||||
782 | /// | ||||
783 | /// This utility is used to register the replacement for the vast majority of | ||||
784 | /// the vectorized operations. | ||||
785 | /// | ||||
786 | /// Example: | ||||
787 | /// * 'replaced': %0 = arith.addf %1, %2 : f32 | ||||
788 | /// * 'replacement': %0 = arith.addf %1, %2 : vector<128xf32> | ||||
789 | void VectorizationState::registerOpVectorReplacement(Operation *replaced, | ||||
790 | Operation *replacement) { | ||||
791 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ commit vectorized op:\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ commit vectorized op:\n" ; } } while (false); | ||||
792 | LLVM_DEBUG(dbgs() << *replaced << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << *replaced << "\n"; } } while (false); | ||||
793 | LLVM_DEBUG(dbgs() << "into\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "into\n"; } } while (false); | ||||
794 | LLVM_DEBUG(dbgs() << *replacement << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << *replacement << "\n"; } } while (false); | ||||
795 | |||||
796 | assert(replaced->getNumResults() == replacement->getNumResults() &&(static_cast <bool> (replaced->getNumResults() == replacement ->getNumResults() && "Unexpected replaced and replacement results" ) ? void (0) : __assert_fail ("replaced->getNumResults() == replacement->getNumResults() && \"Unexpected replaced and replacement results\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 797 , __extension__ __PRETTY_FUNCTION__)) | ||||
797 | "Unexpected replaced and replacement results")(static_cast <bool> (replaced->getNumResults() == replacement ->getNumResults() && "Unexpected replaced and replacement results" ) ? void (0) : __assert_fail ("replaced->getNumResults() == replacement->getNumResults() && \"Unexpected replaced and replacement results\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 797 , __extension__ __PRETTY_FUNCTION__)); | ||||
798 | assert(opVectorReplacement.count(replaced) == 0 && "already registered")(static_cast <bool> (opVectorReplacement.count(replaced ) == 0 && "already registered") ? void (0) : __assert_fail ("opVectorReplacement.count(replaced) == 0 && \"already registered\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 798 , __extension__ __PRETTY_FUNCTION__)); | ||||
799 | opVectorReplacement[replaced] = replacement; | ||||
800 | |||||
801 | for (auto resultTuple : | ||||
802 | llvm::zip(replaced->getResults(), replacement->getResults())) | ||||
803 | registerValueVectorReplacementImpl(std::get<0>(resultTuple), | ||||
804 | std::get<1>(resultTuple)); | ||||
805 | } | ||||
806 | |||||
807 | /// Registers the vector replacement of a scalar value. The replacement | ||||
808 | /// operation should have a single result, which replaces the scalar value. | ||||
809 | /// | ||||
810 | /// This utility is used to register the vector replacement of block arguments | ||||
811 | /// and operation results which are not directly vectorized (i.e., their | ||||
812 | /// scalar version still exists after vectorization), like uniforms. | ||||
813 | /// | ||||
814 | /// Example: | ||||
815 | /// * 'replaced': block argument or operation outside of the vectorized loop. | ||||
816 | /// * 'replacement': %0 = vector.broadcast %1 : f32 to vector<128xf32> | ||||
817 | void VectorizationState::registerValueVectorReplacement( | ||||
818 | Value replaced, Operation *replacement) { | ||||
819 | assert(replacement->getNumResults() == 1 &&(static_cast <bool> (replacement->getNumResults() == 1 && "Expected single-result replacement") ? void (0 ) : __assert_fail ("replacement->getNumResults() == 1 && \"Expected single-result replacement\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 820 , __extension__ __PRETTY_FUNCTION__)) | ||||
820 | "Expected single-result replacement")(static_cast <bool> (replacement->getNumResults() == 1 && "Expected single-result replacement") ? void (0 ) : __assert_fail ("replacement->getNumResults() == 1 && \"Expected single-result replacement\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 820 , __extension__ __PRETTY_FUNCTION__)); | ||||
821 | if (Operation *defOp = replaced.getDefiningOp()) | ||||
822 | registerOpVectorReplacement(defOp, replacement); | ||||
823 | else | ||||
824 | registerValueVectorReplacementImpl(replaced, replacement->getResult(0)); | ||||
825 | } | ||||
826 | |||||
827 | /// Registers the vector replacement of a block argument (e.g., iter_args). | ||||
828 | /// | ||||
829 | /// Example: | ||||
830 | /// * 'replaced': 'iter_arg' block argument. | ||||
831 | /// * 'replacement': vectorized 'iter_arg' block argument. | ||||
832 | void VectorizationState::registerBlockArgVectorReplacement( | ||||
833 | BlockArgument replaced, BlockArgument replacement) { | ||||
834 | registerValueVectorReplacementImpl(replaced, replacement); | ||||
835 | } | ||||
836 | |||||
837 | void VectorizationState::registerValueVectorReplacementImpl(Value replaced, | ||||
838 | Value replacement) { | ||||
839 | assert(!valueVectorReplacement.contains(replaced) &&(static_cast <bool> (!valueVectorReplacement.contains(replaced ) && "Vector replacement already registered") ? void ( 0) : __assert_fail ("!valueVectorReplacement.contains(replaced) && \"Vector replacement already registered\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 840 , __extension__ __PRETTY_FUNCTION__)) | ||||
840 | "Vector replacement already registered")(static_cast <bool> (!valueVectorReplacement.contains(replaced ) && "Vector replacement already registered") ? void ( 0) : __assert_fail ("!valueVectorReplacement.contains(replaced) && \"Vector replacement already registered\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 840 , __extension__ __PRETTY_FUNCTION__)); | ||||
841 | assert(replacement.getType().isa<VectorType>() &&(static_cast <bool> (replacement.getType().isa<VectorType >() && "Expected vector type in vector replacement" ) ? void (0) : __assert_fail ("replacement.getType().isa<VectorType>() && \"Expected vector type in vector replacement\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 842 , __extension__ __PRETTY_FUNCTION__)) | ||||
842 | "Expected vector type in vector replacement")(static_cast <bool> (replacement.getType().isa<VectorType >() && "Expected vector type in vector replacement" ) ? void (0) : __assert_fail ("replacement.getType().isa<VectorType>() && \"Expected vector type in vector replacement\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 842 , __extension__ __PRETTY_FUNCTION__)); | ||||
843 | valueVectorReplacement.map(replaced, replacement); | ||||
844 | } | ||||
845 | |||||
846 | /// Registers the scalar replacement of a scalar value. 'replacement' must be | ||||
847 | /// scalar. Both values must be block arguments. Operation results should be | ||||
848 | /// replaced using the 'registerOp*' utilitites. | ||||
849 | /// | ||||
850 | /// This utility is used to register the replacement of block arguments | ||||
851 | /// that are within the loop to be vectorized and will continue being scalar | ||||
852 | /// within the vector loop. | ||||
853 | /// | ||||
854 | /// Example: | ||||
855 | /// * 'replaced': induction variable of a loop to be vectorized. | ||||
856 | /// * 'replacement': new induction variable in the new vector loop. | ||||
857 | void VectorizationState::registerValueScalarReplacement( | ||||
858 | BlockArgument replaced, BlockArgument replacement) { | ||||
859 | registerValueScalarReplacementImpl(replaced, replacement); | ||||
860 | } | ||||
861 | |||||
862 | /// Registers the scalar replacement of a scalar result returned from a | ||||
863 | /// reduction loop. 'replacement' must be scalar. | ||||
864 | /// | ||||
865 | /// This utility is used to register the replacement for scalar results of | ||||
866 | /// vectorized reduction loops with iter_args. | ||||
867 | /// | ||||
868 | /// Example 2: | ||||
869 | /// * 'replaced': %0 = affine.for %i = 0 to 512 iter_args(%x = ...) -> (f32) | ||||
870 | /// * 'replacement': %1 = vector.reduction <add>, %0 : vector<4xf32> into f32 | ||||
871 | void VectorizationState::registerLoopResultScalarReplacement( | ||||
872 | Value replaced, Value replacement) { | ||||
873 | assert(isa<AffineForOp>(replaced.getDefiningOp()))(static_cast <bool> (isa<AffineForOp>(replaced.getDefiningOp ())) ? void (0) : __assert_fail ("isa<AffineForOp>(replaced.getDefiningOp())" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 873 , __extension__ __PRETTY_FUNCTION__)); | ||||
874 | assert(loopResultScalarReplacement.count(replaced) == 0 &&(static_cast <bool> (loopResultScalarReplacement.count( replaced) == 0 && "already registered") ? void (0) : __assert_fail ("loopResultScalarReplacement.count(replaced) == 0 && \"already registered\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 875 , __extension__ __PRETTY_FUNCTION__)) | ||||
875 | "already registered")(static_cast <bool> (loopResultScalarReplacement.count( replaced) == 0 && "already registered") ? void (0) : __assert_fail ("loopResultScalarReplacement.count(replaced) == 0 && \"already registered\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 875 , __extension__ __PRETTY_FUNCTION__)); | ||||
876 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ will replace a result of the loop "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ will replace a result of the loop " "with scalar: " << replacement; } } while (false) | ||||
877 | "with scalar: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ will replace a result of the loop " "with scalar: " << replacement; } } while (false) | ||||
878 | << replacement)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ will replace a result of the loop " "with scalar: " << replacement; } } while (false); | ||||
879 | loopResultScalarReplacement[replaced] = replacement; | ||||
880 | } | ||||
881 | |||||
882 | void VectorizationState::registerValueScalarReplacementImpl(Value replaced, | ||||
883 | Value replacement) { | ||||
884 | assert(!valueScalarReplacement.contains(replaced) &&(static_cast <bool> (!valueScalarReplacement.contains(replaced ) && "Scalar value replacement already registered") ? void (0) : __assert_fail ("!valueScalarReplacement.contains(replaced) && \"Scalar value replacement already registered\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 885 , __extension__ __PRETTY_FUNCTION__)) | ||||
885 | "Scalar value replacement already registered")(static_cast <bool> (!valueScalarReplacement.contains(replaced ) && "Scalar value replacement already registered") ? void (0) : __assert_fail ("!valueScalarReplacement.contains(replaced) && \"Scalar value replacement already registered\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 885 , __extension__ __PRETTY_FUNCTION__)); | ||||
886 | assert(!replacement.getType().isa<VectorType>() &&(static_cast <bool> (!replacement.getType().isa<VectorType >() && "Expected scalar type in scalar replacement" ) ? void (0) : __assert_fail ("!replacement.getType().isa<VectorType>() && \"Expected scalar type in scalar replacement\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 887 , __extension__ __PRETTY_FUNCTION__)) | ||||
887 | "Expected scalar type in scalar replacement")(static_cast <bool> (!replacement.getType().isa<VectorType >() && "Expected scalar type in scalar replacement" ) ? void (0) : __assert_fail ("!replacement.getType().isa<VectorType>() && \"Expected scalar type in scalar replacement\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 887 , __extension__ __PRETTY_FUNCTION__)); | ||||
888 | valueScalarReplacement.map(replaced, replacement); | ||||
889 | } | ||||
890 | |||||
891 | /// Returns in 'replacedVals' the scalar replacement for values in 'inputVals'. | ||||
892 | void VectorizationState::getScalarValueReplacementsFor( | ||||
893 | ValueRange inputVals, SmallVectorImpl<Value> &replacedVals) { | ||||
894 | for (Value inputVal : inputVals) | ||||
895 | replacedVals.push_back(valueScalarReplacement.lookupOrDefault(inputVal)); | ||||
896 | } | ||||
897 | |||||
898 | /// Erases a loop nest, including all its nested operations. | ||||
899 | static void eraseLoopNest(AffineForOp forOp) { | ||||
900 | LLVM_DEBUG(dbgs() << "[early-vect]+++++ erasing:\n" << forOp << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "[early-vect]+++++ erasing:\n" << forOp << "\n"; } } while (false); | ||||
901 | forOp.erase(); | ||||
902 | } | ||||
903 | |||||
904 | /// Erases the scalar loop nest after its successful vectorization. | ||||
905 | void VectorizationState::finishVectorizationPattern(AffineForOp rootLoop) { | ||||
906 | LLVM_DEBUG(dbgs() << "\n[early-vect] Finalizing vectorization\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect] Finalizing vectorization\n" ; } } while (false); | ||||
907 | eraseLoopNest(rootLoop); | ||||
908 | } | ||||
909 | |||||
910 | // Apply 'map' with 'mapOperands' returning resulting values in 'results'. | ||||
911 | static void computeMemoryOpIndices(Operation *op, AffineMap map, | ||||
912 | ValueRange mapOperands, | ||||
913 | VectorizationState &state, | ||||
914 | SmallVectorImpl<Value> &results) { | ||||
915 | for (auto resultExpr : map.getResults()) { | ||||
916 | auto singleResMap = | ||||
917 | AffineMap::get(map.getNumDims(), map.getNumSymbols(), resultExpr); | ||||
918 | auto afOp = state.builder.create<AffineApplyOp>(op->getLoc(), singleResMap, | ||||
919 | mapOperands); | ||||
920 | results.push_back(afOp); | ||||
921 | } | ||||
922 | } | ||||
923 | |||||
924 | /// Returns a FilterFunctionType that can be used in NestedPattern to match a | ||||
925 | /// loop whose underlying load/store accesses are either invariant or all | ||||
926 | // varying along the `fastestVaryingMemRefDimension`. | ||||
927 | static FilterFunctionType | ||||
928 | isVectorizableLoopPtrFactory(const DenseSet<Operation *> ¶llelLoops, | ||||
929 | int fastestVaryingMemRefDimension) { | ||||
930 | return [¶llelLoops, fastestVaryingMemRefDimension](Operation &forOp) { | ||||
931 | auto loop = cast<AffineForOp>(forOp); | ||||
932 | auto parallelIt = parallelLoops.find(loop); | ||||
933 | if (parallelIt == parallelLoops.end()) | ||||
934 | return false; | ||||
935 | int memRefDim = -1; | ||||
936 | auto vectorizableBody = | ||||
937 | isVectorizableLoopBody(loop, &memRefDim, vectorTransferPattern()); | ||||
938 | if (!vectorizableBody) | ||||
939 | return false; | ||||
940 | return memRefDim == -1 || fastestVaryingMemRefDimension == -1 || | ||||
941 | memRefDim == fastestVaryingMemRefDimension; | ||||
942 | }; | ||||
943 | } | ||||
944 | |||||
945 | /// Returns the vector type resulting from applying the provided vectorization | ||||
946 | /// strategy on the scalar type. | ||||
947 | static VectorType getVectorType(Type scalarTy, | ||||
948 | const VectorizationStrategy *strategy) { | ||||
949 | assert(!scalarTy.isa<VectorType>() && "Expected scalar type")(static_cast <bool> (!scalarTy.isa<VectorType>() && "Expected scalar type") ? void (0) : __assert_fail ("!scalarTy.isa<VectorType>() && \"Expected scalar type\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 949 , __extension__ __PRETTY_FUNCTION__)); | ||||
950 | return VectorType::get(strategy->vectorSizes, scalarTy); | ||||
951 | } | ||||
952 | |||||
953 | /// Tries to transform a scalar constant into a vector constant. Returns the | ||||
954 | /// vector constant if the scalar type is valid vector element type. Returns | ||||
955 | /// nullptr, otherwise. | ||||
956 | static arith::ConstantOp vectorizeConstant(arith::ConstantOp constOp, | ||||
957 | VectorizationState &state) { | ||||
958 | Type scalarTy = constOp.getType(); | ||||
959 | if (!VectorType::isValidElementType(scalarTy)) | ||||
960 | return nullptr; | ||||
| |||||
| |||||
961 | |||||
962 | auto vecTy = getVectorType(scalarTy, state.strategy); | ||||
963 | auto vecAttr = DenseElementsAttr::get(vecTy, constOp.getValue()); | ||||
964 | |||||
965 | OpBuilder::InsertionGuard guard(state.builder); | ||||
966 | Operation *parentOp = state.builder.getInsertionBlock()->getParentOp(); | ||||
967 | // Find the innermost vectorized ancestor loop to insert the vector constant. | ||||
968 | while (parentOp && !state.vecLoopToVecDim.count(parentOp)) | ||||
969 | parentOp = parentOp->getParentOp(); | ||||
970 | assert(parentOp && state.vecLoopToVecDim.count(parentOp) &&(static_cast <bool> (parentOp && state.vecLoopToVecDim .count(parentOp) && isa<AffineForOp>(parentOp) && "Expected a vectorized for op") ? void (0) : __assert_fail ( "parentOp && state.vecLoopToVecDim.count(parentOp) && isa<AffineForOp>(parentOp) && \"Expected a vectorized for op\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 971 , __extension__ __PRETTY_FUNCTION__)) | ||||
971 | isa<AffineForOp>(parentOp) && "Expected a vectorized for op")(static_cast <bool> (parentOp && state.vecLoopToVecDim .count(parentOp) && isa<AffineForOp>(parentOp) && "Expected a vectorized for op") ? void (0) : __assert_fail ( "parentOp && state.vecLoopToVecDim.count(parentOp) && isa<AffineForOp>(parentOp) && \"Expected a vectorized for op\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 971 , __extension__ __PRETTY_FUNCTION__)); | ||||
972 | auto vecForOp = cast<AffineForOp>(parentOp); | ||||
973 | state.builder.setInsertionPointToStart(vecForOp.getBody()); | ||||
974 | auto newConstOp = | ||||
975 | state.builder.create<arith::ConstantOp>(constOp.getLoc(), vecAttr); | ||||
976 | |||||
977 | // Register vector replacement for future uses in the scope. | ||||
978 | state.registerOpVectorReplacement(constOp, newConstOp); | ||||
979 | return newConstOp; | ||||
980 | } | ||||
981 | |||||
982 | /// Creates a constant vector filled with the neutral elements of the given | ||||
983 | /// reduction. The scalar type of vector elements will be taken from | ||||
984 | /// `oldOperand`. | ||||
985 | static arith::ConstantOp createInitialVector(arith::AtomicRMWKind reductionKind, | ||||
986 | Value oldOperand, | ||||
987 | VectorizationState &state) { | ||||
988 | Type scalarTy = oldOperand.getType(); | ||||
989 | if (!VectorType::isValidElementType(scalarTy)) | ||||
990 | return nullptr; | ||||
991 | |||||
992 | Attribute valueAttr = getIdentityValueAttr( | ||||
993 | reductionKind, scalarTy, state.builder, oldOperand.getLoc()); | ||||
994 | auto vecTy = getVectorType(scalarTy, state.strategy); | ||||
995 | auto vecAttr = DenseElementsAttr::get(vecTy, valueAttr); | ||||
996 | auto newConstOp = | ||||
997 | state.builder.create<arith::ConstantOp>(oldOperand.getLoc(), vecAttr); | ||||
998 | |||||
999 | return newConstOp; | ||||
1000 | } | ||||
1001 | |||||
1002 | /// Creates a mask used to filter out garbage elements in the last iteration | ||||
1003 | /// of unaligned loops. If a mask is not required then `nullptr` is returned. | ||||
1004 | /// The mask will be a vector of booleans representing meaningful vector | ||||
1005 | /// elements in the current iteration. It is filled with ones for each iteration | ||||
1006 | /// except for the last one, where it has the form `11...100...0` with the | ||||
1007 | /// number of ones equal to the number of meaningful elements (i.e. the number | ||||
1008 | /// of iterations that would be left in the original loop). | ||||
1009 | static Value createMask(AffineForOp vecForOp, VectorizationState &state) { | ||||
1010 | assert(state.strategy->vectorSizes.size() == 1 &&(static_cast <bool> (state.strategy->vectorSizes.size () == 1 && "Creating a mask non-1-D vectors is not supported." ) ? void (0) : __assert_fail ("state.strategy->vectorSizes.size() == 1 && \"Creating a mask non-1-D vectors is not supported.\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1011 , __extension__ __PRETTY_FUNCTION__)) | ||||
1011 | "Creating a mask non-1-D vectors is not supported.")(static_cast <bool> (state.strategy->vectorSizes.size () == 1 && "Creating a mask non-1-D vectors is not supported." ) ? void (0) : __assert_fail ("state.strategy->vectorSizes.size() == 1 && \"Creating a mask non-1-D vectors is not supported.\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1011 , __extension__ __PRETTY_FUNCTION__)); | ||||
1012 | assert(vecForOp.getStep() == state.strategy->vectorSizes[0] &&(static_cast <bool> (vecForOp.getStep() == state.strategy ->vectorSizes[0] && "Creating a mask for loops with non-unit original step size is not " "supported.") ? void (0) : __assert_fail ("vecForOp.getStep() == state.strategy->vectorSizes[0] && \"Creating a mask for loops with non-unit original step size is not \" \"supported.\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1014 , __extension__ __PRETTY_FUNCTION__)) | ||||
1013 | "Creating a mask for loops with non-unit original step size is not "(static_cast <bool> (vecForOp.getStep() == state.strategy ->vectorSizes[0] && "Creating a mask for loops with non-unit original step size is not " "supported.") ? void (0) : __assert_fail ("vecForOp.getStep() == state.strategy->vectorSizes[0] && \"Creating a mask for loops with non-unit original step size is not \" \"supported.\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1014 , __extension__ __PRETTY_FUNCTION__)) | ||||
1014 | "supported.")(static_cast <bool> (vecForOp.getStep() == state.strategy ->vectorSizes[0] && "Creating a mask for loops with non-unit original step size is not " "supported.") ? void (0) : __assert_fail ("vecForOp.getStep() == state.strategy->vectorSizes[0] && \"Creating a mask for loops with non-unit original step size is not \" \"supported.\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1014 , __extension__ __PRETTY_FUNCTION__)); | ||||
1015 | |||||
1016 | // Check if we have already created the mask. | ||||
1017 | if (Value mask = state.vecLoopToMask.lookup(vecForOp)) | ||||
1018 | return mask; | ||||
1019 | |||||
1020 | // If the loop has constant bounds and the original number of iterations is | ||||
1021 | // divisable by the vector size then we don't need a mask. | ||||
1022 | if (vecForOp.hasConstantBounds()) { | ||||
1023 | int64_t originalTripCount = | ||||
1024 | vecForOp.getConstantUpperBound() - vecForOp.getConstantLowerBound(); | ||||
1025 | if (originalTripCount % vecForOp.getStep() == 0) | ||||
1026 | return nullptr; | ||||
1027 | } | ||||
1028 | |||||
1029 | OpBuilder::InsertionGuard guard(state.builder); | ||||
1030 | state.builder.setInsertionPointToStart(vecForOp.getBody()); | ||||
1031 | |||||
1032 | // We generate the mask using the `vector.create_mask` operation which accepts | ||||
1033 | // the number of meaningful elements (i.e. the length of the prefix of 1s). | ||||
1034 | // To compute the number of meaningful elements we subtract the current value | ||||
1035 | // of the iteration variable from the upper bound of the loop. Example: | ||||
1036 | // | ||||
1037 | // // 500 is the upper bound of the loop | ||||
1038 | // #map = affine_map<(d0) -> (500 - d0)> | ||||
1039 | // %elems_left = affine.apply #map(%iv) | ||||
1040 | // %mask = vector.create_mask %elems_left : vector<128xi1> | ||||
1041 | |||||
1042 | Location loc = vecForOp.getLoc(); | ||||
1043 | |||||
1044 | // First we get the upper bound of the loop using `affine.apply` or | ||||
1045 | // `affine.min`. | ||||
1046 | AffineMap ubMap = vecForOp.getUpperBoundMap(); | ||||
1047 | Value ub; | ||||
1048 | if (ubMap.getNumResults() == 1) | ||||
1049 | ub = state.builder.create<AffineApplyOp>(loc, vecForOp.getUpperBoundMap(), | ||||
1050 | vecForOp.getUpperBoundOperands()); | ||||
1051 | else | ||||
1052 | ub = state.builder.create<AffineMinOp>(loc, vecForOp.getUpperBoundMap(), | ||||
1053 | vecForOp.getUpperBoundOperands()); | ||||
1054 | // Then we compute the number of (original) iterations left in the loop. | ||||
1055 | AffineExpr subExpr = | ||||
1056 | state.builder.getAffineDimExpr(0) - state.builder.getAffineDimExpr(1); | ||||
1057 | Value itersLeft = | ||||
1058 | makeComposedAffineApply(state.builder, loc, AffineMap::get(2, 0, subExpr), | ||||
1059 | {ub, vecForOp.getInductionVar()}); | ||||
1060 | // If the affine maps were successfully composed then `ub` is unneeded. | ||||
1061 | if (ub.use_empty()) | ||||
1062 | ub.getDefiningOp()->erase(); | ||||
1063 | // Finally we create the mask. | ||||
1064 | Type maskTy = VectorType::get(state.strategy->vectorSizes, | ||||
1065 | state.builder.getIntegerType(1)); | ||||
1066 | Value mask = | ||||
1067 | state.builder.create<vector::CreateMaskOp>(loc, maskTy, itersLeft); | ||||
1068 | |||||
1069 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ creating a mask:\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ creating a mask:\n" << itersLeft << "\n" << mask << "\n" ; } } while (false) | ||||
1070 | << itersLeft << "\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ creating a mask:\n" << itersLeft << "\n" << mask << "\n" ; } } while (false) | ||||
1071 | << mask << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ creating a mask:\n" << itersLeft << "\n" << mask << "\n" ; } } while (false); | ||||
1072 | |||||
1073 | state.vecLoopToMask[vecForOp] = mask; | ||||
1074 | return mask; | ||||
1075 | } | ||||
1076 | |||||
1077 | /// Returns true if the provided value is vector uniform given the vectorization | ||||
1078 | /// strategy. | ||||
1079 | // TODO: For now, only values that are induction variables of loops not in | ||||
1080 | // `loopToVectorDim` or invariants to all the loops in the vectorization | ||||
1081 | // strategy are considered vector uniforms. | ||||
1082 | static bool isUniformDefinition(Value value, | ||||
1083 | const VectorizationStrategy *strategy) { | ||||
1084 | AffineForOp forOp = getForInductionVarOwner(value); | ||||
1085 | if (forOp && strategy->loopToVectorDim.count(forOp) == 0) | ||||
1086 | return true; | ||||
1087 | |||||
1088 | for (auto loopToDim : strategy->loopToVectorDim) { | ||||
1089 | auto loop = cast<AffineForOp>(loopToDim.first); | ||||
1090 | if (!loop.isDefinedOutsideOfLoop(value)) | ||||
1091 | return false; | ||||
1092 | } | ||||
1093 | return true; | ||||
1094 | } | ||||
1095 | |||||
1096 | /// Generates a broadcast op for the provided uniform value using the | ||||
1097 | /// vectorization strategy in 'state'. | ||||
1098 | static Operation *vectorizeUniform(Value uniformVal, | ||||
1099 | VectorizationState &state) { | ||||
1100 | OpBuilder::InsertionGuard guard(state.builder); | ||||
1101 | Value uniformScalarRepl = | ||||
1102 | state.valueScalarReplacement.lookupOrDefault(uniformVal); | ||||
1103 | state.builder.setInsertionPointAfterValue(uniformScalarRepl); | ||||
1104 | |||||
1105 | auto vectorTy = getVectorType(uniformVal.getType(), state.strategy); | ||||
1106 | auto bcastOp = state.builder.create<BroadcastOp>(uniformVal.getLoc(), | ||||
1107 | vectorTy, uniformScalarRepl); | ||||
1108 | state.registerValueVectorReplacement(uniformVal, bcastOp); | ||||
1109 | return bcastOp; | ||||
1110 | } | ||||
1111 | |||||
1112 | /// Tries to vectorize a given `operand` by applying the following logic: | ||||
1113 | /// 1. if the defining operation has been already vectorized, `operand` is | ||||
1114 | /// already in the proper vector form; | ||||
1115 | /// 2. if the `operand` is a constant, returns the vectorized form of the | ||||
1116 | /// constant; | ||||
1117 | /// 3. if the `operand` is uniform, returns a vector broadcast of the `op`; | ||||
1118 | /// 4. otherwise, the vectorization of `operand` is not supported. | ||||
1119 | /// Newly created vector operations are registered in `state` as replacement | ||||
1120 | /// for their scalar counterparts. | ||||
1121 | /// In particular this logic captures some of the use cases where definitions | ||||
1122 | /// that are not scoped under the current pattern are needed to vectorize. | ||||
1123 | /// One such example is top level function constants that need to be splatted. | ||||
1124 | /// | ||||
1125 | /// Returns an operand that has been vectorized to match `state`'s strategy if | ||||
1126 | /// vectorization is possible with the above logic. Returns nullptr otherwise. | ||||
1127 | /// | ||||
1128 | /// TODO: handle more complex cases. | ||||
1129 | static Value vectorizeOperand(Value operand, VectorizationState &state) { | ||||
1130 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ vectorize operand: " << operand)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ vectorize operand: " << operand; } } while (false); | ||||
1131 | // If this value is already vectorized, we are done. | ||||
1132 | if (Value vecRepl = state.valueVectorReplacement.lookupOrNull(operand)) { | ||||
1133 | LLVM_DEBUG(dbgs() << " -> already vectorized: " << vecRepl)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << " -> already vectorized: " << vecRepl; } } while (false); | ||||
1134 | return vecRepl; | ||||
1135 | } | ||||
1136 | |||||
1137 | // An vector operand that is not in the replacement map should never reach | ||||
1138 | // this point. Reaching this point could mean that the code was already | ||||
1139 | // vectorized and we shouldn't try to vectorize already vectorized code. | ||||
1140 | assert(!operand.getType().isa<VectorType>() &&(static_cast <bool> (!operand.getType().isa<VectorType >() && "Vector op not found in replacement map") ? void (0) : __assert_fail ("!operand.getType().isa<VectorType>() && \"Vector op not found in replacement map\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1141 , __extension__ __PRETTY_FUNCTION__)) | ||||
1141 | "Vector op not found in replacement map")(static_cast <bool> (!operand.getType().isa<VectorType >() && "Vector op not found in replacement map") ? void (0) : __assert_fail ("!operand.getType().isa<VectorType>() && \"Vector op not found in replacement map\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1141 , __extension__ __PRETTY_FUNCTION__)); | ||||
1142 | |||||
1143 | // Vectorize constant. | ||||
1144 | if (auto constOp = operand.getDefiningOp<arith::ConstantOp>()) { | ||||
1145 | auto vecConstant = vectorizeConstant(constOp, state); | ||||
1146 | LLVM_DEBUG(dbgs() << "-> constant: " << vecConstant)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "-> constant: " << vecConstant; } } while (false); | ||||
1147 | return vecConstant.getResult(); | ||||
1148 | } | ||||
1149 | |||||
1150 | // Vectorize uniform values. | ||||
1151 | if (isUniformDefinition(operand, state.strategy)) { | ||||
1152 | Operation *vecUniform = vectorizeUniform(operand, state); | ||||
1153 | LLVM_DEBUG(dbgs() << "-> uniform: " << *vecUniform)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "-> uniform: " << * vecUniform; } } while (false); | ||||
1154 | return vecUniform->getResult(0); | ||||
1155 | } | ||||
1156 | |||||
1157 | // Check for unsupported block argument scenarios. A supported block argument | ||||
1158 | // should have been vectorized already. | ||||
1159 | if (!operand.getDefiningOp()) | ||||
1160 | LLVM_DEBUG(dbgs() << "-> unsupported block argument\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "-> unsupported block argument\n" ; } } while (false); | ||||
1161 | else | ||||
1162 | // Generic unsupported case. | ||||
1163 | LLVM_DEBUG(dbgs() << "-> non-vectorizable\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "-> non-vectorizable\n"; } } while (false); | ||||
1164 | |||||
1165 | return nullptr; | ||||
1166 | } | ||||
1167 | |||||
1168 | /// Vectorizes an affine load with the vectorization strategy in 'state' by | ||||
1169 | /// generating a 'vector.transfer_read' op with the proper permutation map | ||||
1170 | /// inferred from the indices of the load. The new 'vector.transfer_read' is | ||||
1171 | /// registered as replacement of the scalar load. Returns the newly created | ||||
1172 | /// 'vector.transfer_read' if vectorization was successful. Returns nullptr, | ||||
1173 | /// otherwise. | ||||
1174 | static Operation *vectorizeAffineLoad(AffineLoadOp loadOp, | ||||
1175 | VectorizationState &state) { | ||||
1176 | MemRefType memRefType = loadOp.getMemRefType(); | ||||
1177 | Type elementType = memRefType.getElementType(); | ||||
1178 | auto vectorType = VectorType::get(state.strategy->vectorSizes, elementType); | ||||
1179 | |||||
1180 | // Replace map operands with operands from the vector loop nest. | ||||
1181 | SmallVector<Value, 8> mapOperands; | ||||
1182 | state.getScalarValueReplacementsFor(loadOp.getMapOperands(), mapOperands); | ||||
1183 | |||||
1184 | // Compute indices for the transfer op. AffineApplyOp's may be generated. | ||||
1185 | SmallVector<Value, 8> indices; | ||||
1186 | indices.reserve(memRefType.getRank()); | ||||
1187 | if (loadOp.getAffineMap() != | ||||
1188 | state.builder.getMultiDimIdentityMap(memRefType.getRank())) | ||||
1189 | computeMemoryOpIndices(loadOp, loadOp.getAffineMap(), mapOperands, state, | ||||
1190 | indices); | ||||
1191 | else | ||||
1192 | indices.append(mapOperands.begin(), mapOperands.end()); | ||||
1193 | |||||
1194 | // Compute permutation map using the information of new vector loops. | ||||
1195 | auto permutationMap = makePermutationMap(state.builder.getInsertionBlock(), | ||||
1196 | indices, state.vecLoopToVecDim); | ||||
1197 | if (!permutationMap) { | ||||
1198 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ can't compute permutationMap\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ can't compute permutationMap\n" ; } } while (false); | ||||
1199 | return nullptr; | ||||
1200 | } | ||||
1201 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ permutationMap: ")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ permutationMap: " ; } } while (false); | ||||
1202 | LLVM_DEBUG(permutationMap.print(dbgs()))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { permutationMap.print(dbgs()); } } while (false ); | ||||
1203 | |||||
1204 | auto transfer = state.builder.create<vector::TransferReadOp>( | ||||
1205 | loadOp.getLoc(), vectorType, loadOp.getMemRef(), indices, permutationMap); | ||||
1206 | |||||
1207 | // Register replacement for future uses in the scope. | ||||
1208 | state.registerOpVectorReplacement(loadOp, transfer); | ||||
1209 | return transfer; | ||||
1210 | } | ||||
1211 | |||||
1212 | /// Vectorizes an affine store with the vectorization strategy in 'state' by | ||||
1213 | /// generating a 'vector.transfer_write' op with the proper permutation map | ||||
1214 | /// inferred from the indices of the store. The new 'vector.transfer_store' is | ||||
1215 | /// registered as replacement of the scalar load. Returns the newly created | ||||
1216 | /// 'vector.transfer_write' if vectorization was successful. Returns nullptr, | ||||
1217 | /// otherwise. | ||||
1218 | static Operation *vectorizeAffineStore(AffineStoreOp storeOp, | ||||
1219 | VectorizationState &state) { | ||||
1220 | MemRefType memRefType = storeOp.getMemRefType(); | ||||
1221 | Value vectorValue = vectorizeOperand(storeOp.getValueToStore(), state); | ||||
1222 | if (!vectorValue) | ||||
1223 | return nullptr; | ||||
1224 | |||||
1225 | // Replace map operands with operands from the vector loop nest. | ||||
1226 | SmallVector<Value, 8> mapOperands; | ||||
1227 | state.getScalarValueReplacementsFor(storeOp.getMapOperands(), mapOperands); | ||||
1228 | |||||
1229 | // Compute indices for the transfer op. AffineApplyOp's may be generated. | ||||
1230 | SmallVector<Value, 8> indices; | ||||
1231 | indices.reserve(memRefType.getRank()); | ||||
1232 | if (storeOp.getAffineMap() != | ||||
1233 | state.builder.getMultiDimIdentityMap(memRefType.getRank())) | ||||
1234 | computeMemoryOpIndices(storeOp, storeOp.getAffineMap(), mapOperands, state, | ||||
1235 | indices); | ||||
1236 | else | ||||
1237 | indices.append(mapOperands.begin(), mapOperands.end()); | ||||
1238 | |||||
1239 | // Compute permutation map using the information of new vector loops. | ||||
1240 | auto permutationMap = makePermutationMap(state.builder.getInsertionBlock(), | ||||
1241 | indices, state.vecLoopToVecDim); | ||||
1242 | if (!permutationMap) | ||||
1243 | return nullptr; | ||||
1244 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ permutationMap: ")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ permutationMap: " ; } } while (false); | ||||
1245 | LLVM_DEBUG(permutationMap.print(dbgs()))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { permutationMap.print(dbgs()); } } while (false ); | ||||
1246 | |||||
1247 | auto transfer = state.builder.create<vector::TransferWriteOp>( | ||||
1248 | storeOp.getLoc(), vectorValue, storeOp.getMemRef(), indices, | ||||
1249 | permutationMap); | ||||
1250 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ vectorized store: " << transfer)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ vectorized store: " << transfer; } } while (false); | ||||
1251 | |||||
1252 | // Register replacement for future uses in the scope. | ||||
1253 | state.registerOpVectorReplacement(storeOp, transfer); | ||||
1254 | return transfer; | ||||
1255 | } | ||||
1256 | |||||
1257 | /// Returns true if `value` is a constant equal to the neutral element of the | ||||
1258 | /// given vectorizable reduction. | ||||
1259 | static bool isNeutralElementConst(arith::AtomicRMWKind reductionKind, | ||||
1260 | Value value, VectorizationState &state) { | ||||
1261 | Type scalarTy = value.getType(); | ||||
1262 | if (!VectorType::isValidElementType(scalarTy)) | ||||
1263 | return false; | ||||
1264 | Attribute valueAttr = getIdentityValueAttr(reductionKind, scalarTy, | ||||
1265 | state.builder, value.getLoc()); | ||||
1266 | if (auto constOp = dyn_cast_or_null<arith::ConstantOp>(value.getDefiningOp())) | ||||
1267 | return constOp.getValue() == valueAttr; | ||||
1268 | return false; | ||||
1269 | } | ||||
1270 | |||||
1271 | /// Vectorizes a loop with the vectorization strategy in 'state'. A new loop is | ||||
1272 | /// created and registered as replacement for the scalar loop. The builder's | ||||
1273 | /// insertion point is set to the new loop's body so that subsequent vectorized | ||||
1274 | /// operations are inserted into the new loop. If the loop is a vector | ||||
1275 | /// dimension, the step of the newly created loop will reflect the vectorization | ||||
1276 | /// factor used to vectorized that dimension. | ||||
1277 | static Operation *vectorizeAffineForOp(AffineForOp forOp, | ||||
1278 | VectorizationState &state) { | ||||
1279 | const VectorizationStrategy &strategy = *state.strategy; | ||||
1280 | auto loopToVecDimIt = strategy.loopToVectorDim.find(forOp); | ||||
1281 | bool isLoopVecDim = loopToVecDimIt != strategy.loopToVectorDim.end(); | ||||
1282 | |||||
1283 | // TODO: Vectorization of reduction loops is not supported for non-unit steps. | ||||
1284 | if (isLoopVecDim && forOp.getNumIterOperands() > 0 && forOp.getStep() != 1) { | ||||
1285 | LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ unsupported step size for reduction loop: " << forOp.getStep() << "\n"; } } while (false) | ||||
1286 | dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ unsupported step size for reduction loop: " << forOp.getStep() << "\n"; } } while (false) | ||||
1287 | << "\n[early-vect]+++++ unsupported step size for reduction loop: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ unsupported step size for reduction loop: " << forOp.getStep() << "\n"; } } while (false) | ||||
1288 | << forOp.getStep() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ unsupported step size for reduction loop: " << forOp.getStep() << "\n"; } } while (false); | ||||
1289 | return nullptr; | ||||
1290 | } | ||||
1291 | |||||
1292 | // If we are vectorizing a vector dimension, compute a new step for the new | ||||
1293 | // vectorized loop using the vectorization factor for the vector dimension. | ||||
1294 | // Otherwise, propagate the step of the scalar loop. | ||||
1295 | unsigned newStep; | ||||
1296 | if (isLoopVecDim) { | ||||
1297 | unsigned vectorDim = loopToVecDimIt->second; | ||||
1298 | assert(vectorDim < strategy.vectorSizes.size() && "vector dim overflow")(static_cast <bool> (vectorDim < strategy.vectorSizes .size() && "vector dim overflow") ? void (0) : __assert_fail ("vectorDim < strategy.vectorSizes.size() && \"vector dim overflow\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1298 , __extension__ __PRETTY_FUNCTION__)); | ||||
1299 | int64_t forOpVecFactor = strategy.vectorSizes[vectorDim]; | ||||
1300 | newStep = forOp.getStep() * forOpVecFactor; | ||||
1301 | } else { | ||||
1302 | newStep = forOp.getStep(); | ||||
1303 | } | ||||
1304 | |||||
1305 | // Get information about reduction kinds. | ||||
1306 | ArrayRef<LoopReduction> reductions; | ||||
1307 | if (isLoopVecDim && forOp.getNumIterOperands() > 0) { | ||||
1308 | auto it = strategy.reductionLoops.find(forOp); | ||||
1309 | assert(it != strategy.reductionLoops.end() &&(static_cast <bool> (it != strategy.reductionLoops.end( ) && "Reduction descriptors not found when vectorizing a reduction loop" ) ? void (0) : __assert_fail ("it != strategy.reductionLoops.end() && \"Reduction descriptors not found when vectorizing a reduction loop\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1310 , __extension__ __PRETTY_FUNCTION__)) | ||||
1310 | "Reduction descriptors not found when vectorizing a reduction loop")(static_cast <bool> (it != strategy.reductionLoops.end( ) && "Reduction descriptors not found when vectorizing a reduction loop" ) ? void (0) : __assert_fail ("it != strategy.reductionLoops.end() && \"Reduction descriptors not found when vectorizing a reduction loop\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1310 , __extension__ __PRETTY_FUNCTION__)); | ||||
1311 | reductions = it->second; | ||||
1312 | assert(reductions.size() == forOp.getNumIterOperands() &&(static_cast <bool> (reductions.size() == forOp.getNumIterOperands () && "The size of reductions array must match the number of iter_args" ) ? void (0) : __assert_fail ("reductions.size() == forOp.getNumIterOperands() && \"The size of reductions array must match the number of iter_args\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1313 , __extension__ __PRETTY_FUNCTION__)) | ||||
1313 | "The size of reductions array must match the number of iter_args")(static_cast <bool> (reductions.size() == forOp.getNumIterOperands () && "The size of reductions array must match the number of iter_args" ) ? void (0) : __assert_fail ("reductions.size() == forOp.getNumIterOperands() && \"The size of reductions array must match the number of iter_args\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1313 , __extension__ __PRETTY_FUNCTION__)); | ||||
1314 | } | ||||
1315 | |||||
1316 | // Vectorize 'iter_args'. | ||||
1317 | SmallVector<Value, 8> vecIterOperands; | ||||
1318 | if (!isLoopVecDim) { | ||||
1319 | for (auto operand : forOp.getIterOperands()) | ||||
1320 | vecIterOperands.push_back(vectorizeOperand(operand, state)); | ||||
1321 | } else { | ||||
1322 | // For reduction loops we need to pass a vector of neutral elements as an | ||||
1323 | // initial value of the accumulator. We will add the original initial value | ||||
1324 | // later. | ||||
1325 | for (auto redAndOperand : llvm::zip(reductions, forOp.getIterOperands())) { | ||||
1326 | vecIterOperands.push_back(createInitialVector( | ||||
1327 | std::get<0>(redAndOperand).kind, std::get<1>(redAndOperand), state)); | ||||
1328 | } | ||||
1329 | } | ||||
1330 | |||||
1331 | auto vecForOp = state.builder.create<AffineForOp>( | ||||
1332 | forOp.getLoc(), forOp.getLowerBoundOperands(), forOp.getLowerBoundMap(), | ||||
1333 | forOp.getUpperBoundOperands(), forOp.getUpperBoundMap(), newStep, | ||||
1334 | vecIterOperands, | ||||
1335 | /*bodyBuilder=*/[](OpBuilder &, Location, Value, ValueRange) { | ||||
1336 | // Make sure we don't create a default terminator in the loop body as | ||||
1337 | // the proper terminator will be added during vectorization. | ||||
1338 | }); | ||||
1339 | |||||
1340 | // Register loop-related replacements: | ||||
1341 | // 1) The new vectorized loop is registered as vector replacement of the | ||||
1342 | // scalar loop. | ||||
1343 | // 2) The new iv of the vectorized loop is registered as scalar replacement | ||||
1344 | // since a scalar copy of the iv will prevail in the vectorized loop. | ||||
1345 | // TODO: A vector replacement will also be added in the future when | ||||
1346 | // vectorization of linear ops is supported. | ||||
1347 | // 3) The new 'iter_args' region arguments are registered as vector | ||||
1348 | // replacements since they have been vectorized. | ||||
1349 | // 4) If the loop performs a reduction along the vector dimension, a | ||||
1350 | // `vector.reduction` or similar op is inserted for each resulting value | ||||
1351 | // of the loop and its scalar value replaces the corresponding scalar | ||||
1352 | // result of the loop. | ||||
1353 | state.registerOpVectorReplacement(forOp, vecForOp); | ||||
1354 | state.registerValueScalarReplacement(forOp.getInductionVar(), | ||||
1355 | vecForOp.getInductionVar()); | ||||
1356 | for (auto iterTuple : | ||||
1357 | llvm ::zip(forOp.getRegionIterArgs(), vecForOp.getRegionIterArgs())) | ||||
1358 | state.registerBlockArgVectorReplacement(std::get<0>(iterTuple), | ||||
1359 | std::get<1>(iterTuple)); | ||||
1360 | |||||
1361 | if (isLoopVecDim) { | ||||
1362 | for (unsigned i = 0; i < vecForOp.getNumIterOperands(); ++i) { | ||||
1363 | // First, we reduce the vector returned from the loop into a scalar. | ||||
1364 | Value reducedRes = | ||||
1365 | getVectorReductionOp(reductions[i].kind, state.builder, | ||||
1366 | vecForOp.getLoc(), vecForOp.getResult(i)); | ||||
1367 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ creating a vector reduction: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ creating a vector reduction: " << reducedRes; } } while (false) | ||||
1368 | << reducedRes)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ creating a vector reduction: " << reducedRes; } } while (false); | ||||
1369 | // Then we combine it with the original (scalar) initial value unless it | ||||
1370 | // is equal to the neutral element of the reduction. | ||||
1371 | Value origInit = forOp.getOperand(forOp.getNumControlOperands() + i); | ||||
1372 | Value finalRes = reducedRes; | ||||
1373 | if (!isNeutralElementConst(reductions[i].kind, origInit, state)) | ||||
1374 | finalRes = | ||||
1375 | arith::getReductionOp(reductions[i].kind, state.builder, | ||||
1376 | reducedRes.getLoc(), reducedRes, origInit); | ||||
1377 | state.registerLoopResultScalarReplacement(forOp.getResult(i), finalRes); | ||||
1378 | } | ||||
1379 | } | ||||
1380 | |||||
1381 | if (isLoopVecDim) | ||||
1382 | state.vecLoopToVecDim[vecForOp] = loopToVecDimIt->second; | ||||
1383 | |||||
1384 | // Change insertion point so that upcoming vectorized instructions are | ||||
1385 | // inserted into the vectorized loop's body. | ||||
1386 | state.builder.setInsertionPointToStart(vecForOp.getBody()); | ||||
1387 | |||||
1388 | // If this is a reduction loop then we may need to create a mask to filter out | ||||
1389 | // garbage in the last iteration. | ||||
1390 | if (isLoopVecDim && forOp.getNumIterOperands() > 0) | ||||
1391 | createMask(vecForOp, state); | ||||
1392 | |||||
1393 | return vecForOp; | ||||
1394 | } | ||||
1395 | |||||
1396 | /// Vectorizes arbitrary operation by plain widening. We apply generic type | ||||
1397 | /// widening of all its results and retrieve the vector counterparts for all its | ||||
1398 | /// operands. | ||||
1399 | static Operation *widenOp(Operation *op, VectorizationState &state) { | ||||
1400 | SmallVector<Type, 8> vectorTypes; | ||||
1401 | for (Value result : op->getResults()) | ||||
1402 | vectorTypes.push_back( | ||||
1403 | VectorType::get(state.strategy->vectorSizes, result.getType())); | ||||
1404 | |||||
1405 | SmallVector<Value, 8> vectorOperands; | ||||
1406 | for (Value operand : op->getOperands()) { | ||||
1407 | Value vecOperand = vectorizeOperand(operand, state); | ||||
1408 | if (!vecOperand) { | ||||
1409 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ an operand failed vectorize\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ an operand failed vectorize\n" ; } } while (false); | ||||
1410 | return nullptr; | ||||
1411 | } | ||||
1412 | vectorOperands.push_back(vecOperand); | ||||
1413 | } | ||||
1414 | |||||
1415 | // Create a clone of the op with the proper operands and return types. | ||||
1416 | // TODO: The following assumes there is always an op with a fixed | ||||
1417 | // name that works both in scalar mode and vector mode. | ||||
1418 | // TODO: Is it worth considering an Operation.clone operation which | ||||
1419 | // changes the type so we can promote an Operation with less boilerplate? | ||||
1420 | Operation *vecOp = | ||||
1421 | state.builder.create(op->getLoc(), op->getName().getIdentifier(), | ||||
1422 | vectorOperands, vectorTypes, op->getAttrs()); | ||||
1423 | state.registerOpVectorReplacement(op, vecOp); | ||||
1424 | return vecOp; | ||||
1425 | } | ||||
1426 | |||||
1427 | /// Vectorizes a yield operation by widening its types. The builder's insertion | ||||
1428 | /// point is set after the vectorized parent op to continue vectorizing the | ||||
1429 | /// operations after the parent op. When vectorizing a reduction loop a mask may | ||||
1430 | /// be used to prevent adding garbage values to the accumulator. | ||||
1431 | static Operation *vectorizeAffineYieldOp(AffineYieldOp yieldOp, | ||||
1432 | VectorizationState &state) { | ||||
1433 | Operation *newYieldOp = widenOp(yieldOp, state); | ||||
| |||||
1434 | Operation *newParentOp = state.builder.getInsertionBlock()->getParentOp(); | ||||
1435 | |||||
1436 | // If there is a mask for this loop then we must prevent garbage values from | ||||
1437 | // being added to the accumulator by inserting `select` operations, for | ||||
1438 | // example: | ||||
1439 | // | ||||
1440 | // %val_masked = select %mask, %val, %neutralCst : vector<128xi1>, | ||||
1441 | // vector<128xf32> | ||||
1442 | // %res = arith.addf %acc, %val_masked : vector<128xf32> | ||||
1443 | // affine.yield %res : vector<128xf32> | ||||
1444 | // | ||||
1445 | if (Value mask = state.vecLoopToMask.lookup(newParentOp)) { | ||||
1446 | state.builder.setInsertionPoint(newYieldOp); | ||||
1447 | for (unsigned i = 0; i < newYieldOp->getNumOperands(); ++i) { | ||||
1448 | SmallVector<Operation *> combinerOps; | ||||
1449 | Value reducedVal = matchReduction( | ||||
1450 | cast<AffineForOp>(newParentOp).getRegionIterArgs(), i, combinerOps); | ||||
1451 | assert(reducedVal && "expect non-null value for parallel reduction loop")(static_cast <bool> (reducedVal && "expect non-null value for parallel reduction loop" ) ? void (0) : __assert_fail ("reducedVal && \"expect non-null value for parallel reduction loop\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1451 , __extension__ __PRETTY_FUNCTION__)); | ||||
1452 | assert(combinerOps.size() == 1 && "expect only one combiner op")(static_cast <bool> (combinerOps.size() == 1 && "expect only one combiner op") ? void (0) : __assert_fail ("combinerOps.size() == 1 && \"expect only one combiner op\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1452 , __extension__ __PRETTY_FUNCTION__)); | ||||
1453 | // IterOperands are neutral element vectors. | ||||
1454 | Value neutralVal = cast<AffineForOp>(newParentOp).getIterOperands()[i]; | ||||
1455 | state.builder.setInsertionPoint(combinerOps.back()); | ||||
1456 | Value maskedReducedVal = state.builder.create<arith::SelectOp>( | ||||
1457 | reducedVal.getLoc(), mask, reducedVal, neutralVal); | ||||
1458 | LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ masking an input to a binary op that" "produces value for a yield Op: " << maskedReducedVal; } } while (false) | ||||
1459 | dbgs() << "\n[early-vect]+++++ masking an input to a binary op that"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ masking an input to a binary op that" "produces value for a yield Op: " << maskedReducedVal; } } while (false) | ||||
1460 | "produces value for a yield Op: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ masking an input to a binary op that" "produces value for a yield Op: " << maskedReducedVal; } } while (false) | ||||
1461 | << maskedReducedVal)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ masking an input to a binary op that" "produces value for a yield Op: " << maskedReducedVal; } } while (false); | ||||
1462 | combinerOps.back()->replaceUsesOfWith(reducedVal, maskedReducedVal); | ||||
1463 | } | ||||
1464 | } | ||||
1465 | |||||
1466 | state.builder.setInsertionPointAfter(newParentOp); | ||||
1467 | return newYieldOp; | ||||
1468 | } | ||||
1469 | |||||
1470 | /// Encodes Operation-specific behavior for vectorization. In general we | ||||
1471 | /// assume that all operands of an op must be vectorized but this is not | ||||
1472 | /// always true. In the future, it would be nice to have a trait that | ||||
1473 | /// describes how a particular operation vectorizes. For now we implement the | ||||
1474 | /// case distinction here. Returns a vectorized form of an operation or | ||||
1475 | /// nullptr if vectorization fails. | ||||
1476 | // TODO: consider adding a trait to Op to describe how it gets vectorized. | ||||
1477 | // Maybe some Ops are not vectorizable or require some tricky logic, we cannot | ||||
1478 | // do one-off logic here; ideally it would be TableGen'd. | ||||
1479 | static Operation *vectorizeOneOperation(Operation *op, | ||||
1480 | VectorizationState &state) { | ||||
1481 | // Sanity checks. | ||||
1482 | assert(!isa<vector::TransferReadOp>(op) &&(static_cast <bool> (!isa<vector::TransferReadOp> (op) && "vector.transfer_read cannot be further vectorized" ) ? void (0) : __assert_fail ("!isa<vector::TransferReadOp>(op) && \"vector.transfer_read cannot be further vectorized\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1483 , __extension__ __PRETTY_FUNCTION__)) | ||||
1483 | "vector.transfer_read cannot be further vectorized")(static_cast <bool> (!isa<vector::TransferReadOp> (op) && "vector.transfer_read cannot be further vectorized" ) ? void (0) : __assert_fail ("!isa<vector::TransferReadOp>(op) && \"vector.transfer_read cannot be further vectorized\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1483 , __extension__ __PRETTY_FUNCTION__)); | ||||
1484 | assert(!isa<vector::TransferWriteOp>(op) &&(static_cast <bool> (!isa<vector::TransferWriteOp> (op) && "vector.transfer_write cannot be further vectorized" ) ? void (0) : __assert_fail ("!isa<vector::TransferWriteOp>(op) && \"vector.transfer_write cannot be further vectorized\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1485 , __extension__ __PRETTY_FUNCTION__)) | ||||
1485 | "vector.transfer_write cannot be further vectorized")(static_cast <bool> (!isa<vector::TransferWriteOp> (op) && "vector.transfer_write cannot be further vectorized" ) ? void (0) : __assert_fail ("!isa<vector::TransferWriteOp>(op) && \"vector.transfer_write cannot be further vectorized\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1485 , __extension__ __PRETTY_FUNCTION__)); | ||||
1486 | |||||
1487 | if (auto loadOp = dyn_cast<AffineLoadOp>(op)) | ||||
1488 | return vectorizeAffineLoad(loadOp, state); | ||||
1489 | if (auto storeOp = dyn_cast<AffineStoreOp>(op)) | ||||
1490 | return vectorizeAffineStore(storeOp, state); | ||||
1491 | if (auto forOp = dyn_cast<AffineForOp>(op)) | ||||
1492 | return vectorizeAffineForOp(forOp, state); | ||||
1493 | if (auto yieldOp = dyn_cast<AffineYieldOp>(op)) | ||||
1494 | return vectorizeAffineYieldOp(yieldOp, state); | ||||
1495 | if (auto constant = dyn_cast<arith::ConstantOp>(op)) | ||||
1496 | return vectorizeConstant(constant, state); | ||||
1497 | |||||
1498 | // Other ops with regions are not supported. | ||||
1499 | if (op->getNumRegions() != 0) | ||||
1500 | return nullptr; | ||||
1501 | |||||
1502 | return widenOp(op, state); | ||||
1503 | } | ||||
1504 | |||||
1505 | /// Recursive implementation to convert all the nested loops in 'match' to a 2D | ||||
1506 | /// vector container that preserves the relative nesting level of each loop with | ||||
1507 | /// respect to the others in 'match'. 'currentLevel' is the nesting level that | ||||
1508 | /// will be assigned to the loop in the current 'match'. | ||||
1509 | static void | ||||
1510 | getMatchedAffineLoopsRec(NestedMatch match, unsigned currentLevel, | ||||
1511 | std::vector<SmallVector<AffineForOp, 2>> &loops) { | ||||
1512 | // Add a new empty level to the output if it doesn't exist already. | ||||
1513 | assert(currentLevel <= loops.size() && "Unexpected currentLevel")(static_cast <bool> (currentLevel <= loops.size() && "Unexpected currentLevel") ? void (0) : __assert_fail ("currentLevel <= loops.size() && \"Unexpected currentLevel\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1513 , __extension__ __PRETTY_FUNCTION__)); | ||||
1514 | if (currentLevel == loops.size()) | ||||
1515 | loops.emplace_back(); | ||||
1516 | |||||
1517 | // Add current match and recursively visit its children. | ||||
1518 | loops[currentLevel].push_back(cast<AffineForOp>(match.getMatchedOperation())); | ||||
1519 | for (auto childMatch : match.getMatchedChildren()) { | ||||
1520 | getMatchedAffineLoopsRec(childMatch, currentLevel + 1, loops); | ||||
1521 | } | ||||
1522 | } | ||||
1523 | |||||
1524 | /// Converts all the nested loops in 'match' to a 2D vector container that | ||||
1525 | /// preserves the relative nesting level of each loop with respect to the others | ||||
1526 | /// in 'match'. This means that every loop in 'loops[i]' will have a parent loop | ||||
1527 | /// in 'loops[i-1]'. A loop in 'loops[i]' may or may not have a child loop in | ||||
1528 | /// 'loops[i+1]'. | ||||
1529 | static void | ||||
1530 | getMatchedAffineLoops(NestedMatch match, | ||||
1531 | std::vector<SmallVector<AffineForOp, 2>> &loops) { | ||||
1532 | getMatchedAffineLoopsRec(match, /*currLoopDepth=*/0, loops); | ||||
1533 | } | ||||
1534 | |||||
1535 | /// Internal implementation to vectorize affine loops from a single loop nest | ||||
1536 | /// using an n-D vectorization strategy. | ||||
1537 | static LogicalResult | ||||
1538 | vectorizeLoopNest(std::vector<SmallVector<AffineForOp, 2>> &loops, | ||||
1539 | const VectorizationStrategy &strategy) { | ||||
1540 | assert(loops[0].size() == 1 && "Expected single root loop")(static_cast <bool> (loops[0].size() == 1 && "Expected single root loop" ) ? void (0) : __assert_fail ("loops[0].size() == 1 && \"Expected single root loop\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1540 , __extension__ __PRETTY_FUNCTION__)); | ||||
1541 | AffineForOp rootLoop = loops[0][0]; | ||||
1542 | VectorizationState state(rootLoop.getContext()); | ||||
1543 | state.builder.setInsertionPointAfter(rootLoop); | ||||
1544 | state.strategy = &strategy; | ||||
1545 | |||||
1546 | // Since patterns are recursive, they can very well intersect. | ||||
1547 | // Since we do not want a fully greedy strategy in general, we decouple | ||||
1548 | // pattern matching, from profitability analysis, from application. | ||||
1549 | // As a consequence we must check that each root pattern is still | ||||
1550 | // vectorizable. If a pattern is not vectorizable anymore, we just skip it. | ||||
1551 | // TODO: implement a non-greedy profitability analysis that keeps only | ||||
1552 | // non-intersecting patterns. | ||||
1553 | if (!isVectorizableLoopBody(rootLoop, vectorTransferPattern())) { | ||||
1554 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ loop is not vectorizable")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ loop is not vectorizable" ; } } while (false); | ||||
1555 | return failure(); | ||||
1556 | } | ||||
1557 | |||||
1558 | ////////////////////////////////////////////////////////////////////////////// | ||||
1559 | // Vectorize the scalar loop nest following a topological order. A new vector | ||||
1560 | // loop nest with the vectorized operations is created along the process. If | ||||
1561 | // vectorization succeeds, the scalar loop nest is erased. If vectorization | ||||
1562 | // fails, the vector loop nest is erased and the scalar loop nest is not | ||||
1563 | // modified. | ||||
1564 | ////////////////////////////////////////////////////////////////////////////// | ||||
1565 | |||||
1566 | auto opVecResult = rootLoop.walk<WalkOrder::PreOrder>([&](Operation *op) { | ||||
1567 | LLVM_DEBUG(dbgs() << "[early-vect]+++++ Vectorizing: " << *op)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "[early-vect]+++++ Vectorizing: " << *op; } } while (false); | ||||
1568 | Operation *vectorOp = vectorizeOneOperation(op, state); | ||||
1569 | if (!vectorOp) { | ||||
1570 | LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "[early-vect]+++++ failed vectorizing the operation: " << *op << "\n"; } } while (false) | ||||
1571 | dbgs() << "[early-vect]+++++ failed vectorizing the operation: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "[early-vect]+++++ failed vectorizing the operation: " << *op << "\n"; } } while (false) | ||||
1572 | << *op << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "[early-vect]+++++ failed vectorizing the operation: " << *op << "\n"; } } while (false); | ||||
1573 | return WalkResult::interrupt(); | ||||
1574 | } | ||||
1575 | |||||
1576 | return WalkResult::advance(); | ||||
1577 | }); | ||||
1578 | |||||
1579 | if (opVecResult.wasInterrupted()) { | ||||
1580 | LLVM_DEBUG(dbgs() << "[early-vect]+++++ failed vectorization for: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "[early-vect]+++++ failed vectorization for: " << rootLoop << "\n"; } } while (false) | ||||
1581 | << rootLoop << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "[early-vect]+++++ failed vectorization for: " << rootLoop << "\n"; } } while (false); | ||||
1582 | // Erase vector loop nest if it was created. | ||||
1583 | auto vecRootLoopIt = state.opVectorReplacement.find(rootLoop); | ||||
1584 | if (vecRootLoopIt != state.opVectorReplacement.end()) | ||||
1585 | eraseLoopNest(cast<AffineForOp>(vecRootLoopIt->second)); | ||||
1586 | |||||
1587 | return failure(); | ||||
1588 | } | ||||
1589 | |||||
1590 | // Replace results of reduction loops with the scalar values computed using | ||||
1591 | // `vector.reduce` or similar ops. | ||||
1592 | for (auto resPair : state.loopResultScalarReplacement) | ||||
1593 | resPair.first.replaceAllUsesWith(resPair.second); | ||||
1594 | |||||
1595 | assert(state.opVectorReplacement.count(rootLoop) == 1 &&(static_cast <bool> (state.opVectorReplacement.count(rootLoop ) == 1 && "Expected vector replacement for loop nest" ) ? void (0) : __assert_fail ("state.opVectorReplacement.count(rootLoop) == 1 && \"Expected vector replacement for loop nest\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1596 , __extension__ __PRETTY_FUNCTION__)) | ||||
1596 | "Expected vector replacement for loop nest")(static_cast <bool> (state.opVectorReplacement.count(rootLoop ) == 1 && "Expected vector replacement for loop nest" ) ? void (0) : __assert_fail ("state.opVectorReplacement.count(rootLoop) == 1 && \"Expected vector replacement for loop nest\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1596 , __extension__ __PRETTY_FUNCTION__)); | ||||
1597 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ success vectorizing pattern")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ success vectorizing pattern" ; } } while (false); | ||||
1598 | LLVM_DEBUG(dbgs() << "\n[early-vect]+++++ vectorization result:\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ vectorization result:\n" << *state.opVectorReplacement[rootLoop]; } } while (false ) | ||||
1599 | << *state.opVectorReplacement[rootLoop])do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect]+++++ vectorization result:\n" << *state.opVectorReplacement[rootLoop]; } } while (false ); | ||||
1600 | |||||
1601 | // Finish this vectorization pattern. | ||||
1602 | state.finishVectorizationPattern(rootLoop); | ||||
1603 | return success(); | ||||
1604 | } | ||||
1605 | |||||
1606 | /// Extracts the matched loops and vectorizes them following a topological | ||||
1607 | /// order. A new vector loop nest will be created if vectorization succeeds. The | ||||
1608 | /// original loop nest won't be modified in any case. | ||||
1609 | static LogicalResult vectorizeRootMatch(NestedMatch m, | ||||
1610 | const VectorizationStrategy &strategy) { | ||||
1611 | std::vector<SmallVector<AffineForOp, 2>> loopsToVectorize; | ||||
1612 | getMatchedAffineLoops(m, loopsToVectorize); | ||||
1613 | return vectorizeLoopNest(loopsToVectorize, strategy); | ||||
1614 | } | ||||
1615 | |||||
1616 | /// Traverses all the loop matches and classifies them into intersection | ||||
1617 | /// buckets. Two matches intersect if any of them encloses the other one. A | ||||
1618 | /// match intersects with a bucket if the match intersects with the root | ||||
1619 | /// (outermost) loop in that bucket. | ||||
1620 | static void computeIntersectionBuckets( | ||||
1621 | ArrayRef<NestedMatch> matches, | ||||
1622 | std::vector<SmallVector<NestedMatch, 8>> &intersectionBuckets) { | ||||
1623 | assert(intersectionBuckets.empty() && "Expected empty output")(static_cast <bool> (intersectionBuckets.empty() && "Expected empty output") ? void (0) : __assert_fail ("intersectionBuckets.empty() && \"Expected empty output\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1623 , __extension__ __PRETTY_FUNCTION__)); | ||||
1624 | // Keeps track of the root (outermost) loop of each bucket. | ||||
1625 | SmallVector<AffineForOp, 8> bucketRoots; | ||||
1626 | |||||
1627 | for (const NestedMatch &match : matches) { | ||||
1628 | AffineForOp matchRoot = cast<AffineForOp>(match.getMatchedOperation()); | ||||
1629 | bool intersects = false; | ||||
1630 | for (int i = 0, end = intersectionBuckets.size(); i < end; ++i) { | ||||
1631 | AffineForOp bucketRoot = bucketRoots[i]; | ||||
1632 | // Add match to the bucket if the bucket root encloses the match root. | ||||
1633 | if (bucketRoot->isAncestor(matchRoot)) { | ||||
1634 | intersectionBuckets[i].push_back(match); | ||||
1635 | intersects = true; | ||||
1636 | break; | ||||
1637 | } | ||||
1638 | // Add match to the bucket if the match root encloses the bucket root. The | ||||
1639 | // match root becomes the new bucket root. | ||||
1640 | if (matchRoot->isAncestor(bucketRoot)) { | ||||
1641 | bucketRoots[i] = matchRoot; | ||||
1642 | intersectionBuckets[i].push_back(match); | ||||
1643 | intersects = true; | ||||
1644 | break; | ||||
1645 | } | ||||
1646 | } | ||||
1647 | |||||
1648 | // Match doesn't intersect with any existing bucket. Create a new bucket for | ||||
1649 | // it. | ||||
1650 | if (!intersects) { | ||||
1651 | bucketRoots.push_back(matchRoot); | ||||
1652 | intersectionBuckets.emplace_back(); | ||||
1653 | intersectionBuckets.back().push_back(match); | ||||
1654 | } | ||||
1655 | } | ||||
1656 | } | ||||
1657 | |||||
1658 | /// Internal implementation to vectorize affine loops in 'loops' using the n-D | ||||
1659 | /// vectorization factors in 'vectorSizes'. By default, each vectorization | ||||
1660 | /// factor is applied inner-to-outer to the loops of each loop nest. | ||||
1661 | /// 'fastestVaryingPattern' can be optionally used to provide a different loop | ||||
1662 | /// vectorization order. `reductionLoops` can be provided to specify loops which | ||||
1663 | /// can be vectorized along the reduction dimension. | ||||
1664 | static void vectorizeLoops(Operation *parentOp, DenseSet<Operation *> &loops, | ||||
1665 | ArrayRef<int64_t> vectorSizes, | ||||
1666 | ArrayRef<int64_t> fastestVaryingPattern, | ||||
1667 | const ReductionLoopMap &reductionLoops) { | ||||
1668 | assert((reductionLoops.empty() || vectorSizes.size() == 1) &&(static_cast <bool> ((reductionLoops.empty() || vectorSizes .size() == 1) && "Vectorizing reductions is supported only for 1-D vectors" ) ? void (0) : __assert_fail ("(reductionLoops.empty() || vectorSizes.size() == 1) && \"Vectorizing reductions is supported only for 1-D vectors\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1669 , __extension__ __PRETTY_FUNCTION__)) | ||||
1669 | "Vectorizing reductions is supported only for 1-D vectors")(static_cast <bool> ((reductionLoops.empty() || vectorSizes .size() == 1) && "Vectorizing reductions is supported only for 1-D vectors" ) ? void (0) : __assert_fail ("(reductionLoops.empty() || vectorSizes.size() == 1) && \"Vectorizing reductions is supported only for 1-D vectors\"" , "mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp", 1669 , __extension__ __PRETTY_FUNCTION__)); | ||||
1670 | |||||
1671 | // Compute 1-D, 2-D or 3-D loop pattern to be matched on the target loops. | ||||
1672 | std::optional<NestedPattern> pattern = | ||||
1673 | makePattern(loops, vectorSizes.size(), fastestVaryingPattern); | ||||
1674 | if (!pattern) { | ||||
1675 | LLVM_DEBUG(dbgs() << "\n[early-vect] pattern couldn't be computed\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect] pattern couldn't be computed\n" ; } } while (false); | ||||
1676 | return; | ||||
1677 | } | ||||
1678 | |||||
1679 | LLVM_DEBUG(dbgs() << "\n******************************************")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n******************************************" ; } } while (false); | ||||
1680 | LLVM_DEBUG(dbgs() << "\n******************************************")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n******************************************" ; } } while (false); | ||||
1681 | LLVM_DEBUG(dbgs() << "\n[early-vect] new pattern on parent op\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n[early-vect] new pattern on parent op\n" ; } } while (false); | ||||
1682 | LLVM_DEBUG(dbgs() << *parentOp << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << *parentOp << "\n"; } } while (false); | ||||
1683 | |||||
1684 | unsigned patternDepth = pattern->getDepth(); | ||||
1685 | |||||
1686 | // Compute all the pattern matches and classify them into buckets of | ||||
1687 | // intersecting matches. | ||||
1688 | SmallVector<NestedMatch, 32> allMatches; | ||||
1689 | pattern->match(parentOp, &allMatches); | ||||
1690 | std::vector<SmallVector<NestedMatch, 8>> intersectionBuckets; | ||||
1691 | computeIntersectionBuckets(allMatches, intersectionBuckets); | ||||
1692 | |||||
1693 | // Iterate over all buckets and vectorize the matches eagerly. We can only | ||||
1694 | // vectorize one match from each bucket since all the matches within a bucket | ||||
1695 | // intersect. | ||||
1696 | for (auto &intersectingMatches : intersectionBuckets) { | ||||
1697 | for (NestedMatch &match : intersectingMatches) { | ||||
1698 | VectorizationStrategy strategy; | ||||
1699 | // TODO: depending on profitability, elect to reduce the vector size. | ||||
1700 | strategy.vectorSizes.assign(vectorSizes.begin(), vectorSizes.end()); | ||||
1701 | strategy.reductionLoops = reductionLoops; | ||||
1702 | if (failed(analyzeProfitability(match.getMatchedChildren(), 1, | ||||
1703 | patternDepth, &strategy))) { | ||||
1704 | continue; | ||||
1705 | } | ||||
1706 | vectorizeLoopIfProfitable(match.getMatchedOperation(), 0, patternDepth, | ||||
1707 | &strategy); | ||||
1708 | // Vectorize match. Skip the rest of intersecting matches in the bucket if | ||||
1709 | // vectorization succeeded. | ||||
1710 | // TODO: if pattern does not apply, report it; alter the cost/benefit. | ||||
1711 | // TODO: some diagnostics if failure to vectorize occurs. | ||||
1712 | if (succeeded(vectorizeRootMatch(match, strategy))) | ||||
1713 | break; | ||||
1714 | } | ||||
1715 | } | ||||
1716 | |||||
1717 | LLVM_DEBUG(dbgs() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("early-vect")) { dbgs() << "\n"; } } while (false); | ||||
1718 | } | ||||
1719 | |||||
1720 | /// Applies vectorization to the current function by searching over a bunch of | ||||
1721 | /// predetermined patterns. | ||||
1722 | void Vectorize::runOnOperation() { | ||||
1723 | func::FuncOp f = getOperation(); | ||||
1724 | if (!fastestVaryingPattern.empty() && | ||||
1725 | fastestVaryingPattern.size() != vectorSizes.size()) { | ||||
1726 | f.emitRemark("Fastest varying pattern specified with different size than " | ||||
1727 | "the vector size."); | ||||
1728 | return signalPassFailure(); | ||||
1729 | } | ||||
1730 | |||||
1731 | if (vectorizeReductions && vectorSizes.size() != 1) { | ||||
1732 | f.emitError("Vectorizing reductions is supported only for 1-D vectors."); | ||||
1733 | return signalPassFailure(); | ||||
1734 | } | ||||
1735 | |||||
1736 | DenseSet<Operation *> parallelLoops; | ||||
1737 | ReductionLoopMap reductionLoops; | ||||
1738 | |||||
1739 | // If 'vectorize-reduction=true' is provided, we also populate the | ||||
1740 | // `reductionLoops` map. | ||||
1741 | if (vectorizeReductions) { | ||||
1742 | f.walk([¶llelLoops, &reductionLoops](AffineForOp loop) { | ||||
1743 | SmallVector<LoopReduction, 2> reductions; | ||||
1744 | if (isLoopParallel(loop, &reductions)) { | ||||
1745 | parallelLoops.insert(loop); | ||||
1746 | // If it's not a reduction loop, adding it to the map is not necessary. | ||||
1747 | if (!reductions.empty()) | ||||
1748 | reductionLoops[loop] = reductions; | ||||
1749 | } | ||||
1750 | }); | ||||
1751 | } else { | ||||
1752 | f.walk([¶llelLoops](AffineForOp loop) { | ||||
1753 | if (isLoopParallel(loop)) | ||||
1754 | parallelLoops.insert(loop); | ||||
1755 | }); | ||||
1756 | } | ||||
1757 | |||||
1758 | // Thread-safe RAII local context, BumpPtrAllocator freed on exit. | ||||
1759 | NestedPatternContext mlContext; | ||||
1760 | vectorizeLoops(f, parallelLoops, vectorSizes, fastestVaryingPattern, | ||||
1761 | reductionLoops); | ||||
1762 | } | ||||
1763 | |||||
1764 | /// Verify that affine loops in 'loops' meet the nesting criteria expected by | ||||
1765 | /// SuperVectorizer: | ||||
1766 | /// * There must be at least one loop. | ||||
1767 | /// * There must be a single root loop (nesting level 0). | ||||
1768 | /// * Each loop at a given nesting level must be nested in a loop from a | ||||
1769 | /// previous nesting level. | ||||
1770 | static LogicalResult | ||||
1771 | verifyLoopNesting(const std::vector<SmallVector<AffineForOp, 2>> &loops) { | ||||
1772 | // Expected at least one loop. | ||||
1773 | if (loops.empty()) | ||||
1774 | return failure(); | ||||
1775 | |||||
1776 | // Expected only one root loop. | ||||
1777 | if (loops[0].size() != 1) | ||||
1778 | return failure(); | ||||
1779 | |||||
1780 | // Traverse loops outer-to-inner to check some invariants. | ||||
1781 | for (int i = 1, end = loops.size(); i < end; ++i) { | ||||
1782 | for (AffineForOp loop : loops[i]) { | ||||
1783 | // Check that each loop at this level is nested in one of the loops from | ||||
1784 | // the previous level. | ||||
1785 | if (none_of(loops[i - 1], [&](AffineForOp maybeParent) { | ||||
1786 | return maybeParent->isProperAncestor(loop); | ||||
1787 | })) | ||||
1788 | return failure(); | ||||
1789 | |||||
1790 | // Check that each loop at this level is not nested in another loop from | ||||
1791 | // this level. | ||||
1792 | for (AffineForOp sibling : loops[i]) { | ||||
1793 | if (sibling->isProperAncestor(loop)) | ||||
1794 | return failure(); | ||||
1795 | } | ||||
1796 | } | ||||
1797 | } | ||||
1798 | |||||
1799 | return success(); | ||||
1800 | } | ||||
1801 | |||||
1802 | |||||
1803 | /// External utility to vectorize affine loops in 'loops' using the n-D | ||||
1804 | /// vectorization factors in 'vectorSizes'. By default, each vectorization | ||||
1805 | /// factor is applied inner-to-outer to the loops of each loop nest. | ||||
1806 | /// 'fastestVaryingPattern' can be optionally used to provide a different loop | ||||
1807 | /// vectorization order. | ||||
1808 | /// If `reductionLoops` is not empty, the given reduction loops may be | ||||
1809 | /// vectorized along the reduction dimension. | ||||
1810 | /// TODO: Vectorizing reductions is supported only for 1-D vectorization. | ||||
1811 | void mlir::affine::vectorizeAffineLoops( | ||||
1812 | Operation *parentOp, DenseSet<Operation *> &loops, | ||||
1813 | ArrayRef<int64_t> vectorSizes, ArrayRef<int64_t> fastestVaryingPattern, | ||||
1814 | const ReductionLoopMap &reductionLoops) { | ||||
1815 | // Thread-safe RAII local context, BumpPtrAllocator freed on exit. | ||||
1816 | NestedPatternContext mlContext; | ||||
1817 | vectorizeLoops(parentOp, loops, vectorSizes, fastestVaryingPattern, | ||||
1818 | reductionLoops); | ||||
1819 | } | ||||
1820 | |||||
1821 | /// External utility to vectorize affine loops from a single loop nest using an | ||||
1822 | /// n-D vectorization strategy (see doc in VectorizationStrategy definition). | ||||
1823 | /// Loops are provided in a 2D vector container. The first dimension represents | ||||
1824 | /// the nesting level relative to the loops to be vectorized. The second | ||||
1825 | /// dimension contains the loops. This means that: | ||||
1826 | /// a) every loop in 'loops[i]' must have a parent loop in 'loops[i-1]', | ||||
1827 | /// b) a loop in 'loops[i]' may or may not have a child loop in 'loops[i+1]'. | ||||
1828 | /// | ||||
1829 | /// For example, for the following loop nest: | ||||
1830 | /// | ||||
1831 | /// func @vec2d(%in0: memref<64x128x512xf32>, %in1: memref<64x128x128xf32>, | ||||
1832 | /// %out0: memref<64x128x512xf32>, | ||||
1833 | /// %out1: memref<64x128x128xf32>) { | ||||
1834 | /// affine.for %i0 = 0 to 64 { | ||||
1835 | /// affine.for %i1 = 0 to 128 { | ||||
1836 | /// affine.for %i2 = 0 to 512 { | ||||
1837 | /// %ld = affine.load %in0[%i0, %i1, %i2] : memref<64x128x512xf32> | ||||
1838 | /// affine.store %ld, %out0[%i0, %i1, %i2] : memref<64x128x512xf32> | ||||
1839 | /// } | ||||
1840 | /// affine.for %i3 = 0 to 128 { | ||||
1841 | /// %ld = affine.load %in1[%i0, %i1, %i3] : memref<64x128x128xf32> | ||||
1842 | /// affine.store %ld, %out1[%i0, %i1, %i3] : memref<64x128x128xf32> | ||||
1843 | /// } | ||||
1844 | /// } | ||||
1845 | /// } | ||||
1846 | /// return | ||||
1847 | /// } | ||||
1848 | /// | ||||
1849 | /// loops = {{%i0}, {%i2, %i3}}, to vectorize the outermost and the two | ||||
1850 | /// innermost loops; | ||||
1851 | /// loops = {{%i1}, {%i2, %i3}}, to vectorize the middle and the two innermost | ||||
1852 | /// loops; | ||||
1853 | /// loops = {{%i2}}, to vectorize only the first innermost loop; | ||||
1854 | /// loops = {{%i3}}, to vectorize only the second innermost loop; | ||||
1855 | /// loops = {{%i1}}, to vectorize only the middle loop. | ||||
1856 | LogicalResult mlir::affine::vectorizeAffineLoopNest( | ||||
1857 | std::vector<SmallVector<AffineForOp, 2>> &loops, | ||||
1858 | const VectorizationStrategy &strategy) { | ||||
1859 | // Thread-safe RAII local context, BumpPtrAllocator freed on exit. | ||||
1860 | NestedPatternContext mlContext; | ||||
1861 | if (failed(verifyLoopNesting(loops))) | ||||
1862 | return failure(); | ||||
1863 | return vectorizeLoopNest(loops, strategy); | ||||
1864 | } |
1 | //===- Value.h - Base of the SSA Value hierarchy ----------------*- 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 defines generic Value type and manipulation utilities. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef MLIR_IR_VALUE_H |
14 | #define MLIR_IR_VALUE_H |
15 | |
16 | #include "mlir/IR/Types.h" |
17 | #include "mlir/IR/UseDefLists.h" |
18 | #include "mlir/Support/LLVM.h" |
19 | #include "llvm/Support/PointerLikeTypeTraits.h" |
20 | |
21 | namespace mlir { |
22 | class AsmState; |
23 | class Block; |
24 | class BlockArgument; |
25 | class Operation; |
26 | class OpOperand; |
27 | class OpPrintingFlags; |
28 | class OpResult; |
29 | class Region; |
30 | class Value; |
31 | |
32 | //===----------------------------------------------------------------------===// |
33 | // Value |
34 | //===----------------------------------------------------------------------===// |
35 | |
36 | namespace detail { |
37 | |
38 | /// The base class for all derived Value classes. It contains all of the |
39 | /// components that are shared across Value classes. |
40 | class alignas(8) ValueImpl : public IRObjectWithUseList<OpOperand> { |
41 | public: |
42 | /// The enumeration represents the various different kinds of values the |
43 | /// internal representation may take. We use all of the bits from Type that we |
44 | /// can to store indices inline. |
45 | enum class Kind { |
46 | /// The first N kinds are all inline operation results. An inline operation |
47 | /// result means that the kind represents the result number. This removes |
48 | /// the need to store an additional index value. The derived class here is |
49 | /// an `OpResultImpl`. |
50 | InlineOpResult = 0, |
51 | |
52 | /// The next kind represents a 'out-of-line' operation result. This is for |
53 | /// results with numbers larger than we can represent inline. The derived |
54 | /// class here is an `OpResultImpl`. |
55 | OutOfLineOpResult = 6, |
56 | |
57 | /// The last kind represents a block argument. The derived class here is an |
58 | /// `BlockArgumentImpl`. |
59 | BlockArgument = 7 |
60 | }; |
61 | |
62 | /// Return the type of this value. |
63 | Type getType() const { return typeAndKind.getPointer(); } |
64 | |
65 | /// Set the type of this value. |
66 | void setType(Type type) { return typeAndKind.setPointer(type); } |
67 | |
68 | /// Return the kind of this value. |
69 | Kind getKind() const { return typeAndKind.getInt(); } |
70 | |
71 | protected: |
72 | ValueImpl(Type type, Kind kind) : typeAndKind(type, kind) {} |
73 | |
74 | /// Expose a few methods explicitly for the debugger to call for |
75 | /// visualization. |
76 | #ifndef NDEBUG |
77 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) Type debug_getType() const { return getType(); } |
78 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) Kind debug_getKind() const { return getKind(); } |
79 | |
80 | #endif |
81 | |
82 | /// The type of this result and the kind. |
83 | llvm::PointerIntPair<Type, 3, Kind> typeAndKind; |
84 | }; |
85 | } // namespace detail |
86 | |
87 | /// This class represents an instance of an SSA value in the MLIR system, |
88 | /// representing a computable value that has a type and a set of users. An SSA |
89 | /// value is either a BlockArgument or the result of an operation. Note: This |
90 | /// class has value-type semantics and is just a simple wrapper around a |
91 | /// ValueImpl that is either owner by a block(in the case of a BlockArgument) or |
92 | /// an Operation(in the case of an OpResult). |
93 | class Value { |
94 | public: |
95 | constexpr Value(detail::ValueImpl *impl = nullptr) : impl(impl) {} |
96 | |
97 | template <typename U> |
98 | bool isa() const { |
99 | return llvm::isa<U>(*this); |
100 | } |
101 | |
102 | template <typename U> |
103 | U dyn_cast() const { |
104 | return llvm::dyn_cast<U>(*this); |
105 | } |
106 | |
107 | template <typename U> |
108 | U dyn_cast_or_null() const { |
109 | return llvm::dyn_cast_if_present<U>(*this); |
110 | } |
111 | |
112 | template <typename U> |
113 | U cast() const { |
114 | return llvm::cast<U>(*this); |
115 | } |
116 | |
117 | explicit operator bool() const { return impl; } |
118 | bool operator==(const Value &other) const { return impl == other.impl; } |
119 | bool operator!=(const Value &other) const { return !(*this == other); } |
120 | |
121 | /// Return the type of this value. |
122 | Type getType() const { return impl->getType(); } |
123 | |
124 | /// Utility to get the associated MLIRContext that this value is defined in. |
125 | MLIRContext *getContext() const { return getType().getContext(); } |
126 | |
127 | /// Mutate the type of this Value to be of the specified type. |
128 | /// |
129 | /// Note that this is an extremely dangerous operation which can create |
130 | /// completely invalid IR very easily. It is strongly recommended that you |
131 | /// recreate IR objects with the right types instead of mutating them in |
132 | /// place. |
133 | void setType(Type newType) { impl->setType(newType); } |
134 | |
135 | /// If this value is the result of an operation, return the operation that |
136 | /// defines it. |
137 | Operation *getDefiningOp() const; |
138 | |
139 | /// If this value is the result of an operation of type OpTy, return the |
140 | /// operation that defines it. |
141 | template <typename OpTy> |
142 | OpTy getDefiningOp() const { |
143 | return llvm::dyn_cast_or_null<OpTy>(getDefiningOp()); |
144 | } |
145 | |
146 | /// Return the location of this value. |
147 | Location getLoc() const; |
148 | void setLoc(Location loc); |
149 | |
150 | /// Return the Region in which this Value is defined. |
151 | Region *getParentRegion(); |
152 | |
153 | /// Return the Block in which this Value is defined. |
154 | Block *getParentBlock(); |
155 | |
156 | //===--------------------------------------------------------------------===// |
157 | // UseLists |
158 | //===--------------------------------------------------------------------===// |
159 | |
160 | /// Drop all uses of this object from their respective owners. |
161 | void dropAllUses() const { return impl->dropAllUses(); } |
162 | |
163 | /// Replace all uses of 'this' value with the new value, updating anything in |
164 | /// the IR that uses 'this' to use the other value instead. When this returns |
165 | /// there are zero uses of 'this'. |
166 | void replaceAllUsesWith(Value newValue) const { |
167 | impl->replaceAllUsesWith(newValue); |
168 | } |
169 | |
170 | /// Replace all uses of 'this' value with 'newValue', updating anything in the |
171 | /// IR that uses 'this' to use the other value instead except if the user is |
172 | /// listed in 'exceptions' . |
173 | void |
174 | replaceAllUsesExcept(Value newValue, |
175 | const SmallPtrSetImpl<Operation *> &exceptions) const; |
176 | |
177 | /// Replace all uses of 'this' value with 'newValue', updating anything in the |
178 | /// IR that uses 'this' to use the other value instead except if the user is |
179 | /// 'exceptedUser'. |
180 | void replaceAllUsesExcept(Value newValue, Operation *exceptedUser) const; |
181 | |
182 | /// Replace all uses of 'this' value with 'newValue' if the given callback |
183 | /// returns true. |
184 | void replaceUsesWithIf(Value newValue, |
185 | function_ref<bool(OpOperand &)> shouldReplace); |
186 | |
187 | /// Returns true if the value is used outside of the given block. |
188 | bool isUsedOutsideOfBlock(Block *block); |
189 | |
190 | //===--------------------------------------------------------------------===// |
191 | // Uses |
192 | |
193 | /// This class implements an iterator over the uses of a value. |
194 | using use_iterator = ValueUseIterator<OpOperand>; |
195 | using use_range = iterator_range<use_iterator>; |
196 | |
197 | use_iterator use_begin() const { return impl->use_begin(); } |
198 | use_iterator use_end() const { return use_iterator(); } |
199 | |
200 | /// Returns a range of all uses, which is useful for iterating over all uses. |
201 | use_range getUses() const { return {use_begin(), use_end()}; } |
202 | |
203 | /// Returns true if this value has exactly one use. |
204 | bool hasOneUse() const { return impl->hasOneUse(); } |
205 | |
206 | /// Returns true if this value has no uses. |
207 | bool use_empty() const { return impl->use_empty(); } |
208 | |
209 | //===--------------------------------------------------------------------===// |
210 | // Users |
211 | |
212 | using user_iterator = ValueUserIterator<use_iterator, OpOperand>; |
213 | using user_range = iterator_range<user_iterator>; |
214 | |
215 | user_iterator user_begin() const { return use_begin(); } |
216 | user_iterator user_end() const { return use_end(); } |
217 | user_range getUsers() const { return {user_begin(), user_end()}; } |
218 | |
219 | //===--------------------------------------------------------------------===// |
220 | // Utilities |
221 | |
222 | void print(raw_ostream &os); |
223 | void print(raw_ostream &os, const OpPrintingFlags &flags); |
224 | void print(raw_ostream &os, AsmState &state); |
225 | void dump(); |
226 | |
227 | /// Print this value as if it were an operand. |
228 | void printAsOperand(raw_ostream &os, AsmState &state); |
229 | void printAsOperand(raw_ostream &os, const OpPrintingFlags &flags); |
230 | |
231 | /// Methods for supporting PointerLikeTypeTraits. |
232 | void *getAsOpaquePointer() const { return impl; } |
233 | static Value getFromOpaquePointer(const void *pointer) { |
234 | return reinterpret_cast<detail::ValueImpl *>(const_cast<void *>(pointer)); |
235 | } |
236 | detail::ValueImpl *getImpl() const { return impl; } |
237 | |
238 | friend ::llvm::hash_code hash_value(Value arg); |
239 | |
240 | protected: |
241 | /// A pointer to the internal implementation of the value. |
242 | detail::ValueImpl *impl; |
243 | }; |
244 | |
245 | inline raw_ostream &operator<<(raw_ostream &os, Value value) { |
246 | value.print(os); |
247 | return os; |
248 | } |
249 | |
250 | //===----------------------------------------------------------------------===// |
251 | // OpOperand |
252 | //===----------------------------------------------------------------------===// |
253 | |
254 | /// This class represents an operand of an operation. Instances of this class |
255 | /// contain a reference to a specific `Value`. |
256 | class OpOperand : public IROperand<OpOperand, Value> { |
257 | public: |
258 | /// Provide the use list that is attached to the given value. |
259 | static IRObjectWithUseList<OpOperand> *getUseList(Value value) { |
260 | return value.getImpl(); |
261 | } |
262 | |
263 | /// Return which operand this is in the OpOperand list of the Operation. |
264 | unsigned getOperandNumber(); |
265 | |
266 | private: |
267 | /// Keep the constructor private and accessible to the OperandStorage class |
268 | /// only to avoid hard-to-debug typo/programming mistakes. |
269 | friend class OperandStorage; |
270 | using IROperand<OpOperand, Value>::IROperand; |
271 | }; |
272 | |
273 | //===----------------------------------------------------------------------===// |
274 | // BlockArgument |
275 | //===----------------------------------------------------------------------===// |
276 | |
277 | namespace detail { |
278 | /// The internal implementation of a BlockArgument. |
279 | class BlockArgumentImpl : public ValueImpl { |
280 | public: |
281 | static bool classof(const ValueImpl *value) { |
282 | return value->getKind() == ValueImpl::Kind::BlockArgument; |
283 | } |
284 | |
285 | private: |
286 | BlockArgumentImpl(Type type, Block *owner, int64_t index, Location loc) |
287 | : ValueImpl(type, Kind::BlockArgument), owner(owner), index(index), |
288 | loc(loc) {} |
289 | |
290 | /// The owner of this argument. |
291 | Block *owner; |
292 | |
293 | /// The position in the argument list. |
294 | int64_t index; |
295 | |
296 | /// The source location of this argument. |
297 | Location loc; |
298 | |
299 | /// Allow access to owner and constructor. |
300 | friend BlockArgument; |
301 | }; |
302 | } // namespace detail |
303 | |
304 | /// This class represents an argument of a Block. |
305 | class BlockArgument : public Value { |
306 | public: |
307 | using Value::Value; |
308 | |
309 | static bool classof(Value value) { |
310 | return llvm::isa<detail::BlockArgumentImpl>(value.getImpl()); |
311 | } |
312 | |
313 | /// Returns the block that owns this argument. |
314 | Block *getOwner() const { return getImpl()->owner; } |
315 | |
316 | /// Returns the number of this argument. |
317 | unsigned getArgNumber() const { return getImpl()->index; } |
318 | |
319 | /// Return the location for this argument. |
320 | Location getLoc() const { return getImpl()->loc; } |
321 | void setLoc(Location loc) { getImpl()->loc = loc; } |
322 | |
323 | private: |
324 | /// Allocate a new argument with the given type and owner. |
325 | static BlockArgument create(Type type, Block *owner, int64_t index, |
326 | Location loc) { |
327 | return new detail::BlockArgumentImpl(type, owner, index, loc); |
328 | } |
329 | |
330 | /// Destroy and deallocate this argument. |
331 | void destroy() { delete getImpl(); } |
332 | |
333 | /// Get a raw pointer to the internal implementation. |
334 | detail::BlockArgumentImpl *getImpl() const { |
335 | return reinterpret_cast<detail::BlockArgumentImpl *>(impl); |
336 | } |
337 | |
338 | /// Cache the position in the block argument list. |
339 | void setArgNumber(int64_t index) { getImpl()->index = index; } |
340 | |
341 | /// Allow access to `create`, `destroy` and `setArgNumber`. |
342 | friend Block; |
343 | |
344 | /// Allow access to 'getImpl'. |
345 | friend Value; |
346 | }; |
347 | |
348 | //===----------------------------------------------------------------------===// |
349 | // OpResult |
350 | //===----------------------------------------------------------------------===// |
351 | |
352 | namespace detail { |
353 | /// This class provides the implementation for an operation result. |
354 | class alignas(8) OpResultImpl : public ValueImpl { |
355 | public: |
356 | using ValueImpl::ValueImpl; |
357 | |
358 | static bool classof(const ValueImpl *value) { |
359 | return value->getKind() != ValueImpl::Kind::BlockArgument; |
360 | } |
361 | |
362 | /// Returns the parent operation of this result. |
363 | Operation *getOwner() const; |
364 | |
365 | /// Returns the result number of this op result. |
366 | unsigned getResultNumber() const; |
367 | |
368 | /// Returns the next operation result at `offset` after this result. This |
369 | /// method is useful when indexing the result storage of an operation, given |
370 | /// that there is more than one kind of operation result (with the different |
371 | /// kinds having different sizes) and that operations are stored in reverse |
372 | /// order. |
373 | OpResultImpl *getNextResultAtOffset(intptr_t offset); |
374 | |
375 | /// Returns the maximum number of results that can be stored inline. |
376 | static unsigned getMaxInlineResults() { |
377 | return static_cast<unsigned>(Kind::OutOfLineOpResult); |
378 | } |
379 | }; |
380 | |
381 | /// This class provides the implementation for an operation result whose index |
382 | /// can be represented "inline" in the underlying ValueImpl. |
383 | struct InlineOpResult : public OpResultImpl { |
384 | public: |
385 | InlineOpResult(Type type, unsigned resultNo) |
386 | : OpResultImpl(type, static_cast<ValueImpl::Kind>(resultNo)) { |
387 | assert(resultNo < getMaxInlineResults())(static_cast <bool> (resultNo < getMaxInlineResults( )) ? void (0) : __assert_fail ("resultNo < getMaxInlineResults()" , "mlir/include/mlir/IR/Value.h", 387, __extension__ __PRETTY_FUNCTION__ )); |
388 | } |
389 | |
390 | /// Return the result number of this op result. |
391 | unsigned getResultNumber() const { return static_cast<unsigned>(getKind()); } |
392 | |
393 | static bool classof(const OpResultImpl *value) { |
394 | return value->getKind() != ValueImpl::Kind::OutOfLineOpResult; |
395 | } |
396 | }; |
397 | |
398 | /// This class provides the implementation for an operation result whose index |
399 | /// cannot be represented "inline", and thus requires an additional index field. |
400 | class OutOfLineOpResult : public OpResultImpl { |
401 | public: |
402 | OutOfLineOpResult(Type type, uint64_t outOfLineIndex) |
403 | : OpResultImpl(type, Kind::OutOfLineOpResult), |
404 | outOfLineIndex(outOfLineIndex) {} |
405 | |
406 | static bool classof(const OpResultImpl *value) { |
407 | return value->getKind() == ValueImpl::Kind::OutOfLineOpResult; |
408 | } |
409 | |
410 | /// Return the result number of this op result. |
411 | unsigned getResultNumber() const { |
412 | return outOfLineIndex + getMaxInlineResults(); |
413 | } |
414 | |
415 | /// The trailing result number, or the offset from the beginning of the |
416 | /// `OutOfLineOpResult` array. |
417 | uint64_t outOfLineIndex; |
418 | }; |
419 | |
420 | /// Return the result number of this op result. |
421 | inline unsigned OpResultImpl::getResultNumber() const { |
422 | if (const auto *outOfLineResult = dyn_cast<OutOfLineOpResult>(this)) |
423 | return outOfLineResult->getResultNumber(); |
424 | return cast<InlineOpResult>(this)->getResultNumber(); |
425 | } |
426 | |
427 | /// TypedValue is a Value with a statically know type. |
428 | /// TypedValue can be null/empty |
429 | template <typename Ty> |
430 | struct TypedValue : Value { |
431 | using Value::Value; |
432 | |
433 | static bool classof(Value value) { return llvm::isa<Ty>(value.getType()); } |
434 | |
435 | /// Return the known Type |
436 | Ty getType() { return Value::getType().template cast<Ty>(); } |
437 | void setType(Ty ty) { Value::setType(ty); } |
438 | }; |
439 | |
440 | } // namespace detail |
441 | |
442 | /// This is a value defined by a result of an operation. |
443 | class OpResult : public Value { |
444 | public: |
445 | using Value::Value; |
446 | |
447 | static bool classof(Value value) { |
448 | return llvm::isa<detail::OpResultImpl>(value.getImpl()); |
449 | } |
450 | |
451 | /// Returns the operation that owns this result. |
452 | Operation *getOwner() const { return getImpl()->getOwner(); } |
453 | |
454 | /// Returns the number of this result. |
455 | unsigned getResultNumber() const { return getImpl()->getResultNumber(); } |
456 | |
457 | private: |
458 | /// Get a raw pointer to the internal implementation. |
459 | detail::OpResultImpl *getImpl() const { |
460 | return reinterpret_cast<detail::OpResultImpl *>(impl); |
461 | } |
462 | |
463 | /// Given a number of operation results, returns the number that need to be |
464 | /// stored inline. |
465 | static unsigned getNumInline(unsigned numResults); |
466 | |
467 | /// Given a number of operation results, returns the number that need to be |
468 | /// stored as trailing. |
469 | static unsigned getNumTrailing(unsigned numResults); |
470 | |
471 | /// Allow access to constructor. |
472 | friend Operation; |
473 | }; |
474 | |
475 | /// Make Value hashable. |
476 | inline ::llvm::hash_code hash_value(Value arg) { |
477 | return ::llvm::hash_value(arg.getImpl()); |
478 | } |
479 | |
480 | template <typename Ty, typename Value = mlir::Value> |
481 | /// If Ty is mlir::Type this will select `Value` instead of having a wrapper |
482 | /// around it. This helps resolve ambiguous conversion issues. |
483 | using TypedValue = std::conditional_t<std::is_same_v<Ty, mlir::Type>, |
484 | mlir::Value, detail::TypedValue<Ty>>; |
485 | |
486 | } // namespace mlir |
487 | |
488 | namespace llvm { |
489 | |
490 | template <> |
491 | struct DenseMapInfo<mlir::Value> { |
492 | static mlir::Value getEmptyKey() { |
493 | void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey(); |
494 | return mlir::Value::getFromOpaquePointer(pointer); |
495 | } |
496 | static mlir::Value getTombstoneKey() { |
497 | void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey(); |
498 | return mlir::Value::getFromOpaquePointer(pointer); |
499 | } |
500 | static unsigned getHashValue(mlir::Value val) { |
501 | return mlir::hash_value(val); |
502 | } |
503 | static bool isEqual(mlir::Value lhs, mlir::Value rhs) { return lhs == rhs; } |
504 | }; |
505 | template <> |
506 | struct DenseMapInfo<mlir::BlockArgument> : public DenseMapInfo<mlir::Value> { |
507 | static mlir::BlockArgument getEmptyKey() { |
508 | void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey(); |
509 | return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer); |
510 | } |
511 | static mlir::BlockArgument getTombstoneKey() { |
512 | void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey(); |
513 | return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer); |
514 | } |
515 | }; |
516 | template <> |
517 | struct DenseMapInfo<mlir::OpResult> : public DenseMapInfo<mlir::Value> { |
518 | static mlir::OpResult getEmptyKey() { |
519 | void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey(); |
520 | return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer); |
521 | } |
522 | static mlir::OpResult getTombstoneKey() { |
523 | void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey(); |
524 | return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer); |
525 | } |
526 | }; |
527 | |
528 | /// Allow stealing the low bits of a value. |
529 | template <> |
530 | struct PointerLikeTypeTraits<mlir::Value> { |
531 | public: |
532 | static inline void *getAsVoidPointer(mlir::Value value) { |
533 | return const_cast<void *>(value.getAsOpaquePointer()); |
534 | } |
535 | static inline mlir::Value getFromVoidPointer(void *pointer) { |
536 | return mlir::Value::getFromOpaquePointer(pointer); |
537 | } |
538 | enum { |
539 | NumLowBitsAvailable = |
540 | PointerLikeTypeTraits<mlir::detail::ValueImpl *>::NumLowBitsAvailable |
541 | }; |
542 | }; |
543 | template <> |
544 | struct PointerLikeTypeTraits<mlir::BlockArgument> |
545 | : public PointerLikeTypeTraits<mlir::Value> { |
546 | public: |
547 | static inline mlir::BlockArgument getFromVoidPointer(void *pointer) { |
548 | return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer); |
549 | } |
550 | }; |
551 | template <> |
552 | struct PointerLikeTypeTraits<mlir::OpResult> |
553 | : public PointerLikeTypeTraits<mlir::Value> { |
554 | public: |
555 | static inline mlir::OpResult getFromVoidPointer(void *pointer) { |
556 | return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer); |
557 | } |
558 | }; |
559 | |
560 | /// Add support for llvm style casts. We provide a cast between To and From if |
561 | /// From is mlir::Value or derives from it. |
562 | template <typename To, typename From> |
563 | struct CastInfo< |
564 | To, From, |
565 | std::enable_if_t<std::is_same_v<mlir::Value, std::remove_const_t<From>> || |
566 | std::is_base_of_v<mlir::Value, From>>> |
567 | : NullableValueCastFailed<To>, |
568 | DefaultDoCastIfPossible<To, From, CastInfo<To, From>> { |
569 | /// Arguments are taken as mlir::Value here and not as `From`, because |
570 | /// when casting from an intermediate type of the hierarchy to one of its |
571 | /// children, the val.getKind() inside T::classof will use the static |
572 | /// getKind() of the parent instead of the non-static ValueImpl::getKind() |
573 | /// that returns the dynamic type. This means that T::classof would end up |
574 | /// comparing the static Kind of the children to the static Kind of its |
575 | /// parent, making it impossible to downcast from the parent to the child. |
576 | static inline bool isPossible(mlir::Value ty) { |
577 | /// Return a constant true instead of a dynamic true when casting to self or |
578 | /// up the hierarchy. |
579 | if constexpr (std::is_base_of_v<To, From>) { |
580 | (void)ty; |
581 | return true; |
582 | } else { |
583 | return To::classof(ty); |
584 | } |
585 | } |
586 | static inline To doCast(mlir::Value value) { return To(value.getImpl()); } |
587 | }; |
588 | |
589 | } // namespace llvm |
590 | |
591 | #endif |
1 | //===- llvm/Support/Casting.h - Allow flexible, checked, casts --*- 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 defines the isa<X>(), cast<X>(), dyn_cast<X>(), |
10 | // cast_if_present<X>(), and dyn_cast_if_present<X>() templates. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_SUPPORT_CASTING_H |
15 | #define LLVM_SUPPORT_CASTING_H |
16 | |
17 | #include "llvm/Support/Compiler.h" |
18 | #include "llvm/Support/type_traits.h" |
19 | #include <cassert> |
20 | #include <memory> |
21 | #include <optional> |
22 | #include <type_traits> |
23 | |
24 | namespace llvm { |
25 | |
26 | //===----------------------------------------------------------------------===// |
27 | // simplify_type |
28 | //===----------------------------------------------------------------------===// |
29 | |
30 | /// Define a template that can be specialized by smart pointers to reflect the |
31 | /// fact that they are automatically dereferenced, and are not involved with the |
32 | /// template selection process... the default implementation is a noop. |
33 | // TODO: rename this and/or replace it with other cast traits. |
34 | template <typename From> struct simplify_type { |
35 | using SimpleType = From; // The real type this represents... |
36 | |
37 | // An accessor to get the real value... |
38 | static SimpleType &getSimplifiedValue(From &Val) { return Val; } |
39 | }; |
40 | |
41 | template <typename From> struct simplify_type<const From> { |
42 | using NonConstSimpleType = typename simplify_type<From>::SimpleType; |
43 | using SimpleType = typename add_const_past_pointer<NonConstSimpleType>::type; |
44 | using RetType = |
45 | typename add_lvalue_reference_if_not_pointer<SimpleType>::type; |
46 | |
47 | static RetType getSimplifiedValue(const From &Val) { |
48 | return simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val)); |
49 | } |
50 | }; |
51 | |
52 | // TODO: add this namespace once everyone is switched to using the new |
53 | // interface. |
54 | // namespace detail { |
55 | |
56 | //===----------------------------------------------------------------------===// |
57 | // isa_impl |
58 | //===----------------------------------------------------------------------===// |
59 | |
60 | // The core of the implementation of isa<X> is here; To and From should be |
61 | // the names of classes. This template can be specialized to customize the |
62 | // implementation of isa<> without rewriting it from scratch. |
63 | template <typename To, typename From, typename Enabler = void> struct isa_impl { |
64 | static inline bool doit(const From &Val) { return To::classof(&Val); } |
65 | }; |
66 | |
67 | // Always allow upcasts, and perform no dynamic check for them. |
68 | template <typename To, typename From> |
69 | struct isa_impl<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> { |
70 | static inline bool doit(const From &) { return true; } |
71 | }; |
72 | |
73 | template <typename To, typename From> struct isa_impl_cl { |
74 | static inline bool doit(const From &Val) { |
75 | return isa_impl<To, From>::doit(Val); |
76 | } |
77 | }; |
78 | |
79 | template <typename To, typename From> struct isa_impl_cl<To, const From> { |
80 | static inline bool doit(const From &Val) { |
81 | return isa_impl<To, From>::doit(Val); |
82 | } |
83 | }; |
84 | |
85 | template <typename To, typename From> |
86 | struct isa_impl_cl<To, const std::unique_ptr<From>> { |
87 | static inline bool doit(const std::unique_ptr<From> &Val) { |
88 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 88, __extension__ __PRETTY_FUNCTION__ )); |
89 | return isa_impl_cl<To, From>::doit(*Val); |
90 | } |
91 | }; |
92 | |
93 | template <typename To, typename From> struct isa_impl_cl<To, From *> { |
94 | static inline bool doit(const From *Val) { |
95 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 95, __extension__ __PRETTY_FUNCTION__ )); |
96 | return isa_impl<To, From>::doit(*Val); |
97 | } |
98 | }; |
99 | |
100 | template <typename To, typename From> struct isa_impl_cl<To, From *const> { |
101 | static inline bool doit(const From *Val) { |
102 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 102, __extension__ __PRETTY_FUNCTION__ )); |
103 | return isa_impl<To, From>::doit(*Val); |
104 | } |
105 | }; |
106 | |
107 | template <typename To, typename From> struct isa_impl_cl<To, const From *> { |
108 | static inline bool doit(const From *Val) { |
109 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 109, __extension__ __PRETTY_FUNCTION__ )); |
110 | return isa_impl<To, From>::doit(*Val); |
111 | } |
112 | }; |
113 | |
114 | template <typename To, typename From> |
115 | struct isa_impl_cl<To, const From *const> { |
116 | static inline bool doit(const From *Val) { |
117 | assert(Val && "isa<> used on a null pointer")(static_cast <bool> (Val && "isa<> used on a null pointer" ) ? void (0) : __assert_fail ("Val && \"isa<> used on a null pointer\"" , "llvm/include/llvm/Support/Casting.h", 117, __extension__ __PRETTY_FUNCTION__ )); |
118 | return isa_impl<To, From>::doit(*Val); |
119 | } |
120 | }; |
121 | |
122 | template <typename To, typename From, typename SimpleFrom> |
123 | struct isa_impl_wrap { |
124 | // When From != SimplifiedType, we can simplify the type some more by using |
125 | // the simplify_type template. |
126 | static bool doit(const From &Val) { |
127 | return isa_impl_wrap<To, SimpleFrom, |
128 | typename simplify_type<SimpleFrom>::SimpleType>:: |
129 | doit(simplify_type<const From>::getSimplifiedValue(Val)); |
130 | } |
131 | }; |
132 | |
133 | template <typename To, typename FromTy> |
134 | struct isa_impl_wrap<To, FromTy, FromTy> { |
135 | // When From == SimpleType, we are as simple as we are going to get. |
136 | static bool doit(const FromTy &Val) { |
137 | return isa_impl_cl<To, FromTy>::doit(Val); |
138 | } |
139 | }; |
140 | |
141 | //===----------------------------------------------------------------------===// |
142 | // cast_retty + cast_retty_impl |
143 | //===----------------------------------------------------------------------===// |
144 | |
145 | template <class To, class From> struct cast_retty; |
146 | |
147 | // Calculate what type the 'cast' function should return, based on a requested |
148 | // type of To and a source type of From. |
149 | template <class To, class From> struct cast_retty_impl { |
150 | using ret_type = To &; // Normal case, return Ty& |
151 | }; |
152 | template <class To, class From> struct cast_retty_impl<To, const From> { |
153 | using ret_type = const To &; // Normal case, return Ty& |
154 | }; |
155 | |
156 | template <class To, class From> struct cast_retty_impl<To, From *> { |
157 | using ret_type = To *; // Pointer arg case, return Ty* |
158 | }; |
159 | |
160 | template <class To, class From> struct cast_retty_impl<To, const From *> { |
161 | using ret_type = const To *; // Constant pointer arg case, return const Ty* |
162 | }; |
163 | |
164 | template <class To, class From> struct cast_retty_impl<To, const From *const> { |
165 | using ret_type = const To *; // Constant pointer arg case, return const Ty* |
166 | }; |
167 | |
168 | template <class To, class From> |
169 | struct cast_retty_impl<To, std::unique_ptr<From>> { |
170 | private: |
171 | using PointerType = typename cast_retty_impl<To, From *>::ret_type; |
172 | using ResultType = std::remove_pointer_t<PointerType>; |
173 | |
174 | public: |
175 | using ret_type = std::unique_ptr<ResultType>; |
176 | }; |
177 | |
178 | template <class To, class From, class SimpleFrom> struct cast_retty_wrap { |
179 | // When the simplified type and the from type are not the same, use the type |
180 | // simplifier to reduce the type, then reuse cast_retty_impl to get the |
181 | // resultant type. |
182 | using ret_type = typename cast_retty<To, SimpleFrom>::ret_type; |
183 | }; |
184 | |
185 | template <class To, class FromTy> struct cast_retty_wrap<To, FromTy, FromTy> { |
186 | // When the simplified type is equal to the from type, use it directly. |
187 | using ret_type = typename cast_retty_impl<To, FromTy>::ret_type; |
188 | }; |
189 | |
190 | template <class To, class From> struct cast_retty { |
191 | using ret_type = typename cast_retty_wrap< |
192 | To, From, typename simplify_type<From>::SimpleType>::ret_type; |
193 | }; |
194 | |
195 | //===----------------------------------------------------------------------===// |
196 | // cast_convert_val |
197 | //===----------------------------------------------------------------------===// |
198 | |
199 | // Ensure the non-simple values are converted using the simplify_type template |
200 | // that may be specialized by smart pointers... |
201 | // |
202 | template <class To, class From, class SimpleFrom> struct cast_convert_val { |
203 | // This is not a simple type, use the template to simplify it... |
204 | static typename cast_retty<To, From>::ret_type doit(const From &Val) { |
205 | return cast_convert_val<To, SimpleFrom, |
206 | typename simplify_type<SimpleFrom>::SimpleType>:: |
207 | doit(simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val))); |
208 | } |
209 | }; |
210 | |
211 | template <class To, class FromTy> struct cast_convert_val<To, FromTy, FromTy> { |
212 | // If it's a reference, switch to a pointer to do the cast and then deref it. |
213 | static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) { |
214 | return *(std::remove_reference_t<typename cast_retty<To, FromTy>::ret_type> |
215 | *)&const_cast<FromTy &>(Val); |
216 | } |
217 | }; |
218 | |
219 | template <class To, class FromTy> |
220 | struct cast_convert_val<To, FromTy *, FromTy *> { |
221 | // If it's a pointer, we can use c-style casting directly. |
222 | static typename cast_retty<To, FromTy *>::ret_type doit(const FromTy *Val) { |
223 | return (typename cast_retty<To, FromTy *>::ret_type) const_cast<FromTy *>( |
224 | Val); |
225 | } |
226 | }; |
227 | |
228 | //===----------------------------------------------------------------------===// |
229 | // is_simple_type |
230 | //===----------------------------------------------------------------------===// |
231 | |
232 | template <class X> struct is_simple_type { |
233 | static const bool value = |
234 | std::is_same_v<X, typename simplify_type<X>::SimpleType>; |
235 | }; |
236 | |
237 | // } // namespace detail |
238 | |
239 | //===----------------------------------------------------------------------===// |
240 | // CastIsPossible |
241 | //===----------------------------------------------------------------------===// |
242 | |
243 | /// This struct provides a way to check if a given cast is possible. It provides |
244 | /// a static function called isPossible that is used to check if a cast can be |
245 | /// performed. It should be overridden like this: |
246 | /// |
247 | /// template<> struct CastIsPossible<foo, bar> { |
248 | /// static inline bool isPossible(const bar &b) { |
249 | /// return bar.isFoo(); |
250 | /// } |
251 | /// }; |
252 | template <typename To, typename From, typename Enable = void> |
253 | struct CastIsPossible { |
254 | static inline bool isPossible(const From &f) { |
255 | return isa_impl_wrap< |
256 | To, const From, |
257 | typename simplify_type<const From>::SimpleType>::doit(f); |
258 | } |
259 | }; |
260 | |
261 | // Needed for optional unwrapping. This could be implemented with isa_impl, but |
262 | // we want to implement things in the new method and move old implementations |
263 | // over. In fact, some of the isa_impl templates should be moved over to |
264 | // CastIsPossible. |
265 | template <typename To, typename From> |
266 | struct CastIsPossible<To, std::optional<From>> { |
267 | static inline bool isPossible(const std::optional<From> &f) { |
268 | assert(f && "CastIsPossible::isPossible called on a nullopt!")(static_cast <bool> (f && "CastIsPossible::isPossible called on a nullopt!" ) ? void (0) : __assert_fail ("f && \"CastIsPossible::isPossible called on a nullopt!\"" , "llvm/include/llvm/Support/Casting.h", 268, __extension__ __PRETTY_FUNCTION__ )); |
269 | return isa_impl_wrap< |
270 | To, const From, |
271 | typename simplify_type<const From>::SimpleType>::doit(*f); |
272 | } |
273 | }; |
274 | |
275 | /// Upcasting (from derived to base) and casting from a type to itself should |
276 | /// always be possible. |
277 | template <typename To, typename From> |
278 | struct CastIsPossible<To, From, std::enable_if_t<std::is_base_of_v<To, From>>> { |
279 | static inline bool isPossible(const From &f) { return true; } |
280 | }; |
281 | |
282 | //===----------------------------------------------------------------------===// |
283 | // Cast traits |
284 | //===----------------------------------------------------------------------===// |
285 | |
286 | /// All of these cast traits are meant to be implementations for useful casts |
287 | /// that users may want to use that are outside the standard behavior. An |
288 | /// example of how to use a special cast called `CastTrait` is: |
289 | /// |
290 | /// template<> struct CastInfo<foo, bar> : public CastTrait<foo, bar> {}; |
291 | /// |
292 | /// Essentially, if your use case falls directly into one of the use cases |
293 | /// supported by a given cast trait, simply inherit your special CastInfo |
294 | /// directly from one of these to avoid having to reimplement the boilerplate |
295 | /// `isPossible/castFailed/doCast/doCastIfPossible`. A cast trait can also |
296 | /// provide a subset of those functions. |
297 | |
298 | /// This cast trait just provides castFailed for the specified `To` type to make |
299 | /// CastInfo specializations more declarative. In order to use this, the target |
300 | /// result type must be `To` and `To` must be constructible from `nullptr`. |
301 | template <typename To> struct NullableValueCastFailed { |
302 | static To castFailed() { return To(nullptr); } |
303 | }; |
304 | |
305 | /// This cast trait just provides the default implementation of doCastIfPossible |
306 | /// to make CastInfo specializations more declarative. The `Derived` template |
307 | /// parameter *must* be provided for forwarding castFailed and doCast. |
308 | template <typename To, typename From, typename Derived> |
309 | struct DefaultDoCastIfPossible { |
310 | static To doCastIfPossible(From f) { |
311 | if (!Derived::isPossible(f)) |
312 | return Derived::castFailed(); |
313 | return Derived::doCast(f); |
314 | } |
315 | }; |
316 | |
317 | namespace detail { |
318 | /// A helper to derive the type to use with `Self` for cast traits, when the |
319 | /// provided CRTP derived type is allowed to be void. |
320 | template <typename OptionalDerived, typename Default> |
321 | using SelfType = std::conditional_t<std::is_same_v<OptionalDerived, void>, |
322 | Default, OptionalDerived>; |
323 | } // namespace detail |
324 | |
325 | /// This cast trait provides casting for the specific case of casting to a |
326 | /// value-typed object from a pointer-typed object. Note that `To` must be |
327 | /// nullable/constructible from a pointer to `From` to use this cast. |
328 | template <typename To, typename From, typename Derived = void> |
329 | struct ValueFromPointerCast |
330 | : public CastIsPossible<To, From *>, |
331 | public NullableValueCastFailed<To>, |
332 | public DefaultDoCastIfPossible< |
333 | To, From *, |
334 | detail::SelfType<Derived, ValueFromPointerCast<To, From>>> { |
335 | static inline To doCast(From *f) { return To(f); } |
336 | }; |
337 | |
338 | /// This cast trait provides std::unique_ptr casting. It has the semantics of |
339 | /// moving the contents of the input unique_ptr into the output unique_ptr |
340 | /// during the cast. It's also a good example of how to implement a move-only |
341 | /// cast. |
342 | template <typename To, typename From, typename Derived = void> |
343 | struct UniquePtrCast : public CastIsPossible<To, From *> { |
344 | using Self = detail::SelfType<Derived, UniquePtrCast<To, From>>; |
345 | using CastResultType = std::unique_ptr< |
346 | std::remove_reference_t<typename cast_retty<To, From>::ret_type>>; |
347 | |
348 | static inline CastResultType doCast(std::unique_ptr<From> &&f) { |
349 | return CastResultType((typename CastResultType::element_type *)f.release()); |
350 | } |
351 | |
352 | static inline CastResultType castFailed() { return CastResultType(nullptr); } |
353 | |
354 | static inline CastResultType doCastIfPossible(std::unique_ptr<From> &&f) { |
355 | if (!Self::isPossible(f)) |
356 | return castFailed(); |
357 | return doCast(f); |
358 | } |
359 | }; |
360 | |
361 | /// This cast trait provides std::optional<T> casting. This means that if you |
362 | /// have a value type, you can cast it to another value type and have dyn_cast |
363 | /// return an std::optional<T>. |
364 | template <typename To, typename From, typename Derived = void> |
365 | struct OptionalValueCast |
366 | : public CastIsPossible<To, From>, |
367 | public DefaultDoCastIfPossible< |
368 | std::optional<To>, From, |
369 | detail::SelfType<Derived, OptionalValueCast<To, From>>> { |
370 | static inline std::optional<To> castFailed() { return std::optional<To>{}; } |
371 | |
372 | static inline std::optional<To> doCast(const From &f) { return To(f); } |
373 | }; |
374 | |
375 | /// Provides a cast trait that strips `const` from types to make it easier to |
376 | /// implement a const-version of a non-const cast. It just removes boilerplate |
377 | /// and reduces the amount of code you as the user need to implement. You can |
378 | /// use it like this: |
379 | /// |
380 | /// template<> struct CastInfo<foo, bar> { |
381 | /// ...verbose implementation... |
382 | /// }; |
383 | /// |
384 | /// template<> struct CastInfo<foo, const bar> : public |
385 | /// ConstStrippingForwardingCast<foo, const bar, CastInfo<foo, bar>> {}; |
386 | /// |
387 | template <typename To, typename From, typename ForwardTo> |
388 | struct ConstStrippingForwardingCast { |
389 | // Remove the pointer if it exists, then we can get rid of consts/volatiles. |
390 | using DecayedFrom = std::remove_cv_t<std::remove_pointer_t<From>>; |
391 | // Now if it's a pointer, add it back. Otherwise, we want a ref. |
392 | using NonConstFrom = |
393 | std::conditional_t<std::is_pointer_v<From>, DecayedFrom *, DecayedFrom &>; |
394 | |
395 | static inline bool isPossible(const From &f) { |
396 | return ForwardTo::isPossible(const_cast<NonConstFrom>(f)); |
397 | } |
398 | |
399 | static inline decltype(auto) castFailed() { return ForwardTo::castFailed(); } |
400 | |
401 | static inline decltype(auto) doCast(const From &f) { |
402 | return ForwardTo::doCast(const_cast<NonConstFrom>(f)); |
403 | } |
404 | |
405 | static inline decltype(auto) doCastIfPossible(const From &f) { |
406 | return ForwardTo::doCastIfPossible(const_cast<NonConstFrom>(f)); |
407 | } |
408 | }; |
409 | |
410 | /// Provides a cast trait that uses a defined pointer to pointer cast as a base |
411 | /// for reference-to-reference casts. Note that it does not provide castFailed |
412 | /// and doCastIfPossible because a pointer-to-pointer cast would likely just |
413 | /// return `nullptr` which could cause nullptr dereference. You can use it like |
414 | /// this: |
415 | /// |
416 | /// template <> struct CastInfo<foo, bar *> { ... verbose implementation... }; |
417 | /// |
418 | /// template <> |
419 | /// struct CastInfo<foo, bar> |
420 | /// : public ForwardToPointerCast<foo, bar, CastInfo<foo, bar *>> {}; |
421 | /// |
422 | template <typename To, typename From, typename ForwardTo> |
423 | struct ForwardToPointerCast { |
424 | static inline bool isPossible(const From &f) { |
425 | return ForwardTo::isPossible(&f); |
426 | } |
427 | |
428 | static inline decltype(auto) doCast(const From &f) { |
429 | return *ForwardTo::doCast(&f); |
430 | } |
431 | }; |
432 | |
433 | //===----------------------------------------------------------------------===// |
434 | // CastInfo |
435 | //===----------------------------------------------------------------------===// |
436 | |
437 | /// This struct provides a method for customizing the way a cast is performed. |
438 | /// It inherits from CastIsPossible, to support the case of declaring many |
439 | /// CastIsPossible specializations without having to specialize the full |
440 | /// CastInfo. |
441 | /// |
442 | /// In order to specialize different behaviors, specify different functions in |
443 | /// your CastInfo specialization. |
444 | /// For isa<> customization, provide: |
445 | /// |
446 | /// `static bool isPossible(const From &f)` |
447 | /// |
448 | /// For cast<> customization, provide: |
449 | /// |
450 | /// `static To doCast(const From &f)` |
451 | /// |
452 | /// For dyn_cast<> and the *_if_present<> variants' customization, provide: |
453 | /// |
454 | /// `static To castFailed()` and `static To doCastIfPossible(const From &f)` |
455 | /// |
456 | /// Your specialization might look something like this: |
457 | /// |
458 | /// template<> struct CastInfo<foo, bar> : public CastIsPossible<foo, bar> { |
459 | /// static inline foo doCast(const bar &b) { |
460 | /// return foo(const_cast<bar &>(b)); |
461 | /// } |
462 | /// static inline foo castFailed() { return foo(); } |
463 | /// static inline foo doCastIfPossible(const bar &b) { |
464 | /// if (!CastInfo<foo, bar>::isPossible(b)) |
465 | /// return castFailed(); |
466 | /// return doCast(b); |
467 | /// } |
468 | /// }; |
469 | |
470 | // The default implementations of CastInfo don't use cast traits for now because |
471 | // we need to specify types all over the place due to the current expected |
472 | // casting behavior and the way cast_retty works. New use cases can and should |
473 | // take advantage of the cast traits whenever possible! |
474 | |
475 | template <typename To, typename From, typename Enable = void> |
476 | struct CastInfo : public CastIsPossible<To, From> { |
477 | using Self = CastInfo<To, From, Enable>; |
478 | |
479 | using CastReturnType = typename cast_retty<To, From>::ret_type; |
480 | |
481 | static inline CastReturnType doCast(const From &f) { |
482 | return cast_convert_val< |
483 | To, From, |
484 | typename simplify_type<From>::SimpleType>::doit(const_cast<From &>(f)); |
485 | } |
486 | |
487 | // This assumes that you can construct the cast return type from `nullptr`. |
488 | // This is largely to support legacy use cases - if you don't want this |
489 | // behavior you should specialize CastInfo for your use case. |
490 | static inline CastReturnType castFailed() { return CastReturnType(nullptr); } |
491 | |
492 | static inline CastReturnType doCastIfPossible(const From &f) { |
493 | if (!Self::isPossible(f)) |
494 | return castFailed(); |
495 | return doCast(f); |
496 | } |
497 | }; |
498 | |
499 | /// This struct provides an overload for CastInfo where From has simplify_type |
500 | /// defined. This simply forwards to the appropriate CastInfo with the |
501 | /// simplified type/value, so you don't have to implement both. |
502 | template <typename To, typename From> |
503 | struct CastInfo<To, From, std::enable_if_t<!is_simple_type<From>::value>> { |
504 | using Self = CastInfo<To, From>; |
505 | using SimpleFrom = typename simplify_type<From>::SimpleType; |
506 | using SimplifiedSelf = CastInfo<To, SimpleFrom>; |
507 | |
508 | static inline bool isPossible(From &f) { |
509 | return SimplifiedSelf::isPossible( |
510 | simplify_type<From>::getSimplifiedValue(f)); |
511 | } |
512 | |
513 | static inline decltype(auto) doCast(From &f) { |
514 | return SimplifiedSelf::doCast(simplify_type<From>::getSimplifiedValue(f)); |
515 | } |
516 | |
517 | static inline decltype(auto) castFailed() { |
518 | return SimplifiedSelf::castFailed(); |
519 | } |
520 | |
521 | static inline decltype(auto) doCastIfPossible(From &f) { |
522 | return SimplifiedSelf::doCastIfPossible( |
523 | simplify_type<From>::getSimplifiedValue(f)); |
524 | } |
525 | }; |
526 | |
527 | //===----------------------------------------------------------------------===// |
528 | // Pre-specialized CastInfo |
529 | //===----------------------------------------------------------------------===// |
530 | |
531 | /// Provide a CastInfo specialized for std::unique_ptr. |
532 | template <typename To, typename From> |
533 | struct CastInfo<To, std::unique_ptr<From>> : public UniquePtrCast<To, From> {}; |
534 | |
535 | /// Provide a CastInfo specialized for std::optional<From>. It's assumed that if |
536 | /// the input is std::optional<From> that the output can be std::optional<To>. |
537 | /// If that's not the case, specialize CastInfo for your use case. |
538 | template <typename To, typename From> |
539 | struct CastInfo<To, std::optional<From>> : public OptionalValueCast<To, From> { |
540 | }; |
541 | |
542 | /// isa<X> - Return true if the parameter to the template is an instance of one |
543 | /// of the template type arguments. Used like this: |
544 | /// |
545 | /// if (isa<Type>(myVal)) { ... } |
546 | /// if (isa<Type0, Type1, Type2>(myVal)) { ... } |
547 | template <typename To, typename From> |
548 | [[nodiscard]] inline bool isa(const From &Val) { |
549 | return CastInfo<To, const From>::isPossible(Val); |
550 | } |
551 | |
552 | template <typename First, typename Second, typename... Rest, typename From> |
553 | [[nodiscard]] inline bool isa(const From &Val) { |
554 | return isa<First>(Val) || isa<Second, Rest...>(Val); |
555 | } |
556 | |
557 | /// cast<X> - Return the argument parameter cast to the specified type. This |
558 | /// casting operator asserts that the type is correct, so it does not return |
559 | /// null on failure. It does not allow a null argument (use cast_if_present for |
560 | /// that). It is typically used like this: |
561 | /// |
562 | /// cast<Instruction>(myVal)->getParent() |
563 | |
564 | template <typename To, typename From> |
565 | [[nodiscard]] inline decltype(auto) cast(const From &Val) { |
566 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 566, __extension__ __PRETTY_FUNCTION__ )); |
567 | return CastInfo<To, const From>::doCast(Val); |
568 | } |
569 | |
570 | template <typename To, typename From> |
571 | [[nodiscard]] inline decltype(auto) cast(From &Val) { |
572 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 572, __extension__ __PRETTY_FUNCTION__ )); |
573 | return CastInfo<To, From>::doCast(Val); |
574 | } |
575 | |
576 | template <typename To, typename From> |
577 | [[nodiscard]] inline decltype(auto) cast(From *Val) { |
578 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 578, __extension__ __PRETTY_FUNCTION__ )); |
579 | return CastInfo<To, From *>::doCast(Val); |
580 | } |
581 | |
582 | template <typename To, typename From> |
583 | [[nodiscard]] inline decltype(auto) cast(std::unique_ptr<From> &&Val) { |
584 | assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!")(static_cast <bool> (isa<To>(Val) && "cast<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<To>(Val) && \"cast<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 584, __extension__ __PRETTY_FUNCTION__ )); |
585 | return CastInfo<To, std::unique_ptr<From>>::doCast(std::move(Val)); |
586 | } |
587 | |
588 | //===----------------------------------------------------------------------===// |
589 | // ValueIsPresent |
590 | //===----------------------------------------------------------------------===// |
591 | |
592 | template <typename T> |
593 | constexpr bool IsNullable = |
594 | std::is_pointer_v<T> || std::is_constructible_v<T, std::nullptr_t>; |
595 | |
596 | /// ValueIsPresent provides a way to check if a value is, well, present. For |
597 | /// pointers, this is the equivalent of checking against nullptr, for Optionals |
598 | /// this is the equivalent of checking hasValue(). It also provides a method for |
599 | /// unwrapping a value (think calling .value() on an optional). |
600 | |
601 | // Generic values can't *not* be present. |
602 | template <typename T, typename Enable = void> struct ValueIsPresent { |
603 | using UnwrappedType = T; |
604 | static inline bool isPresent(const T &t) { return true; } |
605 | static inline decltype(auto) unwrapValue(T &t) { return t; } |
606 | }; |
607 | |
608 | // Optional provides its own way to check if something is present. |
609 | template <typename T> struct ValueIsPresent<std::optional<T>> { |
610 | using UnwrappedType = T; |
611 | static inline bool isPresent(const std::optional<T> &t) { |
612 | return t.has_value(); |
613 | } |
614 | static inline decltype(auto) unwrapValue(std::optional<T> &t) { return *t; } |
615 | }; |
616 | |
617 | // If something is "nullable" then we just compare it to nullptr to see if it |
618 | // exists. |
619 | template <typename T> |
620 | struct ValueIsPresent<T, std::enable_if_t<IsNullable<T>>> { |
621 | using UnwrappedType = T; |
622 | static inline bool isPresent(const T &t) { return t != T(nullptr); } |
623 | static inline decltype(auto) unwrapValue(T &t) { return t; } |
624 | }; |
625 | |
626 | namespace detail { |
627 | // Convenience function we can use to check if a value is present. Because of |
628 | // simplify_type, we have to call it on the simplified type for now. |
629 | template <typename T> inline bool isPresent(const T &t) { |
630 | return ValueIsPresent<typename simplify_type<T>::SimpleType>::isPresent( |
631 | simplify_type<T>::getSimplifiedValue(const_cast<T &>(t))); |
632 | } |
633 | |
634 | // Convenience function we can use to unwrap a value. |
635 | template <typename T> inline decltype(auto) unwrapValue(T &t) { |
636 | return ValueIsPresent<T>::unwrapValue(t); |
637 | } |
638 | } // namespace detail |
639 | |
640 | /// dyn_cast<X> - Return the argument parameter cast to the specified type. This |
641 | /// casting operator returns null if the argument is of the wrong type, so it |
642 | /// can be used to test for a type as well as cast if successful. The value |
643 | /// passed in must be present, if not, use dyn_cast_if_present. This should be |
644 | /// used in the context of an if statement like this: |
645 | /// |
646 | /// if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... } |
647 | |
648 | template <typename To, typename From> |
649 | [[nodiscard]] inline decltype(auto) dyn_cast(const From &Val) { |
650 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 650, __extension__ __PRETTY_FUNCTION__ )); |
651 | return CastInfo<To, const From>::doCastIfPossible(Val); |
652 | } |
653 | |
654 | template <typename To, typename From> |
655 | [[nodiscard]] inline decltype(auto) dyn_cast(From &Val) { |
656 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 656, __extension__ __PRETTY_FUNCTION__ )); |
657 | return CastInfo<To, From>::doCastIfPossible(Val); |
658 | } |
659 | |
660 | template <typename To, typename From> |
661 | [[nodiscard]] inline decltype(auto) dyn_cast(From *Val) { |
662 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 662, __extension__ __PRETTY_FUNCTION__ )); |
663 | return CastInfo<To, From *>::doCastIfPossible(Val); |
664 | } |
665 | |
666 | template <typename To, typename From> |
667 | [[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) { |
668 | assert(detail::isPresent(Val) && "dyn_cast on a non-existent value")(static_cast <bool> (detail::isPresent(Val) && "dyn_cast on a non-existent value" ) ? void (0) : __assert_fail ("detail::isPresent(Val) && \"dyn_cast on a non-existent value\"" , "llvm/include/llvm/Support/Casting.h", 668, __extension__ __PRETTY_FUNCTION__ )); |
669 | return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible( |
670 | std::forward<std::unique_ptr<From> &&>(Val)); |
671 | } |
672 | |
673 | /// isa_and_present<X> - Functionally identical to isa, except that a null value |
674 | /// is accepted. |
675 | template <typename... X, class Y> |
676 | [[nodiscard]] inline bool isa_and_present(const Y &Val) { |
677 | if (!detail::isPresent(Val)) |
678 | return false; |
679 | return isa<X...>(Val); |
680 | } |
681 | |
682 | template <typename... X, class Y> |
683 | [[nodiscard]] inline bool isa_and_nonnull(const Y &Val) { |
684 | return isa_and_present<X...>(Val); |
685 | } |
686 | |
687 | /// cast_if_present<X> - Functionally identical to cast, except that a null |
688 | /// value is accepted. |
689 | template <class X, class Y> |
690 | [[nodiscard]] inline auto cast_if_present(const Y &Val) { |
691 | if (!detail::isPresent(Val)) |
692 | return CastInfo<X, const Y>::castFailed(); |
693 | assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 693, __extension__ __PRETTY_FUNCTION__ )); |
694 | return cast<X>(detail::unwrapValue(Val)); |
695 | } |
696 | |
697 | template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y &Val) { |
698 | if (!detail::isPresent(Val)) |
699 | return CastInfo<X, Y>::castFailed(); |
700 | assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 700, __extension__ __PRETTY_FUNCTION__ )); |
701 | return cast<X>(detail::unwrapValue(Val)); |
702 | } |
703 | |
704 | template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y *Val) { |
705 | if (!detail::isPresent(Val)) |
706 | return CastInfo<X, Y *>::castFailed(); |
707 | assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!")(static_cast <bool> (isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!" ) ? void (0) : __assert_fail ("isa<X>(Val) && \"cast_if_present<Ty>() argument of incompatible type!\"" , "llvm/include/llvm/Support/Casting.h", 707, __extension__ __PRETTY_FUNCTION__ )); |
708 | return cast<X>(detail::unwrapValue(Val)); |
709 | } |
710 | |
711 | template <class X, class Y> |
712 | [[nodiscard]] inline auto cast_if_present(std::unique_ptr<Y> &&Val) { |
713 | if (!detail::isPresent(Val)) |
714 | return UniquePtrCast<X, Y>::castFailed(); |
715 | return UniquePtrCast<X, Y>::doCast(std::move(Val)); |
716 | } |
717 | |
718 | // Provide a forwarding from cast_or_null to cast_if_present for current |
719 | // users. This is deprecated and will be removed in a future patch, use |
720 | // cast_if_present instead. |
721 | template <class X, class Y> auto cast_or_null(const Y &Val) { |
722 | return cast_if_present<X>(Val); |
723 | } |
724 | |
725 | template <class X, class Y> auto cast_or_null(Y &Val) { |
726 | return cast_if_present<X>(Val); |
727 | } |
728 | |
729 | template <class X, class Y> auto cast_or_null(Y *Val) { |
730 | return cast_if_present<X>(Val); |
731 | } |
732 | |
733 | template <class X, class Y> auto cast_or_null(std::unique_ptr<Y> &&Val) { |
734 | return cast_if_present<X>(std::move(Val)); |
735 | } |
736 | |
737 | /// dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a |
738 | /// null (or none in the case of optionals) value is accepted. |
739 | template <class X, class Y> auto dyn_cast_if_present(const Y &Val) { |
740 | if (!detail::isPresent(Val)) |
741 | return CastInfo<X, const Y>::castFailed(); |
742 | return CastInfo<X, const Y>::doCastIfPossible(detail::unwrapValue(Val)); |
743 | } |
744 | |
745 | template <class X, class Y> auto dyn_cast_if_present(Y &Val) { |
746 | if (!detail::isPresent(Val)) |
747 | return CastInfo<X, Y>::castFailed(); |
748 | return CastInfo<X, Y>::doCastIfPossible(detail::unwrapValue(Val)); |
749 | } |
750 | |
751 | template <class X, class Y> auto dyn_cast_if_present(Y *Val) { |
752 | if (!detail::isPresent(Val)) |
753 | return CastInfo<X, Y *>::castFailed(); |
754 | return CastInfo<X, Y *>::doCastIfPossible(detail::unwrapValue(Val)); |
755 | } |
756 | |
757 | // Forwards to dyn_cast_if_present to avoid breaking current users. This is |
758 | // deprecated and will be removed in a future patch, use |
759 | // cast_if_present instead. |
760 | template <class X, class Y> auto dyn_cast_or_null(const Y &Val) { |
761 | return dyn_cast_if_present<X>(Val); |
762 | } |
763 | |
764 | template <class X, class Y> auto dyn_cast_or_null(Y &Val) { |
765 | return dyn_cast_if_present<X>(Val); |
766 | } |
767 | |
768 | template <class X, class Y> auto dyn_cast_or_null(Y *Val) { |
769 | return dyn_cast_if_present<X>(Val); |
770 | } |
771 | |
772 | /// unique_dyn_cast<X> - Given a unique_ptr<Y>, try to return a unique_ptr<X>, |
773 | /// taking ownership of the input pointer iff isa<X>(Val) is true. If the |
774 | /// cast is successful, From refers to nullptr on exit and the casted value |
775 | /// is returned. If the cast is unsuccessful, the function returns nullptr |
776 | /// and From is unchanged. |
777 | template <class X, class Y> |
778 | [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType |
779 | unique_dyn_cast(std::unique_ptr<Y> &Val) { |
780 | if (!isa<X>(Val)) |
781 | return nullptr; |
782 | return cast<X>(std::move(Val)); |
783 | } |
784 | |
785 | template <class X, class Y> |
786 | [[nodiscard]] inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val) { |
787 | return unique_dyn_cast<X, Y>(Val); |
788 | } |
789 | |
790 | // unique_dyn_cast_or_null<X> - Functionally identical to unique_dyn_cast, |
791 | // except that a null value is accepted. |
792 | template <class X, class Y> |
793 | [[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType |
794 | unique_dyn_cast_or_null(std::unique_ptr<Y> &Val) { |
795 | if (!Val) |
796 | return nullptr; |
797 | return unique_dyn_cast<X, Y>(Val); |
798 | } |
799 | |
800 | template <class X, class Y> |
801 | [[nodiscard]] inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val) { |
802 | return unique_dyn_cast_or_null<X, Y>(Val); |
803 | } |
804 | |
805 | } // end namespace llvm |
806 | |
807 | #endif // LLVM_SUPPORT_CASTING_H |
1 | //===- Operation.h - MLIR Operation Class -----------------------*- 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 defines the Operation class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef MLIR_IR_OPERATION_H |
14 | #define MLIR_IR_OPERATION_H |
15 | |
16 | #include "mlir/IR/Block.h" |
17 | #include "mlir/IR/BuiltinAttributes.h" |
18 | #include "mlir/IR/Diagnostics.h" |
19 | #include "mlir/IR/OperationSupport.h" |
20 | #include "mlir/IR/Region.h" |
21 | #include "llvm/ADT/Twine.h" |
22 | #include <optional> |
23 | |
24 | namespace mlir { |
25 | namespace detail { |
26 | /// This is a "tag" used for mapping the properties storage in |
27 | /// llvm::TrailingObjects. |
28 | enum class OpProperties : char {}; |
29 | } // namespace detail |
30 | |
31 | /// Operation is the basic unit of execution within MLIR. |
32 | /// |
33 | /// The following documentation are recommended to understand this class: |
34 | /// - https://mlir.llvm.org/docs/LangRef/#operations |
35 | /// - https://mlir.llvm.org/docs/Tutorials/UnderstandingTheIRStructure/ |
36 | /// |
37 | /// An Operation is defined first by its name, which is a unique string. The |
38 | /// name is interpreted so that if it contains a '.' character, the part before |
39 | /// is the dialect name this operation belongs to, and everything that follows |
40 | /// is this operation name within the dialect. |
41 | /// |
42 | /// An Operation defines zero or more SSA `Value` that we refer to as the |
43 | /// Operation results. This array of Value is actually stored in memory before |
44 | /// the Operation itself in reverse order. That is for an Operation with 3 |
45 | /// results we allocate the following memory layout: |
46 | /// |
47 | /// [Result2, Result1, Result0, Operation] |
48 | /// ^ this is where `Operation*` pointer points to. |
49 | /// |
50 | /// A consequence of this is that this class must be heap allocated, which is |
51 | /// handled by the various `create` methods. Each result contains: |
52 | /// - one pointer to the first use (see `OpOperand`) |
53 | /// - the type of the SSA Value this result defines. |
54 | /// - the index for this result in the array. |
55 | /// The results are defined as subclass of `ValueImpl`, and more precisely as |
56 | /// the only two subclasses of `OpResultImpl`: `InlineOpResult` and |
57 | /// `OutOfLineOpResult`. The former is used for the first 5 results and the |
58 | /// latter for the subsequent ones. They differ in how they store their index: |
59 | /// the first 5 results only need 3 bits and thus are packed with the Type |
60 | /// pointer, while the subsequent one have an extra `unsigned` value and thus |
61 | /// need more space. |
62 | /// |
63 | /// An Operation also has zero or more operands: these are uses of SSA Value, |
64 | /// which can be the results of other operations or Block arguments. Each of |
65 | /// these uses is an instance of `OpOperand`. This optional array is initially |
66 | /// tail allocated with the operation class itself, but can be dynamically moved |
67 | /// out-of-line in a dynamic allocation as needed. |
68 | /// |
69 | /// An Operation may contain optionally one or multiple Regions, stored in a |
70 | /// tail allocated array. Each `Region` is a list of Blocks. Each `Block` is |
71 | /// itself a list of Operations. This structure is effectively forming a tree. |
72 | /// |
73 | /// Some operations like branches also refer to other Block, in which case they |
74 | /// would have an array of `BlockOperand`. |
75 | /// |
76 | /// An Operation may contain optionally a "Properties" object: this is a |
77 | /// pre-defined C++ object with a fixed size. This object is owned by the |
78 | /// operation and deleted with the operation. It can be converted to an |
79 | /// Attribute on demand, or loaded from an Attribute. |
80 | /// |
81 | /// |
82 | /// Finally an Operation also contain an optional `DictionaryAttr`, a Location, |
83 | /// and a pointer to its parent Block (if any). |
84 | class alignas(8) Operation final |
85 | : public llvm::ilist_node_with_parent<Operation, Block>, |
86 | private llvm::TrailingObjects<Operation, detail::OperandStorage, |
87 | detail::OpProperties, BlockOperand, Region, |
88 | OpOperand> { |
89 | public: |
90 | /// Create a new Operation with the specific fields. This constructor |
91 | /// populates the provided attribute list with default attributes if |
92 | /// necessary. |
93 | static Operation *create(Location location, OperationName name, |
94 | TypeRange resultTypes, ValueRange operands, |
95 | NamedAttrList &&attributes, |
96 | OpaqueProperties properties, BlockRange successors, |
97 | unsigned numRegions); |
98 | |
99 | /// Create a new Operation with the specific fields. This constructor uses an |
100 | /// existing attribute dictionary to avoid uniquing a list of attributes. |
101 | static Operation *create(Location location, OperationName name, |
102 | TypeRange resultTypes, ValueRange operands, |
103 | DictionaryAttr attributes, |
104 | OpaqueProperties properties, BlockRange successors, |
105 | unsigned numRegions); |
106 | |
107 | /// Create a new Operation from the fields stored in `state`. |
108 | static Operation *create(const OperationState &state); |
109 | |
110 | /// Create a new Operation with the specific fields. |
111 | static Operation *create(Location location, OperationName name, |
112 | TypeRange resultTypes, ValueRange operands, |
113 | NamedAttrList &&attributes, |
114 | OpaqueProperties properties, |
115 | BlockRange successors = {}, |
116 | RegionRange regions = {}); |
117 | |
118 | /// The name of an operation is the key identifier for it. |
119 | OperationName getName() { return name; } |
120 | |
121 | /// If this operation has a registered operation description, return it. |
122 | /// Otherwise return std::nullopt. |
123 | std::optional<RegisteredOperationName> getRegisteredInfo() { |
124 | return getName().getRegisteredInfo(); |
125 | } |
126 | |
127 | /// Returns true if this operation has a registered operation description, |
128 | /// otherwise false. |
129 | bool isRegistered() { return getName().isRegistered(); } |
130 | |
131 | /// Remove this operation from its parent block and delete it. |
132 | void erase(); |
133 | |
134 | /// Remove the operation from its parent block, but don't delete it. |
135 | void remove(); |
136 | |
137 | /// Class encompassing various options related to cloning an operation. Users |
138 | /// of this class should pass it to Operation's 'clone' methods. |
139 | /// Current options include: |
140 | /// * Whether cloning should recursively traverse into the regions of the |
141 | /// operation or not. |
142 | /// * Whether cloning should also clone the operands of the operation. |
143 | class CloneOptions { |
144 | public: |
145 | /// Default constructs an option with all flags set to false. That means all |
146 | /// parts of an operation that may optionally not be cloned, are not cloned. |
147 | CloneOptions(); |
148 | |
149 | /// Constructs an instance with the clone regions and clone operands flags |
150 | /// set accordingly. |
151 | CloneOptions(bool cloneRegions, bool cloneOperands); |
152 | |
153 | /// Returns an instance with all flags set to true. This is the default |
154 | /// when using the clone method and clones all parts of the operation. |
155 | static CloneOptions all(); |
156 | |
157 | /// Configures whether cloning should traverse into any of the regions of |
158 | /// the operation. If set to true, the operation's regions are recursively |
159 | /// cloned. If set to false, cloned operations will have the same number of |
160 | /// regions, but they will be empty. |
161 | /// Cloning of nested operations in the operation's regions are currently |
162 | /// unaffected by other flags. |
163 | CloneOptions &cloneRegions(bool enable = true); |
164 | |
165 | /// Returns whether regions of the operation should be cloned as well. |
166 | bool shouldCloneRegions() const { return cloneRegionsFlag; } |
167 | |
168 | /// Configures whether operation' operands should be cloned. Otherwise the |
169 | /// resulting clones will simply have zero operands. |
170 | CloneOptions &cloneOperands(bool enable = true); |
171 | |
172 | /// Returns whether operands should be cloned as well. |
173 | bool shouldCloneOperands() const { return cloneOperandsFlag; } |
174 | |
175 | private: |
176 | /// Whether regions should be cloned. |
177 | bool cloneRegionsFlag : 1; |
178 | /// Whether operands should be cloned. |
179 | bool cloneOperandsFlag : 1; |
180 | }; |
181 | |
182 | /// Create a deep copy of this operation, remapping any operands that use |
183 | /// values outside of the operation using the map that is provided (leaving |
184 | /// them alone if no entry is present). Replaces references to cloned |
185 | /// sub-operations to the corresponding operation that is copied, and adds |
186 | /// those mappings to the map. |
187 | /// Optionally, one may configure what parts of the operation to clone using |
188 | /// the options parameter. |
189 | /// |
190 | /// Calling this method from multiple threads is generally safe if through the |
191 | /// process of cloning no new uses of 'Value's from outside the operation are |
192 | /// created. Cloning an isolated-from-above operation with no operands, such |
193 | /// as top level function operations, is therefore always safe. Using the |
194 | /// mapper, it is possible to avoid adding uses to outside operands by |
195 | /// remapping them to 'Value's owned by the caller thread. |
196 | Operation *clone(IRMapping &mapper, |
197 | CloneOptions options = CloneOptions::all()); |
198 | Operation *clone(CloneOptions options = CloneOptions::all()); |
199 | |
200 | /// Create a partial copy of this operation without traversing into attached |
201 | /// regions. The new operation will have the same number of regions as the |
202 | /// original one, but they will be left empty. |
203 | /// Operands are remapped using `mapper` (if present), and `mapper` is updated |
204 | /// to contain the results. |
205 | Operation *cloneWithoutRegions(IRMapping &mapper); |
206 | |
207 | /// Create a partial copy of this operation without traversing into attached |
208 | /// regions. The new operation will have the same number of regions as the |
209 | /// original one, but they will be left empty. |
210 | Operation *cloneWithoutRegions(); |
211 | |
212 | /// Returns the operation block that contains this operation. |
213 | Block *getBlock() { return block; } |
214 | |
215 | /// Return the context this operation is associated with. |
216 | MLIRContext *getContext() { return location->getContext(); } |
217 | |
218 | /// Return the dialect this operation is associated with, or nullptr if the |
219 | /// associated dialect is not loaded. |
220 | Dialect *getDialect() { return getName().getDialect(); } |
221 | |
222 | /// The source location the operation was defined or derived from. |
223 | Location getLoc() { return location; } |
224 | |
225 | /// Set the source location the operation was defined or derived from. |
226 | void setLoc(Location loc) { location = loc; } |
227 | |
228 | /// Returns the region to which the instruction belongs. Returns nullptr if |
229 | /// the instruction is unlinked. |
230 | Region *getParentRegion() { return block ? block->getParent() : nullptr; } |
231 | |
232 | /// Returns the closest surrounding operation that contains this operation |
233 | /// or nullptr if this is a top-level operation. |
234 | Operation *getParentOp() { return block ? block->getParentOp() : nullptr; } |
235 | |
236 | /// Return the closest surrounding parent operation that is of type 'OpTy'. |
237 | template <typename OpTy> |
238 | OpTy getParentOfType() { |
239 | auto *op = this; |
240 | while ((op = op->getParentOp())) |
241 | if (auto parentOp = dyn_cast<OpTy>(op)) |
242 | return parentOp; |
243 | return OpTy(); |
244 | } |
245 | |
246 | /// Returns the closest surrounding parent operation with trait `Trait`. |
247 | template <template <typename T> class Trait> |
248 | Operation *getParentWithTrait() { |
249 | Operation *op = this; |
250 | while ((op = op->getParentOp())) |
251 | if (op->hasTrait<Trait>()) |
252 | return op; |
253 | return nullptr; |
254 | } |
255 | |
256 | /// Return true if this operation is a proper ancestor of the `other` |
257 | /// operation. |
258 | bool isProperAncestor(Operation *other); |
259 | |
260 | /// Return true if this operation is an ancestor of the `other` operation. An |
261 | /// operation is considered as its own ancestor, use `isProperAncestor` to |
262 | /// avoid this. |
263 | bool isAncestor(Operation *other) { |
264 | return this == other || isProperAncestor(other); |
265 | } |
266 | |
267 | /// Replace any uses of 'from' with 'to' within this operation. |
268 | void replaceUsesOfWith(Value from, Value to); |
269 | |
270 | /// Replace all uses of results of this operation with the provided 'values'. |
271 | template <typename ValuesT> |
272 | void replaceAllUsesWith(ValuesT &&values) { |
273 | getResults().replaceAllUsesWith(std::forward<ValuesT>(values)); |
274 | } |
275 | |
276 | /// Replace uses of results of this operation with the provided `values` if |
277 | /// the given callback returns true. |
278 | template <typename ValuesT> |
279 | void replaceUsesWithIf(ValuesT &&values, |
280 | function_ref<bool(OpOperand &)> shouldReplace) { |
281 | getResults().replaceUsesWithIf(std::forward<ValuesT>(values), |
282 | shouldReplace); |
283 | } |
284 | |
285 | /// Destroys this operation and its subclass data. |
286 | void destroy(); |
287 | |
288 | /// This drops all operand uses from this operation, which is an essential |
289 | /// step in breaking cyclic dependences between references when they are to |
290 | /// be deleted. |
291 | void dropAllReferences(); |
292 | |
293 | /// Drop uses of all values defined by this operation or its nested regions. |
294 | void dropAllDefinedValueUses(); |
295 | |
296 | /// Unlink this operation from its current block and insert it right before |
297 | /// `existingOp` which may be in the same or another block in the same |
298 | /// function. |
299 | void moveBefore(Operation *existingOp); |
300 | |
301 | /// Unlink this operation from its current block and insert it right before |
302 | /// `iterator` in the specified block. |
303 | void moveBefore(Block *block, llvm::iplist<Operation>::iterator iterator); |
304 | |
305 | /// Unlink this operation from its current block and insert it right after |
306 | /// `existingOp` which may be in the same or another block in the same |
307 | /// function. |
308 | void moveAfter(Operation *existingOp); |
309 | |
310 | /// Unlink this operation from its current block and insert it right after |
311 | /// `iterator` in the specified block. |
312 | void moveAfter(Block *block, llvm::iplist<Operation>::iterator iterator); |
313 | |
314 | /// Given an operation 'other' that is within the same parent block, return |
315 | /// whether the current operation is before 'other' in the operation list |
316 | /// of the parent block. |
317 | /// Note: This function has an average complexity of O(1), but worst case may |
318 | /// take O(N) where N is the number of operations within the parent block. |
319 | bool isBeforeInBlock(Operation *other); |
320 | |
321 | void print(raw_ostream &os, const OpPrintingFlags &flags = std::nullopt); |
322 | void print(raw_ostream &os, AsmState &state); |
323 | void dump(); |
324 | |
325 | //===--------------------------------------------------------------------===// |
326 | // Operands |
327 | //===--------------------------------------------------------------------===// |
328 | |
329 | /// Replace the current operands of this operation with the ones provided in |
330 | /// 'operands'. |
331 | void setOperands(ValueRange operands); |
332 | |
333 | /// Replace the operands beginning at 'start' and ending at 'start' + 'length' |
334 | /// with the ones provided in 'operands'. 'operands' may be smaller or larger |
335 | /// than the range pointed to by 'start'+'length'. |
336 | void setOperands(unsigned start, unsigned length, ValueRange operands); |
337 | |
338 | /// Insert the given operands into the operand list at the given 'index'. |
339 | void insertOperands(unsigned index, ValueRange operands); |
340 | |
341 | unsigned getNumOperands() { |
342 | return LLVM_LIKELY(hasOperandStorage)__builtin_expect((bool)(hasOperandStorage), true) ? getOperandStorage().size() : 0; |
343 | } |
344 | |
345 | Value getOperand(unsigned idx) { return getOpOperand(idx).get(); } |
346 | void setOperand(unsigned idx, Value value) { |
347 | return getOpOperand(idx).set(value); |
348 | } |
349 | |
350 | /// Erase the operand at position `idx`. |
351 | void eraseOperand(unsigned idx) { eraseOperands(idx); } |
352 | |
353 | /// Erase the operands starting at position `idx` and ending at position |
354 | /// 'idx'+'length'. |
355 | void eraseOperands(unsigned idx, unsigned length = 1) { |
356 | getOperandStorage().eraseOperands(idx, length); |
357 | } |
358 | |
359 | /// Erases the operands that have their corresponding bit set in |
360 | /// `eraseIndices` and removes them from the operand list. |
361 | void eraseOperands(const BitVector &eraseIndices) { |
362 | getOperandStorage().eraseOperands(eraseIndices); |
363 | } |
364 | |
365 | // Support operand iteration. |
366 | using operand_range = OperandRange; |
367 | using operand_iterator = operand_range::iterator; |
368 | |
369 | operand_iterator operand_begin() { return getOperands().begin(); } |
370 | operand_iterator operand_end() { return getOperands().end(); } |
371 | |
372 | /// Returns an iterator on the underlying Value's. |
373 | operand_range getOperands() { |
374 | MutableArrayRef<OpOperand> operands = getOpOperands(); |
375 | return OperandRange(operands.data(), operands.size()); |
376 | } |
377 | |
378 | MutableArrayRef<OpOperand> getOpOperands() { |
379 | return LLVM_LIKELY(hasOperandStorage)__builtin_expect((bool)(hasOperandStorage), true) ? getOperandStorage().getOperands() |
380 | : MutableArrayRef<OpOperand>(); |
381 | } |
382 | |
383 | OpOperand &getOpOperand(unsigned idx) { |
384 | return getOperandStorage().getOperands()[idx]; |
385 | } |
386 | |
387 | // Support operand type iteration. |
388 | using operand_type_iterator = operand_range::type_iterator; |
389 | using operand_type_range = operand_range::type_range; |
390 | operand_type_iterator operand_type_begin() { return operand_begin(); } |
391 | operand_type_iterator operand_type_end() { return operand_end(); } |
392 | operand_type_range getOperandTypes() { return getOperands().getTypes(); } |
393 | |
394 | //===--------------------------------------------------------------------===// |
395 | // Results |
396 | //===--------------------------------------------------------------------===// |
397 | |
398 | /// Return the number of results held by this operation. |
399 | unsigned getNumResults() { return numResults; } |
400 | |
401 | /// Get the 'idx'th result of this operation. |
402 | OpResult getResult(unsigned idx) { return OpResult(getOpResultImpl(idx)); } |
403 | |
404 | /// Support result iteration. |
405 | using result_range = ResultRange; |
406 | using result_iterator = result_range::iterator; |
407 | |
408 | result_iterator result_begin() { return getResults().begin(); } |
409 | result_iterator result_end() { return getResults().end(); } |
410 | result_range getResults() { |
411 | return numResults == 0 ? result_range(nullptr, 0) |
412 | : result_range(getInlineOpResult(0), numResults); |
413 | } |
414 | |
415 | result_range getOpResults() { return getResults(); } |
416 | OpResult getOpResult(unsigned idx) { return getResult(idx); } |
417 | |
418 | /// Support result type iteration. |
419 | using result_type_iterator = result_range::type_iterator; |
420 | using result_type_range = result_range::type_range; |
421 | result_type_iterator result_type_begin() { return getResultTypes().begin(); } |
422 | result_type_iterator result_type_end() { return getResultTypes().end(); } |
423 | result_type_range getResultTypes() { return getResults().getTypes(); } |
424 | |
425 | //===--------------------------------------------------------------------===// |
426 | // Attributes |
427 | //===--------------------------------------------------------------------===// |
428 | |
429 | // Operations may optionally carry a list of attributes that associate |
430 | // constants to names. Attributes may be dynamically added and removed over |
431 | // the lifetime of an operation. |
432 | |
433 | /// Access an inherent attribute by name: returns an empty optional if there |
434 | /// is no inherent attribute with this name. |
435 | /// |
436 | /// This method is available as a transient facility in the migration process |
437 | /// to use Properties instead. |
438 | std::optional<Attribute> getInherentAttr(StringRef name); |
439 | |
440 | /// Set an inherent attribute by name. |
441 | /// |
442 | /// This method is available as a transient facility in the migration process |
443 | /// to use Properties instead. |
444 | void setInherentAttr(StringAttr name, Attribute value); |
445 | |
446 | /// Access a discardable attribute by name, returns an null Attribute if the |
447 | /// discardable attribute does not exist. |
448 | Attribute getDiscardableAttr(StringRef name) { return attrs.get(name); } |
449 | |
450 | /// Access a discardable attribute by name, returns an null Attribute if the |
451 | /// discardable attribute does not exist. |
452 | Attribute getDiscardableAttr(StringAttr name) { return attrs.get(name); } |
453 | |
454 | /// Set a discardable attribute by name. |
455 | void setDiscardableAttr(StringAttr name, Attribute value) { |
456 | NamedAttrList attributes(attrs); |
457 | if (attributes.set(name, value) != value) |
458 | attrs = attributes.getDictionary(getContext()); |
459 | } |
460 | |
461 | /// Return all of the discardable attributes on this operation. |
462 | ArrayRef<NamedAttribute> getDiscardableAttrs() { return attrs.getValue(); } |
463 | |
464 | /// Return all of the discardable attributes on this operation as a |
465 | /// DictionaryAttr. |
466 | DictionaryAttr getDiscardableAttrDictionary() { return attrs; } |
467 | |
468 | /// Return all of the attributes on this operation. |
469 | ArrayRef<NamedAttribute> getAttrs() { |
470 | if (!getPropertiesStorage()) |
471 | return getDiscardableAttrs(); |
472 | return getAttrDictionary().getValue(); |
473 | } |
474 | |
475 | /// Return all of the attributes on this operation as a DictionaryAttr. |
476 | DictionaryAttr getAttrDictionary(); |
477 | |
478 | /// Set the attributes from a dictionary on this operation. |
479 | /// These methods are expensive: if the dictionnary only contains discardable |
480 | /// attributes, `setDiscardableAttrs` is more efficient. |
481 | void setAttrs(DictionaryAttr newAttrs); |
482 | void setAttrs(ArrayRef<NamedAttribute> newAttrs); |
483 | /// Set the discardable attribute dictionary on this operation. |
484 | void setDiscardableAttrs(DictionaryAttr newAttrs) { |
485 | assert(newAttrs && "expected valid attribute dictionary")(static_cast <bool> (newAttrs && "expected valid attribute dictionary" ) ? void (0) : __assert_fail ("newAttrs && \"expected valid attribute dictionary\"" , "mlir/include/mlir/IR/Operation.h", 485, __extension__ __PRETTY_FUNCTION__ )); |
486 | attrs = newAttrs; |
487 | } |
488 | void setDiscardableAttrs(ArrayRef<NamedAttribute> newAttrs) { |
489 | setDiscardableAttrs(DictionaryAttr::get(getContext(), newAttrs)); |
490 | } |
491 | |
492 | /// Return the specified attribute if present, null otherwise. |
493 | /// These methods are expensive: if the dictionnary only contains discardable |
494 | /// attributes, `getDiscardableAttr` is more efficient. |
495 | Attribute getAttr(StringAttr name) { |
496 | if (getPropertiesStorageSize()) { |
497 | if (std::optional<Attribute> inherentAttr = getInherentAttr(name)) |
498 | return *inherentAttr; |
499 | } |
500 | return attrs.get(name); |
501 | } |
502 | Attribute getAttr(StringRef name) { |
503 | if (getPropertiesStorageSize()) { |
504 | if (std::optional<Attribute> inherentAttr = getInherentAttr(name)) |
505 | return *inherentAttr; |
506 | } |
507 | return attrs.get(name); |
508 | } |
509 | |
510 | template <typename AttrClass> |
511 | AttrClass getAttrOfType(StringAttr name) { |
512 | return getAttr(name).dyn_cast_or_null<AttrClass>(); |
513 | } |
514 | template <typename AttrClass> |
515 | AttrClass getAttrOfType(StringRef name) { |
516 | return getAttr(name).dyn_cast_or_null<AttrClass>(); |
517 | } |
518 | |
519 | /// Return true if the operation has an attribute with the provided name, |
520 | /// false otherwise. |
521 | bool hasAttr(StringAttr name) { |
522 | if (getPropertiesStorageSize()) { |
523 | if (std::optional<Attribute> inherentAttr = getInherentAttr(name)) |
524 | return (bool)*inherentAttr; |
525 | } |
526 | return attrs.contains(name); |
527 | } |
528 | bool hasAttr(StringRef name) { |
529 | if (getPropertiesStorageSize()) { |
530 | if (std::optional<Attribute> inherentAttr = getInherentAttr(name)) |
531 | return (bool)*inherentAttr; |
532 | } |
533 | return attrs.contains(name); |
534 | } |
535 | template <typename AttrClass, typename NameT> |
536 | bool hasAttrOfType(NameT &&name) { |
537 | return static_cast<bool>( |
538 | getAttrOfType<AttrClass>(std::forward<NameT>(name))); |
539 | } |
540 | |
541 | /// If the an attribute exists with the specified name, change it to the new |
542 | /// value. Otherwise, add a new attribute with the specified name/value. |
543 | void setAttr(StringAttr name, Attribute value) { |
544 | if (getPropertiesStorageSize()) { |
545 | if (std::optional<Attribute> inherentAttr = getInherentAttr(name)) { |
546 | setInherentAttr(name, value); |
547 | return; |
548 | } |
549 | } |
550 | NamedAttrList attributes(attrs); |
551 | if (attributes.set(name, value) != value) |
552 | attrs = attributes.getDictionary(getContext()); |
553 | } |
554 | void setAttr(StringRef name, Attribute value) { |
555 | setAttr(StringAttr::get(getContext(), name), value); |
556 | } |
557 | |
558 | /// Remove the attribute with the specified name if it exists. Return the |
559 | /// attribute that was erased, or nullptr if there was no attribute with such |
560 | /// name. |
561 | Attribute removeAttr(StringAttr name) { |
562 | if (getPropertiesStorageSize()) { |
563 | if (std::optional<Attribute> inherentAttr = getInherentAttr(name)) { |
564 | setInherentAttr(name, {}); |
565 | return *inherentAttr; |
566 | } |
567 | } |
568 | NamedAttrList attributes(attrs); |
569 | Attribute removedAttr = attributes.erase(name); |
570 | if (removedAttr) |
571 | attrs = attributes.getDictionary(getContext()); |
572 | return removedAttr; |
573 | } |
574 | Attribute removeAttr(StringRef name) { |
575 | return removeAttr(StringAttr::get(getContext(), name)); |
576 | } |
577 | |
578 | /// A utility iterator that filters out non-dialect attributes. |
579 | class dialect_attr_iterator |
580 | : public llvm::filter_iterator<ArrayRef<NamedAttribute>::iterator, |
581 | bool (*)(NamedAttribute)> { |
582 | static bool filter(NamedAttribute attr) { |
583 | // Dialect attributes are prefixed by the dialect name, like operations. |
584 | return attr.getName().strref().count('.'); |
585 | } |
586 | |
587 | explicit dialect_attr_iterator(ArrayRef<NamedAttribute>::iterator it, |
588 | ArrayRef<NamedAttribute>::iterator end) |
589 | : llvm::filter_iterator<ArrayRef<NamedAttribute>::iterator, |
590 | bool (*)(NamedAttribute)>(it, end, &filter) {} |
591 | |
592 | // Allow access to the constructor. |
593 | friend Operation; |
594 | }; |
595 | using dialect_attr_range = iterator_range<dialect_attr_iterator>; |
596 | |
597 | /// Return a range corresponding to the dialect attributes for this operation. |
598 | dialect_attr_range getDialectAttrs() { |
599 | auto attrs = getAttrs(); |
600 | return {dialect_attr_iterator(attrs.begin(), attrs.end()), |
601 | dialect_attr_iterator(attrs.end(), attrs.end())}; |
602 | } |
603 | dialect_attr_iterator dialect_attr_begin() { |
604 | auto attrs = getAttrs(); |
605 | return dialect_attr_iterator(attrs.begin(), attrs.end()); |
606 | } |
607 | dialect_attr_iterator dialect_attr_end() { |
608 | auto attrs = getAttrs(); |
609 | return dialect_attr_iterator(attrs.end(), attrs.end()); |
610 | } |
611 | |
612 | /// Set the dialect attributes for this operation, and preserve all inherent. |
613 | template <typename DialectAttrT> |
614 | void setDialectAttrs(DialectAttrT &&dialectAttrs) { |
615 | NamedAttrList attrs; |
616 | attrs.append(std::begin(dialectAttrs), std::end(dialectAttrs)); |
617 | for (auto attr : getAttrs()) |
618 | if (!attr.getName().strref().contains('.')) |
619 | attrs.push_back(attr); |
620 | setAttrs(attrs.getDictionary(getContext())); |
621 | } |
622 | |
623 | /// Sets default attributes on unset attributes. |
624 | void populateDefaultAttrs() { |
625 | NamedAttrList attrs(getAttrDictionary()); |
626 | name.populateDefaultAttrs(attrs); |
627 | setAttrs(attrs.getDictionary(getContext())); |
628 | } |
629 | |
630 | //===--------------------------------------------------------------------===// |
631 | // Blocks |
632 | //===--------------------------------------------------------------------===// |
633 | |
634 | /// Returns the number of regions held by this operation. |
635 | unsigned getNumRegions() { return numRegions; } |
636 | |
637 | /// Returns the regions held by this operation. |
638 | MutableArrayRef<Region> getRegions() { |
639 | // Check the count first, as computing the trailing objects can be slow. |
640 | if (numRegions == 0) |
641 | return MutableArrayRef<Region>(); |
642 | |
643 | auto *regions = getTrailingObjects<Region>(); |
644 | return {regions, numRegions}; |
645 | } |
646 | |
647 | /// Returns the region held by this operation at position 'index'. |
648 | Region &getRegion(unsigned index) { |
649 | assert(index < numRegions && "invalid region index")(static_cast <bool> (index < numRegions && "invalid region index" ) ? void (0) : __assert_fail ("index < numRegions && \"invalid region index\"" , "mlir/include/mlir/IR/Operation.h", 649, __extension__ __PRETTY_FUNCTION__ )); |
650 | return getRegions()[index]; |
651 | } |
652 | |
653 | //===--------------------------------------------------------------------===// |
654 | // Successors |
655 | //===--------------------------------------------------------------------===// |
656 | |
657 | MutableArrayRef<BlockOperand> getBlockOperands() { |
658 | return {getTrailingObjects<BlockOperand>(), numSuccs}; |
659 | } |
660 | |
661 | // Successor iteration. |
662 | using succ_iterator = SuccessorRange::iterator; |
663 | succ_iterator successor_begin() { return getSuccessors().begin(); } |
664 | succ_iterator successor_end() { return getSuccessors().end(); } |
665 | SuccessorRange getSuccessors() { return SuccessorRange(this); } |
666 | |
667 | bool hasSuccessors() { return numSuccs != 0; } |
668 | unsigned getNumSuccessors() { return numSuccs; } |
669 | |
670 | Block *getSuccessor(unsigned index) { |
671 | assert(index < getNumSuccessors())(static_cast <bool> (index < getNumSuccessors()) ? void (0) : __assert_fail ("index < getNumSuccessors()", "mlir/include/mlir/IR/Operation.h" , 671, __extension__ __PRETTY_FUNCTION__)); |
672 | return getBlockOperands()[index].get(); |
673 | } |
674 | void setSuccessor(Block *block, unsigned index); |
675 | |
676 | //===--------------------------------------------------------------------===// |
677 | // Accessors for various properties of operations |
678 | //===--------------------------------------------------------------------===// |
679 | |
680 | /// Attempt to fold this operation with the specified constant operand values |
681 | /// - the elements in "operands" will correspond directly to the operands of |
682 | /// the operation, but may be null if non-constant. If folding is successful, |
683 | /// this fills in the `results` vector. If not, `results` is unspecified. |
684 | LogicalResult fold(ArrayRef<Attribute> operands, |
685 | SmallVectorImpl<OpFoldResult> &results); |
686 | |
687 | /// Returns true if the operation was registered with a particular trait, e.g. |
688 | /// hasTrait<OperandsAreSignlessIntegerLike>(). |
689 | template <template <typename T> class Trait> |
690 | bool hasTrait() { |
691 | return name.hasTrait<Trait>(); |
692 | } |
693 | |
694 | /// Returns true if the operation *might* have the provided trait. This |
695 | /// means that either the operation is unregistered, or it was registered with |
696 | /// the provide trait. |
697 | template <template <typename T> class Trait> |
698 | bool mightHaveTrait() { |
699 | return name.mightHaveTrait<Trait>(); |
700 | } |
701 | |
702 | //===--------------------------------------------------------------------===// |
703 | // Operation Walkers |
704 | //===--------------------------------------------------------------------===// |
705 | |
706 | /// Walk the operation by calling the callback for each nested operation |
707 | /// (including this one), block or region, depending on the callback provided. |
708 | /// The order in which regions, blocks and operations at the same nesting |
709 | /// level are visited (e.g., lexicographical or reverse lexicographical order) |
710 | /// is determined by 'Iterator'. The walk order for enclosing regions, blocks |
711 | /// and operations with respect to their nested ones is specified by 'Order' |
712 | /// (post-order by default). A callback on a block or operation is allowed to |
713 | /// erase that block or operation if either: |
714 | /// * the walk is in post-order, or |
715 | /// * the walk is in pre-order and the walk is skipped after the erasure. |
716 | /// |
717 | /// The callback method can take any of the following forms: |
718 | /// void(Operation*) : Walk all operations opaquely. |
719 | /// * op->walk([](Operation *nestedOp) { ...}); |
720 | /// void(OpT) : Walk all operations of the given derived type. |
721 | /// * op->walk([](ReturnOp returnOp) { ...}); |
722 | /// WalkResult(Operation*|OpT) : Walk operations, but allow for |
723 | /// interruption/skipping. |
724 | /// * op->walk([](... op) { |
725 | /// // Skip the walk of this op based on some invariant. |
726 | /// if (some_invariant) |
727 | /// return WalkResult::skip(); |
728 | /// // Interrupt, i.e cancel, the walk based on some invariant. |
729 | /// if (another_invariant) |
730 | /// return WalkResult::interrupt(); |
731 | /// return WalkResult::advance(); |
732 | /// }); |
733 | template <WalkOrder Order = WalkOrder::PostOrder, |
734 | typename Iterator = ForwardIterator, typename FnT, |
735 | typename RetT = detail::walkResultType<FnT>> |
736 | std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 1, |
737 | RetT> |
738 | walk(FnT &&callback) { |
739 | return detail::walk<Order, Iterator>(this, std::forward<FnT>(callback)); |
740 | } |
741 | |
742 | /// Generic walker with a stage aware callback. Walk the operation by calling |
743 | /// the callback for each nested operation (including this one) N+1 times, |
744 | /// where N is the number of regions attached to that operation. |
745 | /// |
746 | /// The callback method can take any of the following forms: |
747 | /// void(Operation *, const WalkStage &) : Walk all operation opaquely |
748 | /// * op->walk([](Operation *nestedOp, const WalkStage &stage) { ...}); |
749 | /// void(OpT, const WalkStage &) : Walk all operations of the given derived |
750 | /// type. |
751 | /// * op->walk([](ReturnOp returnOp, const WalkStage &stage) { ...}); |
752 | /// WalkResult(Operation*|OpT, const WalkStage &stage) : Walk operations, |
753 | /// but allow for interruption/skipping. |
754 | /// * op->walk([](... op, const WalkStage &stage) { |
755 | /// // Skip the walk of this op based on some invariant. |
756 | /// if (some_invariant) |
757 | /// return WalkResult::skip(); |
758 | /// // Interrupt, i.e cancel, the walk based on some invariant. |
759 | /// if (another_invariant) |
760 | /// return WalkResult::interrupt(); |
761 | /// return WalkResult::advance(); |
762 | /// }); |
763 | template <typename FnT, typename RetT = detail::walkResultType<FnT>> |
764 | std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 2, |
765 | RetT> |
766 | walk(FnT &&callback) { |
767 | return detail::walk(this, std::forward<FnT>(callback)); |
768 | } |
769 | |
770 | //===--------------------------------------------------------------------===// |
771 | // Uses |
772 | //===--------------------------------------------------------------------===// |
773 | |
774 | /// Drop all uses of results of this operation. |
775 | void dropAllUses() { |
776 | for (OpResult result : getOpResults()) |
777 | result.dropAllUses(); |
778 | } |
779 | |
780 | using use_iterator = result_range::use_iterator; |
781 | using use_range = result_range::use_range; |
782 | |
783 | use_iterator use_begin() { return getResults().use_begin(); } |
784 | use_iterator use_end() { return getResults().use_end(); } |
785 | |
786 | /// Returns a range of all uses, which is useful for iterating over all uses. |
787 | use_range getUses() { return getResults().getUses(); } |
788 | |
789 | /// Returns true if this operation has exactly one use. |
790 | bool hasOneUse() { return llvm::hasSingleElement(getUses()); } |
791 | |
792 | /// Returns true if this operation has no uses. |
793 | bool use_empty() { return getResults().use_empty(); } |
794 | |
795 | /// Returns true if the results of this operation are used outside of the |
796 | /// given block. |
797 | bool isUsedOutsideOfBlock(Block *block) { |
798 | return llvm::any_of(getOpResults(), [block](OpResult result) { |
799 | return result.isUsedOutsideOfBlock(block); |
800 | }); |
801 | } |
802 | |
803 | //===--------------------------------------------------------------------===// |
804 | // Users |
805 | //===--------------------------------------------------------------------===// |
806 | |
807 | using user_iterator = ValueUserIterator<use_iterator, OpOperand>; |
808 | using user_range = iterator_range<user_iterator>; |
809 | |
810 | user_iterator user_begin() { return user_iterator(use_begin()); } |
811 | user_iterator user_end() { return user_iterator(use_end()); } |
812 | |
813 | /// Returns a range of all users. |
814 | user_range getUsers() { return {user_begin(), user_end()}; } |
815 | |
816 | //===--------------------------------------------------------------------===// |
817 | // Other |
818 | //===--------------------------------------------------------------------===// |
819 | |
820 | /// Emit an error with the op name prefixed, like "'dim' op " which is |
821 | /// convenient for verifiers. |
822 | InFlightDiagnostic emitOpError(const Twine &message = {}); |
823 | |
824 | /// Emit an error about fatal conditions with this operation, reporting up to |
825 | /// any diagnostic handlers that may be listening. |
826 | InFlightDiagnostic emitError(const Twine &message = {}); |
827 | |
828 | /// Emit a warning about this operation, reporting up to any diagnostic |
829 | /// handlers that may be listening. |
830 | InFlightDiagnostic emitWarning(const Twine &message = {}); |
831 | |
832 | /// Emit a remark about this operation, reporting up to any diagnostic |
833 | /// handlers that may be listening. |
834 | InFlightDiagnostic emitRemark(const Twine &message = {}); |
835 | |
836 | /// Returns the properties storage size. |
837 | int getPropertiesStorageSize() const { |
838 | return ((int)propertiesStorageSize) * 8; |
839 | } |
840 | /// Returns the properties storage. |
841 | OpaqueProperties getPropertiesStorage() { |
842 | if (propertiesStorageSize) |
843 | return { |
844 | reinterpret_cast<void *>(getTrailingObjects<detail::OpProperties>())}; |
845 | return {nullptr}; |
846 | } |
847 | OpaqueProperties getPropertiesStorage() const { |
848 | if (propertiesStorageSize) |
849 | return {reinterpret_cast<void *>(const_cast<detail::OpProperties *>( |
850 | getTrailingObjects<detail::OpProperties>()))}; |
851 | return {nullptr}; |
852 | } |
853 | |
854 | /// Return the properties converted to an attribute. |
855 | /// This is expensive, and mostly useful when dealing with unregistered |
856 | /// operation. Returns an empty attribute if no properties are present. |
857 | Attribute getPropertiesAsAttribute(); |
858 | |
859 | /// Set the properties from the provided attribute. |
860 | /// This is an expensive operation that can fail if the attribute is not |
861 | /// matching the expectations of the properties for this operation. This is |
862 | /// mostly useful for unregistered operations or used when parsing the |
863 | /// generic format. An optional diagnostic can be passed in for richer errors. |
864 | LogicalResult setPropertiesFromAttribute(Attribute attr, |
865 | InFlightDiagnostic *diagnostic); |
866 | |
867 | /// Copy properties from an existing other properties object. The two objects |
868 | /// must be the same type. |
869 | void copyProperties(OpaqueProperties rhs); |
870 | |
871 | /// Compute a hash for the op properties (if any). |
872 | llvm::hash_code hashProperties(); |
873 | |
874 | private: |
875 | //===--------------------------------------------------------------------===// |
876 | // Ordering |
877 | //===--------------------------------------------------------------------===// |
878 | |
879 | /// This value represents an invalid index ordering for an operation within a |
880 | /// block. |
881 | static constexpr unsigned kInvalidOrderIdx = -1; |
882 | |
883 | /// This value represents the stride to use when computing a new order for an |
884 | /// operation. |
885 | static constexpr unsigned kOrderStride = 5; |
886 | |
887 | /// Update the order index of this operation of this operation if necessary, |
888 | /// potentially recomputing the order of the parent block. |
889 | void updateOrderIfNecessary(); |
890 | |
891 | /// Returns true if this operation has a valid order. |
892 | bool hasValidOrder() { return orderIndex != kInvalidOrderIdx; } |
893 | |
894 | private: |
895 | Operation(Location location, OperationName name, unsigned numResults, |
896 | unsigned numSuccessors, unsigned numRegions, |
897 | int propertiesStorageSize, DictionaryAttr attributes, |
898 | OpaqueProperties properties, bool hasOperandStorage); |
899 | |
900 | // Operations are deleted through the destroy() member because they are |
901 | // allocated with malloc. |
902 | ~Operation(); |
903 | |
904 | /// Returns the additional size necessary for allocating the given objects |
905 | /// before an Operation in-memory. |
906 | static size_t prefixAllocSize(unsigned numOutOfLineResults, |
907 | unsigned numInlineResults) { |
908 | return sizeof(detail::OutOfLineOpResult) * numOutOfLineResults + |
909 | sizeof(detail::InlineOpResult) * numInlineResults; |
910 | } |
911 | /// Returns the additional size allocated before this Operation in-memory. |
912 | size_t prefixAllocSize() { |
913 | unsigned numResults = getNumResults(); |
914 | unsigned numOutOfLineResults = OpResult::getNumTrailing(numResults); |
915 | unsigned numInlineResults = OpResult::getNumInline(numResults); |
916 | return prefixAllocSize(numOutOfLineResults, numInlineResults); |
917 | } |
918 | |
919 | /// Returns the operand storage object. |
920 | detail::OperandStorage &getOperandStorage() { |
921 | assert(hasOperandStorage && "expected operation to have operand storage")(static_cast <bool> (hasOperandStorage && "expected operation to have operand storage" ) ? void (0) : __assert_fail ("hasOperandStorage && \"expected operation to have operand storage\"" , "mlir/include/mlir/IR/Operation.h", 921, __extension__ __PRETTY_FUNCTION__ )); |
922 | return *getTrailingObjects<detail::OperandStorage>(); |
923 | } |
924 | |
925 | /// Returns a pointer to the use list for the given out-of-line result. |
926 | detail::OutOfLineOpResult *getOutOfLineOpResult(unsigned resultNumber) { |
927 | // Out-of-line results are stored in reverse order after (before in memory) |
928 | // the inline results. |
929 | return reinterpret_cast<detail::OutOfLineOpResult *>(getInlineOpResult( |
930 | detail::OpResultImpl::getMaxInlineResults() - 1)) - |
931 | ++resultNumber; |
932 | } |
933 | |
934 | /// Returns a pointer to the use list for the given inline result. |
935 | detail::InlineOpResult *getInlineOpResult(unsigned resultNumber) { |
936 | // Inline results are stored in reverse order before the operation in |
937 | // memory. |
938 | return reinterpret_cast<detail::InlineOpResult *>(this) - ++resultNumber; |
939 | } |
940 | |
941 | /// Returns a pointer to the use list for the given result, which may be |
942 | /// either inline or out-of-line. |
943 | detail::OpResultImpl *getOpResultImpl(unsigned resultNumber) { |
944 | assert(resultNumber < getNumResults() &&(static_cast <bool> (resultNumber < getNumResults() && "Result number is out of range for operation") ? void (0) : __assert_fail ("resultNumber < getNumResults() && \"Result number is out of range for operation\"" , "mlir/include/mlir/IR/Operation.h", 945, __extension__ __PRETTY_FUNCTION__ )) |
945 | "Result number is out of range for operation")(static_cast <bool> (resultNumber < getNumResults() && "Result number is out of range for operation") ? void (0) : __assert_fail ("resultNumber < getNumResults() && \"Result number is out of range for operation\"" , "mlir/include/mlir/IR/Operation.h", 945, __extension__ __PRETTY_FUNCTION__ )); |
946 | unsigned maxInlineResults = detail::OpResultImpl::getMaxInlineResults(); |
947 | if (resultNumber < maxInlineResults) |
948 | return getInlineOpResult(resultNumber); |
949 | return getOutOfLineOpResult(resultNumber - maxInlineResults); |
950 | } |
951 | |
952 | /// Provide a 'getParent' method for ilist_node_with_parent methods. |
953 | /// We mark it as a const function because ilist_node_with_parent specifically |
954 | /// requires a 'getParent() const' method. Once ilist_node removes this |
955 | /// constraint, we should drop the const to fit the rest of the MLIR const |
956 | /// model. |
957 | Block *getParent() const { return block; } |
958 | |
959 | /// Expose a few methods explicitly for the debugger to call for |
960 | /// visualization. |
961 | #ifndef NDEBUG |
962 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) operand_range debug_getOperands() { return getOperands(); } |
963 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) result_range debug_getResults() { return getResults(); } |
964 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) SuccessorRange debug_getSuccessors() { |
965 | return getSuccessors(); |
966 | } |
967 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) MutableArrayRef<Region> debug_getRegions() { |
968 | return getRegions(); |
969 | } |
970 | #endif |
971 | |
972 | /// The operation block that contains this operation. |
973 | Block *block = nullptr; |
974 | |
975 | /// This holds information about the source location the operation was defined |
976 | /// or derived from. |
977 | Location location; |
978 | |
979 | /// Relative order of this operation in its parent block. Used for |
980 | /// O(1) local dominance checks between operations. |
981 | mutable unsigned orderIndex = 0; |
982 | |
983 | const unsigned numResults; |
984 | const unsigned numSuccs; |
985 | const unsigned numRegions : 23; |
986 | |
987 | /// This bit signals whether this operation has an operand storage or not. The |
988 | /// operand storage may be elided for operations that are known to never have |
989 | /// operands. |
990 | bool hasOperandStorage : 1; |
991 | |
992 | /// The size of the storage for properties (if any), divided by 8: since the |
993 | /// Properties storage will always be rounded up to the next multiple of 8 we |
994 | /// save some bits here. |
995 | unsigned char propertiesStorageSize : 8; |
996 | /// This is the maximum size we support to allocate properties inline with an |
997 | /// operation: this must match the bitwidth above. |
998 | static constexpr int64_t propertiesCapacity = 8 * 256; |
999 | |
1000 | /// This holds the name of the operation. |
1001 | OperationName name; |
1002 | |
1003 | /// This holds general named attributes for the operation. |
1004 | DictionaryAttr attrs; |
1005 | |
1006 | // allow ilist_traits access to 'block' field. |
1007 | friend struct llvm::ilist_traits<Operation>; |
1008 | |
1009 | // allow block to access the 'orderIndex' field. |
1010 | friend class Block; |
1011 | |
1012 | // allow value to access the 'ResultStorage' methods. |
1013 | friend class Value; |
1014 | |
1015 | // allow ilist_node_with_parent to access the 'getParent' method. |
1016 | friend class llvm::ilist_node_with_parent<Operation, Block>; |
1017 | |
1018 | // This stuff is used by the TrailingObjects template. |
1019 | friend llvm::TrailingObjects<Operation, detail::OperandStorage, |
1020 | detail::OpProperties, BlockOperand, Region, |
1021 | OpOperand>; |
1022 | size_t numTrailingObjects(OverloadToken<detail::OperandStorage>) const { |
1023 | return hasOperandStorage ? 1 : 0; |
1024 | } |
1025 | size_t numTrailingObjects(OverloadToken<BlockOperand>) const { |
1026 | return numSuccs; |
1027 | } |
1028 | size_t numTrailingObjects(OverloadToken<Region>) const { return numRegions; } |
1029 | size_t numTrailingObjects(OverloadToken<detail::OpProperties>) const { |
1030 | return getPropertiesStorageSize(); |
1031 | } |
1032 | }; |
1033 | |
1034 | inline raw_ostream &operator<<(raw_ostream &os, const Operation &op) { |
1035 | const_cast<Operation &>(op).print(os, OpPrintingFlags().useLocalScope()); |
1036 | return os; |
1037 | } |
1038 | |
1039 | } // namespace mlir |
1040 | |
1041 | namespace llvm { |
1042 | /// Cast from an (const) Operation * to a derived operation type. |
1043 | template <typename T> |
1044 | struct CastInfo<T, ::mlir::Operation *> |
1045 | : public ValueFromPointerCast<T, ::mlir::Operation, |
1046 | CastInfo<T, ::mlir::Operation *>> { |
1047 | static bool isPossible(::mlir::Operation *op) { return T::classof(op); } |
1048 | }; |
1049 | template <typename T> |
1050 | struct CastInfo<T, const ::mlir::Operation *> |
1051 | : public ConstStrippingForwardingCast<T, const ::mlir::Operation *, |
1052 | CastInfo<T, ::mlir::Operation *>> {}; |
1053 | |
1054 | /// Cast from an (const) Operation & to a derived operation type. |
1055 | template <typename T> |
1056 | struct CastInfo<T, ::mlir::Operation> |
1057 | : public NullableValueCastFailed<T>, |
1058 | public DefaultDoCastIfPossible<T, ::mlir::Operation &, |
1059 | CastInfo<T, ::mlir::Operation>> { |
1060 | // Provide isPossible here because here we have the const-stripping from |
1061 | // ConstStrippingCast. |
1062 | static bool isPossible(::mlir::Operation &val) { return T::classof(&val); } |
1063 | static T doCast(::mlir::Operation &val) { return T(&val); } |
1064 | }; |
1065 | template <typename T> |
1066 | struct CastInfo<T, const ::mlir::Operation> |
1067 | : public ConstStrippingForwardingCast<T, const ::mlir::Operation, |
1068 | CastInfo<T, ::mlir::Operation>> {}; |
1069 | |
1070 | /// Cast (const) Operation * to itself. This is helpful to avoid SFINAE in |
1071 | /// templated implementations that should work on both base and derived |
1072 | /// operation types. |
1073 | template <> |
1074 | struct CastInfo<::mlir::Operation *, ::mlir::Operation *> |
1075 | : public NullableValueCastFailed<::mlir::Operation *>, |
1076 | public DefaultDoCastIfPossible< |
1077 | ::mlir::Operation *, ::mlir::Operation *, |
1078 | CastInfo<::mlir::Operation *, ::mlir::Operation *>> { |
1079 | static bool isPossible(::mlir::Operation *op) { return true; } |
1080 | static ::mlir::Operation *doCast(::mlir::Operation *op) { return op; } |
1081 | }; |
1082 | template <> |
1083 | struct CastInfo<const ::mlir::Operation *, const ::mlir::Operation *> |
1084 | : public ConstStrippingForwardingCast< |
1085 | const ::mlir::Operation *, const ::mlir::Operation *, |
1086 | CastInfo<::mlir::Operation *, ::mlir::Operation *>> {}; |
1087 | } // namespace llvm |
1088 | |
1089 | #endif // MLIR_IR_OPERATION_H |
1 | /*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ |
2 | |* *| |
3 | |* Op Declarations *| |
4 | |* *| |
5 | |* Automatically generated file, do not edit! *| |
6 | |* *| |
7 | \*===----------------------------------------------------------------------===*/ |
8 | |
9 | #if defined(GET_OP_CLASSES) || defined(GET_OP_FWD_DEFINES) |
10 | #undef GET_OP_FWD_DEFINES |
11 | namespace mlir { |
12 | namespace arith { |
13 | class AddFOp; |
14 | } // namespace arith |
15 | } // namespace mlir |
16 | namespace mlir { |
17 | namespace arith { |
18 | class AddIOp; |
19 | } // namespace arith |
20 | } // namespace mlir |
21 | namespace mlir { |
22 | namespace arith { |
23 | class AddUIExtendedOp; |
24 | } // namespace arith |
25 | } // namespace mlir |
26 | namespace mlir { |
27 | namespace arith { |
28 | class AndIOp; |
29 | } // namespace arith |
30 | } // namespace mlir |
31 | namespace mlir { |
32 | namespace arith { |
33 | class BitcastOp; |
34 | } // namespace arith |
35 | } // namespace mlir |
36 | namespace mlir { |
37 | namespace arith { |
38 | class CeilDivSIOp; |
39 | } // namespace arith |
40 | } // namespace mlir |
41 | namespace mlir { |
42 | namespace arith { |
43 | class CeilDivUIOp; |
44 | } // namespace arith |
45 | } // namespace mlir |
46 | namespace mlir { |
47 | namespace arith { |
48 | class CmpFOp; |
49 | } // namespace arith |
50 | } // namespace mlir |
51 | namespace mlir { |
52 | namespace arith { |
53 | class CmpIOp; |
54 | } // namespace arith |
55 | } // namespace mlir |
56 | namespace mlir { |
57 | namespace arith { |
58 | class ConstantOp; |
59 | } // namespace arith |
60 | } // namespace mlir |
61 | namespace mlir { |
62 | namespace arith { |
63 | class DivFOp; |
64 | } // namespace arith |
65 | } // namespace mlir |
66 | namespace mlir { |
67 | namespace arith { |
68 | class DivSIOp; |
69 | } // namespace arith |
70 | } // namespace mlir |
71 | namespace mlir { |
72 | namespace arith { |
73 | class DivUIOp; |
74 | } // namespace arith |
75 | } // namespace mlir |
76 | namespace mlir { |
77 | namespace arith { |
78 | class ExtFOp; |
79 | } // namespace arith |
80 | } // namespace mlir |
81 | namespace mlir { |
82 | namespace arith { |
83 | class ExtSIOp; |
84 | } // namespace arith |
85 | } // namespace mlir |
86 | namespace mlir { |
87 | namespace arith { |
88 | class ExtUIOp; |
89 | } // namespace arith |
90 | } // namespace mlir |
91 | namespace mlir { |
92 | namespace arith { |
93 | class FPToSIOp; |
94 | } // namespace arith |
95 | } // namespace mlir |
96 | namespace mlir { |
97 | namespace arith { |
98 | class FPToUIOp; |
99 | } // namespace arith |
100 | } // namespace mlir |
101 | namespace mlir { |
102 | namespace arith { |
103 | class FloorDivSIOp; |
104 | } // namespace arith |
105 | } // namespace mlir |
106 | namespace mlir { |
107 | namespace arith { |
108 | class IndexCastOp; |
109 | } // namespace arith |
110 | } // namespace mlir |
111 | namespace mlir { |
112 | namespace arith { |
113 | class IndexCastUIOp; |
114 | } // namespace arith |
115 | } // namespace mlir |
116 | namespace mlir { |
117 | namespace arith { |
118 | class MaxFOp; |
119 | } // namespace arith |
120 | } // namespace mlir |
121 | namespace mlir { |
122 | namespace arith { |
123 | class MaxSIOp; |
124 | } // namespace arith |
125 | } // namespace mlir |
126 | namespace mlir { |
127 | namespace arith { |
128 | class MaxUIOp; |
129 | } // namespace arith |
130 | } // namespace mlir |
131 | namespace mlir { |
132 | namespace arith { |
133 | class MinFOp; |
134 | } // namespace arith |
135 | } // namespace mlir |
136 | namespace mlir { |
137 | namespace arith { |
138 | class MinSIOp; |
139 | } // namespace arith |
140 | } // namespace mlir |
141 | namespace mlir { |
142 | namespace arith { |
143 | class MinUIOp; |
144 | } // namespace arith |
145 | } // namespace mlir |
146 | namespace mlir { |
147 | namespace arith { |
148 | class MulFOp; |
149 | } // namespace arith |
150 | } // namespace mlir |
151 | namespace mlir { |
152 | namespace arith { |
153 | class MulIOp; |
154 | } // namespace arith |
155 | } // namespace mlir |
156 | namespace mlir { |
157 | namespace arith { |
158 | class MulSIExtendedOp; |
159 | } // namespace arith |
160 | } // namespace mlir |
161 | namespace mlir { |
162 | namespace arith { |
163 | class MulUIExtendedOp; |
164 | } // namespace arith |
165 | } // namespace mlir |
166 | namespace mlir { |
167 | namespace arith { |
168 | class NegFOp; |
169 | } // namespace arith |
170 | } // namespace mlir |
171 | namespace mlir { |
172 | namespace arith { |
173 | class OrIOp; |
174 | } // namespace arith |
175 | } // namespace mlir |
176 | namespace mlir { |
177 | namespace arith { |
178 | class RemFOp; |
179 | } // namespace arith |
180 | } // namespace mlir |
181 | namespace mlir { |
182 | namespace arith { |
183 | class RemSIOp; |
184 | } // namespace arith |
185 | } // namespace mlir |
186 | namespace mlir { |
187 | namespace arith { |
188 | class RemUIOp; |
189 | } // namespace arith |
190 | } // namespace mlir |
191 | namespace mlir { |
192 | namespace arith { |
193 | class SIToFPOp; |
194 | } // namespace arith |
195 | } // namespace mlir |
196 | namespace mlir { |
197 | namespace arith { |
198 | class ShLIOp; |
199 | } // namespace arith |
200 | } // namespace mlir |
201 | namespace mlir { |
202 | namespace arith { |
203 | class ShRSIOp; |
204 | } // namespace arith |
205 | } // namespace mlir |
206 | namespace mlir { |
207 | namespace arith { |
208 | class ShRUIOp; |
209 | } // namespace arith |
210 | } // namespace mlir |
211 | namespace mlir { |
212 | namespace arith { |
213 | class SubFOp; |
214 | } // namespace arith |
215 | } // namespace mlir |
216 | namespace mlir { |
217 | namespace arith { |
218 | class SubIOp; |
219 | } // namespace arith |
220 | } // namespace mlir |
221 | namespace mlir { |
222 | namespace arith { |
223 | class TruncFOp; |
224 | } // namespace arith |
225 | } // namespace mlir |
226 | namespace mlir { |
227 | namespace arith { |
228 | class TruncIOp; |
229 | } // namespace arith |
230 | } // namespace mlir |
231 | namespace mlir { |
232 | namespace arith { |
233 | class UIToFPOp; |
234 | } // namespace arith |
235 | } // namespace mlir |
236 | namespace mlir { |
237 | namespace arith { |
238 | class XOrIOp; |
239 | } // namespace arith |
240 | } // namespace mlir |
241 | namespace mlir { |
242 | namespace arith { |
243 | class SelectOp; |
244 | } // namespace arith |
245 | } // namespace mlir |
246 | #endif |
247 | |
248 | #ifdef GET_OP_CLASSES |
249 | #undef GET_OP_CLASSES |
250 | |
251 | |
252 | //===----------------------------------------------------------------------===// |
253 | // Local Utility Method Definitions |
254 | //===----------------------------------------------------------------------===// |
255 | |
256 | namespace mlir { |
257 | namespace arith { |
258 | |
259 | //===----------------------------------------------------------------------===// |
260 | // ::mlir::arith::AddFOp declarations |
261 | //===----------------------------------------------------------------------===// |
262 | |
263 | namespace detail { |
264 | class AddFOpGenericAdaptorBase { |
265 | public: |
266 | struct Properties { |
267 | using fastmathTy = ::mlir::arith::FastMathFlagsAttr; |
268 | fastmathTy fastmath; |
269 | |
270 | auto getFastmath() { |
271 | auto &propStorage = this->fastmath; |
272 | return propStorage.dyn_cast_or_null<::mlir::arith::FastMathFlagsAttr>(); |
273 | } |
274 | void setFastmath(const ::mlir::arith::FastMathFlagsAttr &propValue) { |
275 | this->fastmath = propValue; |
276 | } |
277 | }; |
278 | protected: |
279 | ::mlir::DictionaryAttr odsAttrs; |
280 | ::std::optional<::mlir::OperationName> odsOpName; |
281 | Properties properties; |
282 | ::mlir::RegionRange odsRegions; |
283 | public: |
284 | AddFOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}); |
285 | |
286 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
287 | const Properties &getProperties() { |
288 | return properties; |
289 | } |
290 | |
291 | ::mlir::DictionaryAttr getAttributes(); |
292 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
293 | ::mlir::arith::FastMathFlags getFastmath(); |
294 | }; |
295 | } // namespace detail |
296 | template <typename RangeT> |
297 | class AddFOpGenericAdaptor : public detail::AddFOpGenericAdaptorBase { |
298 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
299 | using Base = detail::AddFOpGenericAdaptorBase; |
300 | public: |
301 | AddFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
302 | |
303 | AddFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : AddFOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {} |
304 | |
305 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
306 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
307 | } |
308 | |
309 | RangeT getODSOperands(unsigned index) { |
310 | auto valueRange = getODSOperandIndexAndLength(index); |
311 | return {std::next(odsOperands.begin(), valueRange.first), |
312 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
313 | } |
314 | |
315 | ValueT getLhs() { |
316 | return (*getODSOperands(0).begin()); |
317 | } |
318 | |
319 | ValueT getRhs() { |
320 | return (*getODSOperands(1).begin()); |
321 | } |
322 | |
323 | RangeT getOperands() { |
324 | return odsOperands; |
325 | } |
326 | |
327 | private: |
328 | RangeT odsOperands; |
329 | }; |
330 | class AddFOpAdaptor : public AddFOpGenericAdaptor<::mlir::ValueRange> { |
331 | public: |
332 | using AddFOpGenericAdaptor::AddFOpGenericAdaptor; |
333 | AddFOpAdaptor(AddFOp op); |
334 | |
335 | ::mlir::LogicalResult verify(::mlir::Location loc); |
336 | }; |
337 | class AddFOp : public ::mlir::Op<AddFOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::arith::ArithFastMathInterface::Trait, ::mlir::OpTrait::IsCommutative, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
338 | public: |
339 | using Op::Op; |
340 | using Op::print; |
341 | using Adaptor = AddFOpAdaptor; |
342 | template <typename RangeT> |
343 | using GenericAdaptor = AddFOpGenericAdaptor<RangeT>; |
344 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
345 | using Properties = FoldAdaptor::Properties; |
346 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
347 | static ::llvm::StringRef attrNames[] = {::llvm::StringRef("fastmath")}; |
348 | return ::llvm::ArrayRef(attrNames); |
349 | } |
350 | |
351 | ::mlir::StringAttr getFastmathAttrName() { |
352 | return getAttributeNameForIndex(0); |
353 | } |
354 | |
355 | static ::mlir::StringAttr getFastmathAttrName(::mlir::OperationName name) { |
356 | return getAttributeNameForIndex(name, 0); |
357 | } |
358 | |
359 | static constexpr ::llvm::StringLiteral getOperationName() { |
360 | return ::llvm::StringLiteral("arith.addf"); |
361 | } |
362 | |
363 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
364 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
365 | ::mlir::Value getLhs(); |
366 | ::mlir::Value getRhs(); |
367 | ::mlir::MutableOperandRange getLhsMutable(); |
368 | ::mlir::MutableOperandRange getRhsMutable(); |
369 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
370 | ::mlir::Operation::result_range getODSResults(unsigned index); |
371 | ::mlir::Value getResult(); |
372 | static ::mlir::LogicalResult setPropertiesFromAttr(Properties &prop, ::mlir::Attribute attr, ::mlir::InFlightDiagnostic *diag); |
373 | static ::mlir::Attribute getPropertiesAsAttr(::mlir::MLIRContext *ctx, const Properties &prop); |
374 | static llvm::hash_code computePropertiesHash(const Properties &prop); |
375 | static std::optional<mlir::Attribute> getInherentAttr(const Properties &prop, llvm::StringRef name); |
376 | static void setInherentAttr(Properties &prop, llvm::StringRef name, mlir::Attribute value); |
377 | static void populateInherentAttrs(const Properties &prop, ::mlir::NamedAttrList &attrs); |
378 | static ::mlir::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> getDiag); |
379 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
380 | ::mlir::arith::FastMathFlags getFastmath(); |
381 | void setFastmathAttr(::mlir::arith::FastMathFlagsAttr attr); |
382 | void setFastmath(::mlir::arith::FastMathFlags attrValue); |
383 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
384 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
385 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
386 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
387 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
388 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
389 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
390 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
391 | static void populateDefaultProperties(::mlir::OperationName opName, Properties &properties); |
392 | ::mlir::LogicalResult verifyInvariantsImpl(); |
393 | ::mlir::LogicalResult verifyInvariants(); |
394 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
395 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
396 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
397 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
398 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
399 | private: |
400 | ::mlir::StringAttr getAttributeNameForIndex(unsigned index) { |
401 | return getAttributeNameForIndex((*this)->getName(), index); |
402 | } |
403 | |
404 | static ::mlir::StringAttr getAttributeNameForIndex(::mlir::OperationName name, unsigned index) { |
405 | assert(index < 1 && "invalid attribute index")(static_cast <bool> (index < 1 && "invalid attribute index" ) ? void (0) : __assert_fail ("index < 1 && \"invalid attribute index\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 405 , __extension__ __PRETTY_FUNCTION__)); |
406 | assert(name.getStringRef() == getOperationName() && "invalid operation name")(static_cast <bool> (name.getStringRef() == getOperationName () && "invalid operation name") ? void (0) : __assert_fail ("name.getStringRef() == getOperationName() && \"invalid operation name\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 406 , __extension__ __PRETTY_FUNCTION__)); |
407 | return name.getAttributeNames()[index]; |
408 | } |
409 | |
410 | public: |
411 | }; |
412 | } // namespace arith |
413 | } // namespace mlir |
414 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::AddFOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::AddFOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
415 | |
416 | namespace mlir { |
417 | namespace arith { |
418 | |
419 | //===----------------------------------------------------------------------===// |
420 | // ::mlir::arith::AddIOp declarations |
421 | //===----------------------------------------------------------------------===// |
422 | |
423 | namespace detail { |
424 | class AddIOpGenericAdaptorBase { |
425 | public: |
426 | protected: |
427 | ::mlir::DictionaryAttr odsAttrs; |
428 | ::std::optional<::mlir::OperationName> odsOpName; |
429 | ::mlir::RegionRange odsRegions; |
430 | public: |
431 | AddIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
432 | |
433 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
434 | ::mlir::DictionaryAttr getAttributes(); |
435 | }; |
436 | } // namespace detail |
437 | template <typename RangeT> |
438 | class AddIOpGenericAdaptor : public detail::AddIOpGenericAdaptorBase { |
439 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
440 | using Base = detail::AddIOpGenericAdaptorBase; |
441 | public: |
442 | AddIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
443 | |
444 | AddIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : AddIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
445 | |
446 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
447 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
448 | } |
449 | |
450 | RangeT getODSOperands(unsigned index) { |
451 | auto valueRange = getODSOperandIndexAndLength(index); |
452 | return {std::next(odsOperands.begin(), valueRange.first), |
453 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
454 | } |
455 | |
456 | ValueT getLhs() { |
457 | return (*getODSOperands(0).begin()); |
458 | } |
459 | |
460 | ValueT getRhs() { |
461 | return (*getODSOperands(1).begin()); |
462 | } |
463 | |
464 | RangeT getOperands() { |
465 | return odsOperands; |
466 | } |
467 | |
468 | private: |
469 | RangeT odsOperands; |
470 | }; |
471 | class AddIOpAdaptor : public AddIOpGenericAdaptor<::mlir::ValueRange> { |
472 | public: |
473 | using AddIOpGenericAdaptor::AddIOpGenericAdaptor; |
474 | AddIOpAdaptor(AddIOp op); |
475 | |
476 | ::mlir::LogicalResult verify(::mlir::Location loc); |
477 | }; |
478 | class AddIOp : public ::mlir::Op<AddIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::OpTrait::IsCommutative, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
479 | public: |
480 | using Op::Op; |
481 | using Op::print; |
482 | using Adaptor = AddIOpAdaptor; |
483 | template <typename RangeT> |
484 | using GenericAdaptor = AddIOpGenericAdaptor<RangeT>; |
485 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
486 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
487 | return {}; |
488 | } |
489 | |
490 | static constexpr ::llvm::StringLiteral getOperationName() { |
491 | return ::llvm::StringLiteral("arith.addi"); |
492 | } |
493 | |
494 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
495 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
496 | ::mlir::Value getLhs(); |
497 | ::mlir::Value getRhs(); |
498 | ::mlir::MutableOperandRange getLhsMutable(); |
499 | ::mlir::MutableOperandRange getRhsMutable(); |
500 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
501 | ::mlir::Operation::result_range getODSResults(unsigned index); |
502 | ::mlir::Value getResult(); |
503 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
504 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
505 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
506 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
507 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
508 | ::mlir::LogicalResult verifyInvariantsImpl(); |
509 | ::mlir::LogicalResult verifyInvariants(); |
510 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
511 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
512 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
513 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
514 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
515 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
516 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
517 | public: |
518 | }; |
519 | } // namespace arith |
520 | } // namespace mlir |
521 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::AddIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::AddIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
522 | |
523 | namespace mlir { |
524 | namespace arith { |
525 | |
526 | //===----------------------------------------------------------------------===// |
527 | // ::mlir::arith::AddUIExtendedOp declarations |
528 | //===----------------------------------------------------------------------===// |
529 | |
530 | namespace detail { |
531 | class AddUIExtendedOpGenericAdaptorBase { |
532 | public: |
533 | protected: |
534 | ::mlir::DictionaryAttr odsAttrs; |
535 | ::std::optional<::mlir::OperationName> odsOpName; |
536 | ::mlir::RegionRange odsRegions; |
537 | public: |
538 | AddUIExtendedOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
539 | |
540 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
541 | ::mlir::DictionaryAttr getAttributes(); |
542 | }; |
543 | } // namespace detail |
544 | template <typename RangeT> |
545 | class AddUIExtendedOpGenericAdaptor : public detail::AddUIExtendedOpGenericAdaptorBase { |
546 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
547 | using Base = detail::AddUIExtendedOpGenericAdaptorBase; |
548 | public: |
549 | AddUIExtendedOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
550 | |
551 | AddUIExtendedOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : AddUIExtendedOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
552 | |
553 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
554 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
555 | } |
556 | |
557 | RangeT getODSOperands(unsigned index) { |
558 | auto valueRange = getODSOperandIndexAndLength(index); |
559 | return {std::next(odsOperands.begin(), valueRange.first), |
560 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
561 | } |
562 | |
563 | ValueT getLhs() { |
564 | return (*getODSOperands(0).begin()); |
565 | } |
566 | |
567 | ValueT getRhs() { |
568 | return (*getODSOperands(1).begin()); |
569 | } |
570 | |
571 | RangeT getOperands() { |
572 | return odsOperands; |
573 | } |
574 | |
575 | private: |
576 | RangeT odsOperands; |
577 | }; |
578 | class AddUIExtendedOpAdaptor : public AddUIExtendedOpGenericAdaptor<::mlir::ValueRange> { |
579 | public: |
580 | using AddUIExtendedOpGenericAdaptor::AddUIExtendedOpGenericAdaptor; |
581 | AddUIExtendedOpAdaptor(AddUIExtendedOp op); |
582 | |
583 | ::mlir::LogicalResult verify(::mlir::Location loc); |
584 | }; |
585 | class AddUIExtendedOp : public ::mlir::Op<AddUIExtendedOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::NResults<2>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::IsCommutative, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::OpAsmOpInterface::Trait> { |
586 | public: |
587 | using Op::Op; |
588 | using Op::print; |
589 | using Adaptor = AddUIExtendedOpAdaptor; |
590 | template <typename RangeT> |
591 | using GenericAdaptor = AddUIExtendedOpGenericAdaptor<RangeT>; |
592 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
593 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
594 | return {}; |
595 | } |
596 | |
597 | void getAsmResultNames(::mlir::OpAsmSetValueNameFn setNameFn); |
598 | static constexpr ::llvm::StringLiteral getOperationName() { |
599 | return ::llvm::StringLiteral("arith.addui_extended"); |
600 | } |
601 | |
602 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
603 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
604 | ::mlir::Value getLhs(); |
605 | ::mlir::Value getRhs(); |
606 | ::mlir::MutableOperandRange getLhsMutable(); |
607 | ::mlir::MutableOperandRange getRhsMutable(); |
608 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
609 | ::mlir::Operation::result_range getODSResults(unsigned index); |
610 | ::mlir::Value getSum(); |
611 | ::mlir::Value getOverflow(); |
612 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, Value lhs, Value rhs); |
613 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type sum, ::mlir::Type overflow, ::mlir::Value lhs, ::mlir::Value rhs); |
614 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
615 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
616 | ::mlir::LogicalResult verifyInvariantsImpl(); |
617 | ::mlir::LogicalResult verifyInvariants(); |
618 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
619 | ::mlir::LogicalResult fold(FoldAdaptor adaptor, ::llvm::SmallVectorImpl<::mlir::OpFoldResult> &results); |
620 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
621 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
622 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
623 | public: |
624 | std::optional<SmallVector<int64_t, 4>> getShapeForUnroll(); |
625 | }; |
626 | } // namespace arith |
627 | } // namespace mlir |
628 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::AddUIExtendedOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::AddUIExtendedOp> { public: static TypeID resolveTypeID() { return id; } private: static SelfOwningTypeID id; }; } } |
629 | |
630 | namespace mlir { |
631 | namespace arith { |
632 | |
633 | //===----------------------------------------------------------------------===// |
634 | // ::mlir::arith::AndIOp declarations |
635 | //===----------------------------------------------------------------------===// |
636 | |
637 | namespace detail { |
638 | class AndIOpGenericAdaptorBase { |
639 | public: |
640 | protected: |
641 | ::mlir::DictionaryAttr odsAttrs; |
642 | ::std::optional<::mlir::OperationName> odsOpName; |
643 | ::mlir::RegionRange odsRegions; |
644 | public: |
645 | AndIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
646 | |
647 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
648 | ::mlir::DictionaryAttr getAttributes(); |
649 | }; |
650 | } // namespace detail |
651 | template <typename RangeT> |
652 | class AndIOpGenericAdaptor : public detail::AndIOpGenericAdaptorBase { |
653 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
654 | using Base = detail::AndIOpGenericAdaptorBase; |
655 | public: |
656 | AndIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
657 | |
658 | AndIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : AndIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
659 | |
660 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
661 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
662 | } |
663 | |
664 | RangeT getODSOperands(unsigned index) { |
665 | auto valueRange = getODSOperandIndexAndLength(index); |
666 | return {std::next(odsOperands.begin(), valueRange.first), |
667 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
668 | } |
669 | |
670 | ValueT getLhs() { |
671 | return (*getODSOperands(0).begin()); |
672 | } |
673 | |
674 | ValueT getRhs() { |
675 | return (*getODSOperands(1).begin()); |
676 | } |
677 | |
678 | RangeT getOperands() { |
679 | return odsOperands; |
680 | } |
681 | |
682 | private: |
683 | RangeT odsOperands; |
684 | }; |
685 | class AndIOpAdaptor : public AndIOpGenericAdaptor<::mlir::ValueRange> { |
686 | public: |
687 | using AndIOpGenericAdaptor::AndIOpGenericAdaptor; |
688 | AndIOpAdaptor(AndIOp op); |
689 | |
690 | ::mlir::LogicalResult verify(::mlir::Location loc); |
691 | }; |
692 | class AndIOp : public ::mlir::Op<AndIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::OpTrait::IsCommutative, ::mlir::OpTrait::IsIdempotent, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
693 | public: |
694 | using Op::Op; |
695 | using Op::print; |
696 | using Adaptor = AndIOpAdaptor; |
697 | template <typename RangeT> |
698 | using GenericAdaptor = AndIOpGenericAdaptor<RangeT>; |
699 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
700 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
701 | return {}; |
702 | } |
703 | |
704 | static constexpr ::llvm::StringLiteral getOperationName() { |
705 | return ::llvm::StringLiteral("arith.andi"); |
706 | } |
707 | |
708 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
709 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
710 | ::mlir::Value getLhs(); |
711 | ::mlir::Value getRhs(); |
712 | ::mlir::MutableOperandRange getLhsMutable(); |
713 | ::mlir::MutableOperandRange getRhsMutable(); |
714 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
715 | ::mlir::Operation::result_range getODSResults(unsigned index); |
716 | ::mlir::Value getResult(); |
717 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
718 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
719 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
720 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
721 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
722 | ::mlir::LogicalResult verifyInvariantsImpl(); |
723 | ::mlir::LogicalResult verifyInvariants(); |
724 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
725 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
726 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
727 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
728 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
729 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
730 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
731 | public: |
732 | }; |
733 | } // namespace arith |
734 | } // namespace mlir |
735 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::AndIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::AndIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
736 | |
737 | namespace mlir { |
738 | namespace arith { |
739 | |
740 | //===----------------------------------------------------------------------===// |
741 | // ::mlir::arith::BitcastOp declarations |
742 | //===----------------------------------------------------------------------===// |
743 | |
744 | namespace detail { |
745 | class BitcastOpGenericAdaptorBase { |
746 | public: |
747 | protected: |
748 | ::mlir::DictionaryAttr odsAttrs; |
749 | ::std::optional<::mlir::OperationName> odsOpName; |
750 | ::mlir::RegionRange odsRegions; |
751 | public: |
752 | BitcastOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
753 | |
754 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
755 | ::mlir::DictionaryAttr getAttributes(); |
756 | }; |
757 | } // namespace detail |
758 | template <typename RangeT> |
759 | class BitcastOpGenericAdaptor : public detail::BitcastOpGenericAdaptorBase { |
760 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
761 | using Base = detail::BitcastOpGenericAdaptorBase; |
762 | public: |
763 | BitcastOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
764 | |
765 | BitcastOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : BitcastOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
766 | |
767 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
768 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
769 | } |
770 | |
771 | RangeT getODSOperands(unsigned index) { |
772 | auto valueRange = getODSOperandIndexAndLength(index); |
773 | return {std::next(odsOperands.begin(), valueRange.first), |
774 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
775 | } |
776 | |
777 | ValueT getIn() { |
778 | return (*getODSOperands(0).begin()); |
779 | } |
780 | |
781 | RangeT getOperands() { |
782 | return odsOperands; |
783 | } |
784 | |
785 | private: |
786 | RangeT odsOperands; |
787 | }; |
788 | class BitcastOpAdaptor : public BitcastOpGenericAdaptor<::mlir::ValueRange> { |
789 | public: |
790 | using BitcastOpGenericAdaptor::BitcastOpGenericAdaptor; |
791 | BitcastOpAdaptor(BitcastOp op); |
792 | |
793 | ::mlir::LogicalResult verify(::mlir::Location loc); |
794 | }; |
795 | class BitcastOp : public ::mlir::Op<BitcastOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
796 | public: |
797 | using Op::Op; |
798 | using Op::print; |
799 | using Adaptor = BitcastOpAdaptor; |
800 | template <typename RangeT> |
801 | using GenericAdaptor = BitcastOpGenericAdaptor<RangeT>; |
802 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
803 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
804 | return {}; |
805 | } |
806 | |
807 | static constexpr ::llvm::StringLiteral getOperationName() { |
808 | return ::llvm::StringLiteral("arith.bitcast"); |
809 | } |
810 | |
811 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
812 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
813 | ::mlir::Value getIn(); |
814 | ::mlir::MutableOperandRange getInMutable(); |
815 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
816 | ::mlir::Operation::result_range getODSResults(unsigned index); |
817 | ::mlir::Value getOut(); |
818 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
819 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
820 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
821 | ::mlir::LogicalResult verifyInvariantsImpl(); |
822 | ::mlir::LogicalResult verifyInvariants(); |
823 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
824 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
825 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
826 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
827 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
828 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
829 | public: |
830 | }; |
831 | } // namespace arith |
832 | } // namespace mlir |
833 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::BitcastOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::BitcastOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
834 | |
835 | namespace mlir { |
836 | namespace arith { |
837 | |
838 | //===----------------------------------------------------------------------===// |
839 | // ::mlir::arith::CeilDivSIOp declarations |
840 | //===----------------------------------------------------------------------===// |
841 | |
842 | namespace detail { |
843 | class CeilDivSIOpGenericAdaptorBase { |
844 | public: |
845 | protected: |
846 | ::mlir::DictionaryAttr odsAttrs; |
847 | ::std::optional<::mlir::OperationName> odsOpName; |
848 | ::mlir::RegionRange odsRegions; |
849 | public: |
850 | CeilDivSIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
851 | |
852 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
853 | ::mlir::DictionaryAttr getAttributes(); |
854 | }; |
855 | } // namespace detail |
856 | template <typename RangeT> |
857 | class CeilDivSIOpGenericAdaptor : public detail::CeilDivSIOpGenericAdaptorBase { |
858 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
859 | using Base = detail::CeilDivSIOpGenericAdaptorBase; |
860 | public: |
861 | CeilDivSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
862 | |
863 | CeilDivSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : CeilDivSIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
864 | |
865 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
866 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
867 | } |
868 | |
869 | RangeT getODSOperands(unsigned index) { |
870 | auto valueRange = getODSOperandIndexAndLength(index); |
871 | return {std::next(odsOperands.begin(), valueRange.first), |
872 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
873 | } |
874 | |
875 | ValueT getLhs() { |
876 | return (*getODSOperands(0).begin()); |
877 | } |
878 | |
879 | ValueT getRhs() { |
880 | return (*getODSOperands(1).begin()); |
881 | } |
882 | |
883 | RangeT getOperands() { |
884 | return odsOperands; |
885 | } |
886 | |
887 | private: |
888 | RangeT odsOperands; |
889 | }; |
890 | class CeilDivSIOpAdaptor : public CeilDivSIOpGenericAdaptor<::mlir::ValueRange> { |
891 | public: |
892 | using CeilDivSIOpGenericAdaptor::CeilDivSIOpGenericAdaptor; |
893 | CeilDivSIOpAdaptor(CeilDivSIOp op); |
894 | |
895 | ::mlir::LogicalResult verify(::mlir::Location loc); |
896 | }; |
897 | class CeilDivSIOp : public ::mlir::Op<CeilDivSIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
898 | public: |
899 | using Op::Op; |
900 | using Op::print; |
901 | using Adaptor = CeilDivSIOpAdaptor; |
902 | template <typename RangeT> |
903 | using GenericAdaptor = CeilDivSIOpGenericAdaptor<RangeT>; |
904 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
905 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
906 | return {}; |
907 | } |
908 | |
909 | static constexpr ::llvm::StringLiteral getOperationName() { |
910 | return ::llvm::StringLiteral("arith.ceildivsi"); |
911 | } |
912 | |
913 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
914 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
915 | ::mlir::Value getLhs(); |
916 | ::mlir::Value getRhs(); |
917 | ::mlir::MutableOperandRange getLhsMutable(); |
918 | ::mlir::MutableOperandRange getRhsMutable(); |
919 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
920 | ::mlir::Operation::result_range getODSResults(unsigned index); |
921 | ::mlir::Value getResult(); |
922 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
923 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
924 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
925 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
926 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
927 | ::mlir::LogicalResult verifyInvariantsImpl(); |
928 | ::mlir::LogicalResult verifyInvariants(); |
929 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
930 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
931 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
932 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
933 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
934 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
935 | public: |
936 | /// Interface method for ConditionallySpeculatable. |
937 | Speculation::Speculatability getSpeculatability(); |
938 | }; |
939 | } // namespace arith |
940 | } // namespace mlir |
941 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::CeilDivSIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::CeilDivSIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
942 | |
943 | namespace mlir { |
944 | namespace arith { |
945 | |
946 | //===----------------------------------------------------------------------===// |
947 | // ::mlir::arith::CeilDivUIOp declarations |
948 | //===----------------------------------------------------------------------===// |
949 | |
950 | namespace detail { |
951 | class CeilDivUIOpGenericAdaptorBase { |
952 | public: |
953 | protected: |
954 | ::mlir::DictionaryAttr odsAttrs; |
955 | ::std::optional<::mlir::OperationName> odsOpName; |
956 | ::mlir::RegionRange odsRegions; |
957 | public: |
958 | CeilDivUIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
959 | |
960 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
961 | ::mlir::DictionaryAttr getAttributes(); |
962 | }; |
963 | } // namespace detail |
964 | template <typename RangeT> |
965 | class CeilDivUIOpGenericAdaptor : public detail::CeilDivUIOpGenericAdaptorBase { |
966 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
967 | using Base = detail::CeilDivUIOpGenericAdaptorBase; |
968 | public: |
969 | CeilDivUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
970 | |
971 | CeilDivUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : CeilDivUIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
972 | |
973 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
974 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
975 | } |
976 | |
977 | RangeT getODSOperands(unsigned index) { |
978 | auto valueRange = getODSOperandIndexAndLength(index); |
979 | return {std::next(odsOperands.begin(), valueRange.first), |
980 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
981 | } |
982 | |
983 | ValueT getLhs() { |
984 | return (*getODSOperands(0).begin()); |
985 | } |
986 | |
987 | ValueT getRhs() { |
988 | return (*getODSOperands(1).begin()); |
989 | } |
990 | |
991 | RangeT getOperands() { |
992 | return odsOperands; |
993 | } |
994 | |
995 | private: |
996 | RangeT odsOperands; |
997 | }; |
998 | class CeilDivUIOpAdaptor : public CeilDivUIOpGenericAdaptor<::mlir::ValueRange> { |
999 | public: |
1000 | using CeilDivUIOpGenericAdaptor::CeilDivUIOpGenericAdaptor; |
1001 | CeilDivUIOpAdaptor(CeilDivUIOp op); |
1002 | |
1003 | ::mlir::LogicalResult verify(::mlir::Location loc); |
1004 | }; |
1005 | class CeilDivUIOp : public ::mlir::Op<CeilDivUIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
1006 | public: |
1007 | using Op::Op; |
1008 | using Op::print; |
1009 | using Adaptor = CeilDivUIOpAdaptor; |
1010 | template <typename RangeT> |
1011 | using GenericAdaptor = CeilDivUIOpGenericAdaptor<RangeT>; |
1012 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
1013 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
1014 | return {}; |
1015 | } |
1016 | |
1017 | static constexpr ::llvm::StringLiteral getOperationName() { |
1018 | return ::llvm::StringLiteral("arith.ceildivui"); |
1019 | } |
1020 | |
1021 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
1022 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
1023 | ::mlir::Value getLhs(); |
1024 | ::mlir::Value getRhs(); |
1025 | ::mlir::MutableOperandRange getLhsMutable(); |
1026 | ::mlir::MutableOperandRange getRhsMutable(); |
1027 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
1028 | ::mlir::Operation::result_range getODSResults(unsigned index); |
1029 | ::mlir::Value getResult(); |
1030 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
1031 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
1032 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
1033 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1034 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1035 | ::mlir::LogicalResult verifyInvariantsImpl(); |
1036 | ::mlir::LogicalResult verifyInvariants(); |
1037 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
1038 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
1039 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
1040 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
1041 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
1042 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
1043 | public: |
1044 | /// Interface method for ConditionallySpeculatable. |
1045 | Speculation::Speculatability getSpeculatability(); |
1046 | }; |
1047 | } // namespace arith |
1048 | } // namespace mlir |
1049 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::CeilDivUIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::CeilDivUIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
1050 | |
1051 | namespace mlir { |
1052 | namespace arith { |
1053 | |
1054 | //===----------------------------------------------------------------------===// |
1055 | // ::mlir::arith::CmpFOp declarations |
1056 | //===----------------------------------------------------------------------===// |
1057 | |
1058 | namespace detail { |
1059 | class CmpFOpGenericAdaptorBase { |
1060 | public: |
1061 | struct Properties { |
1062 | using predicateTy = ::mlir::arith::CmpFPredicateAttr; |
1063 | predicateTy predicate; |
1064 | |
1065 | auto getPredicate() { |
1066 | auto &propStorage = this->predicate; |
1067 | return propStorage.cast<::mlir::arith::CmpFPredicateAttr>(); |
1068 | } |
1069 | void setPredicate(const ::mlir::arith::CmpFPredicateAttr &propValue) { |
1070 | this->predicate = propValue; |
1071 | } |
1072 | }; |
1073 | protected: |
1074 | ::mlir::DictionaryAttr odsAttrs; |
1075 | ::std::optional<::mlir::OperationName> odsOpName; |
1076 | Properties properties; |
1077 | ::mlir::RegionRange odsRegions; |
1078 | public: |
1079 | CmpFOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}); |
1080 | |
1081 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
1082 | const Properties &getProperties() { |
1083 | return properties; |
1084 | } |
1085 | |
1086 | ::mlir::DictionaryAttr getAttributes(); |
1087 | ::mlir::arith::CmpFPredicateAttr getPredicateAttr(); |
1088 | ::mlir::arith::CmpFPredicate getPredicate(); |
1089 | }; |
1090 | } // namespace detail |
1091 | template <typename RangeT> |
1092 | class CmpFOpGenericAdaptor : public detail::CmpFOpGenericAdaptorBase { |
1093 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
1094 | using Base = detail::CmpFOpGenericAdaptorBase; |
1095 | public: |
1096 | CmpFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
1097 | |
1098 | CmpFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : CmpFOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {} |
1099 | |
1100 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
1101 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
1102 | } |
1103 | |
1104 | RangeT getODSOperands(unsigned index) { |
1105 | auto valueRange = getODSOperandIndexAndLength(index); |
1106 | return {std::next(odsOperands.begin(), valueRange.first), |
1107 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
1108 | } |
1109 | |
1110 | ValueT getLhs() { |
1111 | return (*getODSOperands(0).begin()); |
1112 | } |
1113 | |
1114 | ValueT getRhs() { |
1115 | return (*getODSOperands(1).begin()); |
1116 | } |
1117 | |
1118 | RangeT getOperands() { |
1119 | return odsOperands; |
1120 | } |
1121 | |
1122 | private: |
1123 | RangeT odsOperands; |
1124 | }; |
1125 | class CmpFOpAdaptor : public CmpFOpGenericAdaptor<::mlir::ValueRange> { |
1126 | public: |
1127 | using CmpFOpGenericAdaptor::CmpFOpGenericAdaptor; |
1128 | CmpFOpAdaptor(CmpFOp op); |
1129 | |
1130 | ::mlir::LogicalResult verify(::mlir::Location loc); |
1131 | }; |
1132 | class CmpFOp : public ::mlir::Op<CmpFOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameTypeOperands, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
1133 | public: |
1134 | using Op::Op; |
1135 | using Op::print; |
1136 | using Adaptor = CmpFOpAdaptor; |
1137 | template <typename RangeT> |
1138 | using GenericAdaptor = CmpFOpGenericAdaptor<RangeT>; |
1139 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
1140 | using Properties = FoldAdaptor::Properties; |
1141 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
1142 | static ::llvm::StringRef attrNames[] = {::llvm::StringRef("predicate")}; |
1143 | return ::llvm::ArrayRef(attrNames); |
1144 | } |
1145 | |
1146 | ::mlir::StringAttr getPredicateAttrName() { |
1147 | return getAttributeNameForIndex(0); |
1148 | } |
1149 | |
1150 | static ::mlir::StringAttr getPredicateAttrName(::mlir::OperationName name) { |
1151 | return getAttributeNameForIndex(name, 0); |
1152 | } |
1153 | |
1154 | static constexpr ::llvm::StringLiteral getOperationName() { |
1155 | return ::llvm::StringLiteral("arith.cmpf"); |
1156 | } |
1157 | |
1158 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
1159 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
1160 | ::mlir::Value getLhs(); |
1161 | ::mlir::Value getRhs(); |
1162 | ::mlir::MutableOperandRange getLhsMutable(); |
1163 | ::mlir::MutableOperandRange getRhsMutable(); |
1164 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
1165 | ::mlir::Operation::result_range getODSResults(unsigned index); |
1166 | ::mlir::Value getResult(); |
1167 | static ::mlir::LogicalResult setPropertiesFromAttr(Properties &prop, ::mlir::Attribute attr, ::mlir::InFlightDiagnostic *diag); |
1168 | static ::mlir::Attribute getPropertiesAsAttr(::mlir::MLIRContext *ctx, const Properties &prop); |
1169 | static llvm::hash_code computePropertiesHash(const Properties &prop); |
1170 | static std::optional<mlir::Attribute> getInherentAttr(const Properties &prop, llvm::StringRef name); |
1171 | static void setInherentAttr(Properties &prop, llvm::StringRef name, mlir::Attribute value); |
1172 | static void populateInherentAttrs(const Properties &prop, ::mlir::NamedAttrList &attrs); |
1173 | static ::mlir::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> getDiag); |
1174 | ::mlir::arith::CmpFPredicateAttr getPredicateAttr(); |
1175 | ::mlir::arith::CmpFPredicate getPredicate(); |
1176 | void setPredicateAttr(::mlir::arith::CmpFPredicateAttr attr); |
1177 | void setPredicate(::mlir::arith::CmpFPredicate attrValue); |
1178 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::arith::CmpFPredicateAttr predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1179 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::arith::CmpFPredicateAttr predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1180 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::arith::CmpFPredicateAttr predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1181 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::arith::CmpFPredicate predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1182 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::arith::CmpFPredicate predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1183 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::arith::CmpFPredicate predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1184 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1185 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1186 | ::mlir::LogicalResult verifyInvariantsImpl(); |
1187 | ::mlir::LogicalResult verifyInvariants(); |
1188 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
1189 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
1190 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
1191 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
1192 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
1193 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
1194 | private: |
1195 | ::mlir::StringAttr getAttributeNameForIndex(unsigned index) { |
1196 | return getAttributeNameForIndex((*this)->getName(), index); |
1197 | } |
1198 | |
1199 | static ::mlir::StringAttr getAttributeNameForIndex(::mlir::OperationName name, unsigned index) { |
1200 | assert(index < 1 && "invalid attribute index")(static_cast <bool> (index < 1 && "invalid attribute index" ) ? void (0) : __assert_fail ("index < 1 && \"invalid attribute index\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 1200 , __extension__ __PRETTY_FUNCTION__)); |
1201 | assert(name.getStringRef() == getOperationName() && "invalid operation name")(static_cast <bool> (name.getStringRef() == getOperationName () && "invalid operation name") ? void (0) : __assert_fail ("name.getStringRef() == getOperationName() && \"invalid operation name\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 1201 , __extension__ __PRETTY_FUNCTION__)); |
1202 | return name.getAttributeNames()[index]; |
1203 | } |
1204 | |
1205 | public: |
1206 | static arith::CmpFPredicate getPredicateByName(StringRef name); |
1207 | }; |
1208 | } // namespace arith |
1209 | } // namespace mlir |
1210 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::CmpFOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::CmpFOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
1211 | |
1212 | namespace mlir { |
1213 | namespace arith { |
1214 | |
1215 | //===----------------------------------------------------------------------===// |
1216 | // ::mlir::arith::CmpIOp declarations |
1217 | //===----------------------------------------------------------------------===// |
1218 | |
1219 | namespace detail { |
1220 | class CmpIOpGenericAdaptorBase { |
1221 | public: |
1222 | struct Properties { |
1223 | using predicateTy = ::mlir::arith::CmpIPredicateAttr; |
1224 | predicateTy predicate; |
1225 | |
1226 | auto getPredicate() { |
1227 | auto &propStorage = this->predicate; |
1228 | return propStorage.cast<::mlir::arith::CmpIPredicateAttr>(); |
1229 | } |
1230 | void setPredicate(const ::mlir::arith::CmpIPredicateAttr &propValue) { |
1231 | this->predicate = propValue; |
1232 | } |
1233 | }; |
1234 | protected: |
1235 | ::mlir::DictionaryAttr odsAttrs; |
1236 | ::std::optional<::mlir::OperationName> odsOpName; |
1237 | Properties properties; |
1238 | ::mlir::RegionRange odsRegions; |
1239 | public: |
1240 | CmpIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}); |
1241 | |
1242 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
1243 | const Properties &getProperties() { |
1244 | return properties; |
1245 | } |
1246 | |
1247 | ::mlir::DictionaryAttr getAttributes(); |
1248 | ::mlir::arith::CmpIPredicateAttr getPredicateAttr(); |
1249 | ::mlir::arith::CmpIPredicate getPredicate(); |
1250 | }; |
1251 | } // namespace detail |
1252 | template <typename RangeT> |
1253 | class CmpIOpGenericAdaptor : public detail::CmpIOpGenericAdaptorBase { |
1254 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
1255 | using Base = detail::CmpIOpGenericAdaptorBase; |
1256 | public: |
1257 | CmpIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
1258 | |
1259 | CmpIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : CmpIOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {} |
1260 | |
1261 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
1262 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
1263 | } |
1264 | |
1265 | RangeT getODSOperands(unsigned index) { |
1266 | auto valueRange = getODSOperandIndexAndLength(index); |
1267 | return {std::next(odsOperands.begin(), valueRange.first), |
1268 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
1269 | } |
1270 | |
1271 | ValueT getLhs() { |
1272 | return (*getODSOperands(0).begin()); |
1273 | } |
1274 | |
1275 | ValueT getRhs() { |
1276 | return (*getODSOperands(1).begin()); |
1277 | } |
1278 | |
1279 | RangeT getOperands() { |
1280 | return odsOperands; |
1281 | } |
1282 | |
1283 | private: |
1284 | RangeT odsOperands; |
1285 | }; |
1286 | class CmpIOpAdaptor : public CmpIOpGenericAdaptor<::mlir::ValueRange> { |
1287 | public: |
1288 | using CmpIOpGenericAdaptor::CmpIOpGenericAdaptor; |
1289 | CmpIOpAdaptor(CmpIOp op); |
1290 | |
1291 | ::mlir::LogicalResult verify(::mlir::Location loc); |
1292 | }; |
1293 | class CmpIOp : public ::mlir::Op<CmpIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::InferIntRangeInterface::Trait, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameTypeOperands, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
1294 | public: |
1295 | using Op::Op; |
1296 | using Op::print; |
1297 | using Adaptor = CmpIOpAdaptor; |
1298 | template <typename RangeT> |
1299 | using GenericAdaptor = CmpIOpGenericAdaptor<RangeT>; |
1300 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
1301 | using Properties = FoldAdaptor::Properties; |
1302 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
1303 | static ::llvm::StringRef attrNames[] = {::llvm::StringRef("predicate")}; |
1304 | return ::llvm::ArrayRef(attrNames); |
1305 | } |
1306 | |
1307 | ::mlir::StringAttr getPredicateAttrName() { |
1308 | return getAttributeNameForIndex(0); |
1309 | } |
1310 | |
1311 | static ::mlir::StringAttr getPredicateAttrName(::mlir::OperationName name) { |
1312 | return getAttributeNameForIndex(name, 0); |
1313 | } |
1314 | |
1315 | static constexpr ::llvm::StringLiteral getOperationName() { |
1316 | return ::llvm::StringLiteral("arith.cmpi"); |
1317 | } |
1318 | |
1319 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
1320 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
1321 | ::mlir::Value getLhs(); |
1322 | ::mlir::Value getRhs(); |
1323 | ::mlir::MutableOperandRange getLhsMutable(); |
1324 | ::mlir::MutableOperandRange getRhsMutable(); |
1325 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
1326 | ::mlir::Operation::result_range getODSResults(unsigned index); |
1327 | ::mlir::Value getResult(); |
1328 | static ::mlir::LogicalResult setPropertiesFromAttr(Properties &prop, ::mlir::Attribute attr, ::mlir::InFlightDiagnostic *diag); |
1329 | static ::mlir::Attribute getPropertiesAsAttr(::mlir::MLIRContext *ctx, const Properties &prop); |
1330 | static llvm::hash_code computePropertiesHash(const Properties &prop); |
1331 | static std::optional<mlir::Attribute> getInherentAttr(const Properties &prop, llvm::StringRef name); |
1332 | static void setInherentAttr(Properties &prop, llvm::StringRef name, mlir::Attribute value); |
1333 | static void populateInherentAttrs(const Properties &prop, ::mlir::NamedAttrList &attrs); |
1334 | static ::mlir::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> getDiag); |
1335 | ::mlir::arith::CmpIPredicateAttr getPredicateAttr(); |
1336 | ::mlir::arith::CmpIPredicate getPredicate(); |
1337 | void setPredicateAttr(::mlir::arith::CmpIPredicateAttr attr); |
1338 | void setPredicate(::mlir::arith::CmpIPredicate attrValue); |
1339 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::arith::CmpIPredicateAttr predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1340 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::arith::CmpIPredicateAttr predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1341 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::arith::CmpIPredicateAttr predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1342 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::arith::CmpIPredicate predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1343 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::arith::CmpIPredicate predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1344 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::arith::CmpIPredicate predicate, ::mlir::Value lhs, ::mlir::Value rhs); |
1345 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1346 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1347 | ::mlir::LogicalResult verifyInvariantsImpl(); |
1348 | ::mlir::LogicalResult verifyInvariants(); |
1349 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
1350 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
1351 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
1352 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
1353 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
1354 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
1355 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
1356 | private: |
1357 | ::mlir::StringAttr getAttributeNameForIndex(unsigned index) { |
1358 | return getAttributeNameForIndex((*this)->getName(), index); |
1359 | } |
1360 | |
1361 | static ::mlir::StringAttr getAttributeNameForIndex(::mlir::OperationName name, unsigned index) { |
1362 | assert(index < 1 && "invalid attribute index")(static_cast <bool> (index < 1 && "invalid attribute index" ) ? void (0) : __assert_fail ("index < 1 && \"invalid attribute index\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 1362 , __extension__ __PRETTY_FUNCTION__)); |
1363 | assert(name.getStringRef() == getOperationName() && "invalid operation name")(static_cast <bool> (name.getStringRef() == getOperationName () && "invalid operation name") ? void (0) : __assert_fail ("name.getStringRef() == getOperationName() && \"invalid operation name\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 1363 , __extension__ __PRETTY_FUNCTION__)); |
1364 | return name.getAttributeNames()[index]; |
1365 | } |
1366 | |
1367 | public: |
1368 | static arith::CmpIPredicate getPredicateByName(StringRef name); |
1369 | }; |
1370 | } // namespace arith |
1371 | } // namespace mlir |
1372 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::CmpIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::CmpIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
1373 | |
1374 | namespace mlir { |
1375 | namespace arith { |
1376 | |
1377 | //===----------------------------------------------------------------------===// |
1378 | // ::mlir::arith::ConstantOp declarations |
1379 | //===----------------------------------------------------------------------===// |
1380 | |
1381 | namespace detail { |
1382 | class ConstantOpGenericAdaptorBase { |
1383 | public: |
1384 | struct Properties { |
1385 | using valueTy = ::mlir::TypedAttr; |
1386 | valueTy value; |
1387 | |
1388 | auto getValue() { |
1389 | auto &propStorage = this->value; |
1390 | return propStorage.cast<::mlir::TypedAttr>(); |
1391 | } |
1392 | void setValue(const ::mlir::TypedAttr &propValue) { |
1393 | this->value = propValue; |
1394 | } |
1395 | }; |
1396 | protected: |
1397 | ::mlir::DictionaryAttr odsAttrs; |
1398 | ::std::optional<::mlir::OperationName> odsOpName; |
1399 | Properties properties; |
1400 | ::mlir::RegionRange odsRegions; |
1401 | public: |
1402 | ConstantOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}); |
1403 | |
1404 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
1405 | const Properties &getProperties() { |
1406 | return properties; |
1407 | } |
1408 | |
1409 | ::mlir::DictionaryAttr getAttributes(); |
1410 | ::mlir::TypedAttr getValueAttr(); |
1411 | ::mlir::TypedAttr getValue(); |
1412 | }; |
1413 | } // namespace detail |
1414 | template <typename RangeT> |
1415 | class ConstantOpGenericAdaptor : public detail::ConstantOpGenericAdaptorBase { |
1416 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
1417 | using Base = detail::ConstantOpGenericAdaptorBase; |
1418 | public: |
1419 | ConstantOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
1420 | |
1421 | ConstantOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : ConstantOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {} |
1422 | |
1423 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
1424 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
1425 | } |
1426 | |
1427 | RangeT getODSOperands(unsigned index) { |
1428 | auto valueRange = getODSOperandIndexAndLength(index); |
1429 | return {std::next(odsOperands.begin(), valueRange.first), |
1430 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
1431 | } |
1432 | |
1433 | RangeT getOperands() { |
1434 | return odsOperands; |
1435 | } |
1436 | |
1437 | private: |
1438 | RangeT odsOperands; |
1439 | }; |
1440 | class ConstantOpAdaptor : public ConstantOpGenericAdaptor<::mlir::ValueRange> { |
1441 | public: |
1442 | using ConstantOpGenericAdaptor::ConstantOpGenericAdaptor; |
1443 | ConstantOpAdaptor(ConstantOp op); |
1444 | |
1445 | ::mlir::LogicalResult verify(::mlir::Location loc); |
1446 | }; |
1447 | class ConstantOp : public ::mlir::Op<ConstantOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::ZeroOperands, ::mlir::OpTrait::OpInvariants, ::mlir::OpTrait::ConstantLike, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpAsmOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::InferTypeOpInterface::Trait> { |
1448 | public: |
1449 | using Op::Op; |
1450 | using Op::print; |
1451 | using Adaptor = ConstantOpAdaptor; |
1452 | template <typename RangeT> |
1453 | using GenericAdaptor = ConstantOpGenericAdaptor<RangeT>; |
1454 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
1455 | using Properties = FoldAdaptor::Properties; |
1456 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
1457 | static ::llvm::StringRef attrNames[] = {::llvm::StringRef("value")}; |
1458 | return ::llvm::ArrayRef(attrNames); |
1459 | } |
1460 | |
1461 | ::mlir::StringAttr getValueAttrName() { |
1462 | return getAttributeNameForIndex(0); |
1463 | } |
1464 | |
1465 | static ::mlir::StringAttr getValueAttrName(::mlir::OperationName name) { |
1466 | return getAttributeNameForIndex(name, 0); |
1467 | } |
1468 | |
1469 | static constexpr ::llvm::StringLiteral getOperationName() { |
1470 | return ::llvm::StringLiteral("arith.constant"); |
1471 | } |
1472 | |
1473 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
1474 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
1475 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
1476 | ::mlir::Operation::result_range getODSResults(unsigned index); |
1477 | ::mlir::Value getResult(); |
1478 | static ::mlir::LogicalResult setPropertiesFromAttr(Properties &prop, ::mlir::Attribute attr, ::mlir::InFlightDiagnostic *diag); |
1479 | static ::mlir::Attribute getPropertiesAsAttr(::mlir::MLIRContext *ctx, const Properties &prop); |
1480 | static llvm::hash_code computePropertiesHash(const Properties &prop); |
1481 | static std::optional<mlir::Attribute> getInherentAttr(const Properties &prop, llvm::StringRef name); |
1482 | static void setInherentAttr(Properties &prop, llvm::StringRef name, mlir::Attribute value); |
1483 | static void populateInherentAttrs(const Properties &prop, ::mlir::NamedAttrList &attrs); |
1484 | static ::mlir::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> getDiag); |
1485 | ::mlir::TypedAttr getValueAttr(); |
1486 | ::mlir::TypedAttr getValue(); |
1487 | void setValueAttr(::mlir::TypedAttr attr); |
1488 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::TypedAttr value); |
1489 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypedAttr value); |
1490 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::TypedAttr value); |
1491 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1492 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1493 | ::mlir::LogicalResult verifyInvariantsImpl(); |
1494 | ::mlir::LogicalResult verifyInvariants(); |
1495 | ::mlir::LogicalResult verify(); |
1496 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
1497 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
1498 | void getAsmResultNames(::mlir::OpAsmSetValueNameFn setNameFn); |
1499 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
1500 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
1501 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
1502 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
1503 | private: |
1504 | ::mlir::StringAttr getAttributeNameForIndex(unsigned index) { |
1505 | return getAttributeNameForIndex((*this)->getName(), index); |
1506 | } |
1507 | |
1508 | static ::mlir::StringAttr getAttributeNameForIndex(::mlir::OperationName name, unsigned index) { |
1509 | assert(index < 1 && "invalid attribute index")(static_cast <bool> (index < 1 && "invalid attribute index" ) ? void (0) : __assert_fail ("index < 1 && \"invalid attribute index\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 1509 , __extension__ __PRETTY_FUNCTION__)); |
1510 | assert(name.getStringRef() == getOperationName() && "invalid operation name")(static_cast <bool> (name.getStringRef() == getOperationName () && "invalid operation name") ? void (0) : __assert_fail ("name.getStringRef() == getOperationName() && \"invalid operation name\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 1510 , __extension__ __PRETTY_FUNCTION__)); |
1511 | return name.getAttributeNames()[index]; |
1512 | } |
1513 | |
1514 | public: |
1515 | /// Whether the constant op can be constructed with a particular value and |
1516 | /// type. |
1517 | static bool isBuildableWith(Attribute value, Type type); |
1518 | |
1519 | /// Build the constant op with `value` and `type` if possible, otherwise |
1520 | /// returns null. |
1521 | static ConstantOp materialize(OpBuilder &builder, Attribute value, |
1522 | Type type, Location loc); |
1523 | }; |
1524 | } // namespace arith |
1525 | } // namespace mlir |
1526 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::ConstantOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::ConstantOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
1527 | |
1528 | namespace mlir { |
1529 | namespace arith { |
1530 | |
1531 | //===----------------------------------------------------------------------===// |
1532 | // ::mlir::arith::DivFOp declarations |
1533 | //===----------------------------------------------------------------------===// |
1534 | |
1535 | namespace detail { |
1536 | class DivFOpGenericAdaptorBase { |
1537 | public: |
1538 | struct Properties { |
1539 | using fastmathTy = ::mlir::arith::FastMathFlagsAttr; |
1540 | fastmathTy fastmath; |
1541 | |
1542 | auto getFastmath() { |
1543 | auto &propStorage = this->fastmath; |
1544 | return propStorage.dyn_cast_or_null<::mlir::arith::FastMathFlagsAttr>(); |
1545 | } |
1546 | void setFastmath(const ::mlir::arith::FastMathFlagsAttr &propValue) { |
1547 | this->fastmath = propValue; |
1548 | } |
1549 | }; |
1550 | protected: |
1551 | ::mlir::DictionaryAttr odsAttrs; |
1552 | ::std::optional<::mlir::OperationName> odsOpName; |
1553 | Properties properties; |
1554 | ::mlir::RegionRange odsRegions; |
1555 | public: |
1556 | DivFOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}); |
1557 | |
1558 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
1559 | const Properties &getProperties() { |
1560 | return properties; |
1561 | } |
1562 | |
1563 | ::mlir::DictionaryAttr getAttributes(); |
1564 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
1565 | ::mlir::arith::FastMathFlags getFastmath(); |
1566 | }; |
1567 | } // namespace detail |
1568 | template <typename RangeT> |
1569 | class DivFOpGenericAdaptor : public detail::DivFOpGenericAdaptorBase { |
1570 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
1571 | using Base = detail::DivFOpGenericAdaptorBase; |
1572 | public: |
1573 | DivFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
1574 | |
1575 | DivFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : DivFOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {} |
1576 | |
1577 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
1578 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
1579 | } |
1580 | |
1581 | RangeT getODSOperands(unsigned index) { |
1582 | auto valueRange = getODSOperandIndexAndLength(index); |
1583 | return {std::next(odsOperands.begin(), valueRange.first), |
1584 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
1585 | } |
1586 | |
1587 | ValueT getLhs() { |
1588 | return (*getODSOperands(0).begin()); |
1589 | } |
1590 | |
1591 | ValueT getRhs() { |
1592 | return (*getODSOperands(1).begin()); |
1593 | } |
1594 | |
1595 | RangeT getOperands() { |
1596 | return odsOperands; |
1597 | } |
1598 | |
1599 | private: |
1600 | RangeT odsOperands; |
1601 | }; |
1602 | class DivFOpAdaptor : public DivFOpGenericAdaptor<::mlir::ValueRange> { |
1603 | public: |
1604 | using DivFOpGenericAdaptor::DivFOpGenericAdaptor; |
1605 | DivFOpAdaptor(DivFOp op); |
1606 | |
1607 | ::mlir::LogicalResult verify(::mlir::Location loc); |
1608 | }; |
1609 | class DivFOp : public ::mlir::Op<DivFOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::arith::ArithFastMathInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
1610 | public: |
1611 | using Op::Op; |
1612 | using Op::print; |
1613 | using Adaptor = DivFOpAdaptor; |
1614 | template <typename RangeT> |
1615 | using GenericAdaptor = DivFOpGenericAdaptor<RangeT>; |
1616 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
1617 | using Properties = FoldAdaptor::Properties; |
1618 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
1619 | static ::llvm::StringRef attrNames[] = {::llvm::StringRef("fastmath")}; |
1620 | return ::llvm::ArrayRef(attrNames); |
1621 | } |
1622 | |
1623 | ::mlir::StringAttr getFastmathAttrName() { |
1624 | return getAttributeNameForIndex(0); |
1625 | } |
1626 | |
1627 | static ::mlir::StringAttr getFastmathAttrName(::mlir::OperationName name) { |
1628 | return getAttributeNameForIndex(name, 0); |
1629 | } |
1630 | |
1631 | static constexpr ::llvm::StringLiteral getOperationName() { |
1632 | return ::llvm::StringLiteral("arith.divf"); |
1633 | } |
1634 | |
1635 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
1636 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
1637 | ::mlir::Value getLhs(); |
1638 | ::mlir::Value getRhs(); |
1639 | ::mlir::MutableOperandRange getLhsMutable(); |
1640 | ::mlir::MutableOperandRange getRhsMutable(); |
1641 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
1642 | ::mlir::Operation::result_range getODSResults(unsigned index); |
1643 | ::mlir::Value getResult(); |
1644 | static ::mlir::LogicalResult setPropertiesFromAttr(Properties &prop, ::mlir::Attribute attr, ::mlir::InFlightDiagnostic *diag); |
1645 | static ::mlir::Attribute getPropertiesAsAttr(::mlir::MLIRContext *ctx, const Properties &prop); |
1646 | static llvm::hash_code computePropertiesHash(const Properties &prop); |
1647 | static std::optional<mlir::Attribute> getInherentAttr(const Properties &prop, llvm::StringRef name); |
1648 | static void setInherentAttr(Properties &prop, llvm::StringRef name, mlir::Attribute value); |
1649 | static void populateInherentAttrs(const Properties &prop, ::mlir::NamedAttrList &attrs); |
1650 | static ::mlir::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> getDiag); |
1651 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
1652 | ::mlir::arith::FastMathFlags getFastmath(); |
1653 | void setFastmathAttr(::mlir::arith::FastMathFlagsAttr attr); |
1654 | void setFastmath(::mlir::arith::FastMathFlags attrValue); |
1655 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
1656 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
1657 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
1658 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
1659 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
1660 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
1661 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1662 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1663 | static void populateDefaultProperties(::mlir::OperationName opName, Properties &properties); |
1664 | ::mlir::LogicalResult verifyInvariantsImpl(); |
1665 | ::mlir::LogicalResult verifyInvariants(); |
1666 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
1667 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
1668 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
1669 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
1670 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
1671 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
1672 | private: |
1673 | ::mlir::StringAttr getAttributeNameForIndex(unsigned index) { |
1674 | return getAttributeNameForIndex((*this)->getName(), index); |
1675 | } |
1676 | |
1677 | static ::mlir::StringAttr getAttributeNameForIndex(::mlir::OperationName name, unsigned index) { |
1678 | assert(index < 1 && "invalid attribute index")(static_cast <bool> (index < 1 && "invalid attribute index" ) ? void (0) : __assert_fail ("index < 1 && \"invalid attribute index\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 1678 , __extension__ __PRETTY_FUNCTION__)); |
1679 | assert(name.getStringRef() == getOperationName() && "invalid operation name")(static_cast <bool> (name.getStringRef() == getOperationName () && "invalid operation name") ? void (0) : __assert_fail ("name.getStringRef() == getOperationName() && \"invalid operation name\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 1679 , __extension__ __PRETTY_FUNCTION__)); |
1680 | return name.getAttributeNames()[index]; |
1681 | } |
1682 | |
1683 | public: |
1684 | }; |
1685 | } // namespace arith |
1686 | } // namespace mlir |
1687 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::DivFOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::DivFOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
1688 | |
1689 | namespace mlir { |
1690 | namespace arith { |
1691 | |
1692 | //===----------------------------------------------------------------------===// |
1693 | // ::mlir::arith::DivSIOp declarations |
1694 | //===----------------------------------------------------------------------===// |
1695 | |
1696 | namespace detail { |
1697 | class DivSIOpGenericAdaptorBase { |
1698 | public: |
1699 | protected: |
1700 | ::mlir::DictionaryAttr odsAttrs; |
1701 | ::std::optional<::mlir::OperationName> odsOpName; |
1702 | ::mlir::RegionRange odsRegions; |
1703 | public: |
1704 | DivSIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
1705 | |
1706 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
1707 | ::mlir::DictionaryAttr getAttributes(); |
1708 | }; |
1709 | } // namespace detail |
1710 | template <typename RangeT> |
1711 | class DivSIOpGenericAdaptor : public detail::DivSIOpGenericAdaptorBase { |
1712 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
1713 | using Base = detail::DivSIOpGenericAdaptorBase; |
1714 | public: |
1715 | DivSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
1716 | |
1717 | DivSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : DivSIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
1718 | |
1719 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
1720 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
1721 | } |
1722 | |
1723 | RangeT getODSOperands(unsigned index) { |
1724 | auto valueRange = getODSOperandIndexAndLength(index); |
1725 | return {std::next(odsOperands.begin(), valueRange.first), |
1726 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
1727 | } |
1728 | |
1729 | ValueT getLhs() { |
1730 | return (*getODSOperands(0).begin()); |
1731 | } |
1732 | |
1733 | ValueT getRhs() { |
1734 | return (*getODSOperands(1).begin()); |
1735 | } |
1736 | |
1737 | RangeT getOperands() { |
1738 | return odsOperands; |
1739 | } |
1740 | |
1741 | private: |
1742 | RangeT odsOperands; |
1743 | }; |
1744 | class DivSIOpAdaptor : public DivSIOpGenericAdaptor<::mlir::ValueRange> { |
1745 | public: |
1746 | using DivSIOpGenericAdaptor::DivSIOpGenericAdaptor; |
1747 | DivSIOpAdaptor(DivSIOp op); |
1748 | |
1749 | ::mlir::LogicalResult verify(::mlir::Location loc); |
1750 | }; |
1751 | class DivSIOp : public ::mlir::Op<DivSIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
1752 | public: |
1753 | using Op::Op; |
1754 | using Op::print; |
1755 | using Adaptor = DivSIOpAdaptor; |
1756 | template <typename RangeT> |
1757 | using GenericAdaptor = DivSIOpGenericAdaptor<RangeT>; |
1758 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
1759 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
1760 | return {}; |
1761 | } |
1762 | |
1763 | static constexpr ::llvm::StringLiteral getOperationName() { |
1764 | return ::llvm::StringLiteral("arith.divsi"); |
1765 | } |
1766 | |
1767 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
1768 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
1769 | ::mlir::Value getLhs(); |
1770 | ::mlir::Value getRhs(); |
1771 | ::mlir::MutableOperandRange getLhsMutable(); |
1772 | ::mlir::MutableOperandRange getRhsMutable(); |
1773 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
1774 | ::mlir::Operation::result_range getODSResults(unsigned index); |
1775 | ::mlir::Value getResult(); |
1776 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
1777 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
1778 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
1779 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1780 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1781 | ::mlir::LogicalResult verifyInvariantsImpl(); |
1782 | ::mlir::LogicalResult verifyInvariants(); |
1783 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
1784 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
1785 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
1786 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
1787 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
1788 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
1789 | public: |
1790 | /// Interface method for ConditionallySpeculatable. |
1791 | Speculation::Speculatability getSpeculatability(); |
1792 | }; |
1793 | } // namespace arith |
1794 | } // namespace mlir |
1795 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::DivSIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::DivSIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
1796 | |
1797 | namespace mlir { |
1798 | namespace arith { |
1799 | |
1800 | //===----------------------------------------------------------------------===// |
1801 | // ::mlir::arith::DivUIOp declarations |
1802 | //===----------------------------------------------------------------------===// |
1803 | |
1804 | namespace detail { |
1805 | class DivUIOpGenericAdaptorBase { |
1806 | public: |
1807 | protected: |
1808 | ::mlir::DictionaryAttr odsAttrs; |
1809 | ::std::optional<::mlir::OperationName> odsOpName; |
1810 | ::mlir::RegionRange odsRegions; |
1811 | public: |
1812 | DivUIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
1813 | |
1814 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
1815 | ::mlir::DictionaryAttr getAttributes(); |
1816 | }; |
1817 | } // namespace detail |
1818 | template <typename RangeT> |
1819 | class DivUIOpGenericAdaptor : public detail::DivUIOpGenericAdaptorBase { |
1820 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
1821 | using Base = detail::DivUIOpGenericAdaptorBase; |
1822 | public: |
1823 | DivUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
1824 | |
1825 | DivUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : DivUIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
1826 | |
1827 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
1828 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
1829 | } |
1830 | |
1831 | RangeT getODSOperands(unsigned index) { |
1832 | auto valueRange = getODSOperandIndexAndLength(index); |
1833 | return {std::next(odsOperands.begin(), valueRange.first), |
1834 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
1835 | } |
1836 | |
1837 | ValueT getLhs() { |
1838 | return (*getODSOperands(0).begin()); |
1839 | } |
1840 | |
1841 | ValueT getRhs() { |
1842 | return (*getODSOperands(1).begin()); |
1843 | } |
1844 | |
1845 | RangeT getOperands() { |
1846 | return odsOperands; |
1847 | } |
1848 | |
1849 | private: |
1850 | RangeT odsOperands; |
1851 | }; |
1852 | class DivUIOpAdaptor : public DivUIOpGenericAdaptor<::mlir::ValueRange> { |
1853 | public: |
1854 | using DivUIOpGenericAdaptor::DivUIOpGenericAdaptor; |
1855 | DivUIOpAdaptor(DivUIOp op); |
1856 | |
1857 | ::mlir::LogicalResult verify(::mlir::Location loc); |
1858 | }; |
1859 | class DivUIOp : public ::mlir::Op<DivUIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
1860 | public: |
1861 | using Op::Op; |
1862 | using Op::print; |
1863 | using Adaptor = DivUIOpAdaptor; |
1864 | template <typename RangeT> |
1865 | using GenericAdaptor = DivUIOpGenericAdaptor<RangeT>; |
1866 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
1867 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
1868 | return {}; |
1869 | } |
1870 | |
1871 | static constexpr ::llvm::StringLiteral getOperationName() { |
1872 | return ::llvm::StringLiteral("arith.divui"); |
1873 | } |
1874 | |
1875 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
1876 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
1877 | ::mlir::Value getLhs(); |
1878 | ::mlir::Value getRhs(); |
1879 | ::mlir::MutableOperandRange getLhsMutable(); |
1880 | ::mlir::MutableOperandRange getRhsMutable(); |
1881 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
1882 | ::mlir::Operation::result_range getODSResults(unsigned index); |
1883 | ::mlir::Value getResult(); |
1884 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
1885 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
1886 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
1887 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1888 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1889 | ::mlir::LogicalResult verifyInvariantsImpl(); |
1890 | ::mlir::LogicalResult verifyInvariants(); |
1891 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
1892 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
1893 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
1894 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
1895 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
1896 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
1897 | public: |
1898 | /// Interface method for ConditionallySpeculatable. |
1899 | Speculation::Speculatability getSpeculatability(); |
1900 | }; |
1901 | } // namespace arith |
1902 | } // namespace mlir |
1903 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::DivUIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::DivUIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
1904 | |
1905 | namespace mlir { |
1906 | namespace arith { |
1907 | |
1908 | //===----------------------------------------------------------------------===// |
1909 | // ::mlir::arith::ExtFOp declarations |
1910 | //===----------------------------------------------------------------------===// |
1911 | |
1912 | namespace detail { |
1913 | class ExtFOpGenericAdaptorBase { |
1914 | public: |
1915 | protected: |
1916 | ::mlir::DictionaryAttr odsAttrs; |
1917 | ::std::optional<::mlir::OperationName> odsOpName; |
1918 | ::mlir::RegionRange odsRegions; |
1919 | public: |
1920 | ExtFOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
1921 | |
1922 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
1923 | ::mlir::DictionaryAttr getAttributes(); |
1924 | }; |
1925 | } // namespace detail |
1926 | template <typename RangeT> |
1927 | class ExtFOpGenericAdaptor : public detail::ExtFOpGenericAdaptorBase { |
1928 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
1929 | using Base = detail::ExtFOpGenericAdaptorBase; |
1930 | public: |
1931 | ExtFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
1932 | |
1933 | ExtFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : ExtFOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
1934 | |
1935 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
1936 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
1937 | } |
1938 | |
1939 | RangeT getODSOperands(unsigned index) { |
1940 | auto valueRange = getODSOperandIndexAndLength(index); |
1941 | return {std::next(odsOperands.begin(), valueRange.first), |
1942 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
1943 | } |
1944 | |
1945 | ValueT getIn() { |
1946 | return (*getODSOperands(0).begin()); |
1947 | } |
1948 | |
1949 | RangeT getOperands() { |
1950 | return odsOperands; |
1951 | } |
1952 | |
1953 | private: |
1954 | RangeT odsOperands; |
1955 | }; |
1956 | class ExtFOpAdaptor : public ExtFOpGenericAdaptor<::mlir::ValueRange> { |
1957 | public: |
1958 | using ExtFOpGenericAdaptor::ExtFOpGenericAdaptor; |
1959 | ExtFOpAdaptor(ExtFOp op); |
1960 | |
1961 | ::mlir::LogicalResult verify(::mlir::Location loc); |
1962 | }; |
1963 | class ExtFOp : public ::mlir::Op<ExtFOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
1964 | public: |
1965 | using Op::Op; |
1966 | using Op::print; |
1967 | using Adaptor = ExtFOpAdaptor; |
1968 | template <typename RangeT> |
1969 | using GenericAdaptor = ExtFOpGenericAdaptor<RangeT>; |
1970 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
1971 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
1972 | return {}; |
1973 | } |
1974 | |
1975 | static constexpr ::llvm::StringLiteral getOperationName() { |
1976 | return ::llvm::StringLiteral("arith.extf"); |
1977 | } |
1978 | |
1979 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
1980 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
1981 | ::mlir::Value getIn(); |
1982 | ::mlir::MutableOperandRange getInMutable(); |
1983 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
1984 | ::mlir::Operation::result_range getODSResults(unsigned index); |
1985 | ::mlir::Value getOut(); |
1986 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
1987 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
1988 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
1989 | ::mlir::LogicalResult verifyInvariantsImpl(); |
1990 | ::mlir::LogicalResult verifyInvariants(); |
1991 | ::mlir::LogicalResult verify(); |
1992 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
1993 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
1994 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
1995 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
1996 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
1997 | public: |
1998 | }; |
1999 | } // namespace arith |
2000 | } // namespace mlir |
2001 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::ExtFOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::ExtFOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
2002 | |
2003 | namespace mlir { |
2004 | namespace arith { |
2005 | |
2006 | //===----------------------------------------------------------------------===// |
2007 | // ::mlir::arith::ExtSIOp declarations |
2008 | //===----------------------------------------------------------------------===// |
2009 | |
2010 | namespace detail { |
2011 | class ExtSIOpGenericAdaptorBase { |
2012 | public: |
2013 | protected: |
2014 | ::mlir::DictionaryAttr odsAttrs; |
2015 | ::std::optional<::mlir::OperationName> odsOpName; |
2016 | ::mlir::RegionRange odsRegions; |
2017 | public: |
2018 | ExtSIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
2019 | |
2020 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
2021 | ::mlir::DictionaryAttr getAttributes(); |
2022 | }; |
2023 | } // namespace detail |
2024 | template <typename RangeT> |
2025 | class ExtSIOpGenericAdaptor : public detail::ExtSIOpGenericAdaptorBase { |
2026 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
2027 | using Base = detail::ExtSIOpGenericAdaptorBase; |
2028 | public: |
2029 | ExtSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
2030 | |
2031 | ExtSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : ExtSIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
2032 | |
2033 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
2034 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
2035 | } |
2036 | |
2037 | RangeT getODSOperands(unsigned index) { |
2038 | auto valueRange = getODSOperandIndexAndLength(index); |
2039 | return {std::next(odsOperands.begin(), valueRange.first), |
2040 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
2041 | } |
2042 | |
2043 | ValueT getIn() { |
2044 | return (*getODSOperands(0).begin()); |
2045 | } |
2046 | |
2047 | RangeT getOperands() { |
2048 | return odsOperands; |
2049 | } |
2050 | |
2051 | private: |
2052 | RangeT odsOperands; |
2053 | }; |
2054 | class ExtSIOpAdaptor : public ExtSIOpGenericAdaptor<::mlir::ValueRange> { |
2055 | public: |
2056 | using ExtSIOpGenericAdaptor::ExtSIOpGenericAdaptor; |
2057 | ExtSIOpAdaptor(ExtSIOp op); |
2058 | |
2059 | ::mlir::LogicalResult verify(::mlir::Location loc); |
2060 | }; |
2061 | class ExtSIOp : public ::mlir::Op<ExtSIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::InferIntRangeInterface::Trait, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
2062 | public: |
2063 | using Op::Op; |
2064 | using Op::print; |
2065 | using Adaptor = ExtSIOpAdaptor; |
2066 | template <typename RangeT> |
2067 | using GenericAdaptor = ExtSIOpGenericAdaptor<RangeT>; |
2068 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
2069 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
2070 | return {}; |
2071 | } |
2072 | |
2073 | static constexpr ::llvm::StringLiteral getOperationName() { |
2074 | return ::llvm::StringLiteral("arith.extsi"); |
2075 | } |
2076 | |
2077 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
2078 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
2079 | ::mlir::Value getIn(); |
2080 | ::mlir::MutableOperandRange getInMutable(); |
2081 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
2082 | ::mlir::Operation::result_range getODSResults(unsigned index); |
2083 | ::mlir::Value getOut(); |
2084 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
2085 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
2086 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2087 | ::mlir::LogicalResult verifyInvariantsImpl(); |
2088 | ::mlir::LogicalResult verifyInvariants(); |
2089 | ::mlir::LogicalResult verify(); |
2090 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
2091 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
2092 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
2093 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
2094 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
2095 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
2096 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
2097 | public: |
2098 | }; |
2099 | } // namespace arith |
2100 | } // namespace mlir |
2101 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::ExtSIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::ExtSIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
2102 | |
2103 | namespace mlir { |
2104 | namespace arith { |
2105 | |
2106 | //===----------------------------------------------------------------------===// |
2107 | // ::mlir::arith::ExtUIOp declarations |
2108 | //===----------------------------------------------------------------------===// |
2109 | |
2110 | namespace detail { |
2111 | class ExtUIOpGenericAdaptorBase { |
2112 | public: |
2113 | protected: |
2114 | ::mlir::DictionaryAttr odsAttrs; |
2115 | ::std::optional<::mlir::OperationName> odsOpName; |
2116 | ::mlir::RegionRange odsRegions; |
2117 | public: |
2118 | ExtUIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
2119 | |
2120 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
2121 | ::mlir::DictionaryAttr getAttributes(); |
2122 | }; |
2123 | } // namespace detail |
2124 | template <typename RangeT> |
2125 | class ExtUIOpGenericAdaptor : public detail::ExtUIOpGenericAdaptorBase { |
2126 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
2127 | using Base = detail::ExtUIOpGenericAdaptorBase; |
2128 | public: |
2129 | ExtUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
2130 | |
2131 | ExtUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : ExtUIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
2132 | |
2133 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
2134 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
2135 | } |
2136 | |
2137 | RangeT getODSOperands(unsigned index) { |
2138 | auto valueRange = getODSOperandIndexAndLength(index); |
2139 | return {std::next(odsOperands.begin(), valueRange.first), |
2140 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
2141 | } |
2142 | |
2143 | ValueT getIn() { |
2144 | return (*getODSOperands(0).begin()); |
2145 | } |
2146 | |
2147 | RangeT getOperands() { |
2148 | return odsOperands; |
2149 | } |
2150 | |
2151 | private: |
2152 | RangeT odsOperands; |
2153 | }; |
2154 | class ExtUIOpAdaptor : public ExtUIOpGenericAdaptor<::mlir::ValueRange> { |
2155 | public: |
2156 | using ExtUIOpGenericAdaptor::ExtUIOpGenericAdaptor; |
2157 | ExtUIOpAdaptor(ExtUIOp op); |
2158 | |
2159 | ::mlir::LogicalResult verify(::mlir::Location loc); |
2160 | }; |
2161 | class ExtUIOp : public ::mlir::Op<ExtUIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::InferIntRangeInterface::Trait, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
2162 | public: |
2163 | using Op::Op; |
2164 | using Op::print; |
2165 | using Adaptor = ExtUIOpAdaptor; |
2166 | template <typename RangeT> |
2167 | using GenericAdaptor = ExtUIOpGenericAdaptor<RangeT>; |
2168 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
2169 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
2170 | return {}; |
2171 | } |
2172 | |
2173 | static constexpr ::llvm::StringLiteral getOperationName() { |
2174 | return ::llvm::StringLiteral("arith.extui"); |
2175 | } |
2176 | |
2177 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
2178 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
2179 | ::mlir::Value getIn(); |
2180 | ::mlir::MutableOperandRange getInMutable(); |
2181 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
2182 | ::mlir::Operation::result_range getODSResults(unsigned index); |
2183 | ::mlir::Value getOut(); |
2184 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
2185 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
2186 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2187 | ::mlir::LogicalResult verifyInvariantsImpl(); |
2188 | ::mlir::LogicalResult verifyInvariants(); |
2189 | ::mlir::LogicalResult verify(); |
2190 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
2191 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
2192 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
2193 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
2194 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
2195 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
2196 | public: |
2197 | }; |
2198 | } // namespace arith |
2199 | } // namespace mlir |
2200 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::ExtUIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::ExtUIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
2201 | |
2202 | namespace mlir { |
2203 | namespace arith { |
2204 | |
2205 | //===----------------------------------------------------------------------===// |
2206 | // ::mlir::arith::FPToSIOp declarations |
2207 | //===----------------------------------------------------------------------===// |
2208 | |
2209 | namespace detail { |
2210 | class FPToSIOpGenericAdaptorBase { |
2211 | public: |
2212 | protected: |
2213 | ::mlir::DictionaryAttr odsAttrs; |
2214 | ::std::optional<::mlir::OperationName> odsOpName; |
2215 | ::mlir::RegionRange odsRegions; |
2216 | public: |
2217 | FPToSIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
2218 | |
2219 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
2220 | ::mlir::DictionaryAttr getAttributes(); |
2221 | }; |
2222 | } // namespace detail |
2223 | template <typename RangeT> |
2224 | class FPToSIOpGenericAdaptor : public detail::FPToSIOpGenericAdaptorBase { |
2225 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
2226 | using Base = detail::FPToSIOpGenericAdaptorBase; |
2227 | public: |
2228 | FPToSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
2229 | |
2230 | FPToSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : FPToSIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
2231 | |
2232 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
2233 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
2234 | } |
2235 | |
2236 | RangeT getODSOperands(unsigned index) { |
2237 | auto valueRange = getODSOperandIndexAndLength(index); |
2238 | return {std::next(odsOperands.begin(), valueRange.first), |
2239 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
2240 | } |
2241 | |
2242 | ValueT getIn() { |
2243 | return (*getODSOperands(0).begin()); |
2244 | } |
2245 | |
2246 | RangeT getOperands() { |
2247 | return odsOperands; |
2248 | } |
2249 | |
2250 | private: |
2251 | RangeT odsOperands; |
2252 | }; |
2253 | class FPToSIOpAdaptor : public FPToSIOpGenericAdaptor<::mlir::ValueRange> { |
2254 | public: |
2255 | using FPToSIOpGenericAdaptor::FPToSIOpGenericAdaptor; |
2256 | FPToSIOpAdaptor(FPToSIOp op); |
2257 | |
2258 | ::mlir::LogicalResult verify(::mlir::Location loc); |
2259 | }; |
2260 | class FPToSIOp : public ::mlir::Op<FPToSIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
2261 | public: |
2262 | using Op::Op; |
2263 | using Op::print; |
2264 | using Adaptor = FPToSIOpAdaptor; |
2265 | template <typename RangeT> |
2266 | using GenericAdaptor = FPToSIOpGenericAdaptor<RangeT>; |
2267 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
2268 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
2269 | return {}; |
2270 | } |
2271 | |
2272 | static constexpr ::llvm::StringLiteral getOperationName() { |
2273 | return ::llvm::StringLiteral("arith.fptosi"); |
2274 | } |
2275 | |
2276 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
2277 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
2278 | ::mlir::Value getIn(); |
2279 | ::mlir::MutableOperandRange getInMutable(); |
2280 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
2281 | ::mlir::Operation::result_range getODSResults(unsigned index); |
2282 | ::mlir::Value getOut(); |
2283 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
2284 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
2285 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2286 | ::mlir::LogicalResult verifyInvariantsImpl(); |
2287 | ::mlir::LogicalResult verifyInvariants(); |
2288 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
2289 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
2290 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
2291 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
2292 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
2293 | public: |
2294 | }; |
2295 | } // namespace arith |
2296 | } // namespace mlir |
2297 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::FPToSIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::FPToSIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
2298 | |
2299 | namespace mlir { |
2300 | namespace arith { |
2301 | |
2302 | //===----------------------------------------------------------------------===// |
2303 | // ::mlir::arith::FPToUIOp declarations |
2304 | //===----------------------------------------------------------------------===// |
2305 | |
2306 | namespace detail { |
2307 | class FPToUIOpGenericAdaptorBase { |
2308 | public: |
2309 | protected: |
2310 | ::mlir::DictionaryAttr odsAttrs; |
2311 | ::std::optional<::mlir::OperationName> odsOpName; |
2312 | ::mlir::RegionRange odsRegions; |
2313 | public: |
2314 | FPToUIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
2315 | |
2316 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
2317 | ::mlir::DictionaryAttr getAttributes(); |
2318 | }; |
2319 | } // namespace detail |
2320 | template <typename RangeT> |
2321 | class FPToUIOpGenericAdaptor : public detail::FPToUIOpGenericAdaptorBase { |
2322 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
2323 | using Base = detail::FPToUIOpGenericAdaptorBase; |
2324 | public: |
2325 | FPToUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
2326 | |
2327 | FPToUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : FPToUIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
2328 | |
2329 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
2330 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
2331 | } |
2332 | |
2333 | RangeT getODSOperands(unsigned index) { |
2334 | auto valueRange = getODSOperandIndexAndLength(index); |
2335 | return {std::next(odsOperands.begin(), valueRange.first), |
2336 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
2337 | } |
2338 | |
2339 | ValueT getIn() { |
2340 | return (*getODSOperands(0).begin()); |
2341 | } |
2342 | |
2343 | RangeT getOperands() { |
2344 | return odsOperands; |
2345 | } |
2346 | |
2347 | private: |
2348 | RangeT odsOperands; |
2349 | }; |
2350 | class FPToUIOpAdaptor : public FPToUIOpGenericAdaptor<::mlir::ValueRange> { |
2351 | public: |
2352 | using FPToUIOpGenericAdaptor::FPToUIOpGenericAdaptor; |
2353 | FPToUIOpAdaptor(FPToUIOp op); |
2354 | |
2355 | ::mlir::LogicalResult verify(::mlir::Location loc); |
2356 | }; |
2357 | class FPToUIOp : public ::mlir::Op<FPToUIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
2358 | public: |
2359 | using Op::Op; |
2360 | using Op::print; |
2361 | using Adaptor = FPToUIOpAdaptor; |
2362 | template <typename RangeT> |
2363 | using GenericAdaptor = FPToUIOpGenericAdaptor<RangeT>; |
2364 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
2365 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
2366 | return {}; |
2367 | } |
2368 | |
2369 | static constexpr ::llvm::StringLiteral getOperationName() { |
2370 | return ::llvm::StringLiteral("arith.fptoui"); |
2371 | } |
2372 | |
2373 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
2374 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
2375 | ::mlir::Value getIn(); |
2376 | ::mlir::MutableOperandRange getInMutable(); |
2377 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
2378 | ::mlir::Operation::result_range getODSResults(unsigned index); |
2379 | ::mlir::Value getOut(); |
2380 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
2381 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
2382 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2383 | ::mlir::LogicalResult verifyInvariantsImpl(); |
2384 | ::mlir::LogicalResult verifyInvariants(); |
2385 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
2386 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
2387 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
2388 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
2389 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
2390 | public: |
2391 | }; |
2392 | } // namespace arith |
2393 | } // namespace mlir |
2394 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::FPToUIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::FPToUIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
2395 | |
2396 | namespace mlir { |
2397 | namespace arith { |
2398 | |
2399 | //===----------------------------------------------------------------------===// |
2400 | // ::mlir::arith::FloorDivSIOp declarations |
2401 | //===----------------------------------------------------------------------===// |
2402 | |
2403 | namespace detail { |
2404 | class FloorDivSIOpGenericAdaptorBase { |
2405 | public: |
2406 | protected: |
2407 | ::mlir::DictionaryAttr odsAttrs; |
2408 | ::std::optional<::mlir::OperationName> odsOpName; |
2409 | ::mlir::RegionRange odsRegions; |
2410 | public: |
2411 | FloorDivSIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
2412 | |
2413 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
2414 | ::mlir::DictionaryAttr getAttributes(); |
2415 | }; |
2416 | } // namespace detail |
2417 | template <typename RangeT> |
2418 | class FloorDivSIOpGenericAdaptor : public detail::FloorDivSIOpGenericAdaptorBase { |
2419 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
2420 | using Base = detail::FloorDivSIOpGenericAdaptorBase; |
2421 | public: |
2422 | FloorDivSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
2423 | |
2424 | FloorDivSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : FloorDivSIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
2425 | |
2426 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
2427 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
2428 | } |
2429 | |
2430 | RangeT getODSOperands(unsigned index) { |
2431 | auto valueRange = getODSOperandIndexAndLength(index); |
2432 | return {std::next(odsOperands.begin(), valueRange.first), |
2433 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
2434 | } |
2435 | |
2436 | ValueT getLhs() { |
2437 | return (*getODSOperands(0).begin()); |
2438 | } |
2439 | |
2440 | ValueT getRhs() { |
2441 | return (*getODSOperands(1).begin()); |
2442 | } |
2443 | |
2444 | RangeT getOperands() { |
2445 | return odsOperands; |
2446 | } |
2447 | |
2448 | private: |
2449 | RangeT odsOperands; |
2450 | }; |
2451 | class FloorDivSIOpAdaptor : public FloorDivSIOpGenericAdaptor<::mlir::ValueRange> { |
2452 | public: |
2453 | using FloorDivSIOpGenericAdaptor::FloorDivSIOpGenericAdaptor; |
2454 | FloorDivSIOpAdaptor(FloorDivSIOp op); |
2455 | |
2456 | ::mlir::LogicalResult verify(::mlir::Location loc); |
2457 | }; |
2458 | class FloorDivSIOp : public ::mlir::Op<FloorDivSIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
2459 | public: |
2460 | using Op::Op; |
2461 | using Op::print; |
2462 | using Adaptor = FloorDivSIOpAdaptor; |
2463 | template <typename RangeT> |
2464 | using GenericAdaptor = FloorDivSIOpGenericAdaptor<RangeT>; |
2465 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
2466 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
2467 | return {}; |
2468 | } |
2469 | |
2470 | static constexpr ::llvm::StringLiteral getOperationName() { |
2471 | return ::llvm::StringLiteral("arith.floordivsi"); |
2472 | } |
2473 | |
2474 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
2475 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
2476 | ::mlir::Value getLhs(); |
2477 | ::mlir::Value getRhs(); |
2478 | ::mlir::MutableOperandRange getLhsMutable(); |
2479 | ::mlir::MutableOperandRange getRhsMutable(); |
2480 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
2481 | ::mlir::Operation::result_range getODSResults(unsigned index); |
2482 | ::mlir::Value getResult(); |
2483 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
2484 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
2485 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
2486 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2487 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2488 | ::mlir::LogicalResult verifyInvariantsImpl(); |
2489 | ::mlir::LogicalResult verifyInvariants(); |
2490 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
2491 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
2492 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
2493 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
2494 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
2495 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
2496 | public: |
2497 | }; |
2498 | } // namespace arith |
2499 | } // namespace mlir |
2500 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::FloorDivSIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::FloorDivSIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
2501 | |
2502 | namespace mlir { |
2503 | namespace arith { |
2504 | |
2505 | //===----------------------------------------------------------------------===// |
2506 | // ::mlir::arith::IndexCastOp declarations |
2507 | //===----------------------------------------------------------------------===// |
2508 | |
2509 | namespace detail { |
2510 | class IndexCastOpGenericAdaptorBase { |
2511 | public: |
2512 | protected: |
2513 | ::mlir::DictionaryAttr odsAttrs; |
2514 | ::std::optional<::mlir::OperationName> odsOpName; |
2515 | ::mlir::RegionRange odsRegions; |
2516 | public: |
2517 | IndexCastOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
2518 | |
2519 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
2520 | ::mlir::DictionaryAttr getAttributes(); |
2521 | }; |
2522 | } // namespace detail |
2523 | template <typename RangeT> |
2524 | class IndexCastOpGenericAdaptor : public detail::IndexCastOpGenericAdaptorBase { |
2525 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
2526 | using Base = detail::IndexCastOpGenericAdaptorBase; |
2527 | public: |
2528 | IndexCastOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
2529 | |
2530 | IndexCastOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : IndexCastOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
2531 | |
2532 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
2533 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
2534 | } |
2535 | |
2536 | RangeT getODSOperands(unsigned index) { |
2537 | auto valueRange = getODSOperandIndexAndLength(index); |
2538 | return {std::next(odsOperands.begin(), valueRange.first), |
2539 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
2540 | } |
2541 | |
2542 | ValueT getIn() { |
2543 | return (*getODSOperands(0).begin()); |
2544 | } |
2545 | |
2546 | RangeT getOperands() { |
2547 | return odsOperands; |
2548 | } |
2549 | |
2550 | private: |
2551 | RangeT odsOperands; |
2552 | }; |
2553 | class IndexCastOpAdaptor : public IndexCastOpGenericAdaptor<::mlir::ValueRange> { |
2554 | public: |
2555 | using IndexCastOpGenericAdaptor::IndexCastOpGenericAdaptor; |
2556 | IndexCastOpAdaptor(IndexCastOp op); |
2557 | |
2558 | ::mlir::LogicalResult verify(::mlir::Location loc); |
2559 | }; |
2560 | class IndexCastOp : public ::mlir::Op<IndexCastOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::InferIntRangeInterface::Trait, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
2561 | public: |
2562 | using Op::Op; |
2563 | using Op::print; |
2564 | using Adaptor = IndexCastOpAdaptor; |
2565 | template <typename RangeT> |
2566 | using GenericAdaptor = IndexCastOpGenericAdaptor<RangeT>; |
2567 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
2568 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
2569 | return {}; |
2570 | } |
2571 | |
2572 | static constexpr ::llvm::StringLiteral getOperationName() { |
2573 | return ::llvm::StringLiteral("arith.index_cast"); |
2574 | } |
2575 | |
2576 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
2577 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
2578 | ::mlir::Value getIn(); |
2579 | ::mlir::MutableOperandRange getInMutable(); |
2580 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
2581 | ::mlir::Operation::result_range getODSResults(unsigned index); |
2582 | ::mlir::Value getOut(); |
2583 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
2584 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
2585 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2586 | ::mlir::LogicalResult verifyInvariantsImpl(); |
2587 | ::mlir::LogicalResult verifyInvariants(); |
2588 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
2589 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
2590 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
2591 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
2592 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
2593 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
2594 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
2595 | public: |
2596 | }; |
2597 | } // namespace arith |
2598 | } // namespace mlir |
2599 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::IndexCastOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::IndexCastOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
2600 | |
2601 | namespace mlir { |
2602 | namespace arith { |
2603 | |
2604 | //===----------------------------------------------------------------------===// |
2605 | // ::mlir::arith::IndexCastUIOp declarations |
2606 | //===----------------------------------------------------------------------===// |
2607 | |
2608 | namespace detail { |
2609 | class IndexCastUIOpGenericAdaptorBase { |
2610 | public: |
2611 | protected: |
2612 | ::mlir::DictionaryAttr odsAttrs; |
2613 | ::std::optional<::mlir::OperationName> odsOpName; |
2614 | ::mlir::RegionRange odsRegions; |
2615 | public: |
2616 | IndexCastUIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
2617 | |
2618 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
2619 | ::mlir::DictionaryAttr getAttributes(); |
2620 | }; |
2621 | } // namespace detail |
2622 | template <typename RangeT> |
2623 | class IndexCastUIOpGenericAdaptor : public detail::IndexCastUIOpGenericAdaptorBase { |
2624 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
2625 | using Base = detail::IndexCastUIOpGenericAdaptorBase; |
2626 | public: |
2627 | IndexCastUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
2628 | |
2629 | IndexCastUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : IndexCastUIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
2630 | |
2631 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
2632 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
2633 | } |
2634 | |
2635 | RangeT getODSOperands(unsigned index) { |
2636 | auto valueRange = getODSOperandIndexAndLength(index); |
2637 | return {std::next(odsOperands.begin(), valueRange.first), |
2638 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
2639 | } |
2640 | |
2641 | ValueT getIn() { |
2642 | return (*getODSOperands(0).begin()); |
2643 | } |
2644 | |
2645 | RangeT getOperands() { |
2646 | return odsOperands; |
2647 | } |
2648 | |
2649 | private: |
2650 | RangeT odsOperands; |
2651 | }; |
2652 | class IndexCastUIOpAdaptor : public IndexCastUIOpGenericAdaptor<::mlir::ValueRange> { |
2653 | public: |
2654 | using IndexCastUIOpGenericAdaptor::IndexCastUIOpGenericAdaptor; |
2655 | IndexCastUIOpAdaptor(IndexCastUIOp op); |
2656 | |
2657 | ::mlir::LogicalResult verify(::mlir::Location loc); |
2658 | }; |
2659 | class IndexCastUIOp : public ::mlir::Op<IndexCastUIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::InferIntRangeInterface::Trait, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
2660 | public: |
2661 | using Op::Op; |
2662 | using Op::print; |
2663 | using Adaptor = IndexCastUIOpAdaptor; |
2664 | template <typename RangeT> |
2665 | using GenericAdaptor = IndexCastUIOpGenericAdaptor<RangeT>; |
2666 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
2667 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
2668 | return {}; |
2669 | } |
2670 | |
2671 | static constexpr ::llvm::StringLiteral getOperationName() { |
2672 | return ::llvm::StringLiteral("arith.index_castui"); |
2673 | } |
2674 | |
2675 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
2676 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
2677 | ::mlir::Value getIn(); |
2678 | ::mlir::MutableOperandRange getInMutable(); |
2679 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
2680 | ::mlir::Operation::result_range getODSResults(unsigned index); |
2681 | ::mlir::Value getOut(); |
2682 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
2683 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
2684 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2685 | ::mlir::LogicalResult verifyInvariantsImpl(); |
2686 | ::mlir::LogicalResult verifyInvariants(); |
2687 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
2688 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
2689 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
2690 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
2691 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
2692 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
2693 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
2694 | public: |
2695 | }; |
2696 | } // namespace arith |
2697 | } // namespace mlir |
2698 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::IndexCastUIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::IndexCastUIOp> { public: static TypeID resolveTypeID() { return id; } private: static SelfOwningTypeID id; }; } } |
2699 | |
2700 | namespace mlir { |
2701 | namespace arith { |
2702 | |
2703 | //===----------------------------------------------------------------------===// |
2704 | // ::mlir::arith::MaxFOp declarations |
2705 | //===----------------------------------------------------------------------===// |
2706 | |
2707 | namespace detail { |
2708 | class MaxFOpGenericAdaptorBase { |
2709 | public: |
2710 | struct Properties { |
2711 | using fastmathTy = ::mlir::arith::FastMathFlagsAttr; |
2712 | fastmathTy fastmath; |
2713 | |
2714 | auto getFastmath() { |
2715 | auto &propStorage = this->fastmath; |
2716 | return propStorage.dyn_cast_or_null<::mlir::arith::FastMathFlagsAttr>(); |
2717 | } |
2718 | void setFastmath(const ::mlir::arith::FastMathFlagsAttr &propValue) { |
2719 | this->fastmath = propValue; |
2720 | } |
2721 | }; |
2722 | protected: |
2723 | ::mlir::DictionaryAttr odsAttrs; |
2724 | ::std::optional<::mlir::OperationName> odsOpName; |
2725 | Properties properties; |
2726 | ::mlir::RegionRange odsRegions; |
2727 | public: |
2728 | MaxFOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}); |
2729 | |
2730 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
2731 | const Properties &getProperties() { |
2732 | return properties; |
2733 | } |
2734 | |
2735 | ::mlir::DictionaryAttr getAttributes(); |
2736 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
2737 | ::mlir::arith::FastMathFlags getFastmath(); |
2738 | }; |
2739 | } // namespace detail |
2740 | template <typename RangeT> |
2741 | class MaxFOpGenericAdaptor : public detail::MaxFOpGenericAdaptorBase { |
2742 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
2743 | using Base = detail::MaxFOpGenericAdaptorBase; |
2744 | public: |
2745 | MaxFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
2746 | |
2747 | MaxFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : MaxFOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {} |
2748 | |
2749 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
2750 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
2751 | } |
2752 | |
2753 | RangeT getODSOperands(unsigned index) { |
2754 | auto valueRange = getODSOperandIndexAndLength(index); |
2755 | return {std::next(odsOperands.begin(), valueRange.first), |
2756 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
2757 | } |
2758 | |
2759 | ValueT getLhs() { |
2760 | return (*getODSOperands(0).begin()); |
2761 | } |
2762 | |
2763 | ValueT getRhs() { |
2764 | return (*getODSOperands(1).begin()); |
2765 | } |
2766 | |
2767 | RangeT getOperands() { |
2768 | return odsOperands; |
2769 | } |
2770 | |
2771 | private: |
2772 | RangeT odsOperands; |
2773 | }; |
2774 | class MaxFOpAdaptor : public MaxFOpGenericAdaptor<::mlir::ValueRange> { |
2775 | public: |
2776 | using MaxFOpGenericAdaptor::MaxFOpGenericAdaptor; |
2777 | MaxFOpAdaptor(MaxFOp op); |
2778 | |
2779 | ::mlir::LogicalResult verify(::mlir::Location loc); |
2780 | }; |
2781 | class MaxFOp : public ::mlir::Op<MaxFOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::arith::ArithFastMathInterface::Trait, ::mlir::OpTrait::IsCommutative, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
2782 | public: |
2783 | using Op::Op; |
2784 | using Op::print; |
2785 | using Adaptor = MaxFOpAdaptor; |
2786 | template <typename RangeT> |
2787 | using GenericAdaptor = MaxFOpGenericAdaptor<RangeT>; |
2788 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
2789 | using Properties = FoldAdaptor::Properties; |
2790 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
2791 | static ::llvm::StringRef attrNames[] = {::llvm::StringRef("fastmath")}; |
2792 | return ::llvm::ArrayRef(attrNames); |
2793 | } |
2794 | |
2795 | ::mlir::StringAttr getFastmathAttrName() { |
2796 | return getAttributeNameForIndex(0); |
2797 | } |
2798 | |
2799 | static ::mlir::StringAttr getFastmathAttrName(::mlir::OperationName name) { |
2800 | return getAttributeNameForIndex(name, 0); |
2801 | } |
2802 | |
2803 | static constexpr ::llvm::StringLiteral getOperationName() { |
2804 | return ::llvm::StringLiteral("arith.maxf"); |
2805 | } |
2806 | |
2807 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
2808 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
2809 | ::mlir::Value getLhs(); |
2810 | ::mlir::Value getRhs(); |
2811 | ::mlir::MutableOperandRange getLhsMutable(); |
2812 | ::mlir::MutableOperandRange getRhsMutable(); |
2813 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
2814 | ::mlir::Operation::result_range getODSResults(unsigned index); |
2815 | ::mlir::Value getResult(); |
2816 | static ::mlir::LogicalResult setPropertiesFromAttr(Properties &prop, ::mlir::Attribute attr, ::mlir::InFlightDiagnostic *diag); |
2817 | static ::mlir::Attribute getPropertiesAsAttr(::mlir::MLIRContext *ctx, const Properties &prop); |
2818 | static llvm::hash_code computePropertiesHash(const Properties &prop); |
2819 | static std::optional<mlir::Attribute> getInherentAttr(const Properties &prop, llvm::StringRef name); |
2820 | static void setInherentAttr(Properties &prop, llvm::StringRef name, mlir::Attribute value); |
2821 | static void populateInherentAttrs(const Properties &prop, ::mlir::NamedAttrList &attrs); |
2822 | static ::mlir::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> getDiag); |
2823 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
2824 | ::mlir::arith::FastMathFlags getFastmath(); |
2825 | void setFastmathAttr(::mlir::arith::FastMathFlagsAttr attr); |
2826 | void setFastmath(::mlir::arith::FastMathFlags attrValue); |
2827 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
2828 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
2829 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
2830 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
2831 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
2832 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
2833 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2834 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2835 | static void populateDefaultProperties(::mlir::OperationName opName, Properties &properties); |
2836 | ::mlir::LogicalResult verifyInvariantsImpl(); |
2837 | ::mlir::LogicalResult verifyInvariants(); |
2838 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
2839 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
2840 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
2841 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
2842 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
2843 | private: |
2844 | ::mlir::StringAttr getAttributeNameForIndex(unsigned index) { |
2845 | return getAttributeNameForIndex((*this)->getName(), index); |
2846 | } |
2847 | |
2848 | static ::mlir::StringAttr getAttributeNameForIndex(::mlir::OperationName name, unsigned index) { |
2849 | assert(index < 1 && "invalid attribute index")(static_cast <bool> (index < 1 && "invalid attribute index" ) ? void (0) : __assert_fail ("index < 1 && \"invalid attribute index\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 2849 , __extension__ __PRETTY_FUNCTION__)); |
2850 | assert(name.getStringRef() == getOperationName() && "invalid operation name")(static_cast <bool> (name.getStringRef() == getOperationName () && "invalid operation name") ? void (0) : __assert_fail ("name.getStringRef() == getOperationName() && \"invalid operation name\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 2850 , __extension__ __PRETTY_FUNCTION__)); |
2851 | return name.getAttributeNames()[index]; |
2852 | } |
2853 | |
2854 | public: |
2855 | }; |
2856 | } // namespace arith |
2857 | } // namespace mlir |
2858 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::MaxFOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::MaxFOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
2859 | |
2860 | namespace mlir { |
2861 | namespace arith { |
2862 | |
2863 | //===----------------------------------------------------------------------===// |
2864 | // ::mlir::arith::MaxSIOp declarations |
2865 | //===----------------------------------------------------------------------===// |
2866 | |
2867 | namespace detail { |
2868 | class MaxSIOpGenericAdaptorBase { |
2869 | public: |
2870 | protected: |
2871 | ::mlir::DictionaryAttr odsAttrs; |
2872 | ::std::optional<::mlir::OperationName> odsOpName; |
2873 | ::mlir::RegionRange odsRegions; |
2874 | public: |
2875 | MaxSIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
2876 | |
2877 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
2878 | ::mlir::DictionaryAttr getAttributes(); |
2879 | }; |
2880 | } // namespace detail |
2881 | template <typename RangeT> |
2882 | class MaxSIOpGenericAdaptor : public detail::MaxSIOpGenericAdaptorBase { |
2883 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
2884 | using Base = detail::MaxSIOpGenericAdaptorBase; |
2885 | public: |
2886 | MaxSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
2887 | |
2888 | MaxSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : MaxSIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
2889 | |
2890 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
2891 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
2892 | } |
2893 | |
2894 | RangeT getODSOperands(unsigned index) { |
2895 | auto valueRange = getODSOperandIndexAndLength(index); |
2896 | return {std::next(odsOperands.begin(), valueRange.first), |
2897 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
2898 | } |
2899 | |
2900 | ValueT getLhs() { |
2901 | return (*getODSOperands(0).begin()); |
2902 | } |
2903 | |
2904 | ValueT getRhs() { |
2905 | return (*getODSOperands(1).begin()); |
2906 | } |
2907 | |
2908 | RangeT getOperands() { |
2909 | return odsOperands; |
2910 | } |
2911 | |
2912 | private: |
2913 | RangeT odsOperands; |
2914 | }; |
2915 | class MaxSIOpAdaptor : public MaxSIOpGenericAdaptor<::mlir::ValueRange> { |
2916 | public: |
2917 | using MaxSIOpGenericAdaptor::MaxSIOpGenericAdaptor; |
2918 | MaxSIOpAdaptor(MaxSIOp op); |
2919 | |
2920 | ::mlir::LogicalResult verify(::mlir::Location loc); |
2921 | }; |
2922 | class MaxSIOp : public ::mlir::Op<MaxSIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::OpTrait::IsCommutative, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
2923 | public: |
2924 | using Op::Op; |
2925 | using Op::print; |
2926 | using Adaptor = MaxSIOpAdaptor; |
2927 | template <typename RangeT> |
2928 | using GenericAdaptor = MaxSIOpGenericAdaptor<RangeT>; |
2929 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
2930 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
2931 | return {}; |
2932 | } |
2933 | |
2934 | static constexpr ::llvm::StringLiteral getOperationName() { |
2935 | return ::llvm::StringLiteral("arith.maxsi"); |
2936 | } |
2937 | |
2938 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
2939 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
2940 | ::mlir::Value getLhs(); |
2941 | ::mlir::Value getRhs(); |
2942 | ::mlir::MutableOperandRange getLhsMutable(); |
2943 | ::mlir::MutableOperandRange getRhsMutable(); |
2944 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
2945 | ::mlir::Operation::result_range getODSResults(unsigned index); |
2946 | ::mlir::Value getResult(); |
2947 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
2948 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
2949 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
2950 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2951 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
2952 | ::mlir::LogicalResult verifyInvariantsImpl(); |
2953 | ::mlir::LogicalResult verifyInvariants(); |
2954 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
2955 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
2956 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
2957 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
2958 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
2959 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
2960 | public: |
2961 | }; |
2962 | } // namespace arith |
2963 | } // namespace mlir |
2964 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::MaxSIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::MaxSIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
2965 | |
2966 | namespace mlir { |
2967 | namespace arith { |
2968 | |
2969 | //===----------------------------------------------------------------------===// |
2970 | // ::mlir::arith::MaxUIOp declarations |
2971 | //===----------------------------------------------------------------------===// |
2972 | |
2973 | namespace detail { |
2974 | class MaxUIOpGenericAdaptorBase { |
2975 | public: |
2976 | protected: |
2977 | ::mlir::DictionaryAttr odsAttrs; |
2978 | ::std::optional<::mlir::OperationName> odsOpName; |
2979 | ::mlir::RegionRange odsRegions; |
2980 | public: |
2981 | MaxUIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
2982 | |
2983 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
2984 | ::mlir::DictionaryAttr getAttributes(); |
2985 | }; |
2986 | } // namespace detail |
2987 | template <typename RangeT> |
2988 | class MaxUIOpGenericAdaptor : public detail::MaxUIOpGenericAdaptorBase { |
2989 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
2990 | using Base = detail::MaxUIOpGenericAdaptorBase; |
2991 | public: |
2992 | MaxUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
2993 | |
2994 | MaxUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : MaxUIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
2995 | |
2996 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
2997 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
2998 | } |
2999 | |
3000 | RangeT getODSOperands(unsigned index) { |
3001 | auto valueRange = getODSOperandIndexAndLength(index); |
3002 | return {std::next(odsOperands.begin(), valueRange.first), |
3003 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
3004 | } |
3005 | |
3006 | ValueT getLhs() { |
3007 | return (*getODSOperands(0).begin()); |
3008 | } |
3009 | |
3010 | ValueT getRhs() { |
3011 | return (*getODSOperands(1).begin()); |
3012 | } |
3013 | |
3014 | RangeT getOperands() { |
3015 | return odsOperands; |
3016 | } |
3017 | |
3018 | private: |
3019 | RangeT odsOperands; |
3020 | }; |
3021 | class MaxUIOpAdaptor : public MaxUIOpGenericAdaptor<::mlir::ValueRange> { |
3022 | public: |
3023 | using MaxUIOpGenericAdaptor::MaxUIOpGenericAdaptor; |
3024 | MaxUIOpAdaptor(MaxUIOp op); |
3025 | |
3026 | ::mlir::LogicalResult verify(::mlir::Location loc); |
3027 | }; |
3028 | class MaxUIOp : public ::mlir::Op<MaxUIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::OpTrait::IsCommutative, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
3029 | public: |
3030 | using Op::Op; |
3031 | using Op::print; |
3032 | using Adaptor = MaxUIOpAdaptor; |
3033 | template <typename RangeT> |
3034 | using GenericAdaptor = MaxUIOpGenericAdaptor<RangeT>; |
3035 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
3036 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
3037 | return {}; |
3038 | } |
3039 | |
3040 | static constexpr ::llvm::StringLiteral getOperationName() { |
3041 | return ::llvm::StringLiteral("arith.maxui"); |
3042 | } |
3043 | |
3044 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
3045 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
3046 | ::mlir::Value getLhs(); |
3047 | ::mlir::Value getRhs(); |
3048 | ::mlir::MutableOperandRange getLhsMutable(); |
3049 | ::mlir::MutableOperandRange getRhsMutable(); |
3050 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
3051 | ::mlir::Operation::result_range getODSResults(unsigned index); |
3052 | ::mlir::Value getResult(); |
3053 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
3054 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
3055 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
3056 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3057 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3058 | ::mlir::LogicalResult verifyInvariantsImpl(); |
3059 | ::mlir::LogicalResult verifyInvariants(); |
3060 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
3061 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
3062 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
3063 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
3064 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
3065 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
3066 | public: |
3067 | }; |
3068 | } // namespace arith |
3069 | } // namespace mlir |
3070 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::MaxUIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::MaxUIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
3071 | |
3072 | namespace mlir { |
3073 | namespace arith { |
3074 | |
3075 | //===----------------------------------------------------------------------===// |
3076 | // ::mlir::arith::MinFOp declarations |
3077 | //===----------------------------------------------------------------------===// |
3078 | |
3079 | namespace detail { |
3080 | class MinFOpGenericAdaptorBase { |
3081 | public: |
3082 | struct Properties { |
3083 | using fastmathTy = ::mlir::arith::FastMathFlagsAttr; |
3084 | fastmathTy fastmath; |
3085 | |
3086 | auto getFastmath() { |
3087 | auto &propStorage = this->fastmath; |
3088 | return propStorage.dyn_cast_or_null<::mlir::arith::FastMathFlagsAttr>(); |
3089 | } |
3090 | void setFastmath(const ::mlir::arith::FastMathFlagsAttr &propValue) { |
3091 | this->fastmath = propValue; |
3092 | } |
3093 | }; |
3094 | protected: |
3095 | ::mlir::DictionaryAttr odsAttrs; |
3096 | ::std::optional<::mlir::OperationName> odsOpName; |
3097 | Properties properties; |
3098 | ::mlir::RegionRange odsRegions; |
3099 | public: |
3100 | MinFOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}); |
3101 | |
3102 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
3103 | const Properties &getProperties() { |
3104 | return properties; |
3105 | } |
3106 | |
3107 | ::mlir::DictionaryAttr getAttributes(); |
3108 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
3109 | ::mlir::arith::FastMathFlags getFastmath(); |
3110 | }; |
3111 | } // namespace detail |
3112 | template <typename RangeT> |
3113 | class MinFOpGenericAdaptor : public detail::MinFOpGenericAdaptorBase { |
3114 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
3115 | using Base = detail::MinFOpGenericAdaptorBase; |
3116 | public: |
3117 | MinFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
3118 | |
3119 | MinFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : MinFOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {} |
3120 | |
3121 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
3122 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
3123 | } |
3124 | |
3125 | RangeT getODSOperands(unsigned index) { |
3126 | auto valueRange = getODSOperandIndexAndLength(index); |
3127 | return {std::next(odsOperands.begin(), valueRange.first), |
3128 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
3129 | } |
3130 | |
3131 | ValueT getLhs() { |
3132 | return (*getODSOperands(0).begin()); |
3133 | } |
3134 | |
3135 | ValueT getRhs() { |
3136 | return (*getODSOperands(1).begin()); |
3137 | } |
3138 | |
3139 | RangeT getOperands() { |
3140 | return odsOperands; |
3141 | } |
3142 | |
3143 | private: |
3144 | RangeT odsOperands; |
3145 | }; |
3146 | class MinFOpAdaptor : public MinFOpGenericAdaptor<::mlir::ValueRange> { |
3147 | public: |
3148 | using MinFOpGenericAdaptor::MinFOpGenericAdaptor; |
3149 | MinFOpAdaptor(MinFOp op); |
3150 | |
3151 | ::mlir::LogicalResult verify(::mlir::Location loc); |
3152 | }; |
3153 | class MinFOp : public ::mlir::Op<MinFOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::arith::ArithFastMathInterface::Trait, ::mlir::OpTrait::IsCommutative, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
3154 | public: |
3155 | using Op::Op; |
3156 | using Op::print; |
3157 | using Adaptor = MinFOpAdaptor; |
3158 | template <typename RangeT> |
3159 | using GenericAdaptor = MinFOpGenericAdaptor<RangeT>; |
3160 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
3161 | using Properties = FoldAdaptor::Properties; |
3162 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
3163 | static ::llvm::StringRef attrNames[] = {::llvm::StringRef("fastmath")}; |
3164 | return ::llvm::ArrayRef(attrNames); |
3165 | } |
3166 | |
3167 | ::mlir::StringAttr getFastmathAttrName() { |
3168 | return getAttributeNameForIndex(0); |
3169 | } |
3170 | |
3171 | static ::mlir::StringAttr getFastmathAttrName(::mlir::OperationName name) { |
3172 | return getAttributeNameForIndex(name, 0); |
3173 | } |
3174 | |
3175 | static constexpr ::llvm::StringLiteral getOperationName() { |
3176 | return ::llvm::StringLiteral("arith.minf"); |
3177 | } |
3178 | |
3179 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
3180 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
3181 | ::mlir::Value getLhs(); |
3182 | ::mlir::Value getRhs(); |
3183 | ::mlir::MutableOperandRange getLhsMutable(); |
3184 | ::mlir::MutableOperandRange getRhsMutable(); |
3185 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
3186 | ::mlir::Operation::result_range getODSResults(unsigned index); |
3187 | ::mlir::Value getResult(); |
3188 | static ::mlir::LogicalResult setPropertiesFromAttr(Properties &prop, ::mlir::Attribute attr, ::mlir::InFlightDiagnostic *diag); |
3189 | static ::mlir::Attribute getPropertiesAsAttr(::mlir::MLIRContext *ctx, const Properties &prop); |
3190 | static llvm::hash_code computePropertiesHash(const Properties &prop); |
3191 | static std::optional<mlir::Attribute> getInherentAttr(const Properties &prop, llvm::StringRef name); |
3192 | static void setInherentAttr(Properties &prop, llvm::StringRef name, mlir::Attribute value); |
3193 | static void populateInherentAttrs(const Properties &prop, ::mlir::NamedAttrList &attrs); |
3194 | static ::mlir::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> getDiag); |
3195 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
3196 | ::mlir::arith::FastMathFlags getFastmath(); |
3197 | void setFastmathAttr(::mlir::arith::FastMathFlagsAttr attr); |
3198 | void setFastmath(::mlir::arith::FastMathFlags attrValue); |
3199 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
3200 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
3201 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
3202 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
3203 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
3204 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
3205 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3206 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3207 | static void populateDefaultProperties(::mlir::OperationName opName, Properties &properties); |
3208 | ::mlir::LogicalResult verifyInvariantsImpl(); |
3209 | ::mlir::LogicalResult verifyInvariants(); |
3210 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
3211 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
3212 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
3213 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
3214 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
3215 | private: |
3216 | ::mlir::StringAttr getAttributeNameForIndex(unsigned index) { |
3217 | return getAttributeNameForIndex((*this)->getName(), index); |
3218 | } |
3219 | |
3220 | static ::mlir::StringAttr getAttributeNameForIndex(::mlir::OperationName name, unsigned index) { |
3221 | assert(index < 1 && "invalid attribute index")(static_cast <bool> (index < 1 && "invalid attribute index" ) ? void (0) : __assert_fail ("index < 1 && \"invalid attribute index\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 3221 , __extension__ __PRETTY_FUNCTION__)); |
3222 | assert(name.getStringRef() == getOperationName() && "invalid operation name")(static_cast <bool> (name.getStringRef() == getOperationName () && "invalid operation name") ? void (0) : __assert_fail ("name.getStringRef() == getOperationName() && \"invalid operation name\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 3222 , __extension__ __PRETTY_FUNCTION__)); |
3223 | return name.getAttributeNames()[index]; |
3224 | } |
3225 | |
3226 | public: |
3227 | }; |
3228 | } // namespace arith |
3229 | } // namespace mlir |
3230 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::MinFOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::MinFOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
3231 | |
3232 | namespace mlir { |
3233 | namespace arith { |
3234 | |
3235 | //===----------------------------------------------------------------------===// |
3236 | // ::mlir::arith::MinSIOp declarations |
3237 | //===----------------------------------------------------------------------===// |
3238 | |
3239 | namespace detail { |
3240 | class MinSIOpGenericAdaptorBase { |
3241 | public: |
3242 | protected: |
3243 | ::mlir::DictionaryAttr odsAttrs; |
3244 | ::std::optional<::mlir::OperationName> odsOpName; |
3245 | ::mlir::RegionRange odsRegions; |
3246 | public: |
3247 | MinSIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
3248 | |
3249 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
3250 | ::mlir::DictionaryAttr getAttributes(); |
3251 | }; |
3252 | } // namespace detail |
3253 | template <typename RangeT> |
3254 | class MinSIOpGenericAdaptor : public detail::MinSIOpGenericAdaptorBase { |
3255 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
3256 | using Base = detail::MinSIOpGenericAdaptorBase; |
3257 | public: |
3258 | MinSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
3259 | |
3260 | MinSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : MinSIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
3261 | |
3262 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
3263 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
3264 | } |
3265 | |
3266 | RangeT getODSOperands(unsigned index) { |
3267 | auto valueRange = getODSOperandIndexAndLength(index); |
3268 | return {std::next(odsOperands.begin(), valueRange.first), |
3269 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
3270 | } |
3271 | |
3272 | ValueT getLhs() { |
3273 | return (*getODSOperands(0).begin()); |
3274 | } |
3275 | |
3276 | ValueT getRhs() { |
3277 | return (*getODSOperands(1).begin()); |
3278 | } |
3279 | |
3280 | RangeT getOperands() { |
3281 | return odsOperands; |
3282 | } |
3283 | |
3284 | private: |
3285 | RangeT odsOperands; |
3286 | }; |
3287 | class MinSIOpAdaptor : public MinSIOpGenericAdaptor<::mlir::ValueRange> { |
3288 | public: |
3289 | using MinSIOpGenericAdaptor::MinSIOpGenericAdaptor; |
3290 | MinSIOpAdaptor(MinSIOp op); |
3291 | |
3292 | ::mlir::LogicalResult verify(::mlir::Location loc); |
3293 | }; |
3294 | class MinSIOp : public ::mlir::Op<MinSIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::OpTrait::IsCommutative, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
3295 | public: |
3296 | using Op::Op; |
3297 | using Op::print; |
3298 | using Adaptor = MinSIOpAdaptor; |
3299 | template <typename RangeT> |
3300 | using GenericAdaptor = MinSIOpGenericAdaptor<RangeT>; |
3301 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
3302 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
3303 | return {}; |
3304 | } |
3305 | |
3306 | static constexpr ::llvm::StringLiteral getOperationName() { |
3307 | return ::llvm::StringLiteral("arith.minsi"); |
3308 | } |
3309 | |
3310 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
3311 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
3312 | ::mlir::Value getLhs(); |
3313 | ::mlir::Value getRhs(); |
3314 | ::mlir::MutableOperandRange getLhsMutable(); |
3315 | ::mlir::MutableOperandRange getRhsMutable(); |
3316 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
3317 | ::mlir::Operation::result_range getODSResults(unsigned index); |
3318 | ::mlir::Value getResult(); |
3319 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
3320 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
3321 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
3322 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3323 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3324 | ::mlir::LogicalResult verifyInvariantsImpl(); |
3325 | ::mlir::LogicalResult verifyInvariants(); |
3326 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
3327 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
3328 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
3329 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
3330 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
3331 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
3332 | public: |
3333 | }; |
3334 | } // namespace arith |
3335 | } // namespace mlir |
3336 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::MinSIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::MinSIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
3337 | |
3338 | namespace mlir { |
3339 | namespace arith { |
3340 | |
3341 | //===----------------------------------------------------------------------===// |
3342 | // ::mlir::arith::MinUIOp declarations |
3343 | //===----------------------------------------------------------------------===// |
3344 | |
3345 | namespace detail { |
3346 | class MinUIOpGenericAdaptorBase { |
3347 | public: |
3348 | protected: |
3349 | ::mlir::DictionaryAttr odsAttrs; |
3350 | ::std::optional<::mlir::OperationName> odsOpName; |
3351 | ::mlir::RegionRange odsRegions; |
3352 | public: |
3353 | MinUIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
3354 | |
3355 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
3356 | ::mlir::DictionaryAttr getAttributes(); |
3357 | }; |
3358 | } // namespace detail |
3359 | template <typename RangeT> |
3360 | class MinUIOpGenericAdaptor : public detail::MinUIOpGenericAdaptorBase { |
3361 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
3362 | using Base = detail::MinUIOpGenericAdaptorBase; |
3363 | public: |
3364 | MinUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
3365 | |
3366 | MinUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : MinUIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
3367 | |
3368 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
3369 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
3370 | } |
3371 | |
3372 | RangeT getODSOperands(unsigned index) { |
3373 | auto valueRange = getODSOperandIndexAndLength(index); |
3374 | return {std::next(odsOperands.begin(), valueRange.first), |
3375 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
3376 | } |
3377 | |
3378 | ValueT getLhs() { |
3379 | return (*getODSOperands(0).begin()); |
3380 | } |
3381 | |
3382 | ValueT getRhs() { |
3383 | return (*getODSOperands(1).begin()); |
3384 | } |
3385 | |
3386 | RangeT getOperands() { |
3387 | return odsOperands; |
3388 | } |
3389 | |
3390 | private: |
3391 | RangeT odsOperands; |
3392 | }; |
3393 | class MinUIOpAdaptor : public MinUIOpGenericAdaptor<::mlir::ValueRange> { |
3394 | public: |
3395 | using MinUIOpGenericAdaptor::MinUIOpGenericAdaptor; |
3396 | MinUIOpAdaptor(MinUIOp op); |
3397 | |
3398 | ::mlir::LogicalResult verify(::mlir::Location loc); |
3399 | }; |
3400 | class MinUIOp : public ::mlir::Op<MinUIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::OpTrait::IsCommutative, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
3401 | public: |
3402 | using Op::Op; |
3403 | using Op::print; |
3404 | using Adaptor = MinUIOpAdaptor; |
3405 | template <typename RangeT> |
3406 | using GenericAdaptor = MinUIOpGenericAdaptor<RangeT>; |
3407 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
3408 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
3409 | return {}; |
3410 | } |
3411 | |
3412 | static constexpr ::llvm::StringLiteral getOperationName() { |
3413 | return ::llvm::StringLiteral("arith.minui"); |
3414 | } |
3415 | |
3416 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
3417 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
3418 | ::mlir::Value getLhs(); |
3419 | ::mlir::Value getRhs(); |
3420 | ::mlir::MutableOperandRange getLhsMutable(); |
3421 | ::mlir::MutableOperandRange getRhsMutable(); |
3422 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
3423 | ::mlir::Operation::result_range getODSResults(unsigned index); |
3424 | ::mlir::Value getResult(); |
3425 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
3426 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
3427 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
3428 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3429 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3430 | ::mlir::LogicalResult verifyInvariantsImpl(); |
3431 | ::mlir::LogicalResult verifyInvariants(); |
3432 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
3433 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
3434 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
3435 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
3436 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
3437 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
3438 | public: |
3439 | }; |
3440 | } // namespace arith |
3441 | } // namespace mlir |
3442 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::MinUIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::MinUIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
3443 | |
3444 | namespace mlir { |
3445 | namespace arith { |
3446 | |
3447 | //===----------------------------------------------------------------------===// |
3448 | // ::mlir::arith::MulFOp declarations |
3449 | //===----------------------------------------------------------------------===// |
3450 | |
3451 | namespace detail { |
3452 | class MulFOpGenericAdaptorBase { |
3453 | public: |
3454 | struct Properties { |
3455 | using fastmathTy = ::mlir::arith::FastMathFlagsAttr; |
3456 | fastmathTy fastmath; |
3457 | |
3458 | auto getFastmath() { |
3459 | auto &propStorage = this->fastmath; |
3460 | return propStorage.dyn_cast_or_null<::mlir::arith::FastMathFlagsAttr>(); |
3461 | } |
3462 | void setFastmath(const ::mlir::arith::FastMathFlagsAttr &propValue) { |
3463 | this->fastmath = propValue; |
3464 | } |
3465 | }; |
3466 | protected: |
3467 | ::mlir::DictionaryAttr odsAttrs; |
3468 | ::std::optional<::mlir::OperationName> odsOpName; |
3469 | Properties properties; |
3470 | ::mlir::RegionRange odsRegions; |
3471 | public: |
3472 | MulFOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}); |
3473 | |
3474 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
3475 | const Properties &getProperties() { |
3476 | return properties; |
3477 | } |
3478 | |
3479 | ::mlir::DictionaryAttr getAttributes(); |
3480 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
3481 | ::mlir::arith::FastMathFlags getFastmath(); |
3482 | }; |
3483 | } // namespace detail |
3484 | template <typename RangeT> |
3485 | class MulFOpGenericAdaptor : public detail::MulFOpGenericAdaptorBase { |
3486 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
3487 | using Base = detail::MulFOpGenericAdaptorBase; |
3488 | public: |
3489 | MulFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
3490 | |
3491 | MulFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : MulFOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {} |
3492 | |
3493 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
3494 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
3495 | } |
3496 | |
3497 | RangeT getODSOperands(unsigned index) { |
3498 | auto valueRange = getODSOperandIndexAndLength(index); |
3499 | return {std::next(odsOperands.begin(), valueRange.first), |
3500 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
3501 | } |
3502 | |
3503 | ValueT getLhs() { |
3504 | return (*getODSOperands(0).begin()); |
3505 | } |
3506 | |
3507 | ValueT getRhs() { |
3508 | return (*getODSOperands(1).begin()); |
3509 | } |
3510 | |
3511 | RangeT getOperands() { |
3512 | return odsOperands; |
3513 | } |
3514 | |
3515 | private: |
3516 | RangeT odsOperands; |
3517 | }; |
3518 | class MulFOpAdaptor : public MulFOpGenericAdaptor<::mlir::ValueRange> { |
3519 | public: |
3520 | using MulFOpGenericAdaptor::MulFOpGenericAdaptor; |
3521 | MulFOpAdaptor(MulFOp op); |
3522 | |
3523 | ::mlir::LogicalResult verify(::mlir::Location loc); |
3524 | }; |
3525 | class MulFOp : public ::mlir::Op<MulFOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::arith::ArithFastMathInterface::Trait, ::mlir::OpTrait::IsCommutative, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
3526 | public: |
3527 | using Op::Op; |
3528 | using Op::print; |
3529 | using Adaptor = MulFOpAdaptor; |
3530 | template <typename RangeT> |
3531 | using GenericAdaptor = MulFOpGenericAdaptor<RangeT>; |
3532 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
3533 | using Properties = FoldAdaptor::Properties; |
3534 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
3535 | static ::llvm::StringRef attrNames[] = {::llvm::StringRef("fastmath")}; |
3536 | return ::llvm::ArrayRef(attrNames); |
3537 | } |
3538 | |
3539 | ::mlir::StringAttr getFastmathAttrName() { |
3540 | return getAttributeNameForIndex(0); |
3541 | } |
3542 | |
3543 | static ::mlir::StringAttr getFastmathAttrName(::mlir::OperationName name) { |
3544 | return getAttributeNameForIndex(name, 0); |
3545 | } |
3546 | |
3547 | static constexpr ::llvm::StringLiteral getOperationName() { |
3548 | return ::llvm::StringLiteral("arith.mulf"); |
3549 | } |
3550 | |
3551 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
3552 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
3553 | ::mlir::Value getLhs(); |
3554 | ::mlir::Value getRhs(); |
3555 | ::mlir::MutableOperandRange getLhsMutable(); |
3556 | ::mlir::MutableOperandRange getRhsMutable(); |
3557 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
3558 | ::mlir::Operation::result_range getODSResults(unsigned index); |
3559 | ::mlir::Value getResult(); |
3560 | static ::mlir::LogicalResult setPropertiesFromAttr(Properties &prop, ::mlir::Attribute attr, ::mlir::InFlightDiagnostic *diag); |
3561 | static ::mlir::Attribute getPropertiesAsAttr(::mlir::MLIRContext *ctx, const Properties &prop); |
3562 | static llvm::hash_code computePropertiesHash(const Properties &prop); |
3563 | static std::optional<mlir::Attribute> getInherentAttr(const Properties &prop, llvm::StringRef name); |
3564 | static void setInherentAttr(Properties &prop, llvm::StringRef name, mlir::Attribute value); |
3565 | static void populateInherentAttrs(const Properties &prop, ::mlir::NamedAttrList &attrs); |
3566 | static ::mlir::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> getDiag); |
3567 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
3568 | ::mlir::arith::FastMathFlags getFastmath(); |
3569 | void setFastmathAttr(::mlir::arith::FastMathFlagsAttr attr); |
3570 | void setFastmath(::mlir::arith::FastMathFlags attrValue); |
3571 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
3572 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
3573 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
3574 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
3575 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
3576 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
3577 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3578 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3579 | static void populateDefaultProperties(::mlir::OperationName opName, Properties &properties); |
3580 | ::mlir::LogicalResult verifyInvariantsImpl(); |
3581 | ::mlir::LogicalResult verifyInvariants(); |
3582 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
3583 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
3584 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
3585 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
3586 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
3587 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
3588 | private: |
3589 | ::mlir::StringAttr getAttributeNameForIndex(unsigned index) { |
3590 | return getAttributeNameForIndex((*this)->getName(), index); |
3591 | } |
3592 | |
3593 | static ::mlir::StringAttr getAttributeNameForIndex(::mlir::OperationName name, unsigned index) { |
3594 | assert(index < 1 && "invalid attribute index")(static_cast <bool> (index < 1 && "invalid attribute index" ) ? void (0) : __assert_fail ("index < 1 && \"invalid attribute index\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 3594 , __extension__ __PRETTY_FUNCTION__)); |
3595 | assert(name.getStringRef() == getOperationName() && "invalid operation name")(static_cast <bool> (name.getStringRef() == getOperationName () && "invalid operation name") ? void (0) : __assert_fail ("name.getStringRef() == getOperationName() && \"invalid operation name\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 3595 , __extension__ __PRETTY_FUNCTION__)); |
3596 | return name.getAttributeNames()[index]; |
3597 | } |
3598 | |
3599 | public: |
3600 | }; |
3601 | } // namespace arith |
3602 | } // namespace mlir |
3603 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::MulFOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::MulFOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
3604 | |
3605 | namespace mlir { |
3606 | namespace arith { |
3607 | |
3608 | //===----------------------------------------------------------------------===// |
3609 | // ::mlir::arith::MulIOp declarations |
3610 | //===----------------------------------------------------------------------===// |
3611 | |
3612 | namespace detail { |
3613 | class MulIOpGenericAdaptorBase { |
3614 | public: |
3615 | protected: |
3616 | ::mlir::DictionaryAttr odsAttrs; |
3617 | ::std::optional<::mlir::OperationName> odsOpName; |
3618 | ::mlir::RegionRange odsRegions; |
3619 | public: |
3620 | MulIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
3621 | |
3622 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
3623 | ::mlir::DictionaryAttr getAttributes(); |
3624 | }; |
3625 | } // namespace detail |
3626 | template <typename RangeT> |
3627 | class MulIOpGenericAdaptor : public detail::MulIOpGenericAdaptorBase { |
3628 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
3629 | using Base = detail::MulIOpGenericAdaptorBase; |
3630 | public: |
3631 | MulIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
3632 | |
3633 | MulIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : MulIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
3634 | |
3635 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
3636 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
3637 | } |
3638 | |
3639 | RangeT getODSOperands(unsigned index) { |
3640 | auto valueRange = getODSOperandIndexAndLength(index); |
3641 | return {std::next(odsOperands.begin(), valueRange.first), |
3642 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
3643 | } |
3644 | |
3645 | ValueT getLhs() { |
3646 | return (*getODSOperands(0).begin()); |
3647 | } |
3648 | |
3649 | ValueT getRhs() { |
3650 | return (*getODSOperands(1).begin()); |
3651 | } |
3652 | |
3653 | RangeT getOperands() { |
3654 | return odsOperands; |
3655 | } |
3656 | |
3657 | private: |
3658 | RangeT odsOperands; |
3659 | }; |
3660 | class MulIOpAdaptor : public MulIOpGenericAdaptor<::mlir::ValueRange> { |
3661 | public: |
3662 | using MulIOpGenericAdaptor::MulIOpGenericAdaptor; |
3663 | MulIOpAdaptor(MulIOp op); |
3664 | |
3665 | ::mlir::LogicalResult verify(::mlir::Location loc); |
3666 | }; |
3667 | class MulIOp : public ::mlir::Op<MulIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::OpTrait::IsCommutative, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
3668 | public: |
3669 | using Op::Op; |
3670 | using Op::print; |
3671 | using Adaptor = MulIOpAdaptor; |
3672 | template <typename RangeT> |
3673 | using GenericAdaptor = MulIOpGenericAdaptor<RangeT>; |
3674 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
3675 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
3676 | return {}; |
3677 | } |
3678 | |
3679 | static constexpr ::llvm::StringLiteral getOperationName() { |
3680 | return ::llvm::StringLiteral("arith.muli"); |
3681 | } |
3682 | |
3683 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
3684 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
3685 | ::mlir::Value getLhs(); |
3686 | ::mlir::Value getRhs(); |
3687 | ::mlir::MutableOperandRange getLhsMutable(); |
3688 | ::mlir::MutableOperandRange getRhsMutable(); |
3689 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
3690 | ::mlir::Operation::result_range getODSResults(unsigned index); |
3691 | ::mlir::Value getResult(); |
3692 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
3693 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
3694 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
3695 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3696 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3697 | ::mlir::LogicalResult verifyInvariantsImpl(); |
3698 | ::mlir::LogicalResult verifyInvariants(); |
3699 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
3700 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
3701 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
3702 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
3703 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
3704 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
3705 | public: |
3706 | }; |
3707 | } // namespace arith |
3708 | } // namespace mlir |
3709 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::MulIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::MulIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
3710 | |
3711 | namespace mlir { |
3712 | namespace arith { |
3713 | |
3714 | //===----------------------------------------------------------------------===// |
3715 | // ::mlir::arith::MulSIExtendedOp declarations |
3716 | //===----------------------------------------------------------------------===// |
3717 | |
3718 | namespace detail { |
3719 | class MulSIExtendedOpGenericAdaptorBase { |
3720 | public: |
3721 | protected: |
3722 | ::mlir::DictionaryAttr odsAttrs; |
3723 | ::std::optional<::mlir::OperationName> odsOpName; |
3724 | ::mlir::RegionRange odsRegions; |
3725 | public: |
3726 | MulSIExtendedOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
3727 | |
3728 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
3729 | ::mlir::DictionaryAttr getAttributes(); |
3730 | }; |
3731 | } // namespace detail |
3732 | template <typename RangeT> |
3733 | class MulSIExtendedOpGenericAdaptor : public detail::MulSIExtendedOpGenericAdaptorBase { |
3734 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
3735 | using Base = detail::MulSIExtendedOpGenericAdaptorBase; |
3736 | public: |
3737 | MulSIExtendedOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
3738 | |
3739 | MulSIExtendedOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : MulSIExtendedOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
3740 | |
3741 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
3742 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
3743 | } |
3744 | |
3745 | RangeT getODSOperands(unsigned index) { |
3746 | auto valueRange = getODSOperandIndexAndLength(index); |
3747 | return {std::next(odsOperands.begin(), valueRange.first), |
3748 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
3749 | } |
3750 | |
3751 | ValueT getLhs() { |
3752 | return (*getODSOperands(0).begin()); |
3753 | } |
3754 | |
3755 | ValueT getRhs() { |
3756 | return (*getODSOperands(1).begin()); |
3757 | } |
3758 | |
3759 | RangeT getOperands() { |
3760 | return odsOperands; |
3761 | } |
3762 | |
3763 | private: |
3764 | RangeT odsOperands; |
3765 | }; |
3766 | class MulSIExtendedOpAdaptor : public MulSIExtendedOpGenericAdaptor<::mlir::ValueRange> { |
3767 | public: |
3768 | using MulSIExtendedOpGenericAdaptor::MulSIExtendedOpGenericAdaptor; |
3769 | MulSIExtendedOpAdaptor(MulSIExtendedOp op); |
3770 | |
3771 | ::mlir::LogicalResult verify(::mlir::Location loc); |
3772 | }; |
3773 | class MulSIExtendedOp : public ::mlir::Op<MulSIExtendedOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::NResults<2>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::IsCommutative, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait, ::mlir::OpAsmOpInterface::Trait> { |
3774 | public: |
3775 | using Op::Op; |
3776 | using Op::print; |
3777 | using Adaptor = MulSIExtendedOpAdaptor; |
3778 | template <typename RangeT> |
3779 | using GenericAdaptor = MulSIExtendedOpGenericAdaptor<RangeT>; |
3780 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
3781 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
3782 | return {}; |
3783 | } |
3784 | |
3785 | void getAsmResultNames(::mlir::OpAsmSetValueNameFn setNameFn); |
3786 | static constexpr ::llvm::StringLiteral getOperationName() { |
3787 | return ::llvm::StringLiteral("arith.mulsi_extended"); |
3788 | } |
3789 | |
3790 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
3791 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
3792 | ::mlir::Value getLhs(); |
3793 | ::mlir::Value getRhs(); |
3794 | ::mlir::MutableOperandRange getLhsMutable(); |
3795 | ::mlir::MutableOperandRange getRhsMutable(); |
3796 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
3797 | ::mlir::Operation::result_range getODSResults(unsigned index); |
3798 | ::mlir::Value getLow(); |
3799 | ::mlir::Value getHigh(); |
3800 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type low, ::mlir::Type high, ::mlir::Value lhs, ::mlir::Value rhs); |
3801 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
3802 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
3803 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3804 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3805 | ::mlir::LogicalResult verifyInvariantsImpl(); |
3806 | ::mlir::LogicalResult verifyInvariants(); |
3807 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
3808 | ::mlir::LogicalResult fold(FoldAdaptor adaptor, ::llvm::SmallVectorImpl<::mlir::OpFoldResult> &results); |
3809 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
3810 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
3811 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
3812 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
3813 | public: |
3814 | std::optional<SmallVector<int64_t, 4>> getShapeForUnroll(); |
3815 | }; |
3816 | } // namespace arith |
3817 | } // namespace mlir |
3818 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::MulSIExtendedOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::MulSIExtendedOp> { public: static TypeID resolveTypeID() { return id; } private: static SelfOwningTypeID id; }; } } |
3819 | |
3820 | namespace mlir { |
3821 | namespace arith { |
3822 | |
3823 | //===----------------------------------------------------------------------===// |
3824 | // ::mlir::arith::MulUIExtendedOp declarations |
3825 | //===----------------------------------------------------------------------===// |
3826 | |
3827 | namespace detail { |
3828 | class MulUIExtendedOpGenericAdaptorBase { |
3829 | public: |
3830 | protected: |
3831 | ::mlir::DictionaryAttr odsAttrs; |
3832 | ::std::optional<::mlir::OperationName> odsOpName; |
3833 | ::mlir::RegionRange odsRegions; |
3834 | public: |
3835 | MulUIExtendedOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
3836 | |
3837 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
3838 | ::mlir::DictionaryAttr getAttributes(); |
3839 | }; |
3840 | } // namespace detail |
3841 | template <typename RangeT> |
3842 | class MulUIExtendedOpGenericAdaptor : public detail::MulUIExtendedOpGenericAdaptorBase { |
3843 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
3844 | using Base = detail::MulUIExtendedOpGenericAdaptorBase; |
3845 | public: |
3846 | MulUIExtendedOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
3847 | |
3848 | MulUIExtendedOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : MulUIExtendedOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
3849 | |
3850 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
3851 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
3852 | } |
3853 | |
3854 | RangeT getODSOperands(unsigned index) { |
3855 | auto valueRange = getODSOperandIndexAndLength(index); |
3856 | return {std::next(odsOperands.begin(), valueRange.first), |
3857 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
3858 | } |
3859 | |
3860 | ValueT getLhs() { |
3861 | return (*getODSOperands(0).begin()); |
3862 | } |
3863 | |
3864 | ValueT getRhs() { |
3865 | return (*getODSOperands(1).begin()); |
3866 | } |
3867 | |
3868 | RangeT getOperands() { |
3869 | return odsOperands; |
3870 | } |
3871 | |
3872 | private: |
3873 | RangeT odsOperands; |
3874 | }; |
3875 | class MulUIExtendedOpAdaptor : public MulUIExtendedOpGenericAdaptor<::mlir::ValueRange> { |
3876 | public: |
3877 | using MulUIExtendedOpGenericAdaptor::MulUIExtendedOpGenericAdaptor; |
3878 | MulUIExtendedOpAdaptor(MulUIExtendedOp op); |
3879 | |
3880 | ::mlir::LogicalResult verify(::mlir::Location loc); |
3881 | }; |
3882 | class MulUIExtendedOp : public ::mlir::Op<MulUIExtendedOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::NResults<2>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::IsCommutative, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait, ::mlir::OpAsmOpInterface::Trait> { |
3883 | public: |
3884 | using Op::Op; |
3885 | using Op::print; |
3886 | using Adaptor = MulUIExtendedOpAdaptor; |
3887 | template <typename RangeT> |
3888 | using GenericAdaptor = MulUIExtendedOpGenericAdaptor<RangeT>; |
3889 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
3890 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
3891 | return {}; |
3892 | } |
3893 | |
3894 | void getAsmResultNames(::mlir::OpAsmSetValueNameFn setNameFn); |
3895 | static constexpr ::llvm::StringLiteral getOperationName() { |
3896 | return ::llvm::StringLiteral("arith.mului_extended"); |
3897 | } |
3898 | |
3899 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
3900 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
3901 | ::mlir::Value getLhs(); |
3902 | ::mlir::Value getRhs(); |
3903 | ::mlir::MutableOperandRange getLhsMutable(); |
3904 | ::mlir::MutableOperandRange getRhsMutable(); |
3905 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
3906 | ::mlir::Operation::result_range getODSResults(unsigned index); |
3907 | ::mlir::Value getLow(); |
3908 | ::mlir::Value getHigh(); |
3909 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type low, ::mlir::Type high, ::mlir::Value lhs, ::mlir::Value rhs); |
3910 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
3911 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
3912 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3913 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
3914 | ::mlir::LogicalResult verifyInvariantsImpl(); |
3915 | ::mlir::LogicalResult verifyInvariants(); |
3916 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
3917 | ::mlir::LogicalResult fold(FoldAdaptor adaptor, ::llvm::SmallVectorImpl<::mlir::OpFoldResult> &results); |
3918 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
3919 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
3920 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
3921 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
3922 | public: |
3923 | std::optional<SmallVector<int64_t, 4>> getShapeForUnroll(); |
3924 | }; |
3925 | } // namespace arith |
3926 | } // namespace mlir |
3927 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::MulUIExtendedOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::MulUIExtendedOp> { public: static TypeID resolveTypeID() { return id; } private: static SelfOwningTypeID id; }; } } |
3928 | |
3929 | namespace mlir { |
3930 | namespace arith { |
3931 | |
3932 | //===----------------------------------------------------------------------===// |
3933 | // ::mlir::arith::NegFOp declarations |
3934 | //===----------------------------------------------------------------------===// |
3935 | |
3936 | namespace detail { |
3937 | class NegFOpGenericAdaptorBase { |
3938 | public: |
3939 | struct Properties { |
3940 | using fastmathTy = ::mlir::arith::FastMathFlagsAttr; |
3941 | fastmathTy fastmath; |
3942 | |
3943 | auto getFastmath() { |
3944 | auto &propStorage = this->fastmath; |
3945 | return propStorage.dyn_cast_or_null<::mlir::arith::FastMathFlagsAttr>(); |
3946 | } |
3947 | void setFastmath(const ::mlir::arith::FastMathFlagsAttr &propValue) { |
3948 | this->fastmath = propValue; |
3949 | } |
3950 | }; |
3951 | protected: |
3952 | ::mlir::DictionaryAttr odsAttrs; |
3953 | ::std::optional<::mlir::OperationName> odsOpName; |
3954 | Properties properties; |
3955 | ::mlir::RegionRange odsRegions; |
3956 | public: |
3957 | NegFOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}); |
3958 | |
3959 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
3960 | const Properties &getProperties() { |
3961 | return properties; |
3962 | } |
3963 | |
3964 | ::mlir::DictionaryAttr getAttributes(); |
3965 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
3966 | ::mlir::arith::FastMathFlags getFastmath(); |
3967 | }; |
3968 | } // namespace detail |
3969 | template <typename RangeT> |
3970 | class NegFOpGenericAdaptor : public detail::NegFOpGenericAdaptorBase { |
3971 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
3972 | using Base = detail::NegFOpGenericAdaptorBase; |
3973 | public: |
3974 | NegFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
3975 | |
3976 | NegFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : NegFOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {} |
3977 | |
3978 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
3979 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
3980 | } |
3981 | |
3982 | RangeT getODSOperands(unsigned index) { |
3983 | auto valueRange = getODSOperandIndexAndLength(index); |
3984 | return {std::next(odsOperands.begin(), valueRange.first), |
3985 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
3986 | } |
3987 | |
3988 | ValueT getOperand() { |
3989 | return (*getODSOperands(0).begin()); |
3990 | } |
3991 | |
3992 | RangeT getOperands() { |
3993 | return odsOperands; |
3994 | } |
3995 | |
3996 | private: |
3997 | RangeT odsOperands; |
3998 | }; |
3999 | class NegFOpAdaptor : public NegFOpGenericAdaptor<::mlir::ValueRange> { |
4000 | public: |
4001 | using NegFOpGenericAdaptor::NegFOpGenericAdaptor; |
4002 | NegFOpAdaptor(NegFOp op); |
4003 | |
4004 | ::mlir::LogicalResult verify(::mlir::Location loc); |
4005 | }; |
4006 | class NegFOp : public ::mlir::Op<NegFOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::arith::ArithFastMathInterface::Trait, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
4007 | public: |
4008 | using Op::Op; |
4009 | using Op::print; |
4010 | using Adaptor = NegFOpAdaptor; |
4011 | template <typename RangeT> |
4012 | using GenericAdaptor = NegFOpGenericAdaptor<RangeT>; |
4013 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
4014 | using Properties = FoldAdaptor::Properties; |
4015 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
4016 | static ::llvm::StringRef attrNames[] = {::llvm::StringRef("fastmath")}; |
4017 | return ::llvm::ArrayRef(attrNames); |
4018 | } |
4019 | |
4020 | ::mlir::StringAttr getFastmathAttrName() { |
4021 | return getAttributeNameForIndex(0); |
4022 | } |
4023 | |
4024 | static ::mlir::StringAttr getFastmathAttrName(::mlir::OperationName name) { |
4025 | return getAttributeNameForIndex(name, 0); |
4026 | } |
4027 | |
4028 | static constexpr ::llvm::StringLiteral getOperationName() { |
4029 | return ::llvm::StringLiteral("arith.negf"); |
4030 | } |
4031 | |
4032 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
4033 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
4034 | ::mlir::Value getOperand(); |
4035 | ::mlir::MutableOperandRange getOperandMutable(); |
4036 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
4037 | ::mlir::Operation::result_range getODSResults(unsigned index); |
4038 | ::mlir::Value getResult(); |
4039 | static ::mlir::LogicalResult setPropertiesFromAttr(Properties &prop, ::mlir::Attribute attr, ::mlir::InFlightDiagnostic *diag); |
4040 | static ::mlir::Attribute getPropertiesAsAttr(::mlir::MLIRContext *ctx, const Properties &prop); |
4041 | static llvm::hash_code computePropertiesHash(const Properties &prop); |
4042 | static std::optional<mlir::Attribute> getInherentAttr(const Properties &prop, llvm::StringRef name); |
4043 | static void setInherentAttr(Properties &prop, llvm::StringRef name, mlir::Attribute value); |
4044 | static void populateInherentAttrs(const Properties &prop, ::mlir::NamedAttrList &attrs); |
4045 | static ::mlir::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> getDiag); |
4046 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
4047 | ::mlir::arith::FastMathFlags getFastmath(); |
4048 | void setFastmathAttr(::mlir::arith::FastMathFlagsAttr attr); |
4049 | void setFastmath(::mlir::arith::FastMathFlags attrValue); |
4050 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value operand, ::mlir::arith::FastMathFlagsAttr fastmath); |
4051 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value operand, ::mlir::arith::FastMathFlagsAttr fastmath); |
4052 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value operand, ::mlir::arith::FastMathFlagsAttr fastmath); |
4053 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value operand, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
4054 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value operand, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
4055 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value operand, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
4056 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4057 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4058 | static void populateDefaultProperties(::mlir::OperationName opName, Properties &properties); |
4059 | ::mlir::LogicalResult verifyInvariantsImpl(); |
4060 | ::mlir::LogicalResult verifyInvariants(); |
4061 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
4062 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
4063 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
4064 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
4065 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
4066 | private: |
4067 | ::mlir::StringAttr getAttributeNameForIndex(unsigned index) { |
4068 | return getAttributeNameForIndex((*this)->getName(), index); |
4069 | } |
4070 | |
4071 | static ::mlir::StringAttr getAttributeNameForIndex(::mlir::OperationName name, unsigned index) { |
4072 | assert(index < 1 && "invalid attribute index")(static_cast <bool> (index < 1 && "invalid attribute index" ) ? void (0) : __assert_fail ("index < 1 && \"invalid attribute index\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 4072 , __extension__ __PRETTY_FUNCTION__)); |
4073 | assert(name.getStringRef() == getOperationName() && "invalid operation name")(static_cast <bool> (name.getStringRef() == getOperationName () && "invalid operation name") ? void (0) : __assert_fail ("name.getStringRef() == getOperationName() && \"invalid operation name\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 4073 , __extension__ __PRETTY_FUNCTION__)); |
4074 | return name.getAttributeNames()[index]; |
4075 | } |
4076 | |
4077 | public: |
4078 | }; |
4079 | } // namespace arith |
4080 | } // namespace mlir |
4081 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::NegFOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::NegFOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
4082 | |
4083 | namespace mlir { |
4084 | namespace arith { |
4085 | |
4086 | //===----------------------------------------------------------------------===// |
4087 | // ::mlir::arith::OrIOp declarations |
4088 | //===----------------------------------------------------------------------===// |
4089 | |
4090 | namespace detail { |
4091 | class OrIOpGenericAdaptorBase { |
4092 | public: |
4093 | protected: |
4094 | ::mlir::DictionaryAttr odsAttrs; |
4095 | ::std::optional<::mlir::OperationName> odsOpName; |
4096 | ::mlir::RegionRange odsRegions; |
4097 | public: |
4098 | OrIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
4099 | |
4100 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
4101 | ::mlir::DictionaryAttr getAttributes(); |
4102 | }; |
4103 | } // namespace detail |
4104 | template <typename RangeT> |
4105 | class OrIOpGenericAdaptor : public detail::OrIOpGenericAdaptorBase { |
4106 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
4107 | using Base = detail::OrIOpGenericAdaptorBase; |
4108 | public: |
4109 | OrIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
4110 | |
4111 | OrIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : OrIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
4112 | |
4113 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
4114 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
4115 | } |
4116 | |
4117 | RangeT getODSOperands(unsigned index) { |
4118 | auto valueRange = getODSOperandIndexAndLength(index); |
4119 | return {std::next(odsOperands.begin(), valueRange.first), |
4120 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
4121 | } |
4122 | |
4123 | ValueT getLhs() { |
4124 | return (*getODSOperands(0).begin()); |
4125 | } |
4126 | |
4127 | ValueT getRhs() { |
4128 | return (*getODSOperands(1).begin()); |
4129 | } |
4130 | |
4131 | RangeT getOperands() { |
4132 | return odsOperands; |
4133 | } |
4134 | |
4135 | private: |
4136 | RangeT odsOperands; |
4137 | }; |
4138 | class OrIOpAdaptor : public OrIOpGenericAdaptor<::mlir::ValueRange> { |
4139 | public: |
4140 | using OrIOpGenericAdaptor::OrIOpGenericAdaptor; |
4141 | OrIOpAdaptor(OrIOp op); |
4142 | |
4143 | ::mlir::LogicalResult verify(::mlir::Location loc); |
4144 | }; |
4145 | class OrIOp : public ::mlir::Op<OrIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::OpTrait::IsCommutative, ::mlir::OpTrait::IsIdempotent, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
4146 | public: |
4147 | using Op::Op; |
4148 | using Op::print; |
4149 | using Adaptor = OrIOpAdaptor; |
4150 | template <typename RangeT> |
4151 | using GenericAdaptor = OrIOpGenericAdaptor<RangeT>; |
4152 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
4153 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
4154 | return {}; |
4155 | } |
4156 | |
4157 | static constexpr ::llvm::StringLiteral getOperationName() { |
4158 | return ::llvm::StringLiteral("arith.ori"); |
4159 | } |
4160 | |
4161 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
4162 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
4163 | ::mlir::Value getLhs(); |
4164 | ::mlir::Value getRhs(); |
4165 | ::mlir::MutableOperandRange getLhsMutable(); |
4166 | ::mlir::MutableOperandRange getRhsMutable(); |
4167 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
4168 | ::mlir::Operation::result_range getODSResults(unsigned index); |
4169 | ::mlir::Value getResult(); |
4170 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
4171 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
4172 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
4173 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4174 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4175 | ::mlir::LogicalResult verifyInvariantsImpl(); |
4176 | ::mlir::LogicalResult verifyInvariants(); |
4177 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
4178 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
4179 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
4180 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
4181 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
4182 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
4183 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
4184 | public: |
4185 | }; |
4186 | } // namespace arith |
4187 | } // namespace mlir |
4188 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::OrIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::OrIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
4189 | |
4190 | namespace mlir { |
4191 | namespace arith { |
4192 | |
4193 | //===----------------------------------------------------------------------===// |
4194 | // ::mlir::arith::RemFOp declarations |
4195 | //===----------------------------------------------------------------------===// |
4196 | |
4197 | namespace detail { |
4198 | class RemFOpGenericAdaptorBase { |
4199 | public: |
4200 | struct Properties { |
4201 | using fastmathTy = ::mlir::arith::FastMathFlagsAttr; |
4202 | fastmathTy fastmath; |
4203 | |
4204 | auto getFastmath() { |
4205 | auto &propStorage = this->fastmath; |
4206 | return propStorage.dyn_cast_or_null<::mlir::arith::FastMathFlagsAttr>(); |
4207 | } |
4208 | void setFastmath(const ::mlir::arith::FastMathFlagsAttr &propValue) { |
4209 | this->fastmath = propValue; |
4210 | } |
4211 | }; |
4212 | protected: |
4213 | ::mlir::DictionaryAttr odsAttrs; |
4214 | ::std::optional<::mlir::OperationName> odsOpName; |
4215 | Properties properties; |
4216 | ::mlir::RegionRange odsRegions; |
4217 | public: |
4218 | RemFOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}); |
4219 | |
4220 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
4221 | const Properties &getProperties() { |
4222 | return properties; |
4223 | } |
4224 | |
4225 | ::mlir::DictionaryAttr getAttributes(); |
4226 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
4227 | ::mlir::arith::FastMathFlags getFastmath(); |
4228 | }; |
4229 | } // namespace detail |
4230 | template <typename RangeT> |
4231 | class RemFOpGenericAdaptor : public detail::RemFOpGenericAdaptorBase { |
4232 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
4233 | using Base = detail::RemFOpGenericAdaptorBase; |
4234 | public: |
4235 | RemFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
4236 | |
4237 | RemFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : RemFOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {} |
4238 | |
4239 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
4240 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
4241 | } |
4242 | |
4243 | RangeT getODSOperands(unsigned index) { |
4244 | auto valueRange = getODSOperandIndexAndLength(index); |
4245 | return {std::next(odsOperands.begin(), valueRange.first), |
4246 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
4247 | } |
4248 | |
4249 | ValueT getLhs() { |
4250 | return (*getODSOperands(0).begin()); |
4251 | } |
4252 | |
4253 | ValueT getRhs() { |
4254 | return (*getODSOperands(1).begin()); |
4255 | } |
4256 | |
4257 | RangeT getOperands() { |
4258 | return odsOperands; |
4259 | } |
4260 | |
4261 | private: |
4262 | RangeT odsOperands; |
4263 | }; |
4264 | class RemFOpAdaptor : public RemFOpGenericAdaptor<::mlir::ValueRange> { |
4265 | public: |
4266 | using RemFOpGenericAdaptor::RemFOpGenericAdaptor; |
4267 | RemFOpAdaptor(RemFOp op); |
4268 | |
4269 | ::mlir::LogicalResult verify(::mlir::Location loc); |
4270 | }; |
4271 | class RemFOp : public ::mlir::Op<RemFOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::arith::ArithFastMathInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
4272 | public: |
4273 | using Op::Op; |
4274 | using Op::print; |
4275 | using Adaptor = RemFOpAdaptor; |
4276 | template <typename RangeT> |
4277 | using GenericAdaptor = RemFOpGenericAdaptor<RangeT>; |
4278 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
4279 | using Properties = FoldAdaptor::Properties; |
4280 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
4281 | static ::llvm::StringRef attrNames[] = {::llvm::StringRef("fastmath")}; |
4282 | return ::llvm::ArrayRef(attrNames); |
4283 | } |
4284 | |
4285 | ::mlir::StringAttr getFastmathAttrName() { |
4286 | return getAttributeNameForIndex(0); |
4287 | } |
4288 | |
4289 | static ::mlir::StringAttr getFastmathAttrName(::mlir::OperationName name) { |
4290 | return getAttributeNameForIndex(name, 0); |
4291 | } |
4292 | |
4293 | static constexpr ::llvm::StringLiteral getOperationName() { |
4294 | return ::llvm::StringLiteral("arith.remf"); |
4295 | } |
4296 | |
4297 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
4298 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
4299 | ::mlir::Value getLhs(); |
4300 | ::mlir::Value getRhs(); |
4301 | ::mlir::MutableOperandRange getLhsMutable(); |
4302 | ::mlir::MutableOperandRange getRhsMutable(); |
4303 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
4304 | ::mlir::Operation::result_range getODSResults(unsigned index); |
4305 | ::mlir::Value getResult(); |
4306 | static ::mlir::LogicalResult setPropertiesFromAttr(Properties &prop, ::mlir::Attribute attr, ::mlir::InFlightDiagnostic *diag); |
4307 | static ::mlir::Attribute getPropertiesAsAttr(::mlir::MLIRContext *ctx, const Properties &prop); |
4308 | static llvm::hash_code computePropertiesHash(const Properties &prop); |
4309 | static std::optional<mlir::Attribute> getInherentAttr(const Properties &prop, llvm::StringRef name); |
4310 | static void setInherentAttr(Properties &prop, llvm::StringRef name, mlir::Attribute value); |
4311 | static void populateInherentAttrs(const Properties &prop, ::mlir::NamedAttrList &attrs); |
4312 | static ::mlir::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> getDiag); |
4313 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
4314 | ::mlir::arith::FastMathFlags getFastmath(); |
4315 | void setFastmathAttr(::mlir::arith::FastMathFlagsAttr attr); |
4316 | void setFastmath(::mlir::arith::FastMathFlags attrValue); |
4317 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
4318 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
4319 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
4320 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
4321 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
4322 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
4323 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4324 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4325 | static void populateDefaultProperties(::mlir::OperationName opName, Properties &properties); |
4326 | ::mlir::LogicalResult verifyInvariantsImpl(); |
4327 | ::mlir::LogicalResult verifyInvariants(); |
4328 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
4329 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
4330 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
4331 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
4332 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
4333 | private: |
4334 | ::mlir::StringAttr getAttributeNameForIndex(unsigned index) { |
4335 | return getAttributeNameForIndex((*this)->getName(), index); |
4336 | } |
4337 | |
4338 | static ::mlir::StringAttr getAttributeNameForIndex(::mlir::OperationName name, unsigned index) { |
4339 | assert(index < 1 && "invalid attribute index")(static_cast <bool> (index < 1 && "invalid attribute index" ) ? void (0) : __assert_fail ("index < 1 && \"invalid attribute index\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 4339 , __extension__ __PRETTY_FUNCTION__)); |
4340 | assert(name.getStringRef() == getOperationName() && "invalid operation name")(static_cast <bool> (name.getStringRef() == getOperationName () && "invalid operation name") ? void (0) : __assert_fail ("name.getStringRef() == getOperationName() && \"invalid operation name\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 4340 , __extension__ __PRETTY_FUNCTION__)); |
4341 | return name.getAttributeNames()[index]; |
4342 | } |
4343 | |
4344 | public: |
4345 | }; |
4346 | } // namespace arith |
4347 | } // namespace mlir |
4348 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::RemFOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::RemFOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
4349 | |
4350 | namespace mlir { |
4351 | namespace arith { |
4352 | |
4353 | //===----------------------------------------------------------------------===// |
4354 | // ::mlir::arith::RemSIOp declarations |
4355 | //===----------------------------------------------------------------------===// |
4356 | |
4357 | namespace detail { |
4358 | class RemSIOpGenericAdaptorBase { |
4359 | public: |
4360 | protected: |
4361 | ::mlir::DictionaryAttr odsAttrs; |
4362 | ::std::optional<::mlir::OperationName> odsOpName; |
4363 | ::mlir::RegionRange odsRegions; |
4364 | public: |
4365 | RemSIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
4366 | |
4367 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
4368 | ::mlir::DictionaryAttr getAttributes(); |
4369 | }; |
4370 | } // namespace detail |
4371 | template <typename RangeT> |
4372 | class RemSIOpGenericAdaptor : public detail::RemSIOpGenericAdaptorBase { |
4373 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
4374 | using Base = detail::RemSIOpGenericAdaptorBase; |
4375 | public: |
4376 | RemSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
4377 | |
4378 | RemSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : RemSIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
4379 | |
4380 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
4381 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
4382 | } |
4383 | |
4384 | RangeT getODSOperands(unsigned index) { |
4385 | auto valueRange = getODSOperandIndexAndLength(index); |
4386 | return {std::next(odsOperands.begin(), valueRange.first), |
4387 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
4388 | } |
4389 | |
4390 | ValueT getLhs() { |
4391 | return (*getODSOperands(0).begin()); |
4392 | } |
4393 | |
4394 | ValueT getRhs() { |
4395 | return (*getODSOperands(1).begin()); |
4396 | } |
4397 | |
4398 | RangeT getOperands() { |
4399 | return odsOperands; |
4400 | } |
4401 | |
4402 | private: |
4403 | RangeT odsOperands; |
4404 | }; |
4405 | class RemSIOpAdaptor : public RemSIOpGenericAdaptor<::mlir::ValueRange> { |
4406 | public: |
4407 | using RemSIOpGenericAdaptor::RemSIOpGenericAdaptor; |
4408 | RemSIOpAdaptor(RemSIOp op); |
4409 | |
4410 | ::mlir::LogicalResult verify(::mlir::Location loc); |
4411 | }; |
4412 | class RemSIOp : public ::mlir::Op<RemSIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
4413 | public: |
4414 | using Op::Op; |
4415 | using Op::print; |
4416 | using Adaptor = RemSIOpAdaptor; |
4417 | template <typename RangeT> |
4418 | using GenericAdaptor = RemSIOpGenericAdaptor<RangeT>; |
4419 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
4420 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
4421 | return {}; |
4422 | } |
4423 | |
4424 | static constexpr ::llvm::StringLiteral getOperationName() { |
4425 | return ::llvm::StringLiteral("arith.remsi"); |
4426 | } |
4427 | |
4428 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
4429 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
4430 | ::mlir::Value getLhs(); |
4431 | ::mlir::Value getRhs(); |
4432 | ::mlir::MutableOperandRange getLhsMutable(); |
4433 | ::mlir::MutableOperandRange getRhsMutable(); |
4434 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
4435 | ::mlir::Operation::result_range getODSResults(unsigned index); |
4436 | ::mlir::Value getResult(); |
4437 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
4438 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
4439 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
4440 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4441 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4442 | ::mlir::LogicalResult verifyInvariantsImpl(); |
4443 | ::mlir::LogicalResult verifyInvariants(); |
4444 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
4445 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
4446 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
4447 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
4448 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
4449 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
4450 | public: |
4451 | }; |
4452 | } // namespace arith |
4453 | } // namespace mlir |
4454 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::RemSIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::RemSIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
4455 | |
4456 | namespace mlir { |
4457 | namespace arith { |
4458 | |
4459 | //===----------------------------------------------------------------------===// |
4460 | // ::mlir::arith::RemUIOp declarations |
4461 | //===----------------------------------------------------------------------===// |
4462 | |
4463 | namespace detail { |
4464 | class RemUIOpGenericAdaptorBase { |
4465 | public: |
4466 | protected: |
4467 | ::mlir::DictionaryAttr odsAttrs; |
4468 | ::std::optional<::mlir::OperationName> odsOpName; |
4469 | ::mlir::RegionRange odsRegions; |
4470 | public: |
4471 | RemUIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
4472 | |
4473 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
4474 | ::mlir::DictionaryAttr getAttributes(); |
4475 | }; |
4476 | } // namespace detail |
4477 | template <typename RangeT> |
4478 | class RemUIOpGenericAdaptor : public detail::RemUIOpGenericAdaptorBase { |
4479 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
4480 | using Base = detail::RemUIOpGenericAdaptorBase; |
4481 | public: |
4482 | RemUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
4483 | |
4484 | RemUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : RemUIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
4485 | |
4486 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
4487 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
4488 | } |
4489 | |
4490 | RangeT getODSOperands(unsigned index) { |
4491 | auto valueRange = getODSOperandIndexAndLength(index); |
4492 | return {std::next(odsOperands.begin(), valueRange.first), |
4493 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
4494 | } |
4495 | |
4496 | ValueT getLhs() { |
4497 | return (*getODSOperands(0).begin()); |
4498 | } |
4499 | |
4500 | ValueT getRhs() { |
4501 | return (*getODSOperands(1).begin()); |
4502 | } |
4503 | |
4504 | RangeT getOperands() { |
4505 | return odsOperands; |
4506 | } |
4507 | |
4508 | private: |
4509 | RangeT odsOperands; |
4510 | }; |
4511 | class RemUIOpAdaptor : public RemUIOpGenericAdaptor<::mlir::ValueRange> { |
4512 | public: |
4513 | using RemUIOpGenericAdaptor::RemUIOpGenericAdaptor; |
4514 | RemUIOpAdaptor(RemUIOp op); |
4515 | |
4516 | ::mlir::LogicalResult verify(::mlir::Location loc); |
4517 | }; |
4518 | class RemUIOp : public ::mlir::Op<RemUIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
4519 | public: |
4520 | using Op::Op; |
4521 | using Op::print; |
4522 | using Adaptor = RemUIOpAdaptor; |
4523 | template <typename RangeT> |
4524 | using GenericAdaptor = RemUIOpGenericAdaptor<RangeT>; |
4525 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
4526 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
4527 | return {}; |
4528 | } |
4529 | |
4530 | static constexpr ::llvm::StringLiteral getOperationName() { |
4531 | return ::llvm::StringLiteral("arith.remui"); |
4532 | } |
4533 | |
4534 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
4535 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
4536 | ::mlir::Value getLhs(); |
4537 | ::mlir::Value getRhs(); |
4538 | ::mlir::MutableOperandRange getLhsMutable(); |
4539 | ::mlir::MutableOperandRange getRhsMutable(); |
4540 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
4541 | ::mlir::Operation::result_range getODSResults(unsigned index); |
4542 | ::mlir::Value getResult(); |
4543 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
4544 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
4545 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
4546 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4547 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4548 | ::mlir::LogicalResult verifyInvariantsImpl(); |
4549 | ::mlir::LogicalResult verifyInvariants(); |
4550 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
4551 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
4552 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
4553 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
4554 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
4555 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
4556 | public: |
4557 | }; |
4558 | } // namespace arith |
4559 | } // namespace mlir |
4560 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::RemUIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::RemUIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
4561 | |
4562 | namespace mlir { |
4563 | namespace arith { |
4564 | |
4565 | //===----------------------------------------------------------------------===// |
4566 | // ::mlir::arith::SIToFPOp declarations |
4567 | //===----------------------------------------------------------------------===// |
4568 | |
4569 | namespace detail { |
4570 | class SIToFPOpGenericAdaptorBase { |
4571 | public: |
4572 | protected: |
4573 | ::mlir::DictionaryAttr odsAttrs; |
4574 | ::std::optional<::mlir::OperationName> odsOpName; |
4575 | ::mlir::RegionRange odsRegions; |
4576 | public: |
4577 | SIToFPOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
4578 | |
4579 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
4580 | ::mlir::DictionaryAttr getAttributes(); |
4581 | }; |
4582 | } // namespace detail |
4583 | template <typename RangeT> |
4584 | class SIToFPOpGenericAdaptor : public detail::SIToFPOpGenericAdaptorBase { |
4585 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
4586 | using Base = detail::SIToFPOpGenericAdaptorBase; |
4587 | public: |
4588 | SIToFPOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
4589 | |
4590 | SIToFPOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : SIToFPOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
4591 | |
4592 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
4593 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
4594 | } |
4595 | |
4596 | RangeT getODSOperands(unsigned index) { |
4597 | auto valueRange = getODSOperandIndexAndLength(index); |
4598 | return {std::next(odsOperands.begin(), valueRange.first), |
4599 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
4600 | } |
4601 | |
4602 | ValueT getIn() { |
4603 | return (*getODSOperands(0).begin()); |
4604 | } |
4605 | |
4606 | RangeT getOperands() { |
4607 | return odsOperands; |
4608 | } |
4609 | |
4610 | private: |
4611 | RangeT odsOperands; |
4612 | }; |
4613 | class SIToFPOpAdaptor : public SIToFPOpGenericAdaptor<::mlir::ValueRange> { |
4614 | public: |
4615 | using SIToFPOpGenericAdaptor::SIToFPOpGenericAdaptor; |
4616 | SIToFPOpAdaptor(SIToFPOp op); |
4617 | |
4618 | ::mlir::LogicalResult verify(::mlir::Location loc); |
4619 | }; |
4620 | class SIToFPOp : public ::mlir::Op<SIToFPOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
4621 | public: |
4622 | using Op::Op; |
4623 | using Op::print; |
4624 | using Adaptor = SIToFPOpAdaptor; |
4625 | template <typename RangeT> |
4626 | using GenericAdaptor = SIToFPOpGenericAdaptor<RangeT>; |
4627 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
4628 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
4629 | return {}; |
4630 | } |
4631 | |
4632 | static constexpr ::llvm::StringLiteral getOperationName() { |
4633 | return ::llvm::StringLiteral("arith.sitofp"); |
4634 | } |
4635 | |
4636 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
4637 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
4638 | ::mlir::Value getIn(); |
4639 | ::mlir::MutableOperandRange getInMutable(); |
4640 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
4641 | ::mlir::Operation::result_range getODSResults(unsigned index); |
4642 | ::mlir::Value getOut(); |
4643 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
4644 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
4645 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4646 | ::mlir::LogicalResult verifyInvariantsImpl(); |
4647 | ::mlir::LogicalResult verifyInvariants(); |
4648 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
4649 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
4650 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
4651 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
4652 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
4653 | public: |
4654 | }; |
4655 | } // namespace arith |
4656 | } // namespace mlir |
4657 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::SIToFPOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::SIToFPOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
4658 | |
4659 | namespace mlir { |
4660 | namespace arith { |
4661 | |
4662 | //===----------------------------------------------------------------------===// |
4663 | // ::mlir::arith::ShLIOp declarations |
4664 | //===----------------------------------------------------------------------===// |
4665 | |
4666 | namespace detail { |
4667 | class ShLIOpGenericAdaptorBase { |
4668 | public: |
4669 | protected: |
4670 | ::mlir::DictionaryAttr odsAttrs; |
4671 | ::std::optional<::mlir::OperationName> odsOpName; |
4672 | ::mlir::RegionRange odsRegions; |
4673 | public: |
4674 | ShLIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
4675 | |
4676 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
4677 | ::mlir::DictionaryAttr getAttributes(); |
4678 | }; |
4679 | } // namespace detail |
4680 | template <typename RangeT> |
4681 | class ShLIOpGenericAdaptor : public detail::ShLIOpGenericAdaptorBase { |
4682 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
4683 | using Base = detail::ShLIOpGenericAdaptorBase; |
4684 | public: |
4685 | ShLIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
4686 | |
4687 | ShLIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : ShLIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
4688 | |
4689 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
4690 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
4691 | } |
4692 | |
4693 | RangeT getODSOperands(unsigned index) { |
4694 | auto valueRange = getODSOperandIndexAndLength(index); |
4695 | return {std::next(odsOperands.begin(), valueRange.first), |
4696 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
4697 | } |
4698 | |
4699 | ValueT getLhs() { |
4700 | return (*getODSOperands(0).begin()); |
4701 | } |
4702 | |
4703 | ValueT getRhs() { |
4704 | return (*getODSOperands(1).begin()); |
4705 | } |
4706 | |
4707 | RangeT getOperands() { |
4708 | return odsOperands; |
4709 | } |
4710 | |
4711 | private: |
4712 | RangeT odsOperands; |
4713 | }; |
4714 | class ShLIOpAdaptor : public ShLIOpGenericAdaptor<::mlir::ValueRange> { |
4715 | public: |
4716 | using ShLIOpGenericAdaptor::ShLIOpGenericAdaptor; |
4717 | ShLIOpAdaptor(ShLIOp op); |
4718 | |
4719 | ::mlir::LogicalResult verify(::mlir::Location loc); |
4720 | }; |
4721 | class ShLIOp : public ::mlir::Op<ShLIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
4722 | public: |
4723 | using Op::Op; |
4724 | using Op::print; |
4725 | using Adaptor = ShLIOpAdaptor; |
4726 | template <typename RangeT> |
4727 | using GenericAdaptor = ShLIOpGenericAdaptor<RangeT>; |
4728 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
4729 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
4730 | return {}; |
4731 | } |
4732 | |
4733 | static constexpr ::llvm::StringLiteral getOperationName() { |
4734 | return ::llvm::StringLiteral("arith.shli"); |
4735 | } |
4736 | |
4737 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
4738 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
4739 | ::mlir::Value getLhs(); |
4740 | ::mlir::Value getRhs(); |
4741 | ::mlir::MutableOperandRange getLhsMutable(); |
4742 | ::mlir::MutableOperandRange getRhsMutable(); |
4743 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
4744 | ::mlir::Operation::result_range getODSResults(unsigned index); |
4745 | ::mlir::Value getResult(); |
4746 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
4747 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
4748 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
4749 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4750 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4751 | ::mlir::LogicalResult verifyInvariantsImpl(); |
4752 | ::mlir::LogicalResult verifyInvariants(); |
4753 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
4754 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
4755 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
4756 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
4757 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
4758 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
4759 | public: |
4760 | }; |
4761 | } // namespace arith |
4762 | } // namespace mlir |
4763 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::ShLIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::ShLIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
4764 | |
4765 | namespace mlir { |
4766 | namespace arith { |
4767 | |
4768 | //===----------------------------------------------------------------------===// |
4769 | // ::mlir::arith::ShRSIOp declarations |
4770 | //===----------------------------------------------------------------------===// |
4771 | |
4772 | namespace detail { |
4773 | class ShRSIOpGenericAdaptorBase { |
4774 | public: |
4775 | protected: |
4776 | ::mlir::DictionaryAttr odsAttrs; |
4777 | ::std::optional<::mlir::OperationName> odsOpName; |
4778 | ::mlir::RegionRange odsRegions; |
4779 | public: |
4780 | ShRSIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
4781 | |
4782 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
4783 | ::mlir::DictionaryAttr getAttributes(); |
4784 | }; |
4785 | } // namespace detail |
4786 | template <typename RangeT> |
4787 | class ShRSIOpGenericAdaptor : public detail::ShRSIOpGenericAdaptorBase { |
4788 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
4789 | using Base = detail::ShRSIOpGenericAdaptorBase; |
4790 | public: |
4791 | ShRSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
4792 | |
4793 | ShRSIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : ShRSIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
4794 | |
4795 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
4796 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
4797 | } |
4798 | |
4799 | RangeT getODSOperands(unsigned index) { |
4800 | auto valueRange = getODSOperandIndexAndLength(index); |
4801 | return {std::next(odsOperands.begin(), valueRange.first), |
4802 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
4803 | } |
4804 | |
4805 | ValueT getLhs() { |
4806 | return (*getODSOperands(0).begin()); |
4807 | } |
4808 | |
4809 | ValueT getRhs() { |
4810 | return (*getODSOperands(1).begin()); |
4811 | } |
4812 | |
4813 | RangeT getOperands() { |
4814 | return odsOperands; |
4815 | } |
4816 | |
4817 | private: |
4818 | RangeT odsOperands; |
4819 | }; |
4820 | class ShRSIOpAdaptor : public ShRSIOpGenericAdaptor<::mlir::ValueRange> { |
4821 | public: |
4822 | using ShRSIOpGenericAdaptor::ShRSIOpGenericAdaptor; |
4823 | ShRSIOpAdaptor(ShRSIOp op); |
4824 | |
4825 | ::mlir::LogicalResult verify(::mlir::Location loc); |
4826 | }; |
4827 | class ShRSIOp : public ::mlir::Op<ShRSIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
4828 | public: |
4829 | using Op::Op; |
4830 | using Op::print; |
4831 | using Adaptor = ShRSIOpAdaptor; |
4832 | template <typename RangeT> |
4833 | using GenericAdaptor = ShRSIOpGenericAdaptor<RangeT>; |
4834 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
4835 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
4836 | return {}; |
4837 | } |
4838 | |
4839 | static constexpr ::llvm::StringLiteral getOperationName() { |
4840 | return ::llvm::StringLiteral("arith.shrsi"); |
4841 | } |
4842 | |
4843 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
4844 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
4845 | ::mlir::Value getLhs(); |
4846 | ::mlir::Value getRhs(); |
4847 | ::mlir::MutableOperandRange getLhsMutable(); |
4848 | ::mlir::MutableOperandRange getRhsMutable(); |
4849 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
4850 | ::mlir::Operation::result_range getODSResults(unsigned index); |
4851 | ::mlir::Value getResult(); |
4852 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
4853 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
4854 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
4855 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4856 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4857 | ::mlir::LogicalResult verifyInvariantsImpl(); |
4858 | ::mlir::LogicalResult verifyInvariants(); |
4859 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
4860 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
4861 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
4862 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
4863 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
4864 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
4865 | public: |
4866 | }; |
4867 | } // namespace arith |
4868 | } // namespace mlir |
4869 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::ShRSIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::ShRSIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
4870 | |
4871 | namespace mlir { |
4872 | namespace arith { |
4873 | |
4874 | //===----------------------------------------------------------------------===// |
4875 | // ::mlir::arith::ShRUIOp declarations |
4876 | //===----------------------------------------------------------------------===// |
4877 | |
4878 | namespace detail { |
4879 | class ShRUIOpGenericAdaptorBase { |
4880 | public: |
4881 | protected: |
4882 | ::mlir::DictionaryAttr odsAttrs; |
4883 | ::std::optional<::mlir::OperationName> odsOpName; |
4884 | ::mlir::RegionRange odsRegions; |
4885 | public: |
4886 | ShRUIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
4887 | |
4888 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
4889 | ::mlir::DictionaryAttr getAttributes(); |
4890 | }; |
4891 | } // namespace detail |
4892 | template <typename RangeT> |
4893 | class ShRUIOpGenericAdaptor : public detail::ShRUIOpGenericAdaptorBase { |
4894 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
4895 | using Base = detail::ShRUIOpGenericAdaptorBase; |
4896 | public: |
4897 | ShRUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
4898 | |
4899 | ShRUIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : ShRUIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
4900 | |
4901 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
4902 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
4903 | } |
4904 | |
4905 | RangeT getODSOperands(unsigned index) { |
4906 | auto valueRange = getODSOperandIndexAndLength(index); |
4907 | return {std::next(odsOperands.begin(), valueRange.first), |
4908 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
4909 | } |
4910 | |
4911 | ValueT getLhs() { |
4912 | return (*getODSOperands(0).begin()); |
4913 | } |
4914 | |
4915 | ValueT getRhs() { |
4916 | return (*getODSOperands(1).begin()); |
4917 | } |
4918 | |
4919 | RangeT getOperands() { |
4920 | return odsOperands; |
4921 | } |
4922 | |
4923 | private: |
4924 | RangeT odsOperands; |
4925 | }; |
4926 | class ShRUIOpAdaptor : public ShRUIOpGenericAdaptor<::mlir::ValueRange> { |
4927 | public: |
4928 | using ShRUIOpGenericAdaptor::ShRUIOpGenericAdaptor; |
4929 | ShRUIOpAdaptor(ShRUIOp op); |
4930 | |
4931 | ::mlir::LogicalResult verify(::mlir::Location loc); |
4932 | }; |
4933 | class ShRUIOp : public ::mlir::Op<ShRUIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
4934 | public: |
4935 | using Op::Op; |
4936 | using Op::print; |
4937 | using Adaptor = ShRUIOpAdaptor; |
4938 | template <typename RangeT> |
4939 | using GenericAdaptor = ShRUIOpGenericAdaptor<RangeT>; |
4940 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
4941 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
4942 | return {}; |
4943 | } |
4944 | |
4945 | static constexpr ::llvm::StringLiteral getOperationName() { |
4946 | return ::llvm::StringLiteral("arith.shrui"); |
4947 | } |
4948 | |
4949 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
4950 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
4951 | ::mlir::Value getLhs(); |
4952 | ::mlir::Value getRhs(); |
4953 | ::mlir::MutableOperandRange getLhsMutable(); |
4954 | ::mlir::MutableOperandRange getRhsMutable(); |
4955 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
4956 | ::mlir::Operation::result_range getODSResults(unsigned index); |
4957 | ::mlir::Value getResult(); |
4958 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
4959 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
4960 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
4961 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4962 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
4963 | ::mlir::LogicalResult verifyInvariantsImpl(); |
4964 | ::mlir::LogicalResult verifyInvariants(); |
4965 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
4966 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
4967 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
4968 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
4969 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
4970 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
4971 | public: |
4972 | }; |
4973 | } // namespace arith |
4974 | } // namespace mlir |
4975 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::ShRUIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::ShRUIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
4976 | |
4977 | namespace mlir { |
4978 | namespace arith { |
4979 | |
4980 | //===----------------------------------------------------------------------===// |
4981 | // ::mlir::arith::SubFOp declarations |
4982 | //===----------------------------------------------------------------------===// |
4983 | |
4984 | namespace detail { |
4985 | class SubFOpGenericAdaptorBase { |
4986 | public: |
4987 | struct Properties { |
4988 | using fastmathTy = ::mlir::arith::FastMathFlagsAttr; |
4989 | fastmathTy fastmath; |
4990 | |
4991 | auto getFastmath() { |
4992 | auto &propStorage = this->fastmath; |
4993 | return propStorage.dyn_cast_or_null<::mlir::arith::FastMathFlagsAttr>(); |
4994 | } |
4995 | void setFastmath(const ::mlir::arith::FastMathFlagsAttr &propValue) { |
4996 | this->fastmath = propValue; |
4997 | } |
4998 | }; |
4999 | protected: |
5000 | ::mlir::DictionaryAttr odsAttrs; |
5001 | ::std::optional<::mlir::OperationName> odsOpName; |
5002 | Properties properties; |
5003 | ::mlir::RegionRange odsRegions; |
5004 | public: |
5005 | SubFOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}); |
5006 | |
5007 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
5008 | const Properties &getProperties() { |
5009 | return properties; |
5010 | } |
5011 | |
5012 | ::mlir::DictionaryAttr getAttributes(); |
5013 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
5014 | ::mlir::arith::FastMathFlags getFastmath(); |
5015 | }; |
5016 | } // namespace detail |
5017 | template <typename RangeT> |
5018 | class SubFOpGenericAdaptor : public detail::SubFOpGenericAdaptorBase { |
5019 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
5020 | using Base = detail::SubFOpGenericAdaptorBase; |
5021 | public: |
5022 | SubFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const Properties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
5023 | |
5024 | SubFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : SubFOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {} |
5025 | |
5026 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
5027 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
5028 | } |
5029 | |
5030 | RangeT getODSOperands(unsigned index) { |
5031 | auto valueRange = getODSOperandIndexAndLength(index); |
5032 | return {std::next(odsOperands.begin(), valueRange.first), |
5033 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
5034 | } |
5035 | |
5036 | ValueT getLhs() { |
5037 | return (*getODSOperands(0).begin()); |
5038 | } |
5039 | |
5040 | ValueT getRhs() { |
5041 | return (*getODSOperands(1).begin()); |
5042 | } |
5043 | |
5044 | RangeT getOperands() { |
5045 | return odsOperands; |
5046 | } |
5047 | |
5048 | private: |
5049 | RangeT odsOperands; |
5050 | }; |
5051 | class SubFOpAdaptor : public SubFOpGenericAdaptor<::mlir::ValueRange> { |
5052 | public: |
5053 | using SubFOpGenericAdaptor::SubFOpGenericAdaptor; |
5054 | SubFOpAdaptor(SubFOp op); |
5055 | |
5056 | ::mlir::LogicalResult verify(::mlir::Location loc); |
5057 | }; |
5058 | class SubFOp : public ::mlir::Op<SubFOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::arith::ArithFastMathInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
5059 | public: |
5060 | using Op::Op; |
5061 | using Op::print; |
5062 | using Adaptor = SubFOpAdaptor; |
5063 | template <typename RangeT> |
5064 | using GenericAdaptor = SubFOpGenericAdaptor<RangeT>; |
5065 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
5066 | using Properties = FoldAdaptor::Properties; |
5067 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
5068 | static ::llvm::StringRef attrNames[] = {::llvm::StringRef("fastmath")}; |
5069 | return ::llvm::ArrayRef(attrNames); |
5070 | } |
5071 | |
5072 | ::mlir::StringAttr getFastmathAttrName() { |
5073 | return getAttributeNameForIndex(0); |
5074 | } |
5075 | |
5076 | static ::mlir::StringAttr getFastmathAttrName(::mlir::OperationName name) { |
5077 | return getAttributeNameForIndex(name, 0); |
5078 | } |
5079 | |
5080 | static constexpr ::llvm::StringLiteral getOperationName() { |
5081 | return ::llvm::StringLiteral("arith.subf"); |
5082 | } |
5083 | |
5084 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
5085 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
5086 | ::mlir::Value getLhs(); |
5087 | ::mlir::Value getRhs(); |
5088 | ::mlir::MutableOperandRange getLhsMutable(); |
5089 | ::mlir::MutableOperandRange getRhsMutable(); |
5090 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
5091 | ::mlir::Operation::result_range getODSResults(unsigned index); |
5092 | ::mlir::Value getResult(); |
5093 | static ::mlir::LogicalResult setPropertiesFromAttr(Properties &prop, ::mlir::Attribute attr, ::mlir::InFlightDiagnostic *diag); |
5094 | static ::mlir::Attribute getPropertiesAsAttr(::mlir::MLIRContext *ctx, const Properties &prop); |
5095 | static llvm::hash_code computePropertiesHash(const Properties &prop); |
5096 | static std::optional<mlir::Attribute> getInherentAttr(const Properties &prop, llvm::StringRef name); |
5097 | static void setInherentAttr(Properties &prop, llvm::StringRef name, mlir::Attribute value); |
5098 | static void populateInherentAttrs(const Properties &prop, ::mlir::NamedAttrList &attrs); |
5099 | static ::mlir::LogicalResult verifyInherentAttrs(::mlir::OperationName opName, ::mlir::NamedAttrList &attrs, llvm::function_ref<::mlir::InFlightDiagnostic()> getDiag); |
5100 | ::mlir::arith::FastMathFlagsAttr getFastmathAttr(); |
5101 | ::mlir::arith::FastMathFlags getFastmath(); |
5102 | void setFastmathAttr(::mlir::arith::FastMathFlagsAttr attr); |
5103 | void setFastmath(::mlir::arith::FastMathFlags attrValue); |
5104 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
5105 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
5106 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlagsAttr fastmath); |
5107 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
5108 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
5109 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs, ::mlir::arith::FastMathFlags fastmath = ::mlir::arith::FastMathFlags::none); |
5110 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
5111 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
5112 | static void populateDefaultProperties(::mlir::OperationName opName, Properties &properties); |
5113 | ::mlir::LogicalResult verifyInvariantsImpl(); |
5114 | ::mlir::LogicalResult verifyInvariants(); |
5115 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
5116 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
5117 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
5118 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
5119 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
5120 | private: |
5121 | ::mlir::StringAttr getAttributeNameForIndex(unsigned index) { |
5122 | return getAttributeNameForIndex((*this)->getName(), index); |
5123 | } |
5124 | |
5125 | static ::mlir::StringAttr getAttributeNameForIndex(::mlir::OperationName name, unsigned index) { |
5126 | assert(index < 1 && "invalid attribute index")(static_cast <bool> (index < 1 && "invalid attribute index" ) ? void (0) : __assert_fail ("index < 1 && \"invalid attribute index\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 5126 , __extension__ __PRETTY_FUNCTION__)); |
5127 | assert(name.getStringRef() == getOperationName() && "invalid operation name")(static_cast <bool> (name.getStringRef() == getOperationName () && "invalid operation name") ? void (0) : __assert_fail ("name.getStringRef() == getOperationName() && \"invalid operation name\"" , "tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc", 5127 , __extension__ __PRETTY_FUNCTION__)); |
5128 | return name.getAttributeNames()[index]; |
5129 | } |
5130 | |
5131 | public: |
5132 | }; |
5133 | } // namespace arith |
5134 | } // namespace mlir |
5135 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::SubFOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::SubFOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
5136 | |
5137 | namespace mlir { |
5138 | namespace arith { |
5139 | |
5140 | //===----------------------------------------------------------------------===// |
5141 | // ::mlir::arith::SubIOp declarations |
5142 | //===----------------------------------------------------------------------===// |
5143 | |
5144 | namespace detail { |
5145 | class SubIOpGenericAdaptorBase { |
5146 | public: |
5147 | protected: |
5148 | ::mlir::DictionaryAttr odsAttrs; |
5149 | ::std::optional<::mlir::OperationName> odsOpName; |
5150 | ::mlir::RegionRange odsRegions; |
5151 | public: |
5152 | SubIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
5153 | |
5154 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
5155 | ::mlir::DictionaryAttr getAttributes(); |
5156 | }; |
5157 | } // namespace detail |
5158 | template <typename RangeT> |
5159 | class SubIOpGenericAdaptor : public detail::SubIOpGenericAdaptorBase { |
5160 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
5161 | using Base = detail::SubIOpGenericAdaptorBase; |
5162 | public: |
5163 | SubIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
5164 | |
5165 | SubIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : SubIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
5166 | |
5167 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
5168 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
5169 | } |
5170 | |
5171 | RangeT getODSOperands(unsigned index) { |
5172 | auto valueRange = getODSOperandIndexAndLength(index); |
5173 | return {std::next(odsOperands.begin(), valueRange.first), |
5174 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
5175 | } |
5176 | |
5177 | ValueT getLhs() { |
5178 | return (*getODSOperands(0).begin()); |
5179 | } |
5180 | |
5181 | ValueT getRhs() { |
5182 | return (*getODSOperands(1).begin()); |
5183 | } |
5184 | |
5185 | RangeT getOperands() { |
5186 | return odsOperands; |
5187 | } |
5188 | |
5189 | private: |
5190 | RangeT odsOperands; |
5191 | }; |
5192 | class SubIOpAdaptor : public SubIOpGenericAdaptor<::mlir::ValueRange> { |
5193 | public: |
5194 | using SubIOpGenericAdaptor::SubIOpGenericAdaptor; |
5195 | SubIOpAdaptor(SubIOp op); |
5196 | |
5197 | ::mlir::LogicalResult verify(::mlir::Location loc); |
5198 | }; |
5199 | class SubIOp : public ::mlir::Op<SubIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
5200 | public: |
5201 | using Op::Op; |
5202 | using Op::print; |
5203 | using Adaptor = SubIOpAdaptor; |
5204 | template <typename RangeT> |
5205 | using GenericAdaptor = SubIOpGenericAdaptor<RangeT>; |
5206 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
5207 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
5208 | return {}; |
5209 | } |
5210 | |
5211 | static constexpr ::llvm::StringLiteral getOperationName() { |
5212 | return ::llvm::StringLiteral("arith.subi"); |
5213 | } |
5214 | |
5215 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
5216 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
5217 | ::mlir::Value getLhs(); |
5218 | ::mlir::Value getRhs(); |
5219 | ::mlir::MutableOperandRange getLhsMutable(); |
5220 | ::mlir::MutableOperandRange getRhsMutable(); |
5221 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
5222 | ::mlir::Operation::result_range getODSResults(unsigned index); |
5223 | ::mlir::Value getResult(); |
5224 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
5225 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
5226 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
5227 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
5228 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
5229 | ::mlir::LogicalResult verifyInvariantsImpl(); |
5230 | ::mlir::LogicalResult verifyInvariants(); |
5231 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
5232 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
5233 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
5234 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
5235 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
5236 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
5237 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
5238 | public: |
5239 | }; |
5240 | } // namespace arith |
5241 | } // namespace mlir |
5242 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::SubIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::SubIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
5243 | |
5244 | namespace mlir { |
5245 | namespace arith { |
5246 | |
5247 | //===----------------------------------------------------------------------===// |
5248 | // ::mlir::arith::TruncFOp declarations |
5249 | //===----------------------------------------------------------------------===// |
5250 | |
5251 | namespace detail { |
5252 | class TruncFOpGenericAdaptorBase { |
5253 | public: |
5254 | protected: |
5255 | ::mlir::DictionaryAttr odsAttrs; |
5256 | ::std::optional<::mlir::OperationName> odsOpName; |
5257 | ::mlir::RegionRange odsRegions; |
5258 | public: |
5259 | TruncFOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
5260 | |
5261 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
5262 | ::mlir::DictionaryAttr getAttributes(); |
5263 | }; |
5264 | } // namespace detail |
5265 | template <typename RangeT> |
5266 | class TruncFOpGenericAdaptor : public detail::TruncFOpGenericAdaptorBase { |
5267 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
5268 | using Base = detail::TruncFOpGenericAdaptorBase; |
5269 | public: |
5270 | TruncFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
5271 | |
5272 | TruncFOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : TruncFOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
5273 | |
5274 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
5275 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
5276 | } |
5277 | |
5278 | RangeT getODSOperands(unsigned index) { |
5279 | auto valueRange = getODSOperandIndexAndLength(index); |
5280 | return {std::next(odsOperands.begin(), valueRange.first), |
5281 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
5282 | } |
5283 | |
5284 | ValueT getIn() { |
5285 | return (*getODSOperands(0).begin()); |
5286 | } |
5287 | |
5288 | RangeT getOperands() { |
5289 | return odsOperands; |
5290 | } |
5291 | |
5292 | private: |
5293 | RangeT odsOperands; |
5294 | }; |
5295 | class TruncFOpAdaptor : public TruncFOpGenericAdaptor<::mlir::ValueRange> { |
5296 | public: |
5297 | using TruncFOpGenericAdaptor::TruncFOpGenericAdaptor; |
5298 | TruncFOpAdaptor(TruncFOp op); |
5299 | |
5300 | ::mlir::LogicalResult verify(::mlir::Location loc); |
5301 | }; |
5302 | class TruncFOp : public ::mlir::Op<TruncFOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
5303 | public: |
5304 | using Op::Op; |
5305 | using Op::print; |
5306 | using Adaptor = TruncFOpAdaptor; |
5307 | template <typename RangeT> |
5308 | using GenericAdaptor = TruncFOpGenericAdaptor<RangeT>; |
5309 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
5310 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
5311 | return {}; |
5312 | } |
5313 | |
5314 | static constexpr ::llvm::StringLiteral getOperationName() { |
5315 | return ::llvm::StringLiteral("arith.truncf"); |
5316 | } |
5317 | |
5318 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
5319 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
5320 | ::mlir::Value getIn(); |
5321 | ::mlir::MutableOperandRange getInMutable(); |
5322 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
5323 | ::mlir::Operation::result_range getODSResults(unsigned index); |
5324 | ::mlir::Value getOut(); |
5325 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
5326 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
5327 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
5328 | ::mlir::LogicalResult verifyInvariantsImpl(); |
5329 | ::mlir::LogicalResult verifyInvariants(); |
5330 | ::mlir::LogicalResult verify(); |
5331 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
5332 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
5333 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
5334 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
5335 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
5336 | public: |
5337 | }; |
5338 | } // namespace arith |
5339 | } // namespace mlir |
5340 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::TruncFOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::TruncFOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
5341 | |
5342 | namespace mlir { |
5343 | namespace arith { |
5344 | |
5345 | //===----------------------------------------------------------------------===// |
5346 | // ::mlir::arith::TruncIOp declarations |
5347 | //===----------------------------------------------------------------------===// |
5348 | |
5349 | namespace detail { |
5350 | class TruncIOpGenericAdaptorBase { |
5351 | public: |
5352 | protected: |
5353 | ::mlir::DictionaryAttr odsAttrs; |
5354 | ::std::optional<::mlir::OperationName> odsOpName; |
5355 | ::mlir::RegionRange odsRegions; |
5356 | public: |
5357 | TruncIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
5358 | |
5359 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
5360 | ::mlir::DictionaryAttr getAttributes(); |
5361 | }; |
5362 | } // namespace detail |
5363 | template <typename RangeT> |
5364 | class TruncIOpGenericAdaptor : public detail::TruncIOpGenericAdaptorBase { |
5365 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
5366 | using Base = detail::TruncIOpGenericAdaptorBase; |
5367 | public: |
5368 | TruncIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
5369 | |
5370 | TruncIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : TruncIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
5371 | |
5372 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
5373 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
5374 | } |
5375 | |
5376 | RangeT getODSOperands(unsigned index) { |
5377 | auto valueRange = getODSOperandIndexAndLength(index); |
5378 | return {std::next(odsOperands.begin(), valueRange.first), |
5379 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
5380 | } |
5381 | |
5382 | ValueT getIn() { |
5383 | return (*getODSOperands(0).begin()); |
5384 | } |
5385 | |
5386 | RangeT getOperands() { |
5387 | return odsOperands; |
5388 | } |
5389 | |
5390 | private: |
5391 | RangeT odsOperands; |
5392 | }; |
5393 | class TruncIOpAdaptor : public TruncIOpGenericAdaptor<::mlir::ValueRange> { |
5394 | public: |
5395 | using TruncIOpGenericAdaptor::TruncIOpGenericAdaptor; |
5396 | TruncIOpAdaptor(TruncIOp op); |
5397 | |
5398 | ::mlir::LogicalResult verify(::mlir::Location loc); |
5399 | }; |
5400 | class TruncIOp : public ::mlir::Op<TruncIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::InferIntRangeInterface::Trait, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
5401 | public: |
5402 | using Op::Op; |
5403 | using Op::print; |
5404 | using Adaptor = TruncIOpAdaptor; |
5405 | template <typename RangeT> |
5406 | using GenericAdaptor = TruncIOpGenericAdaptor<RangeT>; |
5407 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
5408 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
5409 | return {}; |
5410 | } |
5411 | |
5412 | static constexpr ::llvm::StringLiteral getOperationName() { |
5413 | return ::llvm::StringLiteral("arith.trunci"); |
5414 | } |
5415 | |
5416 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
5417 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
5418 | ::mlir::Value getIn(); |
5419 | ::mlir::MutableOperandRange getInMutable(); |
5420 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
5421 | ::mlir::Operation::result_range getODSResults(unsigned index); |
5422 | ::mlir::Value getOut(); |
5423 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
5424 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
5425 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
5426 | ::mlir::LogicalResult verifyInvariantsImpl(); |
5427 | ::mlir::LogicalResult verifyInvariants(); |
5428 | ::mlir::LogicalResult verify(); |
5429 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
5430 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
5431 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
5432 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
5433 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
5434 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
5435 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
5436 | public: |
5437 | }; |
5438 | } // namespace arith |
5439 | } // namespace mlir |
5440 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::TruncIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::TruncIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
5441 | |
5442 | namespace mlir { |
5443 | namespace arith { |
5444 | |
5445 | //===----------------------------------------------------------------------===// |
5446 | // ::mlir::arith::UIToFPOp declarations |
5447 | //===----------------------------------------------------------------------===// |
5448 | |
5449 | namespace detail { |
5450 | class UIToFPOpGenericAdaptorBase { |
5451 | public: |
5452 | protected: |
5453 | ::mlir::DictionaryAttr odsAttrs; |
5454 | ::std::optional<::mlir::OperationName> odsOpName; |
5455 | ::mlir::RegionRange odsRegions; |
5456 | public: |
5457 | UIToFPOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
5458 | |
5459 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
5460 | ::mlir::DictionaryAttr getAttributes(); |
5461 | }; |
5462 | } // namespace detail |
5463 | template <typename RangeT> |
5464 | class UIToFPOpGenericAdaptor : public detail::UIToFPOpGenericAdaptorBase { |
5465 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
5466 | using Base = detail::UIToFPOpGenericAdaptorBase; |
5467 | public: |
5468 | UIToFPOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
5469 | |
5470 | UIToFPOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : UIToFPOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
5471 | |
5472 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
5473 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
5474 | } |
5475 | |
5476 | RangeT getODSOperands(unsigned index) { |
5477 | auto valueRange = getODSOperandIndexAndLength(index); |
5478 | return {std::next(odsOperands.begin(), valueRange.first), |
5479 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
5480 | } |
5481 | |
5482 | ValueT getIn() { |
5483 | return (*getODSOperands(0).begin()); |
5484 | } |
5485 | |
5486 | RangeT getOperands() { |
5487 | return odsOperands; |
5488 | } |
5489 | |
5490 | private: |
5491 | RangeT odsOperands; |
5492 | }; |
5493 | class UIToFPOpAdaptor : public UIToFPOpGenericAdaptor<::mlir::ValueRange> { |
5494 | public: |
5495 | using UIToFPOpGenericAdaptor::UIToFPOpGenericAdaptor; |
5496 | UIToFPOpAdaptor(UIToFPOp op); |
5497 | |
5498 | ::mlir::LogicalResult verify(::mlir::Location loc); |
5499 | }; |
5500 | class UIToFPOp : public ::mlir::Op<UIToFPOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::OneOperand, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultShape, ::mlir::CastOpInterface::Trait, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable> { |
5501 | public: |
5502 | using Op::Op; |
5503 | using Op::print; |
5504 | using Adaptor = UIToFPOpAdaptor; |
5505 | template <typename RangeT> |
5506 | using GenericAdaptor = UIToFPOpGenericAdaptor<RangeT>; |
5507 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
5508 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
5509 | return {}; |
5510 | } |
5511 | |
5512 | static constexpr ::llvm::StringLiteral getOperationName() { |
5513 | return ::llvm::StringLiteral("arith.uitofp"); |
5514 | } |
5515 | |
5516 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
5517 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
5518 | ::mlir::Value getIn(); |
5519 | ::mlir::MutableOperandRange getInMutable(); |
5520 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
5521 | ::mlir::Operation::result_range getODSResults(unsigned index); |
5522 | ::mlir::Value getOut(); |
5523 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type out, ::mlir::Value in); |
5524 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value in); |
5525 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
5526 | ::mlir::LogicalResult verifyInvariantsImpl(); |
5527 | ::mlir::LogicalResult verifyInvariants(); |
5528 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
5529 | static bool areCastCompatible(::mlir::TypeRange inputs, ::mlir::TypeRange outputs); |
5530 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
5531 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
5532 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
5533 | public: |
5534 | }; |
5535 | } // namespace arith |
5536 | } // namespace mlir |
5537 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::UIToFPOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::UIToFPOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
5538 | |
5539 | namespace mlir { |
5540 | namespace arith { |
5541 | |
5542 | //===----------------------------------------------------------------------===// |
5543 | // ::mlir::arith::XOrIOp declarations |
5544 | //===----------------------------------------------------------------------===// |
5545 | |
5546 | namespace detail { |
5547 | class XOrIOpGenericAdaptorBase { |
5548 | public: |
5549 | protected: |
5550 | ::mlir::DictionaryAttr odsAttrs; |
5551 | ::std::optional<::mlir::OperationName> odsOpName; |
5552 | ::mlir::RegionRange odsRegions; |
5553 | public: |
5554 | XOrIOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
5555 | |
5556 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
5557 | ::mlir::DictionaryAttr getAttributes(); |
5558 | }; |
5559 | } // namespace detail |
5560 | template <typename RangeT> |
5561 | class XOrIOpGenericAdaptor : public detail::XOrIOpGenericAdaptorBase { |
5562 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
5563 | using Base = detail::XOrIOpGenericAdaptorBase; |
5564 | public: |
5565 | XOrIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
5566 | |
5567 | XOrIOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : XOrIOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
5568 | |
5569 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
5570 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
5571 | } |
5572 | |
5573 | RangeT getODSOperands(unsigned index) { |
5574 | auto valueRange = getODSOperandIndexAndLength(index); |
5575 | return {std::next(odsOperands.begin(), valueRange.first), |
5576 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
5577 | } |
5578 | |
5579 | ValueT getLhs() { |
5580 | return (*getODSOperands(0).begin()); |
5581 | } |
5582 | |
5583 | ValueT getRhs() { |
5584 | return (*getODSOperands(1).begin()); |
5585 | } |
5586 | |
5587 | RangeT getOperands() { |
5588 | return odsOperands; |
5589 | } |
5590 | |
5591 | private: |
5592 | RangeT odsOperands; |
5593 | }; |
5594 | class XOrIOpAdaptor : public XOrIOpGenericAdaptor<::mlir::ValueRange> { |
5595 | public: |
5596 | using XOrIOpGenericAdaptor::XOrIOpGenericAdaptor; |
5597 | XOrIOpAdaptor(XOrIOp op); |
5598 | |
5599 | ::mlir::LogicalResult verify(::mlir::Location loc); |
5600 | }; |
5601 | class XOrIOp : public ::mlir::Op<XOrIOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<2>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::OpTrait::IsCommutative, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::SameOperandsAndResultType, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::InferTypeOpInterface::Trait> { |
5602 | public: |
5603 | using Op::Op; |
5604 | using Op::print; |
5605 | using Adaptor = XOrIOpAdaptor; |
5606 | template <typename RangeT> |
5607 | using GenericAdaptor = XOrIOpGenericAdaptor<RangeT>; |
5608 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
5609 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
5610 | return {}; |
5611 | } |
5612 | |
5613 | static constexpr ::llvm::StringLiteral getOperationName() { |
5614 | return ::llvm::StringLiteral("arith.xori"); |
5615 | } |
5616 | |
5617 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
5618 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
5619 | ::mlir::Value getLhs(); |
5620 | ::mlir::Value getRhs(); |
5621 | ::mlir::MutableOperandRange getLhsMutable(); |
5622 | ::mlir::MutableOperandRange getRhsMutable(); |
5623 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
5624 | ::mlir::Operation::result_range getODSResults(unsigned index); |
5625 | ::mlir::Value getResult(); |
5626 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value lhs, ::mlir::Value rhs); |
5627 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value lhs, ::mlir::Value rhs); |
5628 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value lhs, ::mlir::Value rhs); |
5629 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
5630 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
5631 | ::mlir::LogicalResult verifyInvariantsImpl(); |
5632 | ::mlir::LogicalResult verifyInvariants(); |
5633 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
5634 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
5635 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
5636 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
5637 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
5638 | void print(::mlir::OpAsmPrinter &_odsPrinter); |
5639 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
5640 | public: |
5641 | }; |
5642 | } // namespace arith |
5643 | } // namespace mlir |
5644 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::XOrIOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::XOrIOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
5645 | |
5646 | namespace mlir { |
5647 | namespace arith { |
5648 | |
5649 | //===----------------------------------------------------------------------===// |
5650 | // ::mlir::arith::SelectOp declarations |
5651 | //===----------------------------------------------------------------------===// |
5652 | |
5653 | namespace detail { |
5654 | class SelectOpGenericAdaptorBase { |
5655 | public: |
5656 | protected: |
5657 | ::mlir::DictionaryAttr odsAttrs; |
5658 | ::std::optional<::mlir::OperationName> odsOpName; |
5659 | ::mlir::RegionRange odsRegions; |
5660 | public: |
5661 | SelectOpGenericAdaptorBase(::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}); |
5662 | |
5663 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index, unsigned odsOperandsSize); |
5664 | ::mlir::DictionaryAttr getAttributes(); |
5665 | }; |
5666 | } // namespace detail |
5667 | template <typename RangeT> |
5668 | class SelectOpGenericAdaptor : public detail::SelectOpGenericAdaptorBase { |
5669 | using ValueT = ::llvm::detail::ValueOfRange<RangeT>; |
5670 | using Base = detail::SelectOpGenericAdaptorBase; |
5671 | public: |
5672 | SelectOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr, const ::mlir::EmptyProperties &properties = {}, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {} |
5673 | |
5674 | SelectOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : SelectOpGenericAdaptor(values, attrs, (properties ? *properties.as<::mlir::EmptyProperties *>() : ::mlir::EmptyProperties{}), regions) {} |
5675 | |
5676 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index) { |
5677 | return Base::getODSOperandIndexAndLength(index, odsOperands.size()); |
5678 | } |
5679 | |
5680 | RangeT getODSOperands(unsigned index) { |
5681 | auto valueRange = getODSOperandIndexAndLength(index); |
5682 | return {std::next(odsOperands.begin(), valueRange.first), |
5683 | std::next(odsOperands.begin(), valueRange.first + valueRange.second)}; |
5684 | } |
5685 | |
5686 | ValueT getCondition() { |
5687 | return (*getODSOperands(0).begin()); |
5688 | } |
5689 | |
5690 | ValueT getTrueValue() { |
5691 | return (*getODSOperands(1).begin()); |
5692 | } |
5693 | |
5694 | ValueT getFalseValue() { |
5695 | return (*getODSOperands(2).begin()); |
5696 | } |
5697 | |
5698 | RangeT getOperands() { |
5699 | return odsOperands; |
5700 | } |
5701 | |
5702 | private: |
5703 | RangeT odsOperands; |
5704 | }; |
5705 | class SelectOpAdaptor : public SelectOpGenericAdaptor<::mlir::ValueRange> { |
5706 | public: |
5707 | using SelectOpGenericAdaptor::SelectOpGenericAdaptor; |
5708 | SelectOpAdaptor(SelectOp op); |
5709 | |
5710 | ::mlir::LogicalResult verify(::mlir::Location loc); |
5711 | }; |
5712 | class SelectOp : public ::mlir::Op<SelectOp, ::mlir::OpTrait::ZeroRegions, ::mlir::OpTrait::OneResult, ::mlir::OpTrait::OneTypedResult<::mlir::Type>::Impl, ::mlir::OpTrait::ZeroSuccessors, ::mlir::OpTrait::NOperands<3>::Impl, ::mlir::OpTrait::OpInvariants, ::mlir::ConditionallySpeculatable::Trait, ::mlir::OpTrait::AlwaysSpeculatableImplTrait, ::mlir::MemoryEffectOpInterface::Trait, ::mlir::InferIntRangeInterface::Trait, ::mlir::OpTrait::Elementwise, ::mlir::OpTrait::Scalarizable, ::mlir::OpTrait::Vectorizable, ::mlir::OpTrait::Tensorizable, ::mlir::VectorUnrollOpInterface::Trait, ::mlir::InferTypeOpInterface::Trait> { |
5713 | public: |
5714 | using Op::Op; |
5715 | using Op::print; |
5716 | using Adaptor = SelectOpAdaptor; |
5717 | template <typename RangeT> |
5718 | using GenericAdaptor = SelectOpGenericAdaptor<RangeT>; |
5719 | using FoldAdaptor = GenericAdaptor<::llvm::ArrayRef<::mlir::Attribute>>; |
5720 | static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames() { |
5721 | return {}; |
5722 | } |
5723 | |
5724 | static constexpr ::llvm::StringLiteral getOperationName() { |
5725 | return ::llvm::StringLiteral("arith.select"); |
5726 | } |
5727 | |
5728 | std::pair<unsigned, unsigned> getODSOperandIndexAndLength(unsigned index); |
5729 | ::mlir::Operation::operand_range getODSOperands(unsigned index); |
5730 | ::mlir::Value getCondition(); |
5731 | ::mlir::Value getTrueValue(); |
5732 | ::mlir::Value getFalseValue(); |
5733 | ::mlir::MutableOperandRange getConditionMutable(); |
5734 | ::mlir::MutableOperandRange getTrueValueMutable(); |
5735 | ::mlir::MutableOperandRange getFalseValueMutable(); |
5736 | std::pair<unsigned, unsigned> getODSResultIndexAndLength(unsigned index); |
5737 | ::mlir::Operation::result_range getODSResults(unsigned index); |
5738 | ::mlir::Value getResult(); |
5739 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type result, ::mlir::Value condition, ::mlir::Value true_value, ::mlir::Value false_value); |
5740 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Value condition, ::mlir::Value true_value, ::mlir::Value false_value); |
5741 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::Value condition, ::mlir::Value true_value, ::mlir::Value false_value); |
5742 | static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
5743 | static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); |
5744 | static ::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result); |
5745 | void print(::mlir::OpAsmPrinter &p); |
5746 | ::mlir::LogicalResult verifyInvariantsImpl(); |
5747 | ::mlir::LogicalResult verifyInvariants(); |
5748 | ::mlir::LogicalResult verify(); |
5749 | static void getCanonicalizationPatterns(::mlir::RewritePatternSet &results, ::mlir::MLIRContext *context); |
5750 | ::mlir::OpFoldResult fold(FoldAdaptor adaptor); |
5751 | static ::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type>&inferredReturnTypes); |
5752 | void inferResultRanges(::llvm::ArrayRef<::mlir::ConstantIntRanges> argRanges, ::mlir::SetIntRangeFn setResultRanges); |
5753 | void getEffects(::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<::mlir::MemoryEffects::Effect>> &effects); |
5754 | public: |
5755 | }; |
5756 | } // namespace arith |
5757 | } // namespace mlir |
5758 | MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::arith::SelectOp)namespace mlir { namespace detail { template <> class TypeIDResolver < ::mlir::arith::SelectOp> { public: static TypeID resolveTypeID () { return id; } private: static SelfOwningTypeID id; }; } } |
5759 | |
5760 | |
5761 | #endif // GET_OP_CLASSES |
5762 |
1 | //===- OpDefinition.h - Classes for defining concrete Op types --*- 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 implements helper classes for implementing the "Op" types. This | |||
10 | // includes the Op type, which is the base class for Op class definitions, | |||
11 | // as well as number of traits in the OpTrait namespace that provide a | |||
12 | // declarative way to specify properties of Ops. | |||
13 | // | |||
14 | // The purpose of these types are to allow light-weight implementation of | |||
15 | // concrete ops (like DimOp) with very little boilerplate. | |||
16 | // | |||
17 | //===----------------------------------------------------------------------===// | |||
18 | ||||
19 | #ifndef MLIR_IR_OPDEFINITION_H | |||
20 | #define MLIR_IR_OPDEFINITION_H | |||
21 | ||||
22 | #include "mlir/IR/Dialect.h" | |||
23 | #include "mlir/IR/Operation.h" | |||
24 | #include "llvm/Support/PointerLikeTypeTraits.h" | |||
25 | ||||
26 | #include <optional> | |||
27 | #include <type_traits> | |||
28 | ||||
29 | namespace mlir { | |||
30 | class Builder; | |||
31 | class OpBuilder; | |||
32 | ||||
33 | /// This class implements `Optional` functionality for ParseResult. We don't | |||
34 | /// directly use Optional here, because it provides an implicit conversion | |||
35 | /// to 'bool' which we want to avoid. This class is used to implement tri-state | |||
36 | /// 'parseOptional' functions that may have a failure mode when parsing that | |||
37 | /// shouldn't be attributed to "not present". | |||
38 | class OptionalParseResult { | |||
39 | public: | |||
40 | OptionalParseResult() = default; | |||
41 | OptionalParseResult(LogicalResult result) : impl(result) {} | |||
42 | OptionalParseResult(ParseResult result) : impl(result) {} | |||
43 | OptionalParseResult(const InFlightDiagnostic &) | |||
44 | : OptionalParseResult(failure()) {} | |||
45 | OptionalParseResult(std::nullopt_t) : impl(std::nullopt) {} | |||
46 | ||||
47 | /// Returns true if we contain a valid ParseResult value. | |||
48 | bool has_value() const { return impl.has_value(); } | |||
49 | ||||
50 | /// Access the internal ParseResult value. | |||
51 | ParseResult value() const { return *impl; } | |||
52 | ParseResult operator*() const { return value(); } | |||
53 | ||||
54 | private: | |||
55 | std::optional<ParseResult> impl; | |||
56 | }; | |||
57 | ||||
58 | // These functions are out-of-line utilities, which avoids them being template | |||
59 | // instantiated/duplicated. | |||
60 | namespace impl { | |||
61 | /// Insert an operation, generated by `buildTerminatorOp`, at the end of the | |||
62 | /// region's only block if it does not have a terminator already. If the region | |||
63 | /// is empty, insert a new block first. `buildTerminatorOp` should return the | |||
64 | /// terminator operation to insert. | |||
65 | void ensureRegionTerminator( | |||
66 | Region ®ion, OpBuilder &builder, Location loc, | |||
67 | function_ref<Operation *(OpBuilder &, Location)> buildTerminatorOp); | |||
68 | void ensureRegionTerminator( | |||
69 | Region ®ion, Builder &builder, Location loc, | |||
70 | function_ref<Operation *(OpBuilder &, Location)> buildTerminatorOp); | |||
71 | ||||
72 | } // namespace impl | |||
73 | ||||
74 | /// Structure used by default as a "marker" when no "Properties" are set on an | |||
75 | /// Operation. | |||
76 | struct EmptyProperties {}; | |||
77 | ||||
78 | /// Traits to detect whether an Operation defined a `Properties` type, otherwise | |||
79 | /// it'll default to `EmptyProperties`. | |||
80 | template <class Op, class = void> | |||
81 | struct PropertiesSelector { | |||
82 | using type = EmptyProperties; | |||
83 | }; | |||
84 | template <class Op> | |||
85 | struct PropertiesSelector<Op, std::void_t<typename Op::Properties>> { | |||
86 | using type = typename Op::Properties; | |||
87 | }; | |||
88 | ||||
89 | /// This is the concrete base class that holds the operation pointer and has | |||
90 | /// non-generic methods that only depend on State (to avoid having them | |||
91 | /// instantiated on template types that don't affect them. | |||
92 | /// | |||
93 | /// This also has the fallback implementations of customization hooks for when | |||
94 | /// they aren't customized. | |||
95 | class OpState { | |||
96 | public: | |||
97 | /// Ops are pointer-like, so we allow conversion to bool. | |||
98 | explicit operator bool() { return getOperation() != nullptr; } | |||
99 | ||||
100 | /// This implicitly converts to Operation*. | |||
101 | operator Operation *() const { return state; } | |||
102 | ||||
103 | /// Shortcut of `->` to access a member of Operation. | |||
104 | Operation *operator->() const { return state; } | |||
105 | ||||
106 | /// Return the operation that this refers to. | |||
107 | Operation *getOperation() { return state; } | |||
108 | ||||
109 | /// Return the context this operation belongs to. | |||
110 | MLIRContext *getContext() { return getOperation()->getContext(); } | |||
111 | ||||
112 | /// Print the operation to the given stream. | |||
113 | void print(raw_ostream &os, OpPrintingFlags flags = std::nullopt) { | |||
114 | state->print(os, flags); | |||
| ||||
115 | } | |||
116 | void print(raw_ostream &os, AsmState &asmState) { | |||
117 | state->print(os, asmState); | |||
118 | } | |||
119 | ||||
120 | /// Dump this operation. | |||
121 | void dump() { state->dump(); } | |||
122 | ||||
123 | /// The source location the operation was defined or derived from. | |||
124 | Location getLoc() { return state->getLoc(); } | |||
125 | ||||
126 | /// Return true if there are no users of any results of this operation. | |||
127 | bool use_empty() { return state->use_empty(); } | |||
128 | ||||
129 | /// Remove this operation from its parent block and delete it. | |||
130 | void erase() { state->erase(); } | |||
131 | ||||
132 | /// Emit an error with the op name prefixed, like "'dim' op " which is | |||
133 | /// convenient for verifiers. | |||
134 | InFlightDiagnostic emitOpError(const Twine &message = {}); | |||
135 | ||||
136 | /// Emit an error about fatal conditions with this operation, reporting up to | |||
137 | /// any diagnostic handlers that may be listening. | |||
138 | InFlightDiagnostic emitError(const Twine &message = {}); | |||
139 | ||||
140 | /// Emit a warning about this operation, reporting up to any diagnostic | |||
141 | /// handlers that may be listening. | |||
142 | InFlightDiagnostic emitWarning(const Twine &message = {}); | |||
143 | ||||
144 | /// Emit a remark about this operation, reporting up to any diagnostic | |||
145 | /// handlers that may be listening. | |||
146 | InFlightDiagnostic emitRemark(const Twine &message = {}); | |||
147 | ||||
148 | /// Walk the operation by calling the callback for each nested operation | |||
149 | /// (including this one), block or region, depending on the callback provided. | |||
150 | /// The order in which regions, blocks and operations the same nesting level | |||
151 | /// are visited (e.g., lexicographical or reverse lexicographical order) is | |||
152 | /// determined by 'Iterator'. The walk order for enclosing regions, blocks | |||
153 | /// and operations with respect to their nested ones is specified by 'Order' | |||
154 | /// (post-order by default). A callback on a block or operation is allowed to | |||
155 | /// erase that block or operation if either: | |||
156 | /// * the walk is in post-order, or | |||
157 | /// * the walk is in pre-order and the walk is skipped after the erasure. | |||
158 | /// See Operation::walk for more details. | |||
159 | template <WalkOrder Order = WalkOrder::PostOrder, | |||
160 | typename Iterator = ForwardIterator, typename FnT, | |||
161 | typename RetT = detail::walkResultType<FnT>> | |||
162 | std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 1, | |||
163 | RetT> | |||
164 | walk(FnT &&callback) { | |||
165 | return state->walk<Order, Iterator>(std::forward<FnT>(callback)); | |||
166 | } | |||
167 | ||||
168 | /// Generic walker with a stage aware callback. Walk the operation by calling | |||
169 | /// the callback for each nested operation (including this one) N+1 times, | |||
170 | /// where N is the number of regions attached to that operation. | |||
171 | /// | |||
172 | /// The callback method can take any of the following forms: | |||
173 | /// void(Operation *, const WalkStage &) : Walk all operation opaquely | |||
174 | /// * op.walk([](Operation *nestedOp, const WalkStage &stage) { ...}); | |||
175 | /// void(OpT, const WalkStage &) : Walk all operations of the given derived | |||
176 | /// type. | |||
177 | /// * op.walk([](ReturnOp returnOp, const WalkStage &stage) { ...}); | |||
178 | /// WalkResult(Operation*|OpT, const WalkStage &stage) : Walk operations, | |||
179 | /// but allow for interruption/skipping. | |||
180 | /// * op.walk([](... op, const WalkStage &stage) { | |||
181 | /// // Skip the walk of this op based on some invariant. | |||
182 | /// if (some_invariant) | |||
183 | /// return WalkResult::skip(); | |||
184 | /// // Interrupt, i.e cancel, the walk based on some invariant. | |||
185 | /// if (another_invariant) | |||
186 | /// return WalkResult::interrupt(); | |||
187 | /// return WalkResult::advance(); | |||
188 | /// }); | |||
189 | template <typename FnT, typename RetT = detail::walkResultType<FnT>> | |||
190 | std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 2, | |||
191 | RetT> | |||
192 | walk(FnT &&callback) { | |||
193 | return state->walk(std::forward<FnT>(callback)); | |||
194 | } | |||
195 | ||||
196 | // These are default implementations of customization hooks. | |||
197 | public: | |||
198 | /// This hook returns any canonicalization pattern rewrites that the operation | |||
199 | /// supports, for use by the canonicalization pass. | |||
200 | static void getCanonicalizationPatterns(RewritePatternSet &results, | |||
201 | MLIRContext *context) {} | |||
202 | ||||
203 | /// This hook populates any unset default attrs. | |||
204 | static void populateDefaultAttrs(const OperationName &, NamedAttrList &) {} | |||
205 | ||||
206 | protected: | |||
207 | /// If the concrete type didn't implement a custom verifier hook, just fall | |||
208 | /// back to this one which accepts everything. | |||
209 | LogicalResult verify() { return success(); } | |||
210 | LogicalResult verifyRegions() { return success(); } | |||
211 | ||||
212 | /// Parse the custom form of an operation. Unless overridden, this method will | |||
213 | /// first try to get an operation parser from the op's dialect. Otherwise the | |||
214 | /// custom assembly form of an op is always rejected. Op implementations | |||
215 | /// should implement this to return failure. On success, they should fill in | |||
216 | /// result with the fields to use. | |||
217 | static ParseResult parse(OpAsmParser &parser, OperationState &result); | |||
218 | ||||
219 | /// Print the operation. Unless overridden, this method will first try to get | |||
220 | /// an operation printer from the dialect. Otherwise, it prints the operation | |||
221 | /// in generic form. | |||
222 | static void print(Operation *op, OpAsmPrinter &p, StringRef defaultDialect); | |||
223 | ||||
224 | /// Parse properties as a Attribute. | |||
225 | static ParseResult genericParseProperties(OpAsmParser &parser, | |||
226 | Attribute &result); | |||
227 | ||||
228 | /// Print the properties as a Attribute. | |||
229 | static void genericPrintProperties(OpAsmPrinter &p, Attribute properties); | |||
230 | ||||
231 | /// Print an operation name, eliding the dialect prefix if necessary. | |||
232 | static void printOpName(Operation *op, OpAsmPrinter &p, | |||
233 | StringRef defaultDialect); | |||
234 | ||||
235 | /// Mutability management is handled by the OpWrapper/OpConstWrapper classes, | |||
236 | /// so we can cast it away here. | |||
237 | explicit OpState(Operation *state) : state(state) {} | |||
238 | ||||
239 | /// For all op which don't have properties, we keep a single instance of | |||
240 | /// `EmptyProperties` to be used where a reference to a properties is needed: | |||
241 | /// this allow to bind a pointer to the reference without triggering UB. | |||
242 | static EmptyProperties &getEmptyProperties() { | |||
243 | static EmptyProperties emptyProperties; | |||
244 | return emptyProperties; | |||
245 | } | |||
246 | ||||
247 | private: | |||
248 | Operation *state; | |||
249 | ||||
250 | /// Allow access to internal hook implementation methods. | |||
251 | friend RegisteredOperationName; | |||
252 | }; | |||
253 | ||||
254 | // Allow comparing operators. | |||
255 | inline bool operator==(OpState lhs, OpState rhs) { | |||
256 | return lhs.getOperation() == rhs.getOperation(); | |||
257 | } | |||
258 | inline bool operator!=(OpState lhs, OpState rhs) { | |||
259 | return lhs.getOperation() != rhs.getOperation(); | |||
260 | } | |||
261 | ||||
262 | raw_ostream &operator<<(raw_ostream &os, OpFoldResult ofr); | |||
263 | ||||
264 | /// This class represents a single result from folding an operation. | |||
265 | class OpFoldResult : public PointerUnion<Attribute, Value> { | |||
266 | using PointerUnion<Attribute, Value>::PointerUnion; | |||
267 | ||||
268 | public: | |||
269 | void dump() const { llvm::errs() << *this << "\n"; } | |||
270 | }; | |||
271 | ||||
272 | /// Allow printing to a stream. | |||
273 | inline raw_ostream &operator<<(raw_ostream &os, OpFoldResult ofr) { | |||
274 | if (Value value = ofr.dyn_cast<Value>()) | |||
275 | value.print(os); | |||
276 | else | |||
277 | ofr.dyn_cast<Attribute>().print(os); | |||
278 | return os; | |||
279 | } | |||
280 | ||||
281 | /// Allow printing to a stream. | |||
282 | inline raw_ostream &operator<<(raw_ostream &os, OpState op) { | |||
283 | op.print(os, OpPrintingFlags().useLocalScope()); | |||
284 | return os; | |||
285 | } | |||
286 | ||||
287 | //===----------------------------------------------------------------------===// | |||
288 | // Operation Trait Types | |||
289 | //===----------------------------------------------------------------------===// | |||
290 | ||||
291 | namespace OpTrait { | |||
292 | ||||
293 | // These functions are out-of-line implementations of the methods in the | |||
294 | // corresponding trait classes. This avoids them being template | |||
295 | // instantiated/duplicated. | |||
296 | namespace impl { | |||
297 | OpFoldResult foldIdempotent(Operation *op); | |||
298 | OpFoldResult foldInvolution(Operation *op); | |||
299 | LogicalResult verifyZeroOperands(Operation *op); | |||
300 | LogicalResult verifyOneOperand(Operation *op); | |||
301 | LogicalResult verifyNOperands(Operation *op, unsigned numOperands); | |||
302 | LogicalResult verifyIsIdempotent(Operation *op); | |||
303 | LogicalResult verifyIsInvolution(Operation *op); | |||
304 | LogicalResult verifyAtLeastNOperands(Operation *op, unsigned numOperands); | |||
305 | LogicalResult verifyOperandsAreFloatLike(Operation *op); | |||
306 | LogicalResult verifyOperandsAreSignlessIntegerLike(Operation *op); | |||
307 | LogicalResult verifySameTypeOperands(Operation *op); | |||
308 | LogicalResult verifyZeroRegions(Operation *op); | |||
309 | LogicalResult verifyOneRegion(Operation *op); | |||
310 | LogicalResult verifyNRegions(Operation *op, unsigned numRegions); | |||
311 | LogicalResult verifyAtLeastNRegions(Operation *op, unsigned numRegions); | |||
312 | LogicalResult verifyZeroResults(Operation *op); | |||
313 | LogicalResult verifyOneResult(Operation *op); | |||
314 | LogicalResult verifyNResults(Operation *op, unsigned numOperands); | |||
315 | LogicalResult verifyAtLeastNResults(Operation *op, unsigned numOperands); | |||
316 | LogicalResult verifySameOperandsShape(Operation *op); | |||
317 | LogicalResult verifySameOperandsAndResultShape(Operation *op); | |||
318 | LogicalResult verifySameOperandsElementType(Operation *op); | |||
319 | LogicalResult verifySameOperandsAndResultElementType(Operation *op); | |||
320 | LogicalResult verifySameOperandsAndResultType(Operation *op); | |||
321 | LogicalResult verifyResultsAreBoolLike(Operation *op); | |||
322 | LogicalResult verifyResultsAreFloatLike(Operation *op); | |||
323 | LogicalResult verifyResultsAreSignlessIntegerLike(Operation *op); | |||
324 | LogicalResult verifyIsTerminator(Operation *op); | |||
325 | LogicalResult verifyZeroSuccessors(Operation *op); | |||
326 | LogicalResult verifyOneSuccessor(Operation *op); | |||
327 | LogicalResult verifyNSuccessors(Operation *op, unsigned numSuccessors); | |||
328 | LogicalResult verifyAtLeastNSuccessors(Operation *op, unsigned numSuccessors); | |||
329 | LogicalResult verifyValueSizeAttr(Operation *op, StringRef attrName, | |||
330 | StringRef valueGroupName, | |||
331 | size_t expectedCount); | |||
332 | LogicalResult verifyOperandSizeAttr(Operation *op, StringRef sizeAttrName); | |||
333 | LogicalResult verifyResultSizeAttr(Operation *op, StringRef sizeAttrName); | |||
334 | LogicalResult verifyNoRegionArguments(Operation *op); | |||
335 | LogicalResult verifyElementwise(Operation *op); | |||
336 | LogicalResult verifyIsIsolatedFromAbove(Operation *op); | |||
337 | } // namespace impl | |||
338 | ||||
339 | /// Helper class for implementing traits. Clients are not expected to interact | |||
340 | /// with this directly, so its members are all protected. | |||
341 | template <typename ConcreteType, template <typename> class TraitType> | |||
342 | class TraitBase { | |||
343 | protected: | |||
344 | /// Return the ultimate Operation being worked on. | |||
345 | Operation *getOperation() { | |||
346 | auto *concrete = static_cast<ConcreteType *>(this); | |||
347 | return concrete->getOperation(); | |||
348 | } | |||
349 | }; | |||
350 | ||||
351 | //===----------------------------------------------------------------------===// | |||
352 | // Operand Traits | |||
353 | ||||
354 | namespace detail { | |||
355 | /// Utility trait base that provides accessors for derived traits that have | |||
356 | /// multiple operands. | |||
357 | template <typename ConcreteType, template <typename> class TraitType> | |||
358 | struct MultiOperandTraitBase : public TraitBase<ConcreteType, TraitType> { | |||
359 | using operand_iterator = Operation::operand_iterator; | |||
360 | using operand_range = Operation::operand_range; | |||
361 | using operand_type_iterator = Operation::operand_type_iterator; | |||
362 | using operand_type_range = Operation::operand_type_range; | |||
363 | ||||
364 | /// Return the number of operands. | |||
365 | unsigned getNumOperands() { return this->getOperation()->getNumOperands(); } | |||
366 | ||||
367 | /// Return the operand at index 'i'. | |||
368 | Value getOperand(unsigned i) { return this->getOperation()->getOperand(i); } | |||
369 | ||||
370 | /// Set the operand at index 'i' to 'value'. | |||
371 | void setOperand(unsigned i, Value value) { | |||
372 | this->getOperation()->setOperand(i, value); | |||
373 | } | |||
374 | ||||
375 | /// Operand iterator access. | |||
376 | operand_iterator operand_begin() { | |||
377 | return this->getOperation()->operand_begin(); | |||
378 | } | |||
379 | operand_iterator operand_end() { return this->getOperation()->operand_end(); } | |||
380 | operand_range getOperands() { return this->getOperation()->getOperands(); } | |||
381 | ||||
382 | /// Operand type access. | |||
383 | operand_type_iterator operand_type_begin() { | |||
384 | return this->getOperation()->operand_type_begin(); | |||
385 | } | |||
386 | operand_type_iterator operand_type_end() { | |||
387 | return this->getOperation()->operand_type_end(); | |||
388 | } | |||
389 | operand_type_range getOperandTypes() { | |||
390 | return this->getOperation()->getOperandTypes(); | |||
391 | } | |||
392 | }; | |||
393 | } // namespace detail | |||
394 | ||||
395 | /// `verifyInvariantsImpl` verifies the invariants like the types, attrs, .etc. | |||
396 | /// It should be run after core traits and before any other user defined traits. | |||
397 | /// In order to run it in the correct order, wrap it with OpInvariants trait so | |||
398 | /// that tblgen will be able to put it in the right order. | |||
399 | template <typename ConcreteType> | |||
400 | class OpInvariants : public TraitBase<ConcreteType, OpInvariants> { | |||
401 | public: | |||
402 | static LogicalResult verifyTrait(Operation *op) { | |||
403 | return cast<ConcreteType>(op).verifyInvariantsImpl(); | |||
404 | } | |||
405 | }; | |||
406 | ||||
407 | /// This class provides the API for ops that are known to have no | |||
408 | /// SSA operand. | |||
409 | template <typename ConcreteType> | |||
410 | class ZeroOperands : public TraitBase<ConcreteType, ZeroOperands> { | |||
411 | public: | |||
412 | static LogicalResult verifyTrait(Operation *op) { | |||
413 | return impl::verifyZeroOperands(op); | |||
414 | } | |||
415 | ||||
416 | private: | |||
417 | // Disable these. | |||
418 | void getOperand() {} | |||
419 | void setOperand() {} | |||
420 | }; | |||
421 | ||||
422 | /// This class provides the API for ops that are known to have exactly one | |||
423 | /// SSA operand. | |||
424 | template <typename ConcreteType> | |||
425 | class OneOperand : public TraitBase<ConcreteType, OneOperand> { | |||
426 | public: | |||
427 | Value getOperand() { return this->getOperation()->getOperand(0); } | |||
428 | ||||
429 | void setOperand(Value value) { this->getOperation()->setOperand(0, value); } | |||
430 | ||||
431 | static LogicalResult verifyTrait(Operation *op) { | |||
432 | return impl::verifyOneOperand(op); | |||
433 | } | |||
434 | }; | |||
435 | ||||
436 | /// This class provides the API for ops that are known to have a specified | |||
437 | /// number of operands. This is used as a trait like this: | |||
438 | /// | |||
439 | /// class FooOp : public Op<FooOp, OpTrait::NOperands<2>::Impl> { | |||
440 | /// | |||
441 | template <unsigned N> | |||
442 | class NOperands { | |||
443 | public: | |||
444 | static_assert(N > 1, "use ZeroOperands/OneOperand for N < 2"); | |||
445 | ||||
446 | template <typename ConcreteType> | |||
447 | class Impl | |||
448 | : public detail::MultiOperandTraitBase<ConcreteType, NOperands<N>::Impl> { | |||
449 | public: | |||
450 | static LogicalResult verifyTrait(Operation *op) { | |||
451 | return impl::verifyNOperands(op, N); | |||
452 | } | |||
453 | }; | |||
454 | }; | |||
455 | ||||
456 | /// This class provides the API for ops that are known to have a at least a | |||
457 | /// specified number of operands. This is used as a trait like this: | |||
458 | /// | |||
459 | /// class FooOp : public Op<FooOp, OpTrait::AtLeastNOperands<2>::Impl> { | |||
460 | /// | |||
461 | template <unsigned N> | |||
462 | class AtLeastNOperands { | |||
463 | public: | |||
464 | template <typename ConcreteType> | |||
465 | class Impl : public detail::MultiOperandTraitBase<ConcreteType, | |||
466 | AtLeastNOperands<N>::Impl> { | |||
467 | public: | |||
468 | static LogicalResult verifyTrait(Operation *op) { | |||
469 | return impl::verifyAtLeastNOperands(op, N); | |||
470 | } | |||
471 | }; | |||
472 | }; | |||
473 | ||||
474 | /// This class provides the API for ops which have an unknown number of | |||
475 | /// SSA operands. | |||
476 | template <typename ConcreteType> | |||
477 | class VariadicOperands | |||
478 | : public detail::MultiOperandTraitBase<ConcreteType, VariadicOperands> {}; | |||
479 | ||||
480 | //===----------------------------------------------------------------------===// | |||
481 | // Region Traits | |||
482 | ||||
483 | /// This class provides verification for ops that are known to have zero | |||
484 | /// regions. | |||
485 | template <typename ConcreteType> | |||
486 | class ZeroRegions : public TraitBase<ConcreteType, ZeroRegions> { | |||
487 | public: | |||
488 | static LogicalResult verifyTrait(Operation *op) { | |||
489 | return impl::verifyZeroRegions(op); | |||
490 | } | |||
491 | }; | |||
492 | ||||
493 | namespace detail { | |||
494 | /// Utility trait base that provides accessors for derived traits that have | |||
495 | /// multiple regions. | |||
496 | template <typename ConcreteType, template <typename> class TraitType> | |||
497 | struct MultiRegionTraitBase : public TraitBase<ConcreteType, TraitType> { | |||
498 | using region_iterator = MutableArrayRef<Region>; | |||
499 | using region_range = RegionRange; | |||
500 | ||||
501 | /// Return the number of regions. | |||
502 | unsigned getNumRegions() { return this->getOperation()->getNumRegions(); } | |||
503 | ||||
504 | /// Return the region at `index`. | |||
505 | Region &getRegion(unsigned i) { return this->getOperation()->getRegion(i); } | |||
506 | ||||
507 | /// Region iterator access. | |||
508 | region_iterator region_begin() { | |||
509 | return this->getOperation()->region_begin(); | |||
510 | } | |||
511 | region_iterator region_end() { return this->getOperation()->region_end(); } | |||
512 | region_range getRegions() { return this->getOperation()->getRegions(); } | |||
513 | }; | |||
514 | } // namespace detail | |||
515 | ||||
516 | /// This class provides APIs for ops that are known to have a single region. | |||
517 | template <typename ConcreteType> | |||
518 | class OneRegion : public TraitBase<ConcreteType, OneRegion> { | |||
519 | public: | |||
520 | Region &getRegion() { return this->getOperation()->getRegion(0); } | |||
521 | ||||
522 | /// Returns a range of operations within the region of this operation. | |||
523 | auto getOps() { return getRegion().getOps(); } | |||
524 | template <typename OpT> | |||
525 | auto getOps() { | |||
526 | return getRegion().template getOps<OpT>(); | |||
527 | } | |||
528 | ||||
529 | static LogicalResult verifyTrait(Operation *op) { | |||
530 | return impl::verifyOneRegion(op); | |||
531 | } | |||
532 | }; | |||
533 | ||||
534 | /// This class provides the API for ops that are known to have a specified | |||
535 | /// number of regions. | |||
536 | template <unsigned N> | |||
537 | class NRegions { | |||
538 | public: | |||
539 | static_assert(N > 1, "use ZeroRegions/OneRegion for N < 2"); | |||
540 | ||||
541 | template <typename ConcreteType> | |||
542 | class Impl | |||
543 | : public detail::MultiRegionTraitBase<ConcreteType, NRegions<N>::Impl> { | |||
544 | public: | |||
545 | static LogicalResult verifyTrait(Operation *op) { | |||
546 | return impl::verifyNRegions(op, N); | |||
547 | } | |||
548 | }; | |||
549 | }; | |||
550 | ||||
551 | /// This class provides APIs for ops that are known to have at least a specified | |||
552 | /// number of regions. | |||
553 | template <unsigned N> | |||
554 | class AtLeastNRegions { | |||
555 | public: | |||
556 | template <typename ConcreteType> | |||
557 | class Impl : public detail::MultiRegionTraitBase<ConcreteType, | |||
558 | AtLeastNRegions<N>::Impl> { | |||
559 | public: | |||
560 | static LogicalResult verifyTrait(Operation *op) { | |||
561 | return impl::verifyAtLeastNRegions(op, N); | |||
562 | } | |||
563 | }; | |||
564 | }; | |||
565 | ||||
566 | /// This class provides the API for ops which have an unknown number of | |||
567 | /// regions. | |||
568 | template <typename ConcreteType> | |||
569 | class VariadicRegions | |||
570 | : public detail::MultiRegionTraitBase<ConcreteType, VariadicRegions> {}; | |||
571 | ||||
572 | //===----------------------------------------------------------------------===// | |||
573 | // Result Traits | |||
574 | ||||
575 | /// This class provides return value APIs for ops that are known to have | |||
576 | /// zero results. | |||
577 | template <typename ConcreteType> | |||
578 | class ZeroResults : public TraitBase<ConcreteType, ZeroResults> { | |||
579 | public: | |||
580 | static LogicalResult verifyTrait(Operation *op) { | |||
581 | return impl::verifyZeroResults(op); | |||
582 | } | |||
583 | }; | |||
584 | ||||
585 | namespace detail { | |||
586 | /// Utility trait base that provides accessors for derived traits that have | |||
587 | /// multiple results. | |||
588 | template <typename ConcreteType, template <typename> class TraitType> | |||
589 | struct MultiResultTraitBase : public TraitBase<ConcreteType, TraitType> { | |||
590 | using result_iterator = Operation::result_iterator; | |||
591 | using result_range = Operation::result_range; | |||
592 | using result_type_iterator = Operation::result_type_iterator; | |||
593 | using result_type_range = Operation::result_type_range; | |||
594 | ||||
595 | /// Return the number of results. | |||
596 | unsigned getNumResults() { return this->getOperation()->getNumResults(); } | |||
597 | ||||
598 | /// Return the result at index 'i'. | |||
599 | Value getResult(unsigned i) { return this->getOperation()->getResult(i); } | |||
600 | ||||
601 | /// Replace all uses of results of this operation with the provided 'values'. | |||
602 | /// 'values' may correspond to an existing operation, or a range of 'Value'. | |||
603 | template <typename ValuesT> | |||
604 | void replaceAllUsesWith(ValuesT &&values) { | |||
605 | this->getOperation()->replaceAllUsesWith(std::forward<ValuesT>(values)); | |||
606 | } | |||
607 | ||||
608 | /// Return the type of the `i`-th result. | |||
609 | Type getType(unsigned i) { return getResult(i).getType(); } | |||
610 | ||||
611 | /// Result iterator access. | |||
612 | result_iterator result_begin() { | |||
613 | return this->getOperation()->result_begin(); | |||
614 | } | |||
615 | result_iterator result_end() { return this->getOperation()->result_end(); } | |||
616 | result_range getResults() { return this->getOperation()->getResults(); } | |||
617 | ||||
618 | /// Result type access. | |||
619 | result_type_iterator result_type_begin() { | |||
620 | return this->getOperation()->result_type_begin(); | |||
621 | } | |||
622 | result_type_iterator result_type_end() { | |||
623 | return this->getOperation()->result_type_end(); | |||
624 | } | |||
625 | result_type_range getResultTypes() { | |||
626 | return this->getOperation()->getResultTypes(); | |||
627 | } | |||
628 | }; | |||
629 | } // namespace detail | |||
630 | ||||
631 | /// This class provides return value APIs for ops that are known to have a | |||
632 | /// single result. ResultType is the concrete type returned by getType(). | |||
633 | template <typename ConcreteType> | |||
634 | class OneResult : public TraitBase<ConcreteType, OneResult> { | |||
635 | public: | |||
636 | /// Replace all uses of 'this' value with the new value, updating anything | |||
637 | /// in the IR that uses 'this' to use the other value instead. When this | |||
638 | /// returns there are zero uses of 'this'. | |||
639 | void replaceAllUsesWith(Value newValue) { | |||
640 | this->getOperation()->getResult(0).replaceAllUsesWith(newValue); | |||
641 | } | |||
642 | ||||
643 | /// Replace all uses of 'this' value with the result of 'op'. | |||
644 | void replaceAllUsesWith(Operation *op) { | |||
645 | this->getOperation()->replaceAllUsesWith(op); | |||
646 | } | |||
647 | ||||
648 | static LogicalResult verifyTrait(Operation *op) { | |||
649 | return impl::verifyOneResult(op); | |||
650 | } | |||
651 | }; | |||
652 | ||||
653 | /// This trait is used for return value APIs for ops that are known to have a | |||
654 | /// specific type other than `Type`. This allows the "getType()" member to be | |||
655 | /// more specific for an op. This should be used in conjunction with OneResult, | |||
656 | /// and occur in the trait list before OneResult. | |||
657 | template <typename ResultType> | |||
658 | class OneTypedResult { | |||
659 | public: | |||
660 | /// This class provides return value APIs for ops that are known to have a | |||
661 | /// single result. ResultType is the concrete type returned by getType(). | |||
662 | template <typename ConcreteType> | |||
663 | class Impl | |||
664 | : public TraitBase<ConcreteType, OneTypedResult<ResultType>::Impl> { | |||
665 | public: | |||
666 | mlir::TypedValue<ResultType> getResult() { | |||
667 | return cast<mlir::TypedValue<ResultType>>( | |||
668 | this->getOperation()->getResult(0)); | |||
669 | } | |||
670 | ||||
671 | /// If the operation returns a single value, then the Op can be implicitly | |||
672 | /// converted to a Value. This yields the value of the only result. | |||
673 | operator mlir::TypedValue<ResultType>() { return getResult(); } | |||
674 | ||||
675 | ResultType getType() { return getResult().getType(); } | |||
676 | }; | |||
677 | }; | |||
678 | ||||
679 | /// This class provides the API for ops that are known to have a specified | |||
680 | /// number of results. This is used as a trait like this: | |||
681 | /// | |||
682 | /// class FooOp : public Op<FooOp, OpTrait::NResults<2>::Impl> { | |||
683 | /// | |||
684 | template <unsigned N> | |||
685 | class NResults { | |||
686 | public: | |||
687 | static_assert(N > 1, "use ZeroResults/OneResult for N < 2"); | |||
688 | ||||
689 | template <typename ConcreteType> | |||
690 | class Impl | |||
691 | : public detail::MultiResultTraitBase<ConcreteType, NResults<N>::Impl> { | |||
692 | public: | |||
693 | static LogicalResult verifyTrait(Operation *op) { | |||
694 | return impl::verifyNResults(op, N); | |||
695 | } | |||
696 | }; | |||
697 | }; | |||
698 | ||||
699 | /// This class provides the API for ops that are known to have at least a | |||
700 | /// specified number of results. This is used as a trait like this: | |||
701 | /// | |||
702 | /// class FooOp : public Op<FooOp, OpTrait::AtLeastNResults<2>::Impl> { | |||
703 | /// | |||
704 | template <unsigned N> | |||
705 | class AtLeastNResults { | |||
706 | public: | |||
707 | template <typename ConcreteType> | |||
708 | class Impl : public detail::MultiResultTraitBase<ConcreteType, | |||
709 | AtLeastNResults<N>::Impl> { | |||
710 | public: | |||
711 | static LogicalResult verifyTrait(Operation *op) { | |||
712 | return impl::verifyAtLeastNResults(op, N); | |||
713 | } | |||
714 | }; | |||
715 | }; | |||
716 | ||||
717 | /// This class provides the API for ops which have an unknown number of | |||
718 | /// results. | |||
719 | template <typename ConcreteType> | |||
720 | class VariadicResults | |||
721 | : public detail::MultiResultTraitBase<ConcreteType, VariadicResults> {}; | |||
722 | ||||
723 | //===----------------------------------------------------------------------===// | |||
724 | // Terminator Traits | |||
725 | ||||
726 | /// This class indicates that the regions associated with this op don't have | |||
727 | /// terminators. | |||
728 | template <typename ConcreteType> | |||
729 | class NoTerminator : public TraitBase<ConcreteType, NoTerminator> {}; | |||
730 | ||||
731 | /// This class provides the API for ops that are known to be terminators. | |||
732 | template <typename ConcreteType> | |||
733 | class IsTerminator : public TraitBase<ConcreteType, IsTerminator> { | |||
734 | public: | |||
735 | static LogicalResult verifyTrait(Operation *op) { | |||
736 | return impl::verifyIsTerminator(op); | |||
737 | } | |||
738 | }; | |||
739 | ||||
740 | /// This class provides verification for ops that are known to have zero | |||
741 | /// successors. | |||
742 | template <typename ConcreteType> | |||
743 | class ZeroSuccessors : public TraitBase<ConcreteType, ZeroSuccessors> { | |||
744 | public: | |||
745 | static LogicalResult verifyTrait(Operation *op) { | |||
746 | return impl::verifyZeroSuccessors(op); | |||
747 | } | |||
748 | }; | |||
749 | ||||
750 | namespace detail { | |||
751 | /// Utility trait base that provides accessors for derived traits that have | |||
752 | /// multiple successors. | |||
753 | template <typename ConcreteType, template <typename> class TraitType> | |||
754 | struct MultiSuccessorTraitBase : public TraitBase<ConcreteType, TraitType> { | |||
755 | using succ_iterator = Operation::succ_iterator; | |||
756 | using succ_range = SuccessorRange; | |||
757 | ||||
758 | /// Return the number of successors. | |||
759 | unsigned getNumSuccessors() { | |||
760 | return this->getOperation()->getNumSuccessors(); | |||
761 | } | |||
762 | ||||
763 | /// Return the successor at `index`. | |||
764 | Block *getSuccessor(unsigned i) { | |||
765 | return this->getOperation()->getSuccessor(i); | |||
766 | } | |||
767 | ||||
768 | /// Set the successor at `index`. | |||
769 | void setSuccessor(Block *block, unsigned i) { | |||
770 | return this->getOperation()->setSuccessor(block, i); | |||
771 | } | |||
772 | ||||
773 | /// Successor iterator access. | |||
774 | succ_iterator succ_begin() { return this->getOperation()->succ_begin(); } | |||
775 | succ_iterator succ_end() { return this->getOperation()->succ_end(); } | |||
776 | succ_range getSuccessors() { return this->getOperation()->getSuccessors(); } | |||
777 | }; | |||
778 | } // namespace detail | |||
779 | ||||
780 | /// This class provides APIs for ops that are known to have a single successor. | |||
781 | template <typename ConcreteType> | |||
782 | class OneSuccessor : public TraitBase<ConcreteType, OneSuccessor> { | |||
783 | public: | |||
784 | Block *getSuccessor() { return this->getOperation()->getSuccessor(0); } | |||
785 | void setSuccessor(Block *succ) { | |||
786 | this->getOperation()->setSuccessor(succ, 0); | |||
787 | } | |||
788 | ||||
789 | static LogicalResult verifyTrait(Operation *op) { | |||
790 | return impl::verifyOneSuccessor(op); | |||
791 | } | |||
792 | }; | |||
793 | ||||
794 | /// This class provides the API for ops that are known to have a specified | |||
795 | /// number of successors. | |||
796 | template <unsigned N> | |||
797 | class NSuccessors { | |||
798 | public: | |||
799 | static_assert(N > 1, "use ZeroSuccessors/OneSuccessor for N < 2"); | |||
800 | ||||
801 | template <typename ConcreteType> | |||
802 | class Impl : public detail::MultiSuccessorTraitBase<ConcreteType, | |||
803 | NSuccessors<N>::Impl> { | |||
804 | public: | |||
805 | static LogicalResult verifyTrait(Operation *op) { | |||
806 | return impl::verifyNSuccessors(op, N); | |||
807 | } | |||
808 | }; | |||
809 | }; | |||
810 | ||||
811 | /// This class provides APIs for ops that are known to have at least a specified | |||
812 | /// number of successors. | |||
813 | template <unsigned N> | |||
814 | class AtLeastNSuccessors { | |||
815 | public: | |||
816 | template <typename ConcreteType> | |||
817 | class Impl | |||
818 | : public detail::MultiSuccessorTraitBase<ConcreteType, | |||
819 | AtLeastNSuccessors<N>::Impl> { | |||
820 | public: | |||
821 | static LogicalResult verifyTrait(Operation *op) { | |||
822 | return impl::verifyAtLeastNSuccessors(op, N); | |||
823 | } | |||
824 | }; | |||
825 | }; | |||
826 | ||||
827 | /// This class provides the API for ops which have an unknown number of | |||
828 | /// successors. | |||
829 | template <typename ConcreteType> | |||
830 | class VariadicSuccessors | |||
831 | : public detail::MultiSuccessorTraitBase<ConcreteType, VariadicSuccessors> { | |||
832 | }; | |||
833 | ||||
834 | //===----------------------------------------------------------------------===// | |||
835 | // SingleBlock | |||
836 | ||||
837 | /// This class provides APIs and verifiers for ops with regions having a single | |||
838 | /// block. | |||
839 | template <typename ConcreteType> | |||
840 | struct SingleBlock : public TraitBase<ConcreteType, SingleBlock> { | |||
841 | public: | |||
842 | static LogicalResult verifyTrait(Operation *op) { | |||
843 | for (unsigned i = 0, e = op->getNumRegions(); i < e; ++i) { | |||
844 | Region ®ion = op->getRegion(i); | |||
845 | ||||
846 | // Empty regions are fine. | |||
847 | if (region.empty()) | |||
848 | continue; | |||
849 | ||||
850 | // Non-empty regions must contain a single basic block. | |||
851 | if (!llvm::hasSingleElement(region)) | |||
852 | return op->emitOpError("expects region #") | |||
853 | << i << " to have 0 or 1 blocks"; | |||
854 | ||||
855 | if (!ConcreteType::template hasTrait<NoTerminator>()) { | |||
856 | Block &block = region.front(); | |||
857 | if (block.empty()) | |||
858 | return op->emitOpError() << "expects a non-empty block"; | |||
859 | } | |||
860 | } | |||
861 | return success(); | |||
862 | } | |||
863 | ||||
864 | Block *getBody(unsigned idx = 0) { | |||
865 | Region ®ion = this->getOperation()->getRegion(idx); | |||
866 | assert(!region.empty() && "unexpected empty region")(static_cast <bool> (!region.empty() && "unexpected empty region" ) ? void (0) : __assert_fail ("!region.empty() && \"unexpected empty region\"" , "mlir/include/mlir/IR/OpDefinition.h", 866, __extension__ __PRETTY_FUNCTION__ )); | |||
867 | return ®ion.front(); | |||
868 | } | |||
869 | Region &getBodyRegion(unsigned idx = 0) { | |||
870 | return this->getOperation()->getRegion(idx); | |||
871 | } | |||
872 | ||||
873 | //===------------------------------------------------------------------===// | |||
874 | // Single Region Utilities | |||
875 | //===------------------------------------------------------------------===// | |||
876 | ||||
877 | /// The following are a set of methods only enabled when the parent | |||
878 | /// operation has a single region. Each of these methods take an additional | |||
879 | /// template parameter that represents the concrete operation so that we | |||
880 | /// can use SFINAE to disable the methods for non-single region operations. | |||
881 | template <typename OpT, typename T = void> | |||
882 | using enable_if_single_region = | |||
883 | std::enable_if_t<OpT::template hasTrait<OneRegion>(), T>; | |||
884 | ||||
885 | template <typename OpT = ConcreteType> | |||
886 | enable_if_single_region<OpT, Block::iterator> begin() { | |||
887 | return getBody()->begin(); | |||
888 | } | |||
889 | template <typename OpT = ConcreteType> | |||
890 | enable_if_single_region<OpT, Block::iterator> end() { | |||
891 | return getBody()->end(); | |||
892 | } | |||
893 | template <typename OpT = ConcreteType> | |||
894 | enable_if_single_region<OpT, Operation &> front() { | |||
895 | return *begin(); | |||
896 | } | |||
897 | ||||
898 | /// Insert the operation into the back of the body. | |||
899 | template <typename OpT = ConcreteType> | |||
900 | enable_if_single_region<OpT> push_back(Operation *op) { | |||
901 | insert(Block::iterator(getBody()->end()), op); | |||
902 | } | |||
903 | ||||
904 | /// Insert the operation at the given insertion point. | |||
905 | template <typename OpT = ConcreteType> | |||
906 | enable_if_single_region<OpT> insert(Operation *insertPt, Operation *op) { | |||
907 | insert(Block::iterator(insertPt), op); | |||
908 | } | |||
909 | template <typename OpT = ConcreteType> | |||
910 | enable_if_single_region<OpT> insert(Block::iterator insertPt, Operation *op) { | |||
911 | getBody()->getOperations().insert(insertPt, op); | |||
912 | } | |||
913 | }; | |||
914 | ||||
915 | //===----------------------------------------------------------------------===// | |||
916 | // SingleBlockImplicitTerminator | |||
917 | ||||
918 | /// This class provides APIs and verifiers for ops with regions having a single | |||
919 | /// block that must terminate with `TerminatorOpType`. | |||
920 | template <typename TerminatorOpType> | |||
921 | struct SingleBlockImplicitTerminator { | |||
922 | template <typename ConcreteType> | |||
923 | class Impl : public SingleBlock<ConcreteType> { | |||
924 | private: | |||
925 | using Base = SingleBlock<ConcreteType>; | |||
926 | /// Builds a terminator operation without relying on OpBuilder APIs to avoid | |||
927 | /// cyclic header inclusion. | |||
928 | static Operation *buildTerminator(OpBuilder &builder, Location loc) { | |||
929 | OperationState state(loc, TerminatorOpType::getOperationName()); | |||
930 | TerminatorOpType::build(builder, state); | |||
931 | return Operation::create(state); | |||
932 | } | |||
933 | ||||
934 | public: | |||
935 | /// The type of the operation used as the implicit terminator type. | |||
936 | using ImplicitTerminatorOpT = TerminatorOpType; | |||
937 | ||||
938 | static LogicalResult verifyRegionTrait(Operation *op) { | |||
939 | if (failed(Base::verifyTrait(op))) | |||
940 | return failure(); | |||
941 | for (unsigned i = 0, e = op->getNumRegions(); i < e; ++i) { | |||
942 | Region ®ion = op->getRegion(i); | |||
943 | // Empty regions are fine. | |||
944 | if (region.empty()) | |||
945 | continue; | |||
946 | Operation &terminator = region.front().back(); | |||
947 | if (isa<TerminatorOpType>(terminator)) | |||
948 | continue; | |||
949 | ||||
950 | return op->emitOpError("expects regions to end with '" + | |||
951 | TerminatorOpType::getOperationName() + | |||
952 | "', found '" + | |||
953 | terminator.getName().getStringRef() + "'") | |||
954 | .attachNote() | |||
955 | << "in custom textual format, the absence of terminator implies " | |||
956 | "'" | |||
957 | << TerminatorOpType::getOperationName() << '\''; | |||
958 | } | |||
959 | ||||
960 | return success(); | |||
961 | } | |||
962 | ||||
963 | /// Ensure that the given region has the terminator required by this trait. | |||
964 | /// If OpBuilder is provided, use it to build the terminator and notify the | |||
965 | /// OpBuilder listeners accordingly. If only a Builder is provided, locally | |||
966 | /// construct an OpBuilder with no listeners; this should only be used if no | |||
967 | /// OpBuilder is available at the call site, e.g., in the parser. | |||
968 | static void ensureTerminator(Region ®ion, Builder &builder, | |||
969 | Location loc) { | |||
970 | ::mlir::impl::ensureRegionTerminator(region, builder, loc, | |||
971 | buildTerminator); | |||
972 | } | |||
973 | static void ensureTerminator(Region ®ion, OpBuilder &builder, | |||
974 | Location loc) { | |||
975 | ::mlir::impl::ensureRegionTerminator(region, builder, loc, | |||
976 | buildTerminator); | |||
977 | } | |||
978 | ||||
979 | //===------------------------------------------------------------------===// | |||
980 | // Single Region Utilities | |||
981 | //===------------------------------------------------------------------===// | |||
982 | using Base::getBody; | |||
983 | ||||
984 | template <typename OpT, typename T = void> | |||
985 | using enable_if_single_region = | |||
986 | std::enable_if_t<OpT::template hasTrait<OneRegion>(), T>; | |||
987 | ||||
988 | /// Insert the operation into the back of the body, before the terminator. | |||
989 | template <typename OpT = ConcreteType> | |||
990 | enable_if_single_region<OpT> push_back(Operation *op) { | |||
991 | insert(Block::iterator(getBody()->getTerminator()), op); | |||
992 | } | |||
993 | ||||
994 | /// Insert the operation at the given insertion point. Note: The operation | |||
995 | /// is never inserted after the terminator, even if the insertion point is | |||
996 | /// end(). | |||
997 | template <typename OpT = ConcreteType> | |||
998 | enable_if_single_region<OpT> insert(Operation *insertPt, Operation *op) { | |||
999 | insert(Block::iterator(insertPt), op); | |||
1000 | } | |||
1001 | template <typename OpT = ConcreteType> | |||
1002 | enable_if_single_region<OpT> insert(Block::iterator insertPt, | |||
1003 | Operation *op) { | |||
1004 | auto *body = getBody(); | |||
1005 | if (insertPt == body->end()) | |||
1006 | insertPt = Block::iterator(body->getTerminator()); | |||
1007 | body->getOperations().insert(insertPt, op); | |||
1008 | } | |||
1009 | }; | |||
1010 | }; | |||
1011 | ||||
1012 | /// Check is an op defines the `ImplicitTerminatorOpT` member. This is intended | |||
1013 | /// to be used with `llvm::is_detected`. | |||
1014 | template <class T> | |||
1015 | using has_implicit_terminator_t = typename T::ImplicitTerminatorOpT; | |||
1016 | ||||
1017 | /// Support to check if an operation has the SingleBlockImplicitTerminator | |||
1018 | /// trait. We can't just use `hasTrait` because this class is templated on a | |||
1019 | /// specific terminator op. | |||
1020 | template <class Op, bool hasTerminator = | |||
1021 | llvm::is_detected<has_implicit_terminator_t, Op>::value> | |||
1022 | struct hasSingleBlockImplicitTerminator { | |||
1023 | static constexpr bool value = std::is_base_of< | |||
1024 | typename OpTrait::SingleBlockImplicitTerminator< | |||
1025 | typename Op::ImplicitTerminatorOpT>::template Impl<Op>, | |||
1026 | Op>::value; | |||
1027 | }; | |||
1028 | template <class Op> | |||
1029 | struct hasSingleBlockImplicitTerminator<Op, false> { | |||
1030 | static constexpr bool value = false; | |||
1031 | }; | |||
1032 | ||||
1033 | //===----------------------------------------------------------------------===// | |||
1034 | // Misc Traits | |||
1035 | ||||
1036 | /// This class provides verification for ops that are known to have the same | |||
1037 | /// operand shape: all operands are scalars, vectors/tensors of the same | |||
1038 | /// shape. | |||
1039 | template <typename ConcreteType> | |||
1040 | class SameOperandsShape : public TraitBase<ConcreteType, SameOperandsShape> { | |||
1041 | public: | |||
1042 | static LogicalResult verifyTrait(Operation *op) { | |||
1043 | return impl::verifySameOperandsShape(op); | |||
1044 | } | |||
1045 | }; | |||
1046 | ||||
1047 | /// This class provides verification for ops that are known to have the same | |||
1048 | /// operand and result shape: both are scalars, vectors/tensors of the same | |||
1049 | /// shape. | |||
1050 | template <typename ConcreteType> | |||
1051 | class SameOperandsAndResultShape | |||
1052 | : public TraitBase<ConcreteType, SameOperandsAndResultShape> { | |||
1053 | public: | |||
1054 | static LogicalResult verifyTrait(Operation *op) { | |||
1055 | return impl::verifySameOperandsAndResultShape(op); | |||
1056 | } | |||
1057 | }; | |||
1058 | ||||
1059 | /// This class provides verification for ops that are known to have the same | |||
1060 | /// operand element type (or the type itself if it is scalar). | |||
1061 | /// | |||
1062 | template <typename ConcreteType> | |||
1063 | class SameOperandsElementType | |||
1064 | : public TraitBase<ConcreteType, SameOperandsElementType> { | |||
1065 | public: | |||
1066 | static LogicalResult verifyTrait(Operation *op) { | |||
1067 | return impl::verifySameOperandsElementType(op); | |||
1068 | } | |||
1069 | }; | |||
1070 | ||||
1071 | /// This class provides verification for ops that are known to have the same | |||
1072 | /// operand and result element type (or the type itself if it is scalar). | |||
1073 | /// | |||
1074 | template <typename ConcreteType> | |||
1075 | class SameOperandsAndResultElementType | |||
1076 | : public TraitBase<ConcreteType, SameOperandsAndResultElementType> { | |||
1077 | public: | |||
1078 | static LogicalResult verifyTrait(Operation *op) { | |||
1079 | return impl::verifySameOperandsAndResultElementType(op); | |||
1080 | } | |||
1081 | }; | |||
1082 | ||||
1083 | /// This class provides verification for ops that are known to have the same | |||
1084 | /// operand and result type. | |||
1085 | /// | |||
1086 | /// Note: this trait subsumes the SameOperandsAndResultShape and | |||
1087 | /// SameOperandsAndResultElementType traits. | |||
1088 | template <typename ConcreteType> | |||
1089 | class SameOperandsAndResultType | |||
1090 | : public TraitBase<ConcreteType, SameOperandsAndResultType> { | |||
1091 | public: | |||
1092 | static LogicalResult verifyTrait(Operation *op) { | |||
1093 | return impl::verifySameOperandsAndResultType(op); | |||
1094 | } | |||
1095 | }; | |||
1096 | ||||
1097 | /// This class verifies that any results of the specified op have a boolean | |||
1098 | /// type, a vector thereof, or a tensor thereof. | |||
1099 | template <typename ConcreteType> | |||
1100 | class ResultsAreBoolLike : public TraitBase<ConcreteType, ResultsAreBoolLike> { | |||
1101 | public: | |||
1102 | static LogicalResult verifyTrait(Operation *op) { | |||
1103 | return impl::verifyResultsAreBoolLike(op); | |||
1104 | } | |||
1105 | }; | |||
1106 | ||||
1107 | /// This class verifies that any results of the specified op have a floating | |||
1108 | /// point type, a vector thereof, or a tensor thereof. | |||
1109 | template <typename ConcreteType> | |||
1110 | class ResultsAreFloatLike | |||
1111 | : public TraitBase<ConcreteType, ResultsAreFloatLike> { | |||
1112 | public: | |||
1113 | static LogicalResult verifyTrait(Operation *op) { | |||
1114 | return impl::verifyResultsAreFloatLike(op); | |||
1115 | } | |||
1116 | }; | |||
1117 | ||||
1118 | /// This class verifies that any results of the specified op have a signless | |||
1119 | /// integer or index type, a vector thereof, or a tensor thereof. | |||
1120 | template <typename ConcreteType> | |||
1121 | class ResultsAreSignlessIntegerLike | |||
1122 | : public TraitBase<ConcreteType, ResultsAreSignlessIntegerLike> { | |||
1123 | public: | |||
1124 | static LogicalResult verifyTrait(Operation *op) { | |||
1125 | return impl::verifyResultsAreSignlessIntegerLike(op); | |||
1126 | } | |||
1127 | }; | |||
1128 | ||||
1129 | /// This class adds property that the operation is commutative. | |||
1130 | template <typename ConcreteType> | |||
1131 | class IsCommutative : public TraitBase<ConcreteType, IsCommutative> {}; | |||
1132 | ||||
1133 | /// This class adds property that the operation is an involution. | |||
1134 | /// This means a unary to unary operation "f" that satisfies f(f(x)) = x | |||
1135 | template <typename ConcreteType> | |||
1136 | class IsInvolution : public TraitBase<ConcreteType, IsInvolution> { | |||
1137 | public: | |||
1138 | static LogicalResult verifyTrait(Operation *op) { | |||
1139 | static_assert(ConcreteType::template hasTrait<OneResult>(), | |||
1140 | "expected operation to produce one result"); | |||
1141 | static_assert(ConcreteType::template hasTrait<OneOperand>(), | |||
1142 | "expected operation to take one operand"); | |||
1143 | static_assert(ConcreteType::template hasTrait<SameOperandsAndResultType>(), | |||
1144 | "expected operation to preserve type"); | |||
1145 | // Involution requires the operation to be side effect free as well | |||
1146 | // but currently this check is under a FIXME and is not actually done. | |||
1147 | return impl::verifyIsInvolution(op); | |||
1148 | } | |||
1149 | ||||
1150 | static OpFoldResult foldTrait(Operation *op, ArrayRef<Attribute> operands) { | |||
1151 | return impl::foldInvolution(op); | |||
1152 | } | |||
1153 | }; | |||
1154 | ||||
1155 | /// This class adds property that the operation is idempotent. | |||
1156 | /// This means a unary to unary operation "f" that satisfies f(f(x)) = f(x), | |||
1157 | /// or a binary operation "g" that satisfies g(x, x) = x. | |||
1158 | template <typename ConcreteType> | |||
1159 | class IsIdempotent : public TraitBase<ConcreteType, IsIdempotent> { | |||
1160 | public: | |||
1161 | static LogicalResult verifyTrait(Operation *op) { | |||
1162 | static_assert(ConcreteType::template hasTrait<OneResult>(), | |||
1163 | "expected operation to produce one result"); | |||
1164 | static_assert(ConcreteType::template hasTrait<OneOperand>() || | |||
1165 | ConcreteType::template hasTrait<NOperands<2>::Impl>(), | |||
1166 | "expected operation to take one or two operands"); | |||
1167 | static_assert(ConcreteType::template hasTrait<SameOperandsAndResultType>(), | |||
1168 | "expected operation to preserve type"); | |||
1169 | // Idempotent requires the operation to be side effect free as well | |||
1170 | // but currently this check is under a FIXME and is not actually done. | |||
1171 | return impl::verifyIsIdempotent(op); | |||
1172 | } | |||
1173 | ||||
1174 | static OpFoldResult foldTrait(Operation *op, ArrayRef<Attribute> operands) { | |||
1175 | return impl::foldIdempotent(op); | |||
1176 | } | |||
1177 | }; | |||
1178 | ||||
1179 | /// This class verifies that all operands of the specified op have a float type, | |||
1180 | /// a vector thereof, or a tensor thereof. | |||
1181 | template <typename ConcreteType> | |||
1182 | class OperandsAreFloatLike | |||
1183 | : public TraitBase<ConcreteType, OperandsAreFloatLike> { | |||
1184 | public: | |||
1185 | static LogicalResult verifyTrait(Operation *op) { | |||
1186 | return impl::verifyOperandsAreFloatLike(op); | |||
1187 | } | |||
1188 | }; | |||
1189 | ||||
1190 | /// This class verifies that all operands of the specified op have a signless | |||
1191 | /// integer or index type, a vector thereof, or a tensor thereof. | |||
1192 | template <typename ConcreteType> | |||
1193 | class OperandsAreSignlessIntegerLike | |||
1194 | : public TraitBase<ConcreteType, OperandsAreSignlessIntegerLike> { | |||
1195 | public: | |||
1196 | static LogicalResult verifyTrait(Operation *op) { | |||
1197 | return impl::verifyOperandsAreSignlessIntegerLike(op); | |||
1198 | } | |||
1199 | }; | |||
1200 | ||||
1201 | /// This class verifies that all operands of the specified op have the same | |||
1202 | /// type. | |||
1203 | template <typename ConcreteType> | |||
1204 | class SameTypeOperands : public TraitBase<ConcreteType, SameTypeOperands> { | |||
1205 | public: | |||
1206 | static LogicalResult verifyTrait(Operation *op) { | |||
1207 | return impl::verifySameTypeOperands(op); | |||
1208 | } | |||
1209 | }; | |||
1210 | ||||
1211 | /// This class provides the API for a sub-set of ops that are known to be | |||
1212 | /// constant-like. These are non-side effecting operations with one result and | |||
1213 | /// zero operands that can always be folded to a specific attribute value. | |||
1214 | template <typename ConcreteType> | |||
1215 | class ConstantLike : public TraitBase<ConcreteType, ConstantLike> { | |||
1216 | public: | |||
1217 | static LogicalResult verifyTrait(Operation *op) { | |||
1218 | static_assert(ConcreteType::template hasTrait<OneResult>(), | |||
1219 | "expected operation to produce one result"); | |||
1220 | static_assert(ConcreteType::template hasTrait<ZeroOperands>(), | |||
1221 | "expected operation to take zero operands"); | |||
1222 | // TODO: We should verify that the operation can always be folded, but this | |||
1223 | // requires that the attributes of the op already be verified. We should add | |||
1224 | // support for verifying traits "after" the operation to enable this use | |||
1225 | // case. | |||
1226 | return success(); | |||
1227 | } | |||
1228 | }; | |||
1229 | ||||
1230 | /// This class provides the API for ops that are known to be isolated from | |||
1231 | /// above. | |||
1232 | template <typename ConcreteType> | |||
1233 | class IsIsolatedFromAbove | |||
1234 | : public TraitBase<ConcreteType, IsIsolatedFromAbove> { | |||
1235 | public: | |||
1236 | static LogicalResult verifyRegionTrait(Operation *op) { | |||
1237 | return impl::verifyIsIsolatedFromAbove(op); | |||
1238 | } | |||
1239 | }; | |||
1240 | ||||
1241 | /// A trait of region holding operations that defines a new scope for polyhedral | |||
1242 | /// optimization purposes. Any SSA values of 'index' type that either dominate | |||
1243 | /// such an operation or are used at the top-level of such an operation | |||
1244 | /// automatically become valid symbols for the polyhedral scope defined by that | |||
1245 | /// operation. For more details, see `Traits.md#AffineScope`. | |||
1246 | template <typename ConcreteType> | |||
1247 | class AffineScope : public TraitBase<ConcreteType, AffineScope> { | |||
1248 | public: | |||
1249 | static LogicalResult verifyTrait(Operation *op) { | |||
1250 | static_assert(!ConcreteType::template hasTrait<ZeroRegions>(), | |||
1251 | "expected operation to have one or more regions"); | |||
1252 | return success(); | |||
1253 | } | |||
1254 | }; | |||
1255 | ||||
1256 | /// A trait of region holding operations that define a new scope for automatic | |||
1257 | /// allocations, i.e., allocations that are freed when control is transferred | |||
1258 | /// back from the operation's region. Any operations performing such allocations | |||
1259 | /// (for eg. memref.alloca) will have their allocations automatically freed at | |||
1260 | /// their closest enclosing operation with this trait. | |||
1261 | template <typename ConcreteType> | |||
1262 | class AutomaticAllocationScope | |||
1263 | : public TraitBase<ConcreteType, AutomaticAllocationScope> { | |||
1264 | public: | |||
1265 | static LogicalResult verifyTrait(Operation *op) { | |||
1266 | static_assert(!ConcreteType::template hasTrait<ZeroRegions>(), | |||
1267 | "expected operation to have one or more regions"); | |||
1268 | return success(); | |||
1269 | } | |||
1270 | }; | |||
1271 | ||||
1272 | /// This class provides a verifier for ops that are expecting their parent | |||
1273 | /// to be one of the given parent ops | |||
1274 | template <typename... ParentOpTypes> | |||
1275 | struct HasParent { | |||
1276 | template <typename ConcreteType> | |||
1277 | class Impl : public TraitBase<ConcreteType, Impl> { | |||
1278 | public: | |||
1279 | static LogicalResult verifyTrait(Operation *op) { | |||
1280 | if (llvm::isa_and_nonnull<ParentOpTypes...>(op->getParentOp())) | |||
1281 | return success(); | |||
1282 | ||||
1283 | return op->emitOpError() | |||
1284 | << "expects parent op " | |||
1285 | << (sizeof...(ParentOpTypes) != 1 ? "to be one of '" : "'") | |||
1286 | << llvm::ArrayRef({ParentOpTypes::getOperationName()...}) << "'"; | |||
1287 | } | |||
1288 | ||||
1289 | template <typename ParentOpType = | |||
1290 | std::tuple_element_t<0, std::tuple<ParentOpTypes...>>> | |||
1291 | std::enable_if_t<sizeof...(ParentOpTypes) == 1, ParentOpType> | |||
1292 | getParentOp() { | |||
1293 | Operation *parent = this->getOperation()->getParentOp(); | |||
1294 | return llvm::cast<ParentOpType>(parent); | |||
1295 | } | |||
1296 | }; | |||
1297 | }; | |||
1298 | ||||
1299 | /// A trait for operations that have an attribute specifying operand segments. | |||
1300 | /// | |||
1301 | /// Certain operations can have multiple variadic operands and their size | |||
1302 | /// relationship is not always known statically. For such cases, we need | |||
1303 | /// a per-op-instance specification to divide the operands into logical groups | |||
1304 | /// or segments. This can be modeled by attributes. The attribute will be named | |||
1305 | /// as `operand_segment_sizes`. | |||
1306 | /// | |||
1307 | /// This trait verifies the attribute for specifying operand segments has | |||
1308 | /// the correct type (1D vector) and values (non-negative), etc. | |||
1309 | template <typename ConcreteType> | |||
1310 | class AttrSizedOperandSegments | |||
1311 | : public TraitBase<ConcreteType, AttrSizedOperandSegments> { | |||
1312 | public: | |||
1313 | static StringRef getOperandSegmentSizeAttr() { | |||
1314 | return "operand_segment_sizes"; | |||
1315 | } | |||
1316 | ||||
1317 | static LogicalResult verifyTrait(Operation *op) { | |||
1318 | return ::mlir::OpTrait::impl::verifyOperandSizeAttr( | |||
1319 | op, getOperandSegmentSizeAttr()); | |||
1320 | } | |||
1321 | }; | |||
1322 | ||||
1323 | /// Similar to AttrSizedOperandSegments but used for results. | |||
1324 | template <typename ConcreteType> | |||
1325 | class AttrSizedResultSegments | |||
1326 | : public TraitBase<ConcreteType, AttrSizedResultSegments> { | |||
1327 | public: | |||
1328 | static StringRef getResultSegmentSizeAttr() { return "result_segment_sizes"; } | |||
1329 | ||||
1330 | static LogicalResult verifyTrait(Operation *op) { | |||
1331 | return ::mlir::OpTrait::impl::verifyResultSizeAttr( | |||
1332 | op, getResultSegmentSizeAttr()); | |||
1333 | } | |||
1334 | }; | |||
1335 | ||||
1336 | /// This trait provides a verifier for ops that are expecting their regions to | |||
1337 | /// not have any arguments | |||
1338 | template <typename ConcrentType> | |||
1339 | struct NoRegionArguments : public TraitBase<ConcrentType, NoRegionArguments> { | |||
1340 | static LogicalResult verifyTrait(Operation *op) { | |||
1341 | return ::mlir::OpTrait::impl::verifyNoRegionArguments(op); | |||
1342 | } | |||
1343 | }; | |||
1344 | ||||
1345 | // This trait is used to flag operations that consume or produce | |||
1346 | // values of `MemRef` type where those references can be 'normalized'. | |||
1347 | // TODO: Right now, the operands of an operation are either all normalizable, | |||
1348 | // or not. In the future, we may want to allow some of the operands to be | |||
1349 | // normalizable. | |||
1350 | template <typename ConcrentType> | |||
1351 | struct MemRefsNormalizable | |||
1352 | : public TraitBase<ConcrentType, MemRefsNormalizable> {}; | |||
1353 | ||||
1354 | /// This trait tags element-wise ops on vectors or tensors. | |||
1355 | /// | |||
1356 | /// NOTE: Not all ops that are "elementwise" in some abstract sense satisfy this | |||
1357 | /// trait. In particular, broadcasting behavior is not allowed. | |||
1358 | /// | |||
1359 | /// An `Elementwise` op must satisfy the following properties: | |||
1360 | /// | |||
1361 | /// 1. If any result is a vector/tensor then at least one operand must also be a | |||
1362 | /// vector/tensor. | |||
1363 | /// 2. If any operand is a vector/tensor then there must be at least one result | |||
1364 | /// and all results must be vectors/tensors. | |||
1365 | /// 3. All operand and result vector/tensor types must be of the same shape. The | |||
1366 | /// shape may be dynamic in which case the op's behaviour is undefined for | |||
1367 | /// non-matching shapes. | |||
1368 | /// 4. The operation must be elementwise on its vector/tensor operands and | |||
1369 | /// results. When applied to single-element vectors/tensors, the result must | |||
1370 | /// be the same per elememnt. | |||
1371 | /// | |||
1372 | /// TODO: Avoid hardcoding vector/tensor, and generalize this trait to a new | |||
1373 | /// interface `ElementwiseTypeInterface` that describes the container types for | |||
1374 | /// which the operation is elementwise. | |||
1375 | /// | |||
1376 | /// Rationale: | |||
1377 | /// - 1. and 2. guarantee a well-defined iteration space and exclude the cases | |||
1378 | /// of 0 non-scalar operands or 0 non-scalar results, which complicate a | |||
1379 | /// generic definition of the iteration space. | |||
1380 | /// - 3. guarantees that folding can be done across scalars/vectors/tensors with | |||
1381 | /// the same pattern, as otherwise lots of special handling for type | |||
1382 | /// mismatches would be needed. | |||
1383 | /// - 4. guarantees that no error handling is needed. Higher-level dialects | |||
1384 | /// should reify any needed guards or error handling code before lowering to | |||
1385 | /// an `Elementwise` op. | |||
1386 | template <typename ConcreteType> | |||
1387 | struct Elementwise : public TraitBase<ConcreteType, Elementwise> { | |||
1388 | static LogicalResult verifyTrait(Operation *op) { | |||
1389 | return ::mlir::OpTrait::impl::verifyElementwise(op); | |||
1390 | } | |||
1391 | }; | |||
1392 | ||||
1393 | /// This trait tags `Elementwise` operatons that can be systematically | |||
1394 | /// scalarized. All vector/tensor operands and results are then replaced by | |||
1395 | /// scalars of the respective element type. Semantically, this is the operation | |||
1396 | /// on a single element of the vector/tensor. | |||
1397 | /// | |||
1398 | /// Rationale: | |||
1399 | /// Allow to define the vector/tensor semantics of elementwise operations based | |||
1400 | /// on the same op's behavior on scalars. This provides a constructive procedure | |||
1401 | /// for IR transformations to, e.g., create scalar loop bodies from tensor ops. | |||
1402 | /// | |||
1403 | /// Example: | |||
1404 | /// ``` | |||
1405 | /// %tensor_select = "arith.select"(%pred_tensor, %true_val, %false_val) | |||
1406 | /// : (tensor<?xi1>, tensor<?xf32>, tensor<?xf32>) | |||
1407 | /// -> tensor<?xf32> | |||
1408 | /// ``` | |||
1409 | /// can be scalarized to | |||
1410 | /// | |||
1411 | /// ``` | |||
1412 | /// %scalar_select = "arith.select"(%pred, %true_val_scalar, %false_val_scalar) | |||
1413 | /// : (i1, f32, f32) -> f32 | |||
1414 | /// ``` | |||
1415 | template <typename ConcreteType> | |||
1416 | struct Scalarizable : public TraitBase<ConcreteType, Scalarizable> { | |||
1417 | static LogicalResult verifyTrait(Operation *op) { | |||
1418 | static_assert( | |||
1419 | ConcreteType::template hasTrait<Elementwise>(), | |||
1420 | "`Scalarizable` trait is only applicable to `Elementwise` ops."); | |||
1421 | return success(); | |||
1422 | } | |||
1423 | }; | |||
1424 | ||||
1425 | /// This trait tags `Elementwise` operatons that can be systematically | |||
1426 | /// vectorized. All scalar operands and results are then replaced by vectors | |||
1427 | /// with the respective element type. Semantically, this is the operation on | |||
1428 | /// multiple elements simultaneously. See also `Tensorizable`. | |||
1429 | /// | |||
1430 | /// Rationale: | |||
1431 | /// Provide the reverse to `Scalarizable` which, when chained together, allows | |||
1432 | /// reasoning about the relationship between the tensor and vector case. | |||
1433 | /// Additionally, it permits reasoning about promoting scalars to vectors via | |||
1434 | /// broadcasting in cases like `%select_scalar_pred` below. | |||
1435 | template <typename ConcreteType> | |||
1436 | struct Vectorizable : public TraitBase<ConcreteType, Vectorizable> { | |||
1437 | static LogicalResult verifyTrait(Operation *op) { | |||
1438 | static_assert( | |||
1439 | ConcreteType::template hasTrait<Elementwise>(), | |||
1440 | "`Vectorizable` trait is only applicable to `Elementwise` ops."); | |||
1441 | return success(); | |||
1442 | } | |||
1443 | }; | |||
1444 | ||||
1445 | /// This trait tags `Elementwise` operatons that can be systematically | |||
1446 | /// tensorized. All scalar operands and results are then replaced by tensors | |||
1447 | /// with the respective element type. Semantically, this is the operation on | |||
1448 | /// multiple elements simultaneously. See also `Vectorizable`. | |||
1449 | /// | |||
1450 | /// Rationale: | |||
1451 | /// Provide the reverse to `Scalarizable` which, when chained together, allows | |||
1452 | /// reasoning about the relationship between the tensor and vector case. | |||
1453 | /// Additionally, it permits reasoning about promoting scalars to tensors via | |||
1454 | /// broadcasting in cases like `%select_scalar_pred` below. | |||
1455 | /// | |||
1456 | /// Examples: | |||
1457 | /// ``` | |||
1458 | /// %scalar = "arith.addf"(%a, %b) : (f32, f32) -> f32 | |||
1459 | /// ``` | |||
1460 | /// can be tensorized to | |||
1461 | /// ``` | |||
1462 | /// %tensor = "arith.addf"(%a, %b) : (tensor<?xf32>, tensor<?xf32>) | |||
1463 | /// -> tensor<?xf32> | |||
1464 | /// ``` | |||
1465 | /// | |||
1466 | /// ``` | |||
1467 | /// %scalar_pred = "arith.select"(%pred, %true_val, %false_val) | |||
1468 | /// : (i1, tensor<?xf32>, tensor<?xf32>) -> tensor<?xf32> | |||
1469 | /// ``` | |||
1470 | /// can be tensorized to | |||
1471 | /// ``` | |||
1472 | /// %tensor_pred = "arith.select"(%pred, %true_val, %false_val) | |||
1473 | /// : (tensor<?xi1>, tensor<?xf32>, tensor<?xf32>) | |||
1474 | /// -> tensor<?xf32> | |||
1475 | /// ``` | |||
1476 | template <typename ConcreteType> | |||
1477 | struct Tensorizable : public TraitBase<ConcreteType, Tensorizable> { | |||
1478 | static LogicalResult verifyTrait(Operation *op) { | |||
1479 | static_assert( | |||
1480 | ConcreteType::template hasTrait<Elementwise>(), | |||
1481 | "`Tensorizable` trait is only applicable to `Elementwise` ops."); | |||
1482 | return success(); | |||
1483 | } | |||
1484 | }; | |||
1485 | ||||
1486 | /// Together, `Elementwise`, `Scalarizable`, `Vectorizable`, and `Tensorizable` | |||
1487 | /// provide an easy way for scalar operations to conveniently generalize their | |||
1488 | /// behavior to vectors/tensors, and systematize conversion between these forms. | |||
1489 | bool hasElementwiseMappableTraits(Operation *op); | |||
1490 | ||||
1491 | } // namespace OpTrait | |||
1492 | ||||
1493 | //===----------------------------------------------------------------------===// | |||
1494 | // Internal Trait Utilities | |||
1495 | //===----------------------------------------------------------------------===// | |||
1496 | ||||
1497 | namespace op_definition_impl { | |||
1498 | //===----------------------------------------------------------------------===// | |||
1499 | // Trait Existence | |||
1500 | ||||
1501 | /// Returns true if this given Trait ID matches the IDs of any of the provided | |||
1502 | /// trait types `Traits`. | |||
1503 | template <template <typename T> class... Traits> | |||
1504 | inline bool hasTrait(TypeID traitID) { | |||
1505 | TypeID traitIDs[] = {TypeID::get<Traits>()...}; | |||
1506 | for (unsigned i = 0, e = sizeof...(Traits); i != e; ++i) | |||
1507 | if (traitIDs[i] == traitID) | |||
1508 | return true; | |||
1509 | return false; | |||
1510 | } | |||
1511 | template <> | |||
1512 | inline bool hasTrait<>(TypeID traitID) { | |||
1513 | return false; | |||
1514 | } | |||
1515 | ||||
1516 | //===----------------------------------------------------------------------===// | |||
1517 | // Trait Folding | |||
1518 | ||||
1519 | /// Trait to check if T provides a 'foldTrait' method for single result | |||
1520 | /// operations. | |||
1521 | template <typename T, typename... Args> | |||
1522 | using has_single_result_fold_trait = decltype(T::foldTrait( | |||
1523 | std::declval<Operation *>(), std::declval<ArrayRef<Attribute>>())); | |||
1524 | template <typename T> | |||
1525 | using detect_has_single_result_fold_trait = | |||
1526 | llvm::is_detected<has_single_result_fold_trait, T>; | |||
1527 | /// Trait to check if T provides a general 'foldTrait' method. | |||
1528 | template <typename T, typename... Args> | |||
1529 | using has_fold_trait = | |||
1530 | decltype(T::foldTrait(std::declval<Operation *>(), | |||
1531 | std::declval<ArrayRef<Attribute>>(), | |||
1532 | std::declval<SmallVectorImpl<OpFoldResult> &>())); | |||
1533 | template <typename T> | |||
1534 | using detect_has_fold_trait = llvm::is_detected<has_fold_trait, T>; | |||
1535 | /// Trait to check if T provides any `foldTrait` method. | |||
1536 | template <typename T> | |||
1537 | using detect_has_any_fold_trait = | |||
1538 | std::disjunction<detect_has_fold_trait<T>, | |||
1539 | detect_has_single_result_fold_trait<T>>; | |||
1540 | ||||
1541 | /// Returns the result of folding a trait that implements a `foldTrait` function | |||
1542 | /// that is specialized for operations that have a single result. | |||
1543 | template <typename Trait> | |||
1544 | static std::enable_if_t<detect_has_single_result_fold_trait<Trait>::value, | |||
1545 | LogicalResult> | |||
1546 | foldTrait(Operation *op, ArrayRef<Attribute> operands, | |||
1547 | SmallVectorImpl<OpFoldResult> &results) { | |||
1548 | assert(op->hasTrait<OpTrait::OneResult>() &&(static_cast <bool> (op->hasTrait<OpTrait::OneResult >() && "expected trait on non single-result operation to implement the " "general `foldTrait` method") ? void (0) : __assert_fail ("op->hasTrait<OpTrait::OneResult>() && \"expected trait on non single-result operation to implement the \" \"general `foldTrait` method\"" , "mlir/include/mlir/IR/OpDefinition.h", 1550, __extension__ __PRETTY_FUNCTION__ )) | |||
1549 | "expected trait on non single-result operation to implement the "(static_cast <bool> (op->hasTrait<OpTrait::OneResult >() && "expected trait on non single-result operation to implement the " "general `foldTrait` method") ? void (0) : __assert_fail ("op->hasTrait<OpTrait::OneResult>() && \"expected trait on non single-result operation to implement the \" \"general `foldTrait` method\"" , "mlir/include/mlir/IR/OpDefinition.h", 1550, __extension__ __PRETTY_FUNCTION__ )) | |||
1550 | "general `foldTrait` method")(static_cast <bool> (op->hasTrait<OpTrait::OneResult >() && "expected trait on non single-result operation to implement the " "general `foldTrait` method") ? void (0) : __assert_fail ("op->hasTrait<OpTrait::OneResult>() && \"expected trait on non single-result operation to implement the \" \"general `foldTrait` method\"" , "mlir/include/mlir/IR/OpDefinition.h", 1550, __extension__ __PRETTY_FUNCTION__ )); | |||
1551 | // If a previous trait has already been folded and replaced this operation, we | |||
1552 | // fail to fold this trait. | |||
1553 | if (!results.empty()) | |||
1554 | return failure(); | |||
1555 | ||||
1556 | if (OpFoldResult result = Trait::foldTrait(op, operands)) { | |||
1557 | if (result.template dyn_cast<Value>() != op->getResult(0)) | |||
1558 | results.push_back(result); | |||
1559 | return success(); | |||
1560 | } | |||
1561 | return failure(); | |||
1562 | } | |||
1563 | /// Returns the result of folding a trait that implements a generalized | |||
1564 | /// `foldTrait` function that is supports any operation type. | |||
1565 | template <typename Trait> | |||
1566 | static std::enable_if_t<detect_has_fold_trait<Trait>::value, LogicalResult> | |||
1567 | foldTrait(Operation *op, ArrayRef<Attribute> operands, | |||
1568 | SmallVectorImpl<OpFoldResult> &results) { | |||
1569 | // If a previous trait has already been folded and replaced this operation, we | |||
1570 | // fail to fold this trait. | |||
1571 | return results.empty() ? Trait::foldTrait(op, operands, results) : failure(); | |||
1572 | } | |||
1573 | template <typename Trait> | |||
1574 | static inline std::enable_if_t<!detect_has_any_fold_trait<Trait>::value, | |||
1575 | LogicalResult> | |||
1576 | foldTrait(Operation *, ArrayRef<Attribute>, SmallVectorImpl<OpFoldResult> &) { | |||
1577 | return failure(); | |||
1578 | } | |||
1579 | ||||
1580 | /// Given a tuple type containing a set of traits, return the result of folding | |||
1581 | /// the given operation. | |||
1582 | template <typename... Ts> | |||
1583 | static LogicalResult foldTraits(Operation *op, ArrayRef<Attribute> operands, | |||
1584 | SmallVectorImpl<OpFoldResult> &results) { | |||
1585 | return success((succeeded(foldTrait<Ts>(op, operands, results)) || ...)); | |||
1586 | } | |||
1587 | ||||
1588 | //===----------------------------------------------------------------------===// | |||
1589 | // Trait Verification | |||
1590 | ||||
1591 | /// Trait to check if T provides a `verifyTrait` method. | |||
1592 | template <typename T, typename... Args> | |||
1593 | using has_verify_trait = decltype(T::verifyTrait(std::declval<Operation *>())); | |||
1594 | template <typename T> | |||
1595 | using detect_has_verify_trait = llvm::is_detected<has_verify_trait, T>; | |||
1596 | ||||
1597 | /// Trait to check if T provides a `verifyTrait` method. | |||
1598 | template <typename T, typename... Args> | |||
1599 | using has_verify_region_trait = | |||
1600 | decltype(T::verifyRegionTrait(std::declval<Operation *>())); | |||
1601 | template <typename T> | |||
1602 | using detect_has_verify_region_trait = | |||
1603 | llvm::is_detected<has_verify_region_trait, T>; | |||
1604 | ||||
1605 | /// Verify the given trait if it provides a verifier. | |||
1606 | template <typename T> | |||
1607 | std::enable_if_t<detect_has_verify_trait<T>::value, LogicalResult> | |||
1608 | verifyTrait(Operation *op) { | |||
1609 | return T::verifyTrait(op); | |||
1610 | } | |||
1611 | template <typename T> | |||
1612 | inline std::enable_if_t<!detect_has_verify_trait<T>::value, LogicalResult> | |||
1613 | verifyTrait(Operation *) { | |||
1614 | return success(); | |||
1615 | } | |||
1616 | ||||
1617 | /// Given a set of traits, return the result of verifying the given operation. | |||
1618 | template <typename... Ts> | |||
1619 | LogicalResult verifyTraits(Operation *op) { | |||
1620 | return success((succeeded(verifyTrait<Ts>(op)) && ...)); | |||
1621 | } | |||
1622 | ||||
1623 | /// Verify the given trait if it provides a region verifier. | |||
1624 | template <typename T> | |||
1625 | std::enable_if_t<detect_has_verify_region_trait<T>::value, LogicalResult> | |||
1626 | verifyRegionTrait(Operation *op) { | |||
1627 | return T::verifyRegionTrait(op); | |||
1628 | } | |||
1629 | template <typename T> | |||
1630 | inline std::enable_if_t<!detect_has_verify_region_trait<T>::value, | |||
1631 | LogicalResult> | |||
1632 | verifyRegionTrait(Operation *) { | |||
1633 | return success(); | |||
1634 | } | |||
1635 | ||||
1636 | /// Given a set of traits, return the result of verifying the regions of the | |||
1637 | /// given operation. | |||
1638 | template <typename... Ts> | |||
1639 | LogicalResult verifyRegionTraits(Operation *op) { | |||
1640 | return success((succeeded(verifyRegionTrait<Ts>(op)) && ...)); | |||
1641 | } | |||
1642 | } // namespace op_definition_impl | |||
1643 | ||||
1644 | //===----------------------------------------------------------------------===// | |||
1645 | // Operation Definition classes | |||
1646 | //===----------------------------------------------------------------------===// | |||
1647 | ||||
1648 | /// This provides public APIs that all operations should have. The template | |||
1649 | /// argument 'ConcreteType' should be the concrete type by CRTP and the others | |||
1650 | /// are base classes by the policy pattern. | |||
1651 | template <typename ConcreteType, template <typename T> class... Traits> | |||
1652 | class Op : public OpState, public Traits<ConcreteType>... { | |||
1653 | public: | |||
1654 | /// Inherit getOperation from `OpState`. | |||
1655 | using OpState::getOperation; | |||
1656 | using OpState::verify; | |||
1657 | using OpState::verifyRegions; | |||
1658 | ||||
1659 | /// Return if this operation contains the provided trait. | |||
1660 | template <template <typename T> class Trait> | |||
1661 | static constexpr bool hasTrait() { | |||
1662 | return llvm::is_one_of<Trait<ConcreteType>, Traits<ConcreteType>...>::value; | |||
1663 | } | |||
1664 | ||||
1665 | /// Create a deep copy of this operation. | |||
1666 | ConcreteType clone() { return cast<ConcreteType>(getOperation()->clone()); } | |||
1667 | ||||
1668 | /// Create a partial copy of this operation without traversing into attached | |||
1669 | /// regions. The new operation will have the same number of regions as the | |||
1670 | /// original one, but they will be left empty. | |||
1671 | ConcreteType cloneWithoutRegions() { | |||
1672 | return cast<ConcreteType>(getOperation()->cloneWithoutRegions()); | |||
1673 | } | |||
1674 | ||||
1675 | /// Return true if this "op class" can match against the specified operation. | |||
1676 | static bool classof(Operation *op) { | |||
1677 | if (auto info = op->getRegisteredInfo()) | |||
1678 | return TypeID::get<ConcreteType>() == info->getTypeID(); | |||
1679 | #ifndef NDEBUG | |||
1680 | if (op->getName().getStringRef() == ConcreteType::getOperationName()) | |||
1681 | llvm::report_fatal_error( | |||
1682 | "classof on '" + ConcreteType::getOperationName() + | |||
1683 | "' failed due to the operation not being registered"); | |||
1684 | #endif | |||
1685 | return false; | |||
1686 | } | |||
1687 | /// Provide `classof` support for other OpBase derived classes, such as | |||
1688 | /// Interfaces. | |||
1689 | template <typename T> | |||
1690 | static std::enable_if_t<std::is_base_of<OpState, T>::value, bool> | |||
1691 | classof(const T *op) { | |||
1692 | return classof(const_cast<T *>(op)->getOperation()); | |||
1693 | } | |||
1694 | ||||
1695 | /// Expose the type we are instantiated on to template machinery that may want | |||
1696 | /// to introspect traits on this operation. | |||
1697 | using ConcreteOpType = ConcreteType; | |||
1698 | ||||
1699 | /// This is a public constructor. Any op can be initialized to null. | |||
1700 | explicit Op() : OpState(nullptr) {} | |||
1701 | Op(std::nullptr_t) : OpState(nullptr) {} | |||
1702 | ||||
1703 | /// This is a public constructor to enable access via the llvm::cast family of | |||
1704 | /// methods. This should not be used directly. | |||
1705 | explicit Op(Operation *state) : OpState(state) {} | |||
1706 | ||||
1707 | /// Methods for supporting PointerLikeTypeTraits. | |||
1708 | const void *getAsOpaquePointer() const { | |||
1709 | return static_cast<const void *>((Operation *)*this); | |||
1710 | } | |||
1711 | static ConcreteOpType getFromOpaquePointer(const void *pointer) { | |||
1712 | return ConcreteOpType( | |||
1713 | reinterpret_cast<Operation *>(const_cast<void *>(pointer))); | |||
1714 | } | |||
1715 | ||||
1716 | /// Attach the given models as implementations of the corresponding | |||
1717 | /// interfaces for the concrete operation. | |||
1718 | template <typename... Models> | |||
1719 | static void attachInterface(MLIRContext &context) { | |||
1720 | std::optional<RegisteredOperationName> info = | |||
1721 | RegisteredOperationName::lookup(ConcreteType::getOperationName(), | |||
1722 | &context); | |||
1723 | if (!info) | |||
1724 | llvm::report_fatal_error( | |||
1725 | "Attempting to attach an interface to an unregistered operation " + | |||
1726 | ConcreteType::getOperationName() + "."); | |||
1727 | (checkInterfaceTarget<Models>(), ...); | |||
1728 | info->attachInterface<Models...>(); | |||
1729 | } | |||
1730 | /// Convert the provided attribute to a property and assigned it to the | |||
1731 | /// provided properties. This default implementation forwards to a free | |||
1732 | /// function `setPropertiesFromAttribute` that can be looked up with ADL in | |||
1733 | /// the namespace where the properties are defined. It can also be overridden | |||
1734 | /// in the derived ConcreteOp. | |||
1735 | template <typename PropertiesTy> | |||
1736 | static LogicalResult setPropertiesFromAttr(PropertiesTy &prop, Attribute attr, | |||
1737 | InFlightDiagnostic *diag) { | |||
1738 | return setPropertiesFromAttribute(prop, attr, diag); | |||
1739 | } | |||
1740 | /// Convert the provided properties to an attribute. This default | |||
1741 | /// implementation forwards to a free function `getPropertiesAsAttribute` that | |||
1742 | /// can be looked up with ADL in the namespace where the properties are | |||
1743 | /// defined. It can also be overridden in the derived ConcreteOp. | |||
1744 | template <typename PropertiesTy> | |||
1745 | static Attribute getPropertiesAsAttr(MLIRContext *ctx, | |||
1746 | const PropertiesTy &prop) { | |||
1747 | return getPropertiesAsAttribute(ctx, prop); | |||
1748 | } | |||
1749 | /// Hash the provided properties. This default implementation forwards to a | |||
1750 | /// free function `computeHash` that can be looked up with ADL in the | |||
1751 | /// namespace where the properties are defined. It can also be overridden in | |||
1752 | /// the derived ConcreteOp. | |||
1753 | template <typename PropertiesTy> | |||
1754 | static llvm::hash_code computePropertiesHash(const PropertiesTy &prop) { | |||
1755 | return computeHash(prop); | |||
1756 | } | |||
1757 | ||||
1758 | private: | |||
1759 | /// Trait to check if T provides a 'fold' method for a single result op. | |||
1760 | template <typename T, typename... Args> | |||
1761 | using has_single_result_fold_t = | |||
1762 | decltype(std::declval<T>().fold(std::declval<ArrayRef<Attribute>>())); | |||
1763 | template <typename T> | |||
1764 | constexpr static bool has_single_result_fold_v = | |||
1765 | llvm::is_detected<has_single_result_fold_t, T>::value; | |||
1766 | /// Trait to check if T provides a general 'fold' method. | |||
1767 | template <typename T, typename... Args> | |||
1768 | using has_fold_t = decltype(std::declval<T>().fold( | |||
1769 | std::declval<ArrayRef<Attribute>>(), | |||
1770 | std::declval<SmallVectorImpl<OpFoldResult> &>())); | |||
1771 | template <typename T> | |||
1772 | constexpr static bool has_fold_v = llvm::is_detected<has_fold_t, T>::value; | |||
1773 | /// Trait to check if T provides a 'fold' method with a FoldAdaptor for a | |||
1774 | /// single result op. | |||
1775 | template <typename T, typename... Args> | |||
1776 | using has_fold_adaptor_single_result_fold_t = | |||
1777 | decltype(std::declval<T>().fold(std::declval<typename T::FoldAdaptor>())); | |||
1778 | template <class T> | |||
1779 | constexpr static bool has_fold_adaptor_single_result_v = | |||
1780 | llvm::is_detected<has_fold_adaptor_single_result_fold_t, T>::value; | |||
1781 | /// Trait to check if T provides a general 'fold' method with a FoldAdaptor. | |||
1782 | template <typename T, typename... Args> | |||
1783 | using has_fold_adaptor_fold_t = decltype(std::declval<T>().fold( | |||
1784 | std::declval<typename T::FoldAdaptor>(), | |||
1785 | std::declval<SmallVectorImpl<OpFoldResult> &>())); | |||
1786 | template <class T> | |||
1787 | constexpr static bool has_fold_adaptor_v = | |||
1788 | llvm::is_detected<has_fold_adaptor_fold_t, T>::value; | |||
1789 | ||||
1790 | /// Trait to check if T provides a 'print' method. | |||
1791 | template <typename T, typename... Args> | |||
1792 | using has_print = | |||
1793 | decltype(std::declval<T>().print(std::declval<OpAsmPrinter &>())); | |||
1794 | template <typename T> | |||
1795 | using detect_has_print = llvm::is_detected<has_print, T>; | |||
1796 | ||||
1797 | /// Trait to check if printProperties(OpAsmPrinter, T) exist | |||
1798 | template <typename T, typename... Args> | |||
1799 | using has_print_properties = decltype(printProperties( | |||
1800 | std::declval<OpAsmPrinter &>(), std::declval<T>())); | |||
1801 | template <typename T> | |||
1802 | using detect_has_print_properties = | |||
1803 | llvm::is_detected<has_print_properties, T>; | |||
1804 | ||||
1805 | /// Trait to check if parseProperties(OpAsmParser, T) exist | |||
1806 | template <typename T, typename... Args> | |||
1807 | using has_parse_properties = decltype(parseProperties( | |||
1808 | std::declval<OpAsmParser &>(), std::declval<T &>())); | |||
1809 | template <typename T> | |||
1810 | using detect_has_parse_properties = | |||
1811 | llvm::is_detected<has_parse_properties, T>; | |||
1812 | ||||
1813 | /// Trait to check if T provides a 'ConcreteEntity' type alias. | |||
1814 | template <typename T> | |||
1815 | using has_concrete_entity_t = typename T::ConcreteEntity; | |||
1816 | ||||
1817 | public: | |||
1818 | /// Returns true if this operation defines a `Properties` inner type. | |||
1819 | static constexpr bool hasProperties() { | |||
1820 | return !std::is_same_v< | |||
1821 | typename ConcreteType::template InferredProperties<ConcreteType>, | |||
1822 | EmptyProperties>; | |||
1823 | } | |||
1824 | ||||
1825 | private: | |||
1826 | /// A struct-wrapped type alias to T::ConcreteEntity if provided and to | |||
1827 | /// ConcreteType otherwise. This is akin to std::conditional but doesn't fail | |||
1828 | /// on the missing typedef. Useful for checking if the interface is targeting | |||
1829 | /// the right class. | |||
1830 | template <typename T, | |||
1831 | bool = llvm::is_detected<has_concrete_entity_t, T>::value> | |||
1832 | struct InterfaceTargetOrOpT { | |||
1833 | using type = typename T::ConcreteEntity; | |||
1834 | }; | |||
1835 | template <typename T> | |||
1836 | struct InterfaceTargetOrOpT<T, false> { | |||
1837 | using type = ConcreteType; | |||
1838 | }; | |||
1839 | ||||
1840 | /// A hook for static assertion that the external interface model T is | |||
1841 | /// targeting the concrete type of this op. The model can also be a fallback | |||
1842 | /// model that works for every op. | |||
1843 | template <typename T> | |||
1844 | static void checkInterfaceTarget() { | |||
1845 | static_assert(std::is_same<typename InterfaceTargetOrOpT<T>::type, | |||
1846 | ConcreteType>::value, | |||
1847 | "attaching an interface to the wrong op kind"); | |||
1848 | } | |||
1849 | ||||
1850 | /// Returns an interface map containing the interfaces registered to this | |||
1851 | /// operation. | |||
1852 | static detail::InterfaceMap getInterfaceMap() { | |||
1853 | return detail::InterfaceMap::template get<Traits<ConcreteType>...>(); | |||
1854 | } | |||
1855 | ||||
1856 | /// Return the internal implementations of each of the OperationName | |||
1857 | /// hooks. | |||
1858 | /// Implementation of `FoldHookFn` OperationName hook. | |||
1859 | static OperationName::FoldHookFn getFoldHookFn() { | |||
1860 | // If the operation is single result and defines a `fold` method. | |||
1861 | if constexpr (llvm::is_one_of<OpTrait::OneResult<ConcreteType>, | |||
1862 | Traits<ConcreteType>...>::value && | |||
1863 | (has_single_result_fold_v<ConcreteType> || | |||
1864 | has_fold_adaptor_single_result_v<ConcreteType>)) | |||
1865 | return [](Operation *op, ArrayRef<Attribute> operands, | |||
1866 | SmallVectorImpl<OpFoldResult> &results) { | |||
1867 | return foldSingleResultHook<ConcreteType>(op, operands, results); | |||
1868 | }; | |||
1869 | // The operation is not single result and defines a `fold` method. | |||
1870 | if constexpr (has_fold_v<ConcreteType> || has_fold_adaptor_v<ConcreteType>) | |||
1871 | return [](Operation *op, ArrayRef<Attribute> operands, | |||
1872 | SmallVectorImpl<OpFoldResult> &results) { | |||
1873 | return foldHook<ConcreteType>(op, operands, results); | |||
1874 | }; | |||
1875 | // The operation does not define a `fold` method. | |||
1876 | return [](Operation *op, ArrayRef<Attribute> operands, | |||
1877 | SmallVectorImpl<OpFoldResult> &results) { | |||
1878 | // In this case, we only need to fold the traits of the operation. | |||
1879 | return op_definition_impl::foldTraits<Traits<ConcreteType>...>( | |||
1880 | op, operands, results); | |||
1881 | }; | |||
1882 | } | |||
1883 | /// Return the result of folding a single result operation that defines a | |||
1884 | /// `fold` method. | |||
1885 | template <typename ConcreteOpT> | |||
1886 | static LogicalResult | |||
1887 | foldSingleResultHook(Operation *op, ArrayRef<Attribute> operands, | |||
1888 | SmallVectorImpl<OpFoldResult> &results) { | |||
1889 | OpFoldResult result; | |||
1890 | if constexpr (has_fold_adaptor_single_result_v<ConcreteOpT>) { | |||
1891 | if constexpr (hasProperties()) { | |||
1892 | result = cast<ConcreteOpT>(op).fold(typename ConcreteOpT::FoldAdaptor( | |||
1893 | operands, op->getAttrDictionary(), | |||
1894 | cast<ConcreteOpT>(op).getProperties(), op->getRegions())); | |||
1895 | } else { | |||
1896 | result = cast<ConcreteOpT>(op).fold(typename ConcreteOpT::FoldAdaptor( | |||
1897 | operands, op->getAttrDictionary(), {}, op->getRegions())); | |||
1898 | } | |||
1899 | } else { | |||
1900 | result = cast<ConcreteOpT>(op).fold(operands); | |||
1901 | } | |||
1902 | ||||
1903 | // If the fold failed or was in-place, try to fold the traits of the | |||
1904 | // operation. | |||
1905 | if (!result || result.template dyn_cast<Value>() == op->getResult(0)) { | |||
1906 | if (succeeded(op_definition_impl::foldTraits<Traits<ConcreteType>...>( | |||
1907 | op, operands, results))) | |||
1908 | return success(); | |||
1909 | return success(static_cast<bool>(result)); | |||
1910 | } | |||
1911 | results.push_back(result); | |||
1912 | return success(); | |||
1913 | } | |||
1914 | /// Return the result of folding an operation that defines a `fold` method. | |||
1915 | template <typename ConcreteOpT> | |||
1916 | static LogicalResult foldHook(Operation *op, ArrayRef<Attribute> operands, | |||
1917 | SmallVectorImpl<OpFoldResult> &results) { | |||
1918 | auto result = LogicalResult::failure(); | |||
1919 | if constexpr (has_fold_adaptor_v<ConcreteOpT>) { | |||
1920 | if constexpr (hasProperties()) { | |||
1921 | result = cast<ConcreteOpT>(op).fold( | |||
1922 | typename ConcreteOpT::FoldAdaptor( | |||
1923 | operands, op->getAttrDictionary(), | |||
1924 | cast<ConcreteOpT>(op).getProperties(), op->getRegions()), | |||
1925 | results); | |||
1926 | } else { | |||
1927 | result = cast<ConcreteOpT>(op).fold( | |||
1928 | typename ConcreteOpT::FoldAdaptor(operands, op->getAttrDictionary(), | |||
1929 | {}, op->getRegions()), | |||
1930 | results); | |||
1931 | } | |||
1932 | } else { | |||
1933 | result = cast<ConcreteOpT>(op).fold(operands, results); | |||
1934 | } | |||
1935 | ||||
1936 | // If the fold failed or was in-place, try to fold the traits of the | |||
1937 | // operation. | |||
1938 | if (failed(result) || results.empty()) { | |||
1939 | if (succeeded(op_definition_impl::foldTraits<Traits<ConcreteType>...>( | |||
1940 | op, operands, results))) | |||
1941 | return success(); | |||
1942 | } | |||
1943 | return result; | |||
1944 | } | |||
1945 | ||||
1946 | /// Implementation of `GetHasTraitFn` | |||
1947 | static OperationName::HasTraitFn getHasTraitFn() { | |||
1948 | return | |||
1949 | [](TypeID id) { return op_definition_impl::hasTrait<Traits...>(id); }; | |||
1950 | } | |||
1951 | /// Implementation of `PrintAssemblyFn` OperationName hook. | |||
1952 | static OperationName::PrintAssemblyFn getPrintAssemblyFn() { | |||
1953 | if constexpr (detect_has_print<ConcreteType>::value) | |||
1954 | return [](Operation *op, OpAsmPrinter &p, StringRef defaultDialect) { | |||
1955 | OpState::printOpName(op, p, defaultDialect); | |||
1956 | return cast<ConcreteType>(op).print(p); | |||
1957 | }; | |||
1958 | return [](Operation *op, OpAsmPrinter &printer, StringRef defaultDialect) { | |||
1959 | return OpState::print(op, printer, defaultDialect); | |||
1960 | }; | |||
1961 | } | |||
1962 | ||||
1963 | public: | |||
1964 | template <typename T> | |||
1965 | using InferredProperties = typename PropertiesSelector<T>::type; | |||
1966 | template <typename T = ConcreteType> | |||
1967 | InferredProperties<T> &getProperties() { | |||
1968 | if constexpr (!hasProperties()) | |||
1969 | return getEmptyProperties(); | |||
1970 | return *getOperation() | |||
1971 | ->getPropertiesStorage() | |||
1972 | .template as<InferredProperties<T> *>(); | |||
1973 | } | |||
1974 | ||||
1975 | /// This hook populates any unset default attrs when mapped to properties. | |||
1976 | template <typename T = ConcreteType> | |||
1977 | static void populateDefaultProperties(OperationName opName, | |||
1978 | InferredProperties<T> &properties) {} | |||
1979 | ||||
1980 | /// Print the operation properties. Unless overridden, this method will try to | |||
1981 | /// dispatch to a `printProperties` free-function if it exists, and otherwise | |||
1982 | /// by converting the properties to an Attribute. | |||
1983 | template <typename T> | |||
1984 | static void printProperties(MLIRContext *ctx, OpAsmPrinter &p, | |||
1985 | const T &properties) { | |||
1986 | if constexpr (detect_has_print_properties<T>::value) | |||
1987 | return printProperties(p, properties); | |||
1988 | genericPrintProperties(p, | |||
1989 | ConcreteType::getPropertiesAsAttr(ctx, properties)); | |||
1990 | } | |||
1991 | ||||
1992 | /// Parser the properties. Unless overridden, this method will print by | |||
1993 | /// converting the properties to an Attribute. | |||
1994 | template <typename T = ConcreteType> | |||
1995 | static ParseResult parseProperties(OpAsmParser &parser, | |||
1996 | OperationState &result) { | |||
1997 | if constexpr (detect_has_parse_properties<InferredProperties<T>>::value) { | |||
1998 | return parseProperties( | |||
1999 | parser, result.getOrAddProperties<InferredProperties<T>>()); | |||
2000 | } | |||
2001 | return genericParseProperties(parser, result.propertiesAttr); | |||
2002 | } | |||
2003 | ||||
2004 | private: | |||
2005 | /// Implementation of `PopulateDefaultAttrsFn` OperationName hook. | |||
2006 | static OperationName::PopulateDefaultAttrsFn getPopulateDefaultAttrsFn() { | |||
2007 | return ConcreteType::populateDefaultAttrs; | |||
2008 | } | |||
2009 | /// Implementation of `VerifyInvariantsFn` OperationName hook. | |||
2010 | static LogicalResult verifyInvariants(Operation *op) { | |||
2011 | static_assert(hasNoDataMembers(), | |||
2012 | "Op class shouldn't define new data members"); | |||
2013 | return failure( | |||
2014 | failed(op_definition_impl::verifyTraits<Traits<ConcreteType>...>(op)) || | |||
2015 | failed(cast<ConcreteType>(op).verify())); | |||
2016 | } | |||
2017 | static OperationName::VerifyInvariantsFn getVerifyInvariantsFn() { | |||
2018 | return static_cast<LogicalResult (*)(Operation *)>(&verifyInvariants); | |||
2019 | } | |||
2020 | /// Implementation of `VerifyRegionInvariantsFn` OperationName hook. | |||
2021 | static LogicalResult verifyRegionInvariants(Operation *op) { | |||
2022 | static_assert(hasNoDataMembers(), | |||
2023 | "Op class shouldn't define new data members"); | |||
2024 | return failure( | |||
2025 | failed(op_definition_impl::verifyRegionTraits<Traits<ConcreteType>...>( | |||
2026 | op)) || | |||
2027 | failed(cast<ConcreteType>(op).verifyRegions())); | |||
2028 | } | |||
2029 | static OperationName::VerifyRegionInvariantsFn getVerifyRegionInvariantsFn() { | |||
2030 | return static_cast<LogicalResult (*)(Operation *)>(&verifyRegionInvariants); | |||
2031 | } | |||
2032 | ||||
2033 | static constexpr bool hasNoDataMembers() { | |||
2034 | // Checking that the derived class does not define any member by comparing | |||
2035 | // its size to an ad-hoc EmptyOp. | |||
2036 | class EmptyOp : public Op<EmptyOp, Traits...> {}; | |||
2037 | return sizeof(ConcreteType) == sizeof(EmptyOp); | |||
2038 | } | |||
2039 | ||||
2040 | /// Allow access to internal implementation methods. | |||
2041 | friend RegisteredOperationName; | |||
2042 | }; | |||
2043 | ||||
2044 | /// This class represents the base of an operation interface. See the definition | |||
2045 | /// of `detail::Interface` for requirements on the `Traits` type. | |||
2046 | template <typename ConcreteType, typename Traits> | |||
2047 | class OpInterface | |||
2048 | : public detail::Interface<ConcreteType, Operation *, Traits, | |||
2049 | Op<ConcreteType>, OpTrait::TraitBase> { | |||
2050 | public: | |||
2051 | using Base = OpInterface<ConcreteType, Traits>; | |||
2052 | using InterfaceBase = detail::Interface<ConcreteType, Operation *, Traits, | |||
2053 | Op<ConcreteType>, OpTrait::TraitBase>; | |||
2054 | ||||
2055 | /// Inherit the base class constructor. | |||
2056 | using InterfaceBase::InterfaceBase; | |||
2057 | ||||
2058 | protected: | |||
2059 | /// Returns the impl interface instance for the given operation. | |||
2060 | static typename InterfaceBase::Concept *getInterfaceFor(Operation *op) { | |||
2061 | OperationName name = op->getName(); | |||
2062 | ||||
2063 | // Access the raw interface from the operation info. | |||
2064 | if (std::optional<RegisteredOperationName> rInfo = | |||
2065 | name.getRegisteredInfo()) { | |||
2066 | if (auto *opIface = rInfo->getInterface<ConcreteType>()) | |||
2067 | return opIface; | |||
2068 | // Fallback to the dialect to provide it with a chance to implement this | |||
2069 | // interface for this operation. | |||
2070 | return rInfo->getDialect().getRegisteredInterfaceForOp<ConcreteType>( | |||
2071 | op->getName()); | |||
2072 | } | |||
2073 | // Fallback to the dialect to provide it with a chance to implement this | |||
2074 | // interface for this operation. | |||
2075 | if (Dialect *dialect = name.getDialect()) | |||
2076 | return dialect->getRegisteredInterfaceForOp<ConcreteType>(name); | |||
2077 | return nullptr; | |||
2078 | } | |||
2079 | ||||
2080 | /// Allow access to `getInterfaceFor`. | |||
2081 | friend InterfaceBase; | |||
2082 | }; | |||
2083 | ||||
2084 | //===----------------------------------------------------------------------===// | |||
2085 | // CastOpInterface utilities | |||
2086 | //===----------------------------------------------------------------------===// | |||
2087 | ||||
2088 | // These functions are out-of-line implementations of the methods in | |||
2089 | // CastOpInterface, which avoids them being template instantiated/duplicated. | |||
2090 | namespace impl { | |||
2091 | /// Attempt to fold the given cast operation. | |||
2092 | LogicalResult foldCastInterfaceOp(Operation *op, | |||
2093 | ArrayRef<Attribute> attrOperands, | |||
2094 | SmallVectorImpl<OpFoldResult> &foldResults); | |||
2095 | /// Attempt to verify the given cast operation. | |||
2096 | LogicalResult verifyCastInterfaceOp( | |||
2097 | Operation *op, function_ref<bool(TypeRange, TypeRange)> areCastCompatible); | |||
2098 | } // namespace impl | |||
2099 | } // namespace mlir | |||
2100 | ||||
2101 | namespace llvm { | |||
2102 | ||||
2103 | template <typename T> | |||
2104 | struct DenseMapInfo<T, | |||
2105 | std::enable_if_t<std::is_base_of<mlir::OpState, T>::value && | |||
2106 | !mlir::detail::IsInterface<T>::value>> { | |||
2107 | static inline T getEmptyKey() { | |||
2108 | auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey(); | |||
2109 | return T::getFromOpaquePointer(pointer); | |||
2110 | } | |||
2111 | static inline T getTombstoneKey() { | |||
2112 | auto *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey(); | |||
2113 | return T::getFromOpaquePointer(pointer); | |||
2114 | } | |||
2115 | static unsigned getHashValue(T val) { | |||
2116 | return hash_value(val.getAsOpaquePointer()); | |||
2117 | } | |||
2118 | static bool isEqual(T lhs, T rhs) { return lhs == rhs; } | |||
2119 | }; | |||
2120 | ||||
2121 | } // namespace llvm | |||
2122 | ||||
2123 | #endif |