With new versions of gcc from trunk (like last snapshot SVN 171894), I
observe very bad code from register allocator.

As a test case assume

bar.c:

int a (void);

int b (void)
{
    return a()+1;
}

which, on avr, could be compiled as

b:
.L__stack_usage = 0
        rcall a  ;  6   *call_value_insn/2      [length = 1]
        adiw r24,1       ;  13  *addhi3/2       [length = 1]
/* epilogue start */
        ret      ;  23  return  [length = 1]

what actually happens is this:
b:
        push r28         ;  27  *pushqi/1       [length = 1]
        push r29         ;  28  *pushqi/1       [length = 1]
        rcall .  ;  32  *addhi3_sp_R_pc2        [length = 1]
        in r28,__SP_L__  ;  33  *movhi_sp/2     [length = 2]
        in r29,__SP_H__
.L__stack_usage = 4
        rcall a  ;  6   *call_value_insn/2      [length = 1]
        mov r18,r24      ;  25  *movhi/1        [length = 2]
        mov r19,r25
        subi r18,lo8(-(1))       ;  8   *addhi3/4       [length = 2]
        sbci r19,hi8(-(1))
        std Y+2,r19      ;  26  *movhi/3        [length = 2]
        std Y+1,r18
        ldd r24,Y+1      ;  22  *movqi/4        [length = 1]
        ldd r25,Y+2      ;  23  *movqi/4        [length = 1]
/* epilogue start */
        pop __tmp_reg__  ;  38  *addhi3_sp_R_pc2        [length = 2]
        pop __tmp_reg__
        pop r29  ;  39  popqi   [length = 1]
        pop r28  ;  40  popqi   [length = 1]
        ret      ;  41  return_from_epilogue    [length = 1]
        .size   b, .-b

Just before .ira, in pass .asmcons, RTL looks like this:

(call_insn 6 2 7 2 (parallel [
            (set (reg:HI 24 r24)
                (call (mem:HI (symbol_ref:HI ("a") [flags 0x41]
<function_decl 0xb7508680 a>) [0 a S2 A8])
                    (const_int 0 [0])))
            (use (const_int 0 [0]))
        ]) bar.c:6 123 {*call_value_insn}
     (nil)
    (nil))

(insn 8 7 22 2 (set (reg:HI 46)
        (plus:HI (reg:HI 24 r24)
            (const_int 1 [0x1]))) bar.c:6 22 {*addhi3}
     (nil))

(insn 22 8 23 2 (set (reg:QI 24 r24)
        (subreg:QI (reg:HI 46) 0)) bar.c:7 4 {*movqi}
     (nil))

(insn 23 22 16 2 (set (reg:QI 25 r25 [+1 ])
        (subreg:QI (reg:HI 46) 1)) bar.c:7 4 {*movqi}
     (expr_list:REG_DEAD (reg:HI 46)
        (nil)))

(insn 16 23 0 2 (use (reg/i:HI 24 r24)) bar.c:7 -1
     (nil))


reg:HI 46 gets allocated to a stack slot, which eventually causes the
bulky code. There are plenty of free registers. Why isn't anyone of
them used instead? Seems the problems are related to SUBREGs which are
not handled properly and always end up in mem.

(call_insn 6 2 7 2 (parallel [
            (set (reg:HI 24 r24)
                (call (mem:HI (symbol_ref:HI ("a") [flags 0x41]
<function_decl 0xb7508680 a>) [0 a S2 A8])
                    (const_int 0 [0])))
            (use (const_int 0 [0]))
        ]) bar.c:6 123 {*call_value_insn}
     (nil)
    (nil))

(insn 25 7 8 2 (set (reg:HI 18 r18)
        (reg:HI 24 r24)) bar.c:6 10 {*movhi}
     (nil))

(insn 8 25 26 2 (set (reg:HI 18 r18)
        (plus:HI (reg:HI 18 r18)
            (const_int 1 [0x1]))) bar.c:6 22 {*addhi3}
     (nil))

(insn 26 8 22 2 (set (mem/c:HI (plus:HI (reg/f:HI 28 r28)
                (const_int 1 [0x1])) [3 %sfp+1 S2 A8])
        (reg:HI 18 r18)) bar.c:6 10 {*movhi}
     (nil))

(insn 22 26 23 2 (set (reg:QI 24 r24)
        (mem/c:QI (plus:HI (reg/f:HI 28 r28)
                (const_int 1 [0x1])) [3 %sfp+1 S1 A8])) bar.c:7 4 {*movqi}
     (nil))

(insn 23 22 16 2 (set (reg:QI 25 r25 [+1 ])
        (mem/c:QI (plus:HI (reg/f:HI 28 r28)
                (const_int 2 [0x2])) [3 %sfp+2 S1 A8])) bar.c:7 4 {*movqi}
     (nil))

(insn 16 23 24 2 (use (reg/i:HI 24 r24)) bar.c:7 -1
     (nil))



The recent changed in IRA cause other sorts of trouble as

http://gcc.gnu.org/PR48435

Because the SUBREGs always end up in mem, register conatraints in
linline-asm can never be satisfied.

Johann

== command line

avr-gcc bar.c -da -S -Os -dp

== configuration

Target: avr
Configured with: ../../gcc.gnu.org/trunk/configure --target=avr
--prefix=some-prefix --enable-languages=c,c++ --disable-libssp
--disable-libada --disable-nls --disable-shared
Thread model: single
gcc version 4.7.0 20110404 (experimental) (GCC)

Reply via email to