Efficiency of g77 generated code under egcs-970910

Toon Moene toon@moene.indiv.nluug.nl
Sun Sep 14 05:09:00 GMT 1997


Lectoribus Salutem,

Instead of generating yet another set of numbers showing g77 +  
egcs-970910 generated code performing less than that produced by  
g77-0.5.18 (de dato April 1st, 1996), I thought of showing some code  
comparisons:

Consider the following routine, borrowed from Numerical Recipes:

      subroutine resid(res,u,rhs,n)
      implicit none
      integer n
      double precision res(n,n),rhs(n,n),u(n,n)
      integer i,j
      double precision h, h2i
      h=1.d0/(n-1)
      h2i=1.d0/(h*h)
      do j = 2, n-1
         do i = 2, n-1
            res(i,j)=-h2i*(u(i+1,j)+u(i-1,j)+u(i,j+1)+u(i,j-1)-
     ,          4.d0*u(i,j))+rhs(i,j)
         enddo
      enddo
      end

This is what we get for the inner loop using g77-0.5.20:

L9:
        fmoved a5@+,fp0
        faddd a0@(-8),fp0
        faddd a3@+,fp0
        faddd a2@+,fp0
        fmoved a0@+,fp1
        fmulx fp3,fp1
        fsubx fp1,fp0
        fmulx fp2,fp0
        fnegx fp0,fp0
        movel d0,a1
        addql #8,d0
        faddd a1@,fp0
        fmoved fp0,a4@+
        dbra d3,L9

Now g77-0.5.21:

L9:
        fmoved a0@+,fp0
        faddd a3@(d2:l),fp0
        faddd a3@(d4:l),fp0
        faddd a3@(d1:l),fp0
        fmoved a1@(a3:l),fp1
        fmulx fp3,fp1
        fsubx fp1,fp0
        fmulx fp2,fp0
        fnegx fp0,fp0
        movel a6@(16),a4
        faddd a4@(d0:l),fp0
        movel a6@(8),a4
        fmoved fp0,a4@(d3:l)
        addql #8,d2
        addql #8,d0
        addqw #8,a1
        addql #8,d1
        addql #8,d4
        addql #8,d3
        dbra d5,L9

The results using g77 + egcs-970910:

L9:
        movel a6@(-16),d1
        addl a0,d1
        movel d2,d0
        addl d4,d0
        fmoved a1@(a2:l),fp1
        faddd a2@(d0:l),fp1
        movel a6@(-20),d0
        addl a0,d0
        faddd a2@(d0:l),fp1
        movel a0,d0
        addl a4,d0
        faddd a2@(d0:l),fp1
        movel a0,d0
        addl d4,d0
        fmoved a2@(d0:l),fp0
        fmulx fp3,fp0
        fsubx fp0,fp1
        fmulx fp2,fp1
        fnegx fp1,fp1
        movel a6@(-32),d0
        addl a0,d0
        movel a6@(16),a3
        faddd a3@(d0:l),fp1
        movel a6@(8),a3
        fmoved fp1,a3@(d1:l)
        addql #8,d2
        addql #8,a1
        addql #8,a0
        dbra d3,L9

Fortunately, the difference between g77 + egcs-970910 and  
g77-0.5.21 can be completely explained by the missing rerun of loop  
optimisation in the former compiler.

The difference between g77-0.5.20 and g77-0.5.21 cannot be  
completely explained, but at least part of it (perhaps as much as 90  
%) is covered by the following change in g77-0.5.21 due to  
including GNAT's backend changes:

*************** expand_expr (exp, target, tmode, modifie
*** 4618,4684 ****
                               convert (sizetype, low_bound)));

-       if ((TREE_CODE (index) != INTEGER_CST
-            || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
-           && (! SLOW_UNALIGNED_ACCESS || ! get_inner_unaligned_p  
(exp)))
-         {
-           /* Nonconstant array index or nonconstant element size, and
-              not an array in an unaligned (packed) structure field.
-              Generate the tree for *(&array+index) and expand that,
-              except do it in a language-independent way
-              and don't complain about non-lvalue arrays.
-              `mark_addressable' should already have been called
-              for any array for which this case will be reached.  */
-
-           /* Don't forget the const or volatile flag from the array
-              element. */
-           tree variant_type = build_type_variant (type,
-                                                   TREE_READONLY (exp),
-                                                    
TREE_THIS_VOLATILE (exp));
-           tree array_adr = build1 (ADDR_EXPR,
-                                    build_pointer_type  
(variant_type), array);
-           tree elt;
-           tree size = size_in_bytes (type);
-
-           /* Convert the integer argument to a type the same size  
as sizetype
-              so the multiply won't overflow spuriously.  */
-           if (TYPE_PRECISION (index_type) != TYPE_PRECISION (sizetype))
-             index = convert (type_for_size (TYPE_PRECISION  
(sizetype), 0),
-                              index);
-
-           if (TREE_CODE (size) != INTEGER_CST
-               && contains_placeholder_p (size))
-             size = build (WITH_RECORD_EXPR, sizetype, size, exp);
-
-           /* Don't think the address has side effects
-              just because the array does.
-              (In some cases the address might have side effects,
-              and we fail to record that fact here.  However, it  
should not
-              matter, since expand_expr should not care.)  */
-           TREE_SIDE_EFFECTS (array_adr) = 0;
-
-           elt
-             = build1
-               (INDIRECT_REF, type,
-                fold (build (PLUS_EXPR,
-                             TYPE_POINTER_TO (variant_type),
-                             array_adr,
-                             fold
-                             (build1
-                              (NOP_EXPR,
-                               TYPE_POINTER_TO (variant_type),
-                               fold (build (MULT_EXPR, TREE_TYPE  
(index),
-                                            index,
-                                            convert (TREE_TYPE (index),
-                                                     size))))))));;
-
-           /* Volatility, etc., of new expression is same as old
-              expression.  */
-           TREE_SIDE_EFFECTS (elt) = TREE_SIDE_EFFECTS (exp);
-           TREE_THIS_VOLATILE (elt) = TREE_THIS_VOLATILE (exp);
-           TREE_READONLY (elt) = TREE_READONLY (exp);
-
-           return expand_expr (elt, target, tmode, modifier);
-         }
-

Richard Kenner told us (g77-alpha) that this code was removed  
because it actually caused a bug, not just because it's ugly.
Note: This patch is with respect to gcc-2.7.2.3.

My intuition tells me it is the fold( ... ) calls in the above code  
that cause the difference; unfortunately, one cannot just rerun  
`constant folding' as a separate compiler pass to `prove' this.

HTH,
Toon.



More information about the Gcc mailing list