------- 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

Reply via email to