X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fgimplify.c;h=15005c379bd59264e57810587f61e8ece96398e6;hb=c119b8ad7b84d02c43821a2a79330d79395cc462;hp=d723d9f16a925d17d527924c3a8af6358032fbbc;hpb=78fa9ba7f63d3c9ea10d354dc38aad11a2965704;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/gimplify.c b/gcc/gimplify.c index d723d9f16a9..15005c379bd 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1,6 +1,6 @@ /* Tree lowering pass. This pass converts the GENERIC functions-as-trees tree representation into the GIMPLE form. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Major work done by Sebastian Pop , Diego Novillo and Jason Merrill . @@ -107,12 +107,14 @@ static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool); /* Mark X addressable. Unlike the langhook we expect X to be in gimple form and we don't do any syntax checking. */ -static void +void mark_addressable (tree x) { while (handled_component_p (x)) x = TREE_OPERAND (x, 0); - if (TREE_CODE (x) != VAR_DECL && TREE_CODE (x) != PARM_DECL) + if (TREE_CODE (x) != VAR_DECL + && TREE_CODE (x) != PARM_DECL + && TREE_CODE (x) != RESULT_DECL) return ; TREE_ADDRESSABLE (x) = 1; } @@ -212,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 @@ -518,7 +516,8 @@ create_tmp_var_raw (tree type, const char *prefix) new_type = build_type_variant (type, 0, 0); TYPE_ATTRIBUTES (new_type) = TYPE_ATTRIBUTES (type); - tmp_var = build_decl (VAR_DECL, prefix ? create_tmp_var_name (prefix) : NULL, + tmp_var = build_decl (input_location, + VAR_DECL, prefix ? create_tmp_var_name (prefix) : NULL, type); /* The variable was declared by the compiler. */ @@ -565,7 +564,7 @@ create_tmp_var (tree type, const char *prefix) static inline tree create_tmp_from_val (tree val) { - return create_tmp_var (TYPE_MAIN_VARIANT (TREE_TYPE (val)), get_name (val)); + return create_tmp_var (TREE_TYPE (val), get_name (val)); } /* Create a temporary to hold the value of VAL. If IS_FORMAL, try to reuse @@ -607,9 +606,6 @@ lookup_tmp_var (tree val, bool is_formal) } } - if (is_formal) - DECL_GIMPLE_FORMAL_TEMP_P (ret) = 1; - return ret; } @@ -620,32 +616,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 @@ -653,33 +627,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. Also force a temporary if the type doesn't need - to be stored in memory, since it's cheap and prevents erroneous - tailcalls (PR 17526). */ - if (is_gimple_reg_type (TREE_TYPE (t)) - || (TYPE_MODE (TREE_TYPE (t)) != BLKmode - && (TREE_CODE (t) != CALL_EXPR - || ! aggregate_value_p (t, t)))) + 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, @@ -689,7 +648,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); @@ -710,11 +669,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)); @@ -738,9 +697,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) @@ -772,7 +739,7 @@ declare_vars (tree vars, gimple scope, bool debug_info) temps = nreverse (last); - block = gimple_block (scope); + block = gimple_bind_block (scope); gcc_assert (!block || TREE_CODE (block) == BLOCK); if (!block || !debug_info) { @@ -1245,13 +1212,21 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) omp_add_variable (gimplify_omp_ctxp, t, GOVD_LOCAL | GOVD_SEEN); DECL_SEEN_IN_BIND_EXPR_P (t) = 1; + + if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun) + cfun->has_local_explicit_reg_vars = true; } /* Preliminarily mark non-addressed complex variables as eligible for promotion to gimple registers. We'll transform their uses - as we find them. */ - if ((TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE - || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE) + as we find them. + We exclude complex types if not optimizing because they can be + subject to partial stores in GNU C by means of the __real__ and + __imag__ operators and we cannot promote them to total stores + (see gimplify_modify_expr_complex_part). */ + if (optimize + && (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE + || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE) && !TREE_THIS_VOLATILE (t) && (TREE_CODE (t) == VAR_DECL && !DECL_HARD_REGISTER (t)) && !needs_to_live_in_memory (t)) @@ -1490,7 +1465,7 @@ static enum gimplify_status gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p) { tree saved_label = gimplify_ctxp->exit_label; - tree start_label = create_artificial_label (); + tree start_label = create_artificial_label (UNKNOWN_LOCATION); gimplify_seq_add_stmt (pre_p, gimple_build_label (start_label)); @@ -1630,20 +1605,64 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p) } len = i; + if (!VEC_empty (tree, labels)) + sort_case_labels (labels); + if (!default_case) { - gimple new_default; + tree type = TREE_TYPE (switch_expr); /* If the switch has no default label, add one, so that we jump - around the switch body. */ - default_case = build3 (CASE_LABEL_EXPR, void_type_node, NULL_TREE, - NULL_TREE, create_artificial_label ()); - new_default = gimple_build_label (CASE_LABEL (default_case)); - gimplify_seq_add_stmt (&switch_body_seq, new_default); - } + around the switch body. If the labels already cover the whole + range of type, add the default label pointing to one of the + existing labels. */ + if (type == void_type_node) + type = TREE_TYPE (SWITCH_COND (switch_expr)); + if (len + && INTEGRAL_TYPE_P (type) + && TYPE_MIN_VALUE (type) + && TYPE_MAX_VALUE (type) + && tree_int_cst_equal (CASE_LOW (VEC_index (tree, labels, 0)), + TYPE_MIN_VALUE (type))) + { + tree low, high = CASE_HIGH (VEC_index (tree, labels, len - 1)); + if (!high) + high = CASE_LOW (VEC_index (tree, labels, len - 1)); + if (tree_int_cst_equal (high, TYPE_MAX_VALUE (type))) + { + for (i = 1; i < len; i++) + { + high = CASE_LOW (VEC_index (tree, labels, i)); + low = CASE_HIGH (VEC_index (tree, labels, i - 1)); + if (!low) + low = CASE_LOW (VEC_index (tree, labels, i - 1)); + if ((TREE_INT_CST_LOW (low) + 1 + != TREE_INT_CST_LOW (high)) + || (TREE_INT_CST_HIGH (low) + + (TREE_INT_CST_LOW (high) == 0) + != TREE_INT_CST_HIGH (high))) + break; + } + if (i == len) + default_case = build3 (CASE_LABEL_EXPR, void_type_node, + NULL_TREE, NULL_TREE, + CASE_LABEL (VEC_index (tree, + labels, 0))); + } + } - if (!VEC_empty (tree, labels)) - sort_case_labels (labels); + if (!default_case) + { + gimple new_default; + + default_case + = build3 (CASE_LABEL_EXPR, void_type_node, + NULL_TREE, NULL_TREE, + create_artificial_label (UNKNOWN_LOCATION)); + new_default = gimple_build_label (CASE_LABEL (default_case)); + gimplify_seq_add_stmt (&switch_body_seq, new_default); + } + } gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr), default_case, labels); @@ -1690,7 +1709,7 @@ build_and_jump (tree *label_p) if (*label_p == NULL_TREE) { - tree label = create_artificial_label (); + tree label = create_artificial_label (UNKNOWN_LOCATION); *label_p = label; } @@ -1836,7 +1855,7 @@ gimplify_conversion (tree *expr_p) { tree tem; gcc_assert (CONVERT_EXPR_P (*expr_p)); - + /* Then strip away all but the outermost conversion. */ STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0)); @@ -1851,8 +1870,8 @@ gimplify_conversion (tree *expr_p) && POINTER_TYPE_P (TREE_TYPE (*expr_p)) && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0))) && (tem = maybe_fold_offset_to_address - (TREE_OPERAND (*expr_p, 0), - integer_zero_node, TREE_TYPE (*expr_p))) != NULL_TREE) + (EXPR_LOCATION (*expr_p), TREE_OPERAND (*expr_p, 0), + integer_zero_node, TREE_TYPE (*expr_p))) != NULL_TREE) *expr_p = tem; /* If we still have a conversion at the toplevel, @@ -1882,6 +1901,9 @@ gimplify_conversion (tree *expr_p) return GS_OK; } +/* Nonlocal VLAs seen in the current function. */ +static struct pointer_set_t *nonlocal_vlas; + /* Gimplify a VAR_DECL or PARM_DECL. Returns GS_OK if we expanded a DECL_VALUE_EXPR, and it's worth re-examining things. */ @@ -1912,7 +1934,36 @@ gimplify_var_or_parm_decl (tree *expr_p) /* If the decl is an alias for another expression, substitute it now. */ if (DECL_HAS_VALUE_EXPR_P (decl)) { - *expr_p = unshare_expr (DECL_VALUE_EXPR (decl)); + tree value_expr = DECL_VALUE_EXPR (decl); + + /* For referenced nonlocal VLAs add a decl for debugging purposes + to the current function. */ + if (TREE_CODE (decl) == VAR_DECL + && TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST + && nonlocal_vlas != NULL + && TREE_CODE (value_expr) == INDIRECT_REF + && TREE_CODE (TREE_OPERAND (value_expr, 0)) == VAR_DECL + && decl_function_context (decl) != current_function_decl) + { + struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; + while (ctx && ctx->region_type == ORT_WORKSHARE) + ctx = ctx->outer_context; + if (!ctx && !pointer_set_insert (nonlocal_vlas, decl)) + { + tree copy = copy_node (decl), block; + + lang_hooks.dup_lang_specific_decl (copy); + SET_DECL_RTL (copy, NULL_RTX); + TREE_USED (copy) = 1; + block = DECL_INITIAL (current_function_decl); + TREE_CHAIN (copy) = BLOCK_VARS (block); + BLOCK_VARS (block) = copy; + SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr)); + DECL_HAS_VALUE_EXPR_P (copy) = 1; + } + } + + *expr_p = unshare_expr (value_expr); return GS_OK; } @@ -2006,7 +2057,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 +2077,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 +2100,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 +2123,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 +2219,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; @@ -2238,10 +2290,11 @@ maybe_with_size_expr (tree *expr_p) /* Helper for gimplify_call_expr. Gimplify a single argument *ARG_P - Store any side-effects in PRE_P. */ + Store any side-effects in PRE_P. CALL_LOCATION is the location of + the CALL_EXPR. */ static enum gimplify_status -gimplify_arg (tree *arg_p, gimple_seq *pre_p) +gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location) { bool (*test) (tree); fallback_t fb; @@ -2259,6 +2312,11 @@ gimplify_arg (tree *arg_p, gimple_seq *pre_p) /* If this is a variable sized type, we must remember the size. */ maybe_with_size_expr (arg_p); + /* FIXME diagnostics: This will mess up gcc.dg/Warray-bounds.c. */ + /* Make sure arguments have the same location as the function call + itself. */ + protected_set_expr_location (*arg_p, call_location); + /* There is a sequence point before a function call. Side effects in the argument list must occur before the actual call. So, when gimplifying arguments, force gimplify_expr to use an internal @@ -2319,13 +2377,13 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) if (call_expr_nargs (*expr_p) < 2) { error ("too few arguments to function %"); - *expr_p = build_empty_stmt (); + *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p)); return GS_OK; } if (fold_builtin_next_arg (*expr_p, true)) { - *expr_p = build_empty_stmt (); + *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p)); return GS_OK; } } @@ -2347,56 +2405,14 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) else if (POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_FN (*expr_p)))) parms = TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*expr_p)))); - /* Verify if the type of the argument matches that of the function - declaration. If we cannot verify this or there is a mismatch, - mark the call expression so it doesn't get inlined later. */ if (fndecl && DECL_ARGUMENTS (fndecl)) - { - for (i = 0, p = DECL_ARGUMENTS (fndecl); - i < nargs; - i++, p = TREE_CHAIN (p)) - { - /* We cannot distinguish a varargs function from the case - of excess parameters, still deferring the inlining decision - to the callee is possible. */ - if (!p) - break; - if (p == error_mark_node - || CALL_EXPR_ARG (*expr_p, i) == error_mark_node - || !fold_convertible_p (DECL_ARG_TYPE (p), - CALL_EXPR_ARG (*expr_p, i))) - { - CALL_CANNOT_INLINE_P (*expr_p) = 1; - break; - } - } - } + p = DECL_ARGUMENTS (fndecl); else if (parms) - { - for (i = 0, p = parms; i < nargs; i++, p = TREE_CHAIN (p)) - { - /* If this is a varargs function defer inlining decision - to callee. */ - if (!p) - break; - if (TREE_VALUE (p) == error_mark_node - || CALL_EXPR_ARG (*expr_p, i) == error_mark_node - || TREE_CODE (TREE_VALUE (p)) == VOID_TYPE - || !fold_convertible_p (TREE_VALUE (p), - CALL_EXPR_ARG (*expr_p, i))) - { - CALL_CANNOT_INLINE_P (*expr_p) = 1; - break; - } - } - } + p = parms; else - { - if (nargs != 0) - CALL_CANNOT_INLINE_P (*expr_p) = 1; - i = 0; - p = NULL_TREE; - } + p = NULL_TREE; + for (i = 0; i < nargs && p; i++, p = TREE_CHAIN (p)) + ; /* If the last argument is __builtin_va_arg_pack () and it is not passed as a named argument, decrease the number of CALL_EXPR @@ -2448,7 +2464,8 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) be the plain PARM_DECL. */ if ((i != 1) || !builtin_va_start_p) { - t = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p); + t = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p, + EXPR_LOCATION (*expr_p)); if (t == GS_ERROR) ret = GS_ERROR; @@ -2515,12 +2532,15 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) condition is true or false, respectively. If null, we should generate our own to skip over the evaluation of this specific expression. + LOCUS is the source location of the COND_EXPR. + This function is the tree equivalent of do_jump. shortcut_cond_r should only be called by shortcut_cond_expr. */ static tree -shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p) +shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p, + location_t locus) { tree local_label = NULL_TREE; tree t, expr = NULL; @@ -2530,6 +2550,8 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p) shortcut_cond_expr will append the real blocks later. */ if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR) { + location_t new_locus; + /* Turn if (a && b) into if (a); else goto no; @@ -2539,15 +2561,20 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p) if (false_label_p == NULL) false_label_p = &local_label; - t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p); + /* Keep the original source location on the first 'if'. */ + t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus); append_to_statement_list (t, &expr); - t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, - false_label_p); + /* Set the source location of the && on the second 'if'. */ + new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus; + t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p, + new_locus); append_to_statement_list (t, &expr); } else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR) { + location_t new_locus; + /* Turn if (a || b) into if (a) goto yes; @@ -2557,31 +2584,41 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p) if (true_label_p == NULL) true_label_p = &local_label; - t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL); + /* Keep the original source location on the first 'if'. */ + t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus); append_to_statement_list (t, &expr); - t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, - false_label_p); + /* Set the source location of the || on the second 'if'. */ + new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus; + t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p, + new_locus); append_to_statement_list (t, &expr); } else if (TREE_CODE (pred) == COND_EXPR) { + location_t new_locus; + /* As long as we're messing with gotos, turn if (a ? b : c) into if (a) if (b) goto yes; else goto no; else if (c) goto yes; else goto no; */ + + /* Keep the original source location on the first 'if'. Set the source + location of the ? on the second 'if'. */ + new_locus = EXPR_HAS_LOCATION (pred) ? EXPR_LOCATION (pred) : locus; expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0), shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, - false_label_p), + false_label_p, locus), shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p, - false_label_p)); + false_label_p, new_locus)); } else { expr = build3 (COND_EXPR, void_type_node, pred, build_and_jump (true_label_p), build_and_jump (false_label_p)); + SET_EXPR_LOCATION (expr, locus); } if (local_label) @@ -2613,14 +2650,24 @@ shortcut_cond_expr (tree expr) /* First do simple transformations. */ if (!else_se) { - /* If there is no 'else', turn (a && b) into if (a) if (b). */ + /* If there is no 'else', turn + if (a && b) then c + into + if (a) if (b) then c. */ while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR) { + /* Keep the original source location on the first 'if'. */ + location_t locus = EXPR_HAS_LOCATION (expr) + ? EXPR_LOCATION (expr) : input_location; TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1); + /* Set the source location of the && on the second 'if'. */ + if (EXPR_HAS_LOCATION (pred)) + SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred)); then_ = shortcut_cond_expr (expr); then_se = then_ && TREE_SIDE_EFFECTS (then_); pred = TREE_OPERAND (pred, 0); expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE); + SET_EXPR_LOCATION (expr, locus); } } @@ -2632,11 +2679,18 @@ shortcut_cond_expr (tree expr) if (a); else if (b); else d. */ while (TREE_CODE (pred) == TRUTH_ORIF_EXPR) { + /* Keep the original source location on the first 'if'. */ + location_t locus = EXPR_HAS_LOCATION (expr) + ? EXPR_LOCATION (expr) : input_location; TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1); + /* Set the source location of the || on the second 'if'. */ + if (EXPR_HAS_LOCATION (pred)) + SET_EXPR_LOCATION (expr, EXPR_LOCATION (pred)); else_ = shortcut_cond_expr (expr); else_se = else_ && TREE_SIDE_EFFECTS (else_); pred = TREE_OPERAND (pred, 0); expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_); + SET_EXPR_LOCATION (expr, locus); } } @@ -2690,17 +2744,19 @@ shortcut_cond_expr (tree expr) /* If there was nothing else in our arms, just forward the label(s). */ if (!then_se && !else_se) - return shortcut_cond_r (pred, true_label_p, false_label_p); + return shortcut_cond_r (pred, true_label_p, false_label_p, + EXPR_HAS_LOCATION (expr) + ? EXPR_LOCATION (expr) : input_location); /* If our last subexpression already has a terminal label, reuse it. */ if (else_se) - expr = expr_last (else_); + t = expr_last (else_); else if (then_se) - expr = expr_last (then_); + t = expr_last (then_); else - expr = NULL; - if (expr && TREE_CODE (expr) == LABEL_EXPR) - end_label = LABEL_EXPR_LABEL (expr); + t = NULL; + if (t && TREE_CODE (t) == LABEL_EXPR) + end_label = LABEL_EXPR_LABEL (t); /* If we don't care about jumping to the 'else' branch, jump to the end if the condition is false. */ @@ -2721,7 +2777,9 @@ shortcut_cond_expr (tree expr) non-void function. */ jump_over_else = block_may_fallthru (then_); - pred = shortcut_cond_r (pred, true_label_p, false_label_p); + pred = shortcut_cond_r (pred, true_label_p, false_label_p, + EXPR_HAS_LOCATION (expr) + ? EXPR_LOCATION (expr) : input_location); expr = NULL; append_to_statement_list (pred, &expr); @@ -2731,7 +2789,10 @@ shortcut_cond_expr (tree expr) { if (jump_over_else) { + tree last = expr_last (expr); t = build_and_jump (&end_label); + if (EXPR_HAS_LOCATION (last)) + SET_EXPR_LOCATION (t, EXPR_LOCATION (last)); append_to_statement_list (t, &expr); } if (emit_false) @@ -2990,7 +3051,7 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback) have_then_clause_p = true; } else - label_true = create_artificial_label (); + label_true = create_artificial_label (UNKNOWN_LOCATION); if (TREE_OPERAND (expr, 2) != NULL && TREE_CODE (TREE_OPERAND (expr, 2)) == GOTO_EXPR && TREE_CODE (GOTO_DESTINATION (TREE_OPERAND (expr, 2))) == LABEL_DECL @@ -3008,7 +3069,7 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback) have_else_clause_p = true; } else - label_false = create_artificial_label (); + label_false = create_artificial_label (UNKNOWN_LOCATION); gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1, &arm2); @@ -3039,7 +3100,7 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback) && gimple_seq_may_fallthru (seq)) { gimple g; - label_cont = create_artificial_label (); + label_cont = create_artificial_label (UNKNOWN_LOCATION); g = gimple_build_goto (label_cont); @@ -3094,11 +3155,13 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value, to = TREE_OPERAND (*expr_p, 0); from = TREE_OPERAND (*expr_p, 1); + mark_addressable (from); from_ptr = build_fold_addr_expr (from); - gimplify_arg (&from_ptr, seq_p); + gimplify_arg (&from_ptr, seq_p, EXPR_LOCATION (*expr_p)); + mark_addressable (to); to_ptr = build_fold_addr_expr (to); - gimplify_arg (&to_ptr, seq_p); + gimplify_arg (&to_ptr, seq_p, EXPR_LOCATION (*expr_p)); t = implicit_built_in_decls[BUILT_IN_MEMCPY]; @@ -3145,7 +3208,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value, to = TREE_OPERAND (*expr_p, 0); to_ptr = build_fold_addr_expr (to); - gimplify_arg (&to_ptr, seq_p); + gimplify_arg (&to_ptr, seq_p, EXPR_LOCATION (*expr_p)); t = implicit_built_in_decls[BUILT_IN_MEMSET]; gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size); @@ -3320,9 +3383,9 @@ gimplify_init_ctor_eval_range (tree object, tree lower, tree upper, tree loop_entry_label, loop_exit_label, fall_thru_label; tree var, var_type, cref, tmp; - loop_entry_label = create_artificial_label (); - loop_exit_label = create_artificial_label (); - fall_thru_label = create_artificial_label (); + loop_entry_label = create_artificial_label (UNKNOWN_LOCATION); + loop_exit_label = create_artificial_label (UNKNOWN_LOCATION); + fall_thru_label = create_artificial_label (UNKNOWN_LOCATION); /* Create and initialize the index variable. */ var_type = TREE_TYPE (upper); @@ -3482,15 +3545,90 @@ 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 + the DECL_EXPR before the current statement and using its anonymous + decl instead. */ + +static enum gimplify_status +gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p) +{ + tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (*expr_p); + tree decl = DECL_EXPR_DECL (decl_s); + /* Mark the decl as addressable if the compound literal + expression is addressable now, otherwise it is marked too late + after we gimplify the initialization expression. */ + if (TREE_ADDRESSABLE (*expr_p)) + TREE_ADDRESSABLE (decl) = 1; + + /* Preliminarily mark non-addressed complex variables as eligible + for promotion to gimple registers. We'll transform their uses + as we find them. */ + if ((TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE + || TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE) + && !TREE_THIS_VOLATILE (decl) + && !needs_to_live_in_memory (decl)) + DECL_GIMPLE_REG_P (decl) = 1; + + /* This decl isn't mentioned in the enclosing block, so add it to the + list of temps. FIXME it seems a bit of a kludge to say that + anonymous artificial vars aren't pushed, but everything else is. */ + if (DECL_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl)) + gimple_add_tmp_var (decl); + + gimplify_and_add (decl_s, pre_p); + *expr_p = decl; + return GS_OK; +} + +/* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR, + return a new CONSTRUCTOR if something changed. */ + +static tree +optimize_compound_literals_in_ctor (tree orig_ctor) +{ + tree ctor = orig_ctor; + VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS (ctor); + unsigned int idx, num = VEC_length (constructor_elt, elts); + + for (idx = 0; idx < num; idx++) + { + tree value = VEC_index (constructor_elt, elts, idx)->value; + tree newval = value; + if (TREE_CODE (value) == CONSTRUCTOR) + newval = optimize_compound_literals_in_ctor (value); + else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR) + { + tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (value); + tree decl = DECL_EXPR_DECL (decl_s); + tree init = DECL_INITIAL (decl); + + if (!TREE_ADDRESSABLE (value) + && !TREE_ADDRESSABLE (decl) + && init) + newval = optimize_compound_literals_in_ctor (init); + } + if (newval == value) + continue; + + if (ctor == orig_ctor) + { + ctor = copy_node (orig_ctor); + CONSTRUCTOR_ELTS (ctor) = VEC_copy (constructor_elt, gc, elts); + elts = CONSTRUCTOR_ELTS (ctor); + } + VEC_index (constructor_elt, elts, idx)->value = newval; + } + return ctor; } + /* A subroutine of gimplify_modify_expr. Break out elements of a CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs. @@ -3508,14 +3646,11 @@ static enum gimplify_status gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, bool want_value, bool notify_temp_creation) { - tree object; - tree ctor = TREE_OPERAND (*expr_p, 1); - tree type = TREE_TYPE (ctor); + tree object, ctor, type; enum gimplify_status ret; VEC(constructor_elt,gc) *elts; - if (TREE_CODE (ctor) != CONSTRUCTOR) - return GS_UNHANDLED; + gcc_assert (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR); if (!notify_temp_creation) { @@ -3526,6 +3661,9 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } object = TREE_OPERAND (*expr_p, 0); + ctor = TREE_OPERAND (*expr_p, 1) = + optimize_compound_literals_in_ctor (TREE_OPERAND (*expr_p, 1)); + type = TREE_TYPE (ctor); elts = CONSTRUCTOR_ELTS (ctor); ret = GS_ALL_DONE; @@ -3563,7 +3701,8 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, if (valid_const_initializer && num_nonzero_elements > 1 && TREE_READONLY (object) - && TREE_CODE (object) == VAR_DECL) + && TREE_CODE (object) == VAR_DECL + && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object))) { if (notify_temp_creation) return GS_ERROR; @@ -3619,8 +3758,13 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, be dropped to memory, and then memcpy'd out. Don't do this for sparse arrays, though, as it's more efficient to follow the standard CONSTRUCTOR behavior of memset followed by - individual element initialization. */ - if (valid_const_initializer && !cleared) + individual element initialization. Also don't do this for small + all-zero initializers (which aren't big enough to merit + clearing), and don't try to make bitwise copies of + TREE_ADDRESSABLE types. */ + if (valid_const_initializer + && !(cleared || num_nonzero_elements == 0) + && !TREE_ADDRESSABLE (type)) { HOST_WIDE_INT size = int_size_in_bytes (type); unsigned int align; @@ -3642,7 +3786,9 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, else align = TYPE_ALIGN (type); - if (size > 0 && !can_move_by_pieces (size, align)) + if (size > 0 + && num_nonzero_elements > 1 + && !can_move_by_pieces (size, align)) { tree new_tree; @@ -3918,11 +4064,14 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, switch (TREE_CODE (*from_p)) { case VAR_DECL: - /* If we're assigning from a constant constructor, move the - constructor expression to the RHS of the MODIFY_EXPR. */ + /* If we're assigning from a read-only variable initialized with + a constructor, do the direct assignment from the constructor, + but only if neither source nor target are volatile since this + latter assignment might end up being done on a per-field basis. */ if (DECL_INITIAL (*from_p) && TREE_READONLY (*from_p) && !TREE_THIS_VOLATILE (*from_p) + && !TREE_THIS_VOLATILE (*to_p) && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR) { tree old_from = *from_p; @@ -4068,11 +4217,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. */ @@ -4125,6 +4269,26 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, return GS_OK; } + case COMPOUND_LITERAL_EXPR: + { + tree complit = TREE_OPERAND (*expr_p, 1); + tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit); + tree decl = DECL_EXPR_DECL (decl_s); + tree init = DECL_INITIAL (decl); + + /* struct T x = (struct T) { 0, 1, 2 } can be optimized + into struct T x = { 0, 1, 2 } if the address of the + compound literal has never been taken. */ + if (!TREE_ADDRESSABLE (complit) + && !TREE_ADDRESSABLE (decl) + && init) + { + *expr_p = copy_node (*expr_p); + TREE_OPERAND (*expr_p, 1) = init; + return GS_OK; + } + } + default: ret = GS_UNHANDLED; break; @@ -4318,7 +4482,10 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, gimple_call_set_lhs (assign, *to_p); } else - assign = gimple_build_assign (*to_p, *from_p); + { + assign = gimple_build_assign (*to_p, *from_p); + gimple_set_location (assign, EXPR_LOCATION (*expr_p)); + } gimplify_seq_add_stmt (pre_p, assign); @@ -4393,13 +4560,11 @@ gimplify_scalar_mode_aggregate_compare (tree *expr_p) a && b ? true : false - gimplify_cond_expr will do the rest. - - PRE_P points to the list where side effects that must happen before - *EXPR_P should be stored. */ + LOCUS is the source location to be put on the generated COND_EXPR. + gimplify_cond_expr will do the rest. */ static enum gimplify_status -gimplify_boolean_expr (tree *expr_p) +gimplify_boolean_expr (tree *expr_p, location_t locus) { /* Preserve the original type of the expression. */ tree type = TREE_TYPE (*expr_p); @@ -4408,6 +4573,8 @@ gimplify_boolean_expr (tree *expr_p) fold_convert (type, boolean_true_node), fold_convert (type, boolean_false_node)); + SET_EXPR_LOCATION (*expr_p, locus); + return GS_OK; } @@ -4572,7 +4739,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); @@ -5276,8 +5443,8 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) switch (default_kind) { case OMP_CLAUSE_DEFAULT_NONE: - error ("%qs not specified in enclosing parallel", - IDENTIFIER_POINTER (DECL_NAME (decl))); + error ("%qE not specified in enclosing parallel", + DECL_NAME (decl)); error ("%Henclosing parallel", &ctx->location); /* FALLTHRU */ case OMP_CLAUSE_DEFAULT_SHARED: @@ -5334,6 +5501,20 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) goto do_outer; } + if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0 + && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN + && DECL_SIZE (decl) + && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) + { + splay_tree_node n2; + tree t = DECL_VALUE_EXPR (decl); + gcc_assert (TREE_CODE (t) == INDIRECT_REF); + t = TREE_OPERAND (t, 0); + gcc_assert (DECL_P (t)); + n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t); + n2->value |= GOVD_SEEN; + } + shared = ((flags | n->value) & GOVD_SHARED) != 0; ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared); @@ -5369,8 +5550,8 @@ omp_is_private (struct gimplify_omp_ctx *ctx, tree decl) { if (ctx == gimplify_omp_ctxp) { - error ("iteration variable %qs should be private", - IDENTIFIER_POINTER (DECL_NAME (decl))); + error ("iteration variable %qE should be private", + DECL_NAME (decl)); n->value = GOVD_PRIVATE; return true; } @@ -5383,11 +5564,11 @@ omp_is_private (struct gimplify_omp_ctx *ctx, tree decl) && gimplify_omp_ctxp->outer_context == ctx))) { if ((n->value & GOVD_FIRSTPRIVATE) != 0) - error ("iteration variable %qs should not be firstprivate", - IDENTIFIER_POINTER (DECL_NAME (decl))); + error ("iteration variable %qE should not be firstprivate", + DECL_NAME (decl)); else if ((n->value & GOVD_REDUCTION) != 0) - error ("iteration variable %qs should not be reduction", - IDENTIFIER_POINTER (DECL_NAME (decl))); + error ("iteration variable %qE should not be reduction", + DECL_NAME (decl)); } return (ctx == gimplify_omp_ctxp || (ctx->region_type == ORT_COMBINED_PARALLEL @@ -5549,8 +5730,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, && region_type == ORT_WORKSHARE && omp_check_private (ctx, decl)) { - error ("%s variable %qs is private in outer context", - check_non_private, IDENTIFIER_POINTER (DECL_NAME (decl))); + error ("%s variable %qE is private in outer context", + check_non_private, DECL_NAME (decl)); remove = true; } break; @@ -5644,7 +5825,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data) else gcc_unreachable (); - clause = build_omp_clause (code); + clause = build_omp_clause (input_location, code); OMP_CLAUSE_DECL (clause) = decl; OMP_CLAUSE_CHAIN (clause) = *list_p; if (private_debug) @@ -5806,7 +5987,8 @@ static enum gimplify_status gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) { tree for_stmt, decl, var, t; - enum gimplify_status ret = GS_OK; + enum gimplify_status ret = GS_ALL_DONE; + enum gimplify_status tret; gimple gfor; gimple_seq for_body, for_pre_body; int i; @@ -5856,8 +6038,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) else var = decl; - ret |= gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, + tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, is_gimple_val, fb_rvalue); + ret = MIN (ret, tret); if (ret == GS_ERROR) return ret; @@ -5866,8 +6049,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) gcc_assert (COMPARISON_CLASS_P (t)); gcc_assert (TREE_OPERAND (t, 0) == decl); - ret |= gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, + tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, is_gimple_val, fb_rvalue); + ret = MIN (ret, tret); /* Handle OMP_FOR_INCR. */ t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i); @@ -5914,8 +6098,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) gcc_unreachable (); } - ret |= gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, + tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL, is_gimple_val, fb_rvalue); + ret = MIN (ret, tret); break; default: @@ -6059,12 +6244,27 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr, switch (TREE_CODE_CLASS (TREE_CODE (expr))) { case tcc_binary: + case tcc_comparison: saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr, lhs_var); case tcc_unary: saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr, lhs_var); break; + case tcc_expression: + switch (TREE_CODE (expr)) + { + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, + lhs_addr, lhs_var); + saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, + lhs_addr, lhs_var); + break; + default: + break; + } + break; default: break; } @@ -6215,16 +6415,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 @@ -6289,7 +6485,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } /* Do any language-specific gimplification. */ - ret = lang_hooks.gimplify_expr (expr_p, pre_p, post_p); + ret = ((enum gimplify_status) + lang_hooks.gimplify_expr (expr_p, pre_p, post_p)); if (ret == GS_OK) { if (*expr_p == NULL_TREE) @@ -6358,6 +6555,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none); break; + case COMPOUND_LITERAL_EXPR: + ret = gimplify_compound_literal_expr (expr_p, pre_p); + break; + case MODIFY_EXPR: case INIT_EXPR: ret = gimplify_modify_expr (expr_p, pre_p, post_p, @@ -6366,7 +6567,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: - ret = gimplify_boolean_expr (expr_p); + /* Pass the source location of the outer expression. */ + ret = gimplify_boolean_expr (expr_p, saved_location); break; case TRUTH_NOT_EXPR: @@ -6573,6 +6775,24 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } break; + case TARGET_MEM_REF: + { + enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE; + + if (TMR_SYMBOL (*expr_p)) + r0 = gimplify_expr (&TMR_SYMBOL (*expr_p), pre_p, + post_p, is_gimple_lvalue, fb_either); + else if (TMR_BASE (*expr_p)) + r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p, + post_p, is_gimple_val, fb_either); + if (TMR_INDEX (*expr_p)) + r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p, + post_p, is_gimple_val, fb_rvalue); + /* TMR_STEP and TMR_OFFSET are always integer constants. */ + ret = MIN (r0, r1); + } + break; + case NON_LVALUE_EXPR: /* This should have been stripped above. */ gcc_unreachable (); @@ -6642,19 +6862,6 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, break; } - case CHANGE_DYNAMIC_TYPE_EXPR: - { - gimple cdt; - - ret = gimplify_expr (&CHANGE_DYNAMIC_TYPE_LOCATION (*expr_p), - pre_p, post_p, is_gimple_reg, fb_lvalue); - cdt = gimple_build_cdt (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*expr_p), - CHANGE_DYNAMIC_TYPE_LOCATION (*expr_p)); - gimplify_seq_add_stmt (pre_p, cdt); - ret = GS_ALL_DONE; - } - break; - case OBJ_TYPE_REF: { enum gimplify_status r0, r1; @@ -6768,8 +6975,9 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, */ if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST && (tmp = maybe_fold_offset_to_address - (TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1), - TREE_TYPE (*expr_p)))) + (EXPR_LOCATION (*expr_p), + TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1), + TREE_TYPE (*expr_p)))) { *expr_p = tmp; break; @@ -6780,10 +6988,11 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p, 0),0))) && (tmp = maybe_fold_offset_to_address - (TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0), - TREE_OPERAND (*expr_p, 1), - TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p, 0), - 0))))) + (EXPR_LOCATION (*expr_p), + TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0), + TREE_OPERAND (*expr_p, 1), + TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p, 0), + 0))))) { *expr_p = fold_convert (TREE_TYPE (*expr_p), tmp); break; @@ -6978,7 +7187,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, && code != ASM_EXPR && code != BIND_EXPR && code != CATCH_EXPR - && code != COND_EXPR + && (code != COND_EXPR || gimplify_ctxp->allow_rhs_cond_expr) && code != EH_FILTER_EXPR && code != GOTO_EXPR && code != LABEL_EXPR @@ -7023,7 +7232,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 @@ -7035,12 +7244,14 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, /* The postqueue might change the value of the expression between the initialization and use of the temporary, so we can't use a formal temp. FIXME do we care? */ - *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p); + { + *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p); + if (TREE_CODE (TREE_TYPE (*expr_p)) == COMPLEX_TYPE + || TREE_CODE (TREE_TYPE (*expr_p)) == VECTOR_TYPE) + DECL_GIMPLE_REG_P (*expr_p) = 1; + } 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 { @@ -7138,6 +7349,8 @@ gimplify_type_sizes (tree type, gimple_seq *list_p) if (TREE_CODE (field) == FIELD_DECL) { gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p); + gimplify_one_sizepos (&DECL_SIZE (field), list_p); + gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p); gimplify_type_sizes (TREE_TYPE (field), list_p); } break; @@ -7251,6 +7464,9 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms) unshare_body (body_p, fndecl); unvisit_body (body_p, fndecl); + if (cgraph_node (fndecl)->origin) + nonlocal_vlas = pointer_set_create (); + /* Make sure input_location isn't set to something weird. */ input_location = DECL_SOURCE_LOCATION (fndecl); @@ -7286,6 +7502,12 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms) gimple_bind_set_body (outer_bind, parm_stmts); } + if (nonlocal_vlas) + { + pointer_set_destroy (nonlocal_vlas); + nonlocal_vlas = NULL; + } + pop_gimplify_context (outer_bind); gcc_assert (gimplify_ctxp == NULL); @@ -7366,10 +7588,10 @@ gimplify_function_tree (tree fndecl) x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER]; gimplify_seq_add_stmt (&body, gimple_build_call (x, 0)); gimplify_seq_add_stmt (&body, tf); - new_bind = gimple_build_bind (NULL, body, gimple_block (bind)); + new_bind = gimple_build_bind (NULL, body, gimple_bind_block (bind)); /* Clear the block for BIND, since it is no longer directly inside the function, but within a try block. */ - gimple_set_block (bind, NULL); + gimple_bind_set_block (bind, NULL); /* Replace the current function body with the body wrapped in the try/finally TF. */ @@ -7410,6 +7632,10 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p) gimplify_expr (gimple_cond_rhs_ptr (stmt), &pre, NULL, is_gimple_val, fb_rvalue); break; + case GIMPLE_SWITCH: + gimplify_expr (gimple_switch_index_ptr (stmt), &pre, NULL, + is_gimple_val, fb_rvalue); + break; case GIMPLE_OMP_ATOMIC_LOAD: gimplify_expr (gimple_omp_atomic_load_rhs_ptr (stmt), &pre, NULL, is_gimple_val, fb_rvalue); @@ -7484,9 +7710,9 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p) } lhs = gimple_get_lhs (stmt); - /* If regimplification of the LHS changed it in a way that requires - a simple RHS, create temporary. */ - if (orig_lhs != lhs && !is_gimple_formal_tmp_var (lhs)) + /* If the LHS changed it in a way that requires a simple RHS, + create temporary. */ + if (lhs && !is_gimple_reg (lhs)) { bool need_temp = false; @@ -7535,7 +7761,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; @@ -7560,6 +7785,10 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p) break; } + if (gimple_referenced_vars (cfun)) + for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t)) + add_referenced_var (t); + if (!gimple_seq_empty_p (pre)) { if (gimple_in_ssa_p (cfun)) @@ -7574,10 +7803,6 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p) if (post_stmt) gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT); - if (gimple_referenced_vars (cfun)) - for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t)) - add_referenced_var (t); - pop_gimplify_context (NULL); }