@@ -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,35 @@ 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. */
+ {
+ tree *base = VEC_address (tree, cfun->local_decls);
+ tree *dup_base = base + len;
+ unsigned n = VEC_length (tree, cfun->local_decls) - len;
+
+ memmove (base, dup_base, n*sizeof(*base));
+ VEC_truncate (tree, cfun->local_decls, n);
+ }
+
/* 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 +1460,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)
@@ -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);
@@ -1523,7 +1523,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
@@ -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
@@ -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));
@@ -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
@@ -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
@@ -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)
@@ -3416,7 +3416,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;
@@ -3439,6 +3438,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))
@@ -3454,14 +3454,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);
}
}
}
@@ -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))
@@ -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. */
@@ -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));
@@ -3127,20 +3127,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;
}
@@ -3199,12 +3197,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;
@@ -3323,7 +3321,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;
@@ -3369,6 +3367,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
@@ -3446,7 +3446,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. */
@@ -3504,11 +3504,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
@@ -5538,7 +5538,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
{
@@ -6258,7 +6258,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;
@@ -6298,15 +6298,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);
@@ -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)
@@ -2839,9 +2838,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. */
@@ -2900,7 +2897,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 +2917,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;
@@ -3722,6 +3716,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 +3768,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. */
@@ -3959,20 +3971,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))
{
@@ -4714,7 +4713,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)
@@ -5045,7 +5044,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;
@@ -5170,19 +5168,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,
@@ -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);
}
@@ -4449,6 +4449,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
@@ -4465,14 +4466,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. */
@@ -4824,6 +4824,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);
@@ -4836,8 +4837,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. */
{
@@ -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);