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 <rguent...@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. 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" } } */