This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-ssa] Further reduce memory consumption in tree-ssa code



This is further work to reduce the memory usage for Gerald's favorite PR.

The fundamental issue with this patch is to avoid silly allocations of
virtual arrays and other short lived data structures in the dominator
walk.

For those not familiar with the dominator walker's structure, we have
the ability to record per-block information onto a stack.  When we're
done processing a block, that per-block information is released.

This is what allows us to restore the state of the main hash table
as we pop up the dominator tree.

The problem with this structure is that, well, you allocate the
block local datastructure and anything hanging off that structure
for every block you visit.  We were doing this the lazy way -- just
allocate whatever we need and let the collector sort it out later.

I'd expected this to need to rework this code.  The recent focus on
memory issues and knowing that some upcoming work would make this
situation worse simply gave me the excuse to do so.

What I've done is move the management of the block local data into the
dominator walker itself.  This allows us to re-use the toplevel structure
for local data.  This is completely and totally managed inside the
dominator walker.  Rather than using GC memory for this structure, we use
xmalloc/free.

The dominator walker doesn't know the contents of that structure, so the
job of managing things like varrays which might be hung off the structure
is the job of the callback which initializes the block local data.

That's all and good.  What are the real world results.  For PR8361 we
save another 20M or so and have *far* fewer objects for the GC system
to manage.  We also get a nice little speedup for PR8361 as well as
the more general components of cc1 test.

We don't try and cache any information across calls into the dominator
walker.    This means (for example) that the dominator based jump threader
and the dominator optimizer can't share any data, even though their
datastructures are the same.  SImilarly for the two distinct calls into
the dominator optimizer.

Luckily, I believe Andrew knows how to solve the fundamental problem which
prevents dominator based jump threading from being integrated with the
dominator optimizer.  That will help things further :-)

Bootstrapped and regression tested i686-pc-linux-gnu.

	* Makefile.in (domwalk.o): Depend on $(GGC_H).
	* domwalk.c: Include ggc.h.
	(walk_dominator_tree): Manage allocation/deallocation and
	pushing/popping of the toplevel block data pointer here.
	Use callback to initialize the block local data.
	(init_walk_dominator_tree): New function.
	(fini_walk_dominator_tree): Likewise.
	* domwalk.h (struct dom_walk_data): Add callback to initialize
	block local data.  Add field for sizeof block local data.
	Add "private" field free_block_data.
	(init_dominator_tree, fini_dominator_tree): Prototype.
	* tree-ssa-dom.c (dom_opt_initialize_local_data): New function.
	(tree_ssa_dominator_optimize_1): Initialize new fields in the
	dominator walker structure.  Initialize and finalize the dominator
	walker.  Slightly reorder code to make it more readable..
	(dom_opt_initialize_block): No longer deal with allocation and
	initialization of block local data.
	(dom_opt_finalize_block): Similarly for deallocation of block
	local data.
	* tree-ssa.c (rewrite_block_data): New structure.
	(rewrite_initialize_block_local_data): New function.
	(rewrite_initialize_block): No longer deal with allocation and
	initialization of block local data.
	(rewrite_into_ssa): Initialize new fields in the dominator walker
	structure.  Initialize and finalize the dominator walker.
	(rewrite_initialize_block): No longer deal with allocation and
	initialization of block local data.
	(rewrite_optimize_stmts): Deal with changes in the dominator
	walker structure.
	(rewrite_finalize_block): No longer with deallocation of block
	local data.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.138
