Re: Gcc floating-point optimizer weird behaviour

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 
If I understand correctly, you have an environment in which a function returning double is actually returning 80-bit floating point.  The key section of code is:

double d = f(A, B, C, D), e = f(A, B, C, D);
 int d_gt_e = d > e, d_lt_e = d < e;

Notice that d would tend to be stored (demoted to a true double) before the second call to f() because the second call to f() does not preserve the 80-bit register in which the first call to f() returned its result.  

But the comparisons don't need to trash that register, so d can be reloaded from double (having been changed by being stored as double) while e was never stored nor reloaded.  So the values are consistently different.  So it is just as expected that d != e and that d>e gives an answer consistent with d<e (one is true so the other must be false).

The trick is that after calling another function, the 80-bit value of e will also be demoted to match d.

 
 

On 01/25/15, Vladimir A. Pavlov wrote:

Hello.

I've found a strange behaviour of gcc (4.8.5-20150122) optimizer
relating floating-point on x86 (32 bit).

I have two files (a.c and f.c, look below). In a.c:main() there are two
variables, d and e, assigned the same function call result. But the
optimizer causes their values to be different.

I understand that all floating-point operations are actually calculated
by the processor using long double type then casting the result to the
target type (double in our case). But in our case both variables are of
type double and the same casting should happen which would lead to the
equal values.

Is it gcc bug or do I misunderstand how floating-point arithmetics
works in C and what is allowed for optimizer?

If it's my fault can anyone explain (e.g. provide links) please why
it's an allowed behaviour of optimizer?

I met the similar issue in spead-dreams-2 2.1.0 (in SOLID-2.0 library)
where it makes playing almost impossible leading to game hangs after
10-60 seconds of playing.

Roughly speaking, in SOLID-2.0 code the issue causes a function to
think that in an array every value is greater than the next one and the
last value is greater than the first one (which is obviously not
possible). (I can provide the details if necessary).

How to reproduce the issue:
$ cat >a.c <<EOF
#include <stdio.h>

#define A 0.0026963419787128717
#define B 820.72515869140625
#define C 0.02293671065653248
#define D 398.6868896484375

double f (double a, double b, double c, double d);

double g (double a, double b, double c, double d)
{ return a*b + c*d; }

int main () {
 double d = f(A, B, C, D), e = f(A, B, C, D);
 int d_gt_e = d > e, d_lt_e = d < e;
 printf("d>e=%d d<e=%d\n%.40lf\n%.40lf\n", d_gt_e, d_lt_e, d, e);
 return 0;
}
EOF
$ cat >f.c <<EOF
double g (double a, double b, double c, double d);

double f (double a, double b, double c, double d)
{ return g(a, b, c, d); }
EOF
$ cc -O1 a.c f.c
$ ./a.out
d>e=1 d<e=0
11.3575215287845274758637970080599188804626
11.3575215287845274758637970080599188804626

$ cc -v
Using built-in specs.
COLLECT_GCC=cc
COLLECT_LTO_WRAPPER=/usr/lbin/gcc/i686-pc-linux-gnu/4.8.5/lto-wrapper
Target: i686-pc-linux-gnu
Configured with: ../gcc-4.8-20131128/configure --target=i686-pc-linux-gnu --prefix=/usr --libexecdir=/usr/lbin --with-native-system-header-dir=/usr/include --with-gxx-include-dir=/usr/include/c++/4.8.5 --enable-languages=c,c++,objc,obj-c++ --with-linker-hash-style=gnu --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-objc-gc --disable-checking --disable-nls --with-system-zlib
Thread model: posix
gcc version 4.8.5 20150122 (prerelease) (GCC) 

Actual output:
d>e=1 d<e=0

Expected output:
d>e=0 d<e=0

Or expected output (it's still incorrect but I would understand it;
what I don't understand is why the comparison results are different):
d>e=1 d<e=1

--
Vladimir A. Pavlov




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux