Compile the following code with options -O2

extern "C" void foo(int a[4]);
extern "C" void bar(int a, int b, int c, int d)
{
    int v[4] = {a,b,c,d};
     foo(v);
     foo(v);
}


GCC generates

bar:
        stmfd   sp!, {r4, lr}
        .save {r4, lr}
.LCFI0:
        .pad #16
        sub     sp, sp, #16
.LCFI1:
        mov     lr, #0
        add     ip, sp, #8
        str     lr, [ip], #4
        str     r0, [sp, #0]
        mov     r0, sp
        str     lr, [ip, #0]
        stmib   sp, {r1, r2, r3}        @ phole stm
        bl      foo
        mov     r0, sp
        mov     r4, sp             // A
        bl      foo
        add     sp, sp, #16
        ldmfd   sp!, {r4, lr}
        bx      lr

Instruction A move sp to r4, but r4 is never used again.

If compile the code with options -Os, the result is even worse:

bar:
        stmfd   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr}
        .save {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr}
.LCFI0:
        mov     r6, r0
        mov     r5, r1
        mov     r4, r2
        mov     r1, #0
        mov     r2, #16
        mov     r0, sp
        mov     r8, r3
        bl      memset
        mov     r0, sp
        str     r6, [sp, #0]
        str     r5, [sp, #4]
        str     r4, [sp, #8]
        str     r8, [sp, #12]
        bl      foo
        mov     r0, sp
        mov     r7, sp
        bl      foo
        ldmfd   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr}
        bx      lr

It calls memset to set the array to 0, then store parameters to that array. It
is quite inefficient.


-- 
           Summary: unnecessary register move
           Product: gcc
           Version: 4.5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: carrot at google dot com
 GCC build triplet: i686-linux
  GCC host triplet: i686-linux
GCC target triplet: arm-eabi


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42500

Reply via email to