diff -c -3 -p -r1.903.2.138 Makefile.in
*** Makefile.in	21 Nov 2003 23:17:16 -0000	1.903.2.138
--- Makefile.in	22 Nov 2003 03:48:03 -0000
*************** tree-ssa-dom.o : tree-ssa-dom.c $(TREE_F
*** 1559,1565 ****
  tree-ssanames.o : tree-ssanames.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(TREE_H) varray.h
  domwalk.o : domwalk.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
!    $(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) domwalk.h
  tree-ssa-live.o : tree-ssa-live.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h diagnostic.h \
     ssa.h errors.h toplev.h function.h $(TIMEVAR_H) tree-alias-common.h \
--- 1559,1565 ----
  tree-ssanames.o : tree-ssanames.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(TREE_H) varray.h
  domwalk.o : domwalk.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
!    $(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) domwalk.h $(GGC_H)
  tree-ssa-live.o : tree-ssa-live.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h diagnostic.h \
     ssa.h errors.h toplev.h function.h $(TIMEVAR_H) tree-alias-common.h \
Index: domwalk.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/domwalk.c,v
retrieving revision 1.1.2.3
diff -c -3 -p -r1.1.2.3 domwalk.c
*** domwalk.c	30 Oct 2003 21:53:00 -0000	1.1.2.3
--- domwalk.c	22 Nov 2003 03:48:03 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 27,32 ****
--- 27,33 ----
  #include "basic-block.h"
  #include "tree-flow.h"
  #include "domwalk.h"
+ #include "ggc.h"
  
  /* This file implements a generic walker for dominator trees.  */
  
*************** walk_dominator_tree (struct dom_walk_dat
*** 60,65 ****
--- 61,90 ----
  		     tree last)
  {
    bitmap children;
+   void *bd = NULL;
+ 
+   /* Callback to initialize the local data structure.  */
+   if (walk_data->initialize_block_local_data)
+     {
+       /* First get some local data, reusing any local data pointer we may
+ 	 have saved.  */
+       if (VARRAY_ACTIVE_SIZE (walk_data->free_block_data) > 0)
+ 	{
+ 	  bd = VARRAY_TOP_GENERIC_PTR (walk_data->free_block_data);
+ 	  VARRAY_POP (walk_data->free_block_data);
+ 	}
+       else
+ 	{
+ 	  bd = xcalloc (1, walk_data->block_local_data_size);
+ 	}
+ 
+       /* Push the local data into the local data stack.  */
+       VARRAY_PUSH_GENERIC_PTR (walk_data->block_data_stack, bd);
+ 
+       /* Call the initializer.  */
+       walk_data->initialize_block_local_data (walk_data, bb, last);
+ 
+     }
  
    /* Callback for operations to execute before we have walked the
       dominator children, but before we walk statements.  */
*************** walk_dominator_tree (struct dom_walk_dat
*** 112,115 ****
--- 137,177 ----
       dominator children and after we have walked statements.  */
    if (walk_data->after_dom_children_after_stmts)
      (*walk_data->after_dom_children_after_stmts) (walk_data, bb, last);
+ 
+   if (walk_data->initialize_block_local_data)
+     {
+       /* And save the block data so that we can re-use it.  */
+       VARRAY_PUSH_GENERIC_PTR (walk_data->free_block_data, bd);
+ 
+       /* And finally pop the record off the block local data stack.  */
+       VARRAY_POP (walk_data->block_data_stack);
+     }
+ }
+ 
+ void
+ init_walk_dominator_tree (struct dom_walk_data *walk_data)
+ {
+   if (walk_data->initialize_block_local_data)
+     {
+       VARRAY_GENERIC_PTR_INIT (walk_data->free_block_data, 2, "freelist ");
+       VARRAY_GENERIC_PTR_INIT (walk_data->block_data_stack, 2, "block_data");
+     }
+   else
+     {
+       walk_data->free_block_data = NULL;
+       walk_data->block_data_stack = NULL;
+     }
+ }
+ 
+ void
+ fini_walk_dominator_tree (struct dom_walk_data *walk_data)
+ {
+   if (walk_data->initialize_block_local_data)
+     {
+       while (VARRAY_ACTIVE_SIZE (walk_data->free_block_data) > 0)
+ 	{
+ 	  free (VARRAY_TOP_GENERIC_PTR (walk_data->free_block_data));
+ 	  VARRAY_POP (walk_data->free_block_data);
+ 	}
+     }
  }
Index: domwalk.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/domwalk.h,v
retrieving revision 1.1.2.2
diff -c -3 -p -r1.1.2.2 domwalk.h
*** domwalk.h	4 Nov 2003 06:12:46 -0000	1.1.2.2
--- domwalk.h	22 Nov 2003 03:48:03 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 25,30 ****
--- 25,42 ----
  
  struct dom_walk_data
  {
+   /* Function to initialize block local data.
+ 
+      Note that the dominator walker infrastructure may provide a new
+      fresh, and zero'd block local data structure, or it may re-use an
+      existing block local data structure.
+ 
+      If the block local structure has items such as virtual arrays, then
+      that allows your optimizer to re-use those arrays rather than
+      creating new ones.  */
+   void (*initialize_block_local_data) (struct dom_walk_data *,
+ 				       basic_block, tree);
+ 
    /* Function to call before the statement walk occurring before the
       recursive walk of the dominator children. 
  
*************** struct dom_walk_data
*** 64,71 ****
    /* Global data for a walk through the dominator tree.  */
    void *global_data;
  
!   /* Stack of any data we need to keep on a per-block basis.  */
    varray_type block_data_stack;
  };
  
  void walk_dominator_tree (struct dom_walk_data *, basic_block, tree);
--- 76,97 ----
    /* Global data for a walk through the dominator tree.  */
    void *global_data;
  
!   /* Stack of any data we need to keep on a per-block basis.
! 
!      If you have no local data, then BLOCK_DATA_STACK will be NULL.  */
    varray_type block_data_stack;
+ 
+   /* Size of the block local data.   If this is zero, then it is assumed
+      you have no local data and thus no BLOCK_DATA_STACK as well.  */
+   size_t block_local_data_size;
+ 
+   /* From here below are private data.  Please do not use this
+      information/data outside domwalk.c.  */
+ 
+   /* Stack of available block local structures.   */
+   varray_type free_block_data;
  };
  
  void walk_dominator_tree (struct dom_walk_data *, basic_block, tree);
+ void init_walk_dominator_tree (struct dom_walk_data *);
+ void fini_walk_dominator_tree (struct dom_walk_data *);
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.85
diff -c -3 -p -r1.1.2.85 tree-ssa-dom.c
*** tree-ssa-dom.c	21 Nov 2003 23:12:35 -0000	1.1.2.85
--- tree-ssa-dom.c	22 Nov 2003 03:48:10 -0000
*************** static void record_equivalences_from_stm
*** 224,229 ****
--- 224,231 ----
  					   int, stmt_ann_t);
  static void thread_across_edge (edge);
  static void dom_opt_finalize_block (struct dom_walk_data *, basic_block, 
tree);
+ static void dom_opt_initialize_block_local_data (struct dom_walk_data *,
+ 						 basic_block, tree);
  static void dom_opt_initialize_block (struct dom_walk_data *,
  				      basic_block, tree);
  static void dom_opt_walk_stmts (struct dom_walk_data *, basic_block, tree);
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 349,363 ****
    VARRAY_EDGE_INIT (edges_to_redirect, 20, "edges_to_redirect");
    VARRAY_BB_INIT (redirection_targets, 20, "redirection_targets");
    VARRAY_GENERIC_PTR_INIT (vrp_data, highest_ssa_version, "vrp_data");
