www.digitalmars.com         C & C++   DMDScript  

D.gnu - Floating point constant folding bug?

reply Johannes Pfau <nospam example.com> writes:
writefln("%f\n%f", cast(float)cast(int)float.infinity, float.infinity);

writes
---
2147483648.000000
inf
---

-fdump-tree-original
---
writefln ({.length=5, .ptr="%f\n%f"}, 2.147483647e+9,  Inf);
---

The same conversion at runtime produces the expected result.

Is this a gdc or gcc bug or is this expected?
Mar 15 2013
parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 15 March 2013 15:15, Johannes Pfau <nospam example.com> wrote:

 writefln("%f\n%f", cast(float)cast(int)float.infinity, float.infinity);

 writes
 ---
 2147483648.000000
 inf
 ---

 -fdump-tree-original
 ---
 writefln ({.length=5, .ptr="%f\n%f"}, 2.147483647e+9,  Inf);
 ---

 The same conversion at runtime produces the expected result.

 Is this a gdc or gcc bug or is this expected?

GCC bug, try the same in C and see if it produces the same result. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Mar 15 2013
parent reply Johannes Pfau <nospam example.com> writes:
Forget what I've said, I somehow read that code as a bitwise/reinterpret
cast but of course the code does an integer/float conversion so it's
probably OK.

This is more interesting:

---
    float f = float.infinity;
    float f2 = float.max;
    int i = cast(int) f;
    int i2 = cast(int) f2;
    writefln("0x%x == int.min(0x%x)", i, int.min);
    writefln("0x%x == int.max(0x%x)", cast(int)float.infinity, int.max);
    writefln("0x%x == int.min(0x%x)", i2, int.min);
    writefln("0x%x == int.max(0x%x)", cast(int)float.max, int.max);
---

const folding expands to int.max, but the same code at runtime expands
to int.min. C does not define what happens if too large float values
are cast into ints. Do you know if D somehow defines this?

(There's a failing test in the test suite which assumes that the result
is int.min in all cases above)
Mar 15 2013
parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 15 March 2013 18:35, Johannes Pfau <nospam example.com> wrote:

 Forget what I've said, I somehow read that code as a bitwise/reinterpret
 cast but of course the code does an integer/float conversion so it's
 probably OK.

 This is more interesting:

 ---
     float f = float.infinity;
     float f2 = float.max;
     int i = cast(int) f;
     int i2 = cast(int) f2;
     writefln("0x%x == int.min(0x%x)", i, int.min);
     writefln("0x%x == int.max(0x%x)", cast(int)float.infinity, int.max);
     writefln("0x%x == int.min(0x%x)", i2, int.min);
     writefln("0x%x == int.max(0x%x)", cast(int)float.max, int.max);
 ---

 const folding expands to int.max, but the same code at runtime expands
 to int.min. C does not define what happens if too large float values
 are cast into ints. Do you know if D somehow defines this?

 (There's a failing test in the test suite which assumes that the result
 is int.min in all cases above)

I think the behaviour from DMD is more incidental than intended. They use C's FLOAT_INFINITY, etc, macros. But because of the way it's written, gcc doesn't optimise the use of the value. Whereas with gdc, because it uses gcc's real_t types, values of extreme numbers may change to be either 2147483647 or -2147483648 depending on whether -O is used. As I said, in most cases you can see the same behaviour in C. I can see if there might be some flag I can set to try and make gcc's codegen more safe for floats, but that might have impact on runtime. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Mar 15 2013
parent reply Johannes Pfau <nospam example.com> writes:
Am Fri, 15 Mar 2013 20:20:14 +0000
schrieb Iain Buclaw <ibuclaw ubuntu.com>:

 On 15 March 2013 18:35, Johannes Pfau <nospam example.com> wrote:
 
 Forget what I've said, I somehow read that code as a
 bitwise/reinterpret cast but of course the code does an
 integer/float conversion so it's probably OK.

 This is more interesting:

 ---
     float f = float.infinity;
     float f2 = float.max;
     int i = cast(int) f;
     int i2 = cast(int) f2;
     writefln("0x%x == int.min(0x%x)", i, int.min);
     writefln("0x%x == int.max(0x%x)", cast(int)float.infinity,
 int.max); writefln("0x%x == int.min(0x%x)", i2, int.min);
     writefln("0x%x == int.max(0x%x)", cast(int)float.max, int.max);
 ---

 const folding expands to int.max, but the same code at runtime
 expands to int.min. C does not define what happens if too large
 float values are cast into ints. Do you know if D somehow defines
 this?

 (There's a failing test in the test suite which assumes that the
 result is int.min in all cases above)

I think the behaviour from DMD is more incidental than intended. They use C's FLOAT_INFINITY, etc, macros. But because of the way it's written, gcc doesn't optimise the use of the value. Whereas with gdc, because it uses gcc's real_t types, values of extreme numbers may change to be either 2147483647 or -2147483648 depending on whether -O is used. As I said, in most cases you can see the same behaviour in C. I can see if there might be some flag I can set to try and make gcc's codegen more safe for floats, but that might have impact on runtime.

I think in this case GCC might intentionally use saturating overflows. I just found this message: http://gcc.gnu.org/ml/gcc-patches/2003-09/msg02090.html (This doesn't explain though what the test (constfold.d:test2) in the dmd testsuite is actually supposed to test...)
Mar 15 2013
parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 15 March 2013 22:00, Johannes Pfau <nospam example.com> wrote:

 Am Fri, 15 Mar 2013 20:20:14 +0000
 schrieb Iain Buclaw <ibuclaw ubuntu.com>:

 On 15 March 2013 18:35, Johannes Pfau <nospam example.com> wrote:

 Forget what I've said, I somehow read that code as a
 bitwise/reinterpret cast but of course the code does an
 integer/float conversion so it's probably OK.

 This is more interesting:

 ---
     float f = float.infinity;
     float f2 = float.max;
     int i = cast(int) f;
     int i2 = cast(int) f2;
     writefln("0x%x == int.min(0x%x)", i, int.min);
     writefln("0x%x == int.max(0x%x)", cast(int)float.infinity,
 int.max); writefln("0x%x == int.min(0x%x)", i2, int.min);
     writefln("0x%x == int.max(0x%x)", cast(int)float.max, int.max);
 ---

 const folding expands to int.max, but the same code at runtime
 expands to int.min. C does not define what happens if too large
 float values are cast into ints. Do you know if D somehow defines
 this?

 (There's a failing test in the test suite which assumes that the
 result is int.min in all cases above)

I think the behaviour from DMD is more incidental than intended. They use C's FLOAT_INFINITY, etc, macros. But because of the way it's written, gcc doesn't optimise the use of the value. Whereas with gdc, because it uses gcc's real_t types, values of extreme numbers may change to be either 2147483647 or -2147483648 depending on whether -O is used. As I said, in most cases you can see the same behaviour in C. I can see if there might be some flag I can set to try and make gcc's codegen more safe for floats, but that might have impact on runtime.

I think in this case GCC might intentionally use saturating overflows. I just found this message: http://gcc.gnu.org/ml/gcc-patches/2003-09/msg02090.html (This doesn't explain though what the test (constfold.d:test2) in the dmd testsuite is actually supposed to test...)

It tests an incidental feature of dmd-generated code that got turned into a test case. Rather than something defined in the spec. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Mar 15 2013