[Bug target/45252] New: unnecessary register move

carrot at google dot com gcc-bugzilla@gcc.gnu.org
Wed Aug 11 03:40:00 GMT 2010


Compile the following code with options -march=armv7-a -mthumb -Os

struct S{
    int f1;
    int reserved[3];
};

void ts()
{
        struct S map;
        map.f1 = 0;
        foo(&map);
}

GCC 4.6 generates:

ts:
        push    {r0, r1, r2, r3, r4, lr}
        add     r0, sp, #16        // A
        movs    r3, #0
        str     r3, [r0, #-16]!    // B
        mov     r0, sp             // C
        bl      foo
        add     sp, sp, #20
        pop     {pc}

After instruction B, register r0 already contains the value of sp, so
instruction C is not required, as shown in following.

ts:
        push    {r0, r1, r2, r3, r4, lr}
        add     r0, sp, #16        
        movs    r3, #0
        str     r3, [r0, #-16]!    
        bl      foo
        add     sp, sp, #20
        pop     {pc}

The RTL insns before IRA

(insn 12 5 6 2 (set (reg/f:SI 134)
        (reg/f:SI 25 sfp)) src/ts.c:9 694 {*thumb2_movsi_insn}
     (nil))

(insn 6 12 8 2 (set (mem/s/c:SI (pre_modify:SI (reg/f:SI 134)
                (plus:SI (reg/f:SI 134)
                    (const_int -16 [0xfffffffffffffff0]))) [3 map.f1+0 S4 A64])
        (reg:SI 133)) src/ts.c:9 694 {*thumb2_movsi_insn}
     (expr_list:REG_DEAD (reg:SI 133)
        (expr_list:REG_INC (reg/f:SI 134)
            (expr_list:REG_EQUAL (const_int 0 [0])
                (nil)))))

(insn 8 6 9 2 (set (reg:SI 0 r0)
        (reg/f:SI 134)) src/ts.c:10 694 {*thumb2_movsi_insn}
     (expr_list:REG_DEAD (reg/f:SI 134)
        (expr_list:REG_EQUAL (plus:SI (reg/f:SI 25 sfp)
                (const_int -16 [0xfffffffffffffff0]))
            (nil))))

It shows the address register in insn 6 can be used in insn 8 directly. At RA
stage, physical register r0 is assigned to pseudo register r134, so insn 8
should be
    mov  r0, r0
which should be removed in later pass.

But gcc also finds out from note that r134 is equal to (sfp - 16) which is
equal to sp at the same time. So it generates 
    mov r0, sp


There is even better result:

ts:
        push    {r0, r1, r2, r3, r4, lr}
        movs    r3, #0
        str     r3, [sp]
        mov     r0, sp
        bl      foo
        add     sp, sp, #20
        pop     {pc}

It contains same number of instructions, but the instructions are simpler and
shorter. Actually the IL was in this form after expand

(insn 5 2 6 2 (set (reg:SI 133)
        (const_int 0 [0])) src/ts.c:9 694 {*thumb2_movsi_insn}
     (nil))

(insn 6 5 7 2 (set (mem/s/c:SI (plus:SI (reg/f:SI 25 sfp)
                (const_int -16 [0xfffffffffffffff0])) [3 map.f1+0 S4 A64])
        (reg:SI 133)) src/ts.c:9 694 {*thumb2_movsi_insn}
     (expr_list:REG_DEAD (reg:SI 133)
        (expr_list:REG_EQUAL (const_int 0 [0])
            (nil))))

(insn 7 6 8 2 (set (reg/f:SI 134)
        (plus:SI (reg/f:SI 25 sfp)
            (const_int -16 [0xfffffffffffffff0]))) src/ts.c:10 4 {*arm_addsi3}
     (nil))

(insn 8 7 9 2 (set (reg:SI 0 r0)
        (reg/f:SI 134)) src/ts.c:10 694 {*thumb2_movsi_insn}
     (expr_list:REG_DEAD (reg/f:SI 134)
        (expr_list:REG_EQUAL (plus:SI (reg/f:SI 25 sfp)
                (const_int -16 [0xfffffffffffffff0]))
            (nil))))

After pass auto_inc_dec, (sfp - 16) is identified as an opportunity for
auto_inc_dec optimization. But it doesn't bring any benefit for this case, and
causes more complex instructions.


-- 
           Summary: unnecessary register move
           Product: gcc
           Version: 4.6.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=45252



More information about the Gcc-bugs mailing list