re PR tree-optimization/44913 (-ftree-vectorize causes FAIL: gcc.dg/pr44838.c execution test)
2010-10-14 Richard Guenther <rguenther@suse.de> PR tree-optimization/44913 * tree-data-ref.c (disjoint_objects_p): Remove. (dr_may_alias_p): Simplify. Only hand the base object to the alias-oracle. * tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Handle some more trees, bail out instead of asserting. (ptr_derefs_may_alias_p): Likewise. Export. (refs_may_alias_p_1): Handle STRING_CSTs. * tree-ssa-alias.h (ptr_derefs_may_alias_p): Declare. * gcc.dg/torture/pr44913.c: New testcase. From-SVN: r165473
This commit is contained in:
parent
180f8dbbb3
commit
7d36e53818
6 changed files with 112 additions and 164 deletions
|
@ -1,3 +1,15 @@
|
|||
2010-10-14 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/44913
|
||||
* tree-data-ref.c (disjoint_objects_p): Remove.
|
||||
(dr_may_alias_p): Simplify. Only hand the base object to
|
||||
the alias-oracle.
|
||||
* tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Handle
|
||||
some more trees, bail out instead of asserting.
|
||||
(ptr_derefs_may_alias_p): Likewise. Export.
|
||||
(refs_may_alias_p_1): Handle STRING_CSTs.
|
||||
* tree-ssa-alias.h (ptr_derefs_may_alias_p): Declare.
|
||||
|
||||
2010-10-14 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
PR c/45969
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
PR c/45969
|
||||
* gcc.c-torture/compile/pr45969-1.c: New test.
|
||||
|
||||
2010-10-14 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/44913
|
||||
* gcc.dg/torture/pr44913.c: New testcase.
|
||||
|
||||
2010-10-14 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR lto/45382
|
||||
|
|
24
gcc/testsuite/gcc.dg/torture/pr44913.c
Normal file
24
gcc/testsuite/gcc.dg/torture/pr44913.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* { dg-do run } */
|
||||
|
||||
void __attribute__((noinline,noclone))
|
||||
foo (int *a, int n)
|
||||
{
|
||||
int *lasta = a + n;
|
||||
for (; a != lasta; a++)
|
||||
{
|
||||
*a *= 2;
|
||||
a[1] = a[-1] + a[-2];
|
||||
}
|
||||
}
|
||||
extern void abort (void);
|
||||
int main()
|
||||
{
|
||||
int a[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
|
||||
int r[16] = { 1, 2, 6, 6, 16, 24, 44, 80, 136, 248, 432, 768, 1360, 2400, 4256, 3760 };
|
||||
unsigned i;
|
||||
foo (&a[2], 13);
|
||||
for (i = 0; i < 8; ++i)
|
||||
if (a[i] != r[i])
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
|
@ -1233,154 +1233,20 @@ object_address_invariant_in_loop_p (const struct loop *loop, const_tree obj)
|
|||
loop->num);
|
||||
}
|
||||
|
||||
/* Returns true if A and B are accesses to different objects, or to different
|
||||
fields of the same object. */
|
||||
|
||||
static bool
|
||||
disjoint_objects_p (tree a, tree b)
|
||||
{
|
||||
tree base_a, base_b;
|
||||
VEC (tree, heap) *comp_a = NULL, *comp_b = NULL;
|
||||
bool ret;
|
||||
|
||||
base_a = get_base_address (a);
|
||||
base_b = get_base_address (b);
|
||||
|
||||
if (DECL_P (base_a)
|
||||
&& DECL_P (base_b)
|
||||
&& base_a != base_b)
|
||||
return true;
|
||||
|
||||
if (!operand_equal_p (base_a, base_b, 0))
|
||||
return false;
|
||||
|
||||
/* Compare the component references of A and B. We must start from the inner
|
||||
ones, so record them to the vector first. */
|
||||
while (handled_component_p (a))
|
||||
{
|
||||
VEC_safe_push (tree, heap, comp_a, a);
|
||||
a = TREE_OPERAND (a, 0);
|
||||
}
|
||||
while (handled_component_p (b))
|
||||
{
|
||||
VEC_safe_push (tree, heap, comp_b, b);
|
||||
b = TREE_OPERAND (b, 0);
|
||||
}
|
||||
|
||||
ret = false;
|
||||
while (1)
|
||||
{
|
||||
if (VEC_length (tree, comp_a) == 0
|
||||
|| VEC_length (tree, comp_b) == 0)
|
||||
break;
|
||||
|
||||
a = VEC_pop (tree, comp_a);
|
||||
b = VEC_pop (tree, comp_b);
|
||||
|
||||
/* Real and imaginary part of a variable do not alias. */
|
||||
if ((TREE_CODE (a) == REALPART_EXPR
|
||||
&& TREE_CODE (b) == IMAGPART_EXPR)
|
||||
|| (TREE_CODE (a) == IMAGPART_EXPR
|
||||
&& TREE_CODE (b) == REALPART_EXPR))
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (TREE_CODE (a) != TREE_CODE (b))
|
||||
break;
|
||||
|
||||
/* Nothing to do for ARRAY_REFs, as the indices of array_refs in
|
||||
DR_BASE_OBJECT are always zero. */
|
||||
if (TREE_CODE (a) == ARRAY_REF)
|
||||
continue;
|
||||
else if (TREE_CODE (a) == COMPONENT_REF)
|
||||
{
|
||||
if (operand_equal_p (TREE_OPERAND (a, 1), TREE_OPERAND (b, 1), 0))
|
||||
continue;
|
||||
|
||||
/* Different fields of unions may overlap. */
|
||||
base_a = TREE_OPERAND (a, 0);
|
||||
if (TREE_CODE (TREE_TYPE (base_a)) == UNION_TYPE)
|
||||
break;
|
||||
|
||||
/* Different fields of structures cannot. */
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
VEC_free (tree, heap, comp_a);
|
||||
VEC_free (tree, heap, comp_b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Returns false if we can prove that data references A and B do not alias,
|
||||
true otherwise. */
|
||||
|
||||
bool
|
||||
dr_may_alias_p (const struct data_reference *a, const struct data_reference *b)
|
||||
{
|
||||
const_tree addr_a = DR_BASE_ADDRESS (a);
|
||||
const_tree addr_b = DR_BASE_ADDRESS (b);
|
||||
const_tree type_a, type_b;
|
||||
const_tree decl_a = NULL_TREE, decl_b = NULL_TREE;
|
||||
tree addr_a = DR_BASE_OBJECT (a);
|
||||
tree addr_b = DR_BASE_OBJECT (b);
|
||||
|
||||
/* If the accessed objects are disjoint, the memory references do not
|
||||
alias. */
|
||||
if (disjoint_objects_p (DR_BASE_OBJECT (a), DR_BASE_OBJECT (b)))
|
||||
return false;
|
||||
|
||||
/* Query the alias oracle. */
|
||||
if (DR_IS_WRITE (a) && DR_IS_WRITE (b))
|
||||
{
|
||||
if (!refs_output_dependent_p (DR_REF (a), DR_REF (b)))
|
||||
return false;
|
||||
}
|
||||
return refs_output_dependent_p (addr_a, addr_b);
|
||||
else if (DR_IS_READ (a) && DR_IS_WRITE (b))
|
||||
{
|
||||
if (!refs_anti_dependent_p (DR_REF (a), DR_REF (b)))
|
||||
return false;
|
||||
}
|
||||
else if (!refs_may_alias_p (DR_REF (a), DR_REF (b)))
|
||||
return false;
|
||||
|
||||
if (!addr_a || !addr_b)
|
||||
return true;
|
||||
|
||||
/* If the references are based on different static objects, they cannot
|
||||
alias (PTA should be able to disambiguate such accesses, but often
|
||||
it fails to). */
|
||||
if (TREE_CODE (addr_a) == ADDR_EXPR
|
||||
&& TREE_CODE (addr_b) == ADDR_EXPR)
|
||||
return TREE_OPERAND (addr_a, 0) == TREE_OPERAND (addr_b, 0);
|
||||
|
||||
/* An instruction writing through a restricted pointer is "independent" of any
|
||||
instruction reading or writing through a different restricted pointer,
|
||||
in the same block/scope. */
|
||||
|
||||
type_a = TREE_TYPE (addr_a);
|
||||
type_b = TREE_TYPE (addr_b);
|
||||
gcc_assert (POINTER_TYPE_P (type_a) && POINTER_TYPE_P (type_b));
|
||||
|
||||
if (TREE_CODE (addr_a) == SSA_NAME)
|
||||
decl_a = SSA_NAME_VAR (addr_a);
|
||||
if (TREE_CODE (addr_b) == SSA_NAME)
|
||||
decl_b = SSA_NAME_VAR (addr_b);
|
||||
|
||||
if (TYPE_RESTRICT (type_a) && TYPE_RESTRICT (type_b)
|
||||
&& (DR_IS_WRITE (a) || DR_IS_WRITE (b))
|
||||
&& decl_a && DECL_P (decl_a)
|
||||
&& decl_b && DECL_P (decl_b)
|
||||
&& decl_a != decl_b
|
||||
&& TREE_CODE (DECL_CONTEXT (decl_a)) == FUNCTION_DECL
|
||||
&& DECL_CONTEXT (decl_a) == DECL_CONTEXT (decl_b))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return refs_anti_dependent_p (addr_a, addr_b);
|
||||
return refs_may_alias_p (addr_a, addr_b);
|
||||
}
|
||||
|
||||
static void compute_self_dependence (struct data_dependence_relation *);
|
||||
|
|
|
@ -166,17 +166,31 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
|
|||
{
|
||||
struct ptr_info_def *pi;
|
||||
|
||||
gcc_assert ((TREE_CODE (ptr) == SSA_NAME
|
||||
|| TREE_CODE (ptr) == ADDR_EXPR
|
||||
|| TREE_CODE (ptr) == INTEGER_CST)
|
||||
&& (TREE_CODE (decl) == VAR_DECL
|
||||
|| TREE_CODE (decl) == PARM_DECL
|
||||
|| TREE_CODE (decl) == RESULT_DECL));
|
||||
/* Conversions are irrelevant for points-to information and
|
||||
data-dependence analysis can feed us those. */
|
||||
STRIP_NOPS (ptr);
|
||||
|
||||
/* Non-aliased variables can not be pointed to. */
|
||||
if (!may_be_aliased (decl))
|
||||
/* Anything we do not explicilty handle aliases. */
|
||||
if ((TREE_CODE (ptr) != SSA_NAME
|
||||
&& TREE_CODE (ptr) != ADDR_EXPR
|
||||
&& TREE_CODE (ptr) != POINTER_PLUS_EXPR)
|
||||
|| !POINTER_TYPE_P (TREE_TYPE (ptr))
|
||||
|| (TREE_CODE (decl) != VAR_DECL
|
||||
&& TREE_CODE (decl) != PARM_DECL
|
||||
&& TREE_CODE (decl) != RESULT_DECL))
|
||||
return false;
|
||||
|
||||
/* Disregard pointer offsetting. */
|
||||
if (TREE_CODE (ptr) == POINTER_PLUS_EXPR)
|
||||
{
|
||||
do
|
||||
{
|
||||
ptr = TREE_OPERAND (ptr, 0);
|
||||
}
|
||||
while (TREE_CODE (ptr) == POINTER_PLUS_EXPR);
|
||||
return ptr_deref_may_alias_decl_p (ptr, decl);
|
||||
}
|
||||
|
||||
/* ADDR_EXPR pointers either just offset another pointer or directly
|
||||
specify the pointed-to set. */
|
||||
if (TREE_CODE (ptr) == ADDR_EXPR)
|
||||
|
@ -196,10 +210,9 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* We can end up with dereferencing constant pointers.
|
||||
Just bail out in this case. */
|
||||
if (TREE_CODE (ptr) == INTEGER_CST)
|
||||
return true;
|
||||
/* Non-aliased variables can not be pointed to. */
|
||||
if (!may_be_aliased (decl))
|
||||
return false;
|
||||
|
||||
/* If we do not have useful points-to information for this pointer
|
||||
we cannot disambiguate anything else. */
|
||||
|
@ -222,17 +235,46 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
|
|||
The caller is responsible for applying TBAA to see if accesses
|
||||
through PTR1 and PTR2 may conflict at all. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
|
||||
{
|
||||
struct ptr_info_def *pi1, *pi2;
|
||||
|
||||
gcc_assert ((TREE_CODE (ptr1) == SSA_NAME
|
||||
|| TREE_CODE (ptr1) == ADDR_EXPR
|
||||
|| TREE_CODE (ptr1) == INTEGER_CST)
|
||||
&& (TREE_CODE (ptr2) == SSA_NAME
|
||||
|| TREE_CODE (ptr2) == ADDR_EXPR
|
||||
|| TREE_CODE (ptr2) == INTEGER_CST));
|
||||
/* Conversions are irrelevant for points-to information and
|
||||
data-dependence analysis can feed us those. */
|
||||
STRIP_NOPS (ptr1);
|
||||
STRIP_NOPS (ptr2);
|
||||
|
||||
/* Anything we do not explicilty handle aliases. */
|
||||
if ((TREE_CODE (ptr1) != SSA_NAME
|
||||
&& TREE_CODE (ptr1) != ADDR_EXPR
|
||||
&& TREE_CODE (ptr1) != POINTER_PLUS_EXPR)
|
||||
|| (TREE_CODE (ptr2) != SSA_NAME
|
||||
&& TREE_CODE (ptr2) != ADDR_EXPR
|
||||
&& TREE_CODE (ptr2) != POINTER_PLUS_EXPR)
|
||||
|| !POINTER_TYPE_P (TREE_TYPE (ptr1))
|
||||
|| !POINTER_TYPE_P (TREE_TYPE (ptr2)))
|
||||
return true;
|
||||
|
||||
/* Disregard pointer offsetting. */
|
||||
if (TREE_CODE (ptr1) == POINTER_PLUS_EXPR)
|
||||
{
|
||||
do
|
||||
{
|
||||
ptr1 = TREE_OPERAND (ptr1, 0);
|
||||
}
|
||||
while (TREE_CODE (ptr1) == POINTER_PLUS_EXPR);
|
||||
return ptr_derefs_may_alias_p (ptr1, ptr2);
|
||||
}
|
||||
if (TREE_CODE (ptr2) == POINTER_PLUS_EXPR)
|
||||
{
|
||||
do
|
||||
{
|
||||
ptr2 = TREE_OPERAND (ptr2, 0);
|
||||
}
|
||||
while (TREE_CODE (ptr2) == POINTER_PLUS_EXPR);
|
||||
return ptr_derefs_may_alias_p (ptr1, ptr2);
|
||||
}
|
||||
|
||||
/* ADDR_EXPR pointers either just offset another pointer or directly
|
||||
specify the pointed-to set. */
|
||||
|
@ -263,12 +305,6 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* We can end up with dereferencing constant pointers.
|
||||
Just bail out in this case. */
|
||||
if (TREE_CODE (ptr1) == INTEGER_CST
|
||||
|| TREE_CODE (ptr2) == INTEGER_CST)
|
||||
return true;
|
||||
|
||||
/* We may end up with two empty points-to solutions for two same pointers.
|
||||
In this case we still want to say both pointers alias, so shortcut
|
||||
that here. */
|
||||
|
@ -938,6 +974,7 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
|
|||
gcc_checking_assert ((!ref1->ref
|
||||
|| TREE_CODE (ref1->ref) == SSA_NAME
|
||||
|| DECL_P (ref1->ref)
|
||||
|| TREE_CODE (ref1->ref) == STRING_CST
|
||||
|| handled_component_p (ref1->ref)
|
||||
|| INDIRECT_REF_P (ref1->ref)
|
||||
|| TREE_CODE (ref1->ref) == MEM_REF
|
||||
|
@ -945,6 +982,7 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
|
|||
&& (!ref2->ref
|
||||
|| TREE_CODE (ref2->ref) == SSA_NAME
|
||||
|| DECL_P (ref2->ref)
|
||||
|| TREE_CODE (ref2->ref) == STRING_CST
|
||||
|| handled_component_p (ref2->ref)
|
||||
|| INDIRECT_REF_P (ref2->ref)
|
||||
|| TREE_CODE (ref2->ref) == MEM_REF
|
||||
|
@ -965,6 +1003,8 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
|
|||
|| TREE_CODE (base2) == SSA_NAME
|
||||
|| TREE_CODE (base1) == CONST_DECL
|
||||
|| TREE_CODE (base2) == CONST_DECL
|
||||
|| TREE_CODE (base1) == STRING_CST
|
||||
|| TREE_CODE (base2) == STRING_CST
|
||||
|| is_gimple_min_invariant (base1)
|
||||
|| is_gimple_min_invariant (base2))
|
||||
return false;
|
||||
|
|
|
@ -97,6 +97,7 @@ extern void ao_ref_init_from_ptr_and_size (ao_ref *, tree, tree);
|
|||
extern tree ao_ref_base (ao_ref *);
|
||||
extern alias_set_type ao_ref_alias_set (ao_ref *);
|
||||
extern bool ptr_deref_may_alias_global_p (tree);
|
||||
extern bool ptr_derefs_may_alias_p (tree, tree);
|
||||
extern bool refs_may_alias_p (tree, tree);
|
||||
extern bool refs_may_alias_p_1 (ao_ref *, ao_ref *, bool);
|
||||
extern bool refs_anti_dependent_p (tree, tree);
|
||||
|
|
Loading…
Add table
Reference in a new issue