Date: Wed, 26 Nov 2025 15:13:52 +0100
The mailing list had a discussion earlier this year on suppressing fills for
the new erroneous read features of C++26.
I would like to reopen it, because it is a real problem, and if we end up
having major performance regressions with C++26, it will hamper adoption.
(with recent gcc-16 preview, ~25% of benchmark runtime was spend in these
fills).
To start off let me say where we need this functionality in Qt:
We have work buffers for instance of pixels, and functions optimized to read
special image formats into them, convert image formats out of them, and
optimized functions operating on the buffers, This is done this way because
working on a single pixel at a time doesnt scale well with SIMD, and having
templated routines of all possible combinations of input, output, and
operations, would scale quadratic (O(formats) * O(formats) * O(operations)).
So we need routines that work on an unknown length of pixels in an
intermediate representation, and this is simply achieved with work buffers.
Note at no point did I say we need uninitialized reads, because we do not. The
issue is the functions are not trivial, and some times in different
compilation units (sometimes with different compilation targets). The compiler
has NO WAY of knowing we fill the buffers before reading from them. So we need
to tell the compiler not to fill the buffer, but that we will, to avoid a
major regression with C++26.
Fortunately the standard committee recognized some people might want to read
uninitialized data (which is not the case here), but we can abuse the same
[[indeterminate]] attribute as a hint to the compiler that we will fill the
buffer ourselves.
The issue is that for some silly reason this is only allowed on stack
variables. And not on member variables. Supposedly because member variables
sometimes are initialized any way, though that is irrelevant to the issue.
So how can we avoid severe C++26 performance degradations?
I think the easiest it to allow [[indeterminate]] everywhere even where it
only sometimes has any effect. You could also call it [[maybe_indeterminate]]
if you want to be extra verbose.
Alternatively, give us another way to tell the compiler a buffer will be
filled by a function call, perhaps a pre condition/promise not to read, and
post condition/promise that the buffer data is set on function exit. This
could even be verified by sanitizers, but seems a bit beyond the possible
scope of C++26 this late.
Best regards
Allan
the new erroneous read features of C++26.
I would like to reopen it, because it is a real problem, and if we end up
having major performance regressions with C++26, it will hamper adoption.
(with recent gcc-16 preview, ~25% of benchmark runtime was spend in these
fills).
To start off let me say where we need this functionality in Qt:
We have work buffers for instance of pixels, and functions optimized to read
special image formats into them, convert image formats out of them, and
optimized functions operating on the buffers, This is done this way because
working on a single pixel at a time doesnt scale well with SIMD, and having
templated routines of all possible combinations of input, output, and
operations, would scale quadratic (O(formats) * O(formats) * O(operations)).
So we need routines that work on an unknown length of pixels in an
intermediate representation, and this is simply achieved with work buffers.
Note at no point did I say we need uninitialized reads, because we do not. The
issue is the functions are not trivial, and some times in different
compilation units (sometimes with different compilation targets). The compiler
has NO WAY of knowing we fill the buffers before reading from them. So we need
to tell the compiler not to fill the buffer, but that we will, to avoid a
major regression with C++26.
Fortunately the standard committee recognized some people might want to read
uninitialized data (which is not the case here), but we can abuse the same
[[indeterminate]] attribute as a hint to the compiler that we will fill the
buffer ourselves.
The issue is that for some silly reason this is only allowed on stack
variables. And not on member variables. Supposedly because member variables
sometimes are initialized any way, though that is irrelevant to the issue.
So how can we avoid severe C++26 performance degradations?
I think the easiest it to allow [[indeterminate]] everywhere even where it
only sometimes has any effect. You could also call it [[maybe_indeterminate]]
if you want to be extra verbose.
Alternatively, give us another way to tell the compiler a buffer will be
filled by a function call, perhaps a pre condition/promise not to read, and
post condition/promise that the buffer data is set on function exit. This
could even be verified by sanitizers, but seems a bit beyond the possible
scope of C++26 this late.
Best regards
Allan
Received on 2025-11-26 14:17:22
