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