• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//===-- SPIRVBitOps.td - MLIR SPIR-V Bit 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 bit ops for the SPIR-V dialect. It corresponds
10// to "3.32.13. Bit Instructions" of the SPIR-V specification.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SPIRV_BIT_OPS
15#define SPIRV_BIT_OPS
16
17include "mlir/Dialect/SPIRV/SPIRVBase.td"
18include "mlir/Interfaces/SideEffectInterfaces.td"
19
20class SPV_BitBinaryOp<string mnemonic, list<OpTrait> traits = []> :
21      // All the operands type used in bit instructions are SPV_Integer.
22      SPV_BinaryOp<mnemonic, SPV_Integer, SPV_Integer,
23                   !listconcat(traits,
24                               [NoSideEffect, SameOperandsAndResultType])>;
25
26class SPV_BitFieldExtractOp<string mnemonic, list<OpTrait> traits = []> :
27      SPV_Op<mnemonic, !listconcat(traits,
28             [NoSideEffect, AllTypesMatch<["base", "result"]>])> {
29  let arguments = (ins
30    SPV_ScalarOrVectorOf<SPV_Integer>:$base,
31    SPV_Integer:$offset,
32    SPV_Integer:$count
33  );
34
35  let results = (outs
36    SPV_ScalarOrVectorOf<SPV_Integer>:$result
37  );
38
39  let verifier = [{ return success(); }];
40
41  let assemblyFormat = [{
42    operands attr-dict `:` type($base) `,` type($offset) `,` type($count)
43  }];
44}
45
46class SPV_BitUnaryOp<string mnemonic, list<OpTrait> traits = []> :
47      SPV_UnaryOp<mnemonic, SPV_Integer, SPV_Integer,
48                   !listconcat(traits,
49                               [NoSideEffect, SameOperandsAndResultType])>;
50
51class SPV_ShiftOp<string mnemonic, list<OpTrait> traits = []> :
52      SPV_BinaryOp<mnemonic, SPV_Integer, SPV_Integer,
53                   !listconcat(traits,
54                               [NoSideEffect, SameOperandsAndResultShape])> {
55  let parser = [{ return ::parseShiftOp(parser, result); }];
56  let printer = [{ ::printShiftOp(this->getOperation(), p); }];
57  let verifier = [{ return ::verifyShiftOp(this->getOperation()); }];
58}
59
60// -----
61
62def SPV_BitCountOp : SPV_BitUnaryOp<"BitCount", []> {
63  let summary = "Count the number of set bits in an object.";
64
65  let description = [{
66     Results are computed per component.
67
68    Result Type must be a scalar or vector of integer type.  The components
69    must be wide enough to hold the unsigned Width of Base as an unsigned
70    value. That is, no sign bit is needed or counted when checking for a
71    wide enough result width.
72
73    Base must be a scalar or vector of integer type.  It must have the same
74    number of components as Result Type.
75
76    The result is the unsigned value that is the number of bits in Base that
77    are 1.
78
79    <!-- End of AutoGen section -->
80
81    ```
82    integer-scalar-vector-type ::= integer-type |
83                                  `vector<` integer-literal `x` integer-type `>`
84    bitcount-op ::= ssa-id `=` `spv.BitCount` ssa-use
85                               `:` integer-scalar-vector-type
86    ```
87
88    #### Example:
89
90    ```mlir
91    %2 = spv.BitCount %0: i32
92    %3 = spv.BitCount %1: vector<4xi32>
93    ```
94  }];
95
96  let availability = [
97    MinVersion<SPV_V_1_0>,
98    MaxVersion<SPV_V_1_5>,
99    Extension<[]>,
100    Capability<[]>
101  ];
102}
103
104// -----
105
106def SPV_BitFieldInsertOp : SPV_Op<"BitFieldInsert",
107    [NoSideEffect, AllTypesMatch<["base", "insert", "result"]>]> {
108  let summary = [{
109    Make a copy of an object, with a modified bit field that comes from
110    another object.
111  }];
112
113  let description = [{
114     Results are computed per component.
115
116    Result Type must be a scalar or vector of integer type.
117
118     The type of Base and Insert must be the same as Result Type.
119
120    Any result bits numbered outside [Offset, Offset + Count -  1]
121    (inclusive) will come from the corresponding bits in Base.
122
123    Any result bits numbered in [Offset, Offset + Count -  1] come, in
124    order, from the bits numbered [0, Count - 1] of Insert.
125
126    Count  must be an integer type scalar. Count is the number of bits taken
127    from Insert. It will be consumed as an unsigned value. Count can be 0,
128    in which case the result will be Base.
129
130    Offset  must be an integer type scalar. Offset is the lowest-order bit
131    of the bit field.  It will be consumed as an unsigned value.
132
133    The resulting value is undefined if Count or Offset or their sum is
134    greater than the number of bits in the result.
135
136    <!-- End of AutoGen section -->
137
138    ```
139    integer-scalar-vector-type ::= integer-type |
140                                  `vector<` integer-literal `x` integer-type `>`
141    bitfield-insert-op ::= ssa-id `=` `spv.BitFieldInsert` ssa-use `,` ssa-use
142                                      `,` ssa-use `,` ssa-use
143                                      `:` integer-scalar-vector-type
144                                      `,` integer-type `,` integer-type
145    ```
146
147    #### Example:
148
149    ```mlir
150    %0 = spv.BitFieldInsert %base, %insert, %offset, %count : vector<3xi32>, i8, i8
151    ```
152  }];
153
154  let availability = [
155    MinVersion<SPV_V_1_0>,
156    MaxVersion<SPV_V_1_5>,
157    Extension<[]>,
158    Capability<[SPV_C_Shader]>
159  ];
160
161  let arguments = (ins
162    SPV_ScalarOrVectorOf<SPV_Integer>:$base,
163    SPV_ScalarOrVectorOf<SPV_Integer>:$insert,
164    SPV_Integer:$offset,
165    SPV_Integer:$count
166  );
167
168  let results = (outs
169    SPV_ScalarOrVectorOf<SPV_Integer>:$result
170  );
171
172  let verifier = [{ return success(); }];
173
174  let assemblyFormat = [{
175    operands attr-dict `:` type($base) `,` type($offset) `,` type($count)
176  }];
177}
178
179// -----
180
181def SPV_BitFieldSExtractOp : SPV_BitFieldExtractOp<"BitFieldSExtract", []> {
182  let summary = "Extract a bit field from an object, with sign extension.";
183
184  let description = [{
185     Results are computed per component.
186
187    Result Type must be a scalar or vector of integer type.
188
189     The type of Base must be the same as Result Type.
190
191    If Count is greater than 0: The bits of Base numbered in [Offset, Offset
192    + Count -  1] (inclusive) become the bits numbered [0, Count - 1] of the
193    result. The remaining bits of the result will all be the same as bit
194    Offset + Count -  1 of Base.
195
196    Count  must be an integer type scalar. Count is the number of bits
197    extracted from Base. It will be consumed as an unsigned value. Count can
198    be 0, in which case the result will be 0.
199
200    Offset  must be an integer type scalar. Offset is the lowest-order bit
201    of the bit field to extract from Base.  It will be consumed as an
202    unsigned value.
203
204    The resulting value is undefined if Count or Offset or their sum is
205    greater than the number of bits in the result.
206
207    <!-- End of AutoGen section -->
208
209    ```
210    integer-scalar-vector-type ::= integer-type |
211                                  `vector<` integer-literal `x` integer-type `>`
212    bitfield-extract-s-op ::= ssa-id `=` `spv.BitFieldSExtract` ssa-use
213                                         `,` ssa-use `,` ssa-use
214                                         `:` integer-scalar-vector-type
215                                         `,` integer-type `,` integer-type
216    ```
217
218    #### Example:
219
220    ```mlir
221    %0 = spv.BitFieldSExtract %base, %offset, %count : vector<3xi32>, i8, i8
222    ```
223  }];
224
225  let availability = [
226    MinVersion<SPV_V_1_0>,
227    MaxVersion<SPV_V_1_5>,
228    Extension<[]>,
229    Capability<[SPV_C_Shader]>
230  ];
231}
232
233// -----
234
235def SPV_BitFieldUExtractOp : SPV_BitFieldExtractOp<"BitFieldUExtract", []> {
236  let summary = "Extract a bit field from an object, without sign extension.";
237
238  let description = [{
239    The semantics are the same as with OpBitFieldSExtract with the exception
240    that there is no sign extension. The remaining bits of the result will
241    all be 0.
242
243    <!-- End of AutoGen section -->
244
245    ```
246    integer-scalar-vector-type ::= integer-type |
247                                  `vector<` integer-literal `x` integer-type `>`
248    bitfield-extract-u-op ::= ssa-id `=` `spv.BitFieldUExtract` ssa-use
249                                         `,` ssa-use `,` ssa-use
250                                         `:` integer-scalar-vector-type
251                                         `,` integer-type `,` integer-type
252    ```
253
254    #### Example:
255
256    ```mlir
257    %0 = spv.BitFieldUExtract %base, %offset, %count : vector<3xi32>, i8, i8
258    ```
259  }];
260
261  let availability = [
262    MinVersion<SPV_V_1_0>,
263    MaxVersion<SPV_V_1_5>,
264    Extension<[]>,
265    Capability<[SPV_C_Shader]>
266  ];
267}
268
269// -----
270
271def SPV_BitReverseOp : SPV_BitUnaryOp<"BitReverse", []> {
272  let summary = "Reverse the bits in an object.";
273
274  let description = [{
275     Results are computed per component.
276
277    Result Type must be a scalar or vector of integer type.
278
279     The type of Base must be the same as Result Type.
280
281    The bit-number n of the result will be taken from bit-number Width - 1 -
282    n of Base, where Width is the OpTypeInt operand of the Result Type.
283
284    <!-- End of AutoGen section -->
285
286    ```
287    integer-scalar-vector-type ::= integer-type |
288                                   `vector<` integer-literal `x` integer-type `>`
289    bitreverse-op ::= ssa-id `=` `spv.BitReverse` ssa-use
290                                 `:` integer-scalar-vector-type
291    ```
292
293    #### Example:
294
295    ```mlir
296    %2 = spv.BitReverse %0 : i32
297    %3 = spv.BitReverse %1 : vector<4xi32>
298    ```
299  }];
300
301  let availability = [
302    MinVersion<SPV_V_1_0>,
303    MaxVersion<SPV_V_1_5>,
304    Extension<[]>,
305    Capability<[SPV_C_Shader]>
306  ];
307}
308
309// -----
310
311def SPV_BitwiseAndOp : SPV_BitBinaryOp<"BitwiseAnd", [Commutative]> {
312  let summary = [{
313    Result is 1 if both Operand 1 and Operand 2 are 1. Result is 0 if either
314    Operand 1 or Operand 2 are 0.
315  }];
316
317  let description = [{
318     Results are computed per component, and within each component, per bit.
319
320    Result Type must be a scalar or vector of integer type.  The type of
321    Operand 1 and Operand 2  must be a scalar or vector of integer type.
322    They must have the same number of components as Result Type. They must
323    have the same component width as Result Type.
324
325    <!-- End of AutoGen section -->
326
327    ```
328    integer-scalar-vector-type ::= integer-type |
329                                  `vector<` integer-literal `x` integer-type `>`
330    bitwise-and-op ::= ssa-id `=` `spv.BitwiseAnd` ssa-use, ssa-use
331                                  `:` integer-scalar-vector-type
332    ```
333
334    #### Example:
335
336    ```mlir
337    %2 = spv.BitwiseAnd %0, %1 : i32
338    %2 = spv.BitwiseAnd %0, %1 : vector<4xi32>
339    ```
340  }];
341
342  let availability = [
343    MinVersion<SPV_V_1_0>,
344    MaxVersion<SPV_V_1_5>,
345    Extension<[]>,
346    Capability<[]>
347  ];
348}
349
350// -----
351
352def SPV_BitwiseOrOp : SPV_BitBinaryOp<"BitwiseOr", [Commutative]> {
353  let summary = [{
354    Result is 1 if either Operand 1 or Operand 2 is 1. Result is 0 if both
355    Operand 1 and Operand 2 are 0.
356  }];
357
358  let description = [{
359     Results are computed per component, and within each component, per bit.
360
361    Result Type must be a scalar or vector of integer type.  The type of
362    Operand 1 and Operand 2  must be a scalar or vector of integer type.
363    They must have the same number of components as Result Type. They must
364    have the same component width as Result Type.
365
366    <!-- End of AutoGen section -->
367
368    ```
369    integer-scalar-vector-type ::= integer-type |
370                                  `vector<` integer-literal `x` integer-type `>`
371    bitwise-or-op ::= ssa-id `=` `spv.BitwiseOr` ssa-use, ssa-use
372                                  `:` integer-scalar-vector-type
373    ```
374
375    #### Example:
376
377    ```mlir
378    %2 = spv.BitwiseOr %0, %1 : i32
379    %2 = spv.BitwiseOr %0, %1 : vector<4xi32>
380    ```
381  }];
382
383  let availability = [
384    MinVersion<SPV_V_1_0>,
385    MaxVersion<SPV_V_1_5>,
386    Extension<[]>,
387    Capability<[]>
388  ];
389}
390
391// -----
392
393def SPV_BitwiseXorOp : SPV_BitBinaryOp<"BitwiseXor", [Commutative]> {
394  let summary = [{
395    Result is 1 if exactly one of Operand 1 or Operand 2 is 1. Result is 0
396    if Operand 1 and Operand 2 have the same value.
397  }];
398
399  let description = [{
400     Results are computed per component, and within each component, per bit.
401
402    Result Type must be a scalar or vector of integer type.  The type of
403    Operand 1 and Operand 2  must be a scalar or vector of integer type.
404    They must have the same number of components as Result Type. They must
405    have the same component width as Result Type.
406
407    <!-- End of AutoGen section -->
408
409    ```
410    integer-scalar-vector-type ::= integer-type |
411                                  `vector<` integer-literal `x` integer-type `>`
412    bitwise-xor-op ::= ssa-id `=` `spv.BitwiseXor` ssa-use, ssa-use
413                                  `:` integer-scalar-vector-type
414    ```
415
416    #### Example:
417
418    ```mlir
419    %2 = spv.BitwiseXor %0, %1 : i32
420    %2 = spv.BitwiseXor %0, %1 : vector<4xi32>
421    ```
422  }];
423
424  let availability = [
425    MinVersion<SPV_V_1_0>,
426    MaxVersion<SPV_V_1_5>,
427    Extension<[]>,
428    Capability<[]>
429  ];
430}
431
432// -----
433
434def SPV_ShiftLeftLogicalOp : SPV_ShiftOp<"ShiftLeftLogical", []> {
435  let summary = [{
436    Shift the bits in Base left by the number of bits specified in Shift.
437    The least-significant bits will be zero filled.
438  }];
439
440  let description = [{
441    Result Type must be a scalar or vector of integer type.
442
443     The type of each Base and Shift must be a scalar or vector of integer
444    type. Base and Shift must have the same number of components.  The
445    number of components and bit width of the type of Base must be the same
446    as in Result Type.
447
448    Shift is treated as unsigned. The result is undefined if Shift is
449    greater than or equal to the bit width of the components of Base.
450
451    The number of components and bit width of Result Type must match those
452    Base type. All types must be integer types.
453
454     Results are computed per component.
455
456    <!-- End of AutoGen section -->
457
458    ```
459    integer-scalar-vector-type ::= integer-type |
460                                  `vector<` integer-literal `x` integer-type `>`
461    shift-left-logical-op ::= ssa-id `=` `spv.ShiftLeftLogical`
462                                          ssa-use `,` ssa-use `:`
463                                          integer-scalar-vector-type `,`
464                                          integer-scalar-vector-type
465    ```
466
467    #### Example:
468
469    ```mlir
470    %2 = spv.ShiftLeftLogical %0, %1 : i32, i16
471    %5 = spv.ShiftLeftLogical %3, %4 : vector<3xi32>, vector<3xi16>
472    ```
473  }];
474
475  let availability = [
476    MinVersion<SPV_V_1_0>,
477    MaxVersion<SPV_V_1_5>,
478    Extension<[]>,
479    Capability<[]>
480  ];
481}
482
483// -----
484
485def SPV_ShiftRightArithmeticOp : SPV_ShiftOp<"ShiftRightArithmetic", []> {
486  let summary = [{
487    Shift the bits in Base right by the number of bits specified in Shift.
488    The most-significant bits will be filled with the sign bit from Base.
489  }];
490
491  let description = [{
492    Result Type must be a scalar or vector of integer type.
493
494     The type of each Base and Shift must be a scalar or vector of integer
495    type. Base and Shift must have the same number of components.  The
496    number of components and bit width of the type of Base must be the same
497    as in Result Type.
498
499    Shift is treated as unsigned. The result is undefined if Shift is
500    greater than or equal to the bit width of the components of Base.
501
502     Results are computed per component.
503
504    <!-- End of AutoGen section -->
505
506    ```
507    integer-scalar-vector-type ::= integer-type |
508                                  `vector<` integer-literal `x` integer-type `>`
509    shift-right-arithmetic-op ::= ssa-id `=` `spv.ShiftRightArithmetic`
510                                              ssa-use `,` ssa-use `:`
511                                              integer-scalar-vector-type `,`
512                                              integer-scalar-vector-type
513    ```
514
515    #### Example:
516
517    ```mlir
518    %2 = spv.ShiftRightArithmetic %0, %1 : i32, i16
519    %5 = spv.ShiftRightArithmetic %3, %4 : vector<3xi32>, vector<3xi16>
520    ```
521  }];
522
523  let availability = [
524    MinVersion<SPV_V_1_0>,
525    MaxVersion<SPV_V_1_5>,
526    Extension<[]>,
527    Capability<[]>
528  ];
529}
530
531// -----
532
533def SPV_ShiftRightLogicalOp : SPV_ShiftOp<"ShiftRightLogical", []> {
534  let summary = [{
535    Shift the bits in Base right by the number of bits specified in Shift.
536    The most-significant bits will be zero filled.
537  }];
538
539  let description = [{
540    Result Type must be a scalar or vector of integer type.
541
542     The type of each Base and Shift must be a scalar or vector of integer
543    type. Base and Shift must have the same number of components.  The
544    number of components and bit width of the type of Base must be the same
545    as in Result Type.
546
547    Shift is consumed as an unsigned integer. The result is undefined if
548    Shift is greater than or equal to the bit width of the components of
549    Base.
550
551     Results are computed per component.
552
553    <!-- End of AutoGen section -->
554
555    ```
556    integer-scalar-vector-type ::= integer-type |
557                                  `vector<` integer-literal `x` integer-type `>`
558    shift-right-logical-op ::= ssa-id `=` `spv.ShiftRightLogical`
559                                           ssa-use `,` ssa-use `:`
560                                           integer-scalar-vector-type `,`
561                                           integer-scalar-vector-type
562    ```
563
564    #### Example:
565
566    ```mlir
567    %2 = spv.ShiftRightLogical %0, %1 : i32, i16
568    %5 = spv.ShiftRightLogical %3, %4 : vector<3xi32>, vector<3xi16>
569    ```
570  }];
571
572  let availability = [
573    MinVersion<SPV_V_1_0>,
574    MaxVersion<SPV_V_1_5>,
575    Extension<[]>,
576    Capability<[]>
577  ];
578}
579
580// -----
581
582def SPV_NotOp : SPV_BitUnaryOp<"Not", []> {
583  let summary = "Complement the bits of Operand.";
584
585  let description = [{
586     Results are computed per component, and within each component, per bit.
587
588    Result Type must be a scalar or vector of integer type.
589
590    Operand’s type  must be a scalar or vector of integer type.  It must
591    have the same number of components as Result Type.  The component width
592    must equal the component width in Result Type.
593
594    <!-- End of AutoGen section -->
595
596    ```
597    integer-scalar-vector-type ::= integer-type |
598                                  `vector<` integer-literal `x` integer-type `>`
599    not-op ::= ssa-id `=` `spv.BitNot` ssa-use `:` integer-scalar-vector-type
600    ```
601
602    #### Example:
603
604    ```mlir
605    %2 = spv.Not %0 : i32
606    %3 = spv.Not %1 : vector<4xi32>
607    ```
608  }];
609}
610
611#endif // SPIRV_BIT_OPS
612