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