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)