From cf6b103ecba3ec845e82cac95ce2693954438eec Mon Sep 17 00:00:00 2001 From: jason Date: Thu, 9 Feb 2006 09:54:36 +0000 Subject: PR c++/25979 * tree.def: Elaborate on difference from MODIFY_EXPR. * doc/c-tree.texi (INIT_EXPR): Likewise. * gimplify.c (internal_get_tmp_var): Use INIT_EXPR. (gimplify_decl_expr, gimplify_init_ctor_eval): Likewise. (gimplify_target_expr): Likewise. (gimplify_cond_expr): Remove target handling. (gimplify_modify_expr): Don't clobber INIT_EXPR code here. (gimplify_expr): Clobber it here. (gimplify_modify_expr_rhs): Push assignment into COND_EXPR here. Do return slot optimization if we have an INIT_EXPR. PR tree-opt/24365 * tree-inline.c (declare_return_variable): Also clear DECL_COMPLEX_GIMPLE_REG_P as needed in the modify_dest case. PR c++/16405 * gimplify.c (gimplify_modify_expr_rhs): Re-enable *& handling. PR middle-end/22439 * gimplify.c (gimplify_one_sizepos): Fix typo. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110789 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 24 +++++++++ gcc/cp/ChangeLog | 7 +++ gcc/cp/cp-gimplify.c | 4 +- gcc/cp/typeck2.c | 2 +- gcc/doc/c-tree.texi | 5 +- gcc/gimplify.c | 105 +++++++++++++++++++++++---------------- gcc/testsuite/g++.dg/opt/temp1.C | 2 +- gcc/tree-inline.c | 3 ++ gcc/tree.def | 3 +- 9 files changed, 107 insertions(+), 48 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9aef9b8a009..83b801fd6ba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2006-02-08 Jason Merrill + + PR c++/25979 + * tree.def: Elaborate on difference from MODIFY_EXPR. + * doc/c-tree.texi (INIT_EXPR): Likewise. + * gimplify.c (internal_get_tmp_var): Use INIT_EXPR. + (gimplify_decl_expr, gimplify_init_ctor_eval): Likewise. + (gimplify_target_expr): Likewise. + (gimplify_cond_expr): Remove target handling. + (gimplify_modify_expr): Don't clobber INIT_EXPR code here. + (gimplify_expr): Clobber it here. + (gimplify_modify_expr_rhs): Push assignment into COND_EXPR here. + Do return slot optimization if we have an INIT_EXPR. + + PR tree-opt/24365 + * tree-inline.c (declare_return_variable): Also clear + DECL_COMPLEX_GIMPLE_REG_P as needed in the modify_dest case. + + PR c++/16405 + * gimplify.c (gimplify_modify_expr_rhs): Re-enable *& handling. + + PR middle-end/22439 + * gimplify.c (gimplify_one_sizepos): Fix typo. + 2006-02-08 Jeff Law PR tree-optimization/21417 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 947e080ae90..74071c91e90 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2006-02-08 Jason Merrill + + PR c++/25979 + * cp-gimplify.c (cp_gimplify_expr): Don't call + cp_gimplify_init_expr for MODIFY_EXPRs. + * typeck2.c (split_nonconstant_init_1): Use INIT_EXPR. + 2006-02-08 Volker Reichelt PR c++/26071 diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 38838e734e6..a9fb7bf28e6 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -477,8 +477,10 @@ cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) ret = GS_OK; break; + /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the + LHS of an assignment might also be involved in the RHS, as in bug + 25979. */ case INIT_EXPR: - case MODIFY_EXPR: cp_gimplify_init_expr (expr_p, pre_p, post_p); ret = GS_OK; break; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index fe5b3dff78e..49c58f8e51e 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -502,7 +502,7 @@ split_nonconstant_init_1 (tree dest, tree init) sub = build3 (COMPONENT_REF, inner_type, dest, field_index, NULL_TREE); - code = build2 (MODIFY_EXPR, inner_type, sub, value); + code = build2 (INIT_EXPR, inner_type, sub, value); code = build_stmt (EXPR_STMT, code); add_stmt (code); continue; diff --git a/gcc/doc/c-tree.texi b/gcc/doc/c-tree.texi index 5045b72eb60..62e7738054c 100644 --- a/gcc/doc/c-tree.texi +++ b/gcc/doc/c-tree.texi @@ -2350,7 +2350,10 @@ just like that for @samp{i = i + 3}. @item INIT_EXPR These nodes are just like @code{MODIFY_EXPR}, but are used only when a -variable is initialized, rather than assigned to subsequently. +variable is initialized, rather than assigned to subsequently. This +means that we can assume that the target of the initialization is not +used in computing its own value; any reference to the lhs in computing +the rhs is undefined. @item COMPONENT_REF These nodes represent non-static data member accesses. The first diff --git a/gcc/gimplify.c b/gcc/gimplify.c index da800bba195..710569888ec 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -606,7 +606,7 @@ internal_get_tmp_var (tree val, tree *pre_p, tree *post_p, bool is_formal) if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE) DECL_COMPLEX_GIMPLE_REG_P (t) = 1; - mod = build2 (MODIFY_EXPR, TREE_TYPE (t), t, val); + mod = build2 (INIT_EXPR, TREE_TYPE (t), t, val); if (EXPR_HAS_LOCATION (val)) SET_EXPR_LOCUS (mod, EXPR_LOCUS (val)); @@ -1204,7 +1204,7 @@ gimplify_decl_expr (tree *stmt_p) if (!TREE_STATIC (decl)) { DECL_INITIAL (decl) = NULL_TREE; - init = build2 (MODIFY_EXPR, void_type_node, decl, init); + init = build2 (INIT_EXPR, void_type_node, decl, init); gimplify_and_add (init, stmt_p); } else @@ -2341,14 +2341,10 @@ gimple_boolify (tree expr) TARGET is the tree for T1 above. PRE_P points to the list where side effects that must happen before - *EXPR_P should be stored. - - POST_P points to the list where side effects that must happen after - *EXPR_P should be stored. */ + *EXPR_P should be stored. */ static enum gimplify_status -gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target, - fallback_t fallback) +gimplify_cond_expr (tree *expr_p, tree *pre_p, fallback_t fallback) { tree expr = *expr_p; tree tmp, tmp2, type; @@ -2362,16 +2358,7 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target, { tree result; - if (target) - { - ret = gimplify_expr (&target, pre_p, post_p, - is_gimple_min_lval, fb_lvalue); - if (ret != GS_ERROR) - ret = GS_OK; - result = tmp = target; - tmp2 = unshare_expr (target); - } - else if ((fallback & fb_lvalue) == 0) + if ((fallback & fb_lvalue) == 0) { result = tmp2 = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp"); ret = GS_ALL_DONE; @@ -2836,7 +2823,7 @@ gimplify_init_ctor_eval (tree object, VEC(constructor_elt,gc) *elts, pre_p, cleared); else { - init = build2 (MODIFY_EXPR, TREE_TYPE (cref), cref, value); + init = build2 (INIT_EXPR, TREE_TYPE (cref), cref, value); gimplify_and_add (init, pre_p); } } @@ -3190,7 +3177,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, while (ret != GS_UNHANDLED) switch (TREE_CODE (*from_p)) { -#if 0 case INDIRECT_REF: { /* If we have code like @@ -3212,7 +3198,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, ret = GS_UNHANDLED; break; } -#endif case TARGET_EXPR: { @@ -3257,9 +3242,36 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, copy in other cases as well. */ if (!is_gimple_reg_type (TREE_TYPE (*from_p))) { - *expr_p = *from_p; - return gimplify_cond_expr (expr_p, pre_p, post_p, *to_p, - fb_rvalue); + /* This code should mirror the code in gimplify_cond_expr. */ + enum tree_code code = TREE_CODE (*expr_p); + tree cond = *from_p; + tree result = *to_p; + + ret = gimplify_expr (&result, pre_p, post_p, + is_gimple_min_lval, fb_lvalue); + if (ret != GS_ERROR) + ret = GS_OK; + + if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node) + TREE_OPERAND (cond, 1) + = build2 (code, void_type_node, result, + TREE_OPERAND (cond, 1)); + if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node) + TREE_OPERAND (cond, 2) + = build2 (code, void_type_node, unshare_expr (result), + TREE_OPERAND (cond, 2)); + + TREE_TYPE (cond) = void_type_node; + recalculate_side_effects (cond); + + if (want_value) + { + gimplify_and_add (cond, pre_p); + *expr_p = unshare_expr (result); + } + else + *expr_p = cond; + return ret; } else ret = GS_UNHANDLED; @@ -3273,11 +3285,26 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, { bool use_target; - if (TREE_CODE (*to_p) == RESULT_DECL - && DECL_NAME (*to_p) == NULL_TREE - && needs_to_live_in_memory (*to_p)) + if (!(rhs_predicate_for (*to_p))(*from_p)) + /* If we need a temporary, *to_p isn't accurate. */ + use_target = false; + else if (TREE_CODE (*to_p) == RESULT_DECL + && DECL_NAME (*to_p) == NULL_TREE + && needs_to_live_in_memory (*to_p)) /* It's OK to use the return slot directly unless it's an NRV. */ use_target = true; + else if (is_gimple_reg_type (TREE_TYPE (*to_p))) + /* Don't force regs into memory. */ + use_target = false; + else if (TREE_CODE (*to_p) == VAR_DECL + && DECL_GIMPLE_FORMAL_TEMP_P (*to_p)) + /* Don't use the original target if it's a formal temp; we + don't want to take their addresses. */ + use_target = false; + else if (TREE_CODE (*expr_p) == INIT_EXPR) + /* It's OK to use the target directly if it's being + initialized. */ + use_target = true; else if (!is_gimple_non_addressable (*to_p)) /* Don't use the original target if it's already addressable; if its address escapes, and the called function uses the @@ -3286,14 +3313,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, When optimizing, the return_slot pass marks more functions as safe after we have escape info. */ use_target = false; - else if (TREE_CODE (*to_p) != PARM_DECL - && DECL_GIMPLE_FORMAL_TEMP_P (*to_p)) - /* Don't use the original target if it's a formal temp; we - don't want to take their addresses. */ - use_target = false; - else if (is_gimple_reg_type (TREE_TYPE (*to_p))) - /* Also don't force regs into memory. */ - use_target = false; else use_target = true; @@ -3379,10 +3398,6 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value) gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR || TREE_CODE (*expr_p) == INIT_EXPR); - /* The distinction between MODIFY_EXPR and INIT_EXPR is no longer useful. */ - if (TREE_CODE (*expr_p) == INIT_EXPR) - TREE_SET_CODE (*expr_p, MODIFY_EXPR); - /* For zero sized types only gimplify the left hand side and right hand side as statements and throw away the assignment. */ if (zero_sized_type (TREE_TYPE (*from_p))) @@ -4072,7 +4087,7 @@ gimplify_target_expr (tree *expr_p, tree *pre_p, tree *post_p) gimplify_bind_expr (&init, temp, pre_p); if (init != temp) { - init = build2 (MODIFY_EXPR, void_type_node, temp, init); + init = build2 (INIT_EXPR, void_type_node, temp, init); ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, fb_none); } @@ -5216,8 +5231,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, break; case COND_EXPR: - ret = gimplify_cond_expr (expr_p, pre_p, post_p, NULL_TREE, - fallback); + ret = gimplify_cond_expr (expr_p, pre_p, fallback); /* C99 code may assign to an array in a structure value of a conditional expression, and this has undefined behavior only on execution, so create a temporary if an lvalue is @@ -5253,6 +5267,11 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, case INIT_EXPR: ret = gimplify_modify_expr (expr_p, pre_p, post_p, fallback != fb_none); + + /* The distinction between MODIFY_EXPR and INIT_EXPR is no longer + useful. */ + if (*expr_p && TREE_CODE (*expr_p) == INIT_EXPR) + TREE_SET_CODE (*expr_p, MODIFY_EXPR); break; case TRUTH_ANDIF_EXPR: @@ -5889,7 +5908,7 @@ gimplify_one_sizepos (tree *expr_p, tree *stmt_p) *expr_p = create_tmp_var (type, NULL); tmp = build1 (NOP_EXPR, type, expr); - tmp = build2 (MODIFY_EXPR, type, *expr_p, expr); + tmp = build2 (MODIFY_EXPR, type, *expr_p, tmp); if (EXPR_HAS_LOCATION (expr)) SET_EXPR_LOCUS (tmp, EXPR_LOCUS (expr)); else diff --git a/gcc/testsuite/g++.dg/opt/temp1.C b/gcc/testsuite/g++.dg/opt/temp1.C index 6b0e2f3906d..b822dc464fe 100644 --- a/gcc/testsuite/g++.dg/opt/temp1.C +++ b/gcc/testsuite/g++.dg/opt/temp1.C @@ -1,6 +1,6 @@ // PR c++/16405 // { dg-options "-O2" } -// { dg-do run { xfail *-*-* } } +// { dg-do run } // There should be exactly one temporary generated for the code in "f" // below when optimizing -- for the result of "b + c". We have no diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 07085b104b1..f9ce09bbe35 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1222,6 +1222,9 @@ declare_return_variable (copy_body_data *id, tree return_slot_addr, use_it = false; else if (is_global_var (base_m)) use_it = false; + else if (TREE_CODE (TREE_TYPE (base_m)) == COMPLEX_TYPE + && !DECL_COMPLEX_GIMPLE_REG_P (result)) + DECL_COMPLEX_GIMPLE_REG_P (base_m) = 0; else if (!TREE_ADDRESSABLE (base_m)) use_it = true; } diff --git a/gcc/tree.def b/gcc/tree.def index bc227e20346..14c15a76d5c 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -465,7 +465,8 @@ DEFTREECODE (COMPOUND_EXPR, "compound_expr", tcc_expression, 2) DEFTREECODE (MODIFY_EXPR, "modify_expr", tcc_expression, 2) /* Initialization expression. Operand 0 is the variable to initialize; - Operand 1 is the initializer. */ + Operand 1 is the initializer. This differs from MODIFY_EXPR in that any + reference to the referent of operand 0 within operand 1 is undefined. */ DEFTREECODE (INIT_EXPR, "init_expr", tcc_expression, 2) /* For TARGET_EXPR, operand 0 is the target of an initialization, -- cgit v1.2.1