-   VARRAY_GENERIC_PTR_INIT (walk_data.block_data_stack, 2, "block_data");
  
  
    /* Setup callbacks for the generic dominator tree walker.  */
    walk_data.before_dom_children_before_stmts = dom_opt_initialize_block;
    walk_data.after_dom_children_before_stmts = NULL;
    walk_data.after_dom_children_walk_stmts = NULL;
    walk_data.after_dom_children_after_stmts = dom_opt_finalize_block;
    walk_data.global_data = NULL;
  
    /* Customize walker based on whether or not we are threading jumps
       through blocks with PHI nodes or not.  */
--- 351,366 ----
    VARRAY_EDGE_INIT (edges_to_redirect, 20, "edges_to_redirect");
    VARRAY_BB_INIT (redirection_targets, 20, "redirection_targets");
    VARRAY_GENERIC_PTR_INIT (vrp_data, highest_ssa_version, "vrp_data");
  
  
    /* Setup callbacks for the generic dominator tree walker.  */
+   walk_data.initialize_block_local_data = dom_opt_initialize_block_local_data
;
    walk_data.before_dom_children_before_stmts = dom_opt_initialize_block;
    walk_data.after_dom_children_before_stmts = NULL;
    walk_data.after_dom_children_walk_stmts = NULL;
    walk_data.after_dom_children_after_stmts = dom_opt_finalize_block;
    walk_data.global_data = NULL;
