The PR asks that we optimize pointer comparisons using PTA information.
This patch implements the bits that are possible without adjusting
PTA to be more precise about things like points-to-null or
points-to-string (or points-to-label/function).
This also fixes PR65686 where it avoids a bogus uninit warning
by simplifying the compare in
mytype f(struct S *e)
{
mytype x;
if(&x != e->pu)
where obviously the pointer e->pu in global memory cannot point to x.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
Richard.
2016-04-29 Richard Biener <[email protected]>
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.
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig 2016-04-28 11:56:26.864468581 +0200
--- gcc/tree-ssa-alias.c 2016-04-28 15:25:00.596095600 +0200
*************** ptr_deref_may_alias_ref_p_1 (tree ptr, a
*** 321,326 ****
--- 321,386 ----
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
Index: gcc/tree-ssa-alias.h
===================================================================
*** gcc/tree-ssa-alias.h.orig 2016-04-28 11:56:26.864468581 +0200
--- gcc/tree-ssa-alias.h 2016-04-28 11:57:18.389057793 +0200
*************** extern alias_set_type ao_ref_alias_set (
*** 101,106 ****
--- 101,107 ----
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);
Index: gcc/match.pd
===================================================================
*** gcc/match.pd.orig 2016-04-28 11:56:26.864468581 +0200
--- gcc/match.pd 2016-04-28 11:59:36.070631926 +0200
*************** DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
*** 2409,2414 ****
--- 2409,2422 ----
(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
Index: gcc/testsuite/gcc.dg/uninit-pr65686.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/uninit-pr65686.c 2016-04-28 12:03:13.477128590
+0200
***************
*** 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" } } */