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?

Reply via email to