When a sin() (cos(), log(), etc.) function is called on a value of float type and the returned double value is converted to another value of float type, GCC converts this function call into a float version (sinf()) in the optimization mode. This avoids two type conversions and the float version function call usually takes less time. However, this can result in different result and therefore is unsafe.
For example, the following code produces different results using -O0 (correct), but the same results using -Ox other than -O0 (incorrect). #include <stdio.h> #include <math.h> int main() { float v = 1; printf("%.20f\n", (float)sin(v)); printf("%.20f\n", sinf(v)); } In this patch, we do this conversion only when the flag -funsafe-math-optimizations is set. The patch is shown below. thanks, Cong Index: gcc/testsuite/gcc.c-torture/execute/20030125-1.c =================================================================== --- gcc/testsuite/gcc.c-torture/execute/20030125-1.c (revision 201891) +++ gcc/testsuite/gcc.c-torture/execute/20030125-1.c (working copy) @@ -44,11 +44,11 @@ __attribute__ ((noinline)) double sin(double a) { - abort (); + return a; } __attribute__ ((noinline)) float sinf(float a) { - return a; + abort (); } Index: gcc/convert.c =================================================================== --- gcc/convert.c (revision 201891) +++ gcc/convert.c (working copy) @@ -99,7 +99,7 @@ convert_to_real (tree type, tree expr) /* Disable until we figure out how to decide whether the functions are present in runtime. */ /* Convert (float)sqrt((double)x) where x is float into sqrtf(x) */ - if (optimize + if (optimize && flag_unsafe_math_optimizations && (TYPE_MODE (type) == TYPE_MODE (double_type_node) || TYPE_MODE (type) == TYPE_MODE (float_type_node))) {
Index: gcc/testsuite/gcc.c-torture/execute/20030125-1.c =================================================================== --- gcc/testsuite/gcc.c-torture/execute/20030125-1.c (revision 201891) +++ gcc/testsuite/gcc.c-torture/execute/20030125-1.c (working copy) @@ -44,11 +44,11 @@ __attribute__ ((noinline)) double sin(double a) { - abort (); + return a; } __attribute__ ((noinline)) float sinf(float a) { - return a; + abort (); } Index: gcc/convert.c =================================================================== --- gcc/convert.c (revision 201891) +++ gcc/convert.c (working copy) @@ -99,7 +99,7 @@ convert_to_real (tree type, tree expr) /* Disable until we figure out how to decide whether the functions are present in runtime. */ /* Convert (float)sqrt((double)x) where x is float into sqrtf(x) */ - if (optimize + if (optimize && flag_unsafe_math_optimizations && (TYPE_MODE (type) == TYPE_MODE (double_type_node) || TYPE_MODE (type) == TYPE_MODE (float_type_node))) {