From 362676499c08b5b814947261088c1a614984efb1 Mon Sep 17 00:00:00 2001 From: hubicka Date: Mon, 23 Feb 2009 13:10:53 +0000 Subject: [PATCH] PR tree-optimization/37709 * tree.c (block_ultimate_origin): Move here from dwarf2out. * tree.h (block_ultimate_origin): Declare. * dwarf2out.c (block_ultimate_origin): Move to tree.c * tree-ssa-live.c (remove_unused_scope_block_p): Eliminate blocks containig no instructions nor live variables nor nested blocks. (dump_scope_block): New function. (remove_unused_locals): Enable removal of dead blocks by default; enable dumping at TDF_DETAILS. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@144381 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 13 ++++++++++ gcc/dbxout.c | 2 +- gcc/dwarf2out.c | 46 ----------------------------------- gcc/tree-ssa-live.c | 70 +++++++++++++++++++++++++++++++++++++++++++---------- gcc/tree.c | 45 ++++++++++++++++++++++++++++++++++ gcc/tree.h | 1 + 6 files changed, 117 insertions(+), 60 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1961e74811c..01968baaf2a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2009-02-23 Jan Hubicka + + PR tree-optimization/37709 + * tree.c (block_ultimate_origin): Move here from dwarf2out. + * tree.h (block_ultimate_origin): Declare. + * dwarf2out.c (block_ultimate_origin): Move to tree.c + * tree-ssa-live.c (remove_unused_scope_block_p): + Eliminate blocks containig no instructions nor live variables nor + nested blocks. + (dump_scope_block): New function. + (remove_unused_locals): Enable removal of dead blocks by default; + enable dumping at TDF_DETAILS. + 2008-02-21 H.J. Lu * config/i386/i386.c (classify_argument): Don't allow COImode diff --git a/gcc/dbxout.c b/gcc/dbxout.c index f4a2792bc93..6cfa55f9328 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -3593,7 +3593,7 @@ dbxout_block (tree block, int depth, tree args) while (block) { /* Ignore blocks never expanded or otherwise marked as real. */ - if (TREE_USED (block) && TREE_ASM_WRITTEN (block)) + if (TREE_ASM_WRITTEN (block)) { int did_output; int blocknum = BLOCK_NUMBER (block); diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index d3de6e6afc6..2e5f032c2a2 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -4947,7 +4947,6 @@ static const char *dwarf_tag_name (unsigned); static const char *dwarf_attr_name (unsigned); static const char *dwarf_form_name (unsigned); static tree decl_ultimate_origin (const_tree); -static tree block_ultimate_origin (const_tree); static tree decl_class_context (tree); static void add_dwarf_attr (dw_die_ref, dw_attr_ref); static inline enum dw_val_class AT_class (dw_attr_ref); @@ -5772,51 +5771,6 @@ decl_ultimate_origin (const_tree decl) return DECL_ABSTRACT_ORIGIN (decl); } -/* Determine the "ultimate origin" of a block. The block may be an inlined - instance of an inlined instance of a block which is local to an inline - function, so we have to trace all of the way back through the origin chain - to find out what sort of node actually served as the original seed for the - given block. */ - -static tree -block_ultimate_origin (const_tree block) -{ - tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block); - - /* output_inline_function sets BLOCK_ABSTRACT_ORIGIN for all the - nodes in the function to point to themselves; ignore that if - we're trying to output the abstract instance of this function. */ - if (BLOCK_ABSTRACT (block) && immediate_origin == block) - return NULL_TREE; - - if (immediate_origin == NULL_TREE) - return NULL_TREE; - else - { - tree ret_val; - tree lookahead = immediate_origin; - - do - { - ret_val = lookahead; - lookahead = (TREE_CODE (ret_val) == BLOCK - ? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL); - } - while (lookahead != NULL && lookahead != ret_val); - - /* The block's abstract origin chain may not be the *ultimate* origin of - the block. It could lead to a DECL that has an abstract origin set. - If so, we want that DECL's abstract origin (which is what DECL_ORIGIN - will give us if it has one). Note that DECL's abstract origins are - supposed to be the most distant ancestor (or so decl_ultimate_origin - claims), so we don't need to loop following the DECL origins. */ - if (DECL_P (ret_val)) - return DECL_ORIGIN (ret_val); - - return ret_val; - } -} - /* Get the class to which DECL belongs, if any. In g++, the DECL_CONTEXT of a virtual function may refer to a base class, so we check the 'this' parameter. */ diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index 8ebf30ec926..81e65f732e1 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -485,10 +485,13 @@ remove_unused_scope_block_p (tree scope) next = &TREE_CHAIN (*t); /* Debug info of nested function refers to the block of the - function. */ + function. We might stil call it even if all statements + of function it was nested into was elliminated. + + TODO: We can actually look into cgraph to see if function + will be output to file. */ if (TREE_CODE (*t) == FUNCTION_DECL) unused = false; - /* Remove everything we don't generate debug info for. */ else if (DECL_IGNORED_P (*t)) { @@ -506,15 +509,24 @@ remove_unused_scope_block_p (tree scope) /* 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. */ + a lot of memory. + + For sake of -g3, we keep around those vars but we don't count this as + use of block, so innermost block with no used vars and no instructions + 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. */ + 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); @@ -537,10 +549,7 @@ remove_unused_scope_block_p (tree scope) nsubblocks ++; } else - { - gcc_assert (!BLOCK_VARS (*t)); - *t = BLOCK_CHAIN (*t); - } + *t = BLOCK_CHAIN (*t); } else { @@ -576,6 +585,38 @@ mark_all_vars_used (tree *expr_p, void *data) walk_tree (expr_p, mark_all_vars_used_1, data, NULL); } +/* Dump scope blocks. */ + +static void +dump_scope_block (FILE *file, int indent, tree scope, int flags) +{ + tree var, t; + + fprintf (file, "\n%*sScope block #%i %s\n",indent, "" , BLOCK_NUMBER (scope), + TREE_USED (scope) ? "" : "(unused)"); + if (BLOCK_ABSTRACT_ORIGIN (scope) && DECL_P (block_ultimate_origin (scope))) + { + fprintf (file, "\n%*sOriginating from ",indent + 1, ""); + print_generic_decl (file, block_ultimate_origin (scope), flags); + fprintf (file, "\n"); + } + for (var = BLOCK_VARS (scope); var; var = TREE_CHAIN (var)) + { + bool used = false; + var_ann_t ann; + + if ((ann = var_ann (var)) + && ann->used) + used = true; + + fprintf (file, "%*s",indent, ""); + print_generic_decl (file, var, flags); + fprintf (file, "%s\n", used ? "" : " (unused)"); + } + for (t = BLOCK_SUBBLOCKS (scope); t ; t = BLOCK_CHAIN (t)) + dump_scope_block (file, indent + 2, t, flags); +} + /* Remove local variables that are not referenced in the IL. */ @@ -588,8 +629,7 @@ remove_unused_locals (void) var_ann_t ann; bitmap global_unused_vars = NULL; - if (optimize) - mark_scope_block_unused (DECL_INITIAL (current_function_decl)); + mark_scope_block_unused (DECL_INITIAL (current_function_decl)); /* Assume all locals are unused. */ FOR_EACH_REFERENCED_VAR (t, rvi) @@ -716,8 +756,12 @@ remove_unused_locals (void) && !TREE_ADDRESSABLE (t) && (optimize || DECL_ARTIFICIAL (t))) remove_referenced_var (t); - if (optimize) - remove_unused_scope_block_p (DECL_INITIAL (current_function_decl)); + 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_block (dump_file, 0, DECL_INITIAL (current_function_decl), false); + } } diff --git a/gcc/tree.c b/gcc/tree.c index 03c54cc1cb1..423c8681cf2 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -9199,4 +9199,49 @@ build_target_option_node (void) return t; } +/* Determine the "ultimate origin" of a block. The block may be an inlined + instance of an inlined instance of a block which is local to an inline + function, so we have to trace all of the way back through the origin chain + to find out what sort of node actually served as the original seed for the + given block. */ + +tree +block_ultimate_origin (const_tree block) +{ + tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block); + + /* output_inline_function sets BLOCK_ABSTRACT_ORIGIN for all the + nodes in the function to point to themselves; ignore that if + we're trying to output the abstract instance of this function. */ + if (BLOCK_ABSTRACT (block) && immediate_origin == block) + return NULL_TREE; + + if (immediate_origin == NULL_TREE) + return NULL_TREE; + else + { + tree ret_val; + tree lookahead = immediate_origin; + + do + { + ret_val = lookahead; + lookahead = (TREE_CODE (ret_val) == BLOCK + ? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL); + } + while (lookahead != NULL && lookahead != ret_val); + + /* The block's abstract origin chain may not be the *ultimate* origin of + the block. It could lead to a DECL that has an abstract origin set. + If so, we want that DECL's abstract origin (which is what DECL_ORIGIN + will give us if it has one). Note that DECL's abstract origins are + supposed to be the most distant ancestor (or so decl_ultimate_origin + claims), so we don't need to loop following the DECL origins. */ + if (DECL_P (ret_val)) + return DECL_ORIGIN (ret_val); + + return ret_val; + } +} + #include "gt-tree.h" diff --git a/gcc/tree.h b/gcc/tree.h index 5a7e765784f..ae4291326d9 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5022,6 +5022,7 @@ extern bool gimple_alloca_call_p (const_gimple); extern bool alloca_call_p (const_tree); extern bool must_pass_in_stack_var_size (enum machine_mode, const_tree); extern bool must_pass_in_stack_var_size_or_pad (enum machine_mode, const_tree); +extern tree block_ultimate_origin (const_tree); /* In attribs.c. */ -- 2.11.4.GIT