}
-static inline void mark_all_vars_used (tree *);
+static inline void mark_all_vars_used (tree *, void *data);
/* Helper function for mark_all_vars_used, called via walk_tree. */
static tree
mark_all_vars_used_1 (tree *tp, int *walk_subtrees,
- void *data ATTRIBUTE_UNUSED)
+ void *data)
{
tree t = *tp;
enum tree_code_class c = TREE_CODE_CLASS (TREE_CODE (t));
fields that do not contain vars. */
if (TREE_CODE (t) == TARGET_MEM_REF)
{
- mark_all_vars_used (&TMR_SYMBOL (t));
- mark_all_vars_used (&TMR_BASE (t));
- mark_all_vars_used (&TMR_INDEX (t));
+ mark_all_vars_used (&TMR_SYMBOL (t), data);
+ mark_all_vars_used (&TMR_BASE (t), data);
+ mark_all_vars_used (&TMR_INDEX (t), data);
*walk_subtrees = 0;
return NULL;
}
/* Only need to mark VAR_DECLS; parameters and return results are not
eliminated as unused. */
if (TREE_CODE (t) == VAR_DECL)
- set_is_used (t);
+ {
+ if (data != NULL && bitmap_bit_p ((bitmap) data, DECL_UID (t)))
+ {
+ bitmap_clear_bit ((bitmap) data, DECL_UID (t));
+ mark_all_vars_used (&DECL_INITIAL (t), data);
+ }
+ set_is_used (t);
+ }
if (IS_TYPE_OR_DECL_P (t))
*walk_subtrees = 0;
static bool
remove_unused_scope_block_p (tree scope)
{
- tree *t;
+ tree *t, *next;
bool unused = !TREE_USED (scope);
+ var_ann_t ann;
int nsubblocks = 0;
+ for (t = &BLOCK_VARS (scope); *t; t = next)
+ {
+ next = &TREE_CHAIN (*t);
+
+ /* Debug info of nested function refers to the block of the
+ function. */
+ if (TREE_CODE (*t) == FUNCTION_DECL)
+ unused = false;
+
+ /* When we are outputting debug info, we usually want to output
+ info about optimized-out variables in the scope blocks.
+ Exception are the scope blocks not containing any instructions
+ at all so user can't get into the scopes at first place. */
+ else if ((ann = var_ann (*t)) != NULL
+ && ann->used)
+ unused = false;
+
+ /* When we are not doing full debug info, we however can keep around
+ only the used variables for cfgexpand's memory packing saving quite
+ a lot of memory. */
+ else if (debug_info_level == DINFO_LEVEL_NORMAL
+ || debug_info_level == DINFO_LEVEL_VERBOSE
+ /* Removing declarations before inlining is going to affect
+ DECL_UID that in turn is going to affect hashtables and
+ code generation. */
+ || !cfun->after_inlining)
+ unused = false;
+
+ else
+ {
+ *t = TREE_CHAIN (*t);
+ next = t;
+ }
+ }
+
for (t = &BLOCK_SUBBLOCKS (scope); *t ;)
if (remove_unused_scope_block_p (*t))
{
nsubblocks ++;
}
else
- *t = BLOCK_CHAIN (*t);
+ {
+ gcc_assert (!BLOCK_VARS (*t));
+ *t = BLOCK_CHAIN (*t);
+ }
}
else
{
/* When there is only one subblock, see if it is just wrapper we can
ignore. Wrappers are not declaring any variables and not changing
abstract origin. */
- else if (nsubblocks <= 1
+ else if (nsubblocks == 1
&& (BLOCK_VARS (scope)
- || (BLOCK_ABSTRACT_ORIGIN (scope)
- != BLOCK_ABSTRACT_ORIGIN (BLOCK_SUPERCONTEXT (scope)))))
+ || ((debug_info_level == DINFO_LEVEL_NORMAL
+ || debug_info_level == DINFO_LEVEL_VERBOSE)
+ && ((BLOCK_ABSTRACT_ORIGIN (scope)
+ != BLOCK_ABSTRACT_ORIGIN (BLOCK_SUPERCONTEXT (scope)))))))
unused = false;
return unused;
}
eliminated during the tree->rtl conversion process. */
static inline void
-mark_all_vars_used (tree *expr_p)
+mark_all_vars_used (tree *expr_p, void *data)
{
- walk_tree (expr_p, mark_all_vars_used_1, NULL, NULL);
+ walk_tree (expr_p, mark_all_vars_used_1, data, NULL);
}
tree t, *cell;
referenced_var_iterator rvi;
var_ann_t ann;
+ bitmap global_unused_vars = NULL;
mark_scope_block_unused (DECL_INITIAL (current_function_decl));
/* Assume all locals are unused. */
/* Walk the statements. */
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- mark_all_vars_used (bsi_stmt_ptr (bsi));
+ mark_all_vars_used (bsi_stmt_ptr (bsi), NULL);
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
continue;
def = PHI_RESULT (phi);
- mark_all_vars_used (&def);
+ mark_all_vars_used (&def, NULL);
FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_ALL_USES)
{
tree arg = USE_FROM_PTR (arg_p);
- mark_all_vars_used (&arg);
+ mark_all_vars_used (&arg, NULL);
}
}
}
- /* Remove unmarked vars and clear used flag. */
- for (cell = &cfun->unexpanded_var_list; *cell; )
+ /* Remove unmarked local vars from local_decls. */
+ for (cell = &cfun->local_decls; *cell; )
{
tree var = TREE_VALUE (*cell);
&& (!(ann = var_ann (var))
|| !ann->used))
{
- *cell = TREE_CHAIN (*cell);
- continue;
+ if (is_global_var (var))
+ {
+ if (global_unused_vars == NULL)
+ global_unused_vars = BITMAP_ALLOC (NULL);
+ bitmap_set_bit (global_unused_vars, DECL_UID (var));
+ }
+ else
+ {
+ *cell = TREE_CHAIN (*cell);
+ continue;
+ }
}
cell = &TREE_CHAIN (*cell);
}
+ /* 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);
+ }
+ BITMAP_FREE (global_unused_vars);
+ }
+
/* Remove unused variables from REFERENCED_VARs. As a special
exception keep the variables that are believed to be aliased.
Those can't be easily removed from the alias sets and operand