http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47624
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2011.02.07 13:08:13 CC| |aoliva at gcc dot gnu.org, | |jakub at gcc dot gnu.org Ever Confirmed|0 |1 --- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> 2011-02-07 13:08:13 UTC --- Yeah, this looks like a var-tracking bug. We have: (insn 32 7 9 2 (set (reg/f:DI 4 4 [127]) (reg/f:DI 1 1)) pr43077-1.c:34 358 {*movdi_internal64} (expr_list:REG_EQUAL (reg/f:DI 1 1) (nil))) which adjust_insn transforms into: (insn 32 7 9 2 (set (reg/f:DI 4 4 [127]) (plus:DI (reg/f:DI 67 ap) (const_int -128 [0xffffffffffffff80]))) pr43077-1.c:34 358 {*movdi_internal64} (expr_list:REG_EQUAL (reg/f:DI 1 1) (nil))) and: (insn 9 32 31 2 (set (mem/c/i:DI (pre_modify:DI (reg/f:DI 4 4 [127]) (plus:DI (reg/f:DI 4 4 [127]) (const_int 120 [0x78]))) [0 c+0 S8 A64]) (reg:DI 0 0 [125])) pr43077-1.c:34 358 {*movdi_internal64} (expr_list:REG_DEAD (reg:DI 0 0 [125]) (expr_list:REG_INC (reg/f:DI 4 4 [127]) (nil)))) which is adjusted into: (insn 9 32 31 2 (parallel [ (set (mem/c/i:DI (plus:DI (reg/f:DI 4 4 [127]) (const_int 120 [0x78])) [0 c+0 S8 A64]) (reg:DI 0 0 [125])) (set (reg/f:DI 4 4 [127]) (plus:DI (reg/f:DI 4 4 [127]) (const_int 120 [0x78]))) ]) pr43077-1.c:34 358 {*movdi_internal64} (expr_list:REG_DEAD (reg:DI 0 0 [125]) (expr_list:REG_INC (reg/f:DI 4 4 [127]) (nil)))) I believe that is correct. Now, for the latter insn, we get following uops: bb 2 op 12 insn 9 MO_USE_NO_VAR (reg/f:DI 4 4 [127]) bb 2 op 13 insn 9 MO_USE_NO_VAR (reg:DI 0 0 [125]) bb 2 op 14 insn 9 MO_USE_NO_VAR (reg/f:DI 4 4 [127]) bb 2 op 15 insn 9 MO_VAL_SET (concat/u/i:DI (concat:DI (value/u:DI 7:7851 @0x2fb62b0/0x2fb6150) (reg/f:DI 4 4 [127])) (concat:DI (value/u:DI 4:3802 @0x2fb6268/0x2fb60c0) (plus:DI (value/u:DI 7:7851 @0x2fb62b0/0x2fb6150) (const_int -120 [0xffffffffffffff88])))) bb 2 op 16 insn 9 MO_VAL_SET (concat (concat:DI (value/u:DI 5:3870 @0x2fb6280/0x2fb60f0) (mem/c/i:DI (value/u:DI 7:7851 @0x2fb62b0/0x2fb6150) [0 cD.1258+0 S8 A64])) (set (mem/c/i:DI (plus:DI (reg/f:DI 4 4 [127]) (const_int 120 [0x78])) [0 cD.1258+0 S8 A64]) (reg:DI 0 0 [125]))) In the last uop, we have VAL_HOLDS_TRACK_EXPR set and no other flags. As c is only ever mentioned in MEM_ATTRS, the raw r4 + 120 address is used as its location instead of tracking its value, and furthermore it doesn't even take into account that r4 has been incremented in the very same insn and thus right after the insn it is (mem (reg 4)) anyway. Not sure why we don't value track the mem's address even for decls mentioned in MEM_ATTRS (i.e. why the MEM doesn't use a VALUE as the address), that IMHO would magically fix this. We would even figure out c is stored into a fbreg based loc. Adding manually (in the debugger) a @@ -5383,6 +5383,7 @@ add_stores (rtx loc, const_rtx expr, voi if (GET_CODE (expr) == SET && SET_DEST (expr) == loc) src = var_lowpart (mode2, SET_SRC (expr)); loc = var_lowpart (mode2, loc); +if (type == MO_VAL_SET) loc = replace_expr_with_values (loc); if (src == NULL) { call partly fixes the testcase, c is not claimed to be at r4 + 120 anymore, but at r4, which is correct at that spot; the following call to foo makes r4 register dead though, and so during and after the call the location info for c is not valid anymore. We could try harder and say canonicalize in cselib locs of the form (plus (value X) (const_int N)) (or minus) where (value X) has locs (plus cfa_base_preserved_val->v_val_rtx (const_int M)) into a (plus cfa_base_preserved_val->v_val_rtx (const_int M+N)) and then we'd figure out that r4 + 120 here is actually ap + offset and could even use a hardcoded, non-value related, ap + offset location in this case. But we also need to figure out what to do in a more general case. Alex, ideas? Not a 4.6 material though.