Repository navigation
[SPIRV][AMDGPU][clang][CodeGen][opt] Add late-resolved feature identifying predicates #134016
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 77 commits
91eeaf0
8bf1168
3421292
539c7e6
5926b9f
4381d93
d18f64e
7880ff4
719dfde
36b69b4
e327e15
d35efc5
5dee670
888a080
e35ac62
6c41ed2
8683148
a9b3e85
468a517
1b8b57e
18b4af2
a8bca2f
716cc1f
79035a9
6945c2e
9a7e250
0f04dbc
39a9d55
3fe116e
49c862a
f293f39
251476d
ebde49b
4bdd30e
a1b4a11
18841c1
76848d5
e1bfdf3
4f65468
e940d42
46adb74
ca9521d
11dd570
fab0d14
611ec0d
03b029f
32be1c0
012f74d
cd7c920
33bbe35
46e5a91
8c1e1f5
81a55d8
bbe17fa
c495630
420a19c
dc0221e
7f88eb7
3b727b9
42f5de6
246ff38
adb6469
6b368d5
435ce05
2c2f78b
09115e2
f1d41a8
5d2c2f6
05033ea
b886c55
63d059d
495b567
8ef5c70
8177876
b4decc2
01b5e41
585cde7
283a52b
659dc76
2a406fc
dd663c9
558fb60
c431d41
6c96c9f
6d23d0a
5710e31
776c98b
1630673
915306f
5ac2a9e
6eb3199
eb4beb5
e326aef
84d01ac
a712868
0a211ba
89e5d01
097f274
1cda4cb
d9012fa
6f6f62c
c76c741
b84d483
7fc508d
cc21799
8a11f65
19130f1
1711293
5d0c189
47cc6d7
d362060
a6020cf
62bd27a
0e2b326
64a31e2
3e29297
48bb06d
d1d5e49
e9d7397
875bf68
b5a6fe3
e622583
2221c41
840d396
ccc8f94
8ef2cf4
e215226
5c51979
cf5ba05
b5faaa2
8974de1
70209b6
c791b5c
d0fb131
29285a4
7cc60e4
865af2d
cf7edd8
5bc0be6
a0492f4
33a9a41
e6ba156
0b0f27e
de56602
bdd487b
42cd26a
9fbb33e
56a9fce
68da2c5
1b0e195
aa749a4
0bfba3d
2077a82
e42746b
371feda
9ab6a3e
ca374a8
834ac16
008ba43
20c2b69
0f13bf6
ea407e3
d85b148
9ca3b62
56be10e
e9ee69a
a5d4ec1
187b550
0a25aa2
94341e0
767fd28
f0578b2
71e9e5c
b68bcb8
8086e95
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5044,6 +5044,118 @@ If no address spaces names are provided, all address spaces are fenced. | |
| __builtin_amdgcn_fence(__ATOMIC_SEQ_CST, "workgroup", "local") | ||
| __builtin_amdgcn_fence(__ATOMIC_SEQ_CST, "workgroup", "local", "global") | ||
|
|
||
| __builtin_amdgcn_processor_is and __builtin_amdgcn_is_invocable | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
|
||
| ``__builtin_amdgcn_processor_is`` and ``__builtin_amdgcn_is_invocable`` provide | ||
| a functional mechanism for programatically querying: | ||
|
|
||
| * the identity of the current target processor; | ||
| * the capability of the current target processor to invoke a particular builtin. | ||
|
|
||
| **Syntax**: | ||
|
|
||
| .. code-block:: c | ||
|
|
||
| __amdgpu_feature_predicate_t __builtin_amdgcn_processor_is(const char*); | ||
| __amdgpu_feature_predicate_t __builtin_amdgcn_is_invocable(builtin_name); | ||
|
|
||
| **Example of use**: | ||
|
|
||
| .. code-block:: c++ | ||
|
|
||
| if (__builtin_amdgcn_processor_is("gfx1201") || | ||
| __builtin_amdgcn_is_invocable(__builtin_amdgcn_s_sleep_var)) | ||
| __builtin_amdgcn_s_sleep_var(x); | ||
|
|
||
| if (!__builtin_amdgcn_processor_is("gfx906")) | ||
| __builtin_amdgcn_s_wait_event_export_ready(); | ||
| else if (__builtin_amdgcn_processor_is("gfx1010") || | ||
| __builtin_amdgcn_processor_is("gfx1101")) | ||
| __builtin_amdgcn_s_ttracedata_imm(1); | ||
|
|
||
| while (__builtin_amdgcn_processor_is("gfx1101")) *p += x; | ||
|
|
||
| do { | ||
| break; | ||
| } while (__builtin_amdgcn_processor_is("gfx1010")); | ||
|
|
||
| for (; __builtin_amdgcn_processor_is("gfx1201"); ++*p) break; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same question about inf. loop here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this'd be an infinite loop ever, it's either 0 trips or one trip, if the predicate is true we just |
||
|
|
||
| if (__builtin_amdgcn_is_invocable(__builtin_amdgcn_s_wait_event_export_ready)) | ||
| __builtin_amdgcn_s_wait_event_export_ready(); | ||
| else if (__builtin_amdgcn_is_invocable(__builtin_amdgcn_s_ttracedata_imm)) | ||
| __builtin_amdgcn_s_ttracedata_imm(1); | ||
|
|
||
| do { | ||
| break; | ||
| } while ( | ||
| __builtin_amdgcn_is_invocable(__builtin_amdgcn_global_load_tr_b64_i32)); | ||
|
|
||
| for (; __builtin_amdgcn_is_invocable(__builtin_amdgcn_permlane64); ++*p) | ||
| break; | ||
|
|
||
| **Description**: | ||
|
|
||
| The builtins return a value of type ``__amdgpu_feature_predicate_t``, which is a | ||
| target specific type that behaves as if its C++ definition was the following: | ||
|
Comment on lines
+5614
to
+5615
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this builtin work in C? If so, the docs should be updated to make it clear that this behavior applies to C as well as C++ and explain what it means in a bit more detail (presume that C users have no idea how C++ idioms work).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it does work in C, although I'm not convinced it will see significant use. That being said, there's no good reason to make it C++ only. I have tried to add an explanation for that context / provide a fleshed out example, please do let me know if it's more or less aligned with what you had in mind. Thanks! |
||
|
|
||
| .. code-block:: c++ | ||
|
|
||
| struct __amdgpu_feature_predicate_t { | ||
| __amdgpu_feature_predicate_t() = delete; | ||
| __amdgpu_feature_predicate_t(const __amdgpu_feature_predicate_t&) = delete; | ||
| __amdgpu_feature_predicate_t(__amdgpu_feature_predicate_t&&) = delete; | ||
|
|
||
| explicit | ||
| operator bool() const noexcept; | ||
| }; | ||
|
|
||
| The builtins can be used in C as well, wherein the | ||
| ``__amdgpu_feature_predicate_t`` type behaves as an opaque, forward declared | ||
| type with conditional automated conversion to ``_Bool`` when used as the | ||
|
Comment on lines
+5629
to
+5630
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should have a test case that stuff like this is diagnosed as using an incomplete type? Similar in C++ with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
| predicate argument to a control structure: | ||
|
|
||
| .. code-block:: c | ||
|
|
||
| struct __amdgpu_feature_predicate_t ret(); // Error | ||
| void arg(struct __amdgpu_feature_predicate_t); // Error | ||
| void local() { | ||
| struct __amdgpu_feature_predicate_t x; // Error | ||
| struct __amdgpu_feature_predicate_t y = | ||
| __builtin_amdgcn_processor_is("gfx900"); // Error | ||
| } | ||
| void valid_use() { | ||
| _Bool x = (_Bool)__builtin_amdgcn_processor_is("gfx900"); // OK | ||
| if (__builtin_amdgcn_processor_is("gfx900")) // Implicit cast to _Bool | ||
| return; | ||
| for (; __builtin_amdgcn_processor_is("gfx900");) // Implicit cast to _Bool | ||
| break; | ||
| while (__builtin_amdgcn_processor_is("gfx900")) // Implicit cast to _Bool | ||
| break; | ||
| do { | ||
| break; | ||
| } while (__builtin_amdgcn_processor_is("gfx900")); // Implicit cast to _Bool | ||
|
|
||
| __builtin_amdgcn_processor_is("gfx900") ? x : !x; | ||
| } | ||
|
|
||
| The boolean interpretation of the predicate values returned by the builtins: | ||
|
|
||
| * indicates whether the current target matches the argument; the argument MUST | ||
| be a string literal and a valid AMDGPU target | ||
| * indicates whether the builtin function passed as the argument can be invoked | ||
| by the current target; the argument MUST be either a generic or AMDGPU | ||
| specific builtin name | ||
|
|
||
| When invoked while compiling for a concrete target, the builtins are evaluated | ||
| early by Clang, and never produce any CodeGen effects / have no observable | ||
| side-effects in IR. Conversely, when compiling for AMDGCN flavoured SPIR-v, | ||
| which is an abstract target, a series of predicate values are implicitly | ||
| created. These predicates get resolved when finalizing the compilation process | ||
| for a concrete target, and shall reflect the latter's identity and features. | ||
| Thus, it is possible to author high-level code, in e.g. HIP, that is target | ||
| adaptive in a dynamic fashion, contrary to macro based mechanisms. | ||
|
|
||
| ARM/AArch64 Language Extensions | ||
| ------------------------------- | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CC @sarnex @jhuber6 as this relates to
__has_builtinbehavior somewhat and we've been in discussions about whether that should mean "I know about the builtin" or "I can actually call the builtin".