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:
parent
845d2a4b7d
commit
dae7ec874f
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
105
gcc/gimplify.c
105
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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user