re PR c++/25979 (incorrect codegen for conditional [SVO issue])

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.

From-SVN: r110789
This commit is contained in:
Jason Merrill 2006-02-09 04:54:36 -05:00 committed by Jason Merrill
parent 845d2a4b7d
commit dae7ec874f
9 changed files with 107 additions and 48 deletions

View File

@ -1,3 +1,27 @@
2006-02-08 Jason Merrill <jason@redhat.com>
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 <law@redhat.com>
PR tree-optimization/21417

View File

@ -1,3 +1,10 @@
2006-02-08 Jason Merrill <jason@redhat.com>
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 <reichelt@igpm.rwth-aachen.de>
PR c++/26071

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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,