Commit 54363f8a by Jan Hubicka Committed by Jan Hubicka

re PR lto/61886 (LTO breaks fread with _FORTIFY_SOURCE=2)


	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.

From-SVN: r231478
parent da20571a
2015-12-08 Jan Hubicka <hubicka@ucw.cz> 2015-12-08 Jan Hubicka <hubicka@ucw.cz>
PR ipa/61886 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.
2015-12-08 Jan Hubicka <hubicka@ucw.cz>
PR ipa/61886
* ipa-visibility.c (function_and_variable_visibility): Fix vtable * ipa-visibility.c (function_and_variable_visibility): Fix vtable
rewritting guard. rewritting guard.
...@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h" #include "langhooks.h"
#include "cfganal.h" #include "cfganal.h"
#include "rtl-iter.h" #include "rtl-iter.h"
#include "cgraph.h"
/* The aliasing API provided here solves related but different problems: /* The aliasing API provided here solves related but different problems:
...@@ -990,6 +991,14 @@ get_alias_set (tree t) ...@@ -990,6 +991,14 @@ get_alias_set (tree t)
|| TREE_CODE (p) == VECTOR_TYPE; || TREE_CODE (p) == VECTOR_TYPE;
p = TREE_TYPE (p)) 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) if (TREE_CODE (p) == REFERENCE_TYPE)
/* In LTO we want languages that use references to be compatible /* In LTO we want languages that use references to be compatible
with languages that use pointers. */ with languages that use pointers. */
...@@ -1747,7 +1756,15 @@ rtx_equal_for_memref_p (const_rtx x, const_rtx y) ...@@ -1747,7 +1756,15 @@ rtx_equal_for_memref_p (const_rtx x, const_rtx y)
return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y); return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
case SYMBOL_REF: 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: case ENTRY_VALUE:
/* This is magic, don't go through canonicalization et al. */ /* This is magic, don't go through canonicalization et al. */
...@@ -2010,6 +2027,31 @@ may_be_sp_based_p (rtx x) ...@@ -2010,6 +2027,31 @@ may_be_sp_based_p (rtx x)
return !base || base == static_reg_base_value[STACK_POINTER_REGNUM]; 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 /* 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. */ 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, ...@@ -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)) if (rtx_equal_p (x_base, y_base))
return 1; 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 /* The base addresses are different expressions. If they are not accessed
via AND, there is no conflict. We can bring knowledge of object via AND, there is no conflict. We can bring knowledge of object
alignment into play here. For example, on alpha, "char a, b;" can 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) ...@@ -2268,7 +2321,33 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
else else
y = addr_side_effect_eval (y, abs (ysize), 0); 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); return offset_overlap_p (c, xsize, ysize);
} }
...@@ -2636,7 +2715,7 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y, bool loop_invariant) ...@@ -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 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 stack frame. Otherwise a different base means we can't tell if they
overlap or not. */ overlap or not. */
if (! rtx_equal_p (basex, basey)) if (compare_base_decls (exprx, expry) == 0)
return ((CONSTANT_P (basex) && CONSTANT_P (basey)) return ((CONSTANT_P (basex) && CONSTANT_P (basey))
|| (CONSTANT_P (basex) && REG_P (basey) || (CONSTANT_P (basex) && REG_P (basey)
&& REGNO_PTR_FRAME_P (REGNO (basey))) && REGNO_PTR_FRAME_P (REGNO (basey)))
...@@ -2647,6 +2726,10 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y, bool loop_invariant) ...@@ -2647,6 +2726,10 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y, bool loop_invariant)
if (loop_invariant) if (loop_invariant)
return 0; 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)) sizex = (!MEM_P (rtlx) ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
: MEM_SIZE_KNOWN_P (rtlx) ? MEM_SIZE (rtlx) : MEM_SIZE_KNOWN_P (rtlx) ? MEM_SIZE (rtlx)
: -1); : -1);
......
...@@ -36,6 +36,7 @@ extern int nonoverlapping_memrefs_p (const_rtx, const_rtx, bool); ...@@ -36,6 +36,7 @@ extern int nonoverlapping_memrefs_p (const_rtx, const_rtx, bool);
extern void dump_alias_stats_in_alias_c (FILE *s); extern void dump_alias_stats_in_alias_c (FILE *s);
tree reference_alias_ptr_type (tree); tree reference_alias_ptr_type (tree);
bool alias_ptr_types_compatible_p (tree, tree); bool alias_ptr_types_compatible_p (tree, tree);
int compare_base_decls (tree, tree);
/* This alias set can be used to force a memory to conflict with all /* This alias set can be used to force a memory to conflict with all
other memories, creating a barrier across which no memory reference other memories, creating a barrier across which no memory reference
......
2015-12-08 Jan Hubicka <hubicka@ucw.cz>
PR ipa/61886
PR middle-end/25140
* gcc.c-torture/execute/alias-2.c: New testcase.
2015-12-09 Tobias Burnus <burnus@net-b.de> 2015-12-09 Tobias Burnus <burnus@net-b.de>
Alessandro Fanfarillo <fanfarillo.gcc@gmail.com> Alessandro Fanfarillo <fanfarillo.gcc@gmail.com>
......
/* { dg-require-alias "" } */
int a[10]={};
extern int b[10] __attribute__ ((alias("a")));
int off;
main()
{
b[off]=1;
a[off]=2;
if (b[off]!=2)
__builtin_abort ();
return 0;
}
...@@ -194,7 +194,7 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl) ...@@ -194,7 +194,7 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
ptr = TREE_OPERAND (base, 0); ptr = TREE_OPERAND (base, 0);
else if (base else if (base
&& DECL_P (base)) && DECL_P (base))
return base == decl; return compare_base_decls (base, decl) != 0;
else if (base else if (base
&& CONSTANT_CLASS_P (base)) && CONSTANT_CLASS_P (base))
return false; return false;
...@@ -805,8 +805,10 @@ nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2) ...@@ -805,8 +805,10 @@ nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
ref2 = TREE_OPERAND (TREE_OPERAND (ref2, 0), 0); ref2 = TREE_OPERAND (TREE_OPERAND (ref2, 0), 0);
} }
/* We must have the same base DECL. */ /* Bases must be either same or uncomparable. */
gcc_assert (ref1 == ref2); gcc_checking_assert (ref1 == ref2
|| (DECL_P (ref1) && DECL_P (ref2)
&& compare_base_decls (ref1, ref2) != 0));
/* Pop the stacks in parallel and examine the COMPONENT_REFs of the same /* Pop the stacks in parallel and examine the COMPONENT_REFs of the same
rank. This is sufficient because we start from the same DECL and you rank. This is sufficient because we start from the same DECL and you
...@@ -989,7 +991,7 @@ decl_refs_may_alias_p (tree ref1, tree base1, ...@@ -989,7 +991,7 @@ decl_refs_may_alias_p (tree ref1, tree base1,
gcc_checking_assert (DECL_P (base1) && DECL_P (base2)); gcc_checking_assert (DECL_P (base1) && DECL_P (base2));
/* If both references are based on different variables, they cannot alias. */ /* If both references are based on different variables, they cannot alias. */
if (base1 != base2) if (compare_base_decls (base1, base2) == 0)
return false; return false;
/* If both references are based on the same variable, they cannot alias if /* If both references are based on the same variable, they cannot alias if
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment