From: Nathan Froyd Date: Tue, 6 Jul 2010 02:26:33 +0000 (+0000) Subject: vec.h (FOR_EACH_VEC_ELT_REVERSE): New macro. X-Git-Tag: upstream/12.2.0~91705 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c021f10b188584445b45ec9649cff4d39e640c3e;p=platform%2Fupstream%2Fgcc.git vec.h (FOR_EACH_VEC_ELT_REVERSE): New macro. gcc/ * vec.h (FOR_EACH_VEC_ELT_REVERSE): New macro. * function.h (struct_function): Change type of local_decls field to a VEC. (add_local_decl): New function. (FOR_EACH_LOCAL_DECL): New macro. * cfgexpand.c (init_vars_expansion): Adjust for new type of cfun->local_decls. (estimated_stack_frame_size): Likewise. (expand_used_vars): Likewise. * cgraphbuild.c (build_cgraph_edges): Likewise. * function.c (instantiate_decls_1): Likewise. * ipa-struct-reorg.c (build_data_structure): Likewise. * ipa-type-escape.c (analyze_function): Likewise. * lto-streamer-in.c (input_function): Likewise. * lto-streamer-out.c (output_function): Likewise. * tree-ssa-live.c (remove_unused_locals): Likewise. * tree.c (free_lang_data_in_decl): Likewise. (find_decls_types_in_node): Likewise. * omp-low.c (remove_exit_barrier): Likewise. (expand_omp_taskreg): Likewise. (list2chain): Rename to... (vec2chain): ...this. Adjust. * cgraphunit.c (assemble_thunk): Call add_local_decl. * tree-cfg.c (replace_by_duplicate_decl): Likewise. * gimple-low.c (record_vars_into): Likewise. * tree-inline.c (remap_decls): Likewise. (declare_return_variable): Likewise. (declare_inline_vars): Likewise. (copy_forbidden): Adjust for new type of cfun->local_decls. (add_local_variables): New function. (expand_call_inline): Call it. (tree_function_versioning): Likewise. gcc/cp/ * decl.c (cp_finish_decl): Call add_local_decl. * optimize.c (clone_body): Adjust for new type of cfun->local_decls. From-SVN: r161862 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 333e045..156b55a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,38 @@ +2010-07-05 Nathan Froyd + + * vec.h (FOR_EACH_VEC_ELT_REVERSE): New macro. + * function.h (struct_function): Change type of local_decls field + to a VEC. + (add_local_decl): New function. + (FOR_EACH_LOCAL_DECL): New macro. + * cfgexpand.c (init_vars_expansion): Adjust for new type of + cfun->local_decls. + (estimated_stack_frame_size): Likewise. + (expand_used_vars): Likewise. + * cgraphbuild.c (build_cgraph_edges): Likewise. + * function.c (instantiate_decls_1): Likewise. + * ipa-struct-reorg.c (build_data_structure): Likewise. + * ipa-type-escape.c (analyze_function): Likewise. + * lto-streamer-in.c (input_function): Likewise. + * lto-streamer-out.c (output_function): Likewise. + * tree-ssa-live.c (remove_unused_locals): Likewise. + * tree.c (free_lang_data_in_decl): Likewise. + (find_decls_types_in_node): Likewise. + * omp-low.c (remove_exit_barrier): Likewise. + (expand_omp_taskreg): Likewise. + (list2chain): Rename to... + (vec2chain): ...this. Adjust. + * cgraphunit.c (assemble_thunk): Call add_local_decl. + * tree-cfg.c (replace_by_duplicate_decl): Likewise. + * gimple-low.c (record_vars_into): Likewise. + * tree-inline.c (remap_decls): Likewise. + (declare_return_variable): Likewise. + (declare_inline_vars): Likewise. + (copy_forbidden): Adjust for new type of cfun->local_decls. + (add_local_variables): New function. + (expand_call_inline): Call it. + (tree_function_versioning): Likewise. + 2010-07-05 H.J. Lu AVX Programming Reference (June, 2010) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 3e9ecbf..5b0596e 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1226,9 +1226,10 @@ static void init_vars_expansion (void) { tree t; + unsigned ix; /* Set TREE_USED on all variables in the local_decls. */ - for (t = cfun->local_decls; t; t = TREE_CHAIN (t)) - TREE_USED (TREE_VALUE (t)) = 1; + FOR_EACH_LOCAL_DECL (cfun, ix, t) + TREE_USED (t) = 1; /* Clear TREE_USED on all variables associated with a block scope. */ clear_tree_used (DECL_INITIAL (current_function_decl)); @@ -1264,14 +1265,13 @@ estimated_stack_frame_size (void) { HOST_WIDE_INT size = 0; size_t i; - tree t, outer_block = DECL_INITIAL (current_function_decl); + tree var, outer_block = DECL_INITIAL (current_function_decl); + unsigned ix; init_vars_expansion (); - for (t = cfun->local_decls; t; t = TREE_CHAIN (t)) + FOR_EACH_LOCAL_DECL (cfun, ix, var) { - tree var = TREE_VALUE (t); - if (TREE_USED (var)) size += expand_one_var (var, true, false); TREE_USED (var) = 1; @@ -1296,9 +1296,10 @@ estimated_stack_frame_size (void) static void expand_used_vars (void) { - tree t, next, outer_block = DECL_INITIAL (current_function_decl); - tree maybe_local_decls = NULL_TREE; + tree var, outer_block = DECL_INITIAL (current_function_decl); + VEC(tree,heap) *maybe_local_decls = NULL; unsigned i; + unsigned len; /* Compute the phase of the stack frame for this function. */ { @@ -1333,15 +1334,12 @@ expand_used_vars (void) /* At this point all variables on the local_decls with TREE_USED set are not associated with any block scope. Lay them out. */ - t = cfun->local_decls; - cfun->local_decls = NULL_TREE; - for (; t; t = next) + + len = VEC_length (tree, cfun->local_decls); + FOR_EACH_LOCAL_DECL (cfun, i, var) { - tree var = TREE_VALUE (t); bool expand_now = false; - next = TREE_CHAIN (t); - /* Expanded above already. */ if (is_gimple_reg (var)) { @@ -1377,25 +1375,29 @@ expand_used_vars (void) /* Keep artificial non-ignored vars in cfun->local_decls chain until instantiate_decls. */ if (rtl && (MEM_P (rtl) || GET_CODE (rtl) == CONCAT)) - { - TREE_CHAIN (t) = cfun->local_decls; - cfun->local_decls = t; - continue; - } + add_local_decl (cfun, var); else if (rtl == NULL_RTX) - { - /* If rtl isn't set yet, which can happen e.g. with - -fstack-protector, retry before returning from this - function. */ - TREE_CHAIN (t) = maybe_local_decls; - maybe_local_decls = t; - continue; - } + /* If rtl isn't set yet, which can happen e.g. with + -fstack-protector, retry before returning from this + function. */ + VEC_safe_push (tree, heap, maybe_local_decls, var); } - - ggc_free (t); } + /* We duplicated some of the decls in CFUN->LOCAL_DECLS. + + +-----------------+-----------------+ + | ...processed... | ...duplicates...| + +-----------------+-----------------+ + ^ + +-- LEN points here. + + We just want the duplicates, as those are the artificial + non-ignored vars that we want to keep until instantiate_decls. + Move them down and truncate the array. */ + if (!VEC_empty (tree, cfun->local_decls)) + VEC_block_remove (tree, cfun->local_decls, 0, len); + /* At this point, all variables within the block tree with TREE_USED set are actually used by the optimized function. Lay them out. */ expand_used_vars_for_block (outer_block, true); @@ -1452,24 +1454,16 @@ expand_used_vars (void) /* If there were any artificial non-ignored vars without rtl found earlier, see if deferred stack allocation hasn't assigned rtl to them. */ - for (t = maybe_local_decls; t; t = next) + FOR_EACH_VEC_ELT_REVERSE (tree, maybe_local_decls, i, var) { - tree var = TREE_VALUE (t); rtx rtl = DECL_RTL_IF_SET (var); - next = TREE_CHAIN (t); - /* Keep artificial non-ignored vars in cfun->local_decls chain until instantiate_decls. */ if (rtl && (MEM_P (rtl) || GET_CODE (rtl) == CONCAT)) - { - TREE_CHAIN (t) = cfun->local_decls; - cfun->local_decls = t; - continue; - } - - ggc_free (t); + add_local_decl (cfun, var); } + VEC_free (tree, heap, maybe_local_decls); /* If the target requires that FRAME_OFFSET be aligned, do it. */ if (STACK_ALIGNMENT_NEEDED) diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index 9dcb862..3bd42e3 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -328,7 +328,8 @@ build_cgraph_edges (void) struct cgraph_node *node = cgraph_node (current_function_decl); struct pointer_set_t *visited_nodes = pointer_set_create (); gimple_stmt_iterator gsi; - tree step; + tree decl; + unsigned ix; /* Create the callgraph edges and record the nodes referenced by the function. body. */ @@ -378,15 +379,10 @@ build_cgraph_edges (void) } /* Look for initializers of constant variables and private statics. */ - for (step = cfun->local_decls; - step; - step = TREE_CHAIN (step)) - { - tree decl = TREE_VALUE (step); - if (TREE_CODE (decl) == VAR_DECL - && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))) - varpool_finalize_decl (decl); - } + FOR_EACH_LOCAL_DECL (cfun, ix, decl) + if (TREE_CODE (decl) == VAR_DECL + && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))) + varpool_finalize_decl (decl); record_eh_tables (node, cfun); pointer_set_destroy (visited_nodes); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 2988f1c..da1f983 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1520,7 +1520,7 @@ assemble_thunk (struct cgraph_node *node) if (!is_gimple_reg_type (restype)) { restmp = resdecl; - cfun->local_decls = tree_cons (NULL_TREE, restmp, cfun->local_decls); + add_local_decl (cfun, restmp); BLOCK_VARS (DECL_INITIAL (current_function_decl)) = restmp; } else diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4790208..3f2cac1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2010-07-05 Nathan Froyd + + * decl.c (cp_finish_decl): Call add_local_decl. + * optimize.c (clone_body): Adjust for new type of cfun->local_decls. + 2010-07-05 Paolo Carlini * pt.c (tsubst): Early declare code = TREE_CODE (t) and use it diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1d11fb8..541f77e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5838,8 +5838,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, but [cd]tors are never actually compiled directly. We need to put statics on the list so we can deal with the label address extension. */ - cfun->local_decls = tree_cons (NULL_TREE, decl, - cfun->local_decls); + add_local_decl (cfun, decl); } /* Convert the initializer to the type of DECL, if we have not diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 0196eae..7ec2034 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -107,12 +107,11 @@ clone_body (tree clone, tree fn, void *arg_map) if (DECL_NAME (clone) == base_dtor_identifier || DECL_NAME (clone) == base_ctor_identifier) { - tree decls = DECL_STRUCT_FUNCTION (fn)->local_decls; - for (; decls; decls = TREE_CHAIN (decls)) - { - tree decl = TREE_VALUE (decls); - walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL); - } + unsigned ix; + tree decl; + + FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (fn), ix, decl) + walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL); } append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone)); diff --git a/gcc/function.c b/gcc/function.c index 3a7bb25..9075e08 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -1815,7 +1815,8 @@ instantiate_decls_1 (tree let) static void instantiate_decls (tree fndecl) { - tree decl, t, next; + tree decl; + unsigned ix; /* Process all parameters of the function. */ for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl)) @@ -1832,16 +1833,10 @@ instantiate_decls (tree fndecl) /* Now process all variables defined in the function or its subblocks. */ instantiate_decls_1 (DECL_INITIAL (fndecl)); - t = cfun->local_decls; - cfun->local_decls = NULL_TREE; - for (; t; t = next) - { - next = TREE_CHAIN (t); - decl = TREE_VALUE (t); - if (DECL_RTL_SET_P (decl)) - instantiate_decl_rtl (DECL_RTL (decl)); - ggc_free (t); - } + FOR_EACH_LOCAL_DECL (cfun, ix, decl) + if (DECL_RTL_SET_P (decl)) + instantiate_decl_rtl (DECL_RTL (decl)); + VEC_free (tree, gc, cfun->local_decls); } /* Pass through the INSNS of function FNDECL and convert virtual register diff --git a/gcc/function.h b/gcc/function.h index 6170348..fec0168 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -503,8 +503,8 @@ struct GTY(()) function { pointer. */ tree nonlocal_goto_save_area; - /* List of function local variables, functions, types and constants. */ - tree local_decls; + /* Vector of function local variables, functions, types and constants. */ + VEC(tree,gc) *local_decls; /* For md files. */ @@ -609,6 +609,17 @@ struct GTY(()) function { unsigned int is_thunk : 1; }; +/* Add the decl D to the local_decls list of FUN. */ + +static inline void +add_local_decl (struct function *fun, tree d) +{ + VEC_safe_push (tree, gc, fun->local_decls, d); +} + +#define FOR_EACH_LOCAL_DECL(FUN, I, D) \ + FOR_EACH_VEC_ELT_REVERSE (tree, (FUN)->local_decls, I, D) + /* If va_list_[gf]pr_size is set to this, it means we don't know how many units need to be saved. */ #define VA_LIST_MAX_GPR_SIZE 255 diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 0823b89..381068a 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -907,8 +907,7 @@ record_vars_into (tree vars, tree fn) continue; /* Record the variable. */ - cfun->local_decls = tree_cons (NULL_TREE, var, - cfun->local_decls); + add_local_decl (cfun, var); } if (fn != current_function_decl) diff --git a/gcc/ipa-struct-reorg.c b/gcc/ipa-struct-reorg.c index 98ad91f..4ee8e02 100644 --- a/gcc/ipa-struct-reorg.c +++ b/gcc/ipa-struct-reorg.c @@ -3418,7 +3418,6 @@ static void build_data_structure (VEC (tree, heap) **unsuitable_types) { tree var, type; - tree var_list; struct varpool_node *current_varpool; struct cgraph_node *c_node; @@ -3441,6 +3440,7 @@ build_data_structure (VEC (tree, heap) **unsuitable_types) if (avail == AVAIL_LOCAL || avail == AVAIL_AVAILABLE) { struct function *fn = DECL_STRUCT_FUNCTION (c_node->decl); + unsigned ix; for (var = DECL_ARGUMENTS (c_node->decl); var; var = TREE_CHAIN (var)) @@ -3456,14 +3456,9 @@ build_data_structure (VEC (tree, heap) **unsuitable_types) } /* Check function local variables. */ - for (var_list = fn->local_decls; var_list; - var_list = TREE_CHAIN (var_list)) - { - var = TREE_VALUE (var_list); - - if (is_candidate (var, &type, unsuitable_types)) - add_structure (type); - } + FOR_EACH_LOCAL_DECL (fn, ix, var) + if (is_candidate (var, &type, unsuitable_types)) + add_structure (type); } } } diff --git a/gcc/ipa-type-escape.c b/gcc/ipa-type-escape.c index b6744a6..3b395f9 100644 --- a/gcc/ipa-type-escape.c +++ b/gcc/ipa-type-escape.c @@ -1676,12 +1676,11 @@ analyze_function (struct cgraph_node *fn) /* There may be const decls with interesting right hand sides. */ if (DECL_STRUCT_FUNCTION (decl)) { - tree step; - for (step = DECL_STRUCT_FUNCTION (decl)->local_decls; - step; - step = TREE_CHAIN (step)) + tree var; + unsigned ix; + + FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (decl), ix, var) { - tree var = TREE_VALUE (step); if (TREE_CODE (var) == VAR_DECL && DECL_INITIAL (var) && !TREE_STATIC (var)) diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 635cff4..47f40e2 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -1286,6 +1286,7 @@ input_function (tree fn_decl, struct data_in *data_in, struct bitpack_d bp; struct cgraph_node *node; tree args, narg, oarg; + int len; fn = DECL_STRUCT_FUNCTION (fn_decl); tag = input_record_start (ib); @@ -1320,7 +1321,17 @@ input_function (tree fn_decl, struct data_in *data_in, fn->nonlocal_goto_save_area = lto_input_tree (ib, data_in); /* Read all the local symbols. */ - fn->local_decls = lto_input_tree (ib, data_in); + len = lto_input_sleb128 (ib); + if (len > 0) + { + int i; + VEC_safe_grow (tree, gc, fn->local_decls, len); + for (i = 0; i < len; i++) + { + tree t = lto_input_tree (ib, data_in); + VEC_replace (tree, fn->local_decls, i, t); + } + } /* Read all function arguments. We need to re-map them here to the arguments of the merged function declaration. */ diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index d4bccfb..b702951 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -1840,6 +1840,8 @@ output_function (struct cgraph_node *node) struct function *fn; basic_block bb; struct output_block *ob; + unsigned i; + tree t; function = node->decl; fn = DECL_STRUCT_FUNCTION (function); @@ -1886,7 +1888,9 @@ output_function (struct cgraph_node *node) lto_output_tree_ref (ob, fn->nonlocal_goto_save_area); /* Output all the local variables in the function. */ - lto_output_tree_ref (ob, fn->local_decls); + output_sleb128 (ob, VEC_length (tree, fn->local_decls)); + for (i = 0; VEC_iterate (tree, fn->local_decls, i, t); i++) + lto_output_tree_ref (ob, t); /* Output the head of the arguments list. */ lto_output_tree_ref (ob, DECL_ARGUMENTS (function)); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index eca27c8d..f289159 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3138,20 +3138,18 @@ maybe_catch_exception (gimple_seq body) /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */ static tree -list2chain (tree list) +vec2chain (VEC(tree,gc) *v) { - tree t; + tree chain = NULL_TREE, t; + unsigned ix; - for (t = list; t; t = TREE_CHAIN (t)) + FOR_EACH_VEC_ELT_REVERSE (tree, v, ix, t) { - tree var = TREE_VALUE (t); - if (TREE_CHAIN (t)) - TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t)); - else - TREE_CHAIN (var) = NULL_TREE; + TREE_CHAIN (t) = chain; + chain = t; } - return list ? TREE_VALUE (list) : NULL_TREE; + return chain; } @@ -3210,12 +3208,12 @@ remove_exit_barrier (struct omp_region *region) { gimple parallel_stmt = last_stmt (region->entry); tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt); - tree local_decls = DECL_STRUCT_FUNCTION (child_fun)->local_decls; - tree block; + tree local_decls, block, decl; + unsigned ix; any_addressable_vars = 0; - for (; local_decls; local_decls = TREE_CHAIN (local_decls)) - if (TREE_ADDRESSABLE (TREE_VALUE (local_decls))) + FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl) + if (TREE_ADDRESSABLE (decl)) { any_addressable_vars = 1; break; @@ -3334,7 +3332,7 @@ expand_omp_taskreg (struct omp_region *region) { basic_block entry_bb, exit_bb, new_bb; struct function *child_cfun; - tree child_fn, block, t, ws_args, *tp; + tree child_fn, block, t, ws_args; tree save_current; gimple_stmt_iterator gsi; gimple entry_stmt, stmt; @@ -3380,6 +3378,8 @@ expand_omp_taskreg (struct omp_region *region) } else { + unsigned ix; + /* If the parallel region needs data sent from the parent function, then the very first statement (except possible tree profile counter updates) of the parallel body @@ -3457,7 +3457,7 @@ expand_omp_taskreg (struct omp_region *region) /* Declare local variables needed in CHILD_CFUN. */ block = DECL_INITIAL (child_fn); - BLOCK_VARS (block) = list2chain (child_cfun->local_decls); + BLOCK_VARS (block) = vec2chain (child_cfun->local_decls); /* The gimplifier could record temporaries in parallel/task block rather than in containing function's local_decls chain, which would mean cgraph missed finalizing them. Do it now. */ @@ -3515,11 +3515,11 @@ expand_omp_taskreg (struct omp_region *region) single_succ_edge (new_bb)->flags = EDGE_FALLTHRU; /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */ - for (tp = &child_cfun->local_decls; *tp; ) - if (DECL_CONTEXT (TREE_VALUE (*tp)) != cfun->decl) - tp = &TREE_CHAIN (*tp); + for (ix = 0; VEC_iterate (tree, child_cfun->local_decls, ix, t); ) + if (DECL_CONTEXT (t) != cfun->decl) + ix++; else - *tp = TREE_CHAIN (*tp); + VEC_unordered_remove (tree, child_cfun->local_decls, ix); /* Inform the callgraph about the new function. */ DECL_STRUCT_FUNCTION (child_fn)->curr_properties diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index ccafa4d..87603e7 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -5596,7 +5596,7 @@ replace_by_duplicate_decl (tree *tp, struct pointer_map_t *vars_map, if (SSA_VAR_P (t)) { new_t = copy_var_decl (t, DECL_NAME (t), TREE_TYPE (t)); - f->local_decls = tree_cons (NULL_TREE, new_t, f->local_decls); + add_local_decl (f, new_t); } else { @@ -6316,7 +6316,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, void dump_function_to_file (tree fn, FILE *file, int flags) { - tree arg, vars, var; + tree arg, var; struct function *dsf; bool ignore_topmost_bind = false, any_var = false; basic_block bb; @@ -6356,15 +6356,14 @@ dump_function_to_file (tree fn, FILE *file, int flags) /* When GIMPLE is lowered, the variables are no longer available in BIND_EXPRs, so display them separately. */ - if (cfun && cfun->decl == fn && cfun->local_decls) + if (cfun && cfun->decl == fn && !VEC_empty (tree, cfun->local_decls)) { + unsigned ix; ignore_topmost_bind = true; fprintf (file, "{\n"); - for (vars = cfun->local_decls; vars; vars = TREE_CHAIN (vars)) + FOR_EACH_LOCAL_DECL (cfun, ix, var) { - var = TREE_VALUE (vars); - print_generic_decl (file, var, flags); if (flags & TDF_VERBOSE) print_node (file, "", var, 4); diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 46c604f..e295a6a 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -545,8 +545,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) @@ -2854,9 +2853,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. */ @@ -2915,7 +2912,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) @@ -2934,23 +2932,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; @@ -3737,6 +3731,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 @@ -3769,8 +3783,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. */ @@ -3974,20 +3986,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) use_retvar = declare_return_variable (id, return_slot, modify_dest); /* 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)) { @@ -4729,7 +4728,7 @@ declare_inline_vars (tree block, tree vars) { 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) @@ -5060,7 +5059,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; @@ -5185,19 +5183,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, diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index ca1b985..045d42c 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -663,10 +663,11 @@ void remove_unused_locals (void) { basic_block bb; - tree t, *cell; + tree var, t; referenced_var_iterator rvi; var_ann_t ann; bitmap global_unused_vars = NULL; + unsigned ix; /* Removing declarations from lexical blocks when not optimizing is not only a waste of time, it actually causes differences in stack @@ -733,10 +734,8 @@ remove_unused_locals (void) cfun->has_local_explicit_reg_vars = false; /* Remove unmarked local vars from local_decls. */ - for (cell = &cfun->local_decls; *cell; ) + for (ix = 0; VEC_iterate (tree, cfun->local_decls, ix, var); ) { - tree var = TREE_VALUE (*cell); - if (TREE_CODE (var) != FUNCTION_DECL && (!(ann = var_ann (var)) || !ann->used)) @@ -749,7 +748,7 @@ remove_unused_locals (void) } else { - *cell = TREE_CHAIN (*cell); + VEC_unordered_remove (tree, cfun->local_decls, ix); continue; } } @@ -757,34 +756,29 @@ remove_unused_locals (void) && DECL_HARD_REGISTER (var) && !is_global_var (var)) cfun->has_local_explicit_reg_vars = true; - cell = &TREE_CHAIN (*cell); + + ix++; } /* Remove unmarked global vars from local_decls. */ if (global_unused_vars != NULL) { - for (t = cfun->local_decls; t; t = TREE_CHAIN (t)) - { - tree var = TREE_VALUE (t); - - if (TREE_CODE (var) == VAR_DECL - && is_global_var (var) - && (ann = var_ann (var)) != NULL - && ann->used) - mark_all_vars_used (&DECL_INITIAL (var), global_unused_vars); - } - - for (cell = &cfun->local_decls; *cell; ) - { - tree var = TREE_VALUE (*cell); - - if (TREE_CODE (var) == VAR_DECL - && is_global_var (var) - && bitmap_bit_p (global_unused_vars, DECL_UID (var))) - *cell = TREE_CHAIN (*cell); - else - cell = &TREE_CHAIN (*cell); - } + tree var; + unsigned ix; + FOR_EACH_LOCAL_DECL (cfun, ix, var) + if (TREE_CODE (var) == VAR_DECL + && is_global_var (var) + && (ann = var_ann (var)) != NULL + && ann->used) + mark_all_vars_used (&DECL_INITIAL (var), global_unused_vars); + + for (ix = 0; VEC_iterate (tree, cfun->local_decls, ix, var); ) + if (TREE_CODE (var) == VAR_DECL + && is_global_var (var) + && bitmap_bit_p (global_unused_vars, DECL_UID (var))) + VEC_unordered_remove (tree, cfun->local_decls, ix); + else + ix++; BITMAP_FREE (global_unused_vars); } diff --git a/gcc/tree.c b/gcc/tree.c index b5a99f9..4247047 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -4498,6 +4498,7 @@ free_lang_data_in_decl (tree decl) if (gimple_has_body_p (decl)) { tree t; + unsigned ix; struct pointer_set_t *locals; /* If DECL has a gimple body, then the context for its @@ -4514,14 +4515,13 @@ free_lang_data_in_decl (tree decl) /* Collect all the symbols declared in DECL. */ locals = pointer_set_create (); - t = DECL_STRUCT_FUNCTION (decl)->local_decls; - for (; t; t = TREE_CHAIN (t)) + FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (decl), ix, t) { - pointer_set_insert (locals, TREE_VALUE (t)); + pointer_set_insert (locals, t); /* All the local symbols should have DECL as their context. */ - DECL_CONTEXT (TREE_VALUE (t)) = decl; + DECL_CONTEXT (t) = decl; } /* Get rid of any decl not in local_decls. */ @@ -4873,6 +4873,7 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld) { basic_block bb; struct function *fn; + unsigned ix; tree t; find_decls_types (n->decl, fld); @@ -4885,8 +4886,8 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld) fn = DECL_STRUCT_FUNCTION (n->decl); /* Traverse locals. */ - for (t = fn->local_decls; t; t = TREE_CHAIN (t)) - find_decls_types (TREE_VALUE (t), fld); + FOR_EACH_LOCAL_DECL (fn, ix, t) + find_decls_types (t, fld); /* Traverse EH regions in FN. */ { diff --git a/gcc/vec.h b/gcc/vec.h index e6c42bc..a652250 100644 --- a/gcc/vec.h +++ b/gcc/vec.h @@ -190,6 +190,13 @@ along with GCC; see the file COPYING3. If not see #define VEC_iterate(T,V,I,P) (VEC_OP(T,base,iterate)(VEC_BASE(V),I,&(P))) +/* Convenience macro for reverse iteration. */ + +#define FOR_EACH_VEC_ELT_REVERSE(T,V,I,P) \ + for (I = VEC_length (T, (V)) - 1; \ + VEC_iterate (T, (V), (I), (P)); \ + (I)--) + /* Allocate new vector. VEC(T,A) *VEC_T_A_alloc(int reserve);