re PR middle-end/23401 (Gimplifier produces too many temporaries)
2009-03-31 Richard Guenther <rguenther@suse.de> PR middle-end/23401 PR middle-end/27810 * tree.h (DECL_GIMPLE_FORMAL_TEMP_P): Remove. (struct tree_decl_with_vis): Remove gimple_formal_temp member. * tree-eh.c (lower_eh_constructs_2): Move LHS assignment to a separate statement. * gimplify.c (pop_gimplify_context): Remove formal temp handling. (lookup_tmp_var): Likewise. (is_gimple_formal_tmp_or_call_rhs): Remove. (is_gimple_reg_or_call_rhs): Rename to ... (is_gimple_reg_rhs_or_call): ... this. (is_gimple_mem_or_call_rhs): Rename to ... (is_gimple_mem_rhs_or_call): ... this. (internal_get_tmp_var): Use is_gimple_reg_rhs_or_call. Set DECL_GIMPLE_REG_P only if is_formal is true. (gimplify_compound_lval): Use is_gimple_reg. Remove workaround for non-proper post-modify expression gimplification. (gimplify_self_mod_expr): For post-modify expressions gimplify the lvalue to a minimal lvalue. (rhs_predicate_for): Remove formal temp case. (gimplify_modify_expr_rhs): Likewise. (gimplify_addr_expr): Use is_gimple_reg. (gimplify_expr): Remove formal temp cases. (gimple_regimplify_operands): Likewise. * tree-ssa-pre.c (get_or_alloc_expr_for): Treat EXC_PTR_EXPR and FILTER_EXPR like constants. * gimple.c (walk_gimple_op): Fix val_only initialization, use is_gimple_reg. (is_gimple_formal_tmp_rhs): Remove. (is_gimple_reg_rhs): Remove special casing. (is_gimple_mem_rhs): Fix. (is_gimple_reg): Move DECL_GIMPLE_REG_P handling earlier. (is_gimple_formal_tmp_var): Remove. (is_gimple_formal_tmp_reg): Likewise. (is_gimple_min_lval): Allow invariant component ref parts. * gimple.h (is_gimple_formal_tmp_rhs, is_gimple_formal_tmp_var, is_gimple_formal_tmp_reg): Remove declarations. * tree-cfg.c (verify_expr): Verify that variables with address taken do not have DECL_GIMPLE_REG_P set. * tree-mudflap.c (mf_build_check_statement_for): Use force_gimple_operand instead of gimplify_expr. java/ * java-gimplify.c (java_gimplify_expr): Do not manually gimplify the first operand of binary and comaprison expressions. * gcc.dg/tree-ssa/pr23401.c: New testcase. * gcc.dg/tree-ssa/pr27810.c: Likewise. From-SVN: r145338
This commit is contained in:
parent
8de9b877e7
commit
ba4d8f9d37
@ -1,3 +1,47 @@
|
||||
2009-03-31 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/23401
|
||||
PR middle-end/27810
|
||||
* tree.h (DECL_GIMPLE_FORMAL_TEMP_P): Remove.
|
||||
(struct tree_decl_with_vis): Remove gimple_formal_temp member.
|
||||
* tree-eh.c (lower_eh_constructs_2): Move LHS assignment to
|
||||
a separate statement.
|
||||
* gimplify.c (pop_gimplify_context): Remove formal temp handling.
|
||||
(lookup_tmp_var): Likewise.
|
||||
(is_gimple_formal_tmp_or_call_rhs): Remove.
|
||||
(is_gimple_reg_or_call_rhs): Rename to ...
|
||||
(is_gimple_reg_rhs_or_call): ... this.
|
||||
(is_gimple_mem_or_call_rhs): Rename to ...
|
||||
(is_gimple_mem_rhs_or_call): ... this.
|
||||
(internal_get_tmp_var): Use is_gimple_reg_rhs_or_call. Set
|
||||
DECL_GIMPLE_REG_P only if is_formal is true.
|
||||
(gimplify_compound_lval): Use is_gimple_reg. Remove workaround
|
||||
for non-proper post-modify expression gimplification.
|
||||
(gimplify_self_mod_expr): For post-modify expressions gimplify
|
||||
the lvalue to a minimal lvalue.
|
||||
(rhs_predicate_for): Remove formal temp case.
|
||||
(gimplify_modify_expr_rhs): Likewise.
|
||||
(gimplify_addr_expr): Use is_gimple_reg.
|
||||
(gimplify_expr): Remove formal temp cases.
|
||||
(gimple_regimplify_operands): Likewise.
|
||||
* tree-ssa-pre.c (get_or_alloc_expr_for): Treat EXC_PTR_EXPR
|
||||
and FILTER_EXPR like constants.
|
||||
* gimple.c (walk_gimple_op): Fix val_only initialization, use
|
||||
is_gimple_reg.
|
||||
(is_gimple_formal_tmp_rhs): Remove.
|
||||
(is_gimple_reg_rhs): Remove special casing.
|
||||
(is_gimple_mem_rhs): Fix.
|
||||
(is_gimple_reg): Move DECL_GIMPLE_REG_P handling earlier.
|
||||
(is_gimple_formal_tmp_var): Remove.
|
||||
(is_gimple_formal_tmp_reg): Likewise.
|
||||
(is_gimple_min_lval): Allow invariant component ref parts.
|
||||
* gimple.h (is_gimple_formal_tmp_rhs, is_gimple_formal_tmp_var,
|
||||
is_gimple_formal_tmp_reg): Remove declarations.
|
||||
* tree-cfg.c (verify_expr): Verify that variables with address
|
||||
taken do not have DECL_GIMPLE_REG_P set.
|
||||
* tree-mudflap.c (mf_build_check_statement_for): Use
|
||||
force_gimple_operand instead of gimplify_expr.
|
||||
|
||||
2009-03-31 Ayal Zaks <zaks@il.ibm.com>
|
||||
|
||||
* modulo-sched.c (sms_schedule_by_order): Pass the actual
|
||||
|
74
gcc/gimple.c
74
gcc/gimple.c
@ -1380,7 +1380,8 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
|
||||
/* Walk the RHS operands. A formal temporary LHS may use a
|
||||
COMPONENT_REF RHS. */
|
||||
if (wi)
|
||||
wi->val_only = !is_gimple_formal_tmp_var (gimple_assign_lhs (stmt));
|
||||
wi->val_only = !is_gimple_reg (gimple_assign_lhs (stmt))
|
||||
|| !gimple_assign_single_p (stmt);
|
||||
|
||||
for (i = 1; i < gimple_num_ops (stmt); i++)
|
||||
{
|
||||
@ -2559,37 +2560,13 @@ is_gimple_operand (const_tree op)
|
||||
return op && get_gimple_rhs_class (TREE_CODE (op)) == GIMPLE_SINGLE_RHS;
|
||||
}
|
||||
|
||||
|
||||
/* Return true if T is a GIMPLE RHS for an assignment to a temporary. */
|
||||
|
||||
bool
|
||||
is_gimple_formal_tmp_rhs (tree t)
|
||||
{
|
||||
if (is_gimple_lvalue (t) || is_gimple_val (t))
|
||||
return true;
|
||||
|
||||
return get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS;
|
||||
}
|
||||
|
||||
/* Returns true iff T is a valid RHS for an assignment to a renamed
|
||||
user -- or front-end generated artificial -- variable. */
|
||||
|
||||
bool
|
||||
is_gimple_reg_rhs (tree t)
|
||||
{
|
||||
/* 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 formal
|
||||
temporary. This way the optimizers can determine that the user
|
||||
variable is only modified if evaluation of the RHS does not throw.
|
||||
|
||||
Don't force a temp of a non-renamable type; the copy could be
|
||||
arbitrarily expensive. Instead we will generate a VDEF for
|
||||
the assignment. */
|
||||
|
||||
if (is_gimple_reg_type (TREE_TYPE (t)) && tree_could_throw_p (t))
|
||||
return false;
|
||||
|
||||
return is_gimple_formal_tmp_rhs (t);
|
||||
return get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS;
|
||||
}
|
||||
|
||||
/* Returns true iff T is a valid RHS for an assignment to an un-renamed
|
||||
@ -2603,7 +2580,7 @@ is_gimple_mem_rhs (tree t)
|
||||
if (is_gimple_reg_type (TREE_TYPE (t)))
|
||||
return is_gimple_val (t);
|
||||
else
|
||||
return is_gimple_formal_tmp_rhs (t);
|
||||
return is_gimple_val (t) || is_gimple_lvalue (t);
|
||||
}
|
||||
|
||||
/* Return true if T is a valid LHS for a GIMPLE assignment expression. */
|
||||
@ -2895,6 +2872,12 @@ is_gimple_reg (tree t)
|
||||
if (!is_gimple_variable (t))
|
||||
return false;
|
||||
|
||||
/* Complex and vector values must have been put into SSA-like form.
|
||||
That is, no assignments to the individual components. */
|
||||
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
|
||||
return DECL_GIMPLE_REG_P (t);
|
||||
|
||||
if (!is_gimple_reg_type (TREE_TYPE (t)))
|
||||
return false;
|
||||
|
||||
@ -2921,45 +2904,10 @@ is_gimple_reg (tree t)
|
||||
if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
|
||||
return false;
|
||||
|
||||
/* Complex and vector values must have been put into SSA-like form.
|
||||
That is, no assignments to the individual components. */
|
||||
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
|
||||
return DECL_GIMPLE_REG_P (t);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Returns true if T is a GIMPLE formal temporary variable. */
|
||||
|
||||
bool
|
||||
is_gimple_formal_tmp_var (tree t)
|
||||
{
|
||||
if (TREE_CODE (t) == SSA_NAME)
|
||||
return true;
|
||||
|
||||
return TREE_CODE (t) == VAR_DECL && DECL_GIMPLE_FORMAL_TEMP_P (t);
|
||||
}
|
||||
|
||||
/* Returns true if T is a GIMPLE formal temporary register variable. */
|
||||
|
||||
bool
|
||||
is_gimple_formal_tmp_reg (tree t)
|
||||
{
|
||||
/* The intent of this is to get hold of a value that won't change.
|
||||
An SSA_NAME qualifies no matter if its of a user variable or not. */
|
||||
if (TREE_CODE (t) == SSA_NAME)
|
||||
return true;
|
||||
|
||||
/* We don't know the lifetime characteristics of user variables. */
|
||||
if (!is_gimple_formal_tmp_var (t))
|
||||
return false;
|
||||
|
||||
/* Finally, it must be capable of being placed in a register. */
|
||||
return is_gimple_reg (t);
|
||||
}
|
||||
|
||||
/* Return true if T is a GIMPLE variable whose address is not needed. */
|
||||
|
||||
bool
|
||||
@ -3006,6 +2954,8 @@ is_gimple_asm_val (tree t)
|
||||
bool
|
||||
is_gimple_min_lval (tree t)
|
||||
{
|
||||
if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
|
||||
return false;
|
||||
return (is_gimple_id (t) || TREE_CODE (t) == INDIRECT_REF);
|
||||
}
|
||||
|
||||
|
@ -859,10 +859,6 @@ extern bool is_gimple_stmt (tree);
|
||||
extern bool is_gimple_reg_type (tree);
|
||||
/* Returns true iff T is a scalar register variable. */
|
||||
extern bool is_gimple_reg (tree);
|
||||
/* Returns true if T is a GIMPLE temporary variable, false otherwise. */
|
||||
extern bool is_gimple_formal_tmp_var (tree);
|
||||
/* Returns true if T is a GIMPLE temporary register variable. */
|
||||
extern bool is_gimple_formal_tmp_reg (tree);
|
||||
/* Returns true iff T is any sort of variable. */
|
||||
extern bool is_gimple_variable (tree);
|
||||
/* Returns true iff T is any sort of symbol. */
|
||||
@ -894,7 +890,6 @@ extern bool is_gimple_asm_val (tree);
|
||||
/* Returns true iff T is a valid rhs for a MODIFY_EXPR where the LHS is a
|
||||
GIMPLE temporary, a renamed user variable, or something else,
|
||||
respectively. */
|
||||
extern bool is_gimple_formal_tmp_rhs (tree);
|
||||
extern bool is_gimple_reg_rhs (tree);
|
||||
extern bool is_gimple_mem_rhs (tree);
|
||||
|
||||
|
137
gcc/gimplify.c
137
gcc/gimplify.c
@ -214,16 +214,12 @@ void
|
||||
pop_gimplify_context (gimple body)
|
||||
{
|
||||
struct gimplify_ctx *c = gimplify_ctxp;
|
||||
tree t;
|
||||
|
||||
gcc_assert (c && (c->bind_expr_stack == NULL
|
||||
|| VEC_empty (gimple, c->bind_expr_stack)));
|
||||
VEC_free (gimple, heap, c->bind_expr_stack);
|
||||
gimplify_ctxp = c->prev_context;
|
||||
|
||||
for (t = c->temps; t ; t = TREE_CHAIN (t))
|
||||
DECL_GIMPLE_FORMAL_TEMP_P (t) = 0;
|
||||
|
||||
if (body)
|
||||
declare_vars (c->temps, body, false);
|
||||
else
|
||||
@ -609,9 +605,6 @@ lookup_tmp_var (tree val, bool is_formal)
|
||||
}
|
||||
}
|
||||
|
||||
if (is_formal)
|
||||
DECL_GIMPLE_FORMAL_TEMP_P (ret) = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -622,32 +615,10 @@ lookup_tmp_var (tree val, bool is_formal)
|
||||
gimplify_modify_expr. */
|
||||
|
||||
static bool
|
||||
is_gimple_formal_tmp_or_call_rhs (tree t)
|
||||
is_gimple_reg_rhs_or_call (tree t)
|
||||
{
|
||||
return TREE_CODE (t) == CALL_EXPR || is_gimple_formal_tmp_rhs (t);
|
||||
}
|
||||
|
||||
/* Returns true iff T is a valid RHS for an assignment to a renamed
|
||||
user -- or front-end generated artificial -- variable. */
|
||||
|
||||
static bool
|
||||
is_gimple_reg_or_call_rhs (tree t)
|
||||
{
|
||||
/* 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 formal
|
||||
temporary. This way the optimizers can determine that the user
|
||||
variable is only modified if evaluation of the RHS does not throw.
|
||||
|
||||
Don't force a temp of a non-renamable type; the copy could be
|
||||
arbitrarily expensive. Instead we will generate a VDEF for
|
||||
the assignment. */
|
||||
|
||||
if (is_gimple_reg_type (TREE_TYPE (t))
|
||||
&& ((TREE_CODE (t) == CALL_EXPR && TREE_SIDE_EFFECTS (t))
|
||||
|| tree_could_throw_p (t)))
|
||||
return false;
|
||||
|
||||
return is_gimple_formal_tmp_or_call_rhs (t);
|
||||
return (get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS
|
||||
|| TREE_CODE (t) == CALL_EXPR);
|
||||
}
|
||||
|
||||
/* Return true if T is a valid memory RHS or a CALL_EXPR. Note that
|
||||
@ -655,28 +626,18 @@ is_gimple_reg_or_call_rhs (tree t)
|
||||
rationale for this in gimplify_modify_expr. */
|
||||
|
||||
static bool
|
||||
is_gimple_mem_or_call_rhs (tree t)
|
||||
is_gimple_mem_rhs_or_call (tree t)
|
||||
{
|
||||
/* If we're dealing with a renamable type, either source or dest must be
|
||||
a renamed variable. */
|
||||
if (is_gimple_reg_type (TREE_TYPE (t)))
|
||||
return is_gimple_val (t);
|
||||
else
|
||||
return is_gimple_formal_tmp_or_call_rhs (t);
|
||||
return (is_gimple_val (t) || is_gimple_lvalue (t)
|
||||
|| TREE_CODE (t) == CALL_EXPR);
|
||||
}
|
||||
|
||||
|
||||
/* Returns a formal temporary variable initialized with VAL. PRE_P is as
|
||||
in gimplify_expr. Only use this function if:
|
||||
|
||||
1) The value of the unfactored expression represented by VAL will not
|
||||
change between the initialization and use of the temporary, and
|
||||
2) The temporary will not be otherwise modified.
|
||||
|
||||
For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
|
||||
and #2 means it is inappropriate for && temps.
|
||||
|
||||
For other cases, use get_initialized_tmp_var instead. */
|
||||
/* Helper for get_formal_tmp_var and get_initialized_tmp_var. */
|
||||
|
||||
static tree
|
||||
internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
@ -686,7 +647,7 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
|
||||
/* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
|
||||
can create an INIT_EXPR and convert it into a GIMPLE_CALL below. */
|
||||
gimplify_expr (&val, pre_p, post_p, is_gimple_formal_tmp_or_call_rhs,
|
||||
gimplify_expr (&val, pre_p, post_p, is_gimple_reg_rhs_or_call,
|
||||
fb_rvalue);
|
||||
|
||||
t = lookup_tmp_var (val, is_formal);
|
||||
@ -707,11 +668,11 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
SET_DECL_RESTRICT_BASE (t, u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
|
||||
DECL_GIMPLE_REG_P (t) = 1;
|
||||
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
|
||||
DECL_GIMPLE_REG_P (t) = 1;
|
||||
}
|
||||
|
||||
mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
|
||||
|
||||
@ -735,9 +696,17 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Returns a formal temporary variable initialized with VAL. PRE_P
|
||||
points to a sequence where side-effects needed to compute VAL should be
|
||||
stored. */
|
||||
/* Returns a formal temporary variable initialized with VAL. PRE_P is as
|
||||
in gimplify_expr. Only use this function if:
|
||||
|
||||
1) The value of the unfactored expression represented by VAL will not
|
||||
change between the initialization and use of the temporary, and
|
||||
2) The temporary will not be otherwise modified.
|
||||
|
||||
For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
|
||||
and #2 means it is inappropriate for && temps.
|
||||
|
||||
For other cases, use get_initialized_tmp_var instead. */
|
||||
|
||||
tree
|
||||
get_formal_tmp_var (tree val, gimple_seq *pre_p)
|
||||
@ -2006,7 +1975,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
{
|
||||
TREE_OPERAND (t, 2) = low;
|
||||
tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
|
||||
post_p, is_gimple_formal_tmp_reg,
|
||||
post_p, is_gimple_reg,
|
||||
fb_rvalue);
|
||||
ret = MIN (ret, tret);
|
||||
}
|
||||
@ -2026,7 +1995,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
{
|
||||
TREE_OPERAND (t, 3) = elmt_size;
|
||||
tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
|
||||
post_p, is_gimple_formal_tmp_reg,
|
||||
post_p, is_gimple_reg,
|
||||
fb_rvalue);
|
||||
ret = MIN (ret, tret);
|
||||
}
|
||||
@ -2049,7 +2018,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
{
|
||||
TREE_OPERAND (t, 2) = offset;
|
||||
tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
|
||||
post_p, is_gimple_formal_tmp_reg,
|
||||
post_p, is_gimple_reg,
|
||||
fb_rvalue);
|
||||
ret = MIN (ret, tret);
|
||||
}
|
||||
@ -2072,19 +2041,11 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
|
||||
if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
|
||||
{
|
||||
/* Gimplify the dimension.
|
||||
Temporary fix for gcc.c-torture/execute/20040313-1.c.
|
||||
Gimplify non-constant array indices into a temporary
|
||||
variable.
|
||||
FIXME - The real fix is to gimplify post-modify
|
||||
expressions into a minimal gimple lvalue. However, that
|
||||
exposes bugs in alias analysis. The alias analyzer does
|
||||
not handle &PTR->FIELD very well. Will fix after the
|
||||
branch is merged into mainline (dnovillo 2004-05-03). */
|
||||
/* Gimplify the dimension. */
|
||||
if (!is_gimple_min_invariant (TREE_OPERAND (t, 1)))
|
||||
{
|
||||
tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
|
||||
is_gimple_formal_tmp_reg, fb_rvalue);
|
||||
is_gimple_val, fb_rvalue);
|
||||
ret = MIN (ret, tret);
|
||||
}
|
||||
}
|
||||
@ -2176,9 +2137,18 @@ gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
rhs = TREE_OPERAND (*expr_p, 1);
|
||||
|
||||
/* For postfix operator, we evaluate the LHS to an rvalue and then use
|
||||
that as the result value and in the postqueue operation. */
|
||||
that as the result value and in the postqueue operation. We also
|
||||
make sure to make lvalue a minimal lval, see
|
||||
gcc.c-torture/execute/20040313-1.c for an example where this matters. */
|
||||
if (postfix)
|
||||
{
|
||||
if (!is_gimple_min_lval (lvalue))
|
||||
{
|
||||
mark_addressable (lvalue);
|
||||
lvalue = build_fold_addr_expr (lvalue);
|
||||
gimplify_expr (&lvalue, pre_p, post_p, is_gimple_val, fb_rvalue);
|
||||
lvalue = build_fold_indirect_ref (lvalue);
|
||||
}
|
||||
ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
|
||||
if (ret == GS_ERROR)
|
||||
return ret;
|
||||
@ -3448,12 +3418,10 @@ gimplify_init_ctor_eval (tree object, VEC(constructor_elt,gc) *elts,
|
||||
gimple_predicate
|
||||
rhs_predicate_for (tree lhs)
|
||||
{
|
||||
if (is_gimple_formal_tmp_var (lhs))
|
||||
return is_gimple_formal_tmp_or_call_rhs;
|
||||
else if (is_gimple_reg (lhs))
|
||||
return is_gimple_reg_or_call_rhs;
|
||||
if (is_gimple_reg (lhs))
|
||||
return is_gimple_reg_rhs_or_call;
|
||||
else
|
||||
return is_gimple_mem_or_call_rhs;
|
||||
return is_gimple_mem_rhs_or_call;
|
||||
}
|
||||
|
||||
/* Gimplify a C99 compound literal expression. This just means adding
|
||||
@ -4120,11 +4088,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
|
||||
|| (DECL_P (*to_p) && DECL_REGISTER (*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. */
|
||||
@ -4644,7 +4607,7 @@ gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
|
||||
This mostly happens if the frontend passed us something that
|
||||
it could not mark addressable yet, like a fortran
|
||||
pass-by-reference parameter (int) floatvar. */
|
||||
if (is_gimple_formal_tmp_var (TREE_OPERAND (expr, 0)))
|
||||
if (is_gimple_reg (TREE_OPERAND (expr, 0)))
|
||||
TREE_OPERAND (expr, 0)
|
||||
= get_initialized_tmp_var (TREE_OPERAND (expr, 0), pre_p, post_p);
|
||||
|
||||
@ -6316,16 +6279,12 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
if (gimple_test_f == is_gimple_reg)
|
||||
gcc_assert (fallback & (fb_rvalue | fb_lvalue));
|
||||
else if (gimple_test_f == is_gimple_val
|
||||
|| gimple_test_f == is_gimple_formal_tmp_rhs
|
||||
|| gimple_test_f == is_gimple_formal_tmp_or_call_rhs
|
||||
|| gimple_test_f == is_gimple_formal_tmp_reg
|
||||
|| gimple_test_f == is_gimple_formal_tmp_var
|
||||
|| gimple_test_f == is_gimple_call_addr
|
||||
|| gimple_test_f == is_gimple_condexpr
|
||||
|| gimple_test_f == is_gimple_mem_rhs
|
||||
|| gimple_test_f == is_gimple_mem_or_call_rhs
|
||||
|| gimple_test_f == is_gimple_mem_rhs_or_call
|
||||
|| gimple_test_f == is_gimple_reg_rhs
|
||||
|| gimple_test_f == is_gimple_reg_or_call_rhs
|
||||
|| gimple_test_f == is_gimple_reg_rhs_or_call
|
||||
|| gimple_test_f == is_gimple_asm_val)
|
||||
gcc_assert (fallback & fb_rvalue);
|
||||
else if (gimple_test_f == is_gimple_min_lval
|
||||
@ -7128,7 +7087,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
|
||||
*expr_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (tmp)), tmp);
|
||||
}
|
||||
else if ((fallback & fb_rvalue) && is_gimple_formal_tmp_or_call_rhs (*expr_p))
|
||||
else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
|
||||
{
|
||||
/* An rvalue will do. Assign the gimplified expression into a
|
||||
new temporary TMP and replace the original expression with
|
||||
@ -7143,9 +7102,6 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
*expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
|
||||
else
|
||||
*expr_p = get_formal_tmp_var (*expr_p, pre_p);
|
||||
|
||||
if (TREE_CODE (*expr_p) != SSA_NAME)
|
||||
DECL_GIMPLE_FORMAL_TEMP_P (*expr_p) = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -7597,7 +7553,7 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
|
||||
lhs = gimple_get_lhs (stmt);
|
||||
/* If the LHS changed it in a way that requires a simple RHS,
|
||||
create temporary. */
|
||||
if (lhs && !is_gimple_formal_tmp_var (lhs))
|
||||
if (lhs && !is_gimple_reg (lhs))
|
||||
{
|
||||
bool need_temp = false;
|
||||
|
||||
@ -7646,7 +7602,6 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
|
||||
{
|
||||
tree temp = create_tmp_var (TREE_TYPE (lhs), NULL);
|
||||
|
||||
DECL_GIMPLE_FORMAL_TEMP_P (temp) = 1;
|
||||
if (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE)
|
||||
DECL_GIMPLE_REG_P (temp) = 1;
|
||||
|
@ -1,3 +1,8 @@
|
||||
2009-03-31 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
* java-gimplify.c (java_gimplify_expr): Do not manually gimplify
|
||||
the first operand of binary and comaprison expressions.
|
||||
|
||||
2009-03-30 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
PR rtl-optimization/323
|
||||
|
@ -96,26 +96,6 @@ java_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
|
||||
gcc_unreachable ();
|
||||
|
||||
default:
|
||||
/* Java insists on strict left-to-right evaluation of expressions.
|
||||
A problem may arise if a variable used in the LHS of a binary
|
||||
operation is altered by an assignment to that value in the RHS
|
||||
before we've performed the operation. So, we always copy every
|
||||
LHS to a temporary variable.
|
||||
|
||||
FIXME: Are there any other cases where we should do this?
|
||||
Parameter lists, maybe? Or perhaps that's unnecessary because
|
||||
the front end already generates SAVE_EXPRs. */
|
||||
|
||||
if (TREE_CODE_CLASS (code) == tcc_binary
|
||||
|| TREE_CODE_CLASS (code) == tcc_comparison)
|
||||
{
|
||||
enum gimplify_status stat
|
||||
= gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
|
||||
is_gimple_formal_tmp_var, fb_rvalue);
|
||||
if (stat == GS_ERROR)
|
||||
return stat;
|
||||
}
|
||||
|
||||
return GS_UNHANDLED;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
2009-03-31 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/23401
|
||||
PR middle-end/27810
|
||||
* gcc.dg/tree-ssa/pr23401.c: New testcase.
|
||||
* gcc.dg/tree-ssa/pr27810.c: Likewise.
|
||||
|
||||
2009-03-30 Steven G. Kargl <kargls@comcast.net>
|
||||
|
||||
PR fortran/38389
|
||||
|
24
gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
Normal file
24
gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-fdump-tree-gimple" } */
|
||||
|
||||
struct f
|
||||
{
|
||||
struct {
|
||||
int i;
|
||||
} ff[10];
|
||||
};
|
||||
|
||||
struct f g;
|
||||
int ffff(int i)
|
||||
{
|
||||
int t1 = 0;
|
||||
int i1 = g.ff[t1].i;
|
||||
int i2 = g.ff[i].i;
|
||||
return i1 + i2;
|
||||
}
|
||||
|
||||
/* We should not use extra temporaries apart from for i1 + i2. */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "int" 5 "gimple" } } */
|
||||
/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */
|
||||
/* { dg-final { cleanup-tree-dump "gimple" } } */
|
18
gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
Normal file
18
gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
Normal file
@ -0,0 +1,18 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-fdump-tree-gimple" } */
|
||||
|
||||
int bar (int);
|
||||
|
||||
int qqq (int a)
|
||||
{
|
||||
int result;
|
||||
result = bar (a);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* We should not use an extra temporary for the result of the
|
||||
function call. */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "int" 3 "gimple" } } */
|
||||
/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */
|
||||
/* { dg-final { cleanup-tree-dump "gimple" } } */
|
@ -2886,6 +2886,11 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
|
||||
error ("address taken, but ADDRESSABLE bit not set");
|
||||
return x;
|
||||
}
|
||||
if (DECL_GIMPLE_REG_P (x))
|
||||
{
|
||||
error ("DECL_GIMPLE_REG_P set on a variable with address taken");
|
||||
return x;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -1823,6 +1823,25 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
|
||||
{
|
||||
case GIMPLE_CALL:
|
||||
case GIMPLE_ASSIGN:
|
||||
/* If the stmt can throw use a new temporary for the assignment
|
||||
to a LHS. This makes sure the old value of the LHS is
|
||||
available on the EH edge. */
|
||||
if (stmt_could_throw_p (stmt)
|
||||
&& gimple_has_lhs (stmt)
|
||||
&& !tree_could_throw_p (gimple_get_lhs (stmt))
|
||||
&& is_gimple_reg_type (TREE_TYPE (gimple_get_lhs (stmt))))
|
||||
{
|
||||
tree lhs = gimple_get_lhs (stmt);
|
||||
tree tmp = create_tmp_var (TREE_TYPE (lhs), NULL);
|
||||
gimple s = gimple_build_assign (lhs, tmp);
|
||||
gimple_set_location (s, gimple_location (stmt));
|
||||
gimple_set_block (s, gimple_block (stmt));
|
||||
gimple_set_lhs (stmt, tmp);
|
||||
if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
|
||||
DECL_GIMPLE_REG_P (tmp) = 1;
|
||||
gsi_insert_after (gsi, s, GSI_SAME_STMT);
|
||||
}
|
||||
/* Look for things that can throw exceptions, and record them. */
|
||||
if (state->cur_region && stmt_could_throw_p (stmt))
|
||||
{
|
||||
|
@ -503,7 +503,7 @@ mf_build_check_statement_for (tree base, tree limit,
|
||||
tree mf_elem;
|
||||
tree mf_limit;
|
||||
gimple g;
|
||||
gimple_seq seq;
|
||||
gimple_seq seq, stmts;
|
||||
|
||||
/* We first need to split the current basic block, and start altering
|
||||
the CFG. This allows us to insert the statements we're about to
|
||||
@ -553,14 +553,16 @@ mf_build_check_statement_for (tree base, tree limit,
|
||||
/* Build: __mf_base = (uintptr_t) <base address expression>. */
|
||||
seq = gimple_seq_alloc ();
|
||||
t = fold_convert (mf_uintptr_type, unshare_expr (base));
|
||||
gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
|
||||
t = force_gimple_operand (t, &stmts, false, NULL_TREE);
|
||||
gimple_seq_add_seq (&seq, stmts);
|
||||
g = gimple_build_assign (mf_base, t);
|
||||
gimple_set_location (g, location);
|
||||
gimple_seq_add_stmt (&seq, g);
|
||||
|
||||
/* Build: __mf_limit = (uintptr_t) <limit address expression>. */
|
||||
t = fold_convert (mf_uintptr_type, unshare_expr (limit));
|
||||
gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
|
||||
t = force_gimple_operand (t, &stmts, false, NULL_TREE);
|
||||
gimple_seq_add_seq (&seq, stmts);
|
||||
g = gimple_build_assign (mf_limit, t);
|
||||
gimple_set_location (g, location);
|
||||
gimple_seq_add_stmt (&seq, g);
|
||||
@ -577,7 +579,8 @@ mf_build_check_statement_for (tree base, tree limit,
|
||||
TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
|
||||
mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
|
||||
t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
|
||||
gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
|
||||
t = force_gimple_operand (t, &stmts, false, NULL_TREE);
|
||||
gimple_seq_add_seq (&seq, stmts);
|
||||
g = gimple_build_assign (mf_elem, t);
|
||||
gimple_set_location (g, location);
|
||||
gimple_seq_add_stmt (&seq, g);
|
||||
@ -622,7 +625,8 @@ mf_build_check_statement_for (tree base, tree limit,
|
||||
result of the evaluation of 't' in a temporary variable which we
|
||||
can use as the condition for the conditional jump. */
|
||||
t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u);
|
||||
gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
|
||||
t = force_gimple_operand (t, &stmts, false, NULL_TREE);
|
||||
gimple_seq_add_seq (&seq, stmts);
|
||||
cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
|
||||
g = gimple_build_assign (cond, t);
|
||||
gimple_set_location (g, location);
|
||||
@ -663,7 +667,8 @@ mf_build_check_statement_for (tree base, tree limit,
|
||||
v = fold_build2 (PLUS_EXPR, integer_type_node,
|
||||
fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base),
|
||||
integer_one_node);
|
||||
gimplify_expr (&v, &seq, &seq, is_gimple_mem_rhs, fb_rvalue);
|
||||
v = force_gimple_operand (v, &stmts, true, NULL_TREE);
|
||||
gimple_seq_add_seq (&seq, stmts);
|
||||
g = gimple_build_call (mf_check_fndecl, 4, mf_base, v, dirflag, u);
|
||||
gimple_seq_add_stmt (&seq, g);
|
||||
|
||||
|
@ -1051,7 +1051,9 @@ get_or_alloc_expr_for (tree t)
|
||||
{
|
||||
if (TREE_CODE (t) == SSA_NAME)
|
||||
return get_or_alloc_expr_for_name (t);
|
||||
else if (is_gimple_min_invariant (t))
|
||||
else if (is_gimple_min_invariant (t)
|
||||
|| TREE_CODE (t) == EXC_PTR_EXPR
|
||||
|| TREE_CODE (t) == FILTER_EXPR)
|
||||
return get_or_alloc_expr_for_constant (t);
|
||||
else
|
||||
{
|
||||
|
@ -2928,11 +2928,6 @@ struct tree_parm_decl GTY(())
|
||||
/* Used to indicate that this DECL has weak linkage. */
|
||||
#define DECL_WEAK(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.weak_flag)
|
||||
|
||||
/* Internal to the gimplifier. Indicates that the value is a formal
|
||||
temporary controlled by the gimplifier. */
|
||||
#define DECL_GIMPLE_FORMAL_TEMP_P(DECL) \
|
||||
DECL_WITH_VIS_CHECK (DECL)->decl_with_vis.gimple_formal_temp
|
||||
|
||||
/* Used to indicate that the DECL is a dllimport. */
|
||||
#define DECL_DLLIMPORT_P(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.dllimport_flag)
|
||||
|
||||
@ -3044,7 +3039,6 @@ struct tree_decl_with_vis GTY(())
|
||||
unsigned thread_local:1;
|
||||
unsigned common_flag:1;
|
||||
unsigned in_text_section : 1;
|
||||
unsigned gimple_formal_temp : 1;
|
||||
unsigned dllimport_flag : 1;
|
||||
unsigned based_on_restrict_p : 1;
|
||||
/* Used by C++. Might become a generic decl flag. */
|
||||
@ -3062,7 +3056,7 @@ struct tree_decl_with_vis GTY(())
|
||||
|
||||
/* Belongs to VAR_DECL exclusively. */
|
||||
ENUM_BITFIELD(tls_model) tls_model : 3;
|
||||
/* 12 unused bits. */
|
||||
/* 13 unused bits. */
|
||||
};
|
||||
|
||||
/* In a VAR_DECL that's static,
|
||||
|
Loading…
Reference in New Issue
Block a user