There is some clever code in convert_to_real that converts
double d;
(float)floor(d)
to
floorf((float)d)
(on targets where floor and floorf are considered builtins.)
This is wrong, because the (float)d conversion normally uses
round-to-nearest and can round up to the next integer. For example:
double d = 1024.0 - 1.0 / 32768.0;
extern double floor(double);
extern float floorf(float);
extern int printf(const char*, ...);
int main() {
double df = floor(d);
float f1 = (float)floor(d);
printf("floor(%f) = %f\n", d, df);
printf("(float)floor(%f) = %f\n", d, f1);
return 0;
}
with -O2.
The transformation is also done for ceil, round, rint, trunc and
nearbyint.
I'm not a math guru, but it looks like ceil, rint, trunc and nearbyint
are
also unsafe for this transformation. round may be salvageable.
Comments? Should I preserve the buggy behavior with -ffast-math?