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][4.2] Fix PR32328, wrong code with calls and aliasing


This "backported" patch from Danny fixes PR32328 on the 4.2 branch.  It
basically only adds additional constraints to the PTA solver, so it should
be safe.

Bootstrap and regtest on x86_64-unknown-linux-gnu is still in progress.

Ok for the 4.2 branch if it passes?

Thanks,
Richard.


2007-07-16  Richard Guenther  <rguenther@suse.de>
	Daniel Berlin  <dberlin@dberlin.org>

	PR tree-optimization/32328
	* tree-ssa-structalias.c (handle_rhs_call): New function.
	(find_func_aliases): Generate constraints for each pointer
	passed by address in a function call.

	* gcc.dg/pr32328.c: New testcase.

Index: tree-ssa-structalias.c
===================================================================
*** tree-ssa-structalias.c	(revision 126358)
--- tree-ssa-structalias.c	(working copy)
*************** handle_ptr_arith (VEC (ce_s, heap) *lhsc
*** 3323,3328 ****
--- 3323,3362 ----
    return true;
  }
  
+ /* For non-IPA mode, generate constraints necessary for a call on the
+    RHS.  */
+ 
+ static void
+ handle_rhs_call  (tree rhs)
+ {
+   tree arg, arglist;
+   struct constraint_expr rhsc;
+   
+   rhsc.var = anything_id;
+   rhsc.offset = 0;
+   rhsc.type = ADDRESSOF;
+ 
+   arglist = TREE_OPERAND (rhs, 1);
+   for (;arglist; arglist = TREE_CHAIN (arglist))
+     {
+       arg = TREE_VALUE (arglist);
+       VEC(ce_s, heap) *lhsc = NULL;
+ 
+       /* Find those pointers being passed, and make sure they end up
+ 	 pointing to anything.  */
+       if (POINTER_TYPE_P (TREE_TYPE (arg)))
+ 	{
+ 	  unsigned int j;
+ 	  struct constraint_expr *lhsp;
+ 
+ 	  get_constraint_for (arg, &lhsc);
+ 	  do_deref (&lhsc);
+ 	  for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
+ 	    process_constraint (new_constraint (*lhsp, rhsc));
+ 	  VEC_free (ce_s, heap, lhsc);
+ 	}
+     }
+ }
  
  /* Walk statement T setting up aliasing constraints according to the
     references found in T.  This function is the main part of the
*************** find_func_aliases (tree origt)
*** 3380,3481 ****
    /* In IPA mode, we need to generate constraints to pass call
       arguments through their calls.   There are two case, either a
       modify_expr when we are returning a value, or just a plain
!      call_expr when we are not.   */
!   else if (in_ipa_mode
! 	   && ((TREE_CODE (t) == MODIFY_EXPR 
! 		&& TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR
! 	       && !(call_expr_flags (TREE_OPERAND (t, 1)) 
! 		    & (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))
! 	       || (TREE_CODE (t) == CALL_EXPR 
! 		   && !(call_expr_flags (t) 
! 			& (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))))
!     {
!       tree lhsop;
!       tree rhsop;
!       tree arglist;
!       varinfo_t fi;
!       int i = 1;
!       tree decl;
!       if (TREE_CODE (t) == MODIFY_EXPR)
! 	{
! 	  lhsop = TREE_OPERAND (t, 0);
! 	  rhsop = TREE_OPERAND (t, 1);
! 	}
!       else
! 	{
! 	  lhsop = NULL;
! 	  rhsop = t;
! 	}
!       decl = get_callee_fndecl (rhsop);
  
!       /* If we can directly resolve the function being called, do so.
! 	 Otherwise, it must be some sort of indirect expression that
! 	 we should still be able to handle.  */
!       if (decl)
  	{
! 	  fi = get_vi_for_tree (decl);
  	}
        else
  	{
! 	  decl = TREE_OPERAND (rhsop, 0);
! 	  fi = get_vi_for_tree (decl);
! 	}
! 
!       /* Assign all the passed arguments to the appropriate incoming
! 	 parameters of the function.  */
!       arglist = TREE_OPERAND (rhsop, 1);
! 	
!       for (;arglist; arglist = TREE_CHAIN (arglist))
! 	{
! 	  tree arg = TREE_VALUE (arglist);
! 	  struct constraint_expr lhs ;
! 	  struct constraint_expr *rhsp;
! 
! 	  get_constraint_for (arg, &rhsc);
! 	  if (TREE_CODE (decl) != FUNCTION_DECL)
! 	    {
! 	      lhs.type = DEREF;
! 	      lhs.var = fi->id;
! 	      lhs.offset = i;
  	    }
  	  else
  	    {
! 	      lhs.type = SCALAR;
! 	      lhs.var = first_vi_for_offset (fi, i)->id;
! 	      lhs.offset = 0;
  	    }
! 	  while (VEC_length (ce_s, rhsc) != 0)
  	    {
! 	      rhsp = VEC_last (ce_s, rhsc);
! 	      process_constraint (new_constraint (lhs, *rhsp));
! 	      VEC_pop (ce_s, rhsc);
  	    }
- 	  i++;
- 	}
- 
-       /* If we are returning a value, assign it to the result.  */
-       if (lhsop)
- 	{
- 	  struct constraint_expr rhs;
- 	  struct constraint_expr *lhsp;
- 	  unsigned int j = 0;
  
! 	  get_constraint_for (lhsop, &lhsc);
! 	  if (TREE_CODE (decl) != FUNCTION_DECL)
  	    {
! 	      rhs.type = DEREF;
! 	      rhs.var = fi->id;
! 	      rhs.offset = i;
  	    }
! 	  else
  	    {
! 	      rhs.type = SCALAR;
! 	      rhs.var = first_vi_for_offset (fi, i)->id;
! 	      rhs.offset = 0;
  	    }
! 	  for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
! 	    process_constraint (new_constraint (*lhsp, rhs));
! 	}
      }
    /* Otherwise, just a regular assignment statement.  */
    else if (TREE_CODE (t) == MODIFY_EXPR)
--- 3414,3527 ----
    /* In IPA mode, we need to generate constraints to pass call
       arguments through their calls.   There are two case, either a
       modify_expr when we are returning a value, or just a plain
!      CALL_EXPR when we are not.
  
!      In non-ipa mode, we need to generate constraints for each
!      pointer passed by address.  */
!   else if (((TREE_CODE (t) == MODIFY_EXPR
! 	     && TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR
! 	     && !(call_expr_flags (TREE_OPERAND (t, 1))
! 		  & (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))
! 	    || (TREE_CODE (t) == CALL_EXPR 
! 		&& !(call_expr_flags (t) 
! 		     & (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))))
!     {
!       if (!in_ipa_mode)
  	{
! 	  if (TREE_CODE (t) == MODIFY_EXPR)
! 	    handle_rhs_call (TREE_OPERAND (t, 1));
! 	  else
! 	    handle_rhs_call (t);
  	}
        else
  	{
! 	  tree lhsop;
! 	  tree rhsop;
! 	  tree arglist;
! 	  varinfo_t fi;
! 	  int i = 1;
! 	  tree decl;
! 	  if (TREE_CODE (t) == MODIFY_EXPR)
! 	    {
! 	      lhsop = TREE_OPERAND (t, 0);
! 	      rhsop = TREE_OPERAND (t, 1);
  	    }
  	  else
  	    {
! 	      lhsop = NULL;
! 	      rhsop = t;
  	    }
! 	  decl = get_callee_fndecl (rhsop);
! 
! 	  /* If we can directly resolve the function being called, do so.
! 	     Otherwise, it must be some sort of indirect expression that
! 	     we should still be able to handle.  */
! 	  if (decl)
  	    {
! 	      fi = get_vi_for_tree (decl);
! 	    }
! 	  else
! 	    {
! 	      decl = TREE_OPERAND (rhsop, 0);
! 	      fi = get_vi_for_tree (decl);
  	    }
  
! 	  /* Assign all the passed arguments to the appropriate incoming
! 	     parameters of the function.  */
! 	  arglist = TREE_OPERAND (rhsop, 1);
! 	
! 	  for (;arglist; arglist = TREE_CHAIN (arglist))
  	    {
! 	      tree arg = TREE_VALUE (arglist);
! 	      struct constraint_expr lhs ;
! 	      struct constraint_expr *rhsp;
! 
! 	      get_constraint_for (arg, &rhsc);
! 	      if (TREE_CODE (decl) != FUNCTION_DECL)
! 		{
! 		  lhs.type = DEREF;
! 		  lhs.var = fi->id;
! 		  lhs.offset = i;
! 		}
! 	      else
! 		{
! 		  lhs.type = SCALAR;
! 		  lhs.var = first_vi_for_offset (fi, i)->id;
! 		  lhs.offset = 0;
! 		}
! 	      while (VEC_length (ce_s, rhsc) != 0)
! 		{
! 		  rhsp = VEC_last (ce_s, rhsc);
! 		  process_constraint (new_constraint (lhs, *rhsp));
! 		  VEC_pop (ce_s, rhsc);
! 		}
! 	      i++;
  	    }
! 
! 	  /* If we are returning a value, assign it to the result.  */
! 	  if (lhsop)
  	    {
! 	      struct constraint_expr rhs;
! 	      struct constraint_expr *lhsp;
! 	      unsigned int j = 0;
! 
! 	      get_constraint_for (lhsop, &lhsc);
! 	      if (TREE_CODE (decl) != FUNCTION_DECL)
! 	        {
! 		  rhs.type = DEREF;
! 		  rhs.var = fi->id;
! 		  rhs.offset = i;
! 		}
! 	      else
! 		{
! 		  rhs.type = SCALAR;
! 		  rhs.var = first_vi_for_offset (fi, i)->id;
! 		  rhs.offset = 0;
! 		}
! 	      for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
! 		process_constraint (new_constraint (*lhsp, rhs));
  	    }
!         }
      }
    /* Otherwise, just a regular assignment statement.  */
    else if (TREE_CODE (t) == MODIFY_EXPR)
Index: testsuite/gcc.dg/pr32328.c
===================================================================
*** testsuite/gcc.dg/pr32328.c	(revision 0)
--- testsuite/gcc.dg/pr32328.c	(revision 0)
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-optimized" } */
+ 
+ struct barstruct { char const* some_string; };
+ 
+ void changethepointer(struct barstruct**);
+ 
+ void baz()
+ {
+         struct barstruct bar1;
+         struct barstruct* barptr = &bar1;
+         changethepointer(&barptr);
+         barptr->some_string = "Everything OK";
+ }
+ 
+ /* { dg-final { scan-tree-dump "Everything OK" "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]