+   walk_data.block_local_data_size = sizeof (struct dom_walk_block_data);
  
    /* Customize walker based on whether or not we are threading jumps
       through blocks with PHI nodes or not.  */
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 372,377 ****
--- 375,388 ----
        walk_data.before_dom_children_after_stmts = cprop_into_phis;
      }
  
+   /* Now initialize the dominator walker.  */
+   init_walk_dominator_tree (&walk_data);
+ 
+   /* Reset block_forwardable in each block's annotation.  We use that
+      attribute when threading through COND_EXPRs.  */
+   FOR_EACH_BB (bb)
+     bb_ann (bb)->forwardable = 1;
+ 
    /* Build the dominator tree if necessary. 
  
       We don't have a flag indicating if the dominator tree is available,
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 382,392 ****
      if (dom_children (e->dest))
        break;
  
-   /* Reset block_forwardable in each block's annotation.  We use that
-      attribute when threading through COND_EXPRs.  */
-   FOR_EACH_BB (bb)
-     bb_ann (bb)->forwardable = 1;
- 
    /* If we did not find any dominator children in the successors of the
       entry block, then rebuild the dominator tree.  */
    if (e == NULL)
--- 393,398 ----
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 512,517 ****
--- 518,526 ----
    VARRAY_FREE (edges_to_redirect);
    VARRAY_FREE (redirection_targets);
  
+   /* And finalize the dominator walker.  */
+   fini_walk_dominator_tree (&walk_data);
+ 
    timevar_pop (timevar);
  }
  
*************** thread_across_edge (edge e)
*** 593,598 ****
--- 602,666 ----
      }
  }
  
+ 
+ /* Initialize the local stacks.
+      
+    AVAIL_EXPRS stores all the expressions made available in this block.
+ 
+    TRUE_EXPRS stores all expressions with a true value made in this block.
+ 
+    FALSE_EXPRS stores all expressions with a false value made in this block.
+ 
+    CONST_AND_COPIES stores var/value pairs to restore at the end of this
+    block.
+ 
+    NONZERO_VARS stores the vars which have a nonzero value made in this
+    block.
+ 
+    STMTS_TO_RESCAN is a list of statements we will rescan for operands.
+ 
+    VRP_VARIABLES is the list of variables which have had their values
+    constrained by an operation in this block.
+ 
+    These stacks are cleared in the finalization routine run for each
+    block.  */
+ 
+ static void
+ dom_opt_initialize_block_local_data (struct dom_walk_data *walk_data,
+ 				     basic_block bb ATTRIBUTE_UNUSED,
+ 			             tree parent_block_last_stmt ATTRIBUTE_UNUSED)
+ {
+   struct dom_walk_block_data *bd
+     = (struct dom_walk_block_data *)VARRAY_TOP_GENERIC_PTR (walk_data->
block_data_stack);
+ 
+   /* We get cleared memory from the allocator, so if the memory is not
+      cleared, then we are re-using a previously allocated entry.  In
+      that case, we can also re-use the underlying virtual arrays.  Just
+      make sure we clear them before using them!  */
+   if (bd->avail_exprs)
+     {
+       VARRAY_CLEAR (bd->avail_exprs);
+       VARRAY_CLEAR (bd->true_exprs);
+       VARRAY_CLEAR (bd->false_exprs);
+       VARRAY_CLEAR (bd->const_and_copies);
+       VARRAY_CLEAR (bd->nonzero_vars);
+       VARRAY_CLEAR (bd->stmts_to_rescan);
+       VARRAY_CLEAR (bd->vrp_variables);
+     }
+   else
+     {
+       /* The allocator gave us a new block data structure, so we must
+ 	 initialize new arrays.  */
+       VARRAY_TREE_INIT (bd->avail_exprs, 20, "block_avail_exprs");
+       VARRAY_TREE_INIT (bd->true_exprs, 2, "block_true_exprs");
+       VARRAY_TREE_INIT (bd->false_exprs, 2, "block_false_exprs");
+       VARRAY_TREE_INIT (bd->const_and_copies, 2, "block_const_and_copies");
+       VARRAY_TREE_INIT (bd->nonzero_vars, 2, "block_nonzero_vars");
+       VARRAY_TREE_INIT (bd->stmts_to_rescan, 20, "stmts_to_rescan");
+       VARRAY_TREE_INIT (bd->vrp_variables, 2, "vrp_variables");
+     }
+ }
+ 
  /* Initialize local stacks for this optimizer and record equivalences
     upon entry to BB.  Equivalences can come from the edge traversed to
     reach BB or they may come from PHI nodes at the start of BB.  */
