Gcc 2.95.2, ARM target -
amolitor@visi.com
amolitor@visi.com
Thu Dec 16 20:24:00 GMT 1999
Earlier this evening, I reported two bugs against the version
2.7.2.3 compiler (which is about 2 years old). The same bugs exist in the
2.95..2 compiler (which is what, 3 months old?)
BUG NUMBER ONE:
Input code:
/* ------------- */
void
A(tag)
unsigned short tag;
{
bar(tag);
}
/* ------------- */
Command: 'gcc -S foo.c'
Output code:
_A:
@ args = 0, pretend = 0, frame = 4
@ frame_needed = 1, current_function_anonymous_args = 0
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4
sub sp, sp, #4
mov r3, r0
strb r3, [fp, #-14]
mov r3, r3, asr #8
strb r3, [fp, #-13]
ldr r3, [fp, #-14] @ movhi No, not "movhi", BOOM. Unaligned load.
@ ^^^^^ compiler inserted comment
@ What the hell is movhi, anyways?
@ This is not a SPARC.
mov r2, r3, asl #16
mov r3, r2, lsr #16
mov r0, r3
bl _bar
L2:
ldmea fp, {fp, sp, pc}^
Problem analysis: I dunno, some meathead doesn't understand aligned
data or something? Lay out the freaking stack from on word boundaries
please.
BUG NUMBER TWO:
Input code:
/* -------------------- */
V(var1, var1)
char *var;
char *var2;
{
/* This is fairly idiomatic code, not wild and crazy stuff
like using a short int as an argument. */
if(var1) {
strcpy(var2, var1);
} else {
var2[0] = '\0';
}
}
/* -------------------- */
Command: 'gcc -O2 -S foo.c'
Output code:
_V:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 1, current_function_anonymous_args = 0
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4
subs r1, r0, #0
movne r0, r2
blne _strcpy
L3:
streqb r1, [r2, #0] @ The else clause may or may not happen
@ depending on what strcpy does to the
@ flags.
ldmea fp, {fp, sp, pc}^
Problem analysis: Excessively trivial analysis of "when can I use
condition linstructions to implement an if statement". Here's
a hint - 'it's only a few instructions' isn't good enough. As a
matter of fact, the generated code (even if it were right) probably
isn't any faster on most targets than more naive code with a branch
in it.
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4
subs r1, r0, #0
beq L3
mov r0, r2
bl _strcpy
B L4
L3:
strb r1, [r2, #0]
L4:
ldmea fp, {fp, sp, pc}^
Then, of course, you can lift the ldmea instruction up and replace
the branch to it (this is what we in the trade call a "correct optimization"):
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4
subs r1, r0, #0
beq L3
mov r0, r2
bl _strcpy
ldmea fp, {fp, sp, pc}^
L3:
strb r1, [r2, #0]
ldmea fp, {fp, sp, pc}^
The else case of this code is simply faster (unless your
target has insanely slow branches), as well as being correct, and the
if case trades a 'beq' not taken for a 'streqb' not executed, which
is probably a wash on most targets.
Nobody actually USES this thing, do they? Ha ha. Actually, I
know of at least two companies doing major projects based on it.
No wonder their code is so unstable.
I guess I'll be ponying up a few bucks to ARM Ltd.
More information about the Gcc-bugs
mailing list