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