For C functions with a return value GCC should store the result of the last instruction just before returning it in r0 (in order to avoid using unnecessary register moves). The new register allocation algorithm doesn't solve this problem either. --- c example --- int foo (int a, int b) { if(a+b == 0) return a-b; return b-a; } --- arm code --- --- arm-elf-gcc -S -g0 -Os -o reg-alloc.s reg-alloc.c --- foo: cmn r0, r1 rsb r3, r1, r0 rsbne r3, r0, r1 mov r0, r3 mov pc, lr --- arm code with new-ra --- --- arm-elf-gcc -S -g0 -Os -fnew-ra -o reg-alloc.s reg-alloc.c --- foo: mov r3, r0 cmn r3, r1 rsb r0, r1, r0 rsbne r0, r3, r1 mov pc, lr --- possible solution --- foo: cmn r0, r1 rsbeq r0, r1, r0 rsbne r0, r0, r1 mov pc, lr
Confirmed with gcc mainline (20030824).
This is fixed in GCC 3.4.4 as well as on mainline. This can be closed.
Still happens on the mainline: cmn r0, r1 rsb r3, r1, r0 rsbne r3, r0, r1 mov r0, r3
I suggest closing this unless reproductible on gcc 4.3.x, since at least vanilla arm-elf-gcc 4.2.2 is correct: foo: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. cmn r1, r0 rsbeq r0, r1, r0 rsbne r0, r0, r1 @ lr needed for prologue bx lr .size foo, .-foo .ident "GCC: (GNU) 4.2.2"
Can an ARM maintainer please check this bug? Comment #4 suggests this bug is fixed, but it needs re-checking now that IRA has been merged.
(In reply to comment #5) > Can an ARM maintainer please check this bug? Comment #4 suggests this bug is > fixed, but it needs re-checking now that IRA has been merged. This is now fixed on mainline even after IRA . This bug can now be closed. foo: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. mov r3, r0 cmn r1, r0 rsbeq r0, r1, r0 rsbne r0, r3, r1 bx lr .size foo, .-foo .ident "GCC: (GNU) 4.4.0 20090312 (experimental)"
(In reply to comment #6) > foo: > mov r3, r0 > cmn r1, r0 > rsbeq r0, r1, r0 > rsbne r0, r3, r1 > bx lr This appears to be the code generated at -O1 and although the return is fixed, the redundant insn has now moved to the prologue... Fortunately at -Os and -O2 the output is sensible: foo: cmn r1, r0 rsbeq r0, r1, r0 rsbne r0, r0, r1 bx lr