1//===-- SPIRVAtomicOps.td - MLIR SPIR-V Atomic 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 atomic ops for the SPIR-V dialect. It corresponds to 10// "3.32.18. Atomic Instructions" of the SPIR-V specification. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef SPIRV_ATOMIC_OPS 15#define SPIRV_ATOMIC_OPS 16 17class SPV_AtomicUpdateOp<string mnemonic, list<OpTrait> traits = []> : 18 SPV_Op<mnemonic, traits> { 19 let parser = [{ return ::parseAtomicUpdateOp(parser, result, false); }]; 20 let printer = [{ return ::printAtomicUpdateOp(getOperation(), p); }]; 21 let verifier = [{ return ::verifyAtomicUpdateOp(getOperation()); }]; 22 23 let arguments = (ins 24 SPV_AnyPtr:$pointer, 25 SPV_ScopeAttr:$memory_scope, 26 SPV_MemorySemanticsAttr:$semantics 27 ); 28 29 let results = (outs 30 SPV_Integer:$result 31 ); 32} 33 34class SPV_AtomicUpdateWithValueOp<string mnemonic, list<OpTrait> traits = []> : 35 SPV_Op<mnemonic, traits> { 36 let parser = [{ return ::parseAtomicUpdateOp(parser, result, true); }]; 37 let printer = [{ return ::printAtomicUpdateOp(getOperation(), p); }]; 38 let verifier = [{ return ::verifyAtomicUpdateOp(getOperation()); }]; 39 40 let arguments = (ins 41 SPV_AnyPtr:$pointer, 42 SPV_ScopeAttr:$memory_scope, 43 SPV_MemorySemanticsAttr:$semantics, 44 SPV_Integer:$value 45 ); 46 47 let results = (outs 48 SPV_Integer:$result 49 ); 50 51 let builders = [ 52 OpBuilderDAG<(ins "Value":$pointer, "::mlir::spirv::Scope":$scope, 53 "::mlir::spirv::MemorySemantics":$memory, "Value":$value), 54 [{build($_builder, $_state, value.getType(), pointer, scope, memory, value);}]> 55 ]; 56} 57 58// ----- 59 60def SPV_AtomicAndOp : SPV_AtomicUpdateWithValueOp<"AtomicAnd", []> { 61 let summary = [{ 62 Perform the following steps atomically with respect to any other atomic 63 accesses within Scope to the same location: 64 }]; 65 66 let description = [{ 67 1) load through Pointer to get an Original Value, 68 69 2) get a New Value by the bitwise AND of Original Value and Value, and 70 71 3) store the New Value back through Pointer. 72 73 The instruction’s result is the Original Value. 74 75 Result Type must be an integer type scalar. 76 77 The type of Value must be the same as Result Type. The type of the 78 value pointed to by Pointer must be the same as Result Type. 79 80 Memory must be a valid memory Scope. 81 82 <!-- End of AutoGen section --> 83 84 ``` 85 scope ::= `"CrossDevice"` | `"Device"` | `"Workgroup"` | ... 86 87 memory-semantics ::= `"None"` | `"Acquire"` | "Release"` | ... 88 89 atomic-and-op ::= 90 `spv.AtomicAnd` scope memory-semantics 91 ssa-use `,` ssa-use `:` spv-pointer-type 92 ``` 93 94 #### Example: 95 96 ```mlir 97 %0 = spv.AtomicAnd "Device" "None" %pointer, %value : 98 !spv.ptr<i32, StorageBuffer> 99 ``` 100 }]; 101} 102 103// ----- 104 105def SPV_AtomicCompareExchangeWeakOp : SPV_Op<"AtomicCompareExchangeWeak", []> { 106 let summary = "Deprecated (use OpAtomicCompareExchange)."; 107 108 let description = [{ 109 Has the same semantics as OpAtomicCompareExchange. 110 111 Memory must be a valid memory Scope. 112 113 <!-- End of AutoGen section --> 114 115 ``` 116 atomic-compare-exchange-weak-op ::= 117 `spv.AtomicCompareExchangeWeak` scope memory-semantics memory-semantics 118 ssa-use `,` ssa-use `,` ssa-use 119 `:` spv-pointer-type 120 ``` 121 122 #### Example: 123 124 ```mlir 125 %0 = spv.AtomicCompareExchangeWeak "Workgroup" "Acquire" "None" 126 %pointer, %value, %comparator 127 : !spv.ptr<i32, WorkGroup> 128 ``` 129 }]; 130 131 let availability = [ 132 MinVersion<SPV_V_1_0>, 133 MaxVersion<SPV_V_1_3>, 134 Extension<[]>, 135 Capability<[SPV_C_Kernel]> 136 ]; 137 138 let arguments = (ins 139 SPV_AnyPtr:$pointer, 140 SPV_ScopeAttr:$memory_scope, 141 SPV_MemorySemanticsAttr:$equal_semantics, 142 SPV_MemorySemanticsAttr:$unequal_semantics, 143 SPV_Integer:$value, 144 SPV_Integer:$comparator 145 ); 146 147 let results = (outs 148 SPV_Integer:$result 149 ); 150} 151 152// ----- 153 154def SPV_AtomicIAddOp : SPV_AtomicUpdateWithValueOp<"AtomicIAdd", []> { 155 let summary = [{ 156 Perform the following steps atomically with respect to any other atomic 157 accesses within Scope to the same location: 158 }]; 159 160 let description = [{ 161 1) load through Pointer to get an Original Value, 162 163 2) get a New Value by integer addition of Original Value and Value, and 164 165 3) store the New Value back through Pointer. 166 167 The instruction’s result is the Original Value. 168 169 Result Type must be an integer type scalar. 170 171 The type of Value must be the same as Result Type. The type of the 172 value pointed to by Pointer must be the same as Result Type. 173 174 Memory must be a valid memory Scope. 175 176 <!-- End of AutoGen section --> 177 178 ``` 179 atomic-iadd-op ::= 180 `spv.AtomicIAdd` scope memory-semantics 181 ssa-use `,` ssa-use `:` spv-pointer-type 182 ``` 183 184 #### Example: 185 186 ```mlir 187 %0 = spv.AtomicIAdd "Device" "None" %pointer, %value : 188 !spv.ptr<i32, StorageBuffer> 189 ``` 190 }]; 191} 192 193// ----- 194 195def SPV_AtomicIDecrementOp : SPV_AtomicUpdateOp<"AtomicIDecrement", []> { 196 let summary = [{ 197 Perform the following steps atomically with respect to any other atomic 198 accesses within Scope to the same location: 199 }]; 200 201 let description = [{ 202 1) load through Pointer to get an Original Value, 203 204 2) get a New Value through integer subtraction of 1 from Original Value, 205 and 206 207 3) store the New Value back through Pointer. 208 209 The instruction’s result is the Original Value. 210 211 Result Type must be an integer type scalar. The type of the value 212 pointed to by Pointer must be the same as Result Type. 213 214 Memory must be a valid memory Scope. 215 216 <!-- End of AutoGen section --> 217 218 ``` 219 atomic-idecrement-op ::= 220 `spv.AtomicIDecrement` scope memory-semantics ssa-use 221 `:` spv-pointer-type 222 ``` 223 224 #### Example: 225 226 ```mlir 227 %0 = spv.AtomicIDecrement "Device" "None" %pointer : 228 !spv.ptr<i32, StorageBuffer> 229 ``` 230 }]; 231} 232 233// ----- 234 235def SPV_AtomicIIncrementOp : SPV_AtomicUpdateOp<"AtomicIIncrement", []> { 236 let summary = [{ 237 Perform the following steps atomically with respect to any other atomic 238 accesses within Scope to the same location: 239 }]; 240 241 let description = [{ 242 1) load through Pointer to get an Original Value, 243 244 2) get a New Value through integer addition of 1 to Original Value, and 245 246 3) store the New Value back through Pointer. 247 248 The instruction’s result is the Original Value. 249 250 Result Type must be an integer type scalar. The type of the value 251 pointed to by Pointer must be the same as Result Type. 252 253 Memory must be a valid memory Scope. 254 255 <!-- End of AutoGen section --> 256 257 ``` 258 atomic-iincrement-op ::= 259 `spv.AtomicIIncrement` scope memory-semantics ssa-use 260 `:` spv-pointer-type 261 ``` 262 263 #### Example: 264 265 ```mlir 266 %0 = spv.AtomicIncrement "Device" "None" %pointer : 267 !spv.ptr<i32, StorageBuffer> 268 ``` 269 }]; 270} 271 272// ----- 273 274def SPV_AtomicISubOp : SPV_AtomicUpdateWithValueOp<"AtomicISub", []> { 275 let summary = [{ 276 Perform the following steps atomically with respect to any other atomic 277 accesses within Scope to the same location: 278 }]; 279 280 let description = [{ 281 1) load through Pointer to get an Original Value, 282 283 2) get a New Value by integer subtraction of Value from Original Value, 284 and 285 286 3) store the New Value back through Pointer. 287 288 The instruction’s result is the Original Value. 289 290 Result Type must be an integer type scalar. 291 292 The type of Value must be the same as Result Type. The type of the 293 value pointed to by Pointer must be the same as Result Type. 294 295 Memory must be a valid memory Scope. 296 297 <!-- End of AutoGen section --> 298 299 ``` 300 atomic-isub-op ::= 301 `spv.AtomicISub` scope memory-semantics 302 ssa-use `,` ssa-use `:` spv-pointer-type 303 ``` 304 305 #### Example: 306 307 ```mlir 308 %0 = spv.AtomicISub "Device" "None" %pointer, %value : 309 !spv.ptr<i32, StorageBuffer> 310 ``` 311 }]; 312} 313 314// ----- 315 316def SPV_AtomicOrOp : SPV_AtomicUpdateWithValueOp<"AtomicOr", []> { 317 let summary = [{ 318 Perform the following steps atomically with respect to any other atomic 319 accesses within Scope to the same location: 320 }]; 321 322 let description = [{ 323 1) load through Pointer to get an Original Value, 324 325 2) get a New Value by the bitwise OR of Original Value and Value, and 326 327 3) store the New Value back through Pointer. 328 329 The instruction’s result is the Original Value. 330 331 Result Type must be an integer type scalar. 332 333 The type of Value must be the same as Result Type. The type of the 334 value pointed to by Pointer must be the same as Result Type. 335 336 Memory must be a valid memory Scope. 337 338 <!-- End of AutoGen section --> 339 340 ``` 341 atomic-or-op ::= 342 `spv.AtomicOr` scope memory-semantics 343 ssa-use `,` ssa-use `:` spv-pointer-type 344 ``` 345 346 #### Example: 347 348 ```mlir 349 %0 = spv.AtomicOr "Device" "None" %pointer, %value : 350 !spv.ptr<i32, StorageBuffer> 351 ``` 352 }]; 353} 354 355// ----- 356 357def SPV_AtomicSMaxOp : SPV_AtomicUpdateWithValueOp<"AtomicSMax", []> { 358 let summary = [{ 359 Perform the following steps atomically with respect to any other atomic 360 accesses within Scope to the same location: 361 }]; 362 363 let description = [{ 364 1) load through Pointer to get an Original Value, 365 366 2) get a New Value by finding the largest signed integer of Original 367 Value and Value, and 368 369 3) store the New Value back through Pointer. 370 371 The instruction’s result is the Original Value. 372 373 Result Type must be an integer type scalar. 374 375 The type of Value must be the same as Result Type. The type of the 376 value pointed to by Pointer must be the same as Result Type. 377 378 Memory must be a valid memory Scope. 379 380 <!-- End of AutoGen section --> 381 382 ``` 383 atomic-smax-op ::= 384 `spv.AtomicSMax` scope memory-semantics 385 ssa-use `,` ssa-use `:` spv-pointer-type 386 ``` 387 388 #### Example: 389 390 ```mlir 391 %0 = spv.AtomicSMax "Device" "None" %pointer, %value : 392 !spv.ptr<i32, StorageBuffer> 393 ``` 394 }]; 395} 396 397// ----- 398 399def SPV_AtomicSMinOp : SPV_AtomicUpdateWithValueOp<"AtomicSMin", []> { 400 let summary = [{ 401 Perform the following steps atomically with respect to any other atomic 402 accesses within Scope to the same location: 403 }]; 404 405 let description = [{ 406 1) load through Pointer to get an Original Value, 407 408 2) get a New Value by finding the smallest signed integer of Original 409 Value and Value, and 410 411 3) store the New Value back through Pointer. 412 413 The instruction’s result is the Original Value. 414 415 Result Type must be an integer type scalar. 416 417 The type of Value must be the same as Result Type. The type of the 418 value pointed to by Pointer must be the same as Result Type. 419 420 Memory must be a valid memory Scope. 421 422 <!-- End of AutoGen section --> 423 424 ``` 425 atomic-smin-op ::= 426 `spv.AtomicSMin` scope memory-semantics 427 ssa-use `,` ssa-use `:` spv-pointer-type 428 ``` 429 430 #### Example: 431 432 ```mlir 433 %0 = spv.AtomicSMin "Device" "None" %pointer, %value : 434 !spv.ptr<i32, StorageBuffer> 435 ``` 436 }]; 437} 438 439// ----- 440 441def SPV_AtomicUMaxOp : SPV_AtomicUpdateWithValueOp<"AtomicUMax", []> { 442 let summary = [{ 443 Perform the following steps atomically with respect to any other atomic 444 accesses within Scope to the same location: 445 }]; 446 447 let description = [{ 448 1) load through Pointer to get an Original Value, 449 450 2) get a New Value by finding the largest unsigned integer of Original 451 Value and Value, and 452 453 3) store the New Value back through Pointer. 454 455 The instruction’s result is the Original Value. 456 457 Result Type must be an integer type scalar. 458 459 The type of Value must be the same as Result Type. The type of the 460 value pointed to by Pointer must be the same as Result Type. 461 462 Memory must be a valid memory Scope. 463 464 <!-- End of AutoGen section --> 465 466 ``` 467 atomic-umax-op ::= 468 `spv.AtomicUMax` scope memory-semantics 469 ssa-use `,` ssa-use `:` spv-pointer-type 470 ``` 471 472 #### Example: 473 474 ```mlir 475 %0 = spv.AtomicUMax "Device" "None" %pointer, %value : 476 !spv.ptr<i32, StorageBuffer> 477 ``` 478 }]; 479} 480 481// ----- 482 483def SPV_AtomicUMinOp : SPV_AtomicUpdateWithValueOp<"AtomicUMin", []> { 484 let summary = [{ 485 Perform the following steps atomically with respect to any other atomic 486 accesses within Scope to the same location: 487 }]; 488 489 let description = [{ 490 1) load through Pointer to get an Original Value, 491 492 2) get a New Value by finding the smallest unsigned integer of Original 493 Value and Value, and 494 495 3) store the New Value back through Pointer. 496 497 The instruction’s result is the Original Value. 498 499 Result Type must be an integer type scalar. 500 501 The type of Value must be the same as Result Type. The type of the 502 value pointed to by Pointer must be the same as Result Type. 503 504 Memory must be a valid memory Scope. 505 506 <!-- End of AutoGen section --> 507 508 ``` 509 atomic-umin-op ::= 510 `spv.AtomicUMin` scope memory-semantics 511 ssa-use `,` ssa-use `:` spv-pointer-type 512 ``` 513 514 #### Example: 515 516 ```mlir 517 %0 = spv.AtomicUMin "Device" "None" %pointer, %value : 518 !spv.ptr<i32, StorageBuffer> 519 ``` 520 }]; 521} 522 523// ----- 524 525def SPV_AtomicXorOp : SPV_AtomicUpdateWithValueOp<"AtomicXor", []> { 526 let summary = [{ 527 Perform the following steps atomically with respect to any other atomic 528 accesses within Scope to the same location: 529 }]; 530 531 let description = [{ 532 1) load through Pointer to get an Original Value, 533 534 2) get a New Value by the bitwise exclusive OR of Original Value and 535 Value, and 536 537 3) store the New Value back through Pointer. 538 539 The instruction’s result is the Original Value. 540 541 Result Type must be an integer type scalar. 542 543 The type of Value must be the same as Result Type. The type of the 544 value pointed to by Pointer must be the same as Result Type. 545 546 Memory must be a valid memory Scope. 547 548 <!-- End of AutoGen section --> 549 550 ``` 551 atomic-xor-op ::= 552 `spv.AtomicXor` scope memory-semantics 553 ssa-use `,` ssa-use `:` spv-pointer-type 554 ``` 555 556 #### Example: 557 558 ```mlir 559 %0 = spv.AtomicXor "Device" "None" %pointer, %value : 560 !spv.ptr<i32, StorageBuffer> 561 ``` 562 }]; 563} 564 565// ----- 566 567#endif // SPIRV_ATOMIC_OPS 568