aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog44
-rw-r--r--gcc/gimple.c74
-rw-r--r--gcc/gimple.h5
-rw-r--r--gcc/gimplify.c137
-rw-r--r--gcc/java/ChangeLog5
-rw-r--r--gcc/java/java-gimplify.c20
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr23401.c24
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr27810.c18
-rw-r--r--gcc/tree-cfg.c5
-rw-r--r--gcc/tree-eh.c19
-rw-r--r--gcc/tree-mudflap.c17
-rw-r--r--gcc/tree-ssa-pre.c4
-rw-r--r--gcc/tree.h8
14 files changed, 195 insertions, 192 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8188623..15a8228 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 90de9b3..a1dd6a7 100644
--- a/gcc/gimple.c
+++ b/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);
}
diff --git a/gcc/gimple.h b/gcc/gimple.h
index df9bccd..b482c1d 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -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);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index bd82051..515c58e 100644
--- a/gcc/gimplify.c
+++ b/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;
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index a72a2f9..62c76a7 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -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
diff --git a/gcc/java/java-gimplify.c b/gcc/java/java-gimplify.c
index a43e67e..e2ad02b 100644
--- a/gcc/java/java-gimplify.c
+++ b/gcc/java/java-gimplify.c
@@ -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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index aadb0da..c21f107 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
new file mode 100644
index 0000000..1d30ac7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
new file mode 100644
index 0000000..c7da3bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
@@ -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" } } */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 9c5b2e6..66f1218 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -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;
}
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index f55a417..1d9a9bd 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -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))
{
diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c
index 831fcc1..dae1287 100644
--- a/gcc/tree-mudflap.c
+++ b/gcc/tree-mudflap.c
@@ -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);
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 9d06a8a..267c2fc 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -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
{
diff --git a/gcc/tree.h b/gcc/tree.h
index 830852d..1a83c25 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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,