Bug Summary

File:build/source/mlir/include/mlir/IR/OpDefinition.h
Warning:line 114, column 5
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name SuperVectorize.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -D MLIR_CUDA_CONVERSIONS_ENABLED=1 -D MLIR_ROCM_CONVERSIONS_ENABLED=1 -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/mlir/lib/Dialect/Affine/Transforms -I /build/source/mlir/lib/Dialect/Affine/Transforms -I include -I /build/source/llvm/include -I /build/source/mlir/include -I tools/mlir/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp

/build/source/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp

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
33namespace mlir {
34namespace affine {
35#define GEN_PASS_DEF_AFFINEVECTORIZE
36#include "mlir/Dialect/Affine/Passes.h.inc"
37} // namespace affine
38} // namespace mlir
39
40using namespace mlir;
41using namespace affine;
42using 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
577using llvm::dbgs;
578
579/// Forward declaration.
580static FilterFunctionType
581isVectorizableLoopPtrFactory(const DenseSet<Operation *> &parallelLoops,
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.
588static std::optional<NestedPattern>
589makePattern(const DenseSet<Operation *> &parallelLoops, 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
611static 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
618namespace {
619
620/// Base state for the vectorize pass.
621/// Command line arguments are preempted by non-empty pass arguments.
622struct Vectorize : public affine::impl::AffineVectorizeBase<Vectorize> {
623 using Base::Base;
624
625 void runOnOperation() override;
626};
627
628} // namespace
629
630static 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.
658static 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
675namespace {
676
677struct 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
771private:
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>
789void 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>
817void 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.
832void VectorizationState::registerBlockArgVectorReplacement(
833 BlockArgument replaced, BlockArgument replacement) {
834 registerValueVectorReplacementImpl(replaced, replacement);
835}
836
837void 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.
857void 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
871void 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
882void 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'.
892void 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.
899static 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.
905void 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'.
911static 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`.
927static FilterFunctionType
928isVectorizableLoopPtrFactory(const DenseSet<Operation *> &parallelLoops,
929 int fastestVaryingMemRefDimension) {
930 return [&parallelLoops, 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.
947static 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.
956static arith::ConstantOp vectorizeConstant(arith::ConstantOp constOp,
957 VectorizationState &state) {
958 Type scalarTy = constOp.getType();
959 if (!VectorType::isValidElementType(scalarTy))
23
Taking true branch
960 return nullptr;
24
Calling constructor for 'ConstantOp'
25
Calling constructor for 'Op<mlir::arith::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>'
30
Returning from constructor for 'Op<mlir::arith::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>'
31
Returning from constructor for 'ConstantOp'
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`.
985static 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).
1009static 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.
1082static 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'.
1098static 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.
1129static 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)
;
3
Assuming 'DebugFlag' is false
4
Loop condition is false. Exiting loop
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__))
5
Taking false branch
6
'?' condition is true
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>()) {
7
Calling 'Value::getDefiningOp'
20
Returning from 'Value::getDefiningOp'
21
Taking true branch
1145 auto vecConstant = vectorizeConstant(constOp, state);
22
Calling 'vectorizeConstant'
32
Returning from 'vectorizeConstant'
33
'vecConstant' initialized here
1146 LLVM_DEBUG(dbgs() << "-> constant: " << vecConstant)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("early-vect")) { dbgs() << "-> constant: " <<
vecConstant; } } while (false)
;
34
Assuming 'DebugFlag' is true
35
Assuming the condition is true
36
Taking true branch
37
Null pointer value stored to 'op.state'
38
Calling 'operator<<'
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.
1174static 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.
1218static 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.
1259static 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.
1277static 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.
1399static 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);
2
Calling 'vectorizeOperand'
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.
1431static Operation *vectorizeAffineYieldOp(AffineYieldOp yieldOp,
1432 VectorizationState &state) {
1433 Operation *newYieldOp = widenOp(yieldOp, state);
1
Calling 'widenOp'
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.
1479static 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'.
1509static void
1510getMatchedAffineLoopsRec(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]'.
1529static void
1530getMatchedAffineLoops(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.
1537static LogicalResult
1538vectorizeLoopNest(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.
1609static 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.
1620static 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.
1664static 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.
1722void 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([&parallelLoops, &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([&parallelLoops](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.
1770static LogicalResult
1771verifyLoopNesting(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.
1811void 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.
1856LogicalResult 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}

/build/source/mlir/include/mlir/IR/Value.h

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
21namespace mlir {
22class AsmState;
23class Block;
24class BlockArgument;
25class Operation;
26class OpOperand;
27class OpPrintingFlags;
28class OpResult;
29class Region;
30class Value;
31
32//===----------------------------------------------------------------------===//
33// Value
34//===----------------------------------------------------------------------===//
35
36namespace detail {
37
38/// The base class for all derived Value classes. It contains all of the
39/// components that are shared across Value classes.
40class alignas(8) ValueImpl : public IRObjectWithUseList<OpOperand> {
41public:
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
71protected:
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).
93class Value {
94public:
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());
8
Calling 'dyn_cast_or_null<mlir::arith::ConstantOp, mlir::Operation>'
19
Returning from 'dyn_cast_or_null<mlir::arith::ConstantOp, mlir::Operation>'
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
240protected:
241 /// A pointer to the internal implementation of the value.
242 detail::ValueImpl *impl;
243};
244
245inline 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`.
256class OpOperand : public IROperand<OpOperand, Value> {
257public:
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
266private:
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
277namespace detail {
278/// The internal implementation of a BlockArgument.
279class BlockArgumentImpl : public ValueImpl {
280public:
281 static bool classof(const ValueImpl *value) {
282 return value->getKind() == ValueImpl::Kind::BlockArgument;
283 }
284
285private:
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.
305class BlockArgument : public Value {
306public:
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
323private:
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
352namespace detail {
353/// This class provides the implementation for an operation result.
354class alignas(8) OpResultImpl : public ValueImpl {
355public:
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.
383struct InlineOpResult : public OpResultImpl {
384public:
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.
400class OutOfLineOpResult : public OpResultImpl {
401public:
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.
421inline 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
429template <typename Ty>
430struct 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.
443class OpResult : public Value {
444public:
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
457private:
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.
476inline ::llvm::hash_code hash_value(Value arg) {
477 return ::llvm::hash_value(arg.getImpl());
478}
479
480template <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.
483using TypedValue = std::conditional_t<std::is_same_v<Ty, mlir::Type>,
484 mlir::Value, detail::TypedValue<Ty>>;
485
486} // namespace mlir
487
488namespace llvm {
489
490template <>
491struct 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};
505template <>
506struct 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};
516template <>
517struct 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.
529template <>
530struct PointerLikeTypeTraits<mlir::Value> {
531public:
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};
543template <>
544struct PointerLikeTypeTraits<mlir::BlockArgument>
545 : public PointerLikeTypeTraits<mlir::Value> {
546public:
547 static inline mlir::BlockArgument getFromVoidPointer(void *pointer) {
548 return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer);
549 }
550};
551template <>
552struct PointerLikeTypeTraits<mlir::OpResult>
553 : public PointerLikeTypeTraits<mlir::Value> {
554public:
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.
562template <typename To, typename From>
563struct 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

/build/source/llvm/include/llvm/Support/Casting.h

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
24namespace 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.
34template <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
41template <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.
63template <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.
68template <typename To, typename From>
69struct 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
73template <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
79template <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
85template <typename To, typename From>
86struct 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
93template <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
100template <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
107template <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
114template <typename To, typename From>
115struct 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
122template <typename To, typename From, typename SimpleFrom>
123struct 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
133template <typename To, typename FromTy>
134struct 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
145template <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.
149template <class To, class From> struct cast_retty_impl {
150 using ret_type = To &; // Normal case, return Ty&
151};
152template <class To, class From> struct cast_retty_impl<To, const From> {
153 using ret_type = const To &; // Normal case, return Ty&
154};
155
156template <class To, class From> struct cast_retty_impl<To, From *> {
157 using ret_type = To *; // Pointer arg case, return Ty*
158};
159
160template <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
164template <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
168template <class To, class From>
169struct cast_retty_impl<To, std::unique_ptr<From>> {
170private:
171 using PointerType = typename cast_retty_impl<To, From *>::ret_type;
172 using ResultType = std::remove_pointer_t<PointerType>;
173
174public:
175 using ret_type = std::unique_ptr<ResultType>;
176};
177
178template <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
185template <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
190template <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//
202template <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
211template <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
219template <class To, class FromTy>
220struct 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
232template <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/// };
252template <typename To, typename From, typename Enable = void>
253struct 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.
265template <typename To, typename From>
266struct 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.
277template <typename To, typename From>
278struct 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`.
301template <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.
308template <typename To, typename From, typename Derived>
309struct DefaultDoCastIfPossible {
310 static To doCastIfPossible(From f) {
311 if (!Derived::isPossible(f))
12
Calling 'CastInfo::isPossible'
14
Returning from 'CastInfo::isPossible'
15
Assuming the condition is false
16
Taking false branch
312 return Derived::castFailed();
313 return Derived::doCast(f);
314 }
315};
316
317namespace 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.
320template <typename OptionalDerived, typename Default>
321using 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.
328template <typename To, typename From, typename Derived = void>
329struct 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.
342template <typename To, typename From, typename Derived = void>
343struct 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>.
364template <typename To, typename From, typename Derived = void>
365struct 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///
387template <typename To, typename From, typename ForwardTo>
388struct 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///
422template <typename To, typename From, typename ForwardTo>
423struct 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
475template <typename To, typename From, typename Enable = void>
476struct 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.
502template <typename To, typename From>
503struct 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.
532template <typename To, typename From>
533struct 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.
538template <typename To, typename From>
539struct 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)) { ... }
547template <typename To, typename From>
548[[nodiscard]] inline bool isa(const From &Val) {
549 return CastInfo<To, const From>::isPossible(Val);
550}
551
552template <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
564template <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
570template <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
576template <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
582template <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
592template <typename T>
593constexpr 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.
602template <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.
609template <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.
619template <typename T>
620struct 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
626namespace 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.
629template <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.
635template <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
648template <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
654template <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
660template <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
666template <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.
675template <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
682template <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.
689template <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
697template <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
704template <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
711template <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.
721template <class X, class Y> auto cast_or_null(const Y &Val) {
722 return cast_if_present<X>(Val);
723}
724
725template <class X, class Y> auto cast_or_null(Y &Val) {
726 return cast_if_present<X>(Val);
727}
728
729template <class X, class Y> auto cast_or_null(Y *Val) {
730 return cast_if_present<X>(Val);
731}
732
733template <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.
739template <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
745template <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
751template <class X, class Y> auto dyn_cast_if_present(Y *Val) {
752 if (!detail::isPresent(Val))
10
Taking false branch
753 return CastInfo<X, Y *>::castFailed();
754 return CastInfo<X, Y *>::doCastIfPossible(detail::unwrapValue(Val));
11
Calling 'DefaultDoCastIfPossible::doCastIfPossible'
17
Returning from 'DefaultDoCastIfPossible::doCastIfPossible'
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.
760template <class X, class Y> auto dyn_cast_or_null(const Y &Val) {
761 return dyn_cast_if_present<X>(Val);
762}
763
764template <class X, class Y> auto dyn_cast_or_null(Y &Val) {
765 return dyn_cast_if_present<X>(Val);
766}
767
768template <class X, class Y> auto dyn_cast_or_null(Y *Val) {
769 return dyn_cast_if_present<X>(Val);
9
Calling 'dyn_cast_if_present<mlir::arith::ConstantOp, mlir::Operation>'
18
Returning from 'dyn_cast_if_present<mlir::arith::ConstantOp, mlir::Operation>'
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.
777template <class X, class Y>
778[[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
779unique_dyn_cast(std::unique_ptr<Y> &Val) {
780 if (!isa<X>(Val))
781 return nullptr;
782 return cast<X>(std::move(Val));
783}
784
785template <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.
792template <class X, class Y>
793[[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
794unique_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
800template <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

/build/source/mlir/include/mlir/IR/Operation.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
24namespace mlir {
25namespace detail {
26/// This is a "tag" used for mapping the properties storage in
27/// llvm::TrailingObjects.
28enum 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).
84class 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> {
89public:
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
874private:
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
894private:
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
1034inline 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
1041namespace llvm {
1042/// Cast from an (const) Operation * to a derived operation type.
1043template <typename T>
1044struct 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); }
13
Value assigned to 'DebugFlag', which participates in a condition later
1048};
1049template <typename T>
1050struct 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.
1055template <typename T>
1056struct 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};
1065template <typename T>
1066struct 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.
1073template <>
1074struct 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};
1082template <>
1083struct 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

tools/mlir/include/mlir/Dialect/Arith/IR/ArithOps.h.inc

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
11namespace mlir {
12namespace arith {
13class AddFOp;
14} // namespace arith
15} // namespace mlir
16namespace mlir {
17namespace arith {
18class AddIOp;
19} // namespace arith
20} // namespace mlir
21namespace mlir {
22namespace arith {
23class AddUIExtendedOp;
24} // namespace arith
25} // namespace mlir
26namespace mlir {
27namespace arith {
28class AndIOp;
29} // namespace arith
30} // namespace mlir
31namespace mlir {
32namespace arith {
33class BitcastOp;
34} // namespace arith
35} // namespace mlir
36namespace mlir {
37namespace arith {
38class CeilDivSIOp;
39} // namespace arith
40} // namespace mlir
41namespace mlir {
42namespace arith {
43class CeilDivUIOp;
44} // namespace arith
45} // namespace mlir
46namespace mlir {
47namespace arith {
48class CmpFOp;
49} // namespace arith
50} // namespace mlir
51namespace mlir {
52namespace arith {
53class CmpIOp;
54} // namespace arith
55} // namespace mlir
56namespace mlir {
57namespace arith {
58class ConstantOp;
59} // namespace arith
60} // namespace mlir
61namespace mlir {
62namespace arith {
63class DivFOp;
64} // namespace arith
65} // namespace mlir
66namespace mlir {
67namespace arith {
68class DivSIOp;
69} // namespace arith
70} // namespace mlir
71namespace mlir {
72namespace arith {
73class DivUIOp;
74} // namespace arith
75} // namespace mlir
76namespace mlir {
77namespace arith {
78class ExtFOp;
79} // namespace arith
80} // namespace mlir
81namespace mlir {
82namespace arith {
83class ExtSIOp;
84} // namespace arith
85} // namespace mlir
86namespace mlir {
87namespace arith {
88class ExtUIOp;
89} // namespace arith
90} // namespace mlir
91namespace mlir {
92namespace arith {
93class FPToSIOp;
94} // namespace arith
95} // namespace mlir
96namespace mlir {
97namespace arith {
98class FPToUIOp;
99} // namespace arith
100} // namespace mlir
101namespace mlir {
102namespace arith {
103class FloorDivSIOp;
104} // namespace arith
105} // namespace mlir
106namespace mlir {
107namespace arith {
108class IndexCastOp;
109} // namespace arith
110} // namespace mlir
111namespace mlir {
112namespace arith {
113class IndexCastUIOp;
114} // namespace arith
115} // namespace mlir
116namespace mlir {
117namespace arith {
118class MaxFOp;
119} // namespace arith
120} // namespace mlir
121namespace mlir {
122namespace arith {
123class MaxSIOp;
124} // namespace arith
125} // namespace mlir
126namespace mlir {
127namespace arith {
128class MaxUIOp;
129} // namespace arith
130} // namespace mlir
131namespace mlir {
132namespace arith {
133class MinFOp;
134} // namespace arith
135} // namespace mlir
136namespace mlir {
137namespace arith {
138class MinSIOp;
139} // namespace arith
140} // namespace mlir
141namespace mlir {
142namespace arith {
143class MinUIOp;
144} // namespace arith
145} // namespace mlir
146namespace mlir {
147namespace arith {
148class MulFOp;
149} // namespace arith
150} // namespace mlir
151namespace mlir {
152namespace arith {
153class MulIOp;
154} // namespace arith
155} // namespace mlir
156namespace mlir {
157namespace arith {
158class MulSIExtendedOp;
159} // namespace arith
160} // namespace mlir
161namespace mlir {
162namespace arith {
163class MulUIExtendedOp;
164} // namespace arith
165} // namespace mlir
166namespace mlir {
167namespace arith {
168class NegFOp;
169} // namespace arith
170} // namespace mlir
171namespace mlir {
172namespace arith {
173class OrIOp;
174} // namespace arith
175} // namespace mlir
176namespace mlir {
177namespace arith {
178class RemFOp;
179} // namespace arith
180} // namespace mlir
181namespace mlir {
182namespace arith {
183class RemSIOp;
184} // namespace arith
185} // namespace mlir
186namespace mlir {
187namespace arith {
188class RemUIOp;
189} // namespace arith
190} // namespace mlir
191namespace mlir {
192namespace arith {
193class SIToFPOp;
194} // namespace arith
195} // namespace mlir
196namespace mlir {
197namespace arith {
198class ShLIOp;
199} // namespace arith
200} // namespace mlir
201namespace mlir {
202namespace arith {
203class ShRSIOp;
204} // namespace arith
205} // namespace mlir
206namespace mlir {
207namespace arith {
208class ShRUIOp;
209} // namespace arith
210} // namespace mlir
211namespace mlir {
212namespace arith {
213class SubFOp;
214} // namespace arith
215} // namespace mlir
216namespace mlir {
217namespace arith {
218class SubIOp;
219} // namespace arith
220} // namespace mlir
221namespace mlir {
222namespace arith {
223class TruncFOp;
224} // namespace arith
225} // namespace mlir
226namespace mlir {
227namespace arith {
228class TruncIOp;
229} // namespace arith
230} // namespace mlir
231namespace mlir {
232namespace arith {
233class UIToFPOp;
234} // namespace arith
235} // namespace mlir
236namespace mlir {
237namespace arith {
238class XOrIOp;
239} // namespace arith
240} // namespace mlir
241namespace mlir {
242namespace arith {
243class 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
256namespace mlir {
257namespace arith {
258
259//===----------------------------------------------------------------------===//
260// ::mlir::arith::AddFOp declarations
261//===----------------------------------------------------------------------===//
262
263namespace detail {
264class AddFOpGenericAdaptorBase {
265public:
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 };
278protected:
279 ::mlir::DictionaryAttr odsAttrs;
280 ::std::optional<::mlir::OperationName> odsOpName;
281 Properties properties;
282 ::mlir::RegionRange odsRegions;
283public:
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
296template <typename RangeT>
297class AddFOpGenericAdaptor : public detail::AddFOpGenericAdaptorBase {
298 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
299 using Base = detail::AddFOpGenericAdaptorBase;
300public:
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
327private:
328 RangeT odsOperands;
329};
330class AddFOpAdaptor : public AddFOpGenericAdaptor<::mlir::ValueRange> {
331public:
332 using AddFOpGenericAdaptor::AddFOpGenericAdaptor;
333 AddFOpAdaptor(AddFOp op);
334
335 ::mlir::LogicalResult verify(::mlir::Location loc);
336};
337class 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> {
338public:
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);
399private:
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
410public:
411};
412} // namespace arith
413} // namespace mlir
414MLIR_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
416namespace mlir {
417namespace arith {
418
419//===----------------------------------------------------------------------===//
420// ::mlir::arith::AddIOp declarations
421//===----------------------------------------------------------------------===//
422
423namespace detail {
424class AddIOpGenericAdaptorBase {
425public:
426protected:
427 ::mlir::DictionaryAttr odsAttrs;
428 ::std::optional<::mlir::OperationName> odsOpName;
429 ::mlir::RegionRange odsRegions;
430public:
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
437template <typename RangeT>
438class AddIOpGenericAdaptor : public detail::AddIOpGenericAdaptorBase {
439 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
440 using Base = detail::AddIOpGenericAdaptorBase;
441public:
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
468private:
469 RangeT odsOperands;
470};
471class AddIOpAdaptor : public AddIOpGenericAdaptor<::mlir::ValueRange> {
472public:
473 using AddIOpGenericAdaptor::AddIOpGenericAdaptor;
474 AddIOpAdaptor(AddIOp op);
475
476 ::mlir::LogicalResult verify(::mlir::Location loc);
477};
478class 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> {
479public:
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);
517public:
518};
519} // namespace arith
520} // namespace mlir
521MLIR_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
523namespace mlir {
524namespace arith {
525
526//===----------------------------------------------------------------------===//
527// ::mlir::arith::AddUIExtendedOp declarations
528//===----------------------------------------------------------------------===//
529
530namespace detail {
531class AddUIExtendedOpGenericAdaptorBase {
532public:
533protected:
534 ::mlir::DictionaryAttr odsAttrs;
535 ::std::optional<::mlir::OperationName> odsOpName;
536 ::mlir::RegionRange odsRegions;
537public:
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
544template <typename RangeT>
545class AddUIExtendedOpGenericAdaptor : public detail::AddUIExtendedOpGenericAdaptorBase {
546 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
547 using Base = detail::AddUIExtendedOpGenericAdaptorBase;
548public:
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
575private:
576 RangeT odsOperands;
577};
578class AddUIExtendedOpAdaptor : public AddUIExtendedOpGenericAdaptor<::mlir::ValueRange> {
579public:
580 using AddUIExtendedOpGenericAdaptor::AddUIExtendedOpGenericAdaptor;
581 AddUIExtendedOpAdaptor(AddUIExtendedOp op);
582
583 ::mlir::LogicalResult verify(::mlir::Location loc);
584};
585class 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> {
586public:
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);
623public:
624 std::optional<SmallVector<int64_t, 4>> getShapeForUnroll();
625};
626} // namespace arith
627} // namespace mlir
628MLIR_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
630namespace mlir {
631namespace arith {
632
633//===----------------------------------------------------------------------===//
634// ::mlir::arith::AndIOp declarations
635//===----------------------------------------------------------------------===//
636
637namespace detail {
638class AndIOpGenericAdaptorBase {
639public:
640protected:
641 ::mlir::DictionaryAttr odsAttrs;
642 ::std::optional<::mlir::OperationName> odsOpName;
643 ::mlir::RegionRange odsRegions;
644public:
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
651template <typename RangeT>
652class AndIOpGenericAdaptor : public detail::AndIOpGenericAdaptorBase {
653 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
654 using Base = detail::AndIOpGenericAdaptorBase;
655public:
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
682private:
683 RangeT odsOperands;
684};
685class AndIOpAdaptor : public AndIOpGenericAdaptor<::mlir::ValueRange> {
686public:
687 using AndIOpGenericAdaptor::AndIOpGenericAdaptor;
688 AndIOpAdaptor(AndIOp op);
689
690 ::mlir::LogicalResult verify(::mlir::Location loc);
691};
692class 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> {
693public:
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);
731public:
732};
733} // namespace arith
734} // namespace mlir
735MLIR_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
737namespace mlir {
738namespace arith {
739
740//===----------------------------------------------------------------------===//
741// ::mlir::arith::BitcastOp declarations
742//===----------------------------------------------------------------------===//
743
744namespace detail {
745class BitcastOpGenericAdaptorBase {
746public:
747protected:
748 ::mlir::DictionaryAttr odsAttrs;
749 ::std::optional<::mlir::OperationName> odsOpName;
750 ::mlir::RegionRange odsRegions;
751public:
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
758template <typename RangeT>
759class BitcastOpGenericAdaptor : public detail::BitcastOpGenericAdaptorBase {
760 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
761 using Base = detail::BitcastOpGenericAdaptorBase;
762public:
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
785private:
786 RangeT odsOperands;
787};
788class BitcastOpAdaptor : public BitcastOpGenericAdaptor<::mlir::ValueRange> {
789public:
790 using BitcastOpGenericAdaptor::BitcastOpGenericAdaptor;
791 BitcastOpAdaptor(BitcastOp op);
792
793 ::mlir::LogicalResult verify(::mlir::Location loc);
794};
795class 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> {
796public:
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);
829public:
830};
831} // namespace arith
832} // namespace mlir
833MLIR_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
835namespace mlir {
836namespace arith {
837
838//===----------------------------------------------------------------------===//
839// ::mlir::arith::CeilDivSIOp declarations
840//===----------------------------------------------------------------------===//
841
842namespace detail {
843class CeilDivSIOpGenericAdaptorBase {
844public:
845protected:
846 ::mlir::DictionaryAttr odsAttrs;
847 ::std::optional<::mlir::OperationName> odsOpName;
848 ::mlir::RegionRange odsRegions;
849public:
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
856template <typename RangeT>
857class CeilDivSIOpGenericAdaptor : public detail::CeilDivSIOpGenericAdaptorBase {
858 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
859 using Base = detail::CeilDivSIOpGenericAdaptorBase;
860public:
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
887private:
888 RangeT odsOperands;
889};
890class CeilDivSIOpAdaptor : public CeilDivSIOpGenericAdaptor<::mlir::ValueRange> {
891public:
892 using CeilDivSIOpGenericAdaptor::CeilDivSIOpGenericAdaptor;
893 CeilDivSIOpAdaptor(CeilDivSIOp op);
894
895 ::mlir::LogicalResult verify(::mlir::Location loc);
896};
897class 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> {
898public:
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);
935public:
936 /// Interface method for ConditionallySpeculatable.
937 Speculation::Speculatability getSpeculatability();
938};
939} // namespace arith
940} // namespace mlir
941MLIR_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
943namespace mlir {
944namespace arith {
945
946//===----------------------------------------------------------------------===//
947// ::mlir::arith::CeilDivUIOp declarations
948//===----------------------------------------------------------------------===//
949
950namespace detail {
951class CeilDivUIOpGenericAdaptorBase {
952public:
953protected:
954 ::mlir::DictionaryAttr odsAttrs;
955 ::std::optional<::mlir::OperationName> odsOpName;
956 ::mlir::RegionRange odsRegions;
957public:
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
964template <typename RangeT>
965class CeilDivUIOpGenericAdaptor : public detail::CeilDivUIOpGenericAdaptorBase {
966 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
967 using Base = detail::CeilDivUIOpGenericAdaptorBase;
968public:
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
995private:
996 RangeT odsOperands;
997};
998class CeilDivUIOpAdaptor : public CeilDivUIOpGenericAdaptor<::mlir::ValueRange> {
999public:
1000 using CeilDivUIOpGenericAdaptor::CeilDivUIOpGenericAdaptor;
1001 CeilDivUIOpAdaptor(CeilDivUIOp op);
1002
1003 ::mlir::LogicalResult verify(::mlir::Location loc);
1004};
1005class 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> {
1006public:
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);
1043public:
1044 /// Interface method for ConditionallySpeculatable.
1045 Speculation::Speculatability getSpeculatability();
1046};
1047} // namespace arith
1048} // namespace mlir
1049MLIR_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
1051namespace mlir {
1052namespace arith {
1053
1054//===----------------------------------------------------------------------===//
1055// ::mlir::arith::CmpFOp declarations
1056//===----------------------------------------------------------------------===//
1057
1058namespace detail {
1059class CmpFOpGenericAdaptorBase {
1060public:
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 };
1073protected:
1074 ::mlir::DictionaryAttr odsAttrs;
1075 ::std::optional<::mlir::OperationName> odsOpName;
1076 Properties properties;
1077 ::mlir::RegionRange odsRegions;
1078public:
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
1091template <typename RangeT>
1092class CmpFOpGenericAdaptor : public detail::CmpFOpGenericAdaptorBase {
1093 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
1094 using Base = detail::CmpFOpGenericAdaptorBase;
1095public:
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
1122private:
1123 RangeT odsOperands;
1124};
1125class CmpFOpAdaptor : public CmpFOpGenericAdaptor<::mlir::ValueRange> {
1126public:
1127 using CmpFOpGenericAdaptor::CmpFOpGenericAdaptor;
1128 CmpFOpAdaptor(CmpFOp op);
1129
1130 ::mlir::LogicalResult verify(::mlir::Location loc);
1131};
1132class 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> {
1133public:
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);
1194private:
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
1205public:
1206 static arith::CmpFPredicate getPredicateByName(StringRef name);
1207};
1208} // namespace arith
1209} // namespace mlir
1210MLIR_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
1212namespace mlir {
1213namespace arith {
1214
1215//===----------------------------------------------------------------------===//
1216// ::mlir::arith::CmpIOp declarations
1217//===----------------------------------------------------------------------===//
1218
1219namespace detail {
1220class CmpIOpGenericAdaptorBase {
1221public:
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 };
1234protected:
1235 ::mlir::DictionaryAttr odsAttrs;
1236 ::std::optional<::mlir::OperationName> odsOpName;
1237 Properties properties;
1238 ::mlir::RegionRange odsRegions;
1239public:
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
1252template <typename RangeT>
1253class CmpIOpGenericAdaptor : public detail::CmpIOpGenericAdaptorBase {
1254 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
1255 using Base = detail::CmpIOpGenericAdaptorBase;
1256public:
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
1283private:
1284 RangeT odsOperands;
1285};
1286class CmpIOpAdaptor : public CmpIOpGenericAdaptor<::mlir::ValueRange> {
1287public:
1288 using CmpIOpGenericAdaptor::CmpIOpGenericAdaptor;
1289 CmpIOpAdaptor(CmpIOp op);
1290
1291 ::mlir::LogicalResult verify(::mlir::Location loc);
1292};
1293class 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> {
1294public:
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);
1356private:
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
1367public:
1368 static arith::CmpIPredicate getPredicateByName(StringRef name);
1369};
1370} // namespace arith
1371} // namespace mlir
1372MLIR_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
1374namespace mlir {
1375namespace arith {
1376
1377//===----------------------------------------------------------------------===//
1378// ::mlir::arith::ConstantOp declarations
1379//===----------------------------------------------------------------------===//
1380
1381namespace detail {
1382class ConstantOpGenericAdaptorBase {
1383public:
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 };
1396protected:
1397 ::mlir::DictionaryAttr odsAttrs;
1398 ::std::optional<::mlir::OperationName> odsOpName;
1399 Properties properties;
1400 ::mlir::RegionRange odsRegions;
1401public:
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
1414template <typename RangeT>
1415class ConstantOpGenericAdaptor : public detail::ConstantOpGenericAdaptorBase {
1416 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
1417 using Base = detail::ConstantOpGenericAdaptorBase;
1418public:
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
1437private:
1438 RangeT odsOperands;
1439};
1440class ConstantOpAdaptor : public ConstantOpGenericAdaptor<::mlir::ValueRange> {
1441public:
1442 using ConstantOpGenericAdaptor::ConstantOpGenericAdaptor;
1443 ConstantOpAdaptor(ConstantOp op);
1444
1445 ::mlir::LogicalResult verify(::mlir::Location loc);
1446};
1447class 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> {
1448public:
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);
1503private:
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
1514public:
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
1526MLIR_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
1528namespace mlir {
1529namespace arith {
1530
1531//===----------------------------------------------------------------------===//
1532// ::mlir::arith::DivFOp declarations
1533//===----------------------------------------------------------------------===//
1534
1535namespace detail {
1536class DivFOpGenericAdaptorBase {
1537public:
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 };
1550protected:
1551 ::mlir::DictionaryAttr odsAttrs;
1552 ::std::optional<::mlir::OperationName> odsOpName;
1553 Properties properties;
1554 ::mlir::RegionRange odsRegions;
1555public:
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
1568template <typename RangeT>
1569class DivFOpGenericAdaptor : public detail::DivFOpGenericAdaptorBase {
1570 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
1571 using Base = detail::DivFOpGenericAdaptorBase;
1572public:
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
1599private:
1600 RangeT odsOperands;
1601};
1602class DivFOpAdaptor : public DivFOpGenericAdaptor<::mlir::ValueRange> {
1603public:
1604 using DivFOpGenericAdaptor::DivFOpGenericAdaptor;
1605 DivFOpAdaptor(DivFOp op);
1606
1607 ::mlir::LogicalResult verify(::mlir::Location loc);
1608};
1609class 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> {
1610public:
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);
1672private:
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
1683public:
1684};
1685} // namespace arith
1686} // namespace mlir
1687MLIR_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
1689namespace mlir {
1690namespace arith {
1691
1692//===----------------------------------------------------------------------===//
1693// ::mlir::arith::DivSIOp declarations
1694//===----------------------------------------------------------------------===//
1695
1696namespace detail {
1697class DivSIOpGenericAdaptorBase {
1698public:
1699protected:
1700 ::mlir::DictionaryAttr odsAttrs;
1701 ::std::optional<::mlir::OperationName> odsOpName;
1702 ::mlir::RegionRange odsRegions;
1703public:
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
1710template <typename RangeT>
1711class DivSIOpGenericAdaptor : public detail::DivSIOpGenericAdaptorBase {
1712 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
1713 using Base = detail::DivSIOpGenericAdaptorBase;
1714public:
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
1741private:
1742 RangeT odsOperands;
1743};
1744class DivSIOpAdaptor : public DivSIOpGenericAdaptor<::mlir::ValueRange> {
1745public:
1746 using DivSIOpGenericAdaptor::DivSIOpGenericAdaptor;
1747 DivSIOpAdaptor(DivSIOp op);
1748
1749 ::mlir::LogicalResult verify(::mlir::Location loc);
1750};
1751class 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> {
1752public:
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);
1789public:
1790 /// Interface method for ConditionallySpeculatable.
1791 Speculation::Speculatability getSpeculatability();
1792};
1793} // namespace arith
1794} // namespace mlir
1795MLIR_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
1797namespace mlir {
1798namespace arith {
1799
1800//===----------------------------------------------------------------------===//
1801// ::mlir::arith::DivUIOp declarations
1802//===----------------------------------------------------------------------===//
1803
1804namespace detail {
1805class DivUIOpGenericAdaptorBase {
1806public:
1807protected:
1808 ::mlir::DictionaryAttr odsAttrs;
1809 ::std::optional<::mlir::OperationName> odsOpName;
1810 ::mlir::RegionRange odsRegions;
1811public:
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
1818template <typename RangeT>
1819class DivUIOpGenericAdaptor : public detail::DivUIOpGenericAdaptorBase {
1820 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
1821 using Base = detail::DivUIOpGenericAdaptorBase;
1822public:
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
1849private:
1850 RangeT odsOperands;
1851};
1852class DivUIOpAdaptor : public DivUIOpGenericAdaptor<::mlir::ValueRange> {
1853public:
1854 using DivUIOpGenericAdaptor::DivUIOpGenericAdaptor;
1855 DivUIOpAdaptor(DivUIOp op);
1856
1857 ::mlir::LogicalResult verify(::mlir::Location loc);
1858};
1859class 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> {
1860public:
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);
1897public:
1898 /// Interface method for ConditionallySpeculatable.
1899 Speculation::Speculatability getSpeculatability();
1900};
1901} // namespace arith
1902} // namespace mlir
1903MLIR_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
1905namespace mlir {
1906namespace arith {
1907
1908//===----------------------------------------------------------------------===//
1909// ::mlir::arith::ExtFOp declarations
1910//===----------------------------------------------------------------------===//
1911
1912namespace detail {
1913class ExtFOpGenericAdaptorBase {
1914public:
1915protected:
1916 ::mlir::DictionaryAttr odsAttrs;
1917 ::std::optional<::mlir::OperationName> odsOpName;
1918 ::mlir::RegionRange odsRegions;
1919public:
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
1926template <typename RangeT>
1927class ExtFOpGenericAdaptor : public detail::ExtFOpGenericAdaptorBase {
1928 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
1929 using Base = detail::ExtFOpGenericAdaptorBase;
1930public:
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
1953private:
1954 RangeT odsOperands;
1955};
1956class ExtFOpAdaptor : public ExtFOpGenericAdaptor<::mlir::ValueRange> {
1957public:
1958 using ExtFOpGenericAdaptor::ExtFOpGenericAdaptor;
1959 ExtFOpAdaptor(ExtFOp op);
1960
1961 ::mlir::LogicalResult verify(::mlir::Location loc);
1962};
1963class 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> {
1964public:
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);
1997public:
1998};
1999} // namespace arith
2000} // namespace mlir
2001MLIR_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
2003namespace mlir {
2004namespace arith {
2005
2006//===----------------------------------------------------------------------===//
2007// ::mlir::arith::ExtSIOp declarations
2008//===----------------------------------------------------------------------===//
2009
2010namespace detail {
2011class ExtSIOpGenericAdaptorBase {
2012public:
2013protected:
2014 ::mlir::DictionaryAttr odsAttrs;
2015 ::std::optional<::mlir::OperationName> odsOpName;
2016 ::mlir::RegionRange odsRegions;
2017public:
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
2024template <typename RangeT>
2025class ExtSIOpGenericAdaptor : public detail::ExtSIOpGenericAdaptorBase {
2026 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
2027 using Base = detail::ExtSIOpGenericAdaptorBase;
2028public:
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
2051private:
2052 RangeT odsOperands;
2053};
2054class ExtSIOpAdaptor : public ExtSIOpGenericAdaptor<::mlir::ValueRange> {
2055public:
2056 using ExtSIOpGenericAdaptor::ExtSIOpGenericAdaptor;
2057 ExtSIOpAdaptor(ExtSIOp op);
2058
2059 ::mlir::LogicalResult verify(::mlir::Location loc);
2060};
2061class 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> {
2062public:
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);
2097public:
2098};
2099} // namespace arith
2100} // namespace mlir
2101MLIR_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
2103namespace mlir {
2104namespace arith {
2105
2106//===----------------------------------------------------------------------===//
2107// ::mlir::arith::ExtUIOp declarations
2108//===----------------------------------------------------------------------===//
2109
2110namespace detail {
2111class ExtUIOpGenericAdaptorBase {
2112public:
2113protected:
2114 ::mlir::DictionaryAttr odsAttrs;
2115 ::std::optional<::mlir::OperationName> odsOpName;
2116 ::mlir::RegionRange odsRegions;
2117public:
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
2124template <typename RangeT>
2125class ExtUIOpGenericAdaptor : public detail::ExtUIOpGenericAdaptorBase {
2126 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
2127 using Base = detail::ExtUIOpGenericAdaptorBase;
2128public:
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
2151private:
2152 RangeT odsOperands;
2153};
2154class ExtUIOpAdaptor : public ExtUIOpGenericAdaptor<::mlir::ValueRange> {
2155public:
2156 using ExtUIOpGenericAdaptor::ExtUIOpGenericAdaptor;
2157 ExtUIOpAdaptor(ExtUIOp op);
2158
2159 ::mlir::LogicalResult verify(::mlir::Location loc);
2160};
2161class 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> {
2162public:
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);
2196public:
2197};
2198} // namespace arith
2199} // namespace mlir
2200MLIR_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
2202namespace mlir {
2203namespace arith {
2204
2205//===----------------------------------------------------------------------===//
2206// ::mlir::arith::FPToSIOp declarations
2207//===----------------------------------------------------------------------===//
2208
2209namespace detail {
2210class FPToSIOpGenericAdaptorBase {
2211public:
2212protected:
2213 ::mlir::DictionaryAttr odsAttrs;
2214 ::std::optional<::mlir::OperationName> odsOpName;
2215 ::mlir::RegionRange odsRegions;
2216public:
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
2223template <typename RangeT>
2224class FPToSIOpGenericAdaptor : public detail::FPToSIOpGenericAdaptorBase {
2225 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
2226 using Base = detail::FPToSIOpGenericAdaptorBase;
2227public:
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
2250private:
2251 RangeT odsOperands;
2252};
2253class FPToSIOpAdaptor : public FPToSIOpGenericAdaptor<::mlir::ValueRange> {
2254public:
2255 using FPToSIOpGenericAdaptor::FPToSIOpGenericAdaptor;
2256 FPToSIOpAdaptor(FPToSIOp op);
2257
2258 ::mlir::LogicalResult verify(::mlir::Location loc);
2259};
2260class 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> {
2261public:
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);
2293public:
2294};
2295} // namespace arith
2296} // namespace mlir
2297MLIR_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
2299namespace mlir {
2300namespace arith {
2301
2302//===----------------------------------------------------------------------===//
2303// ::mlir::arith::FPToUIOp declarations
2304//===----------------------------------------------------------------------===//
2305
2306namespace detail {
2307class FPToUIOpGenericAdaptorBase {
2308public:
2309protected:
2310 ::mlir::DictionaryAttr odsAttrs;
2311 ::std::optional<::mlir::OperationName> odsOpName;
2312 ::mlir::RegionRange odsRegions;
2313public:
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
2320template <typename RangeT>
2321class FPToUIOpGenericAdaptor : public detail::FPToUIOpGenericAdaptorBase {
2322 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
2323 using Base = detail::FPToUIOpGenericAdaptorBase;
2324public:
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
2347private:
2348 RangeT odsOperands;
2349};
2350class FPToUIOpAdaptor : public FPToUIOpGenericAdaptor<::mlir::ValueRange> {
2351public:
2352 using FPToUIOpGenericAdaptor::FPToUIOpGenericAdaptor;
2353 FPToUIOpAdaptor(FPToUIOp op);
2354
2355 ::mlir::LogicalResult verify(::mlir::Location loc);
2356};
2357class 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> {
2358public:
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);
2390public:
2391};
2392} // namespace arith
2393} // namespace mlir
2394MLIR_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
2396namespace mlir {
2397namespace arith {
2398
2399//===----------------------------------------------------------------------===//
2400// ::mlir::arith::FloorDivSIOp declarations
2401//===----------------------------------------------------------------------===//
2402
2403namespace detail {
2404class FloorDivSIOpGenericAdaptorBase {
2405public:
2406protected:
2407 ::mlir::DictionaryAttr odsAttrs;
2408 ::std::optional<::mlir::OperationName> odsOpName;
2409 ::mlir::RegionRange odsRegions;
2410public:
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
2417template <typename RangeT>
2418class FloorDivSIOpGenericAdaptor : public detail::FloorDivSIOpGenericAdaptorBase {
2419 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
2420 using Base = detail::FloorDivSIOpGenericAdaptorBase;
2421public:
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
2448private:
2449 RangeT odsOperands;
2450};
2451class FloorDivSIOpAdaptor : public FloorDivSIOpGenericAdaptor<::mlir::ValueRange> {
2452public:
2453 using FloorDivSIOpGenericAdaptor::FloorDivSIOpGenericAdaptor;
2454 FloorDivSIOpAdaptor(FloorDivSIOp op);
2455
2456 ::mlir::LogicalResult verify(::mlir::Location loc);
2457};
2458class 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> {
2459public:
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);
2496public:
2497};
2498} // namespace arith
2499} // namespace mlir
2500MLIR_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
2502namespace mlir {
2503namespace arith {
2504
2505//===----------------------------------------------------------------------===//
2506// ::mlir::arith::IndexCastOp declarations
2507//===----------------------------------------------------------------------===//
2508
2509namespace detail {
2510class IndexCastOpGenericAdaptorBase {
2511public:
2512protected:
2513 ::mlir::DictionaryAttr odsAttrs;
2514 ::std::optional<::mlir::OperationName> odsOpName;
2515 ::mlir::RegionRange odsRegions;
2516public:
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
2523template <typename RangeT>
2524class IndexCastOpGenericAdaptor : public detail::IndexCastOpGenericAdaptorBase {
2525 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
2526 using Base = detail::IndexCastOpGenericAdaptorBase;
2527public:
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
2550private:
2551 RangeT odsOperands;
2552};
2553class IndexCastOpAdaptor : public IndexCastOpGenericAdaptor<::mlir::ValueRange> {
2554public:
2555 using IndexCastOpGenericAdaptor::IndexCastOpGenericAdaptor;
2556 IndexCastOpAdaptor(IndexCastOp op);
2557
2558 ::mlir::LogicalResult verify(::mlir::Location loc);
2559};
2560class 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> {
2561public:
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);
2595public:
2596};
2597} // namespace arith
2598} // namespace mlir
2599MLIR_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
2601namespace mlir {
2602namespace arith {
2603
2604//===----------------------------------------------------------------------===//
2605// ::mlir::arith::IndexCastUIOp declarations
2606//===----------------------------------------------------------------------===//
2607
2608namespace detail {
2609class IndexCastUIOpGenericAdaptorBase {
2610public:
2611protected:
2612 ::mlir::DictionaryAttr odsAttrs;
2613 ::std::optional<::mlir::OperationName> odsOpName;
2614 ::mlir::RegionRange odsRegions;
2615public:
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
2622template <typename RangeT>
2623class IndexCastUIOpGenericAdaptor : public detail::IndexCastUIOpGenericAdaptorBase {
2624 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
2625 using Base = detail::IndexCastUIOpGenericAdaptorBase;
2626public:
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
2649private:
2650 RangeT odsOperands;
2651};
2652class IndexCastUIOpAdaptor : public IndexCastUIOpGenericAdaptor<::mlir::ValueRange> {
2653public:
2654 using IndexCastUIOpGenericAdaptor::IndexCastUIOpGenericAdaptor;
2655 IndexCastUIOpAdaptor(IndexCastUIOp op);
2656
2657 ::mlir::LogicalResult verify(::mlir::Location loc);
2658};
2659class 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> {
2660public:
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);
2694public:
2695};
2696} // namespace arith
2697} // namespace mlir
2698MLIR_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
2700namespace mlir {
2701namespace arith {
2702
2703//===----------------------------------------------------------------------===//
2704// ::mlir::arith::MaxFOp declarations
2705//===----------------------------------------------------------------------===//
2706
2707namespace detail {
2708class MaxFOpGenericAdaptorBase {
2709public:
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 };
2722protected:
2723 ::mlir::DictionaryAttr odsAttrs;
2724 ::std::optional<::mlir::OperationName> odsOpName;
2725 Properties properties;
2726 ::mlir::RegionRange odsRegions;
2727public:
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
2740template <typename RangeT>
2741class MaxFOpGenericAdaptor : public detail::MaxFOpGenericAdaptorBase {
2742 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
2743 using Base = detail::MaxFOpGenericAdaptorBase;
2744public:
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
2771private:
2772 RangeT odsOperands;
2773};
2774class MaxFOpAdaptor : public MaxFOpGenericAdaptor<::mlir::ValueRange> {
2775public:
2776 using MaxFOpGenericAdaptor::MaxFOpGenericAdaptor;
2777 MaxFOpAdaptor(MaxFOp op);
2778
2779 ::mlir::LogicalResult verify(::mlir::Location loc);
2780};
2781class 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> {
2782public:
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);
2843private:
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
2854public:
2855};
2856} // namespace arith
2857} // namespace mlir
2858MLIR_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
2860namespace mlir {
2861namespace arith {
2862
2863//===----------------------------------------------------------------------===//
2864// ::mlir::arith::MaxSIOp declarations
2865//===----------------------------------------------------------------------===//
2866
2867namespace detail {
2868class MaxSIOpGenericAdaptorBase {
2869public:
2870protected:
2871 ::mlir::DictionaryAttr odsAttrs;
2872 ::std::optional<::mlir::OperationName> odsOpName;
2873 ::mlir::RegionRange odsRegions;
2874public:
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
2881template <typename RangeT>
2882class MaxSIOpGenericAdaptor : public detail::MaxSIOpGenericAdaptorBase {
2883 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
2884 using Base = detail::MaxSIOpGenericAdaptorBase;
2885public:
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
2912private:
2913 RangeT odsOperands;
2914};
2915class MaxSIOpAdaptor : public MaxSIOpGenericAdaptor<::mlir::ValueRange> {
2916public:
2917 using MaxSIOpGenericAdaptor::MaxSIOpGenericAdaptor;
2918 MaxSIOpAdaptor(MaxSIOp op);
2919
2920 ::mlir::LogicalResult verify(::mlir::Location loc);
2921};
2922class 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> {
2923public:
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);
2960public:
2961};
2962} // namespace arith
2963} // namespace mlir
2964MLIR_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
2966namespace mlir {
2967namespace arith {
2968
2969//===----------------------------------------------------------------------===//
2970// ::mlir::arith::MaxUIOp declarations
2971//===----------------------------------------------------------------------===//
2972
2973namespace detail {
2974class MaxUIOpGenericAdaptorBase {
2975public:
2976protected:
2977 ::mlir::DictionaryAttr odsAttrs;
2978 ::std::optional<::mlir::OperationName> odsOpName;
2979 ::mlir::RegionRange odsRegions;
2980public:
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
2987template <typename RangeT>
2988class MaxUIOpGenericAdaptor : public detail::MaxUIOpGenericAdaptorBase {
2989 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
2990 using Base = detail::MaxUIOpGenericAdaptorBase;
2991public:
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
3018private:
3019 RangeT odsOperands;
3020};
3021class MaxUIOpAdaptor : public MaxUIOpGenericAdaptor<::mlir::ValueRange> {
3022public:
3023 using MaxUIOpGenericAdaptor::MaxUIOpGenericAdaptor;
3024 MaxUIOpAdaptor(MaxUIOp op);
3025
3026 ::mlir::LogicalResult verify(::mlir::Location loc);
3027};
3028class 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> {
3029public:
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);
3066public:
3067};
3068} // namespace arith
3069} // namespace mlir
3070MLIR_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
3072namespace mlir {
3073namespace arith {
3074
3075//===----------------------------------------------------------------------===//
3076// ::mlir::arith::MinFOp declarations
3077//===----------------------------------------------------------------------===//
3078
3079namespace detail {
3080class MinFOpGenericAdaptorBase {
3081public:
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 };
3094protected:
3095 ::mlir::DictionaryAttr odsAttrs;
3096 ::std::optional<::mlir::OperationName> odsOpName;
3097 Properties properties;
3098 ::mlir::RegionRange odsRegions;
3099public:
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
3112template <typename RangeT>
3113class MinFOpGenericAdaptor : public detail::MinFOpGenericAdaptorBase {
3114 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
3115 using Base = detail::MinFOpGenericAdaptorBase;
3116public:
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
3143private:
3144 RangeT odsOperands;
3145};
3146class MinFOpAdaptor : public MinFOpGenericAdaptor<::mlir::ValueRange> {
3147public:
3148 using MinFOpGenericAdaptor::MinFOpGenericAdaptor;
3149 MinFOpAdaptor(MinFOp op);
3150
3151 ::mlir::LogicalResult verify(::mlir::Location loc);
3152};
3153class 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> {
3154public:
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);
3215private:
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
3226public:
3227};
3228} // namespace arith
3229} // namespace mlir
3230MLIR_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
3232namespace mlir {
3233namespace arith {
3234
3235//===----------------------------------------------------------------------===//
3236// ::mlir::arith::MinSIOp declarations
3237//===----------------------------------------------------------------------===//
3238
3239namespace detail {
3240class MinSIOpGenericAdaptorBase {
3241public:
3242protected:
3243 ::mlir::DictionaryAttr odsAttrs;
3244 ::std::optional<::mlir::OperationName> odsOpName;
3245 ::mlir::RegionRange odsRegions;
3246public:
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
3253template <typename RangeT>
3254class MinSIOpGenericAdaptor : public detail::MinSIOpGenericAdaptorBase {
3255 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
3256 using Base = detail::MinSIOpGenericAdaptorBase;
3257public:
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
3284private:
3285 RangeT odsOperands;
3286};
3287class MinSIOpAdaptor : public MinSIOpGenericAdaptor<::mlir::ValueRange> {
3288public:
3289 using MinSIOpGenericAdaptor::MinSIOpGenericAdaptor;
3290 MinSIOpAdaptor(MinSIOp op);
3291
3292 ::mlir::LogicalResult verify(::mlir::Location loc);
3293};
3294class 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> {
3295public:
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);
3332public:
3333};
3334} // namespace arith
3335} // namespace mlir
3336MLIR_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
3338namespace mlir {
3339namespace arith {
3340
3341//===----------------------------------------------------------------------===//
3342// ::mlir::arith::MinUIOp declarations
3343//===----------------------------------------------------------------------===//
3344
3345namespace detail {
3346class MinUIOpGenericAdaptorBase {
3347public:
3348protected:
3349 ::mlir::DictionaryAttr odsAttrs;
3350 ::std::optional<::mlir::OperationName> odsOpName;
3351 ::mlir::RegionRange odsRegions;
3352public:
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
3359template <typename RangeT>
3360class MinUIOpGenericAdaptor : public detail::MinUIOpGenericAdaptorBase {
3361 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
3362 using Base = detail::MinUIOpGenericAdaptorBase;
3363public:
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
3390private:
3391 RangeT odsOperands;
3392};
3393class MinUIOpAdaptor : public MinUIOpGenericAdaptor<::mlir::ValueRange> {
3394public:
3395 using MinUIOpGenericAdaptor::MinUIOpGenericAdaptor;
3396 MinUIOpAdaptor(MinUIOp op);
3397
3398 ::mlir::LogicalResult verify(::mlir::Location loc);
3399};
3400class 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> {
3401public:
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);
3438public:
3439};
3440} // namespace arith
3441} // namespace mlir
3442MLIR_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
3444namespace mlir {
3445namespace arith {
3446
3447//===----------------------------------------------------------------------===//
3448// ::mlir::arith::MulFOp declarations
3449//===----------------------------------------------------------------------===//
3450
3451namespace detail {
3452class MulFOpGenericAdaptorBase {
3453public:
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 };
3466protected:
3467 ::mlir::DictionaryAttr odsAttrs;
3468 ::std::optional<::mlir::OperationName> odsOpName;
3469 Properties properties;
3470 ::mlir::RegionRange odsRegions;
3471public:
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
3484template <typename RangeT>
3485class MulFOpGenericAdaptor : public detail::MulFOpGenericAdaptorBase {
3486 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
3487 using Base = detail::MulFOpGenericAdaptorBase;
3488public:
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
3515private:
3516 RangeT odsOperands;
3517};
3518class MulFOpAdaptor : public MulFOpGenericAdaptor<::mlir::ValueRange> {
3519public:
3520 using MulFOpGenericAdaptor::MulFOpGenericAdaptor;
3521 MulFOpAdaptor(MulFOp op);
3522
3523 ::mlir::LogicalResult verify(::mlir::Location loc);
3524};
3525class 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> {
3526public:
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);
3588private:
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
3599public:
3600};
3601} // namespace arith
3602} // namespace mlir
3603MLIR_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
3605namespace mlir {
3606namespace arith {
3607
3608//===----------------------------------------------------------------------===//
3609// ::mlir::arith::MulIOp declarations
3610//===----------------------------------------------------------------------===//
3611
3612namespace detail {
3613class MulIOpGenericAdaptorBase {
3614public:
3615protected:
3616 ::mlir::DictionaryAttr odsAttrs;
3617 ::std::optional<::mlir::OperationName> odsOpName;
3618 ::mlir::RegionRange odsRegions;
3619public:
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
3626template <typename RangeT>
3627class MulIOpGenericAdaptor : public detail::MulIOpGenericAdaptorBase {
3628 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
3629 using Base = detail::MulIOpGenericAdaptorBase;
3630public:
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
3657private:
3658 RangeT odsOperands;
3659};
3660class MulIOpAdaptor : public MulIOpGenericAdaptor<::mlir::ValueRange> {
3661public:
3662 using MulIOpGenericAdaptor::MulIOpGenericAdaptor;
3663 MulIOpAdaptor(MulIOp op);
3664
3665 ::mlir::LogicalResult verify(::mlir::Location loc);
3666};
3667class 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> {
3668public:
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);
3705public:
3706};
3707} // namespace arith
3708} // namespace mlir
3709MLIR_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
3711namespace mlir {
3712namespace arith {
3713
3714//===----------------------------------------------------------------------===//
3715// ::mlir::arith::MulSIExtendedOp declarations
3716//===----------------------------------------------------------------------===//
3717
3718namespace detail {
3719class MulSIExtendedOpGenericAdaptorBase {
3720public:
3721protected:
3722 ::mlir::DictionaryAttr odsAttrs;
3723 ::std::optional<::mlir::OperationName> odsOpName;
3724 ::mlir::RegionRange odsRegions;
3725public:
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
3732template <typename RangeT>
3733class MulSIExtendedOpGenericAdaptor : public detail::MulSIExtendedOpGenericAdaptorBase {
3734 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
3735 using Base = detail::MulSIExtendedOpGenericAdaptorBase;
3736public:
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
3763private:
3764 RangeT odsOperands;
3765};
3766class MulSIExtendedOpAdaptor : public MulSIExtendedOpGenericAdaptor<::mlir::ValueRange> {
3767public:
3768 using MulSIExtendedOpGenericAdaptor::MulSIExtendedOpGenericAdaptor;
3769 MulSIExtendedOpAdaptor(MulSIExtendedOp op);
3770
3771 ::mlir::LogicalResult verify(::mlir::Location loc);
3772};
3773class 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> {
3774public:
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);
3813public:
3814 std::optional<SmallVector<int64_t, 4>> getShapeForUnroll();
3815};
3816} // namespace arith
3817} // namespace mlir
3818MLIR_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
3820namespace mlir {
3821namespace arith {
3822
3823//===----------------------------------------------------------------------===//
3824// ::mlir::arith::MulUIExtendedOp declarations
3825//===----------------------------------------------------------------------===//
3826
3827namespace detail {
3828class MulUIExtendedOpGenericAdaptorBase {
3829public:
3830protected:
3831 ::mlir::DictionaryAttr odsAttrs;
3832 ::std::optional<::mlir::OperationName> odsOpName;
3833 ::mlir::RegionRange odsRegions;
3834public:
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
3841template <typename RangeT>
3842class MulUIExtendedOpGenericAdaptor : public detail::MulUIExtendedOpGenericAdaptorBase {
3843 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
3844 using Base = detail::MulUIExtendedOpGenericAdaptorBase;
3845public:
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
3872private:
3873 RangeT odsOperands;
3874};
3875class MulUIExtendedOpAdaptor : public MulUIExtendedOpGenericAdaptor<::mlir::ValueRange> {
3876public:
3877 using MulUIExtendedOpGenericAdaptor::MulUIExtendedOpGenericAdaptor;
3878 MulUIExtendedOpAdaptor(MulUIExtendedOp op);
3879
3880 ::mlir::LogicalResult verify(::mlir::Location loc);
3881};
3882class 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> {
3883public:
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);
3922public:
3923 std::optional<SmallVector<int64_t, 4>> getShapeForUnroll();
3924};
3925} // namespace arith
3926} // namespace mlir
3927MLIR_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
3929namespace mlir {
3930namespace arith {
3931
3932//===----------------------------------------------------------------------===//
3933// ::mlir::arith::NegFOp declarations
3934//===----------------------------------------------------------------------===//
3935
3936namespace detail {
3937class NegFOpGenericAdaptorBase {
3938public:
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 };
3951protected:
3952 ::mlir::DictionaryAttr odsAttrs;
3953 ::std::optional<::mlir::OperationName> odsOpName;
3954 Properties properties;
3955 ::mlir::RegionRange odsRegions;
3956public:
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
3969template <typename RangeT>
3970class NegFOpGenericAdaptor : public detail::NegFOpGenericAdaptorBase {
3971 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
3972 using Base = detail::NegFOpGenericAdaptorBase;
3973public:
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
3996private:
3997 RangeT odsOperands;
3998};
3999class NegFOpAdaptor : public NegFOpGenericAdaptor<::mlir::ValueRange> {
4000public:
4001 using NegFOpGenericAdaptor::NegFOpGenericAdaptor;
4002 NegFOpAdaptor(NegFOp op);
4003
4004 ::mlir::LogicalResult verify(::mlir::Location loc);
4005};
4006class 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> {
4007public:
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);
4066private:
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
4077public:
4078};
4079} // namespace arith
4080} // namespace mlir
4081MLIR_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
4083namespace mlir {
4084namespace arith {
4085
4086//===----------------------------------------------------------------------===//
4087// ::mlir::arith::OrIOp declarations
4088//===----------------------------------------------------------------------===//
4089
4090namespace detail {
4091class OrIOpGenericAdaptorBase {
4092public:
4093protected:
4094 ::mlir::DictionaryAttr odsAttrs;
4095 ::std::optional<::mlir::OperationName> odsOpName;
4096 ::mlir::RegionRange odsRegions;
4097public:
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
4104template <typename RangeT>
4105class OrIOpGenericAdaptor : public detail::OrIOpGenericAdaptorBase {
4106 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
4107 using Base = detail::OrIOpGenericAdaptorBase;
4108public:
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
4135private:
4136 RangeT odsOperands;
4137};
4138class OrIOpAdaptor : public OrIOpGenericAdaptor<::mlir::ValueRange> {
4139public:
4140 using OrIOpGenericAdaptor::OrIOpGenericAdaptor;
4141 OrIOpAdaptor(OrIOp op);
4142
4143 ::mlir::LogicalResult verify(::mlir::Location loc);
4144};
4145class 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> {
4146public:
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);
4184public:
4185};
4186} // namespace arith
4187} // namespace mlir
4188MLIR_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
4190namespace mlir {
4191namespace arith {
4192
4193//===----------------------------------------------------------------------===//
4194// ::mlir::arith::RemFOp declarations
4195//===----------------------------------------------------------------------===//
4196
4197namespace detail {
4198class RemFOpGenericAdaptorBase {
4199public:
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 };
4212protected:
4213 ::mlir::DictionaryAttr odsAttrs;
4214 ::std::optional<::mlir::OperationName> odsOpName;
4215 Properties properties;
4216 ::mlir::RegionRange odsRegions;
4217public:
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
4230template <typename RangeT>
4231class RemFOpGenericAdaptor : public detail::RemFOpGenericAdaptorBase {
4232 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
4233 using Base = detail::RemFOpGenericAdaptorBase;
4234public:
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
4261private:
4262 RangeT odsOperands;
4263};
4264class RemFOpAdaptor : public RemFOpGenericAdaptor<::mlir::ValueRange> {
4265public:
4266 using RemFOpGenericAdaptor::RemFOpGenericAdaptor;
4267 RemFOpAdaptor(RemFOp op);
4268
4269 ::mlir::LogicalResult verify(::mlir::Location loc);
4270};
4271class 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> {
4272public:
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);
4333private:
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
4344public:
4345};
4346} // namespace arith
4347} // namespace mlir
4348MLIR_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
4350namespace mlir {
4351namespace arith {
4352
4353//===----------------------------------------------------------------------===//
4354// ::mlir::arith::RemSIOp declarations
4355//===----------------------------------------------------------------------===//
4356
4357namespace detail {
4358class RemSIOpGenericAdaptorBase {
4359public:
4360protected:
4361 ::mlir::DictionaryAttr odsAttrs;
4362 ::std::optional<::mlir::OperationName> odsOpName;
4363 ::mlir::RegionRange odsRegions;
4364public:
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
4371template <typename RangeT>
4372class RemSIOpGenericAdaptor : public detail::RemSIOpGenericAdaptorBase {
4373 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
4374 using Base = detail::RemSIOpGenericAdaptorBase;
4375public:
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
4402private:
4403 RangeT odsOperands;
4404};
4405class RemSIOpAdaptor : public RemSIOpGenericAdaptor<::mlir::ValueRange> {
4406public:
4407 using RemSIOpGenericAdaptor::RemSIOpGenericAdaptor;
4408 RemSIOpAdaptor(RemSIOp op);
4409
4410 ::mlir::LogicalResult verify(::mlir::Location loc);
4411};
4412class 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> {
4413public:
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);
4450public:
4451};
4452} // namespace arith
4453} // namespace mlir
4454MLIR_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
4456namespace mlir {
4457namespace arith {
4458
4459//===----------------------------------------------------------------------===//
4460// ::mlir::arith::RemUIOp declarations
4461//===----------------------------------------------------------------------===//
4462
4463namespace detail {
4464class RemUIOpGenericAdaptorBase {
4465public:
4466protected:
4467 ::mlir::DictionaryAttr odsAttrs;
4468 ::std::optional<::mlir::OperationName> odsOpName;
4469 ::mlir::RegionRange odsRegions;
4470public:
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
4477template <typename RangeT>
4478class RemUIOpGenericAdaptor : public detail::RemUIOpGenericAdaptorBase {
4479 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
4480 using Base = detail::RemUIOpGenericAdaptorBase;
4481public:
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
4508private:
4509 RangeT odsOperands;
4510};
4511class RemUIOpAdaptor : public RemUIOpGenericAdaptor<::mlir::ValueRange> {
4512public:
4513 using RemUIOpGenericAdaptor::RemUIOpGenericAdaptor;
4514 RemUIOpAdaptor(RemUIOp op);
4515
4516 ::mlir::LogicalResult verify(::mlir::Location loc);
4517};
4518class 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> {
4519public:
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);
4556public:
4557};
4558} // namespace arith
4559} // namespace mlir
4560MLIR_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
4562namespace mlir {
4563namespace arith {
4564
4565//===----------------------------------------------------------------------===//
4566// ::mlir::arith::SIToFPOp declarations
4567//===----------------------------------------------------------------------===//
4568
4569namespace detail {
4570class SIToFPOpGenericAdaptorBase {
4571public:
4572protected:
4573 ::mlir::DictionaryAttr odsAttrs;
4574 ::std::optional<::mlir::OperationName> odsOpName;
4575 ::mlir::RegionRange odsRegions;
4576public:
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
4583template <typename RangeT>
4584class SIToFPOpGenericAdaptor : public detail::SIToFPOpGenericAdaptorBase {
4585 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
4586 using Base = detail::SIToFPOpGenericAdaptorBase;
4587public:
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
4610private:
4611 RangeT odsOperands;
4612};
4613class SIToFPOpAdaptor : public SIToFPOpGenericAdaptor<::mlir::ValueRange> {
4614public:
4615 using SIToFPOpGenericAdaptor::SIToFPOpGenericAdaptor;
4616 SIToFPOpAdaptor(SIToFPOp op);
4617
4618 ::mlir::LogicalResult verify(::mlir::Location loc);
4619};
4620class 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> {
4621public:
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);
4653public:
4654};
4655} // namespace arith
4656} // namespace mlir
4657MLIR_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
4659namespace mlir {
4660namespace arith {
4661
4662//===----------------------------------------------------------------------===//
4663// ::mlir::arith::ShLIOp declarations
4664//===----------------------------------------------------------------------===//
4665
4666namespace detail {
4667class ShLIOpGenericAdaptorBase {
4668public:
4669protected:
4670 ::mlir::DictionaryAttr odsAttrs;
4671 ::std::optional<::mlir::OperationName> odsOpName;
4672 ::mlir::RegionRange odsRegions;
4673public:
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
4680template <typename RangeT>
4681class ShLIOpGenericAdaptor : public detail::ShLIOpGenericAdaptorBase {
4682 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
4683 using Base = detail::ShLIOpGenericAdaptorBase;
4684public:
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
4711private:
4712 RangeT odsOperands;
4713};
4714class ShLIOpAdaptor : public ShLIOpGenericAdaptor<::mlir::ValueRange> {
4715public:
4716 using ShLIOpGenericAdaptor::ShLIOpGenericAdaptor;
4717 ShLIOpAdaptor(ShLIOp op);
4718
4719 ::mlir::LogicalResult verify(::mlir::Location loc);
4720};
4721class 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> {
4722public:
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);
4759public:
4760};
4761} // namespace arith
4762} // namespace mlir
4763MLIR_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
4765namespace mlir {
4766namespace arith {
4767
4768//===----------------------------------------------------------------------===//
4769// ::mlir::arith::ShRSIOp declarations
4770//===----------------------------------------------------------------------===//
4771
4772namespace detail {
4773class ShRSIOpGenericAdaptorBase {
4774public:
4775protected:
4776 ::mlir::DictionaryAttr odsAttrs;
4777 ::std::optional<::mlir::OperationName> odsOpName;
4778 ::mlir::RegionRange odsRegions;
4779public:
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
4786template <typename RangeT>
4787class ShRSIOpGenericAdaptor : public detail::ShRSIOpGenericAdaptorBase {
4788 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
4789 using Base = detail::ShRSIOpGenericAdaptorBase;
4790public:
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
4817private:
4818 RangeT odsOperands;
4819};
4820class ShRSIOpAdaptor : public ShRSIOpGenericAdaptor<::mlir::ValueRange> {
4821public:
4822 using ShRSIOpGenericAdaptor::ShRSIOpGenericAdaptor;
4823 ShRSIOpAdaptor(ShRSIOp op);
4824
4825 ::mlir::LogicalResult verify(::mlir::Location loc);
4826};
4827class 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> {
4828public:
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);
4865public:
4866};
4867} // namespace arith
4868} // namespace mlir
4869MLIR_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
4871namespace mlir {
4872namespace arith {
4873
4874//===----------------------------------------------------------------------===//
4875// ::mlir::arith::ShRUIOp declarations
4876//===----------------------------------------------------------------------===//
4877
4878namespace detail {
4879class ShRUIOpGenericAdaptorBase {
4880public:
4881protected:
4882 ::mlir::DictionaryAttr odsAttrs;
4883 ::std::optional<::mlir::OperationName> odsOpName;
4884 ::mlir::RegionRange odsRegions;
4885public:
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
4892template <typename RangeT>
4893class ShRUIOpGenericAdaptor : public detail::ShRUIOpGenericAdaptorBase {
4894 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
4895 using Base = detail::ShRUIOpGenericAdaptorBase;
4896public:
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
4923private:
4924 RangeT odsOperands;
4925};
4926class ShRUIOpAdaptor : public ShRUIOpGenericAdaptor<::mlir::ValueRange> {
4927public:
4928 using ShRUIOpGenericAdaptor::ShRUIOpGenericAdaptor;
4929 ShRUIOpAdaptor(ShRUIOp op);
4930
4931 ::mlir::LogicalResult verify(::mlir::Location loc);
4932};
4933class 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> {
4934public:
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);
4971public:
4972};
4973} // namespace arith
4974} // namespace mlir
4975MLIR_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
4977namespace mlir {
4978namespace arith {
4979
4980//===----------------------------------------------------------------------===//
4981// ::mlir::arith::SubFOp declarations
4982//===----------------------------------------------------------------------===//
4983
4984namespace detail {
4985class SubFOpGenericAdaptorBase {
4986public:
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 };
4999protected:
5000 ::mlir::DictionaryAttr odsAttrs;
5001 ::std::optional<::mlir::OperationName> odsOpName;
5002 Properties properties;
5003 ::mlir::RegionRange odsRegions;
5004public:
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
5017template <typename RangeT>
5018class SubFOpGenericAdaptor : public detail::SubFOpGenericAdaptorBase {
5019 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
5020 using Base = detail::SubFOpGenericAdaptorBase;
5021public:
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
5048private:
5049 RangeT odsOperands;
5050};
5051class SubFOpAdaptor : public SubFOpGenericAdaptor<::mlir::ValueRange> {
5052public:
5053 using SubFOpGenericAdaptor::SubFOpGenericAdaptor;
5054 SubFOpAdaptor(SubFOp op);
5055
5056 ::mlir::LogicalResult verify(::mlir::Location loc);
5057};
5058class 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> {
5059public:
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);
5120private:
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
5131public:
5132};
5133} // namespace arith
5134} // namespace mlir
5135MLIR_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
5137namespace mlir {
5138namespace arith {
5139
5140//===----------------------------------------------------------------------===//
5141// ::mlir::arith::SubIOp declarations
5142//===----------------------------------------------------------------------===//
5143
5144namespace detail {
5145class SubIOpGenericAdaptorBase {
5146public:
5147protected:
5148 ::mlir::DictionaryAttr odsAttrs;
5149 ::std::optional<::mlir::OperationName> odsOpName;
5150 ::mlir::RegionRange odsRegions;
5151public:
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
5158template <typename RangeT>
5159class SubIOpGenericAdaptor : public detail::SubIOpGenericAdaptorBase {
5160 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
5161 using Base = detail::SubIOpGenericAdaptorBase;
5162public:
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
5189private:
5190 RangeT odsOperands;
5191};
5192class SubIOpAdaptor : public SubIOpGenericAdaptor<::mlir::ValueRange> {
5193public:
5194 using SubIOpGenericAdaptor::SubIOpGenericAdaptor;
5195 SubIOpAdaptor(SubIOp op);
5196
5197 ::mlir::LogicalResult verify(::mlir::Location loc);
5198};
5199class 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> {
5200public:
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);
5238public:
5239};
5240} // namespace arith
5241} // namespace mlir
5242MLIR_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
5244namespace mlir {
5245namespace arith {
5246
5247//===----------------------------------------------------------------------===//
5248// ::mlir::arith::TruncFOp declarations
5249//===----------------------------------------------------------------------===//
5250
5251namespace detail {
5252class TruncFOpGenericAdaptorBase {
5253public:
5254protected:
5255 ::mlir::DictionaryAttr odsAttrs;
5256 ::std::optional<::mlir::OperationName> odsOpName;
5257 ::mlir::RegionRange odsRegions;
5258public:
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
5265template <typename RangeT>
5266class TruncFOpGenericAdaptor : public detail::TruncFOpGenericAdaptorBase {
5267 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
5268 using Base = detail::TruncFOpGenericAdaptorBase;
5269public:
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
5292private:
5293 RangeT odsOperands;
5294};
5295class TruncFOpAdaptor : public TruncFOpGenericAdaptor<::mlir::ValueRange> {
5296public:
5297 using TruncFOpGenericAdaptor::TruncFOpGenericAdaptor;
5298 TruncFOpAdaptor(TruncFOp op);
5299
5300 ::mlir::LogicalResult verify(::mlir::Location loc);
5301};
5302class 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> {
5303public:
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);
5336public:
5337};
5338} // namespace arith
5339} // namespace mlir
5340MLIR_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
5342namespace mlir {
5343namespace arith {
5344
5345//===----------------------------------------------------------------------===//
5346// ::mlir::arith::TruncIOp declarations
5347//===----------------------------------------------------------------------===//
5348
5349namespace detail {
5350class TruncIOpGenericAdaptorBase {
5351public:
5352protected:
5353 ::mlir::DictionaryAttr odsAttrs;
5354 ::std::optional<::mlir::OperationName> odsOpName;
5355 ::mlir::RegionRange odsRegions;
5356public:
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
5363template <typename RangeT>
5364class TruncIOpGenericAdaptor : public detail::TruncIOpGenericAdaptorBase {
5365 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
5366 using Base = detail::TruncIOpGenericAdaptorBase;
5367public:
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
5390private:
5391 RangeT odsOperands;
5392};
5393class TruncIOpAdaptor : public TruncIOpGenericAdaptor<::mlir::ValueRange> {
5394public:
5395 using TruncIOpGenericAdaptor::TruncIOpGenericAdaptor;
5396 TruncIOpAdaptor(TruncIOp op);
5397
5398 ::mlir::LogicalResult verify(::mlir::Location loc);
5399};
5400class 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> {
5401public:
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);
5436public:
5437};
5438} // namespace arith
5439} // namespace mlir
5440MLIR_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
5442namespace mlir {
5443namespace arith {
5444
5445//===----------------------------------------------------------------------===//
5446// ::mlir::arith::UIToFPOp declarations
5447//===----------------------------------------------------------------------===//
5448
5449namespace detail {
5450class UIToFPOpGenericAdaptorBase {
5451public:
5452protected:
5453 ::mlir::DictionaryAttr odsAttrs;
5454 ::std::optional<::mlir::OperationName> odsOpName;
5455 ::mlir::RegionRange odsRegions;
5456public:
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
5463template <typename RangeT>
5464class UIToFPOpGenericAdaptor : public detail::UIToFPOpGenericAdaptorBase {
5465 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
5466 using Base = detail::UIToFPOpGenericAdaptorBase;
5467public:
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
5490private:
5491 RangeT odsOperands;
5492};
5493class UIToFPOpAdaptor : public UIToFPOpGenericAdaptor<::mlir::ValueRange> {
5494public:
5495 using UIToFPOpGenericAdaptor::UIToFPOpGenericAdaptor;
5496 UIToFPOpAdaptor(UIToFPOp op);
5497
5498 ::mlir::LogicalResult verify(::mlir::Location loc);
5499};
5500class 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> {
5501public:
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);
5533public:
5534};
5535} // namespace arith
5536} // namespace mlir
5537MLIR_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
5539namespace mlir {
5540namespace arith {
5541
5542//===----------------------------------------------------------------------===//
5543// ::mlir::arith::XOrIOp declarations
5544//===----------------------------------------------------------------------===//
5545
5546namespace detail {
5547class XOrIOpGenericAdaptorBase {
5548public:
5549protected:
5550 ::mlir::DictionaryAttr odsAttrs;
5551 ::std::optional<::mlir::OperationName> odsOpName;
5552 ::mlir::RegionRange odsRegions;
5553public:
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
5560template <typename RangeT>
5561class XOrIOpGenericAdaptor : public detail::XOrIOpGenericAdaptorBase {
5562 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
5563 using Base = detail::XOrIOpGenericAdaptorBase;
5564public:
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
5591private:
5592 RangeT odsOperands;
5593};
5594class XOrIOpAdaptor : public XOrIOpGenericAdaptor<::mlir::ValueRange> {
5595public:
5596 using XOrIOpGenericAdaptor::XOrIOpGenericAdaptor;
5597 XOrIOpAdaptor(XOrIOp op);
5598
5599 ::mlir::LogicalResult verify(::mlir::Location loc);
5600};
5601class 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> {
5602public:
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);
5640public:
5641};
5642} // namespace arith
5643} // namespace mlir
5644MLIR_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
5646namespace mlir {
5647namespace arith {
5648
5649//===----------------------------------------------------------------------===//
5650// ::mlir::arith::SelectOp declarations
5651//===----------------------------------------------------------------------===//
5652
5653namespace detail {
5654class SelectOpGenericAdaptorBase {
5655public:
5656protected:
5657 ::mlir::DictionaryAttr odsAttrs;
5658 ::std::optional<::mlir::OperationName> odsOpName;
5659 ::mlir::RegionRange odsRegions;
5660public:
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
5667template <typename RangeT>
5668class SelectOpGenericAdaptor : public detail::SelectOpGenericAdaptorBase {
5669 using ValueT = ::llvm::detail::ValueOfRange<RangeT>;
5670 using Base = detail::SelectOpGenericAdaptorBase;
5671public:
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
5702private:
5703 RangeT odsOperands;
5704};
5705class SelectOpAdaptor : public SelectOpGenericAdaptor<::mlir::ValueRange> {
5706public:
5707 using SelectOpGenericAdaptor::SelectOpGenericAdaptor;
5708 SelectOpAdaptor(SelectOp op);
5709
5710 ::mlir::LogicalResult verify(::mlir::Location loc);
5711};
5712class 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> {
5713public:
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);
5754public:
5755};
5756} // namespace arith
5757} // namespace mlir
5758MLIR_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

/build/source/mlir/include/mlir/IR/OpDefinition.h

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
29namespace mlir {
30class Builder;
31class 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".
38class OptionalParseResult {
39public:
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
54private:
55 std::optional<ParseResult> impl;
56};
57
58// These functions are out-of-line utilities, which avoids them being template
59// instantiated/duplicated.
60namespace 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.
65void ensureRegionTerminator(
66 Region &region, OpBuilder &builder, Location loc,
67 function_ref<Operation *(OpBuilder &, Location)> buildTerminatorOp);
68void ensureRegionTerminator(
69 Region &region, 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.
76struct EmptyProperties {};
77
78/// Traits to detect whether an Operation defined a `Properties` type, otherwise
79/// it'll default to `EmptyProperties`.
80template <class Op, class = void>
81struct PropertiesSelector {
82 using type = EmptyProperties;
83};
84template <class Op>
85struct 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.
95class OpState {
96public:
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);
40
Called C++ object pointer is null
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.
197public:
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
206protected:
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) {}
28
Null pointer value stored to 'vecConstant.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
247private:
248 Operation *state;
249
250 /// Allow access to internal hook implementation methods.
251 friend RegisteredOperationName;
252};
253
254// Allow comparing operators.
255inline bool operator==(OpState lhs, OpState rhs) {
256 return lhs.getOperation() == rhs.getOperation();
257}
258inline bool operator!=(OpState lhs, OpState rhs) {
259 return lhs.getOperation() != rhs.getOperation();
260}
261
262raw_ostream &operator<<(raw_ostream &os, OpFoldResult ofr);
263
264/// This class represents a single result from folding an operation.
265class OpFoldResult : public PointerUnion<Attribute, Value> {
266 using PointerUnion<Attribute, Value>::PointerUnion;
267
268public:
269 void dump() const { llvm::errs() << *this << "\n"; }
270};
271
272/// Allow printing to a stream.
273inline 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.
282inline raw_ostream &operator<<(raw_ostream &os, OpState op) {
283 op.print(os, OpPrintingFlags().useLocalScope());
39
Calling 'OpState::print'
284 return os;
285}
286
287//===----------------------------------------------------------------------===//
288// Operation Trait Types
289//===----------------------------------------------------------------------===//
290
291namespace 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.
296namespace impl {
297OpFoldResult foldIdempotent(Operation *op);
298OpFoldResult foldInvolution(Operation *op);
299LogicalResult verifyZeroOperands(Operation *op);
300LogicalResult verifyOneOperand(Operation *op);
301LogicalResult verifyNOperands(Operation *op, unsigned numOperands);
302LogicalResult verifyIsIdempotent(Operation *op);
303LogicalResult verifyIsInvolution(Operation *op);
304LogicalResult verifyAtLeastNOperands(Operation *op, unsigned numOperands);
305LogicalResult verifyOperandsAreFloatLike(Operation *op);
306LogicalResult verifyOperandsAreSignlessIntegerLike(Operation *op);
307LogicalResult verifySameTypeOperands(Operation *op);
308LogicalResult verifyZeroRegions(Operation *op);
309LogicalResult verifyOneRegion(Operation *op);
310LogicalResult verifyNRegions(Operation *op, unsigned numRegions);
311LogicalResult verifyAtLeastNRegions(Operation *op, unsigned numRegions);
312LogicalResult verifyZeroResults(Operation *op);
313LogicalResult verifyOneResult(Operation *op);
314LogicalResult verifyNResults(Operation *op, unsigned numOperands);
315LogicalResult verifyAtLeastNResults(Operation *op, unsigned numOperands);
316LogicalResult verifySameOperandsShape(Operation *op);
317LogicalResult verifySameOperandsAndResultShape(Operation *op);
318LogicalResult verifySameOperandsElementType(Operation *op);
319LogicalResult verifySameOperandsAndResultElementType(Operation *op);
320LogicalResult verifySameOperandsAndResultType(Operation *op);
321LogicalResult verifyResultsAreBoolLike(Operation *op);
322LogicalResult verifyResultsAreFloatLike(Operation *op);
323LogicalResult verifyResultsAreSignlessIntegerLike(Operation *op);
324LogicalResult verifyIsTerminator(Operation *op);
325LogicalResult verifyZeroSuccessors(Operation *op);
326LogicalResult verifyOneSuccessor(Operation *op);
327LogicalResult verifyNSuccessors(Operation *op, unsigned numSuccessors);
328LogicalResult verifyAtLeastNSuccessors(Operation *op, unsigned numSuccessors);
329LogicalResult verifyValueSizeAttr(Operation *op, StringRef attrName,
330 StringRef valueGroupName,
331 size_t expectedCount);
332LogicalResult verifyOperandSizeAttr(Operation *op, StringRef sizeAttrName);
333LogicalResult verifyResultSizeAttr(Operation *op, StringRef sizeAttrName);
334LogicalResult verifyNoRegionArguments(Operation *op);
335LogicalResult verifyElementwise(Operation *op);
336LogicalResult 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.
341template <typename ConcreteType, template <typename> class TraitType>
342class TraitBase {
343protected:
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
354namespace detail {
355/// Utility trait base that provides accessors for derived traits that have
356/// multiple operands.
357template <typename ConcreteType, template <typename> class TraitType>
358struct 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.
399template <typename ConcreteType>
400class OpInvariants : public TraitBase<ConcreteType, OpInvariants> {
401public:
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.
409template <typename ConcreteType>
410class ZeroOperands : public TraitBase<ConcreteType, ZeroOperands> {
411public:
412 static LogicalResult verifyTrait(Operation *op) {
413 return impl::verifyZeroOperands(op);
414 }
415
416private:
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.
424template <typename ConcreteType>
425class OneOperand : public TraitBase<ConcreteType, OneOperand> {
426public:
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///
441template <unsigned N>
442class NOperands {
443public:
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///
461template <unsigned N>
462class AtLeastNOperands {
463public:
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.
476template <typename ConcreteType>
477class 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.
485template <typename ConcreteType>
486class ZeroRegions : public TraitBase<ConcreteType, ZeroRegions> {
487public:
488 static LogicalResult verifyTrait(Operation *op) {
489 return impl::verifyZeroRegions(op);
490 }
491};
492
493namespace detail {
494/// Utility trait base that provides accessors for derived traits that have
495/// multiple regions.
496template <typename ConcreteType, template <typename> class TraitType>
497struct 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.
517template <typename ConcreteType>
518class OneRegion : public TraitBase<ConcreteType, OneRegion> {
519public:
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.
536template <unsigned N>
537class NRegions {
538public:
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.
553template <unsigned N>
554class AtLeastNRegions {
555public:
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.
568template <typename ConcreteType>
569class 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.
577template <typename ConcreteType>
578class ZeroResults : public TraitBase<ConcreteType, ZeroResults> {
579public:
580 static LogicalResult verifyTrait(Operation *op) {
581 return impl::verifyZeroResults(op);
582 }
583};
584
585namespace detail {
586/// Utility trait base that provides accessors for derived traits that have
587/// multiple results.
588template <typename ConcreteType, template <typename> class TraitType>
589struct 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().
633template <typename ConcreteType>
634class OneResult : public TraitBase<ConcreteType, OneResult> {
635public:
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.
657template <typename ResultType>
658class OneTypedResult {
659public:
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///
684template <unsigned N>
685class NResults {
686public:
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///
704template <unsigned N>
705class AtLeastNResults {
706public:
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.
719template <typename ConcreteType>
720class 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.
728template <typename ConcreteType>
729class NoTerminator : public TraitBase<ConcreteType, NoTerminator> {};
730
731/// This class provides the API for ops that are known to be terminators.
732template <typename ConcreteType>
733class IsTerminator : public TraitBase<ConcreteType, IsTerminator> {
734public:
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.
742template <typename ConcreteType>
743class ZeroSuccessors : public TraitBase<ConcreteType, ZeroSuccessors> {
744public:
745 static LogicalResult verifyTrait(Operation *op) {
746 return impl::verifyZeroSuccessors(op);
747 }
748};
749
750namespace detail {
751/// Utility trait base that provides accessors for derived traits that have
752/// multiple successors.
753template <typename ConcreteType, template <typename> class TraitType>
754struct 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.
781template <typename ConcreteType>
782class OneSuccessor : public TraitBase<ConcreteType, OneSuccessor> {
783public:
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.
796template <unsigned N>
797class NSuccessors {
798public:
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.
813template <unsigned N>
814class AtLeastNSuccessors {
815public:
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.
829template <typename ConcreteType>
830class 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.
839template <typename ConcreteType>
840struct SingleBlock : public TraitBase<ConcreteType, SingleBlock> {
841public:
842 static LogicalResult verifyTrait(Operation *op) {
843 for (unsigned i = 0, e = op->getNumRegions(); i < e; ++i) {
844 Region &region = 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 &region = 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 &region.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`.
920template <typename TerminatorOpType>
921struct 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 &region = 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 &region, Builder &builder,
969 Location loc) {
970 ::mlir::impl::ensureRegionTerminator(region, builder, loc,
971 buildTerminator);
972 }
973 static void ensureTerminator(Region &region, 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`.
1014template <class T>
1015using 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.
1020template <class Op, bool hasTerminator =
1021 llvm::is_detected<has_implicit_terminator_t, Op>::value>
1022struct 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};
1028template <class Op>
1029struct 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.
1039template <typename ConcreteType>
1040class SameOperandsShape : public TraitBase<ConcreteType, SameOperandsShape> {
1041public:
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.
1050template <typename ConcreteType>
1051class SameOperandsAndResultShape
1052 : public TraitBase<ConcreteType, SameOperandsAndResultShape> {
1053public:
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///
1062template <typename ConcreteType>
1063class SameOperandsElementType
1064 : public TraitBase<ConcreteType, SameOperandsElementType> {
1065public:
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///
1074template <typename ConcreteType>
1075class SameOperandsAndResultElementType
1076 : public TraitBase<ConcreteType, SameOperandsAndResultElementType> {
1077public:
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.
1088template <typename ConcreteType>
1089class SameOperandsAndResultType
1090 : public TraitBase<ConcreteType, SameOperandsAndResultType> {
1091public:
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.
1099template <typename ConcreteType>
1100class ResultsAreBoolLike : public TraitBase<ConcreteType, ResultsAreBoolLike> {
1101public:
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.
1109template <typename ConcreteType>
1110class ResultsAreFloatLike
1111 : public TraitBase<ConcreteType, ResultsAreFloatLike> {
1112public:
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.
1120template <typename ConcreteType>
1121class ResultsAreSignlessIntegerLike
1122 : public TraitBase<ConcreteType, ResultsAreSignlessIntegerLike> {
1123public:
1124 static LogicalResult verifyTrait(Operation *op) {
1125 return impl::verifyResultsAreSignlessIntegerLike(op);
1126 }
1127};
1128
1129/// This class adds property that the operation is commutative.
1130template <typename ConcreteType>
1131class 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
1135template <typename ConcreteType>
1136class IsInvolution : public TraitBase<ConcreteType, IsInvolution> {
1137public:
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.
1158template <typename ConcreteType>
1159class IsIdempotent : public TraitBase<ConcreteType, IsIdempotent> {
1160public:
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.
1181template <typename ConcreteType>
1182class OperandsAreFloatLike
1183 : public TraitBase<ConcreteType, OperandsAreFloatLike> {
1184public:
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.
1192template <typename ConcreteType>
1193class OperandsAreSignlessIntegerLike
1194 : public TraitBase<ConcreteType, OperandsAreSignlessIntegerLike> {
1195public:
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.
1203template <typename ConcreteType>
1204class SameTypeOperands : public TraitBase<ConcreteType, SameTypeOperands> {
1205public:
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.
1214template <typename ConcreteType>
1215class ConstantLike : public TraitBase<ConcreteType, ConstantLike> {
1216public:
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.
1232template <typename ConcreteType>
1233class IsIsolatedFromAbove
1234 : public TraitBase<ConcreteType, IsIsolatedFromAbove> {
1235public:
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`.
1246template <typename ConcreteType>
1247class AffineScope : public TraitBase<ConcreteType, AffineScope> {
1248public:
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.
1261template <typename ConcreteType>
1262class AutomaticAllocationScope
1263 : public TraitBase<ConcreteType, AutomaticAllocationScope> {
1264public:
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
1274template <typename... ParentOpTypes>
1275struct 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.
1309template <typename ConcreteType>
1310class AttrSizedOperandSegments
1311 : public TraitBase<ConcreteType, AttrSizedOperandSegments> {
1312public:
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.
1324template <typename ConcreteType>
1325class AttrSizedResultSegments
1326 : public TraitBase<ConcreteType, AttrSizedResultSegments> {
1327public:
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
1338template <typename ConcrentType>
1339struct 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.
1350template <typename ConcrentType>
1351struct 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.
1386template <typename ConcreteType>
1387struct 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/// ```
1415template <typename ConcreteType>
1416struct 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.
1435template <typename ConcreteType>
1436struct 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/// ```
1476template <typename ConcreteType>
1477struct 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.
1489bool hasElementwiseMappableTraits(Operation *op);
1490
1491} // namespace OpTrait
1492
1493//===----------------------------------------------------------------------===//
1494// Internal Trait Utilities
1495//===----------------------------------------------------------------------===//
1496
1497namespace 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`.
1503template <template <typename T> class... Traits>
1504inline 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}
1511template <>
1512inline 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.
1521template <typename T, typename... Args>
1522using has_single_result_fold_trait = decltype(T::foldTrait(
1523 std::declval<Operation *>(), std::declval<ArrayRef<Attribute>>()));
1524template <typename T>
1525using 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.
1528template <typename T, typename... Args>
1529using has_fold_trait =
1530 decltype(T::foldTrait(std::declval<Operation *>(),
1531 std::declval<ArrayRef<Attribute>>(),
1532 std::declval<SmallVectorImpl<OpFoldResult> &>()));
1533template <typename T>
1534using detect_has_fold_trait = llvm::is_detected<has_fold_trait, T>;
1535/// Trait to check if T provides any `foldTrait` method.
1536template <typename T>
1537using 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.
1543template <typename Trait>
1544static std::enable_if_t<detect_has_single_result_fold_trait<Trait>::value,
1545 LogicalResult>
1546foldTrait(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.
1565template <typename Trait>
1566static std::enable_if_t<detect_has_fold_trait<Trait>::value, LogicalResult>
1567foldTrait(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}
1573template <typename Trait>
1574static inline std::enable_if_t<!detect_has_any_fold_trait<Trait>::value,
1575 LogicalResult>
1576foldTrait(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.
1582template <typename... Ts>
1583static 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.
1592template <typename T, typename... Args>
1593using has_verify_trait = decltype(T::verifyTrait(std::declval<Operation *>()));
1594template <typename T>
1595using detect_has_verify_trait = llvm::is_detected<has_verify_trait, T>;
1596
1597/// Trait to check if T provides a `verifyTrait` method.
1598template <typename T, typename... Args>
1599using has_verify_region_trait =
1600 decltype(T::verifyRegionTrait(std::declval<Operation *>()));
1601template <typename T>
1602using 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.
1606template <typename T>
1607std::enable_if_t<detect_has_verify_trait<T>::value, LogicalResult>
1608verifyTrait(Operation *op) {
1609 return T::verifyTrait(op);
1610}
1611template <typename T>
1612inline std::enable_if_t<!detect_has_verify_trait<T>::value, LogicalResult>
1613verifyTrait(Operation *) {
1614 return success();
1615}
1616
1617/// Given a set of traits, return the result of verifying the given operation.
1618template <typename... Ts>
1619LogicalResult verifyTraits(Operation *op) {
1620 return success((succeeded(verifyTrait<Ts>(op)) && ...));
1621}
1622
1623/// Verify the given trait if it provides a region verifier.
1624template <typename T>
1625std::enable_if_t<detect_has_verify_region_trait<T>::value, LogicalResult>
1626verifyRegionTrait(Operation *op) {
1627 return T::verifyRegionTrait(op);
1628}
1629template <typename T>
1630inline std::enable_if_t<!detect_has_verify_region_trait<T>::value,
1631 LogicalResult>
1632verifyRegionTrait(Operation *) {
1633 return success();
1634}
1635
1636/// Given a set of traits, return the result of verifying the regions of the
1637/// given operation.
1638template <typename... Ts>
1639LogicalResult 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.
1651template <typename ConcreteType, template <typename T> class... Traits>
1652class Op : public OpState, public Traits<ConcreteType>... {
1653public:
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) {}
26
Passing null pointer value via 1st parameter 'state'
27
Calling constructor for 'OpState'
29
Returning from constructor for 'OpState'
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
1758private:
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
1817public:
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
1825private:
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
1963public:
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
2004private:
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.
2046template <typename ConcreteType, typename Traits>
2047class OpInterface
2048 : public detail::Interface<ConcreteType, Operation *, Traits,
2049 Op<ConcreteType>, OpTrait::TraitBase> {
2050public:
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
2058protected:
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.
2090namespace impl {
2091/// Attempt to fold the given cast operation.
2092LogicalResult foldCastInterfaceOp(Operation *op,
2093 ArrayRef<Attribute> attrOperands,
2094 SmallVectorImpl<OpFoldResult> &foldResults);
2095/// Attempt to verify the given cast operation.
2096LogicalResult verifyCastInterfaceOp(
2097 Operation *op, function_ref<bool(TypeRange, TypeRange)> areCastCompatible);
2098} // namespace impl
2099} // namespace mlir
2100
2101namespace llvm {
2102
2103template <typename T>
2104struct 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