Thread overview
Overly clever constant folding
Dec 10, 2022
John Colvin
Dec 10, 2022
Walter Bright
Dec 11, 2022
Iain Buclaw
Dec 11, 2022
Iain Buclaw
Dec 11, 2022
deadalnix
Dec 12, 2022
Walter Bright
Dec 12, 2022
Timon Gehr
December 10, 2022

Is this the "constant fold at higher precision and break all your IEEE-754 expectations" madness again? Or something else?

void main()
{
    auto a = long.min;
    auto b = long.max;
    auto c = 0.0;
    writeln((long.min + long.max) + 0.0); // -1
    writeln(long.min + (long.max + 0.0)); // -1
    writeln(long.min + cast(double)(long.max)); // -1
    writeln((a + b) + c); // -1
    writeln(a + (b + c)); // 0
    writeln(a + cast(double)(b)); // 0
}

Hint for those confused: the nearest double to long.max is one greater than long.max

The 3rd one is particularly awful.

December 10, 2022
You know what's coming - please file a bugzilla issue!
December 11, 2022

On Saturday, 10 December 2022 at 21:36:42 UTC, John Colvin wrote:

>

Is this the "constant fold at higher precision and break all your IEEE-754 expectations" madness again? Or something else?

--snip--

>

Hint for those confused: the nearest double to long.max is one greater than long.max

The 3rd one is particularly awful.

This is exactly what core.math.toPrec was made for.

import core.math;
writeln((long.min + long.max) + 0.0); // -1
writeln(long.min + toPrec!double(long.max + 0.0)); // 0
writeln(long.min + toPrec!double(long.max)); //  0
December 11, 2022
On Saturday, 10 December 2022 at 23:00:28 UTC, Walter Bright wrote:
> You know what's coming - please file a bugzilla issue!

No bug needed for D, as it was decided what to do wrt CTFE floating point in 2012.

ImportC is affected though: https://issues.dlang.org/show_bug.cgi?id=23550
December 11, 2022

On Saturday, 10 December 2022 at 21:36:42 UTC, John Colvin wrote:

>

Is this the "constant fold at higher precision and break all your IEEE-754 expectations" madness again? Or something else?

[...]

It really isn't. The problem stem from DMD using real precision when doing constant folding in the frontend, without rounding intermediary results. This behavior is not correct according to floating points, and means that any change in the way DMD constant fold in the frontend can change the semantic of the program.

While fixing this after a bug report is dully provided, is certainly a path forward, it would be missing the larger point: why is constant folding done there to begin with? This leads to all kind of strange and bizarre behaviors, such as making it very unpredictable when the compiler will yell at you about unreachable code.

Today's optimizer are shockingly good at doing this kind of transformations, and duplicating the logic between the optimizer and the front will in the ideal case multiply the umber of bugs by two, but in practice much more, because DMD is not and probably never will be battle tested to the degree LLVM or GCC are.

And if take a step back to the step back, we notice that this is where the "fill a bug report" approach fails. While this approach will certainly help fix this one specific issue, it doesn't address the larger point that make this kind of issue - and many others - more likely to occur. In fact, piling up more and more complex logic under the wrong structure makes it harder and harder to replace with a newer, more sensible one.

Anyways, we need to stop constant folding in the front end, and, while we are at it, we should also stop inlining in there.

December 11, 2022
On 12/11/2022 12:39 PM, deadalnix wrote:
> why is constant folding done there to begin with?

How else are you going to have, for example, a static initializer initialized with an expression? How about `static if (expression)` ?

How can you do optimization without constant folding?


> Today's optimizer are shockingly good at doing this kind of transformations

The optimizer is doing the constant folding.


> And if take a step back to the step back, we notice that this is where the "fill a bug report" approach fails.

Not filing a bug report means the bug will never get fixed. The n.g. is not a practical bug reporting system (I know, I tried it in the early days of D).


> we should also stop inlining in there.

I do agree with that. In fact, I implemented it:

https://github.com/dlang/dmd/blob/master/compiler/src/dmd/backend/inliner.d
December 12, 2022
On 12/12/22 03:13, Walter Bright wrote:
> On 12/11/2022 12:39 PM, deadalnix wrote:
>> why is constant folding done there to begin with?
> 
> How else are you going to have, for example, a static initializer initialized with an expression? How about `static if (expression)` ?
> 
> How can you do optimization without constant folding?

I think his proposal was not to stop doing it altogether but to instead do a roundtrip through the backend for constant folding. (I guess SDC is doing CTFE by jitting with LLVM.)