C++ Logo

std-discussion

Advanced search

Re: Is forward progress guarantee still useful?

From: David Brown <david.brown_at_[hidden]>
Date: Fri, 19 Sep 2025 08:55:34 +0200
On 19/09/2025 06:09, Yongwei Wu via Std-Discussion wrote:
> On Fri, 19 Sept 2025 at 04:26, Thiago Macieira via Std-Discussion
> <std-discussion_at_[hidden]> wrote:
>>
>> On Wednesday, 17 September 2025 23:28:45 Pacific Daylight Time Yongwei Wu via
>> Std-Discussion wrote:
>>> First, programmers in general do not want to *rely on* compiler
>>> optimizations to get rid of unused code.
>>
>> Yes, they do. ALL the time, especially in template code but anything that is
>> not nailed down and may have some generality too. For example, anything that
>> may depend on a configuration-time feature check. Given we have the __cpp
>> macros describing the availability of features, this applies to the C++
>> Standard too.
>
> Arguable, especially if -O0 demonstrates completely different
> behaviour. I would normally use #if or if constexpr to ensure
> something is really eliminated, even if optimization is completely
> turned off.
>

Certainly people usually aim to have known dead code eliminated by "if
constexpr" or "#if". These have different semantics than eliminating
dead code by compiler optimisation (for example, lines skipped by #if
don't have to be valid code).

But there are occasions when that is not possible, or not preferable.
An example was given earlier using an "is_debug_build" symbol. That
symbol might be defined in a header somewhere - perhaps sometimes as a
variable that can be changed at runtime, perhaps as a constant
expression or pre-processor symbol. The code using it can use "if" and
developers can rely on optimising compilers removing the code if a
constant expression is used.

I have done /exactly/ that in my code. And my code often has size
restrictions (for running from the internal flash of a small
microcontroller) - I rely on the compiler to do its job well. Without
such optimisations and with the dead code retained, the code will still
be correct in terms of its execution - but if it is too big for the
target space, it cannot do its job. (Executable size is one of these
characteristics that can be important to the user, but is not part of
the language defined observable behaviours.)

You can certainly have a different opinion about how many C++
programmers care about optimisations, or what kind of optimisations they
care about - I have never seen any statistics or studies giving even
vague numbers about such things. But you can't sensibly argue that dead
code elimination after passes like function inlining and constant
propagation is not important for at least /some/ people.


Regarding optimisation, if compilation with -O0 demonstrates completely
different /observable/ behaviour from compilation with -O1 or any other
optimisation flag, then either there's a bug in the compiler, or there
is a bug in the user's code. If the language-defined behaviours when
compiling correct code (which does not execute UB) differ depending on
the optimisations, except between unspecified but equally allowed
behaviours, then these are not optimisation flags but flags controlling
semantic variations of the language. Optimisations - barring bugs in
the compiler and/or the user's code - affect characteristics that are
/not/ part of the language specified behaviours. Most obviously, they
affect runtime speed and executable size. But the code must still do
the same thing - it just does it slower or faster.

Received on 2025-09-19 06:55:40