From f5a76aea0ddbb87fe8b4f64a283951d7e687b84c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 7 Jun 2004 10:53:03 -0700 Subject: [PATCH] gimple-low.c (struct lower_data): Add the_return_label and one_return_stmt. * gimple-low.c (struct lower_data): Add the_return_label and one_return_stmt. (lower_function_body): Initialize and use them. (lower_return_expr): New. (lower_stmt): Call it. * gimplify.c (gimplify_return_expr): Force the argument to be either null or a result_decl. * tree-gimple.c: Update gimple grammer to match. * tree-ssa-copyrename.c (copy_rename_partition_coalesce): Deny coalescing of result_decls. testsuite/ * gcc.dg/tree-ssa/20030728-1.c: Fixup return value to not match if temporaries. From-SVN: r82701 --- gcc/ChangeLog | 13 ++++++ gcc/gimple-low.c | 41 ++++++++++++++++-- gcc/gimplify.c | 49 ++-------------------- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/tree-ssa/20030728-1.c | 2 +- gcc/tree-gimple.c | 4 +- gcc/tree-ssa-copyrename.c | 7 ++++ 7 files changed, 68 insertions(+), 53 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a096a8ac2f7..e42f1ccb111 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2004-06-07 Richard Henderson + + * gimple-low.c (struct lower_data): Add the_return_label and + one_return_stmt. + (lower_function_body): Initialize and use them. + (lower_return_expr): New. + (lower_stmt): Call it. + * gimplify.c (gimplify_return_expr): Force the argument to be either + null or a result_decl. + * tree-gimple.c: Update gimple grammer to match. + * tree-ssa-copyrename.c (copy_rename_partition_coalesce): Deny + coalescing of result_decls. + 2004-06-07 Richard Henderson PR rtl-opt/15193 diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 56f02b7a1ee..458980f898f 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -46,11 +46,16 @@ struct lower_data { /* Block the current statement belongs to. */ tree block; + + /* Label that unifies the return statements. */ + tree the_return_label; + tree one_return_stmt; }; static void lower_stmt (tree_stmt_iterator *, struct lower_data *); static void lower_bind_expr (tree_stmt_iterator *, struct lower_data *); static void lower_cond_expr (tree_stmt_iterator *, struct lower_data *); +static void lower_return_expr (tree_stmt_iterator *, struct lower_data *); static bool expand_var_p (tree); /* Lowers the body of current_function_decl. */ @@ -71,11 +76,25 @@ lower_function_body (void) BLOCK_CHAIN (data.block) = NULL_TREE; TREE_ASM_WRITTEN (data.block) = 1; + data.the_return_label = NULL_TREE; + data.one_return_stmt = NULL_TREE; + *body_p = alloc_stmt_list (); i = tsi_start (*body_p); tsi_link_after (&i, bind, TSI_NEW_STMT); lower_bind_expr (&i, &data); + /* If we lowered any return statements, emit the representative at the + end of the function. */ + if (data.one_return_stmt) + { + tree t; + t = build (LABEL_EXPR, void_type_node, data.the_return_label); + i = tsi_last (*body_p); + tsi_link_after (&i, t, TSI_CONTINUE_LINKING); + tsi_link_after (&i, data.one_return_stmt, TSI_CONTINUE_LINKING); + } + if (data.block != DECL_INITIAL (current_function_decl)) abort (); BLOCK_SUBBLOCKS (data.block) @@ -136,6 +155,9 @@ lower_stmt (tree_stmt_iterator *tsi, struct lower_data *data) case COND_EXPR: lower_cond_expr (tsi, data); return; + case RETURN_EXPR: + lower_return_expr (tsi, data); + return; case TRY_FINALLY_EXPR: case TRY_CATCH_EXPR: @@ -151,7 +173,6 @@ lower_stmt (tree_stmt_iterator *tsi, struct lower_data *data) case NOP_EXPR: case ASM_EXPR: - case RETURN_EXPR: case MODIFY_EXPR: case CALL_EXPR: case GOTO_EXPR: @@ -367,6 +388,22 @@ lower_cond_expr (tree_stmt_iterator *tsi, struct lower_data *data) tsi_next (tsi); } + +static void +lower_return_expr (tree_stmt_iterator *tsi, struct lower_data *data) +{ + tree stmt, label = data->the_return_label; + + if (!label) + { + data->the_return_label = label = create_artificial_label (); + data->one_return_stmt = tsi_stmt (*tsi); + } + + stmt = build (GOTO_EXPR, void_type_node, label); + tsi_link_before (tsi, stmt, TSI_SAME_STMT); + tsi_delink (tsi); +} /* Record the variables in VARS. */ @@ -468,5 +505,3 @@ struct tree_opt_pass pass_remove_useless_vars = 0, /* todo_flags_start */ TODO_dump_func /* todo_flags_finish */ }; - - diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 20d194534ca..8ec6e0d19d6 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -899,54 +899,11 @@ gimplify_return_expr (tree stmt, tree *pre_p) /* We need to pass the full MODIFY_EXPR down so that special handling can replace it with something else. */ - gimplify_stmt (&ret_expr); + gimplify_stmt (&TREE_OPERAND (stmt, 0)); + append_to_statement_list (TREE_OPERAND (stmt, 0), pre_p); - if (result == NULL_TREE) - TREE_OPERAND (stmt, 0) = NULL_TREE; - else if (ret_expr == TREE_OPERAND (stmt, 0)) - /* It was already GIMPLE. */ - return GS_ALL_DONE; - else - { - /* If there's still a MODIFY_EXPR of the RESULT_DECL after - gimplification, find it so we can put it in the RETURN_EXPR. */ - tree ret = NULL_TREE; - - if (TREE_CODE (ret_expr) == STATEMENT_LIST) - { - tree_stmt_iterator si; - 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; - if (tsi_one_before_end_p (si)) - 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); - } - break; - } - } - } - - if (ret) - TREE_OPERAND (stmt, 0) = ret; - else - /* The return value must be set up some other way. Just tell - expand_return that we're returning the RESULT_DECL. */ - TREE_OPERAND (stmt, 0) = result; - } + TREE_OPERAND (stmt, 0) = result; - append_to_statement_list (ret_expr, pre_p); return GS_ALL_DONE; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index af1f8d8bee5..8063bac70f1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-06-07 Richard Henderson + + * gcc.dg/tree-ssa/20030728-1.c: Fixup return value to not match + if temporaries. + 2004-06-07 David Edelsohn * g++.dg/eh/elide1.C: Remove XFAIL. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030728-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030728-1.c index 4bc04bc4da4..04d5a51aca6 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20030728-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030728-1.c @@ -35,7 +35,7 @@ objects_must_conflict_p (t1, t2) if ((t1->common.code == ARRAY_TYPE) != (t2 && t2->common.code == ARRAY_TYPE)) - return 0; + return 11; return foo (t2 ? get_alias_set (t2) : 0); diff --git a/gcc/tree-gimple.c b/gcc/tree-gimple.c index e749ec80097..4643ac652f4 100644 --- a/gcc/tree-gimple.c +++ b/gcc/tree-gimple.c @@ -79,9 +79,7 @@ Boston, MA 02111-1307, USA. */ GOTO_EXPR op0 -> LABEL_DECL | '*' ID | RETURN_EXPR - op0 -> modify-stmt | NULL_TREE - (maybe -> RESULT_DECL | NULL_TREE? seems like some of expand_return - depends on getting a MODIFY_EXPR.) + op0 -> RESULT_DECL | NULL_TREE | THROW_EXPR? do we need/want such a thing for opts, perhaps to generate an ERT_THROW region? I think so. Hmm...this would only work at the GIMPLE level, where we know that diff --git a/gcc/tree-ssa-copyrename.c b/gcc/tree-ssa-copyrename.c index dd698835f06..369c02fbd97 100644 --- a/gcc/tree-ssa-copyrename.c +++ b/gcc/tree-ssa-copyrename.c @@ -187,6 +187,13 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) return; } + if ((TREE_CODE (root1) == RESULT_DECL) != (TREE_CODE (root2) == RESULT_DECL)) + { + if (debug) + fprintf (debug, " : One root a RESULT_DECL. No coalesce.\n"); + return; + } + gimp1 = is_gimple_tmp_var (root1); gimp2 = is_gimple_tmp_var (root2); -- 2.30.2