This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR13962 somewhat
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 29 Apr 2016 10:25:51 +0200 (CEST)
- Subject: [PATCH] Fix PR13962 somewhat
- Authentication-results: sourceware.org; auth=none
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 <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.
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" } } */