When the program shown below starts, it displays ok:
j= 0 9007199616606190.000000 = x k= 0 9007199616606190.000000 = [x] r= 31443101 0.000000 = m*(x-[x])
But when the commented line (ie //if (argc>1) r = atol(argv[1]); ) is uncommented, it produces:
j= 20000 9007199616606190.000000 = x k= 17285 9007199616606190.000000 = [x] r= 31443101 0.000000 = m*(x-[x])
although this line should have no effect since argc>1 is false. Has anyone received a plausible explanation for this problem? Is it reproducible in any other systems?
#include <stdio.h> #include <stdlib.h> #include <math.h> int main(int argc, char *argv[]) { int j, k, m=10000; double r=31443101, jroot=sqrt(83), x; //if (argc>1) r = atol(argv[1]); x = r * r * jroot; j = m*(x-floor(x)); k = floor(m*(x-floor(x))); printf ("j= %9d %24.6f = x\n", j, x); printf ("k= %9d %24.6f = [x]\n", k, floor(x)); printf ("r= %9.0f %24.6f = m*(x-[x]) \n", r, m*(x-floor(x))); return 0; }
Note. test system = AMD Athlon 64 5200+ system with Linux 2.6.35.14-96.fc14.i686 (i.e., bootable to run 32-bit OS on 64-bit HW) with gcc (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4)
Update - A few hours ago I posted a comment that the code generated with and without the if differed only in stack offsets and some missing code. Now I believe that the comment is not entirely correct; that is, this is true for non-optimized code, but not true for the -O3 code that I executed.
Effect of the optimization switch on the problem:
- -O0: both versions of programs work fine
- -O2 or -O3: The commentary version has an error as described above, where
j=20000 and k=17285 - -O1: The comment version has
j=20000 (error) and k=0 (OK)
In any case, looking at the -O3 -S code lists, the two cases differ mainly in skipped if code and stack offsets to the line to call floor , after which the c-if code has another fstpl than the code without the code:
... ;; code without comment: fmul %st, %st(1) fxch %st(1) fstpl (%esp) fxch %st(1) fstpl 48(%esp) fstpl 32(%esp) call floor movl $.LC2, (%esp) fnstcw 86(%esp) movzwl 86(%esp), %eax ... ... ;; versus code with comment: fmul %st, %st(1) fxch %st(1) fstpl (%esp) fxch %st(1) fstpl 48(%esp) fstpl 32(%esp) fstpl 64(%esp) call floor movl $.LC3, (%esp) fnstcw 102(%esp) movzwl 102(%esp), %eax ...
I did not understand the reason for the difference.