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]

Re: [PATCH] Alternative solution for PR36343, missed call-clobbering due to TBAA pruning of points-to sets


On Wed, 28 May 2008, Richard Guenther wrote:

> On Wed, 28 May 2008, Daniel Berlin wrote:
> 
> > This is fine by me.
>
> It seems I have to track down some Ada failures with the patch, so
> don't hold your breath.

The problem was that we cannot disregard escapes to pure/const functions
as we do not track call-used variables separately.

So, this is what I committed after bootstrapping and testing on
x86_64-unknown-linux-gnu for all languages including Ada.

Thanks,
Richard.

2008-05-27  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/36343
	PR tree-optimization/36346
	PR tree-optimization/36347
	* tree-flow.h (clobber_what_p_points_to): Declare.
	* tree-ssa-structalias.c (set_uids_in_ptset): Whether the
	pointed-to variable is dereferenced is irrelevant to whether
	the pointer can access the pointed-to variable.
	(clobber_what_p_points_to): New function.
	* tree-ssa-alias.c (set_initial_properties): Use it.
	* tree-ssa.c (verify_flow_sensitive_alias_info): Adjust
	call clobber check for NMTs.

	* gcc.c-torture/execute/pr36343.c: New testcase.

Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h.orig	2008-05-29 10:58:13.000000000 +0200
--- gcc/tree-flow.h	2008-05-29 11:02:57.000000000 +0200
*************** tree gimple_fold_indirect_ref (tree);
*** 1167,1172 ****
--- 1167,1173 ----
  
  /* In tree-ssa-structalias.c */
  bool find_what_p_points_to (tree);
