#include "tree-dump.h"
#include "tree-ssa-live.h"
#include "diagnostic-core.h"
-#include "toplev.h"
#include "debug.h"
#include "flags.h"
#include "gimple.h"
{
var_map_base_fini (map);
partition_delete (map->var_partition);
- if (map->partition_to_view)
- free (map->partition_to_view);
- if (map->view_to_partition)
- free (map->view_to_partition);
+ free (map->partition_to_view);
+ free (map->view_to_partition);
free (map);
}
eliminated as unused. */
if (TREE_CODE (t) == VAR_DECL)
{
- if (data != NULL && bitmap_clear_bit ((bitmap) data, DECL_UID (t)))
+ if (data != NULL && bitmap_clear_bit ((bitmap) data, DECL_UID (t))
+ && DECL_CONTEXT (t) == current_function_decl)
mark_all_vars_used (&DECL_INITIAL (t), data);
set_is_used (t);
}
{
tree *t, *next;
bool unused = !TREE_USED (scope);
- var_ann_t ann;
int nsubblocks = 0;
for (t = &BLOCK_VARS (scope); *t; t = next)
else if (TREE_CODE (*t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*t))
unused = false;
- /* Remove everything we don't generate debug info for. */
- else if (DECL_IGNORED_P (*t))
+ /* Remove everything we don't generate debug info for.
+ Don't remove larger vars though, because BLOCK_VARS are
+ used also during expansion to determine which variables
+ might share stack space. */
+ else if (DECL_IGNORED_P (*t) && is_gimple_reg (*t))
{
*t = DECL_CHAIN (*t);
next = t;
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)
+ else if (var_ann (*t) != NULL && is_used_p (*t))
unused = false;
else if (TREE_CODE (*t) == LABEL_DECL && TREE_USED (*t))
/* For labels that are still used in the IL, the decision to
can be considered dead. We only want to keep around blocks user can
breakpoint into and ask about value of optimized out variables.
- Similarly we need to keep around types at least until all variables of
- all nested blocks are gone. We track no information on whether given
- type is used or not. */
+ Similarly we need to keep around types at least until all
+ variables of all nested blocks are gone. We track no
+ information on whether given type is used or not, so we have
+ to keep them even when not emitting debug information,
+ otherwise we may end up remapping variables and their (local)
+ types in different orders depending on whether debug
+ information is being generated. */
- else if (debug_info_level == DINFO_LEVEL_NORMAL
+ else if (TREE_CODE (*t) == TYPE_DECL
+ || debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE)
;
else
for (var = BLOCK_VARS (scope); var; var = DECL_CHAIN (var))
{
bool used = false;
- var_ann_t ann;
- if ((ann = var_ann (var))
- && ann->used)
- used = true;
+ if (var_ann (var))
+ used = is_used_p (var);
- fprintf (file, "%*s",indent, "");
+ fprintf (file, "%*s", indent, "");
print_generic_decl (file, var, flags);
fprintf (file, "%s\n", used ? "" : " (unused)");
}
basic_block bb;
tree var, t;
referenced_var_iterator rvi;
- var_ann_t ann;
bitmap global_unused_vars = NULL;
unsigned srcidx, dstidx, num;
+ bool have_local_clobbers = false;
/* Removing declarations from lexical blocks when not optimizing is
not only a waste of time, it actually causes differences in stack
if (!optimize)
return;
+ timevar_push (TV_REMOVE_UNUSED);
+
mark_scope_block_unused (DECL_INITIAL (current_function_decl));
/* Assume all locals are unused. */
- FOR_EACH_REFERENCED_VAR (t, rvi)
- var_ann (t)->used = false;
+ FOR_EACH_REFERENCED_VAR (cfun, t, rvi)
+ clear_is_used (t);
/* Walk the CFG marking all referenced symbols. */
FOR_EACH_BB (bb)
if (is_gimple_debug (stmt))
continue;
+ if (gimple_clobber_p (stmt))
+ {
+ have_local_clobbers = true;
+ continue;
+ }
+
if (b)
TREE_USED (b) = true;
TREE_USED (e->goto_block) = true;
}
+ /* We do a two-pass approach about the out-of-scope clobbers. We want
+ to remove them if they are the only references to a local variable,
+ but we want to retain them when there's any other. So the first pass
+ ignores them, and the second pass (if there were any) tries to remove
+ them. */
+ if (have_local_clobbers)
+ FOR_EACH_BB (bb)
+ {
+ gimple_stmt_iterator gsi;
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
+ {
+ gimple stmt = gsi_stmt (gsi);
+ tree b = gimple_block (stmt);
+
+ if (gimple_clobber_p (stmt))
+ {
+ tree lhs = gimple_assign_lhs (stmt);
+ lhs = get_base_address (lhs);
+ if (TREE_CODE (lhs) == SSA_NAME)
+ lhs = SSA_NAME_VAR (lhs);
+ if (DECL_P (lhs) && (!var_ann (lhs) || !is_used_p (lhs)))
+ {
+ unlink_stmt_vdef (stmt);
+ gsi_remove (&gsi, true);
+ release_defs (stmt);
+ continue;
+ }
+ if (b)
+ TREE_USED (b) = true;
+ }
+ gsi_next (&gsi);
+ }
+ }
+
cfun->has_local_explicit_reg_vars = false;
/* Remove unmarked local vars from local_decls. */
{
var = VEC_index (tree, cfun->local_decls, srcidx);
if (TREE_CODE (var) != FUNCTION_DECL
- && (!(ann = var_ann (var))
- || !ann->used))
+ && (!var_ann (var)
+ || !is_used_p (var)))
{
if (is_global_var (var))
{
FOR_EACH_LOCAL_DECL (cfun, ix, var)
if (TREE_CODE (var) == VAR_DECL
&& is_global_var (var)
- && (ann = var_ann (var)) != NULL
- && ann->used)
+ && var_ann (var) != NULL
+ && is_used_p (var)
+ && DECL_CONTEXT (var) == current_function_decl)
mark_all_vars_used (&DECL_INITIAL (var), global_unused_vars);
num = VEC_length (tree, cfun->local_decls);
}
/* Remove unused variables from REFERENCED_VARs. */
- FOR_EACH_REFERENCED_VAR (t, rvi)
+ FOR_EACH_REFERENCED_VAR (cfun, t, rvi)
if (!is_global_var (t)
&& TREE_CODE (t) != PARM_DECL
&& TREE_CODE (t) != RESULT_DECL
- && !(ann = var_ann (t))->used
- && !ann->is_heapvar)
+ && !is_used_p (t))
remove_referenced_var (t);
remove_unused_scope_block_p (DECL_INITIAL (current_function_decl));
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Scope blocks after cleanups:\n");
dump_scope_blocks (dump_file, dump_flags);
}
+
+ timevar_pop (TV_REMOVE_UNUSED);
}