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]

[improved-aliasing]: Fix PR tree-optimization/24287


This patch causes us to know that things that escape only to pure/const
functions aren't clobbered by the non-pure/const ones, and only read by
the pure/const ones.

Any good context-sensitive mod-ref algorithm would discover this on it's
own, but since we don't have one yet, might as well do the best we can
with what we have.

It also fixes the imprecision that we used to consider anything that had
pt_anything set to have it's value escape, which is not really true.
Things escape only because they escape, not because they point to
anything.  

Fixing this required teaching it that incoming pointers value-escape by
default.


Bootstrapped and regtested on i686-pc-linux-gnu
Committed to improved-aliasing

--Dan
2005-10-18  Daniel Berlin  <dberlin@dberlin.org>

	Fix PR tree-optimization/24287
	* tree-dfa.c (dump_variable): Print reasons for call clobbering.
	* tree-flow.h (struct ptr_info_def): Add escape mask to pointer.
	(ESCAPE_TRANSITIVE): Removed.
	(ESCAPE_TO_PURE_CONST): New.
	(ESCAPE_IS_PARM): New.
	(ESCAPE_UNKNOWN): New.
	* tree-ssa-alias.c (set_initial_properties): Incoming pointers are
	value escaping.
	Pointers that point to anything are not.
	Use pointer escape mask.
	(is_escape_site): Use ESCAPE_TO_PURE_CONST.
	* tree-ssa-operands.c (add_call_clobber_ops): Clean up a bit.
	Things that *only* escape to pure/const functions are only read by
	pure/const functions, and are not clobbered by the non-pure/const
	functions. 
	(add_call_read_ops): Cleanup.
	* tree-ssa-structalias.c (update_alias_info): Use pi->escape_mask,
	not v_ann.
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dfa.c,v
retrieving revision 2.63.4.6
diff -u -p -r2.63.4.6 tree-dfa.c
--- tree-dfa.c	18 Oct 2005 15:35:40 -0000	2.63.4.6
+++ tree-dfa.c	18 Oct 2005 21:42:17 -0000
@@ -353,7 +353,35 @@ dump_variable (FILE *file, tree var)
     fprintf (file, ", is volatile");
 
   if (is_call_clobbered (var))
-    fprintf (file, ", call clobbered");
+    {
+      fprintf (file, ", call clobbered");
+      if (dump_flags & TDF_DETAILS)
+	{
+	  var_ann_t va = var_ann (var);
+	  unsigned int escape_mask = va->escape_mask;
+	  
+	  fprintf (file, " (");
+	  if (escape_mask & ESCAPE_STORED_IN_GLOBAL)
+	    fprintf (file, ", stored in global");
+	  if (escape_mask & ESCAPE_TO_ASM)
+	    fprintf (file, ", goes through ASM");
+	  if (escape_mask & ESCAPE_TO_CALL)
+	    fprintf (file, ", passed to call");
+	  if (escape_mask & ESCAPE_BAD_CAST)
+	    fprintf (file, ", bad cast");
+	  if (escape_mask & ESCAPE_TO_RETURN)
+	    fprintf (file, ", returned from func");
+	  if (escape_mask & ESCAPE_TO_PURE_CONST)
+	    fprintf (file, ", passed to pure/const");
+	  if (escape_mask & ESCAPE_IS_GLOBAL)
+	    fprintf (file, ", is global var");
+	  if (escape_mask & ESCAPE_IS_PARM)
+	    fprintf (file, ", is incoming pointer");
+	  if (escape_mask & ESCAPE_UNKNOWN)
+	    fprintf (file, ", unknown escape");
+	  fprintf (file, " )");
+	}
+    }
 
   if (default_def (var))
     {
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 2.132.2.8
diff -u -p -r2.132.2.8 tree-flow.h
--- tree-flow.h	18 Oct 2005 15:35:40 -0000	2.132.2.8
+++ tree-flow.h	18 Oct 2005 21:42:17 -0000
@@ -92,6 +92,9 @@ struct ptr_info_def GTY(())
      pointer will be represented by this memory tag, instead of the type
      tag computed by TBAA.  */
   tree name_mem_tag;
+
+  /* Mask of reasons this pointer's value escapes the function  */
+  unsigned int escape_mask;
 };
 
 
@@ -777,9 +780,10 @@ enum escape_type 
     ESCAPE_TO_CALL = 1 << 3,
     ESCAPE_BAD_CAST = 1 << 4, 
     ESCAPE_TO_RETURN = 1 << 5,
-    ESCAPE_TRANSITIVE = 1 << 6,
+    ESCAPE_TO_PURE_CONST = 1 << 6,
     ESCAPE_IS_GLOBAL = 1 << 7,
-    ESCAPE_UNKNOWN = 1 << 8
+    ESCAPE_IS_PARM = 1 << 8,
+    ESCAPE_UNKNOWN = 1 << 9
   };
 
 /* In tree-flow-inline.h  */
