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