Eliminating unnecessary loads on SPARC + IA64
john.gill@quadrics.com
john.gill@quadrics.com
Thu Mar 3 11:11:00 GMT 2005
I'm investigating some performance issues with the SPARC
and IA64 ports. I've included some sample code and the
resulting assembler produced on both SPARC + IA64.
In the function below, writec; fp->length is loaded
twice causing a fairly expensive stall for load data
in the processor pipeline. See the code.c below.
But why doesn't gcc recognise that fp->Length is already
kept in a register? Is this down to pointer aliasing?
GCC is treating variable, Length as if it was declared
volatile. Are there target description macros (in
the relevant backends of gcc) that I can tweak to
get better code? I'm sure other peoples' codes would
get a speedup.
Note that I can remove the additional loads by rewriting the code and
declaring a local variable on the stack like so:
void
writec_new (unsigned char c, FP *fp)
{
int idx = fp->Length;
fp->ptr[fp->Length] = c;
fp->Length = ++idx;
}
But it is unreasonable to rewrite our code base ...
Cheers
John
code.c (gcc -O2 -S code.c -o code.s)
===============================================
typedef struct
{
unsigned char *ptr;
int CurrPos;
int Length;
int pack;
} FP;
void
writec (unsigned char c, FP *fp)
{
fp->ptr[fp->Length] = c;
++fp->Length;
}
=================================================
code.s (SPARC)
=================================================
.file "code.c"
.section ".text"
.align 4
.global writec
.type writec, #function
.proc 020
writec:
!#PROLOGUE# 0
!#PROLOGUE# 1
ld [%o1+8], %o4 <<<<<<<<<<<< fp->Length Loaded here
ld [%o1], %o5
stb %o0, [%o5+%o4]
ld [%o1+8], %g1 <<<<<<<<<<<< Why do we reload fp->Length it's in %o4
add %g1, 1, %g1
retl
st %g1, [%o1+8]
.size writec, .-writec
.ident "GCC: (GNU) 3.4.2"
===================================================
code.s (IA64)
===================================================
.file "code.c"
.pred.safe_across_calls p1-p5,p16-p63
.text
.align 16
.global writec#
.proc writec#
writec:
.prologue
.body
adds r16 = 12, r33
ld8 r15 = [r33]
;;
ld4 r14 = [r16] <<<<<<<<< fp->Length loaded into r14
;;
sxt4 r14 = r14 <<<<<<<<< Just a sign extend insn
;;
add r15 = r15, r14
;;
st1 [r15] = r32
ld4 r14 = [r16] <<<<<<<< fp->Length reloaded here into r14 but it hasn't changed
;;
adds r14 = 1, r14
;;
st4 [r16] = r14
br.ret.sptk.many b0
.endp writec#
.ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.2 2.96-128.7.2)"
===================================================
More information about the Gcc-help
mailing list