------- Comment #3 from jakub at gcc dot gnu dot org 2010-03-09 10:13 ------- Distilled testcase -g -O2 -m64: extern void *emit_insn (void *); extern void *gen_load_locked_si (void *, void *); extern void *gen_load_locked_di (void *, void *);
void emit_load_locked (int mode, void *reg, void *mem) { void * (*fn) (void *, void *) = ((void *)0); if (mode == 9) fn = gen_load_locked_si; else if (mode == 10) fn = gen_load_locked_di; emit_insn (fn (reg, mem)); } The problem here is we have: (insn:TI 8 38 120 5 pr43299.i:12 (set (reg/v/f:DI 9 9 [orig:119 fn ] [119]) (mem/u/c:DI (plus:DI (reg:DI 2 2) (const:DI (unspec:DI [ (symbol_ref/u:DI ("*.LC1") [flags 0x2]) ] 49))) [5 S8 A8])) 357 {*movdi_internal64} (expr_list:REG_EQUAL (symbol_ref:DI ("gen_load_locked_di") [flags 0x41] <funct ion_decl 0x7f3f5df8fb00 gen_load_locked_di>) (nil))) (which is correctly tracked as following): (note 120 8 73 5 (var_location fn (expr_list:REG_DEP_TRUE (mem/u/c:DI (symbol_ref/u:DI ("*.LC1") [flags 0x2]) [5 S8 A8]) (const_int 0 [0x0]))) NOTE_INSN_VAR_LOCATION) but then the incoming TOC register is spilled: (insn 24 23 22 4 pr43299.i:13 (set (mem:DI (plus:DI (reg/f:DI 1 1) (const_int 40 [0x28])) [0 S8 A8]) (reg:DI 2 2)) 357 {*movdi_internal64} (expr_list:REG_DEAD (reg:DI 2 2) (nil))) and some new value is loaded into r2. As fn at this point is a MEM with address PLUS (value incoming_r2) (const (unspec)) and (value incoming_r2) after the load of some other value into r2 no longer holds that value, but [r1 + 40] does, we end up with: (note 121 76 77 5 (var_location fn (expr_list:REG_DEP_TRUE (mem/u/c:DI (plus:DI (mem:DI (plus:DI (reg/f:DI 1 1) (const_int 40 [0x28])) [0 S8 A8]) (const:DI (unspec:DI [ (symbol_ref/u:DI ("*.LC1") [flags 0x2]) ] 49))) [5 S8 A8]) (const_int 0 [0x0]))) NOTE_INSN_VAR_LOCATION) and rs6000_delegitimize_address understandably can't do anything there, as it doesn't know [r1 + 40] holds the current function's TOC register value. Obviously the patch I've attached earlier, without the ENABLE_CHECKING hunk, is going to "fix" this, but at the expense of not providing good debug info. As we can't delegitimize such stuff so late, I'm afraid we need to either attempt to delegitimize MEMs (at least MEM_READONLY_Ps) early, during vt_initialize, or use REG_EQUIV notes. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43299