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

Reply via email to