https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81147

--- Comment #7 from Georg-Johann Lay <gjl at gcc dot gnu.org> ---
With your options (no -fverbose-asm for brevity), avr-gcc from trunk gives me

_Z3abcv:
        push r28         ;  19  pushqi1/1       [length = 1]
        push r29         ;  20  pushqi1/1       [length = 1]
         ; SP -= 5       ;  24  *addhi3_sp      [length = 3]
        rcall .
        push __tmp_reg__
        push __tmp_reg__
        in r28,__SP_L__  ;  25  *movhi/8        [length = 2]
        in r29,__SP_H__
/* prologue: function */
/* frame size = 5 */
/* stack size = 7 */
.L__stack_usage = 7
        ldi r24,lo8(97)  ;  5   movqi_insn/2    [length = 1]
        std Y+3,r24      ;  6   movqi_insn/3    [length = 1]
        ldi r24,lo8(32)  ;  7   movqi_insn/2    [length = 1]
        std Y+4,r24      ;  8   movqi_insn/3    [length = 1]
        std Y+5,r24      ;  10  movqi_insn/3    [length = 1]
        movw r24,r28     ;  18  *movhi/1        [length = 1]
        adiw r24,1       ;  11  *addhi3/3       [length = 1]
        call _Z3fooI3seqIS0_I1AS1_ES1_EEvRT_     ;  12  call_insn/2     [length
= 2]
/* epilogue start */
         ; SP += 5       ;  30  *addhi3_sp      [length = 5]
        pop __tmp_reg__
        pop __tmp_reg__
        pop __tmp_reg__
        pop __tmp_reg__
        pop __tmp_reg__
        pop r29  ;  31  popqi   [length = 1]
        pop r28  ;  32  popqi   [length = 1]
        ret      ;  33  return_from_epilogue    [length = 1]
        .size   _Z3abcv, .-_Z3abcv
        .ident  "GCC: (GNU) 8.0.0 20170718 (experimental)"

Your are passing a reference of a storage class auto object to foo, which is
basically the same as taking the address of such a variable.  The address of
such a variable can only be taken if it's in memory, hence that variable is
instanciated in the frame of the current function.

On AVR, frames are rather expensive.  The frame setup in the prologue is insns
19, 20, 24, 25.  The epilogue to pop the frame is insns 30, 31, 32, 33.   So
you have 8 insns (which result in eben more instructions, 14 in this case to be
precise) just to get the frame.  Moreover, if there is a frame then there's
also a frame-pointer (Y).  This doesn't hurt in the current example, but with
higher register pressure you'll have one less "powerful" 16-bit
address-register, and it's more likely that variables are no more held in
registers but will be spilled to the frame, and that any non-frame address will
circle in and out of Z, the only capable address register left.  AVR is not a
64-bit bolide, it's just a poor, tiny 8-bit µC... You'll have to live with
that.

Reply via email to