In current trunk (r170704), 4.4-branch and 4.5-branch I observe the
following optimization issue in IRA: It saves regs in the frame
instead of in callee-saved registers which would be much smarter.
In the following C source, foo2 is compiled as desired (push/pop r17
to save r24). In foo1 and foo3 r24 is saved in the frame. The old
lreg/greg allocator of 4.3-branch generates fine code for all functions.
Saving a reg in the frame should only be done if running out of hard
registers because setting up frame(pointer) and accessing frame is
very expensive on avr.
Maybe someone can give me a hint what's going wrong.
gcc configured
/gnu/source/gcc.gnu.org/trunk/configure --target=avr --prefix=...
--enable-languages=c,c++ --disable-libssp --disable-libada
--disable-nls --disable-shared
and sources compiled
with -Os -mmcu=atmega8 -c -dp -da -fira-verbose=100
/*****************************************************/
void bar0 (void);
void bar1 (char);
void foo1 (char x)
{
bar0();
bar1(x);
}
char foo2 (char x)
{
bar1(x);
return x;
}
char foo3 (char x)
{
bar0();
return x;
}
/*****************************************************/
FYI, I attached IRA dumps and asm output
As far I can see target avr gives appropriate costs for memory and
register moves.
IRA printout is as follows:
Thanks for any hints on that!
Johann
===========================================================
Building IRA IR
Pass 0 for finding pseudo/allocno costs
a0 (r42,l0) best GENERAL_REGS, cover GENERAL_REGS
a0(r42,l0) costs: POINTER_X_REGS:0,0 POINTER_Z_REGS:0,0
BASE_POINTER_REGS:0,0 POINTER_REGS:0,0 ADDW_REGS:0,0
SIMPLE_LD_REGS:0,0 LD_REGS:0,0 NO_LD_REGS:0,0 GENERAL_REGS:0,0 MEM:4000
Pass 1 for finding pseudo/allocno costs
r42: preferred GENERAL_REGS, alternative NO_REGS, cover GENERAL_REGS
a0(r42,l0) costs: POINTER_X_REGS:0,0 POINTER_Z_REGS:0,0
BASE_POINTER_REGS:0,0 POINTER_REGS:0,0 ADDW_REGS:0,0
SIMPLE_LD_REGS:0,0 LD_REGS:0,0 NO_LD_REGS:0,0 GENERAL_REGS:0,0 MEM:4000
Insn 10(l0): point = 0
Insn 9(l0): point = 2
Insn 7(l0): point = 4
Insn 2(l0): point = 6
a0(r42): [3..6]
Compressing live ranges: from 9 to 2 - 22%
Ranges after the compression:
a0(r42): [0..1]
+++Allocating 0 bytes for conflict table (uncompressed size 4)
;; a0(r42,l0) conflicts: regions=1, blocks=3, points=2
allocnos=1 (big 0), copies=0, conflicts=0, ranges=1
**** Allocnos coloring:
Loop 0 (parent -1, header bb0, depth 0)
bbs: 2
all: 0r42
modified regnos: 42
border:
Pressure: GENERAL_REGS=1
Reg 42 of GENERAL_REGS has 6 regs less
Pushing a0(r42,l0)
Popping a0(r42,l0) -- assign reg 24
Disposition:
0:r42 l0 24
New iteration of spill/restore move
+++Costs: overall -4000, reg -4000, mem 0, ld 0, st 0, move 0
+++ move loops 0, new jumps 0
===========================================================
Building IRA IR
Pass 0 for finding pseudo/allocno costs
a0 (r43,l0) best GENERAL_REGS, cover GENERAL_REGS
a0(r43,l0) costs: POINTER_X_REGS:0,0 POINTER_Z_REGS:0,0
BASE_POINTER_REGS:0,0 POINTER_REGS:0,0 ADDW_REGS:0,0
SIMPLE_LD_REGS:0,0 LD_REGS:0,0 NO_LD_REGS:0,0 GENERAL_REGS:0,0 MEM:6000
Pass 1 for finding pseudo/allocno costs
r43: preferred GENERAL_REGS, alternative NO_REGS, cover GENERAL_REGS
a0(r43,l0) costs: POINTER_X_REGS:0,0 POINTER_Z_REGS:0,0
BASE_POINTER_REGS:0,0 POINTER_REGS:0,0 ADDW_REGS:0,0
SIMPLE_LD_REGS:0,0 LD_REGS:0,0 NO_LD_REGS:0,0 GENERAL_REGS:0,0 MEM:6000
Insn 16(l0): point = 0
Insn 13(l0): point = 2
Insn 8(l0): point = 4
Insn 7(l0): point = 6
Insn 2(l0): point = 8
a0(r43): [3..8]
Compressing live ranges: from 11 to 2 - 18%
Ranges after the compression:
a0(r43): [0..1]
+++Allocating 0 bytes for conflict table (uncompressed size 4)
;; a0(r43,l0) conflicts: regions=1, blocks=3, points=2
allocnos=1 (big 0), copies=0, conflicts=0, ranges=1
**** Allocnos coloring:
Loop 0 (parent -1, header bb0, depth 0)
bbs: 2
all: 0r43
modified regnos: 43
border:
Pressure: GENERAL_REGS=2
Reg 43 of GENERAL_REGS has 7 regs less
Pushing a0(r43,l0)
Popping a0(r43,l0) -- assign reg 17
Disposition:
0:r43 l0 17
New iteration of spill/restore move
+++Costs: overall 0, reg 0, mem 0, ld 0, st 0, move 0
+++ move loops 0, new jumps 0
===========================================================
Building IRA IR
Pass 0 for finding pseudo/allocno costs
a0 (r43,l0) best GENERAL_REGS, cover GENERAL_REGS
a0(r43,l0) costs: POINTER_X_REGS:0,0 POINTER_Z_REGS:0,0
BASE_POINTER_REGS:0,0 POINTER_REGS:0,0 ADDW_REGS:0,0
SIMPLE_LD_REGS:0,0 LD_REGS:0,0 NO_LD_REGS:0,0 GENERAL_REGS:0,0 MEM:4000
Pass 1 for finding pseudo/allocno costs
r43: preferred GENERAL_REGS, alternative NO_REGS, cover GENERAL_REGS
a0(r43,l0) costs: POINTER_X_REGS:0,0 POINTER_Z_REGS:0,0
BASE_POINTER_REGS:0,0 POINTER_REGS:0,0 ADDW_REGS:0,0
SIMPLE_LD_REGS:0,0 LD_REGS:0,0 NO_LD_REGS:0,0 GENERAL_REGS:0,0 MEM:4000
Insn 15(l0): point = 0
Insn 12(l0): point = 2
Insn 7(l0): point = 4
Insn 2(l0): point = 6
a0(r43): [3..6]
Compressing live ranges: from 9 to 2 - 22%
Ranges after the compression:
a0(r43): [0..1]
+++Allocating 0 bytes for conflict table (uncompressed size 4)
;; a0(r43,l0) conflicts: regions=1, blocks=3, points=2
allocnos=1 (big 0), copies=0, conflicts=0, ranges=1
**** Allocnos coloring:
Loop 0 (parent -1, header bb0, depth 0)
bbs: 2
all: 0r43
modified regnos: 43
border:
Pressure: GENERAL_REGS=1
Reg 43 of GENERAL_REGS has 6 regs less
Pushing a0(r43,l0)
Popping a0(r43,l0) -- assign reg 24
Disposition:
0:r43 l0 24
New iteration of spill/restore move
+++Costs: overall -4000, reg -4000, mem 0, ld 0, st 0, move 0
+++ move loops 0, new jumps 0
;; Function foo1 (foo1)
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
insn=2, live_throughout: 32, dead_or_set: 24, 42
insn=7, live_throughout: 32, 42, dead_or_set:
insn=9, live_throughout: 32, dead_or_set: 24, 42
insn=10, live_throughout: 32, dead_or_set: 24
changing reg in insn 2
changing reg in insn 9
24 uses a new slot
24 uses a slot from prev iteration
Spilling for insn 16.
Using reg 30 for reload 0
Spilling for insn 17.
Using reg 30 for reload 0
deleting insn with uid = 16.
deleting insn with uid = 17.
24 uses a slot from prev iteration
Spilling for insn 18.
deleting insn with uid = 18.
deleting insn with uid = 19.
24 uses a slot from prev iteration
Spilling for insn 20.
Reloads for insn # 20
Reload 0: reload_out (QI) = (mem/c:QI (plus:HI (reg/f:HI 28 r28)
(const_int 1 [0x1])) [2
S1 A8])
NO_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
reload_out_reg: (mem/c:QI (plus:HI (reg/f:HI 28 r28)
(const_int 1 [0x1])) [2
S1 A8])
deleting insn with uid = 2.
deleting insn with uid = 9.
try_optimize_cfg iteration 1
starting the processing of deferred insns
ending the processing of deferred insns
verify found no changes in insn with uid = 7.
verify found no changes in insn with uid = 10.
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
df_worklist_dataflow_doublequeue:n_basic_blocks 3 n_edges 2 count 3 ( 1)
df_worklist_dataflow_doublequeue:n_basic_blocks 3 n_edges 2 count 3 ( 1)
foo1
Dataflow summary:
;; invalidated by call 0 [r0] 1 [r1] 18 [r18] 19 [r19] 20 [r20] 21
[r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 26 [r26] 27 [r27] 30 [r30] 31 [r31]
33 [__SP_H__] 35 [argH]
;; hardware regs used 32 [__SP_L__]
;; regular block artificial uses 28 [r28] 32 [__SP_L__]
;; eh block artificial uses 28 [r28] 32 [__SP_L__] 34 [argL]
;; entry block defs 8 [r8] 9 [r9] 10 [r10] 11 [r11] 12 [r12] 13 [r13] 14
[r14] 15 [r15] 16 [r16] 17 [r17] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22]
23 [r23] 24 [r24] 25 [r25] 28 [r28] 32 [__SP_L__]
;; exit block uses 28 [r28] 32 [__SP_L__]
;; regs ever live 24[r24] 28[r28] 29[r29] 30[r30] 31[r31] 32[__SP_L__]
;; ref usage r0={2d} r1={2d} r8={1d} r9={1d} r10={1d} r11={1d} r12={1d}
r13={1d} r14={1d} r15={1d} r16={1d} r17={1d} r18={3d} r19={3d} r20={3d}
r21={3d} r22={3d} r23={3d} r24={4d,2u} r25={3d} r26={2d} r27={2d} r28={1d,4u}
r29={2u} r30={2d} r31={2d} r32={1d,4u} r33={2d} r35={2d}
;; total ref usage 65{53d,12u,0e} in 4{2 regular + 2 call} insns.
(note 1 0 4 NOTE_INSN_DELETED)
;; Start of basic block ( 0) -> 2
;; bb 2 artificial_defs: { }
;; bb 2 artificial_uses: { u-1(28){ }u-1(32){ }}
;; lr in 24 [r24] 28 [r28] 29 [r29] 32 [__SP_L__]
;; lr use 24 [r24] 28 [r28] 29 [r29] 32 [__SP_L__]
;; lr def 0 [r0] 1 [r1] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23
[r23] 24 [r24] 25 [r25] 26 [r26] 27 [r27] 30 [r30] 31 [r31] 33 [__SP_H__] 35
[argH]
;; live in 24 [r24] 28 [r28] 32 [__SP_L__]
;; live gen 24 [r24]
;; live kill
;; Pred edge ENTRY [100.0%] (fallthru)
(note 4 1 3 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 3 4 20 2 NOTE_INSN_FUNCTION_BEG)
(insn 20 3 7 2 (set (mem/c:QI (plus:HI (reg/f:HI 28 r28)
(const_int 1 [0x1])) [2 S1 A8])
(reg:QI 24 r24)) sib.c:6 4 {*movqi}
(nil))
(call_insn 7 20 21 2 (call (mem:HI (symbol_ref:HI ("bar0") [flags 0x41]
<function_decl 0xb753e680 bar0>) [0 S2 A8])
(const_int 0 [0])) sib.c:6 122 {call_insn}
(nil)
(nil))
(insn 21 7 10 2 (set (reg:QI 24 r24)
(mem/c:QI (plus:HI (reg/f:HI 28 r28)
(const_int 1 [0x1])) [2 S1 A8])) sib.c:7 4 {*movqi}
(nil))
(call_insn 10 21 15 2 (call (mem:HI (symbol_ref:HI ("bar1") [flags 0x41]
<function_decl 0xb753e700 bar1>) [0 S2 A8])
(const_int 0 [0])) sib.c:7 122 {call_insn}
(nil)
(expr_list:REG_DEP_TRUE (use (reg:QI 24 r24))
(nil)))
;; End of basic block 2 -> ( 1)
;; lr out 28 [r28] 32 [__SP_L__]
;; live out 28 [r28] 32 [__SP_L__]
;; Succ edge EXIT [100.0%] (fallthru)
(note 15 10 0 NOTE_INSN_DELETED)
;; Function foo2 (foo2)
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
insn=2, live_throughout: 32, dead_or_set: 24, 43
insn=7, live_throughout: 32, 43, dead_or_set: 24
insn=8, live_throughout: 32, 43, dead_or_set: 24
insn=13, live_throughout: 32, dead_or_set: 24, 43
insn=16, live_throughout: 24, 32, dead_or_set:
changing reg in insn 2
changing reg in insn 13
changing reg in insn 7
try_optimize_cfg iteration 1
starting the processing of deferred insns
ending the processing of deferred insns
verify found no changes in insn with uid = 8.
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
df_worklist_dataflow_doublequeue:n_basic_blocks 3 n_edges 2 count 3 ( 1)
df_worklist_dataflow_doublequeue:n_basic_blocks 3 n_edges 2 count 3 ( 1)
foo2
Dataflow summary:
;; invalidated by call 0 [r0] 1 [r1] 18 [r18] 19 [r19] 20 [r20] 21
[r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 26 [r26] 27 [r27] 30 [r30] 31 [r31]
33 [__SP_H__] 35 [argH]
;; hardware regs used 32 [__SP_L__]
;; regular block artificial uses 32 [__SP_L__]
;; eh block artificial uses 32 [__SP_L__] 34 [argL]
;; entry block defs 8 [r8] 9 [r9] 10 [r10] 11 [r11] 12 [r12] 13 [r13] 14
[r14] 15 [r15] 16 [r16] 17 [r17] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22]
23 [r23] 24 [r24] 25 [r25] 32 [__SP_L__]
;; exit block uses 24 [r24] 32 [__SP_L__]
;; regs ever live 17[r17] 24[r24] 32[__SP_L__]
;; ref usage r0={1d} r1={1d} r8={1d} r9={1d} r10={1d} r11={1d} r12={1d}
r13={1d} r14={1d} r15={1d} r16={1d} r17={2d,2u} r18={2d} r19={2d} r20={2d}
r21={2d} r22={2d} r23={2d} r24={4d,4u} r25={2d} r26={1d} r27={1d} r30={1d}
r31={1d} r32={1d,3u} r33={1d} r35={1d}
;; total ref usage 47{38d,9u,0e} in 5{4 regular + 1 call} insns.
(note 1 0 4 NOTE_INSN_DELETED)
;; Start of basic block ( 0) -> 2
;; bb 2 artificial_defs: { }
;; bb 2 artificial_uses: { u-1(32){ }}
;; lr in 24 [r24] 32 [__SP_L__]
;; lr use 24 [r24] 32 [__SP_L__]
;; lr def 0 [r0] 1 [r1] 17 [r17] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22
[r22] 23 [r23] 24 [r24] 25 [r25] 26 [r26] 27 [r27] 30 [r30] 31 [r31] 33
[__SP_H__] 35 [argH]
;; live in 24 [r24] 32 [__SP_L__]
;; live gen 17 [r17] 24 [r24]
;; live kill
;; Pred edge ENTRY [100.0%] (fallthru)
(note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(insn 2 4 3 2 (set (reg/v:QI 17 r17 [orig:43 x ] [43])
(reg:QI 24 r24 [ x ])) sib.c:12 4 {*movqi}
(nil))
(note 3 2 7 2 NOTE_INSN_FUNCTION_BEG)
(insn 7 3 8 2 (set (reg:QI 24 r24)
(reg/v:QI 17 r17 [orig:43 x ] [43])) sib.c:13 4 {*movqi}
(nil))
(call_insn 8 7 13 2 (call (mem:HI (symbol_ref:HI ("bar1") [flags 0x41]
<function_decl 0xb753e700 bar1>) [0 S2 A8])
(const_int 0 [0])) sib.c:13 122 {call_insn}
(nil)
(expr_list:REG_DEP_TRUE (use (reg:QI 24 r24))
(nil)))
(insn 13 8 16 2 (set (reg/i:QI 24 r24)
(reg/v:QI 17 r17 [orig:43 x ] [43])) sib.c:16 4 {*movqi}
(nil))
(insn 16 13 20 2 (use (reg/i:QI 24 r24)) sib.c:16 -1
(nil))
;; End of basic block 2 -> ( 1)
;; lr out 24 [r24] 32 [__SP_L__]
;; live out 24 [r24] 32 [__SP_L__]
;; Succ edge EXIT [100.0%] (fallthru)
(note 20 16 0 NOTE_INSN_DELETED)
;; Function foo3 (foo3)
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
insn=2, live_throughout: 32, dead_or_set: 24, 43
insn=7, live_throughout: 32, 43, dead_or_set:
insn=12, live_throughout: 32, dead_or_set: 24, 43
insn=15, live_throughout: 24, 32, dead_or_set:
changing reg in insn 2
changing reg in insn 12
24 uses a new slot
24 uses a slot from prev iteration
Spilling for insn 20.
Using reg 30 for reload 0
Spilling for insn 21.
Using reg 30 for reload 0
deleting insn with uid = 20.
deleting insn with uid = 21.
24 uses a slot from prev iteration
Spilling for insn 22.
deleting insn with uid = 22.
deleting insn with uid = 23.
24 uses a slot from prev iteration
Spilling for insn 24.
Reloads for insn # 24
Reload 0: reload_out (QI) = (mem/c:QI (plus:HI (reg/f:HI 28 r28)
(const_int 1 [0x1])) [2
S1 A8])
NO_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
reload_out_reg: (mem/c:QI (plus:HI (reg/f:HI 28 r28)
(const_int 1 [0x1])) [2
S1 A8])
deleting insn with uid = 2.
deleting insn with uid = 12.
try_optimize_cfg iteration 1
starting the processing of deferred insns
ending the processing of deferred insns
verify found no changes in insn with uid = 7.
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
df_worklist_dataflow_doublequeue:n_basic_blocks 3 n_edges 2 count 3 ( 1)
df_worklist_dataflow_doublequeue:n_basic_blocks 3 n_edges 2 count 3 ( 1)
foo3
Dataflow summary:
;; invalidated by call 0 [r0] 1 [r1] 18 [r18] 19 [r19] 20 [r20] 21
[r21] 22 [r22] 23 [r23] 24 [r24] 25 [r25] 26 [r26] 27 [r27] 30 [r30] 31 [r31]
33 [__SP_H__] 35 [argH]
;; hardware regs used 32 [__SP_L__]
;; regular block artificial uses 28 [r28] 32 [__SP_L__]
;; eh block artificial uses 28 [r28] 32 [__SP_L__] 34 [argL]
;; entry block defs 8 [r8] 9 [r9] 10 [r10] 11 [r11] 12 [r12] 13 [r13] 14
[r14] 15 [r15] 16 [r16] 17 [r17] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22]
23 [r23] 24 [r24] 25 [r25] 28 [r28] 32 [__SP_L__]
;; exit block uses 24 [r24] 28 [r28] 32 [__SP_L__]
;; regs ever live 24[r24] 28[r28] 29[r29] 30[r30] 31[r31] 32[__SP_L__]
;; ref usage r0={1d} r1={1d} r8={1d} r9={1d} r10={1d} r11={1d} r12={1d}
r13={1d} r14={1d} r15={1d} r16={1d} r17={1d} r18={2d} r19={2d} r20={2d}
r21={2d} r22={2d} r23={2d} r24={3d,3u} r25={2d} r26={1d} r27={1d} r28={1d,4u}
r29={2u} r30={1d} r31={1d} r32={1d,3u} r33={1d} r35={1d}
;; total ref usage 49{37d,12u,0e} in 4{3 regular + 1 call} insns.
(note 1 0 4 NOTE_INSN_DELETED)
;; Start of basic block ( 0) -> 2
;; bb 2 artificial_defs: { }
;; bb 2 artificial_uses: { u-1(28){ }u-1(32){ }}
;; lr in 24 [r24] 28 [r28] 29 [r29] 32 [__SP_L__]
;; lr use 24 [r24] 28 [r28] 29 [r29] 32 [__SP_L__]
;; lr def 0 [r0] 1 [r1] 18 [r18] 19 [r19] 20 [r20] 21 [r21] 22 [r22] 23
[r23] 24 [r24] 25 [r25] 26 [r26] 27 [r27] 30 [r30] 31 [r31] 33 [__SP_H__] 35
[argH]
;; live in 24 [r24] 28 [r28] 32 [__SP_L__]
;; live gen 24 [r24]
;; live kill
;; Pred edge ENTRY [100.0%] (fallthru)
(note 4 1 3 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 3 4 24 2 NOTE_INSN_FUNCTION_BEG)
(insn 24 3 7 2 (set (mem/c:QI (plus:HI (reg/f:HI 28 r28)
(const_int 1 [0x1])) [2 S1 A8])
(reg:QI 24 r24)) sib.c:20 4 {*movqi}
(nil))
(call_insn 7 24 25 2 (call (mem:HI (symbol_ref:HI ("bar0") [flags 0x41]
<function_decl 0xb753e680 bar0>) [0 S2 A8])
(const_int 0 [0])) sib.c:20 122 {call_insn}
(nil)
(nil))
(insn 25 7 15 2 (set (reg:QI 24 r24)
(mem/c:QI (plus:HI (reg/f:HI 28 r28)
(const_int 1 [0x1])) [2 S1 A8])) sib.c:23 4 {*movqi}
(nil))
(insn 15 25 19 2 (use (reg/i:QI 24 r24)) sib.c:23 -1
(nil))
;; End of basic block 2 -> ( 1)
;; lr out 24 [r24] 28 [r28] 32 [__SP_L__]
;; live out 24 [r24] 28 [r28] 32 [__SP_L__]
;; Succ edge EXIT [100.0%] (fallthru)
(note 19 15 0 NOTE_INSN_DELETED)
.file "sib.c"
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__tmp_reg__ = 0
__zero_reg__ = 1
.global __do_copy_data
.global __do_clear_bss
.text
.global foo1
.type foo1, @function
foo1:
push r29 ; 22 *pushhi/1 [length = 2]
push r28
push __tmp_reg__ ; 26 *addhi3_sp_R_pc2 [length = 1]
in r28,__SP_L__ ; 27 *movhi_sp/2 [length = 2]
in r29,__SP_H__
/* prologue: function */
/* frame size = 1 */
/* stack size = 3 */
.L__stack_usage = 3
std Y+1,r24 ; 20 *movqi/3 [length = 1]
rcall bar0 ; 7 call_insn/3 [length = 1]
ldd r24,Y+1 ; 21 *movqi/4 [length = 1]
rcall bar1 ; 10 call_insn/3 [length = 1]
/* epilogue start */
pop __tmp_reg__ ; 32 *addhi3_sp_R_pc2 [length = 1]
pop r28 ; 33 pophi [length = 2]
pop r29
ret ; 34 return_from_epilogue [length = 1]
.size foo1, .-foo1
.global foo2
.type foo2, @function
foo2:
push r17 ; 21 *pushqi/1 [length = 1]
/* prologue: function */
/* frame size = 0 */
/* stack size = 1 */
.L__stack_usage = 1
mov r17,r24 ; 2 *movqi/1 [length = 1]
rcall bar1 ; 8 call_insn/3 [length = 1]
mov r24,r17 ; 13 *movqi/1 [length = 1]
/* epilogue start */
pop r17 ; 24 popqi [length = 1]
ret ; 25 return_from_epilogue [length = 1]
.size foo2, .-foo2
.global foo3
.type foo3, @function
foo3:
push r29 ; 26 *pushhi/1 [length = 2]
push r28
push __tmp_reg__ ; 30 *addhi3_sp_R_pc2 [length = 1]
in r28,__SP_L__ ; 31 *movhi_sp/2 [length = 2]
in r29,__SP_H__
/* prologue: function */
/* frame size = 1 */
/* stack size = 3 */
.L__stack_usage = 3
std Y+1,r24 ; 24 *movqi/3 [length = 1]
rcall bar0 ; 7 call_insn/3 [length = 1]
ldd r24,Y+1 ; 25 *movqi/4 [length = 1]
/* epilogue start */
pop __tmp_reg__ ; 36 *addhi3_sp_R_pc2 [length = 1]
pop r28 ; 37 pophi [length = 2]
pop r29
ret ; 38 return_from_epilogue [length = 1]
.size foo3, .-foo3