*************** dom_opt_initialize_block (struct dom_wal
*** 602,638 ****
  			  basic_block bb,
  			  tree parent_block_last_stmt)
  {
-   struct dom_walk_block_data *bd;
- 
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "\n\nOptimizing block #%d\n\n", bb->index);
  
-   /* Initialize the local stacks.
-      
-      AVAIL_EXPRS stores all the expressions made available in this block.
- 
-      CONST_AND_COPIES stores var/value pairs to restore at the end of this
-      block.
- 
-      STMTS_TO_RESCAN is a list of statements we will rescan for operands.
- 
-      VRP_VARIABLES is the list of variables which have had their values
-      constrained by an operation in this block.
- 
-      These stacks are cleared in the finalization routine run for each
-      block.  */
-   bd = ggc_alloc (sizeof (struct dom_walk_block_data));
-   VARRAY_TREE_INIT (bd->avail_exprs, 20, "block_avail_exprs");
-   VARRAY_TREE_INIT (bd->true_exprs, 2, "block_true_exprs");
-   VARRAY_TREE_INIT (bd->false_exprs, 2, "block_false_exprs");
-   VARRAY_TREE_INIT (bd->const_and_copies, 2, "block_const_and_copies");
-   VARRAY_TREE_INIT (bd->nonzero_vars, 2, "block_nonzero_vars");
-   VARRAY_TREE_INIT (bd->stmts_to_rescan, 20, "stmts_to_rescan");
-   VARRAY_TREE_INIT (bd->vrp_variables, 2, "vrp_variables");
- 
-   /* Push this block record onto the stack of block records.  */
-   VARRAY_PUSH_GENERIC_PTR (walk_data->block_data_stack, bd);
- 
    record_equivalences_from_incoming_edge (walk_data, bb,
  					  parent_block_last_stmt);
  
--- 670,678 ----
*************** dom_opt_finalize_block (struct dom_walk_
*** 831,839 ****
        VARRAY_POP (stmts_to_rescan);
        mark_new_vars_to_rename (stmt, vars_to_rename);
      }
- 
-   /* And finally pop the record off the block local data.  */
-   VARRAY_POP (walk_data->block_data_stack);
  }
  
  /* PHI nodes can create equivalences too.
--- 871,876 ----
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.159
diff -c -3 -p -r1.1.4.159 tree-ssa.c
*** tree-ssa.c	21 Nov 2003 23:12:36 -0000	1.1.4.159
--- tree-ssa.c	22 Nov 2003 03:48:14 -0000
*************** struct ssa_stats_d
*** 160,165 ****
--- 160,170 ----
    long num_stmts;
  };
  
+ struct rewrite_block_data
+ {
+   varray_type block_defs;
+ };
+ 
  static struct ssa_stats_d ssa_stats;
  
  /* Bitmap representing variables that need to be renamed into SSA form.  */
