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