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