public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Put scope blocks on a diet
@ 2007-07-24 18:20 Jan Hubicka
  2007-07-24 19:23 ` Diego Novillo
  2007-08-02  8:59 ` Alexandre Oliva
  0 siblings, 2 replies; 64+ messages in thread
From: Jan Hubicka @ 2007-07-24 18:20 UTC (permalink / raw)
  To: gcc-patches

Hi,
this patch adds code for prunning scope blocks that (quite surprisingly) pops
up as top memory consumers in many C++ programs.  This problem is usually
introduced by inliner that for each inlined accestor produce about 3 scope
blocks.

The patch simply removes blocks that should not be needed that is:
  - no statements assigned to them
  - no live variables assigned to them
    (I belive that for blocks you can't breakpoint to, you can't also resonably
     ask about the variable)
  - leaf blocks or nonleaf blocks having precisely one subblock (so the
    block itself can be replaced by subblock)
  - I also check that abstract origin does not change.

With debugging disabled gimplifier also knows to not assign statements
to block so we can remove more of them.  This seems to be safe to do
concerning consistency in between -g and no -g (we still keep enough
block around to support some of other tests made)

We probably can come with more fine grained rules, but I am not expert
in the area so I tried to be conservative.  The patch still saves
substantial portion of memory for testcases I am interested in.

Note also the existence of unused ignore_block debughook. This debughook used
to be used by RTL code removing paired BLOCK notes with no code in them.  What
I do above is more strict than what the debug outputs test (they usually look
for nested functions living in the block).  WIth the new code handling blocks,
we are more aggressive on removing blocks in RTL land basically removing all
blocks that are having no statements (transitively) in them.

I wonder if we want to restore original function (we would probably just need
to emit the required blocks as empty blocks on the end of function or something
since info about their original position is completely lost on this point)

Bootstrapped/regtested i686-linux and run through gdb testsuite.  OK?

Honza
	* gimple-low.c (lower_stmt): When not doing debugging, don't save
	info about block.
	* tree-ssa-live.c: Include debug.h and flags.h.
	(mark_scope_block_unused): New function.
	(remove_unused_scope_block_p): New function.
	(remove_unused_locals): Remove unused blocks too.
Index: gimple-low.c
===================================================================
--- gimple-low.c	(revision 126859)
+++ gimple-low.c	(working copy)
@@ -210,7 +210,9 @@ lower_stmt (tree_stmt_iterator *tsi, str
 {
   tree stmt = tsi_stmt (*tsi);
 
-  if (EXPR_HAS_LOCATION (stmt) && data)
+  if (EXPR_HAS_LOCATION (stmt) && data
+      && (debug_info_level == DINFO_LEVEL_NORMAL
+          || debug_info_level == DINFO_LEVEL_VERBOSE))
     TREE_BLOCK (stmt) = data->block;
 
   switch (TREE_CODE (stmt))
Index: tree-ssa-live.c
===================================================================
--- tree-ssa-live.c	(revision 126859)
+++ tree-ssa-live.c	(working copy)
@@ -30,6 +30,8 @@ Boston, MA 02110-1301, USA.  */
 #include "tree-dump.h"
 #include "tree-ssa-live.h"
 #include "toplev.h"
+#include "debug.h"
+#include "flags.h"
 
 #ifdef ENABLE_CHECKING
 static void  verify_live_on_entry (tree_live_info_p);
@@ -405,9 +407,15 @@ mark_all_vars_used_1 (tree *tp, int *wal
 		      void *data ATTRIBUTE_UNUSED)
 {
   tree t = *tp;
+  char const c = TREE_CODE_CLASS (TREE_CODE (t));
+  tree b;
 
   if (TREE_CODE (t) == SSA_NAME)
     t = SSA_NAME_VAR (t);
+  if ((IS_EXPR_CODE_CLASS (c)
+       || IS_GIMPLE_STMT_CODE_CLASS (c))
+      && (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.  */
@@ -431,6 +439,111 @@ mark_all_vars_used_1 (tree *tp, int *wal
   return NULL;
 }
 
+/* Mark the scope block SCOPE and is subblocks unused when they can be
+   possibly eliminated if dead.  */
+
+static void
+mark_scope_block_unused (tree scope)
+{
+  tree t;
+  TREE_USED (scope) = false;
+  if (!(*debug_hooks->ignore_block) (scope))
+    TREE_USED (scope) = true;
+  for (t = BLOCK_SUBBLOCKS (scope); t ; t = BLOCK_CHAIN (t))
+    mark_scope_block_unused (t);
+}
+
+/* Look if the block is dead (by possibly elliminating it's dead subblocks)
+   and return true if so.  
+   Block is declared dead if:
+     1) No statements are associated with it.
+     2) Declares no live variables
+     3) All subblocks are dead
+	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
+   out of scope blocks to let them to be recycled by GGC and to save copying work
+   done by the inliner.
+*/
+
+static bool
+remove_unused_scope_block_p (tree scope)
+{
+  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 reffers 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)
+	{
+	  *t = TREE_CHAIN (*t);
+	  next = t;
+	}
+    }
+
+  for (t = &BLOCK_SUBBLOCKS (scope); *t ;)
+    if (remove_unused_scope_block_p (*t))
+      {
+	if (BLOCK_SUBBLOCKS (*t))
+	  {
+	    tree next = BLOCK_CHAIN (*t);
+	    tree supercontext = BLOCK_SUPERCONTEXT (*t);
+	    *t = BLOCK_SUBBLOCKS (*t);
+	    gcc_assert (!BLOCK_CHAIN (*t));
+	    BLOCK_CHAIN (*t) = next;
+	    BLOCK_SUPERCONTEXT (*t) = supercontext;
+	    t = &BLOCK_CHAIN (*t);
+	    nsubblocks ++;
+	  }
+	else
+          *t = BLOCK_CHAIN (*t);
+      }
+    else
+      {
+        t = &BLOCK_CHAIN (*t);
+	nsubblocks ++;
+      }
+   /* Outer scope is always used.  */
+   if (!BLOCK_SUPERCONTEXT (scope)
+       || TREE_CODE (BLOCK_SUPERCONTEXT (scope)) == FUNCTION_DECL)
+     unused = false;
+   /* If there are more than one live subblocks, it is used.  */
+   else if (nsubblocks > 1)
+     unused = false;
+   /* 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
+	    && (BLOCK_VARS (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;
+}
 
 /* Mark all VAR_DECLS under *EXPR_P as used, so that they won't be 
    eliminated during the tree->rtl conversion process.  */
@@ -452,6 +565,7 @@ remove_unused_locals (void)
   referenced_var_iterator rvi;
   var_ann_t ann;
 
+  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;
@@ -498,7 +612,6 @@ remove_unused_locals (void)
 	  *cell = TREE_CHAIN (*cell);
 	  continue;
 	}
-
       cell = &TREE_CHAIN (*cell);
     }
 
@@ -516,6 +629,7 @@ remove_unused_locals (void)
 	&& !ann->symbol_mem_tag
 	&& !TREE_ADDRESSABLE (t))
       remove_referenced_var (t);
+  remove_unused_scope_block_p (DECL_INITIAL (current_function_decl));
 }
 
 

