1//===-- SPIRVArithmeticOps.td - MLIR SPIR-V Arithmetic 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.13. Arithmetic Instructions" of the SPIR-V specification. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef SPIRV_ARITHMETIC_OPS 15#define SPIRV_ARITHMETIC_OPS 16 17include "mlir/Dialect/SPIRV/SPIRVBase.td" 18include "mlir/Interfaces/SideEffectInterfaces.td" 19 20class SPV_ArithmeticBinaryOp<string mnemonic, Type type, 21 list<OpTrait> traits = []> : 22 // Operands type same as result type. 23 SPV_BinaryOp<mnemonic, type, type, 24 !listconcat(traits, 25 [NoSideEffect, SameOperandsAndResultType])> { 26 // In addition to normal types arithmetic instructions can support cooperative 27 // matrix. 28 let arguments = (ins 29 SPV_ScalarOrVectorOrCoopMatrixOf<type>:$operand1, 30 SPV_ScalarOrVectorOrCoopMatrixOf<type>:$operand2 31 ); 32 33 let results = (outs 34 SPV_ScalarOrVectorOrCoopMatrixOf<type>:$result 35 ); 36} 37 38class SPV_ArithmeticUnaryOp<string mnemonic, Type type, 39 list<OpTrait> traits = []> : 40 // Operand type same as result type. 41 SPV_UnaryOp<mnemonic, type, type, 42 !listconcat(traits, 43 [NoSideEffect, SameOperandsAndResultType])>; 44 45// ----- 46 47def SPV_FAddOp : SPV_ArithmeticBinaryOp<"FAdd", SPV_Float, [Commutative]> { 48 let summary = "Floating-point addition of Operand 1 and Operand 2."; 49 50 let description = [{ 51 Result Type must be a scalar or vector of floating-point type. 52 53 The types of Operand 1 and Operand 2 both must be the same as Result 54 Type. 55 56 Results are computed per component. 57 58 <!-- End of AutoGen section --> 59 ``` 60 float-scalar-vector-type ::= float-type | 61 `vector<` integer-literal `x` float-type `>` 62 fadd-op ::= ssa-id `=` `spv.FAdd` ssa-use, ssa-use 63 `:` float-scalar-vector-type 64 ``` 65 #### Example: 66 67 ```mlir 68 %4 = spv.FAdd %0, %1 : f32 69 %5 = spv.FAdd %2, %3 : vector<4xf32> 70 ``` 71 }]; 72} 73 74// ----- 75 76def SPV_FDivOp : SPV_ArithmeticBinaryOp<"FDiv", SPV_Float, []> { 77 let summary = "Floating-point division of Operand 1 divided by Operand 2."; 78 79 let description = [{ 80 Result Type must be a scalar or vector of floating-point type. 81 82 The types of Operand 1 and Operand 2 both must be the same as Result 83 Type. 84 85 Results are computed per component. The resulting value is undefined 86 if Operand 2 is 0. 87 88 <!-- End of AutoGen section --> 89 ``` 90 float-scalar-vector-type ::= float-type | 91 `vector<` integer-literal `x` float-type `>` 92 fdiv-op ::= ssa-id `=` `spv.FDiv` ssa-use, ssa-use 93 `:` float-scalar-vector-type 94 ``` 95 96 #### Example: 97 98 ```mlir 99 %4 = spv.FDiv %0, %1 : f32 100 %5 = spv.FDiv %2, %3 : vector<4xf32> 101 ``` 102 }]; 103} 104 105// ----- 106 107def SPV_FModOp : SPV_ArithmeticBinaryOp<"FMod", SPV_Float, []> { 108 let summary = [{ 109 The floating-point remainder whose sign matches the sign of Operand 2. 110 }]; 111 112 let description = [{ 113 Result Type must be a scalar or vector of floating-point type. 114 115 The types of Operand 1 and Operand 2 both must be the same as Result 116 Type. 117 118 Results are computed per component. The resulting value is undefined 119 if Operand 2 is 0. Otherwise, the result is the remainder r of Operand 120 1 divided by Operand 2 where if r ≠ 0, the sign of r is the same as the 121 sign of Operand 2. 122 123 <!-- End of AutoGen section --> 124 ``` 125 float-scalar-vector-type ::= float-type | 126 `vector<` integer-literal `x` float-type `>` 127 fmod-op ::= ssa-id `=` `spv.FMod` ssa-use, ssa-use 128 `:` float-scalar-vector-type 129 ``` 130 #### Example: 131 132 ```mlir 133 %4 = spv.FMod %0, %1 : f32 134 %5 = spv.FMod %2, %3 : vector<4xf32> 135 ``` 136 }]; 137} 138 139// ----- 140 141def SPV_FMulOp : SPV_ArithmeticBinaryOp<"FMul", SPV_Float, [Commutative]> { 142 let summary = "Floating-point multiplication of Operand 1 and Operand 2."; 143 144 let description = [{ 145 Result Type must be a scalar or vector of floating-point type. 146 147 The types of Operand 1 and Operand 2 both must be the same as Result 148 Type. 149 150 Results are computed per component. 151 152 <!-- End of AutoGen section --> 153 154 ``` 155 float-scalar-vector-type ::= float-type | 156 `vector<` integer-literal `x` float-type `>` 157 fmul-op ::= `spv.FMul` ssa-use, ssa-use 158 `:` float-scalar-vector-type 159 ``` 160 161 #### Example: 162 163 ```mlir 164 %4 = spv.FMul %0, %1 : f32 165 %5 = spv.FMul %2, %3 : vector<4xf32> 166 ``` 167 }]; 168} 169 170// ----- 171 172def SPV_FNegateOp : SPV_ArithmeticUnaryOp<"FNegate", SPV_Float, []> { 173 let summary = [{ 174 Inverts the sign bit of Operand. (Note, however, that OpFNegate is still 175 considered a floating-point instruction, and so is subject to the 176 general floating-point rules regarding, for example, subnormals and NaN 177 propagation). 178 }]; 179 180 let description = [{ 181 Result Type must be a scalar or vector of floating-point type. 182 183 The type of Operand must be the same as Result Type. 184 185 Results are computed per component. 186 187 <!-- End of AutoGen section --> 188 189 ``` 190 float-scalar-vector-type ::= float-type | 191 `vector<` integer-literal `x` float-type `>` 192 fmul-op ::= `spv.FNegate` ssa-use `:` float-scalar-vector-type 193 ``` 194 195 #### Example: 196 197 ```mlir 198 %1 = spv.FNegate %0 : f32 199 %3 = spv.FNegate %2 : vector<4xf32> 200 ``` 201 }]; 202} 203 204// ----- 205 206def SPV_FRemOp : SPV_ArithmeticBinaryOp<"FRem", SPV_Float, []> { 207 let summary = [{ 208 The floating-point remainder whose sign matches the sign of Operand 1. 209 }]; 210 211 let description = [{ 212 Result Type must be a scalar or vector of floating-point type. 213 214 The types of Operand 1 and Operand 2 both must be the same as Result 215 Type. 216 217 Results are computed per component. The resulting value is undefined 218 if Operand 2 is 0. Otherwise, the result is the remainder r of Operand 219 1 divided by Operand 2 where if r ≠ 0, the sign of r is the same as the 220 sign of Operand 1. 221 222 <!-- End of AutoGen section --> 223 ``` 224 float-scalar-vector-type ::= float-type | 225 `vector<` integer-literal `x` float-type `>` 226 frem-op ::= ssa-id `=` `spv.FRemOp` ssa-use, ssa-use 227 `:` float-scalar-vector-type 228 ``` 229 230 #### Example: 231 232 ```mlir 233 %4 = spv.FRemOp %0, %1 : f32 234 %5 = spv.FRemOp %2, %3 : vector<4xf32> 235 ``` 236 }]; 237} 238 239// ----- 240 241def SPV_FSubOp : SPV_ArithmeticBinaryOp<"FSub", SPV_Float, []> { 242 let summary = "Floating-point subtraction of Operand 2 from Operand 1."; 243 244 let description = [{ 245 Result Type must be a scalar or vector of floating-point type. 246 247 The types of Operand 1 and Operand 2 both must be the same as Result 248 Type. 249 250 Results are computed per component. 251 252 <!-- End of AutoGen section --> 253 ``` 254 float-scalar-vector-type ::= float-type | 255 `vector<` integer-literal `x` float-type `>` 256 fsub-op ::= ssa-id `=` `spv.FRemOp` ssa-use, ssa-use 257 `:` float-scalar-vector-type 258 ``` 259 260 #### Example: 261 262 ```mlir 263 %4 = spv.FRemOp %0, %1 : f32 264 %5 = spv.FRemOp %2, %3 : vector<4xf32> 265 ``` 266 }]; 267} 268 269// ----- 270 271def SPV_IAddOp : SPV_ArithmeticBinaryOp<"IAdd", SPV_Integer, [Commutative]> { 272 let summary = "Integer addition of Operand 1 and Operand 2."; 273 274 let description = [{ 275 Result Type must be a scalar or vector of integer type. 276 277 The type of Operand 1 and Operand 2 must be a scalar or vector of 278 integer type. They must have the same number of components as Result 279 Type. They must have the same component width as Result Type. 280 281 The resulting value will equal the low-order N bits of the correct 282 result R, where N is the component width and R is computed with enough 283 precision to avoid overflow and underflow. 284 285 Results are computed per component. 286 287 <!-- End of AutoGen section --> 288 ``` 289 integer-scalar-vector-type ::= integer-type | 290 `vector<` integer-literal `x` integer-type `>` 291 iadd-op ::= ssa-id `=` `spv.IAdd` ssa-use, ssa-use 292 `:` integer-scalar-vector-type 293 ``` 294 295 #### Example: 296 297 ```mlir 298 %4 = spv.IAdd %0, %1 : i32 299 %5 = spv.IAdd %2, %3 : vector<4xi32> 300 301 ``` 302 }]; 303 304 let hasFolder = 1; 305} 306 307// ----- 308 309def SPV_IMulOp : SPV_ArithmeticBinaryOp<"IMul", SPV_Integer, [Commutative]> { 310 let summary = "Integer multiplication of Operand 1 and Operand 2."; 311 312 let description = [{ 313 Result Type must be a scalar or vector of integer type. 314 315 The type of Operand 1 and Operand 2 must be a scalar or vector of 316 integer type. They must have the same number of components as Result 317 Type. They must have the same component width as Result Type. 318 319 The resulting value will equal the low-order N bits of the correct 320 result R, where N is the component width and R is computed with enough 321 precision to avoid overflow and underflow. 322 323 Results are computed per component. 324 325 <!-- End of AutoGen section --> 326 ``` 327 integer-scalar-vector-type ::= integer-type | 328 `vector<` integer-literal `x` integer-type `>` 329 imul-op ::= ssa-id `=` `spv.IMul` ssa-use, ssa-use 330 `:` integer-scalar-vector-type 331 ``` 332 333 #### Example: 334 335 ```mlir 336 %4 = spv.IMul %0, %1 : i32 337 %5 = spv.IMul %2, %3 : vector<4xi32> 338 339 ``` 340 }]; 341 342 let hasFolder = 1; 343} 344 345// ----- 346 347def SPV_ISubOp : SPV_ArithmeticBinaryOp<"ISub", SPV_Integer, []> { 348 let summary = "Integer subtraction of Operand 2 from Operand 1."; 349 350 let description = [{ 351 Result Type must be a scalar or vector of integer type. 352 353 The type of Operand 1 and Operand 2 must be a scalar or vector of 354 integer type. They must have the same number of components as Result 355 Type. They must have the same component width as Result Type. 356 357 The resulting value will equal the low-order N bits of the correct 358 result R, where N is the component width and R is computed with enough 359 precision to avoid overflow and underflow. 360 361 Results are computed per component. 362 363 <!-- End of AutoGen section --> 364 ``` 365 integer-scalar-vector-type ::= integer-type | 366 `vector<` integer-literal `x` integer-type `>` 367 isub-op ::= `spv.ISub` ssa-use, ssa-use 368 `:` integer-scalar-vector-type 369 ``` 370 371 #### Example: 372 373 ```mlir 374 %4 = spv.ISub %0, %1 : i32 375 %5 = spv.ISub %2, %3 : vector<4xi32> 376 377 ``` 378 }]; 379 380 let hasFolder = 1; 381} 382 383// ----- 384 385def SPV_SDivOp : SPV_ArithmeticBinaryOp<"SDiv", SPV_Integer, []> { 386 let summary = "Signed-integer division of Operand 1 divided by Operand 2."; 387 388 let description = [{ 389 Result Type must be a scalar or vector of integer type. 390 391 The type of Operand 1 and Operand 2 must be a scalar or vector of 392 integer type. They must have the same number of components as Result 393 Type. They must have the same component width as Result Type. 394 395 Results are computed per component. The resulting value is undefined 396 if Operand 2 is 0. 397 398 <!-- End of AutoGen section --> 399 ``` 400 integer-scalar-vector-type ::= integer-type | 401 `vector<` integer-literal `x` integer-type `>` 402 sdiv-op ::= ssa-id `=` `spv.SDiv` ssa-use, ssa-use 403 `:` integer-scalar-vector-type 404 ``` 405 406 #### Example: 407 408 ```mlir 409 %4 = spv.SDiv %0, %1 : i32 410 %5 = spv.SDiv %2, %3 : vector<4xi32> 411 412 ``` 413 }]; 414} 415 416// ----- 417 418def SPV_SModOp : SPV_ArithmeticBinaryOp<"SMod", SPV_Integer, []> { 419 let summary = [{ 420 Signed remainder operation for the remainder whose sign matches the sign 421 of Operand 2. 422 }]; 423 424 let description = [{ 425 Result Type must be a scalar or vector of integer type. 426 427 The type of Operand 1 and Operand 2 must be a scalar or vector of 428 integer type. They must have the same number of components as Result 429 Type. They must have the same component width as Result Type. 430 431 Results are computed per component. The resulting value is undefined 432 if Operand 2 is 0. Otherwise, the result is the remainder r of Operand 433 1 divided by Operand 2 where if r ≠ 0, the sign of r is the same as the 434 sign of Operand 2. 435 436 <!-- End of AutoGen section --> 437 ``` 438 integer-scalar-vector-type ::= integer-type | 439 `vector<` integer-literal `x` integer-type `>` 440 smod-op ::= ssa-id `=` `spv.SMod` ssa-use, ssa-use 441 `:` integer-scalar-vector-type 442 ``` 443 #### Example: 444 445 ```mlir 446 %4 = spv.SMod %0, %1 : i32 447 %5 = spv.SMod %2, %3 : vector<4xi32> 448 449 ``` 450 }]; 451} 452 453// ----- 454 455def SPV_SNegateOp : SPV_ArithmeticUnaryOp<"SNegate", SPV_Integer, []> { 456 let summary = "Signed-integer subtract of Operand from zero."; 457 458 let description = [{ 459 Result Type must be a scalar or vector of integer type. 460 461 Operand’s type must be a scalar or vector of integer type. It must 462 have the same number of components as Result Type. The component width 463 must equal the component width in Result Type. 464 465 Results are computed per component. 466 467 <!-- End of AutoGen section --> 468 469 #### Example: 470 471 ```mlir 472 %1 = spv.SNegate %0 : i32 473 %3 = spv.SNegate %2 : vector<4xi32> 474 ``` 475 }]; 476} 477 478// ----- 479 480def SPV_SRemOp : SPV_ArithmeticBinaryOp<"SRem", SPV_Integer, []> { 481 let summary = [{ 482 Signed remainder operation for the remainder whose sign matches the sign 483 of Operand 1. 484 }]; 485 486 let description = [{ 487 Result Type must be a scalar or vector of integer type. 488 489 The type of Operand 1 and Operand 2 must be a scalar or vector of 490 integer type. They must have the same number of components as Result 491 Type. They must have the same component width as Result Type. 492 493 Results are computed per component. The resulting value is undefined 494 if Operand 2 is 0. Otherwise, the result is the remainder r of Operand 495 1 divided by Operand 2 where if r ≠ 0, the sign of r is the same as the 496 sign of Operand 1. 497 498 <!-- End of AutoGen section --> 499 ``` 500 integer-scalar-vector-type ::= integer-type | 501 `vector<` integer-literal `x` integer-type `>` 502 srem-op ::= ssa-id `=` `spv.SRem` ssa-use, ssa-use 503 `:` integer-scalar-vector-type 504 ``` 505 #### Example: 506 507 ```mlir 508 %4 = spv.SRem %0, %1 : i32 509 %5 = spv.SRem %2, %3 : vector<4xi32> 510 511 ``` 512 }]; 513} 514 515// ----- 516 517def SPV_UDivOp : SPV_ArithmeticBinaryOp<"UDiv", SPV_Integer, []> { 518 let summary = "Unsigned-integer division of Operand 1 divided by Operand 2."; 519 520 let description = [{ 521 Result Type must be a scalar or vector of integer type, whose Signedness 522 operand is 0. 523 524 The types of Operand 1 and Operand 2 both must be the same as Result 525 Type. 526 527 Results are computed per component. The resulting value is undefined 528 if Operand 2 is 0. 529 530 <!-- End of AutoGen section --> 531 ``` 532 integer-scalar-vector-type ::= integer-type | 533 `vector<` integer-literal `x` integer-type `>` 534 udiv-op ::= ssa-id `=` `spv.UDiv` ssa-use, ssa-use 535 `:` integer-scalar-vector-type 536 ``` 537 #### Example: 538 539 ```mlir 540 %4 = spv.UDiv %0, %1 : i32 541 %5 = spv.UDiv %2, %3 : vector<4xi32> 542 543 ``` 544 }]; 545} 546 547// ----- 548 549def SPV_UModOp : SPV_ArithmeticBinaryOp<"UMod", SPV_Integer> { 550 let summary = "Unsigned modulo operation of Operand 1 modulo Operand 2."; 551 552 let description = [{ 553 Result Type must be a scalar or vector of integer type, whose Signedness 554 operand is 0. 555 556 The types of Operand 1 and Operand 2 both must be the same as Result 557 Type. 558 559 Results are computed per component. The resulting value is undefined 560 if Operand 2 is 0. 561 562 <!-- End of AutoGen section --> 563 ``` 564 integer-scalar-vector-type ::= integer-type | 565 `vector<` integer-literal `x` integer-type `>` 566 umod-op ::= ssa-id `=` `spv.UMod` ssa-use, ssa-use 567 `:` integer-scalar-vector-type 568 ``` 569 #### Example: 570 571 ```mlir 572 %4 = spv.UMod %0, %1 : i32 573 %5 = spv.UMod %2, %3 : vector<4xi32> 574 575 ``` 576 }]; 577} 578 579#endif // SPIRV_ARITHMETIC_OPS 580