------- Additional Comments From coyote at coyotegulch dot com 2004-11-02 03:07 ------- The problem is broader.
For example, the Fortran 95 abs() intrinsic is also broken for x86_64 when compiled with -O1, as illustrated by the following Fortran 95 program (testing on my Opteron box with cvs-20041101 mainline): program cabs implicit none ! Program works if K = 8, breaks if K = 4 integer, parameter :: K = 4 complex(kind=K) :: z, c real(kind=K) :: a1, a2 z = (2.0_K, 3.0_K) ** 2.0_K c = z - (-5.0_K, 12.0_K) a1 = abs(c) a2 = sqrt(aimag(c) ** 2.0_K + real(c) ** 2.0_K) write (*,*) 'z = ', z write (*,*) 'c = ', c write (*,*) 'a1 = ', a1 write (*,*) 'a2 = ', a2 end program cabs Without optimization, I get the expected results: $ gfortran -o runme cabs.f90 $ ./runme z = ( -5.000000 , 12.00000 ) c = ( 0.000000 ,-9.5367432E-07) a1 = 9.5367432E-07 a2 = 9.5367432E-07 With -O1, the program breaks: $ gfortran -O1 -o runme cabs.f90 $ ./runme z = ( -5.000000 , 12.00000 ) c = ( 0.000000 ,-9.5367432E-07) a1 = 13.00000 a2 = 9.5367432E-07 With -O1 *AND* the unfairly maligned -ffast-math, the result is: $ gfortran -O1 -ffast-math -o runme cabs.f90 $ ./runme z = ( -5.000000 , 12.00000 ) c = ( 0.000000 ,-9.5367432E-07) a1 = 9.5367432E-07 a2 = 9.5367432E-07 The ** operation works with all three compiles; the error appears to be in the call to cabsf(). I don't believe the problem is cabsf() itself, because *both* the unoptimized and -O1 versions call cabsf(). Using -ffast-math changes the code substantially, avoiding the optimizer bug. Note that my Pentium 4 system produces correct code, using -march=pentium4 -mfpmath=sse (to correspond with the x86_64's automatic use of SSE). The code is very similar on the two architectures, save that the x86_64 uses the extended registers (and gets abs() wrong, of course). I *think* the wrong arguments are being passed to cabsf() on the x86_64 -- as evidenced by the fact that the "wrong" output is abs(c), as if the embedded subtraction did not exist. This *may* be the same problem as with the cpowl() in your C example -- incorrect arguments as opposed to bas C lib functions. I'm rather burned out tonight, but I thought I'd pass this along. If no one else runs with this, I'll keep going. I'm learning a lot about GCC internals... ;) -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17603