This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR13962 somewhat


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]