Compile the following code with options -march=armv7-a -mthumb -Os
struct A
{
int f0,f1,f2,f3,f4,f5;
};
void func(const struct A* p)
{
printf("%d %d %d %d %d %d %d",
p->f0, p->f1, p->f2, p->f3, p->f4,
(p->f2 == 0) ? 0 : p->f2 * 100 / (p->f1 + p->f2 + p->f3), p->f5);
}
GCC generates:
func:
push {r4, r5, r6, r7, lr}
ldr r4, [r0, #8]
mov r5, r0
ldr r2, [r0, #0]
ldr r6, [r0, #4]
sub sp, sp, #28
ldr r7, [r0, #12]
ldr r3, [r0, #16]
mov r0, r4
cbz r4, .L2
adds r1, r7, r6
movs r0, #100
adds r1, r1, r4
muls r0, r4, r0
str r2, [sp, #20] // A
str r3, [sp, #16] // B
bl __aeabi_idiv
ldr r2, [sp, #20] // C
ldr r3, [sp, #16] // D
.L2:
str r3, [sp, #4]
mov r1, r2
ldr r3, [r5, #20]
mov r2, r6
str r0, [sp, #8]
ldr r0, .L4
str r3, [sp, #12]
mov r3, r4
str r7, [sp, #0]
bl printf
add sp, sp, #28
pop {r4, r5, r6, r7, pc}
.L5:
.align 2
.L4:
.word .LC0
.size func, .-func
.section .rodata.str1.1,"aMS",%progbits,1
.LC0:
.ascii "%d %d %d %d %d %d %d\000"
Instructions AB spills register r2 and r3 to stack. Instructions CD reloads r2
and r3 from stack. Register r2 contains p->f0, r3 contains p->f4. After
function call to __aeabi_idiv, pointer p is still in register r5. So we can
directly reload r2 and r3 through register r5, avoiding spill them to stack.
--
Summary: unnecessary register spill
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=43187