C++ Logo

std-discussion

Advanced search

Re: Is forward progress guarantee still useful?

From: Ell <ell_se_at_[hidden]>
Date: Wed, 17 Sep 2025 11:11:29 +0300
On 9/17/25 09:54, Nate Eldredge via Std-Discussion wrote:
>
>
>> On Sep 17, 2025, at 00:21, Yongwei Wu <wuyongwei_at_[hidden]> wrote:
>>
>> On Wed, 17 Sept 2025 at 13:39, Nate Eldredge
>> <nate_at_[hidden] <mailto:nate_at_[hidden]>> wrote:
>>
>> On Sep 16, 2025, at 20:11, Yongwei Wu via Std-Discussion <std-
>> discussion_at_[hidden] <mailto:std-
>> discussion_at_[hidden]>> wrote:
>>>
>>> I am wondering what are the real-world benefits of the forward
>>> progress guarantee today.... They probably existed, but are they
>>> still there? (If not, should we ...?)
>>
>> I thought the canonical example was something like https://
>> godbolt.org/z/G6onne47x: <https://godbolt.org/z/G6onne47x:>
>>
>> [[gnu::pure]] int update(int) ; // opaque but known to have no
>> side effects
>>
>> void foo(void) {
>> int r = 1;
>> while (r != 0) {
>> r = update(r);
>> }
>> // no further use of r
>> }
>>
>> Instead of an opaque pure function, you may imagine replacing
>> `update` with a sufficiently complicated expression having no side
>> effects, such that the compiler cannot reasonably determine if it
>> will return 0 within finitely many iterations.
>>
>> With the "forward progress guarantee" (I assume you refer
>> to https://eel.is/c++draft/intro.progress#1 <https://eel.is/c+
>> +draft/intro.progress#1>) the compiler can and will delete the
>> loop as dead code, and optimize `foo()` into just a `ret`.
>> Without it (use `-fno-finite-loops`), the compiler must emit code
>> to actually execute all iterations of the loop, since if it turns
>> out the loop does not terminate, the function `foo()` must never
>> return.
>>
>> Such examples, where we have complicated code to compute a value
>> that is not used, must be very common in auto-generated code, and
>> people rely heavily on compilers to optimize it out.
>>
>>
>> I can hardly imagine it is "common". Who would have written such code
>
> A program or script, or perhaps a complicated template.
>

Doesn't have to be particularly complicated:

    void some_algorithm (auto&& nums) {
        assert (std::ranges::min (nums) >= 0);

        // ...
    }

    template void some_algorithm (std::list<unsigned>&);

https://godbolt.org/z/MMK5GPaaf



>> especially when it never terminates?
>
> The useful case is when it *does* terminate, and the programmer can
> prove this, but the compiler cannot. The loop may appear in several
> instances, some in which the result is used, and some in which it is
> not. The programmer expects the compiler to delete the instances for
> which the result is unused.
>
> Assuming that the loop does (theoretically) terminate, the result is
> correct with or without the guarantee. But the guarantee allows the
> "unused" instances to be optimized out. Otherwise they must be executed
> anyway, even if unused, which wastes time.
>
>> I would argue that an infinite loop is better, in that it would alert
>> the programmer that something is broken.
>
> Again, we're assuming here that the code is *not* broken.
>
>> To me (and I believe to most C++ programmers), this is a surprising
>> optimization. I really have difficulty imagining it is truly useful.
>>
>> There are other examples showing this is a bad optimization, say, the
>> infamous disproof of Fermat's last theorem:
>>
>> https://godbolt.org/z/TbYbWzhGq <https://godbolt.org/z/TbYbWzhGq>
>>
>> Yup, it is a bit artificial too, in that a good verification function
>> should return three states instead of two. But I do not think it is
>> more artificial than programmers writing useless loops and hoping
>> the compiler will get rid of it automagically.
>
> Of course, the Fermat example already has UB due to signed integer overflow.
>
>> Anyway, I honestly want to see real-world benefits of the forward
>> progress guarantee. Not theoretical ones, please.
>
> I'll see what I can find.
>
>
>

Received on 2025-09-17 08:11:43