If you try to bootstrap the GNAT 4.7.0 compiler on IA-64/Linux with non-default 
options (-gnatpg replaced with -gnatpgn), you get another comparison failure 
caused by debug insns, stemming from the machine-specific reorg pass (aka insn 
bundling on IA-64).  With -g , when cselib is called on:

(insn 17 41 18 2 (set (reg/f:DI 14 r14 [357])
        (plus:DI (reg:DI 16 r16 [356])
            (const_int 28 
[0x1c]))) /home/eric/gnat.b/gnat7_47/src/gcc/ada/atree.adb:2244 205 {adddi3}
     (expr_list:REG_DEAD (reg:DI 16 r16 [356])
        (nil)))

it finds a previous equivalent value:

(plus:DI (plus:DI (ashift:DI (value:DI 5:111 @0x29abbe0/0x29f5f20)
            (const_int 5 [0x5]))
        (value:DI 9:9 @0x29abc40/0x29f5fe0))
    (const_int 28 [0x1c]))

computed for a debug insn:

(debug_insn 12 10 65 2 (var_location:SI n (mem/j:SI (plus:DI (plus:DI 
(ashift:DI (reg:DI 14 r14 [orig:344 D.2979 ] [344])
                    (const_int 5 [0x5]))
                (reg/f:DI 15 r15 [orig:342 
atree__atree_private_part__nodes__table.32 ] [342]))
            (const_int 28 [0x1c])) [0 
*atree__atree_private_part__nodes__table.32_17
[D.2979_19].is_extension___XVN.S0.field5+0 S4 A8])) sem_ch2.adb:49 -1
     (nil))

When output_dependence is called on a couple of MEMs, it uses the above value
to get the equivalent addresses:

(plus:DI (value:DI 9:9 @0x29abc40/0x29f5fe0)
    (value:DI 12:4189 @0x29abc88/0x29c8a20))

and

(plus:DI (plus:DI (ashift:DI (value:DI 5:111 @0x29abbe0/0x29f5f20)
            (const_int 5 [0x5]))
        (value:DI 9:9 @0x29abc40/0x29f5fe0))
    (const_int 28 [0x1c]))

and rtx_refs_may_alias_p returns true on them because ao_ref_from_mem returns 
false for one of the MEMs.


Without -g, when cselib is called on:

(insn 14 30 15 2 (set (reg/f:DI 14 r14 [357])
        (plus:DI (reg:DI 16 r16 [356])
            (const_int 28 
[0x1c]))) /home/eric/gnat.b/gnat7_47/src/gcc/ada/atree.adb:2244 205 {adddi3}
     (expr_list:REG_DEAD (reg:DI 16 r16 [356])
        (nil)))

output_dependence only gets the equivalent addresses:

(plus:DI (value:DI 8:8 @0x299f2e8/0x299f1a0)
    (value:DI 10:4188 @0x299f318/0x299f200))

and

(plus:DI (value:DI 12:4254 @0x299f348/0x29a0490)
    (const_int 28 [0x1c]))

and memrefs_conflict_p is able to prove that they don't conflict.


The problem is that the more complex expression in the first case fools 
memrefs_conflict_p because the predicate makes a wrong assumption about the 
canonicalization of address expressions.  Hence the attached patch.

Bootstrapped/regtested on IA-64/Linux, OK for the mainline?  Do we also want it 
for 4.7.1 or is it too specific?


2012-03-06  Eric Botcazou  <ebotca...@adacore.com>

        * alias.c (memrefs_conflict_p) <PLUS>: Correct wrong assumption about
        canonicalization of address expressions.


-- 
Eric Botcazou
Index: alias.c
===================================================================
--- alias.c	(revision 184852)
+++ alias.c	(working copy)
@@ -1993,6 +1993,14 @@ memrefs_conflict_p (int xsize, rtx x, in
 	    return memrefs_conflict_p (xsize, x0, ysize, y0, c);
 	  if (rtx_equal_for_memref_p (x0, y0))
 	    return memrefs_conflict_p (xsize, x1, ysize, y1, c);
+
+	  /* Non-legitimate address expressions in debug insns can change the
+	     relative canonicalization wrt legitimate address expressions.  */
+	  if (rtx_equal_for_memref_p (x1, y0))
+	    return memrefs_conflict_p (xsize, x0, ysize, y1, c);
+	  if (rtx_equal_for_memref_p (x0, y1))
+	    return memrefs_conflict_p (xsize, x1, ysize, y0, c);
+
 	  if (CONST_INT_P (x1))
 	    {
 	      if (CONST_INT_P (y1))

Reply via email to