[Bug c/46180] New: CSE across calls to fesetround()
zimmerma+gcc at loria dot fr
gcc-bugzilla@gcc.gnu.org
Tue Oct 26 09:47:00 GMT 2010
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46180
Summary: CSE across calls to fesetround()
Product: gcc
Version: 4.4.4
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
AssignedTo: unassigned@gcc.gnu.org
ReportedBy: zimmerma+gcc@loria.fr
with this program:
#include <stdio.h>
#include <fenv.h>
int main()
{
double x = 3.0;
fesetround (FE_DOWNWARD);
printf ("1/3 arrondi vers -Inf: %.17f\n", 1.0 / x);
fesetround (FE_UPWARD);
printf ("1/3 arrondi vers +Inf: %.17f\n", 1.0 / x);
}
I get with gcc 4.4.4:
tarte% gcc -O1 ex.c -lm
tarte% ./a.out
1/3 arrondi vers -Inf: 0.33333333333333331
1/3 arrondi vers +Inf: 0.33333333333333331
while -O0 gives the expected results:
tarte% ./a.out
1/3 arrondi vers -Inf: 0.33333333333333331
1/3 arrondi vers +Inf: 0.33333333333333337
Kaveh Ghazi believes this is due to incorrect CSE across calls to fesetround().
Also the following program:
#include <stdio.h>
#include <math.h>
#include <fenv.h>
int main()
{
double x = 3.0;
fesetround (FE_DOWNWARD);
printf ("sin(3) arrondi vers -Inf: %.17f\n", sin (x));
fesetround (FE_UPWARD);
printf ("sin(3) arrondi vers +Inf: %.17f\n", sin (x));
fesetround (FE_TONEAREST);
printf ("sin(3) arrondi au plus proche : %.17f\n", sin (x));
fesetround (FE_TOWARDZERO);
printf ("sin(3) arrondi vers 0 : %.17f\n", sin (x));
}
gives with -O0:
tarte% gcc -O0 ex2.c -lm; ./a.out
sin(3) arrondi vers -Inf: 2.78837698122124511
sin(3) arrondi vers +Inf: 0.14112000805986724
sin(3) arrondi au plus proche : 0.14112000805986721
sin(3) arrondi vers 0 : 2.78837698122124511
And with -O1 or -O2:
tarte% gcc -O1 ex2.c -lm ; ./a.out
sin(3) arrondi vers -Inf: 0.14112000805986721
sin(3) arrondi vers +Inf: 0.14112000805986721
sin(3) arrondi au plus proche : 0.14112000805986721
sin(3) arrondi vers 0 : 0.14112000805986721
Kaveh Ghazi found that when compiling the code with -fdump-tree-all
-frounding-math -lm -O1 the
body of main() is transformed into the code below:
main ()
{
double D.4342;
<bb 2>:
fesetround (1024);
D.4342_2 = sin (3.0e+0);
printf (&"sin(3) arrondi vers -Inf: %.17f\n"[0], D.4342_2);
fesetround (2048);
printf (&"sin(3) arrondi vers +Inf: %.17f\n"[0], D.4342_2);
fesetround (0);
printf (&"sin(3) arrondi au plus proche : %.17f\n"[0], D.4342_2);
fesetround (3072);
printf (&"sin(3) arrondi vers 0 : %.17f\n"[0], D.4342_2);
return;
}
which clearly shows that sin(3.0) is computed only once, although the rounding
mode changed.
Paul Zimmermann
PS: a separate issue is that the rounding of sin(3) towards 0 and -Inf are
completely out of the allowed range [-1,1] for -O0...
More information about the Gcc-bugs
mailing list