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: unassig...@gcc.gnu.org ReportedBy: zimmerma+...@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...