+ bool clobber_what_p_points_to (tree);
  
  /* In tree-ssa-live.c */
  extern void remove_unused_locals (void);
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig	2008-05-29 10:58:13.000000000 +0200
--- gcc/tree-ssa-alias.c	2008-05-29 11:14:50.000000000 +0200
*************** set_initial_properties (struct alias_inf
*** 545,552 ****
      {
        struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
        tree tag = symbol_mem_tag (SSA_NAME_VAR (ptr));
!       
!       if (pi->value_escapes_p)
  	{
  	  /* If PTR escapes then its associated memory tags and
  	     pointed-to variables are call-clobbered.  */
--- 545,558 ----
      {
        struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
        tree tag = symbol_mem_tag (SSA_NAME_VAR (ptr));
! 
!       /* A pointer that only escapes via a function return does not
!          add to the call clobber or call used solution.
! 	 To exclude ESCAPE_TO_PURE_CONST we would need to track
! 	 call used variables separately or compute those properly
! 	 in the operand scanner.  */
!       if (pi->value_escapes_p
! 	  && pi->escape_mask & ~ESCAPE_TO_RETURN)
  	{
  	  /* If PTR escapes then its associated memory tags and
  	     pointed-to variables are call-clobbered.  */
*************** set_initial_properties (struct alias_inf
*** 556,579 ****
  	  if (tag)
  	    mark_call_clobbered (tag, pi->escape_mask);
  
! 	  if (pi->pt_vars)
! 	    {
! 	      bitmap_iterator bi;
! 	      unsigned int j;	      
! 	      EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j, bi)
! 		{
! 		  tree alias = referenced_var (j);
! 
! 		  /* If you clobber one part of a structure, you
! 		     clobber the entire thing.  While this does not make
! 		     the world a particularly nice place, it is necessary
! 		     in order to allow C/C++ tricks that involve
! 		     pointer arithmetic to work.  */
! 		  if (!unmodifiable_var_p (alias))
! 		    mark_call_clobbered (alias, pi->escape_mask);
! 		}
! 	    }
! 	  else if (pi->pt_anything)
  	    {
  	      any_pt_anything = true;
  	      pt_anything_mask |= pi->escape_mask;
--- 562,574 ----
  	  if (tag)
  	    mark_call_clobbered (tag, pi->escape_mask);
  
! 	  /* Defer to points-to analysis if possible, otherwise
! 	     clobber all addressable variables.  Parameters cannot
! 	     point to local memory though.
! 	     ???  Properly tracking which pointers point to non-local
! 	     memory only would make a big difference here.  */
! 	  if (!clobber_what_p_points_to (ptr)
! 	      && !(pi->escape_mask & ESCAPE_IS_PARM))
  	    {
  	      any_pt_anything = true;
  	      pt_anything_mask |= pi->escape_mask;
Index: gcc/testsuite/gcc.c-torture/execute/pr36343.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/execute/pr36343.c	2008-05-29 11:02:57.000000000 +0200
***************
*** 0 ****
--- 1,32 ----
+ extern void abort (void);
+ 
+ void __attribute__((noinline))
+ bar (int **p)
+ {
+   float *q = (float *)p;
+   *q = 0.0;
+ }
+ 
+ float __attribute__((noinline))
+ foo (int b)
+ {
+   int *i = 0;
+   float f = 1.0;
+   int **p;
+   if (b)
+     p = &i;
+   else
+     p = (int **)&f;
+   bar (p);
+   if (b)
+     return **p;
+   return f;
+ }
+ 
+ int main()
+ {
+   if (foo(0) != 0.0)
+     abort ();
+   return 0;
+ }
+ 
Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c.orig	2008-05-29 10:58:13.000000000 +0200
--- gcc/tree-ssa-structalias.c	2008-05-29 11:02:57.000000000 +0200
*************** set_uids_in_ptset (tree ptr, bitmap into
*** 4664,4680 ****
  	  || TREE_CODE (vi->decl) == RESULT_DECL)
  	{
  	  /* Just add VI->DECL to the alias set.
! 	     Don't type prune artificial vars.  */
! 	  if (vi->is_artificial_var)
  	    bitmap_set_bit (into, DECL_UID (vi->decl));
  	  else
  	    {
  	      alias_set_type var_alias_set, ptr_alias_set;
  	      var_alias_set = get_alias_set (vi->decl);
  	      ptr_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
! 	      if (no_tbaa_pruning
! 		  || (!is_derefed && !vi->directly_dereferenced)
! 		  || alias_sets_conflict_p (ptr_alias_set, var_alias_set))
  	        bitmap_set_bit (into, DECL_UID (vi->decl));
  	    }
  	}
--- 4664,4682 ----
  	  || TREE_CODE (vi->decl) == RESULT_DECL)
  	{
  	  /* Just add VI->DECL to the alias set.
! 	     Don't type prune artificial vars or points-to sets
! 	     for pointers that have not been dereferenced or with
! 	     type-based pruning disabled.  */
! 	  if (vi->is_artificial_var
! 	      || !is_derefed
! 	      || no_tbaa_pruning)
  	    bitmap_set_bit (into, DECL_UID (vi->decl));
  	  else
  	    {
  	      alias_set_type var_alias_set, ptr_alias_set;
  	      var_alias_set = get_alias_set (vi->decl);
  	      ptr_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
! 	      if (alias_sets_conflict_p (ptr_alias_set, var_alias_set))
  	        bitmap_set_bit (into, DECL_UID (vi->decl));
  	    }
  	}
*************** find_what_p_points_to (tree p)
*** 4885,4891 ****
--- 4887,4957 ----
    return false;
  }
  
+ /* Mark everything that p points to as call clobbered.  Returns true
+    if everything is done and false if all addressable variables need to
+    be clobbered because p points to anything.  */
  
+ bool
+ clobber_what_p_points_to (tree p)
+ {
+   tree lookup_p = p;
+   varinfo_t vi;
+   struct ptr_info_def *pi;
+   unsigned int i;
+   bitmap_iterator bi;
+ 
+   if (!have_alias_info)
+     return false;
+ 
+   /* For parameters, get at the points-to set for the actual parm
+      decl.  */
+   if (TREE_CODE (p) == SSA_NAME
+       && TREE_CODE (SSA_NAME_VAR (p)) == PARM_DECL
+       && SSA_NAME_IS_DEFAULT_DEF (p))
+     lookup_p = SSA_NAME_VAR (p);
+ 
+   vi = lookup_vi_for_tree (lookup_p);
+   if (!vi)
+     return false;
+ 
+   /* We are asking for the points-to solution of pointers.  */
+   gcc_assert (!vi->is_artificial_var
+ 	      && vi->size == vi->fullsize);
+ 
+   pi = get_ptr_info (p);
+ 
+   /* This variable may have been collapsed, let's get the real
+      variable.  */
+   vi = get_varinfo (find (vi->id));
+ 
+   /* Mark variables in the solution call-clobbered.  */
+   EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
+     {
+       varinfo_t vi = get_varinfo (i);
+ 
+       if (vi->is_artificial_var)
+ 	{
+ 	  /* nothing_id and readonly_id do not cause any
+ 	     call clobber ops.  For anything_id and integer_id
+ 	     we need to clobber all addressable vars.  */
+ 	  if (vi->id == anything_id
+ 	      || vi->id == integer_id)
+ 	    return false;
+ 	}
+ 
+       /* Only artificial heap-vars are further interesting.  */
+       if (vi->is_artificial_var && !vi->is_heap_var)
+ 	continue;
+ 
+       if ((TREE_CODE (vi->decl) == VAR_DECL
+ 	   || TREE_CODE (vi->decl) == PARM_DECL
+ 	   || TREE_CODE (vi->decl) == RESULT_DECL)
+ 	  && !unmodifiable_var_p (vi->decl))
+ 	mark_call_clobbered (vi->decl, pi->escape_mask);
+     }
+ 
+   return true;
+ }
  
  /* Dump points-to information to OUTFILE.  */
  
Index: gcc/tree-ssa.c
===================================================================
*** gcc/tree-ssa.c.orig	2008-05-29 10:58:13.000000000 +0200
--- gcc/tree-ssa.c	2008-05-29 12:25:22.000000000 +0200
*************** verify_flow_sensitive_alias_info (void)
*** 571,577 ****
  	  goto err;
  	}
  
!       if (pi->value_escapes_p && pi->name_mem_tag)
  	{
  	  tree t = memory_partition (pi->name_mem_tag);
  	  if (t == NULL_TREE)
--- 571,579 ----
  	  goto err;
  	}
  
!       if (pi->value_escapes_p
! 	  && pi->escape_mask & ~ESCAPE_TO_RETURN
! 	  && pi->name_mem_tag)
  	{
  	  tree t = memory_partition (pi->name_mem_tag);
  	  if (t == NULL_TREE)


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