*************** static sbitmap vars_to_rename;
*** 168,173 ****
--- 173,180 ----
  
  /* Local functions.  */
  static void rewrite_finalize_block (struct dom_walk_data *, basic_block, 
tree);
+ static void rewrite_initialize_block_local_data (struct dom_walk_data *,
+ 						 basic_block, tree);
  static void rewrite_initialize_block (struct dom_walk_data *,
  				      basic_block, tree);
  static void rewrite_walk_stmts (struct dom_walk_data *, basic_block, tree);
*************** rewrite_into_ssa (tree fndecl, sbitmap v
*** 391,403 ****
  
    /* Setup callbacks for the generic dominator tree walker to find and
       mark definition sites.  */
!   walk_data.block_data_stack = NULL;
    walk_data.before_dom_children_before_stmts = NULL;
    walk_data.before_dom_children_walk_stmts = mark_def_sites;
    walk_data.before_dom_children_after_stmts = NULL; 
    walk_data.after_dom_children_before_stmts =  NULL;
    walk_data.after_dom_children_walk_stmts =  NULL;
    walk_data.after_dom_children_after_stmts =  NULL;
    /* Notice that this bitmap is indexed using variable UIDs, so it must be
       large enough to accommodate all the variables referenced in the
       function, not just the ones we are renaming.  */
--- 398,411 ----
  
    /* Setup callbacks for the generic dominator tree walker to find and
       mark definition sites.  */
!   walk_data.initialize_block_local_data = NULL;
    walk_data.before_dom_children_before_stmts = NULL;
    walk_data.before_dom_children_walk_stmts = mark_def_sites;
    walk_data.before_dom_children_after_stmts = NULL; 
    walk_data.after_dom_children_before_stmts =  NULL;
    walk_data.after_dom_children_walk_stmts =  NULL;
    walk_data.after_dom_children_after_stmts =  NULL;
+ 
    /* Notice that this bitmap is indexed using variable UIDs, so it must be
       large enough to accommodate all the variables referenced in the
       function, not just the ones we are renaming.  */
*************** rewrite_into_ssa (tree fndecl, sbitmap v
*** 405,413 ****
--- 413,430 ----
    mark_def_sites_global_data.idom = idom;
    walk_data.global_data = &mark_def_sites_global_data;
  
+   /* We do not have any local data.  */
+   walk_data.block_local_data_size = 0;
+ 
+   /* Initialize the dominator walker.  */
+   init_walk_dominator_tree (&walk_data);
+ 
    /* Recursively walk the dominator tree.  */
    walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR, NULL);
  
+   /* Finalize the dominator walker.  */
+   fini_walk_dominator_tree (&walk_data);
+ 
    /* We no longer need this bitmap, clear and free it.  */
    sbitmap_free (mark_def_sites_global_data.kills);
  
*************** rewrite_into_ssa (tree fndecl, sbitmap v
*** 421,427 ****
    timevar_push (TV_TREE_SSA_REWRITE_BLOCKS);
  
    /* Setup callbacks for the generic dominator tree walker.  */
!   VARRAY_GENERIC_PTR_INIT (walk_data.block_data_stack, 2, "block_data");
    walk_data.before_dom_children_before_stmts = rewrite_initialize_block;
    walk_data.before_dom_children_walk_stmts = rewrite_walk_stmts;
    walk_data.before_dom_children_after_stmts = rewrite_add_phi_arguments; 
--- 438,444 ----
    timevar_push (TV_TREE_SSA_REWRITE_BLOCKS);
  
    /* Setup callbacks for the generic dominator tree walker.  */
!   walk_data.initialize_block_local_data = rewrite_initialize_block_local_data
;
    walk_data.before_dom_children_before_stmts = rewrite_initialize_block;
    walk_data.before_dom_children_walk_stmts = rewrite_walk_stmts;
    walk_data.before_dom_children_after_stmts = rewrite_add_phi_arguments; 
*************** rewrite_into_ssa (tree fndecl, sbitmap v
*** 429,438 ****
--- 446,463 ----
    walk_data.after_dom_children_walk_stmts =  NULL;
    walk_data.after_dom_children_after_stmts =  rewrite_finalize_block;
    walk_data.global_data = NULL;
+   walk_data.block_local_data_size = sizeof (struct rewrite_block_data);
+ 
+   /* Initialize the dominator walker.  */
+   init_walk_dominator_tree (&walk_data);
  
    /* Recursively walk the dominator tree rewriting each statement in
       each basic block.  */
    walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR, NULL);
+ 
+   /* Finalize the dominator walker.  */
+   fini_walk_dominator_tree (&walk_data);
+ 
    timevar_pop (TV_TREE_SSA_REWRITE_BLOCKS);
  
    /* Debugging dumps.  */
*************** insert_phi_nodes (bitmap *dfs)
*** 798,803 ****
--- 823,853 ----
        definitions are restored to the names that were valid in the
        dominator parent of BB.  */
  
+ /* Initialize the local stacks.
+      
+    BLOCK_DEFS is used to save all the existing reaching definitions for
+    the new SSA names introduced in this block.  Before registering a
+    new definition for a variable, the existing reaching definition is
+    pushed into this stack so that we can restore it in Step 5.  */
+ 
+ static void
+ rewrite_initialize_block_local_data (struct dom_walk_data *walk_data,
+ 				     basic_block bb ATTRIBUTE_UNUSED,
+ 				     tree parent_block_last_stmt ATTRIBUTE_UNUSED)
+ {
+   struct rewrite_block_data *bd
+     = (struct rewrite_block_data *)VARRAY_TOP_GENERIC_PTR (walk_data->
block_data_stack);
+                                                                              

+   /* We get cleared memory from the allocator, so if the memory is
+      not cleared, then we are re-using a previously allocated entry.  In
+      that case, we can also re-use the underlying virtal arrays.  Just
+      make sure we clear them before using them!  */
+   if (bd->block_defs)
+     VARRAY_CLEAR (bd->block_defs);
+   else
+     VARRAY_TREE_INIT (bd->block_defs, 20, "block_defs");
+ }
+ 
  /* SSA Rewriting Step 1.  Initialization, create a block local stack
     of reaching definitions for new SSA names produced in this block
     (BLOCK_DEFS).  Register new definitions for every PHI node in the
*************** rewrite_initialize_block (struct dom_wal
*** 808,836 ****
  			  basic_block bb,
  			  tree parent_block_last_stmt ATTRIBUTE_UNUSED)
  {
-   varray_type block_defs;
-   varray_type *block_defs_p;
    tree phi;
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "\n\nRenaming block #%d\n\n", bb->index);
  
-   /* Initialize the local stacks.
-      
-      BLOCK_DEFS is used to save all the existing reaching definitions for
-      the new SSA names introduced in this block.  Before registering a
-      new definition for a variable, the existing reaching definition is
-      pushed into this stack so that we can restore it in Step 5.  */
-   VARRAY_TREE_INIT (block_defs, 20, "block_defs");
- 
-   /* Now push this block's BLOCK_DEFs onto the stack of block local data.  */
-   VARRAY_PUSH_GENERIC_PTR (walk_data->block_data_stack, block_defs);
- 
-   /* We want a pointer to BLOCK_DEFS as stored in BLOCK_DATA_STACK, not the
-      address of the local variable BLOCK_DEFS.  */
-   block_defs_p
-     = (varray_type *) &VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
- 
    /* Step 1.  Register new definitions for every PHI node in the block.
       Conceptually, all the PHI nodes are executed in parallel and each PHI
       node introduces a new version for the associated variable.  */
--- 858,870 ----
  			  basic_block bb,
  			  tree parent_block_last_stmt ATTRIBUTE_UNUSED)
  {
    tree phi;
+   struct rewrite_block_data *bd
+     = (struct rewrite_block_data *)VARRAY_TOP_GENERIC_PTR (walk_data->
block_data_stack);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "\n\nRenaming block #%d\n\n", bb->index);
  
    /* Step 1.  Register new definitions for every PHI node in the block.
       Conceptually, all the PHI nodes are executed in parallel and each PHI
       node introduces a new version for the associated variable.  */
*************** rewrite_initialize_block (struct dom_wal
*** 838,844 ****
      {
        tree result = PHI_RESULT (phi);
  
!       register_new_def (SSA_NAME_VAR (result), result, block_defs_p);
      }
  }
  
--- 872,878 ----
      {
        tree result = PHI_RESULT (phi);
  
!       register_new_def (SSA_NAME_VAR (result), result, &bd->block_defs);
      }
  }
  
