------- 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

Reply via email to