Tomasz Kaminski [Monday, 20 October 2025, 10:47:12 CEST]:
> I think this is something worth discussing on the usual list channel, so
> people not looking
> at forge will also get notice, so posting in here:
>
> In the patch, there is a lot of code that looks like this:
> if (__builtin_is_constant_evaluated() || (__builtin_constant_p(__arg0) &&
> __builtin_constant_p(__arg1))
> {
> // some compile-time compatible coded
> }
> else
> {
> // optimized version
> }
To explain the "why": If a function is implemented using a target-specific
builtin and that builtin's operation is not understood by the optimizer, then
such a call acts as an optimization barrier (very similar to using inline
asm). If we could resolve that, I'd happily delete all my const-prop branches.
I guess you could also say that I should file a lot of missed optimization
PRs. I didn't, because I'm unsure whether that's the best use of everyone's
time in these cases. I do report missed optimizations when I think it's
worthwhile. To me there's quite a list of important issues I'm waiting on
before I feel like I should report more. But please feel free to disagree.
> The __builtin_is_constant_evaluated part is uncontroversial, as we are
> guaranteed that the code
> will get folded at compile time, and never be evaluated at runtime.
It's typically also necessary since the code in the else branch cannot be
called in a constant expression.
> However, we assume that if the
> arg0 and arg1 are building constant, the compiler will constant fold the
> code. But it is not required to
> do so. I believe that you have verified that this is the case on most
> common optimization level, but
> I think this may lead to surprises for users, for example on debug builds.
On -O0 builds __builtin_constant_p(whatever) is unconditionally false, AFAIK.
And yes, my main workflow is to verify asm output (while having unit test
compiling in the background).
There is another pattern:
if (__builtin_is_constant_evaluated())
// #1
else
{
if (__builtin_constant_p(x))
{
_ReturnType __r = ...; // #2
if (__builtin_constant_p(__r)) // #2a
return __r;
}
// #3
}
#1 makes it work in constant expressions
#2 allows the optimizer to understand and optimize / constant-fold
#3 uses target builtins
However, in this pattern, if #2a fails then constant-folding didn't work as
expected and the branch becomes dead code. Only #3 remains.
This pattern only works if we expect complete constant-folding of the
operation. In some cases, e.g. 'x / 2', __builtin_constant_p of the result
cannot be true (unless __builtin_constant_p(x) is also true). But a shift by 1
needs to be preferred over a conversion to double -> 2x divpd -> conversion to
int. (For the division case there's PR90993.)
> This also does not scale well for-used defined types.
You mean, once simd::vec<UDT> gets voted into C++? I don't see a problem from
what that paper is proposing.
> However, I also do not want to simply ask you
> to drop this functionality, so what I suggest instead is to introduce:
>
> template<typename... _Args>
> [[__gnu__::__always_inline__]]
> constexpr __should_constprop(const _Args&... __args)
> {
> if conteval { // of if (__builtin_is_constant_evaluated())
> return true;
> }
> return __is_constprop(__args) && ...;
> }
I can try.
In general, I am afraid of instantiating more templates in the simd
implementation because I'm constantly fighting with my unit tests blowing out
of any reasonable space and time usage.
> The _M_isconstprop member on simd, should become __is_constprop hidden
> friend.
Sounds good.
> […]
> This would allow us to control the constant propagation from arguments in
> one place, and disable it if it's found problematic.
I believe we'd want to disable on a case by case basis. But I understand that
my liberal use of __builtin_constant_p is novel for libstdc++ code and should
be treated with care. (Except for std::experimental::simd)
--
──────────────────────────────────────────────────────────────────────────
Dr. Matthias Kretz https://mattkretz.github.io
GSI Helmholtz Center for Heavy Ion Research https://gsi.de
std::simd
──────────────────────────────────────────────────────────────────────────