Compile the attached source code with options -Os -march=armv5te -mthumb Gcc generates following code snippet:
... cmp r0, r2 bne .L5 b .L15 <--- A .L9: ldr r3, [r1] cmp r3, #0 beq .L7 str r0, [r1, #8] b .L8 .L7: str r3, [r1, #8] .L8: ldr r1, [r1, #4] b .L12 <---- C .L15: mov r0, #1 <--- B .L12: cmp r1, r2 <---- D bne .L9 ... inst A jump to B then fall through to D inst C jump to D there is no other instructions jump to instruction B, so we can put inst B just before A, then A jump to D, and C can be removed. There are two possible functions can potentially do this optimization. They are merge_blocks_move and try_forward_edges. Function try_forward_edges can only redirect a series of forwarder blocks. It can't move the target blocks before the forwarder blocks. In function merge_blocks_move only when both block b and c aren't forwarder blocks then can they be merged. In this case block A is a forwarder block, so they are not merged. -- Summary: missed merge of basic blocks 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=41004