*************** rewrite_walk_stmts (struct dom_walk_data
*** 852,862 ****
  		    tree parent_block_last_stmt ATTRIBUTE_UNUSED)
  {
    block_stmt_iterator si;
!   varray_type *block_defs_p
!     = (varray_type *) &VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
  
    for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
!     rewrite_stmt (si, block_defs_p);
  }
  
  
--- 886,896 ----
  		    tree parent_block_last_stmt ATTRIBUTE_UNUSED)
  {
    block_stmt_iterator si;
!   struct rewrite_block_data *bd
!     = (struct rewrite_block_data *)VARRAY_TOP_GENERIC_PTR (walk_data->
block_data_stack);
  
    for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
!     rewrite_stmt (si, &bd->block_defs);
  }
  
  
*************** rewrite_finalize_block (struct dom_walk_
*** 900,931 ****
  			basic_block bb ATTRIBUTE_UNUSED,
  			tree parent_block_last_stmt ATTRIBUTE_UNUSED)
  {
!   varray_type block_defs
!     = VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
  
    /* Step 5.  Restore the current reaching definition for each variable
       referenced in the block (in reverse order).  */
!   while (VARRAY_ACTIVE_SIZE (block_defs) > 0)
      {
        tree var;
!       tree saved_def = VARRAY_TOP_TREE (block_defs);
!       VARRAY_POP (block_defs);
        
        /* If SAVED_DEF is NULL, then the next slot in the stack contains the
  	 variable associated with SAVED_DEF.  */
        if (saved_def == NULL_TREE)
  	{
! 	  var = VARRAY_TOP_TREE (block_defs);
! 	  VARRAY_POP (block_defs);
  	}
        else
  	var = SSA_NAME_VAR (saved_def);
  
        set_value_for (var, saved_def, currdefs);
      }
- 
-   /* And remove this block's local data off BLOCK_DATA_STACK.  */
-   VARRAY_POP (walk_data->block_data_stack);
  }
  
  /* This function will create a temporary for a partition based on the
--- 934,962 ----
  			basic_block bb ATTRIBUTE_UNUSED,
  			tree parent_block_last_stmt ATTRIBUTE_UNUSED)
  {
!   struct rewrite_block_data *bd
!     = (struct rewrite_block_data *)VARRAY_TOP_GENERIC_PTR (walk_data->
block_data_stack);
  
    /* Step 5.  Restore the current reaching definition for each variable
       referenced in the block (in reverse order).  */
!   while (VARRAY_ACTIVE_SIZE (bd->block_defs) > 0)
      {
        tree var;
!       tree saved_def = VARRAY_TOP_TREE (bd->block_defs);
!       VARRAY_POP (bd->block_defs);
        
        /* If SAVED_DEF is NULL, then the next slot in the stack contains the
  	 variable associated with SAVED_DEF.  */
        if (saved_def == NULL_TREE)
  	{
! 	  var = VARRAY_TOP_TREE (bd->block_defs);
! 	  VARRAY_POP (bd->block_defs);
  	}
        else
  	var = SSA_NAME_VAR (saved_def);
  
        set_value_for (var, saved_def, currdefs);
      }
  }
  
  /* This function will create a temporary for a partition based on the



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]