aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2016-04-29 08:36:49 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2016-04-29 08:36:49 +0000
commit98998245d99f06946b4d5ed6744c77c3760f1141 (patch)
tree1858d6d18d0408f87683330cd1b7664179f40c81
parent59cf7a415cf212da56ea3ebd5b34063e84b9275f (diff)
downloadgcc-98998245d99f06946b4d5ed6744c77c3760f1141.zip
gcc-98998245d99f06946b4d5ed6744c77c3760f1141.tar.gz
gcc-98998245d99f06946b4d5ed6744c77c3760f1141.tar.bz2
re PR tree-optimization/13962 ([tree-ssa] make "fold" use alias information to optimize pointer comparisons)
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. From-SVN: r235622
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/match.pd8
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/uninit-pr65686.c18
-rw-r--r--gcc/tree-ssa-alias.c60
-rw-r--r--gcc/tree-ssa-alias.h1
6 files changed, 103 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 268d487..0e70556 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 0e63328..608afa3 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 d9e1e03..389c124 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 0000000..1962ab7
--- /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 08f10e5..f801b01 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 ccf23b4..0593b05 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);