This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

g77 vs gcc: address calculation of arrays in loops


Please,
 

Here is the problem...

IN A FEW WORDS:

I take a simple SPEC95 loop written in Fortran that contains loads and stores from/to arrays and compile it using the g77 -O3. I obtain an assembly loop body which reduces the address computation to one instruction for each memory access (i.e. one add).
Then, I compile the *same* loop, written in C, using gcc -O3. The assembly program generated now needs two instructions to calculate each address (i.e., one add + one shift).  The execution time difference is not negligible. (~ 28%)
Why? Isn't the back-end the same for g77 and gcc?

IN DETAILS:

1. SYSTEM

uname -a
SunOS 5.6 Generic_105181-16 sun4u sparc SUNW,Ultra-1

2. COMPILERS

g77 -v
g77 version egcs-2.91.60 19981201 (egcs-1.1.1 release) (from FSF-g77 version 0.5.24-19980804)
Driving: g77 -v -c -xf77-version /dev/null -xnone
Reading specs from /opt/gnu/lib/gcc-lib/sparc-sun-solaris2.6/egcs-2.91.60/specs
gcc version egcs-2.91.60 19981201 (egcs-1.1.1 release)
 /opt/gnu/lib/gcc-lib/sparc-sun-solaris2.6/egcs-2.91.60/cpp -lang-c -v -undef -D
__GNUC__=2 -D__GNUC_MINOR__=91 -D__sparc__ -D__sun__ -D__unix__ -D__svr4__ -D__S
VR4 -D__sparc -D__sun -D__unix -Asystem(unix) -Asystem(svr4) -D_LANGUAGE_FORTRAN
 -traditional -D__GCC_NEW_VARARGS__ -Acpu(sparc) -Amachine(sparc) /dev/null /dev
/null
GNU CPP version egcs-2.91.60 19981201 (egcs-1.1.1 release) (sparc)
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /opt/gnu/sparc-sun-solaris2.6/include
 /opt/gnu/lib/gcc-lib/sparc-sun-solaris2.6/egcs-2.91.60/include
 /usr/include
End of search list.
 /opt/gnu/lib/gcc-lib/sparc-sun-solaris2.6/egcs-2.91.60/f771 -fnull-version -qui
et -dumpbase g77-version.f -version -fversion -o /var/tmp/ccxUPtyU.s /dev/null
GNU F77 version egcs-2.91.60 19981201 (egcs-1.1.1 release) (sparc-sun-solaris2.6
) compiled by GNU C version egcs-2.91.60 19981201 (egcs-1.1.1 release).
GNU Fortran Front End version 0.5.24-19980804
 /usr/ccs/bin/as -V -Qy -s -o /var/tmp/ccQEOG0K.o /var/tmp/ccxUPtyU.s
/usr/ccs/bin/as: WorkShop Compilers 4.X dev 18 Sep 1996
 /usr/ccs/bin/ld -V -Y P,/usr/ccs/lib:/usr/lib -Qy -o /var/tmp/ccdn5P1C /var/tmp
/ccQEOG0K.o /opt/gnu/lib/gcc-lib/sparc-sun-solaris2.6/egcs-2.91.60/crt1.o /opt/g
nu/lib/gcc-lib/sparc-sun-solaris2.6/egcs-2.91.60/crti.o /usr/ccs/lib/values-Xa.o
 /opt/gnu/lib/gcc-lib/sparc-sun-solaris2.6/egcs-2.91.60/crtbegin.o -L/opt/gnu/li
b/gcc-lib/sparc-sun-solaris2.6/egcs-2.91.60 -L/opt/gnu/sparc-sun-solaris2.6/lib
-L/usr/ccs/bin -L/usr/ccs/lib -L/opt/gnu/lib -lg2c -lm -lgcc -lc -lgcc /opt/gnu/
lib/gcc-lib/sparc-sun-solaris2.6/egcs-2.91.60/crtend.o /opt/gnu/lib/gcc-lib/spar
c-sun-solaris2.6/egcs-2.91.60/crtn.o
ld: Software Generation Utilities - Solaris/ELF (3.0)
 /var/tmp/ccdn5P1C