Index: tree-ssa-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-alias.c,v
retrieving revision 2.109.4.11
diff -u -p -r2.109.4.11 tree-ssa-alias.c
--- tree-ssa-alias.c	18 Oct 2005 15:35:40 -0000	2.109.4.11
+++ tree-ssa-alias.c	18 Oct 2005 21:42:18 -0000
@@ -327,8 +327,18 @@ set_initial_properties (struct alias_inf
       if (is_global_var (var) 
 	  && (!var_can_have_subvars (var)
 	      || get_subvars_for_var (var) == NULL))
-	if (!unmodifiable_var_p (var))
-	  mark_call_clobbered (var, ESCAPE_IS_GLOBAL);
+	{
+	  if (!unmodifiable_var_p (var))
+	    mark_call_clobbered (var, ESCAPE_IS_GLOBAL);
+	}
+      else if (TREE_CODE (var) == PARM_DECL
+	       && default_def (var)
+	       && POINTER_TYPE_P (TREE_TYPE (var)))
+	{
+	  tree def = default_def (var);
+	  get_ptr_info (def)->value_escapes_p = 1;
+	  get_ptr_info (def)->escape_mask |= ESCAPE_IS_PARM;	  
+	}
     }
 
   for (i = 0; i < VARRAY_ACTIVE_SIZE (ai->processed_ptrs); i++)
