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]

[tree-ssa] PATCH to fix thinko in gimplify_return_expr


My earlier patch caused us to duplicate the assignment to the RESULT_DECL
in many cases.  Fixed thus.

I also considered using "tsi_last_p" instead of "tsi_one_before_end_p", but
decided that the latter was less potentially confusing.

Tested athlon-pc-linux-gnu, applied to tree-ssa.

2003-06-30  Jason Merrill  <jason@redhat.com>

	* gimplify.c (gimplify_modify_expr): Also force a call with a
	possible nonlocal goto into a temporary.
	(gimplify_return_expr): Don't duplicate the MODIFY_EXPR.
	* tree-iterator.h (tsi_one_before_end_p): New fn.

*** gimplify.c.~1~	2003-06-26 16:03:08.000000000 -0400
--- gimplify.c	2003-06-27 18:45:11.000000000 -0400
*************** gimplify_return_expr (tree stmt, tree *p
*** 957,985 ****
        if (result)
  	{
  	  tree ret = NULL_TREE;
- 	  tree last = NULL_TREE;
  
  	  for (si = tsi_start (&ret_expr); !tsi_end_p (si); tsi_next (&si))
  	    {
! 	      last = tsi_stmt (si);
! 	      if (TREE_CODE (last) == MODIFY_EXPR
! 		  && TREE_OPERAND (last, 0) == result)
! 		ret = last;
! 	      else if (ret)
! 		break;
  	    }
  
! 	  /* If there were posteffects after the MODIFY_EXPR, we need a
! 	     temporary.  We also copy the result of a CALL_EXPR into a
! 	     temporary; apparently this simplifies dealing with
! 	     TRY_FINALLY_EXPR somehow.  */
! 	  if (ret
! 	      && (ret != last
! 		  || TREE_CODE (TREE_OPERAND (ret, 1)) == CALL_EXPR))
  	    {
! 	      tree tmp = create_tmp_var (TREE_TYPE (result), "retval");
! 	      TREE_OPERAND (ret, 0) = tmp;
! 	      ret = build (MODIFY_EXPR, TREE_TYPE (result), result, tmp);
  	    }
  
  	  if (ret)
--- 957,988 ----
        if (result)
  	{
  	  tree ret = NULL_TREE;
  
  	  for (si = tsi_start (&ret_expr); !tsi_end_p (si); tsi_next (&si))
  	    {
! 	      tree sub = tsi_stmt (si);
! 	      if (TREE_CODE (sub) == MODIFY_EXPR
! 		  && TREE_OPERAND (sub, 0) == result)
! 		{
! 		  ret = sub;
! 		  break;
! 		}
  	    }
  
! 	  if (ret)
  	    {
! 	      if (tsi_one_before_end_p (si))
! 		/* If the MODIFY_EXPR was the last thing in the GIMPLE
! 		   form, pull it out.  */
! 		tsi_delink (&si);
! 	      else
! 		{
! 		  /* If there were posteffects after the MODIFY_EXPR, we
! 		     need a temporary.  */
! 		  tree tmp = create_tmp_var (TREE_TYPE (result), "retval");
! 		  TREE_OPERAND (ret, 0) = tmp;
! 		  ret = build (MODIFY_EXPR, TREE_TYPE (result), result, tmp);
! 		}
  	    }
  
  	  if (ret)
*************** gimplify_modify_expr (tree *expr_p, tree
*** 1923,1940 ****
        return;
      }
  
!   /* If the RHS of the MODIFY_EXPR may throw and the LHS is a user
!      variable, then we need to introduce a temporary.
       ie temp = RHS; LHS = temp.
  
       This way the optimizers can determine that the user variable is
       only modified if evaluation of the RHS does not throw.
  
       FIXME this should be handled by the is_gimple_rhs predicate.  */
!   if (flag_exceptions
!       && ! (DECL_P (*to_p) && DECL_ARTIFICIAL (*to_p))
        && ((TREE_CODE (*from_p) == CALL_EXPR
! 	   && ! (call_expr_flags (*from_p) & ECF_NOTHROW))
  	  || (flag_non_call_exceptions && could_trap_p (*from_p))))
      pred = is_gimple_val;
    else
--- 1931,1948 ----
        return;
      }
  
!   /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto and
!      the LHS is a user variable, then we need to introduce a temporary.
       ie temp = RHS; LHS = temp.
  
       This way the optimizers can determine that the user variable is
       only modified if evaluation of the RHS does not throw.
  
       FIXME this should be handled by the is_gimple_rhs predicate.  */
!   if (! is_gimple_tmp_var (*to_p)
        && ((TREE_CODE (*from_p) == CALL_EXPR
! 	   && ((flag_exceptions && ! (call_expr_flags (*from_p) & ECF_NOTHROW))
! 	       || FUNCTION_RECEIVES_NONLOCAL_GOTO (current_function_decl)))
  	  || (flag_non_call_exceptions && could_trap_p (*from_p))))
      pred = is_gimple_val;
    else
*** tree-iterator.h.~1~	2003-06-22 10:27:33.000000000 -0400
--- tree-iterator.h	2003-06-27 17:04:10.000000000 -0400
*************** typedef struct {
*** 47,52 ****
--- 47,53 ----
  static inline tree_stmt_iterator tsi_start 	PARAMS ((tree *));
  static inline tree_stmt_iterator tsi_last 	PARAMS ((tree *));
  static inline bool tsi_end_p			PARAMS ((tree_stmt_iterator));
+ static inline bool tsi_one_before_end_p		PARAMS ((tree_stmt_iterator));
  static inline void tsi_next			PARAMS ((tree_stmt_iterator *));
  static inline void tsi_prev			PARAMS ((tree_stmt_iterator *));
  static inline tree tsi_stmt			PARAMS ((tree_stmt_iterator));
*************** tsi_prev (i)
*** 103,108 ****
--- 104,117 ----
    abort();
  }
  
+ static inline bool
+ tsi_one_before_end_p (i)
+      tree_stmt_iterator i;
+ {
+   tsi_next (&i);
+   return tsi_end_p (i);
+ }
+ 
  static inline tree *
  tsi_stmt_ptr (i)
       tree_stmt_iterator i;

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