Date: Wed, 17 Sep 2025 06:54:58 +0000
> 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:
>>
>> [[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) 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.
> 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
>
> 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.
>
> 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:
>>
>> [[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) 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.
> 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
>
> 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 06:55:04