This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] PATCH to fix thinko in gimplify_return_expr
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 30 Jun 2003 09:11:21 -0400
- Subject: [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;