| 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 |