February 08, 2015
https://issues.dlang.org/show_bug.cgi?id=13474

--- Comment #7 from yebblies <yebblies@gmail.com> ---
change(-1e100) calculates its result at real precision, then returns it in
ST(0).  It is duplicated via the stack (truncating to double) but the full
precision value is then added with (1e104) and due to the extra precision they
no longer cancel exactly, instead resulting in -1.3987216024025249e+0087.

This value causes the later addition 10000 to be ignored, leading to the wrong result and the assertion failure.

So, is it invalid to return a double in ST0 without first truncating it to double precision?

--
February 08, 2015
https://issues.dlang.org/show_bug.cgi?id=13474

--- Comment #8 from yebblies <yebblies@gmail.com> ---
(In reply to Илья Ярошенко from comment #6)
> F foo(F)(F c, F d) {
>     c += d;
>     c += d;
>     return c;
> }
> 
> void test1() {
>     alias F = double;
>     enum F d = (cast(F)(2)) ^^ (F.max_exp - 1);
>     assert(foo(-d, d) == d);
> }

That doesn't fail for me on win32 with -O.

--
February 08, 2015
https://issues.dlang.org/show_bug.cgi?id=13474

--- Comment #9 from Илья Ярошенко <ilyayaroshenko@gmail.com> ---
(In reply to yebblies from comment #8)
> (In reply to Илья Ярошенко from comment #6)
> > F foo(F)(F c, F d) {
> >     c += d;
> >     c += d;
> >     return c;
> > }
> > 
> > void test1() {
> >     alias F = double;
> >     enum F d = (cast(F)(2)) ^^ (F.max_exp - 1);
> >     assert(foo(-d, d) == d);
> > }
> 
> That doesn't fail for me on win32 with -O.

Can you open https://github.com/D-Programming-Language/dmd/pull/3992 please?

--
February 08, 2015
https://issues.dlang.org/show_bug.cgi?id=13474

--- Comment #10 from yebblies <yebblies@gmail.com> ---
(In reply to Илья Ярошенко from comment #9)
> 
> Can you open https://github.com/D-Programming-Language/dmd/pull/3992 please?

Why?  The results are still visible here: https://auto-tester.puremagic.com/pull-history.ghtml?projectid=1&repoid=1&pullid=3992

I can reproduce that failure on linux64, so it might be an xmm bug.  Not failing on win32 suggests it's a different bug.

--
February 08, 2015
https://issues.dlang.org/show_bug.cgi?id=13474

--- Comment #11 from Илья Ярошенко <ilyayaroshenko@gmail.com> ---
OK.
This is DMD optimization bug too.
DMD compiles (-d)+(d+d) instead of ((-d)+d)+d.

--
February 08, 2015
https://issues.dlang.org/show_bug.cgi?id=13474

--- Comment #12 from yebblies <yebblies@gmail.com> ---
(In reply to Илья Ярошенко from comment #11)
> OK.
> This is DMD optimization bug too.
> DMD compiles (-d)+(d+d) instead of ((-d)+d)+d.

Yes.  Is there a bug report for that specific bug?

--
February 08, 2015
https://issues.dlang.org/show_bug.cgi?id=13474

--- Comment #13 from Илья Ярошенко <ilyayaroshenko@gmail.com> ---
Yes. https://issues.dlang.org/show_bug.cgi?id=13485

--
February 09, 2015
https://issues.dlang.org/show_bug.cgi?id=13474

--- Comment #14 from Илья Ярошенко <ilyayaroshenko@gmail.com> ---
(In reply to yebblies from comment #7)
> change(-1e100) calculates its result at real precision, then returns it in
> ST(0).  It is duplicated via the stack (truncating to double) but the full
> precision value is then added with (1e104) and due to the extra precision
> they no longer cancel exactly, instead resulting in
> -1.3987216024025249e+0087.
> 
> This value causes the later addition 10000 to be ignored, leading to the wrong result and the assertion failure.
> 
> So, is it invalid to return a double in ST0 without first truncating it to double precision?

I think so. Looks like LDC and GDC have truncation.

--
February 16, 2015
https://issues.dlang.org/show_bug.cgi?id=13474

yebblies <yebblies@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Hardware|x86                         |All
            Summary|32 bit DMD optimizer FP     |Discard excess precision
                   |arithmetic bug              |when returning double in
                   |                            |x87 register
           Severity|blocker                     |enhancement

--- Comment #15 from yebblies <yebblies@gmail.com> ---
I've thought about it some more, and I don't think this is behaving incorrectly given what D does specify about floating point behaviour.

1. Nothing in any ABI I can find specifies that return values must be truncated.  (gcc does have a -ffloat-store flag)

2. D allows floating point intermediates to be at a higher precision than the operand types.  This doesn't explicitly include return values, but...

3. D allows inlining, which means even if return values are explicitly excluded from (2) then it still can't be relied upon.

So, I conclude that calculating and returning floating point values at a higher precision than specified is allowed in D.

The code where you hit the problem can be fixed by:

1. Fixing the tests to not rely on maximum precision.
2. Using a wrapper on function calls where precision must be forced. (An
intrinsic to force precision loss has been discussed in the past)
3. Lobbying Walter for a language change enforcing this in some way.

I've changed the platform as this behaviour is possible on other platforms too even if the current code generator never hits those cases.

--
February 16, 2015
https://issues.dlang.org/show_bug.cgi?id=13474

--- Comment #16 from yebblies <yebblies@gmail.com> ---
Here is the other bug which is relevant: issue 9937.

--