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

Reply via email to