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.

Reply via email to