diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-10-14 15:51:15 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-10-14 15:51:15 +0000 |
commit | 2760c0e3bbb93cd8fff8cbcd5558caf8547196af (patch) | |
tree | 136f40349648fdc45c3adcb47ada09856e717076 /gcc | |
parent | 16a547ac42d850d8f2f902709e2217619e2302d2 (diff) | |
download | gcc-2760c0e3bbb93cd8fff8cbcd5558caf8547196af.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165473 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr44913.c | 24 | ||||
-rw-r--r-- | gcc/tree-data-ref.c | 144 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 92 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.h | 1 |
6 files changed, 113 insertions, 165 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 303ea78a626..bab69584717 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a81938d3509..22dc14b591f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -5,6 +5,11 @@ 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 * g++.dg/lto/20101014-2_0.C: New testcase. diff --git a/gcc/testsuite/gcc.dg/torture/pr44913.c b/gcc/testsuite/gcc.dg/torture/pr44913.c new file mode 100644 index 00000000000..eef61fbfb15 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr44913.c @@ -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; +} diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index 06b36e9d4fe..3cee320846b 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -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; - - /* 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; + tree addr_a = DR_BASE_OBJECT (a); + tree addr_b = DR_BASE_OBJECT (b); - /* 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 *); diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index afd5e0852cc..42335b577a5 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -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)); - - /* Non-aliased variables can not be pointed to. */ - if (!may_be_aliased (decl)) + /* Conversions are irrelevant for points-to information and + data-dependence analysis can feed us those. */ + STRIP_NOPS (ptr); + + /* 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; diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h index 1f220765781..a97ba69822a 100644 --- a/gcc/tree-ssa-alias.h +++ b/gcc/tree-ssa-alias.h @@ -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); |