This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Reload generates wrong spill
- From: Georg-Johann Lay <avr at gjlay dot de>
- To: gcc at gcc dot gnu dot org
- Date: Tue, 19 Apr 2011 12:45:05 +0200
- Subject: Reload generates wrong spill
The following code is a testcase for avr where reload generates wrong
code:
struct S
{
unsigned char a, b;
} ab = {12, 34};
void yoo (struct S y)
{
__asm volatile ("ldi %B0, 56" : "+y" (y));
y.a = 0;
__asm volatile ("; y = %0" : "+y" (y));
ab = y;
}
The asm just serves to direct struct S into register Y.
Y is a 16-bit reg that consists of two 8-bit regs r28 and r29.
The bug also occurs without inline asm for complex code, but this test
case is easier and the problem can be better reproduced.
Y also serves as frame pointer. avr_hard_regno_mode_ok allows
HImode=Pmode to go into Y but rejects QImode.
The program is compiled with -Os, there is no frame pointer needed and
Y can be allocated for ordinary data.
The line y.a = 0 reads in pass .asmcons
(insn 7 6 8 2 (set (subreg:QI (reg/v:HI 43 [ y ]) 0)
(const_int 0 [0])) pr46779-1.c:34 4 {*movqi}
(nil))
This is the only insn between the two asms. After .ira this reads
(insn 7 6 17 2 (set (reg:QI 24 r24)
(const_int 0 [0])) pr46779-1.c:34 4 {*movqi}
(nil))
(insn 17 7 8 2 (set (reg/v:HI 28 r28 [orig:43 y ] [43])
(reg:HI 24 r24)) pr46779-1.c:34 10 {*movhi}
(nil))
so that r29 gets messed up, i.e. there is a
(set (reg:HI 24) (reg:HI 29))
missing before insn 7. Reload fails to generate this insn. This is the
case for current trunk (last snapshot) and 4.5. In 4.3, reload
generates correct code (at least for this test case).
gcc configured (SVN 172597, last 4.7 snapshot):
--target=avr --disable-nls --disable-shared --enable-languages=c
--prefix=...
avr-gcc command line: -c -dp -save-temps -Os -da
Thanks for any hints on this, especially if it's a reload bug or
complete abuse of HARD_REGNO_MODE_OK.
FYI, I attached the two dumps.
A complete test case is located in
gcc.target/avr/pr46779-1.c
Johann
;; Function yoo (yoo)
deferring rescan insn with uid = 15.
deferring rescan insn with uid = 6.
yoo
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 28 [r28] 32 [__SP_L__] 34 [argL]
;; regular block artificial uses 28 [r28] 32 [__SP_L__] 34 [argL]
;; 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__] 34 [argL]
;; exit block uses 28 [r28] 32 [__SP_L__]
;; regs ever live 24[r24] 25[r25]
;; ref usage r8={1d} r9={1d} r10={1d} r11={1d} r12={1d} r13={1d} r14={1d} r15={1d} r16={1d} r17={1d} r18={1d} r19={1d} r20={1d} r21={1d} r22={1d} r23={1d} r24={1d,1u} r25={1d,1u} r28={1d,2u} r32={1d,2u} r34={1d,1u} r43={3d,4u}
;; total ref usage 35{24d,11u,0e} in 6{6 regular + 0 call} insns.
(note 1 0 4 NOTE_INSN_DELETED)
;; Start of basic block ( 0) -> 2
;; bb 2 artificial_defs: { }
;; bb 2 artificial_uses: { u0(28){ }u1(32){ }u2(34){ }}
;; lr in 24 [r24] 25 [r25] 28 [r28] 32 [__SP_L__] 34 [argL]
;; lr use 24 [r24] 25 [r25] 28 [r28] 32 [__SP_L__] 34 [argL]
;; lr def 43
;; live in 24 [r24] 25 [r25] 28 [r28] 32 [__SP_L__] 34 [argL]
;; live gen 43
;; live kill
;; Pred edge ENTRY [100.0%] (fallthru)
(note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 2 4 3 2 NOTE_INSN_DELETED)
(note 3 2 15 2 NOTE_INSN_FUNCTION_BEG)
(insn 15 3 6 2 (set (reg/v:HI 43 [ y ])
(reg:HI 24 r24 [ y ])) pr46779-1.c:32 -1
(nil))
(insn 6 15 7 2 (set (reg/v:HI 43 [ y ])
(asm_operands/v:HI ("ldi %B0, 56") ("=y") 0 [
(reg/v:HI 43 [ y ])
]
[
(asm_input:HI ("0") (null):0)
]
[] pr46779-1.c:36)) pr46779-1.c:32 -1
(nil))
(insn 7 6 8 2 (set (subreg:QI (reg/v:HI 43 [ y ]) 0)
(const_int 0 [0])) pr46779-1.c:34 4 {*movqi}
(nil))
(insn 8 7 10 2 (set (reg/v:HI 43 [ y ])
(asm_operands/v:HI ("; y = %0") ("=y") 0 [
(reg/v:HI 43 [ y ])
]
[
(asm_input:HI ("0") (null):0)
]
[] pr46779-1.c:36)) pr46779-1.c:34 -1
(nil))
(insn 10 8 12 2 (set (mem/s/c:HI (symbol_ref:HI ("ab") [flags 0x2] <var_decl 0xb7683000 ab>) [2 ab+0 S2 A8])
(reg/v:HI 43 [ y ])) pr46779-1.c:35 10 {*movhi}
(nil))
(insn 12 10 0 2 (set (mem/s/c:QI (symbol_ref:HI ("ab") [flags 0x2] <var_decl 0xb7683000 ab>) [0 ab.a+0 S1 A8])
(subreg:QI (reg/v:HI 43 [ y ]) 0)) pr46779-1.c:35 4 {*movqi}
(expr_list:REG_DEAD (reg/v:HI 43 [ y ])
(nil)))
;; End of basic block 2 -> ( 1)
;; lr out 28 [r28] 32 [__SP_L__] 34 [argL]
;; live out 28 [r28] 32 [__SP_L__] 34 [argL]
;; Succ edge EXIT [100.0%] (fallthru)
starting the processing of deferred insns
rescanning insn with uid = 6.
deleting insn with uid = 6.
rescanning insn with uid = 15.
deleting insn with uid = 15.
ending the processing of deferred insns
;; Function yoo (yoo)
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)
Building IRA IR
starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
Pass 0 for finding pseudo/allocno costs
a0 (r43,l0) best POINTER_Y_REGS, allocno POINTER_Y_REGS
a0(r43,l0) costs: POINTER_X_REGS:8000,8000 POINTER_Y_REGS:0,0 POINTER_Z_REGS:8000,8000 BASE_POINTER_REGS:8000,8000 POINTER_REGS:8000,8000 ADDW_REGS:8000,8000 SIMPLE_LD_REGS:8000,8000 LD_REGS:8000,8000 NO_LD_REGS:8000,8000 GENERAL_REGS:8000,8000 ALL_REGS:8000,8000 MEM:28000,28000
Pass 1 for finding pseudo/allocno costs
r43: preferred POINTER_Y_REGS, alternative GENERAL_REGS, allocno GENERAL_REGS
a0(r43,l0) costs: POINTER_X_REGS:8000,8000 POINTER_Y_REGS:0,0 POINTER_Z_REGS:8000,8000 BASE_POINTER_REGS:8000,8000 POINTER_REGS:8000,8000 ADDW_REGS:8000,8000 SIMPLE_LD_REGS:8000,8000 LD_REGS:8000,8000 NO_LD_REGS:8000,8000 GENERAL_REGS:8000,8000 ALL_REGS:8000,8000 MEM:28000,28000
Insn 12(l0): point = 0
Insn 10(l0): point = 2
Insn 8(l0): point = 4
Insn 7(l0): point = 6
Insn 6(l0): point = 8
Insn 15(l0): point = 10
a0(r43 [0]): [1..10]
a0(r43 [1]): [3..10]
Compressing live ranges: from 13 to 2 - 15%
Ranges after the compression:
a0(r43 [0]): [0..1]
a0(r43 [1]): [0..1]
+++Allocating 8 bytes for conflict table (uncompressed size 8)
;; a0(r43,l0) conflicts:
;; subobject 0:
;; total conflict hard regs:
;; conflict hard regs:
;; subobject 1:
;; total conflict hard regs:
;; conflict hard regs:
regions=1, blocks=3, points=2
allocnos=1 (big 1), copies=0, conflicts=0, ranges=2
**** Allocnos coloring:
Loop 0 (parent -1, header bb0, depth 0)
bbs: 2
all: 0r43
modified regnos: 43
border:
Pressure: GENERAL_REGS=3
Hard reg set forest:
0:( 2-31)@112000
Allocno a0r43 of GENERAL_REGS(30) has 29 avail. regs obj 0 2-31 (confl regs = 0 1 32-34 ) node: 2-31, obj 1 2-31 (confl regs = 0 1 32-34 ) node: 2-31
Pushing a0(r43,l0)(cost 0)
Popping a0(r43,l0) -- assign reg 28
Disposition:
0:r43 l0 28
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
insn=15, live_throughout: 32, dead_or_set: 24, 25, 43
insn=6, live_throughout: 32, dead_or_set: 43
insn=7, live_throughout: 32, 43, dead_or_set: 43
insn=8, live_throughout: 32, dead_or_set: 43
insn=10, live_throughout: 32, 43, dead_or_set:
insn=12, live_throughout: 32, dead_or_set: 43
changing reg in insn 15
changing reg in insn 6
changing reg in insn 8
changing reg in insn 6
changing reg in insn 10
changing reg in insn 8
changing reg in insn 7
Spilling for insn 7.
Using reg 24 for reload 0
Spilling for insn 10.
Spilling for insn 12.
Using reg 24 for reload 1
Reloads for insn # 7
Reload 0: reload_out (HI) = (reg/v:HI 28 r28 [orig:43 y ] [43])
GENERAL_REGS, RELOAD_FOR_OUTPUT (opnum = 0)
reload_out_reg: (reg/v:HI 28 r28 [orig:43 y ] [43])
reload_reg_rtx: (reg:HI 24 r24)
Reloads for insn # 10
Reload 0: reload_out (HI) = (mem/s/c:HI (symbol_ref:HI ("ab") [flags 0x2] <var_decl 0xb7683000 ab>) [2 ab+0 S2 A8])
NO_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
reload_out_reg: (mem/s/c:HI (symbol_ref:HI ("ab") [flags 0x2] <var_decl 0xb7683000 ab>) [2 ab+0 S2 A8])
Reloads for insn # 12
Reload 0: reload_out (QI) = (mem/s/c:QI (symbol_ref:HI ("ab") [flags 0x2] <var_decl 0xb7683000 ab>) [0 ab.a+0 S1 A8])
NO_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
reload_out_reg: (mem/s/c:QI (symbol_ref:HI ("ab") [flags 0x2] <var_decl 0xb7683000 ab>) [0 ab.a+0 S1 A8])
Reload 1: reload_in (HI) = (reg/v:HI 28 r28 [orig:43 y ] [43])
GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 1)
reload_in_reg: (reg/v:HI 28 r28 [orig:43 y ] [43])
reload_reg_rtx: (reg:HI 24 r24)
try_optimize_cfg iteration 1
starting the processing of deferred insns
ending the processing of deferred insns
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)
yoo
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 32 [__SP_L__]
;; regs ever live 24[r24] 25[r25] 28[r28] 29[r29]
;; ref usage r8={1d} r9={1d} r10={1d} r11={1d} r12={1d} r13={1d} r14={1d} r15={1d} r16={1d} r17={1d} r18={1d} r19={1d} r20={1d} r21={1d} r22={1d} r23={1d} r24={3d,3u} r25={2d,2u} r28={4d,4u} r29={4d,4u} r32={1d,2u}
;; total ref usage 45{30d,15u,0e} in 8{8 regular + 0 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] 25 [r25] 32 [__SP_L__]
;; lr use 24 [r24] 25 [r25] 32 [__SP_L__]
;; lr def 24 [r24] 25 [r25] 28 [r28] 29 [r29]
;; live in 24 [r24] 25 [r25] 32 [__SP_L__]
;; live gen 24 [r24] 25 [r25] 28 [r28] 29 [r29]
;; live kill
;; Pred edge ENTRY [100.0%] (fallthru)
(note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 2 4 3 2 NOTE_INSN_DELETED)
(note 3 2 15 2 NOTE_INSN_FUNCTION_BEG)
(insn 15 3 6 2 (set (reg/v:HI 28 r28 [orig:43 y ] [43])
(reg:HI 24 r24 [ y ])) pr46779-1.c:32 10 {*movhi}
(nil))
(insn 6 15 7 2 (set (reg/v:HI 28 r28 [orig:43 y ] [43])
(asm_operands/v:HI ("ldi %B0, 56") ("=y") 0 [
(reg/v:HI 28 r28 [orig:43 y ] [43])
]
[
(asm_input:HI ("0") (null):0)
]
[] pr46779-1.c:36)) pr46779-1.c:32 -1
(nil))
(insn 7 6 17 2 (set (reg:QI 24 r24)
(const_int 0 [0])) pr46779-1.c:34 4 {*movqi}
(nil))
(insn 17 7 8 2 (set (reg/v:HI 28 r28 [orig:43 y ] [43])
(reg:HI 24 r24)) pr46779-1.c:34 10 {*movhi}
(nil))
(insn 8 17 10 2 (set (reg/v:HI 28 r28 [orig:43 y ] [43])
(asm_operands/v:HI ("; y = %0") ("=y") 0 [
(reg/v:HI 28 r28 [orig:43 y ] [43])
]
[
(asm_input:HI ("0") (null):0)
]
[] pr46779-1.c:36)) pr46779-1.c:34 -1
(nil))
(insn 10 8 18 2 (set (mem/s/c:HI (symbol_ref:HI ("ab") [flags 0x2] <var_decl 0xb7683000 ab>) [2 ab+0 S2 A8])
(reg/v:HI 28 r28 [orig:43 y ] [43])) pr46779-1.c:35 10 {*movhi}
(nil))
(insn 18 10 12 2 (set (reg:HI 24 r24)
(reg/v:HI 28 r28 [orig:43 y ] [43])) pr46779-1.c:35 10 {*movhi}
(nil))
(insn 12 18 16 2 (set (mem/s/c:QI (symbol_ref:HI ("ab") [flags 0x2] <var_decl 0xb7683000 ab>) [0 ab.a+0 S1 A8])
(reg:QI 24 r24)) pr46779-1.c:35 4 {*movqi}
(nil))
;; End of basic block 2 -> ( 1)
;; lr out 32 [__SP_L__]
;; live out 32 [__SP_L__]
;; Succ edge EXIT [100.0%] (fallthru)
(note 16 12 0 NOTE_INSN_DELETED)