diff options
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r-- | gcc/tree-inline.c | 392 |
1 files changed, 171 insertions, 221 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index f1470d7a384..dc09c29b6ea 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -23,7 +23,8 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" -#include "toplev.h" +#include "toplev.h" /* floor_log2 */ +#include "diagnostic-core.h" #include "tree.h" #include "tree-inline.h" #include "flags.h" @@ -113,7 +114,7 @@ eni_weights eni_time_weights; /* Prototypes. */ -static tree declare_return_variable (copy_body_data *, tree, tree); +static tree declare_return_variable (copy_body_data *, tree, tree, basic_block); static void remap_block (tree *, copy_body_data *); static void copy_bind_expr (tree *, int *, copy_body_data *); static tree mark_local_for_remap_r (tree *, int *, void *); @@ -421,11 +422,11 @@ remap_type_1 (tree type, copy_body_data *id) { tree f, nf = NULL; - for (f = TYPE_FIELDS (new_tree); f ; f = TREE_CHAIN (f)) + for (f = TYPE_FIELDS (new_tree); f ; f = DECL_CHAIN (f)) { t = remap_decl (f, id); DECL_CONTEXT (t) = new_tree; - TREE_CHAIN (t) = nf; + DECL_CHAIN (t) = nf; nf = t; } TYPE_FIELDS (new_tree) = nreverse (nf); @@ -536,7 +537,7 @@ remap_decls (tree decls, VEC(tree,gc) **nonlocalized_list, copy_body_data *id) tree new_decls = NULL_TREE; /* Remap its variables. */ - for (old_var = decls; old_var; old_var = TREE_CHAIN (old_var)) + for (old_var = decls; old_var; old_var = DECL_CHAIN (old_var)) { tree new_var; @@ -545,8 +546,7 @@ remap_decls (tree decls, VEC(tree,gc) **nonlocalized_list, copy_body_data *id) if (TREE_CODE (old_var) == VAR_DECL && ! DECL_EXTERNAL (old_var) && (var_ann (old_var) || !gimple_in_ssa_p (cfun))) - cfun->local_decls = tree_cons (NULL_TREE, old_var, - cfun->local_decls); + add_local_decl (cfun, old_var); if ((!optimize || debug_info_level > DINFO_LEVEL_TERSE) && !DECL_IGNORED_P (old_var) && nonlocalized_list) @@ -573,7 +573,7 @@ remap_decls (tree decls, VEC(tree,gc) **nonlocalized_list, copy_body_data *id) else { gcc_assert (DECL_P (new_var)); - TREE_CHAIN (new_var) = new_decls; + DECL_CHAIN (new_var) = new_decls; new_decls = new_var; /* Also copy value-expressions. */ @@ -811,48 +811,55 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data) { /* Otherwise, just copy the node. Note that copy_tree_r already knows not to copy VAR_DECLs, etc., so this is safe. */ - if (TREE_CODE (*tp) == INDIRECT_REF) + if (TREE_CODE (*tp) == MEM_REF) { - /* Get rid of *& from inline substitutions that can happen when a - pointer argument is an ADDR_EXPR. */ + /* We need to re-canonicalize MEM_REFs from inline substitutions + that can happen when a pointer argument is an ADDR_EXPR. */ tree decl = TREE_OPERAND (*tp, 0); tree *n; + /* See remap_ssa_name. */ + if (TREE_CODE (decl) == SSA_NAME + && TREE_CODE (SSA_NAME_VAR (decl)) == RESULT_DECL + && id->transform_return_to_modify) + decl = SSA_NAME_VAR (decl); + n = (tree *) pointer_map_contains (id->decl_map, decl); if (n) { - tree type, new_tree, old; - - /* If we happen to get an ADDR_EXPR in n->value, strip - it manually here as we'll eventually get ADDR_EXPRs - which lie about their types pointed to. In this case - build_fold_indirect_ref wouldn't strip the - INDIRECT_REF, but we absolutely rely on that. As - fold_indirect_ref does other useful transformations, - try that first, though. */ - type = TREE_TYPE (TREE_TYPE (*n)); - new_tree = unshare_expr (*n); - old = *tp; - *tp = gimple_fold_indirect_ref (new_tree); - if (!*tp) - { - if (TREE_CODE (new_tree) == ADDR_EXPR) - { - *tp = fold_indirect_ref_1 (EXPR_LOCATION (new_tree), - type, new_tree); - /* ??? We should either assert here or build - a VIEW_CONVERT_EXPR instead of blindly leaking - incompatible types to our IL. */ - if (! *tp) - *tp = TREE_OPERAND (new_tree, 0); - } - else - { - *tp = build1 (INDIRECT_REF, type, new_tree); - TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); - TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old); - } + tree old = *tp; + tree ptr = unshare_expr (*n); + tree tem; + if ((tem = maybe_fold_offset_to_reference (EXPR_LOCATION (*tp), + ptr, + TREE_OPERAND (*tp, 1), + TREE_TYPE (*tp))) + && TREE_THIS_VOLATILE (tem) == TREE_THIS_VOLATILE (old)) + { + tree *tem_basep = &tem; + while (handled_component_p (*tem_basep)) + tem_basep = &TREE_OPERAND (*tem_basep, 0); + if (TREE_CODE (*tem_basep) == MEM_REF) + *tem_basep + = build2 (MEM_REF, TREE_TYPE (*tem_basep), + TREE_OPERAND (*tem_basep, 0), + fold_convert (TREE_TYPE (TREE_OPERAND (*tp, 1)), + TREE_OPERAND (*tem_basep, 1))); + else + *tem_basep + = build2 (MEM_REF, TREE_TYPE (*tem_basep), + build_fold_addr_expr (*tem_basep), + build_int_cst + (TREE_TYPE (TREE_OPERAND (*tp, 1)), 0)); + *tp = tem; } + else + { + *tp = fold_build2 (MEM_REF, TREE_TYPE (*tp), + ptr, TREE_OPERAND (*tp, 1)); + TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); + } + TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old); *walk_subtrees = 0; return NULL; } @@ -887,7 +894,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data) else if (TREE_CODE (*tp) == ADDR_EXPR) { /* Variable substitution need not be simple. In particular, - the INDIRECT_REF substitution above. Make sure that + the MEM_REF substitution above. Make sure that TREE_CONSTANT and friends are up-to-date. But make sure to not improperly set TREE_BLOCK on some sub-expressions. */ int invariant = is_gimple_min_invariant (*tp); @@ -895,13 +902,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data) id->block = NULL_TREE; walk_tree (&TREE_OPERAND (*tp, 0), remap_gimple_op_r, data, NULL); id->block = block; - - /* Handle the case where we substituted an INDIRECT_REF - into the operand of the ADDR_EXPR. */ - if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF) - *tp = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0); - else - recompute_tree_invariant_for_addr_expr (*tp); + recompute_tree_invariant_for_addr_expr (*tp); /* If this used to be invariant, but is not any longer, then regimplification is probably needed. */ @@ -1092,6 +1093,25 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) return NULL; } } + else if (TREE_CODE (*tp) == MEM_REF) + { + /* We need to re-canonicalize MEM_REFs from inline substitutions + that can happen when a pointer argument is an ADDR_EXPR. */ + tree decl = TREE_OPERAND (*tp, 0); + tree *n; + + n = (tree *) pointer_map_contains (id->decl_map, decl); + if (n) + { + tree old = *tp; + *tp = fold_build2 (MEM_REF, TREE_TYPE (*tp), + unshare_expr (*n), TREE_OPERAND (*tp, 1)); + TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old); + TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old); + *walk_subtrees = 0; + return NULL; + } + } /* Here is the "usual case". Copy this tree node, and then tweak some special cases. */ @@ -1222,7 +1242,10 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id) If RETVAL is just the result decl, the result decl has already been set (e.g. a recent "foo (&result_decl, ...)"); just toss the entire GIMPLE_RETURN. */ - if (retval && TREE_CODE (retval) != RESULT_DECL) + if (retval + && (TREE_CODE (retval) != RESULT_DECL + && (TREE_CODE (retval) != SSA_NAME + || TREE_CODE (SSA_NAME_VAR (retval)) != RESULT_DECL))) { copy = gimple_build_assign (id->retvar, retval); /* id->retvar is already substituted. Skip it on later remapping. */ @@ -1572,7 +1595,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, size_t nargs = gimple_call_num_args (id->gimple_call); size_t n; - for (p = DECL_ARGUMENTS (id->src_fn); p; p = TREE_CHAIN (p)) + for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p)) nargs--; /* Create the new array of arguments. */ @@ -1619,7 +1642,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, tree count, p; gimple new_stmt; - for (p = DECL_ARGUMENTS (id->src_fn); p; p = TREE_CHAIN (p)) + for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p)) nargs--; count = build_int_cst (integer_type_node, nargs); @@ -2530,7 +2553,7 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn, } /* Declare this new variable. */ - TREE_CHAIN (var) = *vars; + DECL_CHAIN (var) = *vars; *vars = var; /* Make gimplifier happy about this variable. */ @@ -2660,7 +2683,7 @@ initialize_inlined_parameters (copy_body_data *id, gimple stmt, /* Loop through the parameter declarations, replacing each with an equivalent VAR_DECL, appropriately initialized. */ - for (p = parms, i = 0; p; p = TREE_CHAIN (p), i++) + for (p = parms, i = 0; p; p = DECL_CHAIN (p), i++) { tree val; val = i < gimple_call_num_args (stmt) ? gimple_call_arg (stmt, i) : NULL; @@ -2670,25 +2693,26 @@ initialize_inlined_parameters (copy_body_data *id, gimple stmt, in a second loop over all parameters to appropriately remap variable sized arrays when the size is specified in a parameter following the array. */ - for (p = parms, i = 0; p; p = TREE_CHAIN (p), i++) + for (p = parms, i = 0; p; p = DECL_CHAIN (p), i++) { tree *varp = (tree *) pointer_map_contains (id->decl_map, p); if (varp && TREE_CODE (*varp) == VAR_DECL) { - tree def = (gimple_in_ssa_p (cfun) + tree def = (gimple_in_ssa_p (cfun) && is_gimple_reg (p) ? gimple_default_def (id->src_cfun, p) : NULL); - TREE_TYPE (*varp) = remap_type (TREE_TYPE (*varp), id); + tree var = *varp; + TREE_TYPE (var) = remap_type (TREE_TYPE (var), id); /* Also remap the default definition if it was remapped to the default definition of the parameter replacement by the parameter setup. */ - if (def && gimple_in_ssa_p (cfun) && is_gimple_reg (p)) + if (def) { tree *defp = (tree *) pointer_map_contains (id->decl_map, def); if (defp && TREE_CODE (*defp) == SSA_NAME - && SSA_NAME_VAR (*defp) == *varp) - TREE_TYPE (*defp) = TREE_TYPE (*varp); + && SSA_NAME_VAR (*defp) == var) + TREE_TYPE (*defp) = TREE_TYPE (var); } } } @@ -2721,7 +2745,8 @@ initialize_inlined_parameters (copy_body_data *id, gimple stmt, as seen by the caller. */ static tree -declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest) +declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest, + basic_block entry_bb) { tree callee = id->src_fn; tree caller = id->dst_fn; @@ -2839,9 +2864,7 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest) } DECL_SEEN_IN_BIND_EXPR_P (var) = 1; - DECL_STRUCT_FUNCTION (caller)->local_decls - = tree_cons (NULL_TREE, var, - DECL_STRUCT_FUNCTION (caller)->local_decls); + add_local_decl (DECL_STRUCT_FUNCTION (caller), var); /* Do not have the rest of GCC warn about this variable as it should not be visible to the user. */ @@ -2866,8 +2889,28 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest) done: /* Register the VAR_DECL as the equivalent for the RESULT_DECL; that way, when the RESULT_DECL is encountered, it will be - automatically replaced by the VAR_DECL. */ - insert_decl_map (id, result, var); + automatically replaced by the VAR_DECL. + + When returning by reference, ensure that RESULT_DECL remaps to + gimple_val. */ + if (DECL_BY_REFERENCE (result) + && !is_gimple_val (var)) + { + tree temp = create_tmp_var (TREE_TYPE (result), "retvalptr"); + if (gimple_in_ssa_p (id->src_cfun)) + { + get_var_ann (temp); + add_referenced_var (temp); + } + insert_decl_map (id, result, temp); + /* When RESULT_DECL is in SSA form, we need to use it's default_def + SSA_NAME. */ + if (gimple_in_ssa_p (id->src_cfun) && gimple_default_def (id->src_cfun, result)) + temp = remap_ssa_name (gimple_default_def (id->src_cfun, result), id); + insert_init_stmt (id, entry_bb, gimple_build_assign (temp, var)); + } + else + insert_decl_map (id, result, var); /* Remember this so we can ignore it in remap_decls. */ id->retvar = var; @@ -2900,7 +2943,8 @@ static const char * copy_forbidden (struct function *fun, tree fndecl) { const char *reason = fun->cannot_be_copied_reason; - tree step; + tree decl; + unsigned ix; /* Only examine the function once. */ if (fun->cannot_be_copied_set) @@ -2919,23 +2963,19 @@ copy_forbidden (struct function *fun, tree fndecl) goto fail; } - for (step = fun->local_decls; step; step = TREE_CHAIN (step)) - { - tree decl = TREE_VALUE (step); - - if (TREE_CODE (decl) == VAR_DECL - && TREE_STATIC (decl) - && !DECL_EXTERNAL (decl) - && DECL_INITIAL (decl) - && walk_tree_without_duplicates (&DECL_INITIAL (decl), - has_label_address_in_static_1, - fndecl)) - { - reason = G_("function %q+F can never be copied because it saves " - "address of local label in a static variable"); - goto fail; - } - } + FOR_EACH_LOCAL_DECL (fun, ix, decl) + if (TREE_CODE (decl) == VAR_DECL + && TREE_STATIC (decl) + && !DECL_EXTERNAL (decl) + && DECL_INITIAL (decl) + && walk_tree_without_duplicates (&DECL_INITIAL (decl), + has_label_address_in_static_1, + fndecl)) + { + reason = G_("function %q+F can never be copied because it saves " + "address of local label in a static variable"); + goto fail; + } fail: fun->cannot_be_copied_reason = reason; @@ -3438,105 +3478,13 @@ estimate_num_insns (gimple stmt, eni_weights *weights) if (POINTER_TYPE_P (funtype)) funtype = TREE_TYPE (funtype); - if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD) + if (is_simple_builtin (decl)) + return 0; + else if (is_inexpensive_builtin (decl)) cost = weights->target_builtin_call_cost; else cost = weights->call_cost; - if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) - switch (DECL_FUNCTION_CODE (decl)) - { - /* Builtins that expand to constants. */ - case BUILT_IN_CONSTANT_P: - case BUILT_IN_EXPECT: - case BUILT_IN_OBJECT_SIZE: - case BUILT_IN_UNREACHABLE: - /* Simple register moves or loads from stack. */ - case BUILT_IN_RETURN_ADDRESS: - case BUILT_IN_EXTRACT_RETURN_ADDR: - case BUILT_IN_FROB_RETURN_ADDR: - case BUILT_IN_RETURN: - case BUILT_IN_AGGREGATE_INCOMING_ADDRESS: - case BUILT_IN_FRAME_ADDRESS: - case BUILT_IN_VA_END: - case BUILT_IN_STACK_SAVE: - case BUILT_IN_STACK_RESTORE: - /* Exception state returns or moves registers around. */ - case BUILT_IN_EH_FILTER: - case BUILT_IN_EH_POINTER: - case BUILT_IN_EH_COPY_VALUES: - return 0; - - /* builtins that are not expensive (that is they are most probably - expanded inline into resonably simple code). */ - case BUILT_IN_ABS: - case BUILT_IN_ALLOCA: - case BUILT_IN_BSWAP32: - case BUILT_IN_BSWAP64: - case BUILT_IN_CLZ: - case BUILT_IN_CLZIMAX: - case BUILT_IN_CLZL: - case BUILT_IN_CLZLL: - case BUILT_IN_CTZ: - case BUILT_IN_CTZIMAX: - case BUILT_IN_CTZL: - case BUILT_IN_CTZLL: - case BUILT_IN_FFS: - case BUILT_IN_FFSIMAX: - case BUILT_IN_FFSL: - case BUILT_IN_FFSLL: - case BUILT_IN_IMAXABS: - case BUILT_IN_FINITE: - case BUILT_IN_FINITEF: - case BUILT_IN_FINITEL: - case BUILT_IN_FINITED32: - case BUILT_IN_FINITED64: - case BUILT_IN_FINITED128: - case BUILT_IN_FPCLASSIFY: - case BUILT_IN_ISFINITE: - case BUILT_IN_ISINF_SIGN: - case BUILT_IN_ISINF: - case BUILT_IN_ISINFF: - case BUILT_IN_ISINFL: - case BUILT_IN_ISINFD32: - case BUILT_IN_ISINFD64: - case BUILT_IN_ISINFD128: - case BUILT_IN_ISNAN: - case BUILT_IN_ISNANF: - case BUILT_IN_ISNANL: - case BUILT_IN_ISNAND32: - case BUILT_IN_ISNAND64: - case BUILT_IN_ISNAND128: - case BUILT_IN_ISNORMAL: - case BUILT_IN_ISGREATER: - case BUILT_IN_ISGREATEREQUAL: - case BUILT_IN_ISLESS: - case BUILT_IN_ISLESSEQUAL: - case BUILT_IN_ISLESSGREATER: - case BUILT_IN_ISUNORDERED: - case BUILT_IN_VA_ARG_PACK: - case BUILT_IN_VA_ARG_PACK_LEN: - case BUILT_IN_VA_COPY: - case BUILT_IN_TRAP: - case BUILT_IN_SAVEREGS: - case BUILT_IN_POPCOUNTL: - case BUILT_IN_POPCOUNTLL: - case BUILT_IN_POPCOUNTIMAX: - case BUILT_IN_POPCOUNT: - case BUILT_IN_PARITYL: - case BUILT_IN_PARITYLL: - case BUILT_IN_PARITYIMAX: - case BUILT_IN_PARITY: - case BUILT_IN_LABS: - case BUILT_IN_LLABS: - case BUILT_IN_PREFETCH: - cost = weights->target_builtin_call_cost; - break; - - default: - break; - } - if (decl) funtype = TREE_TYPE (decl); @@ -3557,7 +3505,7 @@ estimate_num_insns (gimple stmt, eni_weights *weights) if (decl && DECL_ARGUMENTS (decl) && !stdarg) { tree arg; - for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) + for (arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg)) if (!VOID_TYPE_P (TREE_TYPE (arg))) cost += estimate_move_cost (TREE_TYPE (arg)); } @@ -3722,6 +3670,26 @@ prepend_lexical_block (tree current_block, tree new_block) BLOCK_SUPERCONTEXT (new_block) = current_block; } +/* Add local variables from CALLEE to CALLER. */ + +static inline void +add_local_variables (struct function *callee, struct function *caller, + copy_body_data *id, bool check_var_ann) +{ + tree var; + unsigned ix; + + FOR_EACH_LOCAL_DECL (callee, ix, var) + if (TREE_STATIC (var) && !TREE_ASM_WRITTEN (var)) + { + if (!check_var_ann + || (var_ann (var) && add_referenced_var (var))) + add_local_decl (caller, var); + } + else if (!can_be_nonlocal (var, id)) + add_local_decl (caller, remap_decl (var, id)); +} + /* Fetch callee declaration from the call graph edge going from NODE and associated with STMR call statement. Return NULL_TREE if not found. */ static tree @@ -3754,8 +3722,6 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) gimple_stmt_iterator gsi, stmt_gsi; bool successfully_inlined = FALSE; bool purge_dead_abnormal_edges; - tree t_step; - tree var; /* Set input_location here so we get the right instantiation context if we call instantiate_decl from inlinable_function_p. */ @@ -3956,23 +3922,10 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) } /* Declare the return variable for the function. */ - use_retvar = declare_return_variable (id, return_slot, modify_dest); + use_retvar = declare_return_variable (id, return_slot, modify_dest, bb); /* Add local vars in this inlined callee to caller. */ - t_step = id->src_cfun->local_decls; - for (; t_step; t_step = TREE_CHAIN (t_step)) - { - var = TREE_VALUE (t_step); - if (TREE_STATIC (var) && !TREE_ASM_WRITTEN (var)) - { - if (var_ann (var) && add_referenced_var (var)) - cfun->local_decls = tree_cons (NULL_TREE, var, - cfun->local_decls); - } - else if (!can_be_nonlocal (var, id)) - cfun->local_decls = tree_cons (NULL_TREE, remap_decl (var, id), - cfun->local_decls); - } + add_local_variables (id->src_cfun, cfun, id, true); if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -4710,11 +4663,11 @@ static void declare_inline_vars (tree block, tree vars) { tree t; - for (t = vars; t; t = TREE_CHAIN (t)) + for (t = vars; t; t = DECL_CHAIN (t)) { DECL_SEEN_IN_BIND_EXPR_P (t) = 1; gcc_assert (!TREE_STATIC (t) && !TREE_ASM_WRITTEN (t)); - cfun->local_decls = tree_cons (NULL_TREE, t, cfun->local_decls); + add_local_decl (cfun, t); } if (block) @@ -4859,13 +4812,13 @@ copy_arguments_for_versioning (tree orig_parm, copy_body_data * id, parg = &new_parm; - for (arg = orig_parm; arg; arg = TREE_CHAIN (arg), i++) + for (arg = orig_parm; arg; arg = DECL_CHAIN (arg), i++) if (!args_to_skip || !bitmap_bit_p (args_to_skip, i)) { tree new_tree = remap_decl (arg, id); lang_hooks.dup_lang_specific_decl (new_tree); *parg = new_tree; - parg = &TREE_CHAIN (new_tree); + parg = &DECL_CHAIN (new_tree); } else if (!pointer_map_contains (id->decl_map, arg)) { @@ -4877,7 +4830,7 @@ copy_arguments_for_versioning (tree orig_parm, copy_body_data * id, add_referenced_var (var); insert_decl_map (id, arg, var); /* Declare this new variable. */ - TREE_CHAIN (var) = *vars; + DECL_CHAIN (var) = *vars; *vars = var; } return new_parm; @@ -4890,11 +4843,11 @@ copy_static_chain (tree static_chain, copy_body_data * id) tree *chain_copy, *pvar; chain_copy = &static_chain; - for (pvar = chain_copy; *pvar; pvar = &TREE_CHAIN (*pvar)) + for (pvar = chain_copy; *pvar; pvar = &DECL_CHAIN (*pvar)) { tree new_tree = remap_decl (*pvar, id); lang_hooks.dup_lang_specific_decl (new_tree); - TREE_CHAIN (new_tree) = TREE_CHAIN (*pvar); + DECL_CHAIN (new_tree) = DECL_CHAIN (*pvar); *pvar = new_tree; } return static_chain; @@ -5045,7 +4998,6 @@ tree_function_versioning (tree old_decl, tree new_decl, basic_block old_entry_block, bb; VEC (gimple, heap) *init_stmts = VEC_alloc (gimple, heap, 10); - tree t_step; tree old_current_function_decl = current_function_decl; tree vars = NULL_TREE; @@ -5129,7 +5081,7 @@ tree_function_versioning (tree old_decl, tree new_decl, { int i = replace_info->parm_num; tree parm; - for (parm = DECL_ARGUMENTS (old_decl); i; parm = TREE_CHAIN (parm)) + for (parm = DECL_ARGUMENTS (old_decl); i; parm = DECL_CHAIN (parm)) i --; replace_info->old_tree = parm; } @@ -5170,19 +5122,9 @@ tree_function_versioning (tree old_decl, tree new_decl, declare_inline_vars (DECL_INITIAL (new_decl), vars); - if (DECL_STRUCT_FUNCTION (old_decl)->local_decls != NULL_TREE) + if (!VEC_empty (tree, DECL_STRUCT_FUNCTION (old_decl)->local_decls)) /* Add local vars. */ - for (t_step = DECL_STRUCT_FUNCTION (old_decl)->local_decls; - t_step; t_step = TREE_CHAIN (t_step)) - { - tree var = TREE_VALUE (t_step); - if (TREE_STATIC (var) && !TREE_ASM_WRITTEN (var)) - cfun->local_decls = tree_cons (NULL_TREE, var, cfun->local_decls); - else if (!can_be_nonlocal (var, &id)) - cfun->local_decls = - tree_cons (NULL_TREE, remap_decl (var, &id), - cfun->local_decls); - } + add_local_variables (DECL_STRUCT_FUNCTION (old_decl), cfun, &id, false); /* Copy the Function's body. */ copy_body (&id, old_entry_block->count, REG_BR_PROB_BASE, @@ -5242,7 +5184,15 @@ tree_function_versioning (tree old_decl, tree new_decl, for (e = new_version_node->callees; e; e = e->next_callee) { basic_block bb = gimple_bb (e->call_stmt); - e->frequency = compute_call_stmt_bb_frequency (current_function_decl, bb); + e->frequency = compute_call_stmt_bb_frequency (current_function_decl, + bb); + e->count = bb->count; + } + for (e = new_version_node->indirect_calls; e; e = e->next_callee) + { + basic_block bb = gimple_bb (e->call_stmt); + e->frequency = compute_call_stmt_bb_frequency (current_function_decl, + bb); e->count = bb->count; } } @@ -5278,7 +5228,7 @@ maybe_inline_call_in_expr (tree exp) /* Remap the parameters. */ for (param = DECL_ARGUMENTS (fn), arg = first_call_expr_arg (exp, &iter); param; - param = TREE_CHAIN (param), arg = next_call_expr_arg (&iter)) + param = DECL_CHAIN (param), arg = next_call_expr_arg (&iter)) *pointer_map_insert (decl_map, param) = arg; memset (&id, 0, sizeof (id)); |