@@ -336,16 +346,16 @@ set_initial_properties (struct alias_inf
       tree ptr = VARRAY_TREE (ai->processed_ptrs, i);
       struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
       var_ann_t v_ann = var_ann (SSA_NAME_VAR (ptr));
-
-      if (pi->value_escapes_p || pi->pt_anything)
+      
+      if (pi->value_escapes_p)
 	{
-	  /* If PTR escapes or may point to anything, then its associated
-	     memory tags and pointed-to variables are call-clobbered.  */
+	  /* If PTR escapes then its associated memory tags and
+	     pointed-to variables are call-clobbered.  */
 	  if (pi->name_mem_tag)
-	    mark_call_clobbered (pi->name_mem_tag, v_ann->escape_mask);
+	    mark_call_clobbered (pi->name_mem_tag, pi->escape_mask);
 
 	  if (v_ann->type_mem_tag)
-	    mark_call_clobbered (v_ann->type_mem_tag, v_ann->escape_mask);
+	    mark_call_clobbered (v_ann->type_mem_tag, pi->escape_mask);
 
 	  if (pi->pt_vars)
 	    {
@@ -353,7 +363,7 @@ set_initial_properties (struct alias_inf
 	      unsigned int j;	      
 	      EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j, bi)
 		if (!unmodifiable_var_p (referenced_var (j)))
-		  mark_call_clobbered (referenced_var (j), v_ann->escape_mask);
+		  mark_call_clobbered (referenced_var (j), pi->escape_mask);
 	    }
 	}
       /* If the name tag is call clobbered, so is the type tag
@@ -361,7 +371,7 @@ set_initial_properties (struct alias_inf
       if (pi->name_mem_tag
 	  && v_ann->type_mem_tag
 	  && is_call_clobbered (pi->name_mem_tag))
-	mark_call_clobbered (v_ann->type_mem_tag, v_ann->escape_mask);
+	mark_call_clobbered (v_ann->type_mem_tag, pi->escape_mask);
 
       if ((pi->pt_global_mem || pi->pt_anything) && pi->name_mem_tag)
 	mark_tag_global (pi->name_mem_tag);
@@ -1890,7 +1900,10 @@ is_escape_site (tree stmt, struct alias_
       ai->num_calls_found++;
 
       if (!TREE_SIDE_EFFECTS (call))
-	ai->num_pure_const_calls_found++;
+	{
+	  ai->num_pure_const_calls_found++;
+	  return ESCAPE_TO_PURE_CONST;
+	}
 
       return ESCAPE_TO_CALL;
     }
Index: tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.c,v
retrieving revision 2.100.4.7
diff -u -p -r2.100.4.7 tree-ssa-operands.c
--- tree-ssa-operands.c	18 Oct 2005 15:35:41 -0000	2.100.4.7
+++ tree-ssa-operands.c	18 Oct 2005 21:42:18 -0000
@@ -1860,7 +1860,6 @@ add_call_clobber_ops (tree stmt, tree ca
   struct cgraph_node *ournode = cgraph_node (current_function_decl);
   bool okay_for_call_skip = callee_okay_for_noescape (ournode, callee);
   
-  
   /* Functions that are not const, pure or never return may clobber
      call-clobbered variables.  */
   if (s_ann)
@@ -1888,28 +1887,45 @@ add_call_clobber_ops (tree stmt, tree ca
   /* Add a V_MAY_DEF operand for every call clobbered variable.  */
   EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, u, bi)
     {
-      tree var = referenced_var (u);
+      tree var = referenced_var_lookup (u);
+      unsigned int escape_mask = var_ann (var)->escape_mask;
       bool not_read
 	= not_read_b ? bitmap_bit_p (not_read_b, u) : false;
       bool not_written
 	= not_written_b ? bitmap_bit_p (not_written_b, u) : false;
-      bool before = okay_for_call_skip;
       
       gcc_assert (!unmodifiable_var_p (var));
       
       clobber_stats.clobbered_vars++;
 
+
       /* See if this variable is really clobbered by this function.  */
-      if (okay_for_call_skip)
+
+      /* Trivial case: Things escaping only to pure/const are not
+	 clobbered by non-pure-const, and only read by pure/const. */
+      if ((escape_mask & ~(ESCAPE_TO_PURE_CONST)) == 0)
 	{
-	  okay_for_call_skip &= (var_ann (var)->escape_mask & ~(ESCAPE_TO_CALL)) == 0;	  
-	  if (okay_for_call_skip)
+	  tree call = get_call_expr_in (stmt);
+	  if (call_expr_flags (call) & (ECF_CONST | ECF_PURE))
+	    {
+	      add_stmt_operand (&var, s_ann, opf_none);
+	      clobber_stats.unescapable_clobbers_avoided++;
+	      continue;
+	    }
+	  else
 	    {
 	      clobber_stats.unescapable_clobbers_avoided++;
 	      continue;
 	    }
 	}
-      okay_for_call_skip = before;
+      
+      /* Otherwise, see if we know it doesn't escape to *this*
+	 function.  */
+      if (okay_for_call_skip && (escape_mask & ~(ESCAPE_TO_CALL | ESCAPE_TO_PURE_CONST)) == 0)
+	{
+	  clobber_stats.unescapable_clobbers_avoided++;
+	  continue;
+	}
       
       if (not_written)
 	{
@@ -1954,9 +1970,9 @@ add_call_read_ops (tree stmt, tree calle
   EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, u, bi)
     {
       tree var = referenced_var (u);
+      var_ann_t va = var_ann (var);
       bool not_read = not_read_b ? bitmap_bit_p (not_read_b, u) : false;
-      bool before = okay_for_call_skip;
-      
+
       clobber_stats.readonly_clobbers++;
       
       if (not_read)
@@ -1965,18 +1981,13 @@ add_call_read_ops (tree stmt, tree calle
 	  continue;
 	}
       
-      if (okay_for_call_skip)
+      if (okay_for_call_skip && (va->escape_mask & ~(ESCAPE_TO_CALL | ESCAPE_TO_PURE_CONST)) == 0)
 	{
-	  okay_for_call_skip &= (var_ann (var)->escape_mask & ~(ESCAPE_TO_CALL)) == 0;
-	  if (okay_for_call_skip)
-	    {
-	      clobber_stats.unescapable_clobbers_avoided++;
-	      continue;
-	    }
+	  clobber_stats.unescapable_clobbers_avoided++;
+	  continue;
 	}
       
       add_stmt_operand (&var, s_ann, opf_none | opf_non_specific);
-      okay_for_call_skip = before;      
     }
 }
 
Index: tree-ssa-structalias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-structalias.c,v
retrieving revision 2.27.2.10
diff -u -p -r2.27.2.10 tree-ssa-structalias.c
--- tree-ssa-structalias.c	18 Oct 2005 15:35:41 -0000	2.27.2.10
+++ tree-ssa-structalias.c	18 Oct 2005 21:42:19 -0000
@@ -2998,7 +2998,7 @@ update_alias_info (tree stmt, struct ali
 	     escapes and so the pointed-to variables need to
 	     be marked call-clobbered.  */
 	  pi->value_escapes_p = 1;
-	  v_ann->escape_mask |= stmt_escape_type;
+	  pi->escape_mask |= stmt_escape_type;
 
 	  /* If the statement makes a function call, assume
 	     that pointer OP will be dereferenced in a store
Index: testsuite/gcc.dg/tree-ssa/pr24287.c
===================================================================
RCS file: testsuite/gcc.dg/tree-ssa/pr24287.c
diff -N testsuite/gcc.dg/tree-ssa/pr24287.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/tree-ssa/pr24287.c	18 Oct 2005 21:42:22 -0000
@@ -0,0 +1,25 @@
+/* { dg-do compile } */ 
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+int g1(int);
+int h(int *a, int *b)__attribute__((pure));
+void link_error();
+
+/* The calls to link_error should be eliminated, since nothing escapes to 
+   non-pure functions.  */
+int g(void)
+{
+  int t = 0, t1 = 2;
+  int t2 = h(&t, &t1);
+  if (t != 0)
+    link_error ();
+  if (t1 != 2)
+    link_error ();
+  g1(t2);
+  if (t != 0)
+    link_error ();
+  if (t1 != 2)
+    link_error ();
+  return t2 == 2;
+}
+/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */

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