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 <[email protected]>
* 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))