/* Liveness for SSA trees.
- Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@redhat.com>
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
}
-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;
or there is precisely one subblocks and the block
has same abstract origin as outer block and declares
no variables, so it is pure wrapper.
- When we are not outputting full debug info, we also elliminate dead variables
+ When we are not outputting full debug info, we also eliminate dead variables
out of scope blocks to let them to be recycled by GGC and to save copying work
done by the inliner. */
{
next = &TREE_CHAIN (*t);
- /* Debug info of nested function reffers to the block of the
+ /* Debug info of nested function refers to the block of the
function. */
if (TREE_CODE (*t) == FUNCTION_DECL)
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)
+ 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;
nsubblocks ++;
}
else
- *t = BLOCK_CHAIN (*t);
+ {
+ gcc_assert (!BLOCK_VARS (*t));
+ *t = BLOCK_CHAIN (*t);
+ }
}
else
{
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. */
+ /* Remove unmarked local vars from unexpanded_var_list. */
for (cell = &cfun->unexpanded_var_list; *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 unexpanded_var_list. */
+ if (global_unused_vars != NULL)
+ {
+ for (t = cfun->unexpanded_var_list; 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->unexpanded_var_list; *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