__G77_LIBF77_VERSION__: 0.5.24
@(#)LIBF77 VERSION 19970919
__G77_LIBI77_VERSION__: 0.5.24-19980920
@(#) LIBI77 VERSION pjw,dmg-mods 19980617
__G77_LIBU77_VERSION__: 0.5.24
@(#) LIBU77 VERSION 19980709

gcc -v:
Reading specs from /opt/gnu/lib/gcc-lib/sparc-sun-solaris2.6/egcs-2.91.60/specs
gcc version egcs-2.91.60 19981201 (egcs-1.1.1 release)

3. LOOP

3.1 FORTRAN
The following loop is the critical loop of the most called function (FFTZ2) of 125.turb3d CFP95 SPEC benchmark. It is inside another loop, all the variables ( except for K and LK) are double floating point.

        DO 100 K = 0, LK - 1
          X11 = X(I11+K)
          X12 = X(I11+K+N)
          X21 = X(I12+K)
          X22 = X(I12+K+N)
          T1 = X11 - X21
          T2 = X12 - X22
          Y(I21+K) = X11 + X21
          Y(I21+K+N) = X12 + X22
          Y(I22+K) = U1 * T1 - U2 * T2
          Y(I22+K+N) = U1 * T2 + U2 * T1
 100  CONTINUE

g77 generates the following assembly code:

.LL53:
        ldd [%o0+%i4],%f10
        addcc %l0,-1,%l0
        ldd [%o1+%i4],%f12
        add %o0,8,%o0
        ldd [%o2+%i4],%f6
        add %o1,8,%o1
        ldd [%o3+%i4],%f8
        fsubd %f10,%f6,%f14
        add %o3,8,%o3
        add %o2,8,%o2
        fsubd %f12,%f8,%f2
        fmuld %f18,%f14,%f4
        faddd %f10,%f6,%f10
        fmuld %f20,%f2,%f16
        faddd %f12,%f8,%f12
        std %f10,[%o4+%i5]
        add %o4,8,%o4
        fmuld %f18,%f2,%f2
        fsubd %f4,%f16,%f4
        std %f12,[%o5+%i5]
        add %o5,8,%o5
        std %f4,[%g2+%i5]
        fmuld %f20,%f14,%f14
        add %g2,8,%g2
        faddd %f2,%f14,%f2
        std %f2,[%g3+%i5]
        bpos .LL53
        add %g3,8,%g3

3.2 C LANGUAGE
Now we translate the Loop in C (using f2c and making the variable declaration non "static" but "register")

 for (k = 0; k <= i__2; ++k) {
            x11 = x[i11 + k];
            x12 = x[i11 + k + n];
            x21 = x[i12 + k];
            x22 = x[i12 + k + n];
            t1 = x11 - x21;
            t2 = x12 - x22;
            y[i21 + k] = x11 + x21;
            y[i21 + k + n] = x12 + x22;
            y[i22 + k] = u1 * t1 - u2 * t2;
            y[i22 + k + n] = u1 * t2 + u2 * t1;
/* L100: */
        }

The assembly is:

.LL16:
        add %i1,%o5,%o0
        add %g4,%o5,%o1
        sll %o0,3,%o0
        sll %o1,3,%o1
        ldd [%i4+%o1],%f4
        sll %g2,3,%o2
        ldd [%i4+%o0],%f10
        sll %g3,3,%o3
        fsubd %f10,%f4,%f8
        ldd [%i4+%o2],%f12
        add %i2,%o5,%o4
        ldd [%i4+%o3],%f14
        sll %o4,3,%o4
        fsubd %f12,%f14,%f2
        fmuld %f18,%f8,%f6
        sll %o7,3,%o2
        add %g1,%o5,%o0
        sll %o0,3,%o0
        faddd %f10,%f4,%f10
        sll %l0,3,%o1
        add %o5,1,%o5
        fmuld %f16,%f8,%f8
        add %l0,1,%l0
        faddd %f12,%f14,%f12
        std %f10,[%i5+%o4]
        add %o7,1,%o7
        add %g3,1,%g3
        fmuld %f16,%f2,%f4
        std %f12,[%i5+%o2]
        cmp %o5,%l5
        fmuld %f18,%f2,%f2
        fsubd %f6,%f4,%f6
        std %f6,[%i5+%o0]
        faddd %f2,%f8,%f2
        std %f2,[%i5+%o1]
        ble .LL16
        add %g2,1,%g2

It is evident that the first program (generated by g77) obtains each load/store address by simply incrementing each offset by 8 (double float type size) at each iteration (e.g., add %o0,8,%o0) while the other  (generated by gcc) i) adds the index of the loop (%o5) to the starting offset at each iteration and ii) multiplies the result by 8 (double float type size).i.e.,

add %i1,%o5,%o0
sll %o0,3,%o0
 

QUESTIONS:

 * is it due to the semantic difference between the Fortran DO and the C for loop constructs? If so, why in detail?
 * is it due to a bug of the gcc? (...but do not gcc and g77 share the same back-end?)
 * what else?
 

Thank you

N.Zingirian
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]