================ @@ -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