• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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