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