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:
Richard Guenther 2009-03-31 10:23:44 +00:00 committed by Richard Biener
parent 8de9b877e7
commit ba4d8f9d37
14 changed files with 195 additions and 192 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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" } } */

View 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" } } */

View File

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

View File

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

View File

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

View File

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

View File

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