================
@@ -9102,6 +9102,15 @@ bool InitializationSequence::Diagnose(Sema &S,
 
   case FK_ConversionFailed: {
     QualType FromType = OnlyArg->getType();
+    // __amdgpu_feature_predicate_t can be explicitly cast to the logical op
+    // type, although this is almost always an error and we advise against it
----------------
AlexVlx wrote:

Let's take these piecewise. Your first example actually works / those are 
equivalent. I think the danger here is assuming that the sort of easy to type 
examples we are playing with are representative of where issues show up - they 
are not. The cases where things break down are somewhat more intricate - I 
chose pushing into a container via a function with side-effects on purpose. 

I suspect that the sense that something is tied to optimiser behaviour is due 
to my reply above, which perhaps was insufficiently clear - apologies. I was 
trying to explain why making it trivial to store these as `bool`eans somewhere 
leads to having to run large parts of the optimisation pipeline. There is no 
dependence on the optimiser, `O0` and `Ox` behave in the same way in what 
regards the predicates, because we have a dedicated pass that unconditionally 
runs early in the pipeline, irrespective of optimisation level, and either 
succeeds at the needed folding or fails and diagnoses.

The __has_builtin counter-example actually does not work and cannot work, 
please see: <https://gcc.godbolt.org/z/7G5Y1d85b>. It fact, it's the essence of 
why we need these, the fact that that pattern does not work and cannot work, 
and yet it is extremely useful. Those situations are materially different 
because:

- this is not about calling some generic omni-available code, it's about 
calling target specific code - this has to be statically decided on in the 
compiler, we MUST know if the target can run it or not, which is why this is a 
target specific BI;
- furthermore, the `...later...` bit is pretty important: what happens on that 
path? do you pass the boolean by reference into an `extern` function which gets 
linked in at run time (i.e. no idea what it does)? do you mutate the value 
based on a run time value? if you do any of those, your distant `has_builtin` 
variable no longer reflects the predicate, which is the issue;
- the answer to the above bit might be "make it `constexpr`" - sure, but then 
it rolls back into not working for abstract targets / resolving these late, 
which is the gap in functionality with things like the `__has_builtin` macro 
that these try to fill.

` I think the default expectation is that you should be able to query the 
processor information at any point you want, store the results anywhere you 
want, and use them later with the expected semantics` - I don't think this is 
actually the case, unless what you are thinking about is `__builtin_cpu_is`, 
which is a different mechanism that operates at execution time.

Overall, this might be less profound / convoluted than we've made it seem:

1. use the predicates as intended, things work;
2. explicitly cast to `bool` and then stash:
    a) if the chain formed from the point of cast to the final point of use can 
be folded in a terminator, for all uses of 
        the cast, happy days;
    b) if for a chain from point of cast to final point of use folding fails 
(because you passed your value to an 
        opaque function, modified it based on a run time value etc.), you get 
an error and a diagnostic.

This is independent from optimisation level, and essentially matches what you 
would have to do with `__has_builtin` as well (except you'd have to make the 
stashed variable `constexpr` and then make the control structure be something 
like `if constexpr`).

https://github.com/llvm/llvm-project/pull/134016
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to