From ba4d8f9d37bf11be3a98504812447cd9bbaad708 Mon Sep 17 00:00:00 2001 From: Richard Guenther <rguenther@suse.de> Date: Tue, 31 Mar 2009 10:23:44 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 44 ++++++++ gcc/gimple.c | 74 +++---------- gcc/gimple.h | 5 - gcc/gimplify.c | 137 ++++++++---------------- gcc/java/ChangeLog | 5 + gcc/java/java-gimplify.c | 20 ---- gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/gcc.dg/tree-ssa/pr23401.c | 24 +++++ gcc/testsuite/gcc.dg/tree-ssa/pr27810.c | 18 ++++ gcc/tree-cfg.c | 5 + gcc/tree-eh.c | 19 ++++ gcc/tree-mudflap.c | 17 +-- gcc/tree-ssa-pre.c | 4 +- gcc/tree.h | 8 +- 14 files changed, 195 insertions(+), 192 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr23401.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr27810.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 81886235bd6e..15a8228c6cf9 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 90de9b3ebc56..a1dd6a750723 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 df9bccdc3cdc..b482c1d607df 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 bd82051d1589..515c58ed57e9 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 a72a2f947019..62c76a77c4f3 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 a43e67e5fec3..e2ad02b697a1 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 aadb0da5e339..c21f1074cfb6 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 000000000000..1d30ac7519f5 --- /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 000000000000..c7da3bd5d06b --- /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 9c5b2e6c58ca..66f121836cb3 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 f55a4172b104..1d9a9bdac362 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 831fcc1791a8..dae12874dad6 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 9d06a8a3f297..267c2fcfea22 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 830852de8b56..1a83c2505da5 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, -- GitLab