^ permalink raw reply	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2007-12-18 11:43 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-07-24 18:20 Put scope blocks on a diet Jan Hubicka
2007-07-24 19:23 ` Diego Novillo
2007-08-02  8:59 ` Alexandre Oliva
2007-08-02 23:13   ` Alexandre Oliva
2007-08-03  8:29     ` Jan Hubicka
2007-08-06 20:11     ` Jan Hubicka
2007-08-16 19:04       ` Alexandre Oliva
2007-10-03 17:01       ` Alexandre Oliva
2007-10-03 17:27         ` Jan Hubicka
2007-10-05 18:26           ` Alexandre Oliva
2007-10-03 18:19         ` Richard Guenther
2007-10-07 22:37           ` Jan Hubicka
2007-10-08  5:53             ` Michael Matz
2007-10-08  7:13               ` Jan Hubicka
2007-10-08  7:46                 ` Michael Matz
2007-10-09 21:09         ` Alexandre Oliva
2007-10-10  8:08           ` Alexandre Oliva
2007-10-10  8:20         ` Alexandre Oliva
2007-10-10  8:46           ` Jan Hubicka
2007-10-11  6:20             ` Alexandre Oliva
2007-10-11  8:39               ` Richard Guenther
2007-10-11 22:12                 ` Jan Hubicka
2007-10-12  1:33                   ` Alexandre Oliva
2007-10-12  6:14                     ` Jan Hubicka
2007-11-27 17:37                       ` Richard Guenther
2007-11-27 20:39                         ` Mark Mitchell
2007-11-27 21:34                         ` Alexandre Oliva
2007-11-27 21:59                           ` Mark Mitchell
2007-11-27 23:14                             ` Jan Hubicka
2007-11-28  1:10                             ` Alexandre Oliva
2007-11-28  1:15                               ` Richard Guenther
2007-11-28  1:17                               ` Mark Mitchell
2007-11-28  8:12                                 ` Alexandre Oliva
2007-11-28  9:34                                   ` Mark Mitchell
2007-11-29 10:14                                     ` Alexandre Oliva
2007-11-28  8:54                                 ` Alexandre Oliva
2007-11-27 22:08                           ` Richard Guenther
2007-11-28  1:08                             ` Alexandre Oliva
2007-11-28  1:10                               ` Richard Guenther
2007-11-28  3:28                                 ` Alexandre Oliva
2007-11-28 14:30                                   ` Richard Guenther
2007-11-28 20:51                                     ` Mark Mitchell
2007-11-28 23:10                                       ` Richard Guenther
2007-11-28 23:21                                         ` Mark Mitchell
2007-11-29  1:26                                           ` Richard Guenther
2007-11-29  9:56                                           ` Alexandre Oliva
2007-11-29 17:01                                             ` Jan Hubicka
2007-11-29 18:29                                             ` Mark Mitchell
2007-11-29 19:43                                               ` Richard Guenther
2007-11-29 21:29                                                 ` Mark Mitchell
2007-11-30 11:14                                                   ` Alexandre Oliva
2007-11-29 21:36                                               ` Jan Hubicka
2007-11-29 21:38                                                 ` Mark Mitchell
2007-11-29 22:06                                                   ` Jan Hubicka
2007-11-29 22:34                                                     ` Mark Mitchell
2007-11-30  1:02                                                       ` Richard Guenther
2007-11-28 23:02                                     ` Alexandre Oliva
2007-11-28 23:15                                       ` Richard Guenther
2007-11-29 10:16                                         ` Alexandre Oliva
2007-11-29 13:36                                           ` Richard Guenther
2007-11-30 10:53                                             ` Alexandre Oliva
2007-11-29 17:30                                           ` Jan Hubicka
2007-12-15 21:59                                             ` Alexandre Oliva
2007-12-18 11:50                                               ` Jan Hubicka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).