summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-live.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-19 18:19:39 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-19 18:19:39 +0000
commite56043cd2c207982e812ce6fcecb7353dea58363 (patch)
tree01a6f37ad5a9ae6b18bdc20f052b04e19b4255c0 /gcc/tree-ssa-live.c
parent2e02a1a4548f2ee1ea519c88e68b20621ad16fcc (diff)
downloadgcc-e56043cd2c207982e812ce6fcecb7353dea58363.tar.gz
2010-09-19 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 164348, with some improvements in gcc/melt-runtime.[ch] 2010-09-19 Basile Starynkevitch <basile@starynkevitch.net> [[merged with trunk rev.164348, so improved MELT runtime!]] * gcc/melt-runtime.h: improved comments. (melt_debug_garbcoll, melt_debuggc_eprintf): Moved from melt-runtime.c. (melt_obmag_string): New declaration. (struct meltobject_st, struct meltclosure_st, struct meltroutine_st, struct meltmixbigint_st, struct meltstring_st): using GTY variable_size and @@MELTGTY@@ comment. (melt_mark_special): added debug print. * gcc/melt-runtime.c: Improved comments. Include bversion.h, realmpfr.h, gimple-pretty-print.h. (ggc_force_collect) Declared external. (melt_forward_counter): Added. (melt_obmag_string): New function. (melt_alptr_1, melt_alptr_2, melt_break_alptr_1_at) (melt_break_alptr_2_at, melt_break_alptr_1,melt_break_alptr_1) (melt_allocate_young_gc_zone, melt_free_young_gc_zone): New. (delete_special, meltgc_make_special): Improved debug printf and use melt_break_alptr_1... (ggc_alloc_*) macros defined for backport to GCC 4.5 (melt_forwarded_copy): Don't clear the new destination zone in old GGC heap. (meltgc_add_out_raw_len): Use ggc_alloc_atomic. (meltgc_raw_new_mappointers, meltgc_raw_put_mappointers) (meltgc_raw_remove_mappointers): Corrected length argument to ggc_alloc_cleared_vec_entrypointermelt_st. (melt_really_initialize): Call melt_allocate_young_gc_zone. (melt_initialize): Set flag_plugin_added. (melt_val2passflag): TODO_verify_loops only in GCC 4.5 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@164424 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-live.c')
-rw-r--r--gcc/tree-ssa-live.c211
1 files changed, 161 insertions, 50 deletions
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index c0ccb4fe20d..715b5a71c07 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -1,6 +1,6 @@
/* Liveness for SSA trees.
- Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
- Inc.
+ Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@redhat.com>
This file is part of GCC.
@@ -24,14 +24,17 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
+#include "gimple-pretty-print.h"
#include "bitmap.h"
#include "tree-flow.h"
#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"
#ifdef ENABLE_CHECKING
static void verify_live_on_entry (tree_live_info_p);
@@ -359,13 +362,13 @@ mark_all_vars_used_1 (tree *tp, int *walk_subtrees, void *data)
&& (b = TREE_BLOCK (t)) != NULL)
TREE_USED (b) = true;
- /* Ignore TREE_ORIGINAL for TARGET_MEM_REFS, as well as other
- fields that do not contain vars. */
+ /* Ignore TMR_OFFSET and TMR_STEP for TARGET_MEM_REFS, as those
+ fields do not contain vars. */
if (TREE_CODE (t) == TARGET_MEM_REF)
{
- mark_all_vars_used (&TMR_SYMBOL (t), data);
mark_all_vars_used (&TMR_BASE (t), data);
mark_all_vars_used (&TMR_INDEX (t), data);
+ mark_all_vars_used (&TMR_INDEX2 (t), data);
*walk_subtrees = 0;
return NULL;
}
@@ -374,13 +377,18 @@ mark_all_vars_used_1 (tree *tp, int *walk_subtrees, void *data)
eliminated as unused. */
if (TREE_CODE (t) == VAR_DECL)
{
- 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);
- }
+ if (data != NULL && bitmap_clear_bit ((bitmap) data, DECL_UID (t)))
+ mark_all_vars_used (&DECL_INITIAL (t), data);
set_is_used (t);
}
+ /* remove_unused_scope_block_p requires information about labels
+ which are not DECL_IGNORED_P to tell if they might be used in the IL. */
+ if (TREE_CODE (t) == LABEL_DECL)
+ /* Although the TREE_USED values that the frontend uses would be
+ acceptable (albeit slightly over-conservative) for our purposes,
+ init_vars_expansion clears TREE_USED for LABEL_DECLs too, so we
+ must re-compute it here. */
+ TREE_USED (t) = 1;
if (IS_TYPE_OR_DECL_P (t))
*walk_subtrees = 0;
@@ -425,7 +433,7 @@ remove_unused_scope_block_p (tree scope)
for (t = &BLOCK_VARS (scope); *t; t = next)
{
- next = &TREE_CHAIN (*t);
+ next = &DECL_CHAIN (*t);
/* Debug info of nested function refers to the block of the
function. We might stil call it even if all statements
@@ -449,7 +457,7 @@ remove_unused_scope_block_p (tree scope)
/* Remove everything we don't generate debug info for. */
else if (DECL_IGNORED_P (*t))
{
- *t = TREE_CHAIN (*t);
+ *t = DECL_CHAIN (*t);
next = t;
}
@@ -460,6 +468,19 @@ remove_unused_scope_block_p (tree scope)
else if ((ann = var_ann (*t)) != NULL
&& ann->used)
unused = false;
+ else if (TREE_CODE (*t) == LABEL_DECL && TREE_USED (*t))
+ /* For labels that are still used in the IL, the decision to
+ preserve them must not depend DEBUG_INFO_LEVEL, otherwise we
+ risk having different ordering in debug vs. non-debug builds
+ during inlining or versioning.
+ A label appearing here (we have already checked DECL_IGNORED_P)
+ should not be used in the IL unless it has been explicitly used
+ before, so we use TREE_USED as an approximation. */
+ /* In principle, we should do the same here as for the debug case
+ below, however, when debugging, there might be additional nested
+ levels that keep an upper level with a label live, so we have to
+ force this block to be considered used, too. */
+ 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
@@ -479,7 +500,7 @@ remove_unused_scope_block_p (tree scope)
;
else
{
- *t = TREE_CHAIN (*t);
+ *t = DECL_CHAIN (*t);
next = t;
}
}
@@ -602,7 +623,7 @@ dump_scope_block (FILE *file, int indent, tree scope, int flags)
}
}
fprintf (file, " \n");
- for (var = BLOCK_VARS (scope); var; var = TREE_CHAIN (var))
+ for (var = BLOCK_VARS (scope); var; var = DECL_CHAIN (var))
{
bool used = false;
var_ann_t ann;
@@ -630,7 +651,7 @@ dump_scope_block (FILE *file, int indent, tree scope, int flags)
/* Dump the tree of lexical scopes starting at SCOPE to stderr. FLAGS
is as in print_generic_expr. */
-void
+DEBUG_FUNCTION void
debug_scope_block (tree scope, int flags)
{
dump_scope_block (stderr, 0, scope, flags);
@@ -650,7 +671,7 @@ dump_scope_blocks (FILE *file, int flags)
/* Dump the tree of lexical scopes of current_function_decl to stderr.
FLAGS is as in print_generic_expr. */
-void
+DEBUG_FUNCTION void
debug_scope_blocks (int flags)
{
dump_scope_blocks (stderr, flags);
@@ -662,10 +683,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 srcidx, dstidx, num;
/* Removing declarations from lexical blocks when not optimizing is
not only a waste of time, it actually causes differences in stack
@@ -732,10 +754,10 @@ remove_unused_locals (void)
cfun->has_local_explicit_reg_vars = false;
/* Remove unmarked local vars from local_decls. */
- for (cell = &cfun->local_decls; *cell; )
+ num = VEC_length (tree, cfun->local_decls);
+ for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
{
- tree var = TREE_VALUE (*cell);
-
+ var = VEC_index (tree, cfun->local_decls, srcidx);
if (TREE_CODE (var) != FUNCTION_DECL
&& (!(ann = var_ann (var))
|| !ann->used))
@@ -747,58 +769,57 @@ remove_unused_locals (void)
bitmap_set_bit (global_unused_vars, DECL_UID (var));
}
else
- {
- *cell = TREE_CHAIN (*cell);
- continue;
- }
+ continue;
}
else if (TREE_CODE (var) == VAR_DECL
&& DECL_HARD_REGISTER (var)
&& !is_global_var (var))
cfun->has_local_explicit_reg_vars = true;
- cell = &TREE_CHAIN (*cell);
+
+ if (srcidx != dstidx)
+ VEC_replace (tree, cfun->local_decls, dstidx, var);
+ dstidx++;
}
+ if (dstidx != num)
+ VEC_truncate (tree, cfun->local_decls, dstidx);
/* 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;
+ 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);
+
+ num = VEC_length (tree, cfun->local_decls);
+ for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
{
- tree var = TREE_VALUE (*cell);
-
+ var = VEC_index (tree, cfun->local_decls, srcidx);
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);
+ continue;
+
+ if (srcidx != dstidx)
+ VEC_replace (tree, cfun->local_decls, dstidx, var);
+ dstidx++;
}
+ if (dstidx != num)
+ VEC_truncate (tree, cfun->local_decls, dstidx);
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
- caches. They will be removed shortly after the next may_alias
- pass is performed. */
+ /* Remove unused variables from REFERENCED_VARs. */
FOR_EACH_REFERENCED_VAR (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
- && !TREE_ADDRESSABLE (t))
+ && !ann->is_heapvar)
remove_referenced_var (t);
remove_unused_scope_block_p (DECL_INITIAL (current_function_decl));
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1168,6 +1189,96 @@ dump_live_info (FILE *f, tree_live_info_p live, int flag)
}
}
+struct GTY(()) numbered_tree_d
+{
+ tree t;
+ int num;
+};
+typedef struct numbered_tree_d numbered_tree;
+
+DEF_VEC_O (numbered_tree);
+DEF_VEC_ALLOC_O (numbered_tree, heap);
+
+/* Compare two declarations references by their DECL_UID / sequence number.
+ Called via qsort. */
+
+static int
+compare_decls_by_uid (const void *pa, const void *pb)
+{
+ const numbered_tree *nt_a = ((const numbered_tree *)pa);
+ const numbered_tree *nt_b = ((const numbered_tree *)pb);
+
+ if (DECL_UID (nt_a->t) != DECL_UID (nt_b->t))
+ return DECL_UID (nt_a->t) - DECL_UID (nt_b->t);
+ return nt_a->num - nt_b->num;
+}
+
+/* Called via walk_gimple_stmt / walk_gimple_op by dump_enumerated_decls. */
+static tree
+dump_enumerated_decls_push (tree *tp, int *walk_subtrees, void *data)
+{
+ struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+ VEC (numbered_tree, heap) **list = (VEC (numbered_tree, heap) **) &wi->info;
+ numbered_tree nt;
+
+ if (!DECL_P (*tp))
+ return NULL_TREE;
+ nt.t = *tp;
+ nt.num = VEC_length (numbered_tree, *list);
+ VEC_safe_push (numbered_tree, heap, *list, &nt);
+ *walk_subtrees = 0;
+ return NULL_TREE;
+}
+
+/* Find all the declarations used by the current function, sort them by uid,
+ and emit the sorted list. Each declaration is tagged with a sequence
+ number indicating when it was found during statement / tree walking,
+ so that TDF_NOUID comparisons of anonymous declarations are still
+ meaningful. Where a declaration was encountered more than once, we
+ emit only the sequence number of the first encounter.
+ FILE is the dump file where to output the list and FLAGS is as in
+ print_generic_expr. */
+void
+dump_enumerated_decls (FILE *file, int flags)
+{
+ basic_block bb;
+ struct walk_stmt_info wi;
+ VEC (numbered_tree, heap) *decl_list = VEC_alloc (numbered_tree, heap, 40);
+
+ memset (&wi, '\0', sizeof (wi));
+ wi.info = (void*) decl_list;
+ FOR_EACH_BB (bb)
+ {
+ gimple_stmt_iterator gsi;
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ if (!is_gimple_debug (gsi_stmt (gsi)))
+ walk_gimple_stmt (&gsi, NULL, dump_enumerated_decls_push, &wi);
+ }
+ decl_list = (VEC (numbered_tree, heap) *) wi.info;
+ qsort (VEC_address (numbered_tree, decl_list),
+ VEC_length (numbered_tree, decl_list),
+ sizeof (numbered_tree), compare_decls_by_uid);
+ if (VEC_length (numbered_tree, decl_list))
+ {
+ unsigned ix;
+ numbered_tree *ntp;
+ tree last = NULL_TREE;
+
+ fprintf (file, "Declarations used by %s, sorted by DECL_UID:\n",
+ current_function_name ());
+ FOR_EACH_VEC_ELT (numbered_tree, decl_list, ix, ntp)
+ {
+ if (ntp->t == last)
+ continue;
+ fprintf (file, "%d: ", ntp->num);
+ print_generic_decl (file, ntp->t, flags);
+ fprintf (file, "\n");
+ last = ntp->t;
+ }
+ }
+ VEC_free (numbered_tree, heap, decl_list);
+}
#ifdef ENABLE_CHECKING
/* Verify that SSA_VAR is a non-virtual SSA_NAME. */