xref: /llvm-project/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td (revision bf68e9047f62c22ca87f9a4a7c59a46b3de06abb)
1//===-- SPIRVLogicalOps.td - MLIR SPIR-V Logical Ops -------*- tablegen -*-===//
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 contains arithmetic ops for the SPIR-V dialect. It corresponds
10// to "3.32.15. Relational and Logical Instructions" of the SPIR-V spec.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef MLIR_DIALECT_SPIRV_IR_LOGICAL_OPS
15#define MLIR_DIALECT_SPIRV_IR_LOGICAL_OPS
16
17include "mlir/Dialect/SPIRV/IR/SPIRVBase.td"
18include "mlir/Interfaces/SideEffectInterfaces.td"
19
20class SPIRV_LogicalBinaryOp<string mnemonic, Type operandsType,
21                            list<Trait> traits = []> :
22      // Result type is SPIRV_Bool.
23      SPIRV_BinaryOp<mnemonic, SPIRV_Bool, operandsType,
24                   !listconcat(traits, [
25                     Pure, SameTypeOperands,
26                     SameOperandsAndResultShape,
27                     TypesMatchWith<"type of result to correspond to the `i1` "
28                                    "equivalent of the operand",
29                                    "operand1", "result",
30                                    "getUnaryOpResultType($_self)"
31                     >])> {
32  let assemblyFormat = "$operand1 `,` $operand2 `:` type($operand1) attr-dict";
33}
34
35class SPIRV_LogicalUnaryOp<string mnemonic, Type operandType,
36                         list<Trait> traits = []> :
37      // Result type is SPIRV_Bool.
38      SPIRV_UnaryOp<mnemonic, SPIRV_Bool, operandType,
39                  !listconcat(traits, [
40                     Pure, SameTypeOperands, SameOperandsAndResultShape,
41                     TypesMatchWith<"type of result to correspond to the `i1` "
42                                    "equivalent of the operand",
43                                    "operand", "result",
44                                    "getUnaryOpResultType($_self)"
45                     >])> {
46  let assemblyFormat = "$operand `:` type($operand) attr-dict";
47}
48
49// -----
50
51def SPIRV_FOrdEqualOp : SPIRV_LogicalBinaryOp<"FOrdEqual", SPIRV_Float, [Commutative]> {
52  let summary = "Floating-point comparison for being ordered and equal.";
53
54  let description = [{
55    Result Type must be a scalar or vector of Boolean type.
56
57    The type of Operand 1 and Operand 2  must be a scalar or vector of
58    floating-point type.  They must have the same type, and they must have
59    the same number of components as Result Type.
60
61    Results are computed per component.
62
63    #### Example:
64
65    ```mlir
66    %4 = spirv.FOrdEqual %0, %1 : f32
67    %5 = spirv.FOrdEqual %2, %3 : vector<4xf32>
68    ```
69  }];
70}
71
72// -----
73
74def SPIRV_FOrdGreaterThanOp : SPIRV_LogicalBinaryOp<"FOrdGreaterThan", SPIRV_Float, []> {
75  let summary = [{
76    Floating-point comparison if operands are ordered and Operand 1 is
77    greater than  Operand 2.
78  }];
79
80  let description = [{
81    Result Type must be a scalar or vector of Boolean type.
82
83    The type of Operand 1 and Operand 2  must be a scalar or vector of
84    floating-point type.  They must have the same type, and they must have
85    the same number of components as Result Type.
86
87    Results are computed per component.
88
89    #### Example:
90
91    ```mlir
92    %4 = spirv.FOrdGreaterThan %0, %1 : f32
93    %5 = spirv.FOrdGreaterThan %2, %3 : vector<4xf32>
94    ```
95  }];
96}
97
98// -----
99
100def SPIRV_FOrdGreaterThanEqualOp : SPIRV_LogicalBinaryOp<"FOrdGreaterThanEqual", SPIRV_Float, []> {
101  let summary = [{
102    Floating-point comparison if operands are ordered and Operand 1 is
103    greater than or equal to Operand 2.
104  }];
105
106  let description = [{
107    Result Type must be a scalar or vector of Boolean type.
108
109    The type of Operand 1 and Operand 2  must be a scalar or vector of
110    floating-point type.  They must have the same type, and they must have
111    the same number of components as Result Type.
112
113    Results are computed per component.
114
115    #### Example:
116
117    ```mlir
118    %4 = spirv.FOrdGreaterThanEqual %0, %1 : f32
119    %5 = spirv.FOrdGreaterThanEqual %2, %3 : vector<4xf32>
120    ```
121  }];
122}
123
124// -----
125
126def SPIRV_FOrdLessThanOp : SPIRV_LogicalBinaryOp<"FOrdLessThan", SPIRV_Float, []> {
127  let summary = [{
128    Floating-point comparison if operands are ordered and Operand 1 is less
129    than Operand 2.
130  }];
131
132  let description = [{
133    Result Type must be a scalar or vector of Boolean type.
134
135    The type of Operand 1 and Operand 2  must be a scalar or vector of
136    floating-point type.  They must have the same type, and they must have
137    the same number of components as Result Type.
138
139    Results are computed per component.
140
141    #### Example:
142
143    ```mlir
144    %4 = spirv.FOrdLessThan %0, %1 : f32
145    %5 = spirv.FOrdLessThan %2, %3 : vector<4xf32>
146    ```
147  }];
148}
149
150// -----
151
152def SPIRV_FOrdLessThanEqualOp : SPIRV_LogicalBinaryOp<"FOrdLessThanEqual", SPIRV_Float, []> {
153  let summary = [{
154    Floating-point comparison if operands are ordered and Operand 1 is less
155    than or equal to Operand 2.
156  }];
157
158  let description = [{
159    Result Type must be a scalar or vector of Boolean type.
160
161    The type of Operand 1 and Operand 2  must be a scalar or vector of
162    floating-point type.  They must have the same type, and they must have
163    the same number of components as Result Type.
164
165    Results are computed per component.
166
167    #### Example:
168
169    ```mlir
170    %4 = spirv.FOrdLessThanEqual %0, %1 : f32
171    %5 = spirv.FOrdLessThanEqual %2, %3 : vector<4xf32>
172    ```
173  }];
174}
175
176// -----
177
178def SPIRV_FOrdNotEqualOp : SPIRV_LogicalBinaryOp<"FOrdNotEqual", SPIRV_Float, [Commutative]> {
179  let summary = "Floating-point comparison for being ordered and not equal.";
180
181  let description = [{
182    Result Type must be a scalar or vector of Boolean type.
183
184    The type of Operand 1 and Operand 2  must be a scalar or vector of
185    floating-point type.  They must have the same type, and they must have
186    the same number of components as Result Type.
187
188    Results are computed per component.
189
190    #### Example:
191
192    ```mlir
193    %4 = spirv.FOrdNotEqual %0, %1 : f32
194    %5 = spirv.FOrdNotEqual %2, %3 : vector<4xf32>
195    ```
196  }];
197}
198
199// -----
200
201def SPIRV_FUnordEqualOp : SPIRV_LogicalBinaryOp<"FUnordEqual", SPIRV_Float, [Commutative]> {
202  let summary = "Floating-point comparison for being unordered or equal.";
203
204  let description = [{
205    Result Type must be a scalar or vector of Boolean type.
206
207    The type of Operand 1 and Operand 2  must be a scalar or vector of
208    floating-point type.  They must have the same type, and they must have
209    the same number of components as Result Type.
210
211    Results are computed per component.
212
213    #### Example:
214
215    ```mlir
216    %4 = spirv.FUnordEqual %0, %1 : f32
217    %5 = spirv.FUnordEqual %2, %3 : vector<4xf32>
218    ```
219  }];
220}
221
222// -----
223
224def SPIRV_FUnordGreaterThanOp : SPIRV_LogicalBinaryOp<"FUnordGreaterThan", SPIRV_Float, []> {
225  let summary = [{
226    Floating-point comparison if operands are unordered or Operand 1 is
227    greater than  Operand 2.
228  }];
229
230  let description = [{
231    Result Type must be a scalar or vector of Boolean type.
232
233    The type of Operand 1 and Operand 2  must be a scalar or vector of
234    floating-point type.  They must have the same type, and they must have
235    the same number of components as Result Type.
236
237    Results are computed per component.
238
239    #### Example:
240
241    ```mlir
242    %4 = spirv.FUnordGreaterThan %0, %1 : f32
243    %5 = spirv.FUnordGreaterThan %2, %3 : vector<4xf32>
244    ```
245  }];
246}
247
248// -----
249
250def SPIRV_FUnordGreaterThanEqualOp : SPIRV_LogicalBinaryOp<"FUnordGreaterThanEqual", SPIRV_Float, []> {
251  let summary = [{
252    Floating-point comparison if operands are unordered or Operand 1 is
253    greater than or equal to Operand 2.
254  }];
255
256  let description = [{
257    Result Type must be a scalar or vector of Boolean type.
258
259    The type of Operand 1 and Operand 2  must be a scalar or vector of
260    floating-point type.  They must have the same type, and they must have
261    the same number of components as Result Type.
262
263    Results are computed per component.
264
265    #### Example:
266
267    ```mlir
268    %4 = spirv.FUnordGreaterThanEqual %0, %1 : f32
269    %5 = spirv.FUnordGreaterThanEqual %2, %3 : vector<4xf32>
270    ```
271  }];
272}
273
274// -----
275
276def SPIRV_FUnordLessThanOp : SPIRV_LogicalBinaryOp<"FUnordLessThan", SPIRV_Float, []> {
277  let summary = [{
278    Floating-point comparison if operands are unordered or Operand 1 is less
279    than Operand 2.
280  }];
281
282  let description = [{
283    Result Type must be a scalar or vector of Boolean type.
284
285    The type of Operand 1 and Operand 2  must be a scalar or vector of
286    floating-point type.  They must have the same type, and they must have
287    the same number of components as Result Type.
288
289    Results are computed per component.
290
291    #### Example:
292
293    ```mlir
294    %4 = spirv.FUnordLessThan %0, %1 : f32
295    %5 = spirv.FUnordLessThan %2, %3 : vector<4xf32>
296    ```
297  }];
298}
299
300// -----
301
302def SPIRV_FUnordLessThanEqualOp : SPIRV_LogicalBinaryOp<"FUnordLessThanEqual", SPIRV_Float, []> {
303  let summary = [{
304    Floating-point comparison if operands are unordered or Operand 1 is less
305    than or equal to Operand 2.
306  }];
307
308  let description = [{
309    Result Type must be a scalar or vector of Boolean type.
310
311    The type of Operand 1 and Operand 2  must be a scalar or vector of
312    floating-point type.  They must have the same type, and they must have
313    the same number of components as Result Type.
314
315    Results are computed per component.
316
317    #### Example:
318
319    ```mlir
320    %4 = spirv.FUnordLessThanEqual %0, %1 : f32
321    %5 = spirv.FUnordLessThanEqual %2, %3 : vector<4xf32>
322    ```
323  }];
324}
325
326// -----
327
328def SPIRV_FUnordNotEqualOp : SPIRV_LogicalBinaryOp<"FUnordNotEqual", SPIRV_Float, [Commutative]> {
329  let summary = "Floating-point comparison for being unordered or not equal.";
330
331  let description = [{
332    Result Type must be a scalar or vector of Boolean type.
333
334    The type of Operand 1 and Operand 2  must be a scalar or vector of
335    floating-point type.  They must have the same type, and they must have
336    the same number of components as Result Type.
337
338    Results are computed per component.
339
340    #### Example:
341
342    ```mlir
343    %4 = spirv.FUnordNotEqual %0, %1 : f32
344    %5 = spirv.FUnordNotEqual %2, %3 : vector<4xf32>
345    ```
346  }];
347}
348
349// -----
350
351def SPIRV_IEqualOp : SPIRV_LogicalBinaryOp<"IEqual",
352                                       SPIRV_Integer,
353                                       [Commutative, UsableInSpecConstantOp]> {
354  let summary = "Integer comparison for equality.";
355
356  let description = [{
357    Result Type must be a scalar or vector of Boolean type.
358
359    The type of Operand 1 and Operand 2  must be a scalar or vector of
360    integer type.  They must have the same component width, and they must
361    have the same number of components as Result Type.
362
363    Results are computed per component.
364
365    #### Example:
366
367    ```mlir
368    %4 = spirv.IEqual %0, %1 : i32
369    %5 = spirv.IEqual %2, %3 : vector<4xi32>
370    ```
371  }];
372
373  let hasFolder = 1;
374}
375
376// -----
377
378def SPIRV_INotEqualOp : SPIRV_LogicalBinaryOp<"INotEqual",
379                                          SPIRV_Integer,
380                                          [Commutative, UsableInSpecConstantOp]> {
381  let summary = "Integer comparison for inequality.";
382
383  let description = [{
384    Result Type must be a scalar or vector of Boolean type.
385
386    The type of Operand 1 and Operand 2  must be a scalar or vector of
387    integer type.  They must have the same component width, and they must
388    have the same number of components as Result Type.
389
390    Results are computed per component.
391
392    #### Example:
393
394    ```mlir
395    %4 = spirv.INotEqual %0, %1 : i32
396    %5 = spirv.INotEqual %2, %3 : vector<4xi32>
397
398    ```
399  }];
400
401  let hasFolder = 1;
402}
403
404// -----
405
406def SPIRV_IsInfOp : SPIRV_LogicalUnaryOp<"IsInf", SPIRV_Float, []> {
407  let summary = "Result is true if x is an IEEE Inf, otherwise result is false";
408
409  let description = [{
410    Result Type must be a scalar or vector of Boolean type.
411
412    x must be a scalar or vector of floating-point type.  It must have the
413    same number of components as Result Type.
414
415    Results are computed per component.
416
417    #### Example:
418
419    ```mlir
420    %2 = spirv.IsInf %0: f32
421    %3 = spirv.IsInf %1: vector<4xi32>
422    ```
423  }];
424}
425
426// -----
427
428def SPIRV_IsNanOp : SPIRV_LogicalUnaryOp<"IsNan", SPIRV_Float, []> {
429  let summary = [{
430    Result is true if x is an IEEE NaN, otherwise result is false.
431  }];
432
433  let description = [{
434    Result Type must be a scalar or vector of Boolean type.
435
436    x must be a scalar or vector of floating-point type.  It must have the
437    same number of components as Result Type.
438
439    Results are computed per component.
440
441    #### Example:
442
443    ```mlir
444    %2 = spirv.IsNan %0: f32
445    %3 = spirv.IsNan %1: vector<4xi32>
446    ```
447  }];
448}
449
450// -----
451
452def SPIRV_LogicalAndOp : SPIRV_LogicalBinaryOp<"LogicalAnd",
453                                           SPIRV_Bool,
454                                           [Commutative,
455                                            UsableInSpecConstantOp]> {
456  let summary = [{
457    Result is true if both Operand 1 and Operand 2 are true. Result is false
458    if either Operand 1 or Operand 2 are false.
459  }];
460
461  let description = [{
462    Result Type must be a scalar or vector of Boolean type.
463
464    The type of Operand 1 must be the same as Result Type.
465
466    The type of Operand 2 must be the same as Result Type.
467
468    Results are computed per component.
469
470    #### Example:
471
472    ```mlir
473    %2 = spirv.LogicalAnd %0, %1 : i1
474    %2 = spirv.LogicalAnd %0, %1 : vector<4xi1>
475    ```
476  }];
477
478  let hasFolder = 1;
479}
480
481// -----
482
483def SPIRV_LogicalEqualOp : SPIRV_LogicalBinaryOp<"LogicalEqual",
484                                             SPIRV_Bool,
485                                             [Commutative,
486                                              UsableInSpecConstantOp]> {
487  let summary = [{
488    Result is true if Operand 1 and Operand 2 have the same value. Result is
489    false if Operand 1 and Operand 2 have different values.
490  }];
491
492  let description = [{
493    Result Type must be a scalar or vector of Boolean type.
494
495    The type of Operand 1 must be the same as Result Type.
496
497    The type of Operand 2 must be the same as Result Type.
498
499    Results are computed per component.
500
501    #### Example:
502
503    ```mlir
504    %2 = spirv.LogicalEqual %0, %1 : i1
505    %2 = spirv.LogicalEqual %0, %1 : vector<4xi1>
506    ```
507  }];
508
509  let hasFolder = 1;
510}
511
512// -----
513
514def SPIRV_LogicalNotOp : SPIRV_LogicalUnaryOp<"LogicalNot",
515                                          SPIRV_Bool,
516                                          [UsableInSpecConstantOp]> {
517  let summary = [{
518    Result is true if Operand is false.  Result is false if Operand is true.
519  }];
520
521  let description = [{
522    Result Type must be a scalar or vector of Boolean type.
523
524    The type of Operand must be the same as Result Type.
525
526    Results are computed per component.
527
528    #### Example:
529
530    ```mlir
531    %2 = spirv.LogicalNot %0 : i1
532    %2 = spirv.LogicalNot %0 : vector<4xi1>
533    ```
534  }];
535
536  let hasCanonicalizer = 1;
537  let hasFolder = 1;
538}
539
540// -----
541
542def SPIRV_LogicalNotEqualOp : SPIRV_LogicalBinaryOp<"LogicalNotEqual",
543                                                SPIRV_Bool,
544                                                [Commutative,
545                                                 UsableInSpecConstantOp]> {
546  let summary = [{
547    Result is true if Operand 1 and Operand 2 have different values. Result
548    is false if Operand 1 and Operand 2 have the same value.
549  }];
550
551  let description = [{
552    Result Type must be a scalar or vector of Boolean type.
553
554    The type of Operand 1 must be the same as Result Type.
555
556    The type of Operand 2 must be the same as Result Type.
557
558    Results are computed per component.
559
560    #### Example:
561
562    ```mlir
563    %2 = spirv.LogicalNotEqual %0, %1 : i1
564    %2 = spirv.LogicalNotEqual %0, %1 : vector<4xi1>
565    ```
566  }];
567
568  let hasFolder = 1;
569}
570
571// -----
572
573def SPIRV_LogicalOrOp : SPIRV_LogicalBinaryOp<"LogicalOr",
574                                          SPIRV_Bool,
575                                          [Commutative,
576                                           UsableInSpecConstantOp]> {
577  let summary = [{
578    Result is true if either Operand 1 or Operand 2 is true. Result is false
579    if both Operand 1 and Operand 2 are false.
580  }];
581
582  let description = [{
583    Result Type must be a scalar or vector of Boolean type.
584
585    The type of Operand 1 must be the same as Result Type.
586
587    The type of Operand 2 must be the same as Result Type.
588
589    Results are computed per component.
590
591    #### Example:
592
593    ```mlir
594    %2 = spirv.LogicalOr %0, %1 : i1
595    %2 = spirv.LogicalOr %0, %1 : vector<4xi1>
596    ```
597  }];
598
599  let hasFolder = 1;
600}
601
602// -----
603
604def SPIRV_OrderedOp : SPIRV_LogicalBinaryOp<"Ordered", SPIRV_Float, [Commutative]> {
605  let summary = [{
606    Result is true if both x == x and y == y are true, where IEEE comparison
607    is used, otherwise result is false.
608  }];
609
610  let description = [{
611    Result Type must be a scalar or vector of Boolean type.
612
613    x must be a scalar or vector of floating-point type.  It must have the
614    same number of components as Result Type.
615
616    y must have the same type as x.
617
618    Results are computed per component.
619
620    #### Example:
621
622    ```mlir
623    %4 = spirv.Ordered %0, %1 : f32
624    %5 = spirv.Ordered %2, %3 : vector<4xf32>
625    ```
626  }];
627
628  let availability = [
629    MinVersion<SPIRV_V_1_0>,
630    MaxVersion<SPIRV_V_1_6>,
631    Extension<[]>,
632    Capability<[SPIRV_C_Kernel]>
633  ];
634}
635
636// -----
637
638def SPIRV_SGreaterThanOp : SPIRV_LogicalBinaryOp<"SGreaterThan",
639                                             SPIRV_Integer,
640                                             [UsableInSpecConstantOp, SignedOp]> {
641  let summary = [{
642    Signed-integer comparison if Operand 1 is greater than  Operand 2.
643  }];
644
645  let description = [{
646    Result Type must be a scalar or vector of Boolean type.
647
648    The type of Operand 1 and Operand 2  must be a scalar or vector of
649    integer type.  They must have the same component width, and they must
650    have the same number of components as Result Type.
651
652    Results are computed per component.
653
654    #### Example:
655
656    ```mlir
657    %4 = spirv.SGreaterThan %0, %1 : i32
658    %5 = spirv.SGreaterThan %2, %3 : vector<4xi32>
659
660    ```
661  }];
662
663  let hasFolder = 1;
664}
665
666// -----
667
668def SPIRV_SGreaterThanEqualOp : SPIRV_LogicalBinaryOp<"SGreaterThanEqual",
669                                                  SPIRV_Integer,
670                                                  [UsableInSpecConstantOp,
671                                                   SignedOp]> {
672  let summary = [{
673    Signed-integer comparison if Operand 1 is greater than or equal to
674    Operand 2.
675  }];
676
677  let description = [{
678    Result Type must be a scalar or vector of Boolean type.
679
680    The type of Operand 1 and Operand 2  must be a scalar or vector of
681    integer type.  They must have the same component width, and they must
682    have the same number of components as Result Type.
683
684    Results are computed per component.
685
686    #### Example:
687
688    ```mlir
689    %4 = spirv.SGreaterThanEqual %0, %1 : i32
690    %5 = spirv.SGreaterThanEqual %2, %3 : vector<4xi32>
691    ```
692  }];
693
694  let hasFolder = 1;
695}
696
697// -----
698
699def SPIRV_SLessThanOp : SPIRV_LogicalBinaryOp<"SLessThan",
700                                          SPIRV_Integer,
701                                          [UsableInSpecConstantOp, SignedOp]> {
702  let summary = [{
703    Signed-integer comparison if Operand 1 is less than Operand 2.
704  }];
705
706  let description = [{
707    Result Type must be a scalar or vector of Boolean type.
708
709    The type of Operand 1 and Operand 2  must be a scalar or vector of
710    integer type.  They must have the same component width, and they must
711    have the same number of components as Result Type.
712
713    Results are computed per component.
714
715    #### Example:
716
717    ```mlir
718    %4 = spirv.SLessThan %0, %1 : i32
719    %5 = spirv.SLessThan %2, %3 : vector<4xi32>
720
721    ```
722  }];
723
724  let hasFolder = 1;
725}
726
727// -----
728
729def SPIRV_SLessThanEqualOp : SPIRV_LogicalBinaryOp<"SLessThanEqual",
730                                               SPIRV_Integer,
731                                               [UsableInSpecConstantOp,
732                                                SignedOp]> {
733  let summary = [{
734    Signed-integer comparison if Operand 1 is less than or equal to Operand
735    2.
736  }];
737
738  let description = [{
739    Result Type must be a scalar or vector of Boolean type.
740
741    The type of Operand 1 and Operand 2  must be a scalar or vector of
742    integer type.  They must have the same component width, and they must
743    have the same number of components as Result Type.
744
745    Results are computed per component.
746
747    #### Example:
748
749    ```mlir
750    %4 = spirv.SLessThanEqual %0, %1 : i32
751    %5 = spirv.SLessThanEqual %2, %3 : vector<4xi32>
752    ```
753  }];
754
755  let hasFolder = 1;
756}
757
758// -----
759
760def SPIRV_SelectOp : SPIRV_Op<"Select",
761    [Pure,
762     AllTypesMatch<["true_value", "false_value", "result"]>,
763     UsableInSpecConstantOp,
764     DeclareOpInterfaceMethods<SelectLikeOpInterface>]> {
765  let summary = [{
766    Select between two objects. Before version 1.4, results are only
767    computed per component.
768  }];
769
770  let description = [{
771    Before version 1.4, Result Type must be a pointer, scalar, or vector.
772
773    The types of Object 1 and Object 2 must be the same as Result Type.
774
775    Condition must be a scalar or vector of Boolean type.
776
777    If Condition is a scalar and true, the result is Object 1. If Condition
778    is a scalar and false, the result is Object 2.
779
780    If Condition is a vector, Result Type must be a vector with the same
781    number of components as Condition and the result is a mix of Object 1
782    and Object 2: When a component of Condition is true, the corresponding
783    component in the result is taken from Object 1, otherwise it is taken
784    from Object 2.
785
786    #### Example:
787
788    ```mlir
789    %3 = spirv.Select %0, %1, %2 : i1, f32
790    %3 = spirv.Select %0, %1, %2 : i1, vector<3xi32>
791    %3 = spirv.Select %0, %1, %2 : vector<3xi1>, vector<3xf32>
792    ```
793  }];
794
795  let arguments = (ins
796    SPIRV_ScalarOrVectorOf<SPIRV_Bool>:$condition,
797    SPIRV_SelectType:$true_value,
798    SPIRV_SelectType:$false_value
799  );
800
801  let results = (outs
802    SPIRV_SelectType:$result
803  );
804
805  let assemblyFormat = [{
806    operands attr-dict `:` type($condition) `,` type($result)
807  }];
808
809  // These ops require dynamic availability specification based on operand and
810  // result types.
811  bit autogenAvailability = 0;
812
813  let hasFolder = 1;
814}
815
816// -----
817
818def SPIRV_UGreaterThanOp : SPIRV_LogicalBinaryOp<"UGreaterThan",
819                                             SPIRV_Integer,
820                                             [UnsignedOp,
821                                              UsableInSpecConstantOp]> {
822  let summary = [{
823    Unsigned-integer comparison if Operand 1 is greater than  Operand 2.
824  }];
825
826  let description = [{
827    Result Type must be a scalar or vector of Boolean type.
828
829    The type of Operand 1 and Operand 2  must be a scalar or vector of
830    integer type.  They must have the same component width, and they must
831    have the same number of components as Result Type.
832
833    Results are computed per component.
834
835    #### Example:
836
837    ```mlir
838    %4 = spirv.UGreaterThan %0, %1 : i32
839    %5 = spirv.UGreaterThan %2, %3 : vector<4xi32>
840    ```
841  }];
842
843  let hasFolder = 1;
844}
845
846// -----
847
848def SPIRV_UGreaterThanEqualOp : SPIRV_LogicalBinaryOp<"UGreaterThanEqual",
849                                                  SPIRV_Integer,
850                                                  [UnsignedOp,
851                                                   UsableInSpecConstantOp]> {
852  let summary = [{
853    Unsigned-integer comparison if Operand 1 is greater than or equal to
854    Operand 2.
855  }];
856
857  let description = [{
858    Result Type must be a scalar or vector of Boolean type.
859
860    The type of Operand 1 and Operand 2  must be a scalar or vector of
861    integer type.  They must have the same component width, and they must
862    have the same number of components as Result Type.
863
864    Results are computed per component.
865
866    #### Example:
867
868    ```mlir
869    %4 = spirv.UGreaterThanEqual %0, %1 : i32
870    %5 = spirv.UGreaterThanEqual %2, %3 : vector<4xi32>
871    ```
872  }];
873
874  let hasFolder = 1;
875}
876
877// -----
878
879def SPIRV_ULessThanOp : SPIRV_LogicalBinaryOp<"ULessThan",
880                                          SPIRV_Integer,
881                                          [UnsignedOp, UsableInSpecConstantOp]> {
882  let summary = [{
883    Unsigned-integer comparison if Operand 1 is less than Operand 2.
884  }];
885
886  let description = [{
887    Result Type must be a scalar or vector of Boolean type.
888
889    The type of Operand 1 and Operand 2  must be a scalar or vector of
890    integer type.  They must have the same component width, and they must
891    have the same number of components as Result Type.
892
893    Results are computed per component.
894
895    #### Example:
896
897    ```mlir
898    %4 = spirv.ULessThan %0, %1 : i32
899    %5 = spirv.ULessThan %2, %3 : vector<4xi32>
900    ```
901  }];
902
903  let hasFolder = 1;
904}
905
906// -----
907
908def SPIRV_UnorderedOp : SPIRV_LogicalBinaryOp<"Unordered", SPIRV_Float, [Commutative]> {
909  let summary = [{
910    Result is true if either x or y is an IEEE NaN, otherwise result is
911    false.
912  }];
913
914  let description = [{
915    Result Type must be a scalar or vector of Boolean type.
916
917    x must be a scalar or vector of floating-point type.  It must have the
918    same number of components as Result Type.
919
920    y must have the same type as x.
921
922    Results are computed per component.
923
924    #### Example:
925
926    ```mlir
927    %4 = spirv.Unordered %0, %1 : f32
928    %5 = spirv.Unordered %2, %3 : vector<4xf32>
929    ```
930  }];
931
932  let availability = [
933    MinVersion<SPIRV_V_1_0>,
934    MaxVersion<SPIRV_V_1_6>,
935    Extension<[]>,
936    Capability<[SPIRV_C_Kernel]>
937  ];
938}
939
940// -----
941
942def SPIRV_ULessThanEqualOp : SPIRV_LogicalBinaryOp<"ULessThanEqual",
943                                               SPIRV_Integer,
944                                               [UnsignedOp,
945                                                UsableInSpecConstantOp]> {
946  let summary = [{
947    Unsigned-integer comparison if Operand 1 is less than or equal to
948    Operand 2.
949  }];
950
951  let description = [{
952    Result Type must be a scalar or vector of Boolean type.
953
954    The type of Operand 1 and Operand 2  must be a scalar or vector of
955    integer type.  They must have the same component width, and they must
956    have the same number of components as Result Type.
957
958    Results are computed per component.
959
960    #### Example:
961
962    ```mlir
963    %4 = spirv.ULessThanEqual %0, %1 : i32
964    %5 = spirv.ULessThanEqual %2, %3 : vector<4xi32>
965    ```
966  }];
967
968  let hasFolder = 1;
969}
970
971#endif // MLIR_DIALECT_SPIRV_IR_LOGICAL_OPS
972