X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fgimplify.c;h=50cfc45ea0b0b86bea2f6644db52e100372b1029;hb=12426f5d85c9da480c7c0c235f4b7393d6331806;hp=5559f0e3698257a3afa638c06eb71510982c1150;hpb=86638c2ef3b5ed40e2c8f19e5ce0cdbf86593413;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 5559f0e3698..50cfc45ea0b 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, 2009, 2010 + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Major work done by Sebastian Pop , Diego Novillo and Jason Merrill . @@ -39,7 +39,7 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "output.h" #include "ggc.h" -#include "toplev.h" +#include "diagnostic-core.h" #include "target.h" #include "pointer-set.h" #include "splay-tree.h" @@ -145,9 +145,11 @@ gimple_tree_eq (const void *p1, const void *p2) if (!operand_equal_p (t1, t2, 0)) return 0; +#ifdef ENABLE_CHECKING /* Only allow them to compare equal if they also hash equal; otherwise results are nondeterminate, and we fail bootstrap comparison. */ gcc_assert (gimple_tree_hash (p1) == gimple_tree_hash (p2)); +#endif return 1; } @@ -586,10 +588,7 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p, mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val)); - if (EXPR_HAS_LOCATION (val)) - SET_EXPR_LOCATION (mod, EXPR_LOCATION (val)); - else - SET_EXPR_LOCATION (mod, input_location); + SET_EXPR_LOCATION (mod, EXPR_LOC_OR_HERE (val)); /* gimplify_modify_expr might want to reduce this further. */ gimplify_and_add (mod, pre_p); @@ -652,7 +651,7 @@ declare_vars (tree vars, gimple scope, bool debug_info) gcc_assert (!block || TREE_CODE (block) == BLOCK); if (!block || !debug_info) { - TREE_CHAIN (last) = gimple_bind_vars (scope); + DECL_CHAIN (last) = gimple_bind_vars (scope); gimple_bind_set_vars (scope, temps); } else @@ -700,7 +699,7 @@ force_constant_size (tree var) void gimple_add_tmp_var (tree tmp) { - gcc_assert (!TREE_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp)); + gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp)); /* Later processing assumes that the object size is constant, which might not be true at this point. Force the use of a constant upper bound in @@ -713,7 +712,7 @@ gimple_add_tmp_var (tree tmp) if (gimplify_ctxp) { - TREE_CHAIN (tmp) = gimplify_ctxp->temps; + DECL_CHAIN (tmp) = gimplify_ctxp->temps; gimplify_ctxp->temps = tmp; /* Mark temporaries local within the nearest enclosing parallel. */ @@ -1132,14 +1131,14 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) tree temp = voidify_wrapper_expr (bind_expr, NULL); /* Mark variables seen in this bind expr. */ - for (t = BIND_EXPR_VARS (bind_expr); t ; t = TREE_CHAIN (t)) + for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t)) { if (TREE_CODE (t) == VAR_DECL) { struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; /* Mark variable as local. */ - if (ctx && !is_global_var (t) + if (ctx && !DECL_EXTERNAL (t) && (! DECL_SEEN_IN_BIND_EXPR_P (t) || splay_tree_lookup (ctx->variables, (splay_tree_key) t) == NULL)) @@ -1328,6 +1327,8 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p) t = built_in_decls[BUILT_IN_ALLOCA]; t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl)); + /* The call has been built for a variable-sized object. */ + ALLOCA_FOR_VAR_P (t) = 1; t = fold_convert (ptr_type, t); t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t); @@ -1369,6 +1370,14 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p) STACK_CHECK_MAX_VAR_SIZE) > 0)) gimplify_vla_decl (decl, seq_p); + /* Some front ends do not explicitly declare all anonymous + artificial variables. We compensate here by declaring the + variables, though it would be better if the front ends would + explicitly declare them. */ + if (!DECL_SEEN_IN_BIND_EXPR_P (decl) + && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE) + gimple_add_tmp_var (decl); + if (init && init != error_mark_node) { if (!TREE_STATIC (decl)) @@ -1383,14 +1392,6 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p) as they may contain a label address. */ walk_tree (&init, force_labels_r, NULL, NULL); } - - /* Some front ends do not explicitly declare all anonymous - artificial variables. We compensate here by declaring the - variables, though it would be better if the front ends would - explicitly declare them. */ - if (!DECL_SEEN_IN_BIND_EXPR_P (decl) - && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE) - gimple_add_tmp_var (decl); } return GS_ALL_DONE; @@ -1473,9 +1474,7 @@ compare_case_labels (const void *p1, const void *p2) void sort_case_labels (VEC(tree,heap)* label_vec) { - size_t len = VEC_length (tree, label_vec); - qsort (VEC_address (tree, label_vec), len, sizeof (tree), - compare_case_labels); + VEC_qsort (tree, label_vec, compare_case_labels); } @@ -1901,7 +1900,7 @@ gimplify_var_or_parm_decl (tree *expr_p) SET_DECL_RTL (copy, 0); TREE_USED (copy) = 1; block = DECL_INITIAL (current_function_decl); - TREE_CHAIN (copy) = BLOCK_VARS (block); + DECL_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; @@ -2009,8 +2008,14 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = MIN (ret, tret); } } + else + { + tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, + is_gimple_reg, fb_rvalue); + ret = MIN (ret, tret); + } - if (!TREE_OPERAND (t, 3)) + if (TREE_OPERAND (t, 3) == NULL_TREE) { tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0))); tree elmt_size = unshare_expr (array_ref_element_size (t)); @@ -2029,11 +2034,17 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = MIN (ret, tret); } } + else + { + tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p, + is_gimple_reg, fb_rvalue); + ret = MIN (ret, tret); + } } else if (TREE_CODE (t) == COMPONENT_REF) { /* Set the field offset into T and gimplify it. */ - if (!TREE_OPERAND (t, 2)) + if (TREE_OPERAND (t, 2) == NULL_TREE) { tree offset = unshare_expr (component_ref_field_offset (t)); tree field = TREE_OPERAND (t, 1); @@ -2052,6 +2063,12 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = MIN (ret, tret); } } + else + { + tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p, + is_gimple_reg, fb_rvalue); + ret = MIN (ret, tret); + } } } @@ -2476,8 +2493,11 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) { /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we have to do is replicate it as a GIMPLE_CALL tuple. */ + gimple_stmt_iterator gsi; call = gimple_build_call_from_tree (*expr_p); gimplify_seq_add_stmt (pre_p, call); + gsi = gsi_last (*pre_p); + fold_stmt (&gsi); *expr_p = NULL_TREE; } @@ -2553,7 +2573,9 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p, new_locus); append_to_statement_list (t, &expr); } - else if (TREE_CODE (pred) == COND_EXPR) + else if (TREE_CODE (pred) == COND_EXPR + && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 1))) + && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 2)))) { location_t new_locus; @@ -2561,7 +2583,10 @@ shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p, if (a) if (b) goto yes; else goto no; else - if (c) goto yes; else goto no; */ + if (c) goto yes; else goto no; + + Don't do this if one of the arms has void type, which can happen + in C++ when the arm is throw. */ /* Keep the original source location on the first 'if'. Set the source location of the ? on the second 'if'. */ @@ -2616,8 +2641,7 @@ shortcut_cond_expr (tree expr) 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; + location_t locus = EXPR_LOC_OR_HERE (expr); TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1); /* Set the source location of the && on the second 'if'. */ if (EXPR_HAS_LOCATION (pred)) @@ -2639,8 +2663,7 @@ shortcut_cond_expr (tree expr) 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; + location_t locus = EXPR_LOC_OR_HERE (expr); TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1); /* Set the source location of the || on the second 'if'. */ if (EXPR_HAS_LOCATION (pred)) @@ -2704,8 +2727,7 @@ 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, - EXPR_HAS_LOCATION (expr) - ? EXPR_LOCATION (expr) : input_location); + EXPR_LOC_OR_HERE (expr)); /* If our last subexpression already has a terminal label, reuse it. */ if (else_se) @@ -2737,8 +2759,7 @@ shortcut_cond_expr (tree expr) jump_over_else = block_may_fallthru (then_); pred = shortcut_cond_r (pred, true_label_p, false_label_p, - EXPR_HAS_LOCATION (expr) - ? EXPR_LOCATION (expr) : input_location); + EXPR_LOC_OR_HERE (expr)); expr = NULL; append_to_statement_list (pred, &expr); @@ -3327,7 +3348,7 @@ gimplify_init_ctor_preeval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, constructor_elt *ce; VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (*expr_p); - for (ix = 0; VEC_iterate (constructor_elt, v, ix, ce); ix++) + FOR_EACH_VEC_ELT (constructor_elt, v, ix, ce) gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data); return; @@ -3821,11 +3842,12 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } } - /* If the target is volatile and we have non-zero elements - initialize the target from a temporary. */ + /* If the target is volatile, we have non-zero elements and more than + one field to assign, initialize the target from a temporary. */ if (TREE_THIS_VOLATILE (object) && !TREE_ADDRESSABLE (type) - && num_nonzero_elements > 0) + && num_nonzero_elements > 0 + && VEC_length (constructor_elt, elts) > 1) { tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type), NULL); TREE_OPERAND (*expr_p, 0) = temp; @@ -3887,7 +3909,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, i = VEC_index (constructor_elt, elts, 1)->value; if (r == NULL || i == NULL) { - tree zero = fold_convert (TREE_TYPE (type), integer_zero_node); + tree zero = build_zero_cst (TREE_TYPE (type)); if (r == NULL) r = zero; if (i == NULL) @@ -3956,7 +3978,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, /* Vector types use CONSTRUCTOR all the way through gimple compilation as a general initializer. */ - for (ix = 0; VEC_iterate (constructor_elt, elts, ix, ce); ix++) + FOR_EACH_VEC_ELT (constructor_elt, elts, ix, ce) { enum gimplify_status tret; tret = gimplify_expr (&ce->value, pre_p, post_p, is_gimple_val, @@ -4193,9 +4215,18 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, This kind of code arises in C++ when an object is bound to a const reference, and if "x" is a TARGET_EXPR we want to take advantage of the optimization below. */ + bool volatile_p = TREE_THIS_VOLATILE (*from_p); tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0)); if (t) { + if (TREE_THIS_VOLATILE (t) != volatile_p) + { + if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration) + t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p), + build_fold_addr_expr (t)); + if (REFERENCE_CLASS_P (t)) + TREE_THIS_VOLATILE (t) = volatile_p; + } *from_p = t; ret = GS_OK; changed = true; @@ -4236,6 +4267,10 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, break; case CONSTRUCTOR: + /* If we already made some changes, let the front end have a + crack at this before we break it down. */ + if (ret != GS_UNHANDLED) + break; /* If we're initializing from a CONSTRUCTOR, break this into individual MODIFY_EXPRs. */ return gimplify_init_constructor (expr_p, pre_p, post_p, want_value, @@ -4559,7 +4594,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, /* Try to alleviate the effects of the gimplification creating artificial temporaries (see for example is_gimple_reg_rhs) on the debug info. */ if (!gimplify_ctxp->into_ssa - && DECL_P (*from_p) + && TREE_CODE (*from_p) == VAR_DECL && DECL_IGNORED_P (*from_p) && DECL_P (*to_p) && !DECL_IGNORED_P (*to_p)) @@ -4571,6 +4606,9 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, SET_DECL_DEBUG_EXPR (*from_p, *to_p); } + if (want_value && TREE_THIS_VOLATILE (*to_p)) + *from_p = get_initialized_tmp_var (*from_p, pre_p, post_p); + if (TREE_CODE (*from_p) == CALL_EXPR) { /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL @@ -4598,7 +4636,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, if (want_value) { - *expr_p = unshare_expr (*to_p); + *expr_p = TREE_THIS_VOLATILE (*to_p) ? *from_p : unshare_expr (*to_p); return GS_OK; } else @@ -4613,10 +4651,10 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, static enum gimplify_status gimplify_variable_sized_compare (tree *expr_p) { + location_t loc = EXPR_LOCATION (*expr_p); tree op0 = TREE_OPERAND (*expr_p, 0); tree op1 = TREE_OPERAND (*expr_p, 1); - tree t, arg, dest, src; - location_t loc = EXPR_LOCATION (*expr_p); + tree t, arg, dest, src, expr; arg = TYPE_SIZE_UNIT (TREE_TYPE (op0)); arg = unshare_expr (arg); @@ -4625,8 +4663,11 @@ gimplify_variable_sized_compare (tree *expr_p) dest = build_fold_addr_expr_loc (loc, op0); t = implicit_built_in_decls[BUILT_IN_MEMCMP]; t = build_call_expr_loc (loc, t, 3, dest, src, arg); - *expr_p + + expr = build2 (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node); + SET_EXPR_LOCATION (expr, loc); + *expr_p = expr; return GS_OK; } @@ -4780,7 +4821,6 @@ gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) switch (TREE_CODE (op0)) { case INDIRECT_REF: - case MISALIGNED_INDIRECT_REF: do_indirect_ref: /* Check if we are dealing with an expression of the form '&*ptr'. While the front end folds away '&*ptr' into 'ptr', these @@ -5050,6 +5090,13 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) /* If the operand is a memory input, it should be an lvalue. */ if (!allows_reg && allows_mem) { + tree inputv = TREE_VALUE (link); + STRIP_NOPS (inputv); + if (TREE_CODE (inputv) == PREDECREMENT_EXPR + || TREE_CODE (inputv) == PREINCREMENT_EXPR + || TREE_CODE (inputv) == POSTDECREMENT_EXPR + || TREE_CODE (inputv) == POSTINCREMENT_EXPR) + TREE_VALUE (link) = error_mark_node; tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p, is_gimple_lvalue, fb_lvalue | fb_mayfail); mark_addressable (TREE_VALUE (link)); @@ -5391,7 +5438,7 @@ omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type) case QUAL_UNION_TYPE: { tree field; - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL) { omp_firstprivatize_variable (ctx, DECL_FIELD_OFFSET (field)); @@ -5487,7 +5534,8 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags) For local variables TYPE_SIZE_UNIT might not be gimplified yet, in this case omp_notice_variable will be called later on when it is gimplified. */ - else if (! (flags & GOVD_LOCAL)) + else if (! (flags & GOVD_LOCAL) + && DECL_P (TYPE_SIZE_UNIT (TREE_TYPE (decl)))) omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true); } else if (lang_hooks.decls.omp_privatize_by_reference (decl)) @@ -6397,8 +6445,12 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr, { case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: + case TRUTH_AND_EXPR: + case TRUTH_OR_EXPR: + case TRUTH_XOR_EXPR: saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr, lhs_var); + case TRUTH_NOT_EXPR: saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr, lhs_var); break; @@ -6769,17 +6821,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, recalculate_side_effects (*expr_p); break; - case MISALIGNED_INDIRECT_REF: - /* We can only reach this through re-gimplification from - tree optimizers. */ - ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, - is_gimple_reg, fb_rvalue); - recalculate_side_effects (*expr_p); - break; - case INDIRECT_REF: { bool volatilep = TREE_THIS_VOLATILE (*expr_p); + bool notrap = TREE_THIS_NOTRAP (*expr_p); tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0)); *expr_p = fold_indirect_ref_loc (input_location, *expr_p); @@ -6791,13 +6836,16 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_gimple_reg, fb_rvalue); - recalculate_side_effects (*expr_p); + if (ret == GS_ERROR) + break; + recalculate_side_effects (*expr_p); *expr_p = fold_build2_loc (input_location, MEM_REF, TREE_TYPE (*expr_p), TREE_OPERAND (*expr_p, 0), build_int_cst (saved_ptr_type, 0)); TREE_THIS_VOLATILE (*expr_p) = volatilep; + TREE_THIS_NOTRAP (*expr_p) = notrap; ret = GS_OK; break; } @@ -6817,6 +6865,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_gimple_mem_ref_addr, fb_rvalue); + if (ret == GS_ERROR) + break; recalculate_side_effects (*expr_p); ret = GS_ALL_DONE; break; @@ -6910,14 +6960,11 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, if (fallback == fb_none) { unsigned HOST_WIDE_INT ix; - constructor_elt *ce; + tree val; tree temp = NULL_TREE; - for (ix = 0; - VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (*expr_p), - ix, ce); - ix++) - if (TREE_SIDE_EFFECTS (ce->value)) - append_to_statement_list (ce->value, &temp); + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (*expr_p), ix, val) + if (TREE_SIDE_EFFECTS (val)) + append_to_statement_list (val, &temp); *expr_p = temp; ret = temp ? GS_OK : GS_ALL_DONE; @@ -6965,15 +7012,15 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, { 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)) + if (TMR_BASE (*expr_p)) r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p, - post_p, is_gimple_val, fb_either); + post_p, is_gimple_mem_ref_addr, fb_either); if (TMR_INDEX (*expr_p)) r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p, post_p, is_gimple_val, fb_rvalue); + if (TMR_INDEX2 (*expr_p)) + r1 = gimplify_expr (&TMR_INDEX2 (*expr_p), pre_p, + post_p, is_gimple_val, fb_rvalue); /* TMR_STEP and TMR_OFFSET are always integer constants. */ ret = MIN (r0, r1); } @@ -7155,6 +7202,16 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = gimplify_omp_atomic (expr_p, pre_p); break; + case TRUTH_AND_EXPR: + case TRUTH_OR_EXPR: + case TRUTH_XOR_EXPR: + /* Classified as tcc_expression. */ + goto expr_2; + + case FMA_EXPR: + /* Classified as tcc_expression. */ + goto expr_3; + case POINTER_PLUS_EXPR: /* Convert ((type *)A)+offset into &A->field_of_type_and_offset. The second is gimple immediate saving a need for extra statement. @@ -7234,16 +7291,28 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, break; } + expr_3: + { + enum gimplify_status r0, r1, r2; + + r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, + post_p, is_gimple_val, fb_rvalue); + r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, + post_p, is_gimple_val, fb_rvalue); + r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p, + post_p, is_gimple_val, fb_rvalue); + + ret = MIN (MIN (r0, r1), r2); + break; + } + case tcc_declaration: case tcc_constant: ret = GS_ALL_DONE; goto dont_recalculate; default: - gcc_assert (TREE_CODE (*expr_p) == TRUTH_AND_EXPR - || TREE_CODE (*expr_p) == TRUTH_OR_EXPR - || TREE_CODE (*expr_p) == TRUTH_XOR_EXPR); - goto expr_2; + gcc_unreachable (); } recalculate_side_effects (*expr_p); @@ -7516,7 +7585,10 @@ gimplify_type_sizes (tree type, gimple_seq *list_p) /* Ensure VLA bounds aren't removed, for -O0 they should be variables with assigned stack slots, for -O1+ -g they should be tracked by VTA. */ - if (TYPE_DOMAIN (type) + if (!(TYPE_NAME (type) + && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_IGNORED_P (TYPE_NAME (type))) + && TYPE_DOMAIN (type) && INTEGRAL_TYPE_P (TYPE_DOMAIN (type))) { t = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); @@ -7531,7 +7603,7 @@ gimplify_type_sizes (tree type, gimple_seq *list_p) case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL) { gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p); @@ -7613,10 +7685,7 @@ gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p) *expr_p = create_tmp_var (type, NULL); tmp = build1 (NOP_EXPR, type, expr); stmt = gimplify_assign (*expr_p, tmp, stmt_p); - if (EXPR_HAS_LOCATION (expr)) - gimple_set_location (stmt, EXPR_LOCATION (expr)); - else - gimple_set_location (stmt, input_location); + gimple_set_location (stmt, EXPR_LOC_OR_HERE (expr)); } } @@ -7690,7 +7759,7 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms) gimple_bind_set_body (outer_bind, parm_stmts); for (parm = DECL_ARGUMENTS (current_function_decl); - parm; parm = TREE_CHAIN (parm)) + parm; parm = DECL_CHAIN (parm)) if (DECL_HAS_VALUE_EXPR_P (parm)) { DECL_HAS_VALUE_EXPR_P (parm) = 0; @@ -7718,6 +7787,46 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms) return outer_bind; } +typedef char *char_p; /* For DEF_VEC_P. */ +DEF_VEC_P(char_p); +DEF_VEC_ALLOC_P(char_p,heap); + +/* Return whether we should exclude FNDECL from instrumentation. */ + +static bool +flag_instrument_functions_exclude_p (tree fndecl) +{ + VEC(char_p,heap) *vec; + + vec = (VEC(char_p,heap) *) flag_instrument_functions_exclude_functions; + if (VEC_length (char_p, vec) > 0) + { + const char *name; + int i; + char *s; + + name = lang_hooks.decl_printable_name (fndecl, 0); + FOR_EACH_VEC_ELT (char_p, vec, i, s) + if (strstr (name, s) != NULL) + return true; + } + + vec = (VEC(char_p,heap) *) flag_instrument_functions_exclude_files; + if (VEC_length (char_p, vec) > 0) + { + const char *name; + int i; + char *s; + + name = DECL_SOURCE_FILE (fndecl); + FOR_EACH_VEC_ELT (char_p, vec, i, s) + if (strstr (name, s) != NULL) + return true; + } + + return false; +} + /* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL node for the function we want to gimplify. @@ -7740,7 +7849,7 @@ gimplify_function_tree (tree fndecl) else push_struct_function (fndecl); - for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = TREE_CHAIN (parm)) + for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = DECL_CHAIN (parm)) { /* Preliminarily mark non-addressed complex variables as eligible for promotion to gimple registers. We'll transform their uses @@ -7778,13 +7887,31 @@ gimplify_function_tree (tree fndecl) gimple new_bind; gimple tf; gimple_seq cleanup = NULL, body = NULL; - + tree tmp_var; + gimple call; + + x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS]; + call = gimple_build_call (x, 1, integer_zero_node); + tmp_var = create_tmp_var (ptr_type_node, "return_addr"); + gimple_call_set_lhs (call, tmp_var); + gimplify_seq_add_stmt (&cleanup, call); x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT]; - gimplify_seq_add_stmt (&cleanup, gimple_build_call (x, 0)); + call = gimple_build_call (x, 2, + build_fold_addr_expr (current_function_decl), + tmp_var); + gimplify_seq_add_stmt (&cleanup, call); tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY); + x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS]; + call = gimple_build_call (x, 1, integer_zero_node); + tmp_var = create_tmp_var (ptr_type_node, "return_addr"); + gimple_call_set_lhs (call, tmp_var); + gimplify_seq_add_stmt (&body, call); x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER]; - gimplify_seq_add_stmt (&body, gimple_build_call (x, 0)); + call = gimple_build_call (x, 2, + build_fold_addr_expr (current_function_decl), + tmp_var); + gimplify_seq_add_stmt (&body, call); gimplify_seq_add_stmt (&body, tf); new_bind = gimple_build_bind (NULL, body, gimple_bind_block (bind)); /* Clear the block for BIND, since it is no longer directly inside @@ -7996,26 +8123,27 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p) } -/* Expands EXPR to list of gimple statements STMTS. If SIMPLE is true, - force the result to be either ssa_name or an invariant, otherwise - just force it to be a rhs expression. If VAR is not NULL, make the +/* Expands EXPR to list of gimple statements STMTS. GIMPLE_TEST_F specifies + the predicate that will hold for the result. If VAR is not NULL, make the base variable of the final destination be VAR if suitable. */ tree -force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var) +force_gimple_operand_1 (tree expr, gimple_seq *stmts, + gimple_predicate gimple_test_f, tree var) { tree t; enum gimplify_status ret; - gimple_predicate gimple_test_f; struct gimplify_ctx gctx; *stmts = NULL; - if (is_gimple_val (expr)) + /* gimple_test_f might be more strict than is_gimple_val, make + sure we pass both. Just checking gimple_test_f doesn't work + because most gimple predicates do not work recursively. */ + if (is_gimple_val (expr) + && (*gimple_test_f) (expr)) return expr; - gimple_test_f = simple ? is_gimple_val : is_gimple_reg_rhs; - push_gimplify_context (&gctx); gimplify_ctxp->into_ssa = gimple_in_ssa_p (cfun); gimplify_ctxp->allow_rhs_cond_expr = true; @@ -8036,7 +8164,7 @@ force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var) } if (gimple_referenced_vars (cfun)) - for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t)) + for (t = gimplify_ctxp->temps; t ; t = DECL_CHAIN (t)) add_referenced_var (t); pop_gimplify_context (NULL); @@ -8044,20 +8172,34 @@ force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var) return expr; } -/* Invokes force_gimple_operand for EXPR with parameters SIMPLE_P and VAR. If - some statements are produced, emits them at GSI. If BEFORE is true. - the statements are appended before GSI, otherwise they are appended after - it. M specifies the way GSI moves after insertion (GSI_SAME_STMT or - GSI_CONTINUE_LINKING are the usual values). */ +/* Expands EXPR to list of gimple statements STMTS. If SIMPLE is true, + force the result to be either ssa_name or an invariant, otherwise + just force it to be a rhs expression. If VAR is not NULL, make the + base variable of the final destination be VAR if suitable. */ tree -force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr, - bool simple_p, tree var, bool before, - enum gsi_iterator_update m) +force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var) +{ + return force_gimple_operand_1 (expr, stmts, + simple ? is_gimple_val : is_gimple_reg_rhs, + var); +} + +/* Invokes force_gimple_operand_1 for EXPR with parameters GIMPLE_TEST_F + and VAR. If some statements are produced, emits them at GSI. + If BEFORE is true. the statements are appended before GSI, otherwise + they are appended after it. M specifies the way GSI moves after + insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING are the usual values). */ + +tree +force_gimple_operand_gsi_1 (gimple_stmt_iterator *gsi, tree expr, + gimple_predicate gimple_test_f, + tree var, bool before, + enum gsi_iterator_update m) { gimple_seq stmts; - expr = force_gimple_operand (expr, &stmts, simple_p, var); + expr = force_gimple_operand_1 (expr, &stmts, gimple_test_f, var); if (!gimple_seq_empty_p (stmts)) { @@ -8078,4 +8220,24 @@ force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr, return expr; } +/* Invokes force_gimple_operand_1 for EXPR with parameter VAR. + If SIMPLE is true, force the result to be either ssa_name or an invariant, + otherwise just force it to be a rhs expression. If some statements are + produced, emits them at GSI. If BEFORE is true, the statements are + appended before GSI, otherwise they are appended after it. M specifies + the way GSI moves after insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING + are the usual values). */ + +tree +force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr, + bool simple_p, tree var, bool before, + enum gsi_iterator_update m) +{ + return force_gimple_operand_gsi_1 (gsi, expr, + simple_p + ? is_gimple_val : is_gimple_reg_rhs, + var, before, m); +} + + #include "gt-gimplify.h"