summaryrefslogtreecommitdiff
path: root/gcc/alias.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-09 23:28:01 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-09 23:28:01 +0000
commit96ba6770321b15c5dabd6ac721a1e2d257d0473d (patch)
tree8ef2dd128c31080dac218b7c43d96a8c2b68c98a /gcc/alias.c
parent7e28e64631c8ab6c4871bda4457bd3d9ba0c77f6 (diff)
downloadgcc-96ba6770321b15c5dabd6ac721a1e2d257d0473d.tar.gz
PR ipa/61886
PR middle-end/25140 * tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Use compare_base_decls (nonoverlapping_component_refs_of_decl_p): Update sanity check. (decl_refs_may_alias_p): Use compare_base_decls. * alias.c: Include cgraph.h (rtx_equal_for_memref_p): Use rtx_equal_for_memref_p. (compare_base_decls): New function. (base_alias_check): Likewise. (memrefs_conflict_p): Likewise. (nonoverlapping_memrefs_p): Likewise. * alias.h (compare_base_decls): Declare. * gcc.c-torture/execute/alias-2.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231478 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/alias.c')
-rw-r--r--gcc/alias.c89
1 files changed, 86 insertions, 3 deletions
diff --git a/gcc/alias.c b/gcc/alias.c
index 66aedcef4c9..095b2ade180 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "cfganal.h"
#include "rtl-iter.h"
+#include "cgraph.h"
/* The aliasing API provided here solves related but different problems:
@@ -990,6 +991,14 @@ get_alias_set (tree t)
|| TREE_CODE (p) == VECTOR_TYPE;
p = TREE_TYPE (p))
{
+ /* Ada supports recusive pointers. Instead of doing recrusion check
+ just give up once the preallocated space of 8 elements is up.
+ In this case just punt to void * alias set. */
+ if (reference.length () == 8)
+ {
+ p = ptr_type_node;
+ break;
+ }
if (TREE_CODE (p) == REFERENCE_TYPE)
/* In LTO we want languages that use references to be compatible
with languages that use pointers. */
@@ -1747,7 +1756,15 @@ rtx_equal_for_memref_p (const_rtx x, const_rtx y)
return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
case SYMBOL_REF:
- return XSTR (x, 0) == XSTR (y, 0);
+ {
+ tree x_decl = SYMBOL_REF_DECL (x);
+ tree y_decl = SYMBOL_REF_DECL (y);
+
+ if (!x_decl || !y_decl)
+ return XSTR (x, 0) == XSTR (y, 0);
+ else
+ return compare_base_decls (x_decl, y_decl) == 1;
+ }
case ENTRY_VALUE:
/* This is magic, don't go through canonicalization et al. */
@@ -2010,6 +2027,31 @@ may_be_sp_based_p (rtx x)
return !base || base == static_reg_base_value[STACK_POINTER_REGNUM];
}
+/* BASE1 and BASE2 are decls. Return 1 if they refer to same object, 0
+ if they refer to different objects and -1 if we can not decide. */
+
+int
+compare_base_decls (tree base1, tree base2)
+{
+ int ret;
+ gcc_checking_assert (DECL_P (base1) && DECL_P (base2));
+ if (base1 == base2)
+ return 1;
+
+ bool in_symtab1 = decl_in_symtab_p (base1);
+ bool in_symtab2 = decl_in_symtab_p (base2);
+
+ /* Declarations of non-automatic variables may have aliases. All other
+ decls are unique. */
+ if (in_symtab1 != in_symtab2 || !in_symtab1)
+ return 0;
+ ret = symtab_node::get_create (base1)->equal_address_to
+ (symtab_node::get_create (base2), true);
+ if (ret == 2)
+ return -1;
+ return ret;
+}
+
/* Return 0 if the addresses X and Y are known to point to different
objects, 1 if they might be pointers to the same object. */
@@ -2047,6 +2089,17 @@ base_alias_check (rtx x, rtx x_base, rtx y, rtx y_base,
if (rtx_equal_p (x_base, y_base))
return 1;
+ if (GET_CODE (x_base) == SYMBOL_REF && GET_CODE (y_base) == SYMBOL_REF)
+ {
+ tree x_decl = SYMBOL_REF_DECL (x_base);
+ tree y_decl = SYMBOL_REF_DECL (y_base);
+
+ /* We can assume that no stores are made to labels. */
+ if (!x_decl || !y_decl)
+ return 0;
+ return compare_base_decls (x_decl, y_decl) != 0;
+ }
+
/* The base addresses are different expressions. If they are not accessed
via AND, there is no conflict. We can bring knowledge of object
alignment into play here. For example, on alpha, "char a, b;" can
@@ -2268,7 +2321,33 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
else
y = addr_side_effect_eval (y, abs (ysize), 0);
- if (rtx_equal_for_memref_p (x, y))
+ if (GET_CODE (x) == SYMBOL_REF && GET_CODE (y) == SYMBOL_REF)
+ {
+ tree x_decl = SYMBOL_REF_DECL (x);
+ tree y_decl = SYMBOL_REF_DECL (y);
+ int cmp;
+
+ if (!x_decl || !y_decl)
+ {
+ /* Label and normal symbol are never the same. */
+ if (x_decl != y_decl)
+ return 0;
+ return offset_overlap_p (c, xsize, ysize);
+ }
+ else
+ cmp = compare_base_decls (x_decl, y_decl);
+
+ /* If both decls are the same, decide by offsets. */
+ if (cmp == 1)
+ return offset_overlap_p (c, xsize, ysize);
+ /* If decls are different or we know by offsets that there is no overlap,
+ we win. */
+ if (!cmp || !offset_overlap_p (c, xsize, ysize))
+ return 0;
+ /* Decls may or may not be different and offsets overlap....*/
+ return -1;
+ }
+ else if (rtx_equal_for_memref_p (x, y))
{
return offset_overlap_p (c, xsize, ysize);
}
@@ -2636,7 +2715,7 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y, bool loop_invariant)
are constants or if one is a constant and the other a pointer into the
stack frame. Otherwise a different base means we can't tell if they
overlap or not. */
- if (! rtx_equal_p (basex, basey))
+ if (compare_base_decls (exprx, expry) == 0)
return ((CONSTANT_P (basex) && CONSTANT_P (basey))
|| (CONSTANT_P (basex) && REG_P (basey)
&& REGNO_PTR_FRAME_P (REGNO (basey)))
@@ -2647,6 +2726,10 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y, bool loop_invariant)
if (loop_invariant)
return 0;
+ /* Offset based disambiguation is OK even if we do not know that the
+ declarations are necessarily different
+ (i.e. compare_base_decls (exprx, expry) == -1) */
+
sizex = (!MEM_P (rtlx) ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
: MEM_SIZE_KNOWN_P (rtlx) ? MEM_SIZE (rtlx)
: -1);