[clang] [llvm] [AMDGPU][clang][CodeGen][opt] Add late-resolved feature identifying predicates (PR #134016)

Alex Voicu via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 30 10:39:18 PDT 2025


AlexVlx wrote:

> Let me add my few cents here.
> 
> > In the case where the target features are known during clang codegen, lowering is easy: you just skip generating the bodies of the if statements that don't match. If you want to some kind of "runtime" (actual runtime, or SPIR-V compilation-time) detection, it's not clear what the LLVM IR should look like: we only support specifying target features on a per-function level. But we can look at that separately.
> 
> Let me try to attempt to answer this question without introducing a new builtin in clang (at first). In SPIR-V there is [specialization constant](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#SpecializationSection) which AFAIK doesn't have a direct LLVM IR counterpart. Some pseudo-code on SPIR-V would be looking like this:
> 
> ```
> %int = OpTypeInt 32 1
> %runtime_known_hw_id = OpSpecConstant %int 0 // global var
> %hw_id_that_supports_feature = OpConstant %int 42
> 
> kernel void foo(...) {
> /* ... */
> %cmp = OpIEqual %bool %runtime_known_hw_id %hw_id_that_supports_feature
> if (%cmp = true) {
> /* some feature */
> } else {
> /* other feature */
> }
> ```
> 
> At runtime, when such SPIR-V module is JIT compiled OpSpecConstant materializes, so DCE (or better say some variation of DCE that is enforced to work with optnone) will be able to reason about %cmp result removing the dead branch, so we won't get unsupported feature at codegen.
> 
> Problem is: how to generate such SPIR-V from clang. So my understanding, that the new builtin should eventually lowered (by SPIR-V backend?) to a construct like in the pseudo-code, though that is not what is currently happening. And I believe, that existing `__builtin_cpu_supports` is not a good match for such lowering.

This is one possible implementation indeed, for a workflow that goes from SPIR-V to ISA, or chooses to do the DCE in SPIR-V. Due to having to compose with an existing mature toolchain, rather than starting fresh, we have a slightly different flow where we reverse translate to LLVM IR and "resume" compilation from that point. Hence, the implicitly inserted never to be emitted globals, which play the role the spec constants play in your example, when coupled with the dedicated predicate expansion pass. Something similar could be added to e.g. `spirv-opt`. Thank you for the example, it is helpful.

https://github.com/llvm/llvm-project/pull/134016


More information about the llvm-commits mailing list