diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-04-29 08:36:49 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-04-29 08:36:49 +0000 |
commit | 73447cc5d17178b0a756be48133e55fdc7574c13 (patch) | |
tree | 1858d6d18d0408f87683330cd1b7664179f40c81 | |
parent | fb13bff45b1ea57e8128d38fcd0ba37a30a17f26 (diff) |
2016-04-29 Richard Biener <rguenther@suse.de>
PR tree-optimization/13962
PR tree-optimization/65686
* tree-ssa-alias.h (ptrs_compare_unequal): Declare.
* tree-ssa-alias.c (ptrs_compare_unequal): New function
using PTA to compare pointers.
* match.pd: Add pattern for pointer equality compare simplification
using ptrs_compare_unequal.
* gcc.dg/uninit-pr65686.c: New testcase.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235622 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/match.pd | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/uninit-pr65686.c | 18 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 60 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.h | 1 |
6 files changed, 103 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 268d4877988..0e7055614c6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,15 @@ 2016-04-29 Richard Biener <rguenther@suse.de> + PR tree-optimization/13962 + PR tree-optimization/65686 + * tree-ssa-alias.h (ptrs_compare_unequal): Declare. + * tree-ssa-alias.c (ptrs_compare_unequal): New function + using PTA to compare pointers. + * match.pd: Add pattern for pointer equality compare simplification + using ptrs_compare_unequal. + +2016-04-29 Richard Biener <rguenther@suse.de> + * stor-layout.c (layout_type): Do not build a pointer-to-element type for arrays. diff --git a/gcc/match.pd b/gcc/match.pd index 0e63328c43c..608afa3e25e 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2400,6 +2400,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (cmp == NE_EXPR) { constant_boolean_node (true, type); }))))))))) +/* Simplify pointer equality compares using PTA. */ +(for neeq (ne eq) + (simplify + (neeq @0 @1) + (if (POINTER_TYPE_P (TREE_TYPE (@0)) + && ptrs_compare_unequal (@0, @1)) + { neeq == EQ_EXPR ? boolean_false_node : boolean_true_node; }))) + /* Non-equality compare simplifications from fold_binary */ (for cmp (lt gt le ge) /* Comparisons with the highest or lowest possible integer of diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d9e1e03760e..389c124627f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-04-29 Richard Biener <rguenther@suse.de> + + PR tree-optimization/13962 + PR tree-optimization/65686 + * gcc.dg/uninit-pr65686.c: New testcase. + 2016-04-29 Jakub Jelinek <jakub@redhat.com> PR middle-end/70843 diff --git a/gcc/testsuite/gcc.dg/uninit-pr65686.c b/gcc/testsuite/gcc.dg/uninit-pr65686.c new file mode 100644 index 00000000000..1962ab76b93 --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-pr65686.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wall -fdump-tree-optimized" } */ + +typedef unsigned mytype; + +struct S { + mytype *pu; +}; + +mytype f(struct S *e) +{ + mytype x; /* { dg-bogus { "uninitialized" } } */ + if(&x != e->pu) + __builtin_memcpy(&x, e->pu, sizeof(unsigned)); + return x; +} + +/* { dg-final { scan-tree-dump-not "if" "optimized" } } */ diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 08f10e5248b..f801b013092 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -321,6 +321,66 @@ ptr_deref_may_alias_ref_p_1 (tree ptr, ao_ref *ref) return true; } +/* Returns true if PTR1 and PTR2 compare unequal because of points-to. */ + +bool +ptrs_compare_unequal (tree ptr1, tree ptr2) +{ + /* First resolve the pointers down to a SSA name pointer base or + a VAR_DECL, PARM_DECL or RESULT_DECL. This explicitely does + not yet try to handle LABEL_DECLs, FUNCTION_DECLs, CONST_DECLs + or STRING_CSTs which needs points-to adjustments to track them + in the points-to sets. */ + tree obj1 = NULL_TREE; + tree obj2 = NULL_TREE; + if (TREE_CODE (ptr1) == ADDR_EXPR) + { + tree tem = get_base_address (TREE_OPERAND (ptr1, 0)); + if (! tem) + return false; + if (TREE_CODE (tem) == VAR_DECL + || TREE_CODE (tem) == PARM_DECL + || TREE_CODE (tem) == RESULT_DECL) + obj1 = tem; + else if (TREE_CODE (tem) == MEM_REF) + ptr1 = TREE_OPERAND (tem, 0); + } + if (TREE_CODE (ptr2) == ADDR_EXPR) + { + tree tem = get_base_address (TREE_OPERAND (ptr2, 0)); + if (! tem) + return false; + if (TREE_CODE (tem) == VAR_DECL + || TREE_CODE (tem) == PARM_DECL + || TREE_CODE (tem) == RESULT_DECL) + obj2 = tem; + else if (TREE_CODE (tem) == MEM_REF) + ptr2 = TREE_OPERAND (tem, 0); + } + + if (obj1 && obj2) + /* Other code handles this correctly, no need to duplicate it here. */; + else if (obj1 && TREE_CODE (ptr2) == SSA_NAME) + { + struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr2); + if (!pi) + return false; + return !pt_solution_includes (&pi->pt, obj1); + } + else if (TREE_CODE (ptr1) == SSA_NAME && obj2) + { + struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr1); + if (!pi) + return false; + return !pt_solution_includes (&pi->pt, obj2); + } + + /* ??? We'd like to handle ptr1 != NULL and ptr1 != ptr2 + but those require pt.null to be conservatively correct. */ + + return false; +} + /* Returns whether reference REF to BASE may refer to global memory. */ static bool diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h index ccf23b4df30..0593b05a7bc 100644 --- a/gcc/tree-ssa-alias.h +++ b/gcc/tree-ssa-alias.h @@ -101,6 +101,7 @@ extern alias_set_type ao_ref_alias_set (ao_ref *); extern alias_set_type ao_ref_base_alias_set (ao_ref *); extern bool ptr_deref_may_alias_global_p (tree); extern bool ptr_derefs_may_alias_p (tree, tree); +extern bool ptrs_compare_unequal (tree, tree); extern bool ref_may_alias_global_p (tree); extern bool ref_may_alias_global_p (ao_ref *); extern bool refs_may_alias_p (tree, tree); |