http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47855
Summary: missed cbnz optimization Product: gcc Version: 4.6.0 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: target AssignedTo: unassig...@gcc.gnu.org ReportedBy: car...@google.com Target: arm-linux-androideabi Created attachment 23440 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=23440 testcase Compile the attached source code with options -march=armv7-a -mthumb -Os, GCC 4.6 generates pnm_gethdr: @ args = 0, pretend = 0, frame = 8 @ frame_needed = 0, uses_anonymous_args = 0 push {r0, r1, r2, r4, r5, lr} mov r5, r0 mov r4, r1 bl foo2 cmp r0, #0 // A bne .L13 // B adds r1, r4, #4 mov r0, r5 bl foo3 cmp r0, #0 // C bne .L13 // D add r1, r4, #8 mov r0, r5 bl foo1 cbnz r0, .L13 // E ldr r0, [r4, #0] bl pnm_type cmp r0, #2 beq .L3 mov r0, r5 add r1, sp, #4 bl pnm_getsintstr cbz r0, .L4 b .L13 .L3: movs r3, #1 str r3, [sp, #4] .L4: ldr r3, [sp, #4] cmp r3, #0 bge .L5 negs r3, r3 str r3, [r4, #16] movs r3, #1 b .L14 .L5: str r3, [r4, #16] movs r3, #0 .L14: strb r3, [r4, #20] ldr r0, [r4, #0] bl pnm_type cmp r0, #0 beq .L8 blt .L7 cmp r0, #2 bgt .L7 movs r3, #1 movs r0, #0 str r3, [r4, #12] b .L2 .L8: movs r3, #3 str r3, [r4, #12] b .L2 .L7: bl abort .L13: mov r0, #-1 .L2: pop {r1, r2, r3, r4, r5, pc} The branch distance of cbz/cbnz is 126 bytes. The size of the whole function is 124 bytes. So instructions AB and CD can be replaced by cbnz r0, .L13 same as instruction E.