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] Improve jump threading


So after a long delay, here's the next in a series of patches to improve
jump threading.

One of the fundamental limitations of the existing jump threading
in the dominator optimizer is that it could not thread through a PHI
once we did anything that extended the lifetime of a variable.

This restriction was necessary to ensure that after threading
through a PHI we could drop all the SSA_NAMEs for the variable
referenced/set by the PHI, update the CFG, then re-rewrite
that variable back into SSA form.

Unfortunately, with that restriction in place the dominator based
jump threader was unable to take advantage of many threading
opportunities created by the dominator optimizer, CCP, DCE, etc etc.

Recently Andrew slightly reorganized the out-of-ssa code and made
it amazingly easy to actually run the out-of-ssa pass on a select
set of variables.  So, instead of just droping the SSA_NAMEs when
we thread through PHIs, we can instead actually translate them
out of SSA form using our existing out-of-ssa code (which handles
overlapping lifetimes and such).

Ultimately this means that the restriction for threading through 
PHIs can be lifted and we can eliminate the separate jump threading
pass.

When building the components of cc1, these changes increase the number
of jump threading opportunities we find by ~15%.  We also get a ~1%
improvement in compile times.

Oh yea, before I forget, by combining the passes we also get a nice
memory reduction for Gerald's testcase in addition to a 1% speedup :-)
I don't have data handy anymore, but it was something like a 20M reduction
in the amount of memory allocated by the GC system (presumably due to fewer
varrays) and 1-2M reduction in persistent memory (likely due to less
fragmentation of memory due to allocating fewer GC nodes).

This has been bootstrapped and regression tested (several times over the
last week) on i686-pc-linux-gnu.  Whee.  The thread_across_edge changes
are mostly reindention.

There's a minor testsuite change now that the thread dump file is
gone.  I'll check that in separately.

Expect more improvement to come now that the major blocker to progress
has been lifted....

        * timevar.def (TV_TREE_SSA_THREAD_JUMPS): Kill.
        * tree-dump.c (dump_files): Kill .thread dump.
	* tree.h (TDI_thread_jumps): Kill.
        * tree-flow.h (tree_ssa_dominator_thread_jumps): Kill prototype.
        * tree-optimize.c (optimize_function_tree): Kill call to
        tree_ssa_dominator_thread_jumps.
        * tree-ssa-dom.c (thread_through_phis): Kill.  We no longer need
        to restrict threading through PHIs.
        (tree_ssa_dominator_thread_jumps): Kill.
        (tree_ssa_domiantor_optimize_1): Fold back into
        tree_ssa_dominator_optimize.
        (tree_ssa_dominator_optimize): Mark back edges in the flow graph.
        Kill code which conditionalized the walk_tree callbacks based
        on thread_through_phis.  When threading jumps, reorganize code
        so that we can take the affected variables out of SSA form.
        Mark new variables created by out-of-ssa code as needing to be
        rewritten.
        (thread_across_edge): Always allow threading through phis.
        (thread_jumps_walk_stmts): Kill.

Index: timevar.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/timevar.def,v
retrieving revision 1.14.2.26
diff -c -3 -p -r1.14.2.26 timevar.def
*** timevar.def	6 Dec 2003 12:31:27 -0000	1.14.2.26
--- timevar.def	13 Dec 2003 07:03:13 -0000
*************** DEFTIMEVAR (TV_TREE_INSERT_PHI_NODES , "
*** 70,76 ****
  DEFTIMEVAR (TV_TREE_SSA_REWRITE_BLOCKS, "tree SSA rewrite")
  DEFTIMEVAR (TV_TREE_SSA_OTHER	     , "tree SSA other")
  DEFTIMEVAR (TV_TREE_DFA	             , "tree dataflow analysis")
- DEFTIMEVAR (TV_TREE_SSA_THREAD_JUMPS , "tree thread jumps")
  DEFTIMEVAR (TV_TREE_SSA_DOMINATOR_OPTS   , "dominator optimization")
  DEFTIMEVAR (TV_TREE_SRA              , "tree SRA")
  DEFTIMEVAR (TV_TREE_CCP		     , "tree CCP")
--- 70,75 ----
Index: tree-dump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dump.c,v
retrieving revision 1.6.2.59
diff -c -3 -p -r1.6.2.59 tree-dump.c
*** tree-dump.c	8 Dec 2003 20:29:26 -0000	1.6.2.59
--- tree-dump.c	13 Dec 2003 07:03:14 -0000
*************** static struct dump_file_info dump_files[
*** 661,667 ****
    {".pta", "tree-pta", 0, 0},
    {".alias", "tree-alias", 0, 0},
    {".ssa1", "tree-ssa1", 0, 0},
-   {".thread", "tree-jumpthread", 0, 0},
    {".dom1", "tree-dom1", 0, 0},
    {".ssa2", "tree-ssa2", 0, 0},
    {".dce1", "tree-dce1", 0, 0},
--- 661,666 ----
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.168
diff -c -3 -p -r1.1.4.168 tree-flow.h
*** tree-flow.h	13 Dec 2003 05:14:27 -0000	1.1.4.168
--- tree-flow.h	13 Dec 2003 07:03:14 -0000
*************** bool fold_stmt (tree *);
*** 533,539 ****
  tree widen_bitfield (tree, tree, tree);
  
  /* In tree-ssa-dom.c  */
- extern void tree_ssa_dominator_thread_jumps (tree, enum tree_dump_index);
  extern void tree_ssa_dominator_optimize (tree, bitmap, enum tree_dump_index);
  extern void dump_dominator_optimization_stats (FILE *);
  extern void debug_dominator_optimization_stats (void);
--- 533,538 ----
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.92
diff -c -3 -p -r1.1.4.92 tree-optimize.c
*** tree-optimize.c	9 Dec 2003 15:39:11 -0000	1.1.4.92
--- tree-optimize.c	13 Dec 2003 07:03:16 -0000
*************** optimize_function_tree (tree fndecl, tre
*** 112,119 ****
        /* Perform dominator optimizations.  */
        if (flag_tree_dom)
  	{
- 	  tree_ssa_dominator_thread_jumps (fndecl, TDI_thread_jumps);
- 
  	  bitmap_clear (vars_to_rename);
  	  tree_ssa_dominator_optimize (fndecl, vars_to_rename, TDI_dom_1);
  
--- 112,117 ----
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.94
diff -c -3 -p -r1.1.2.94 tree-ssa-dom.c
*** tree-ssa-dom.c	11 Dec 2003 19:15:11 -0000	1.1.2.94
--- tree-ssa-dom.c	13 Dec 2003 07:03:21 -0000
*************** static bool cfg_altered;
*** 82,92 ****
     this bitmap.  */
  static bitmap vars_to_rename;
  
- /* Nonzero if we should thread jumps through blocks which contain PHI
-    nodes.  This is not safe once we have performed any transformation
-    which extends the lifetime of variables.  */
- static int thread_through_phis;
- 
  /* Statistics for dominator optimizations.  */
  struct opt_stats_d
  {
--- 82,87 ----
*************** static void dom_opt_initialize_block (st
*** 238,246 ****
  				      basic_block, tree);
  static void dom_opt_walk_stmts (struct dom_walk_data *, basic_block, tree);
  static void cprop_into_phis (struct dom_walk_data *, basic_block, tree);
- static void tree_ssa_dominator_optimize_1 (tree, enum tree_dump_index,
- 					   timevar_id_t);
- static void thread_jumps_walk_stmts (struct dom_walk_data *, basic_block, tree);
  
  
  /* Propagate the value VAL (assumed to be a constant or another SSA_NAME)
--- 233,238 ----
*************** set_value_for (tree var, tree value, var
*** 273,325 ****
    VARRAY_TREE (table, SSA_NAME_VERSION (var)) = value;
  }
  
! /* Thread jumps in FNDECL based on equivalences created by walking the
!    dominator tree.
! 
!    Fundamentally this optimization changes the dominator tree in ways
!    that other optimizers care about.  Furthermore, if we thread a jump
!    through a block with PHI nodes, then we need to re-rewrite all the
!    variables appearing in those PHI nodes.
! 
!    The need to be able to re-rewrite those variables means that this
!    jump threading optimization must be run before we make any transformations
!    which could extend the lifetime of any variable or replace a use of a 
!    variable with a constant.  Thus this optimizer is the first optimizer we
!    run once we are in SSA form and this optimizer is responsible for updaing
!    the SSA form if transformations are made.
! 
!    A more limited form of this optimizer is run as part of the main dominator
!    optimizer which does not make transformations which require the ability to
!    re-rewrite variables.  Specifically the later version of this optimizer
!    does not thread through blocks with PHI nodes.
! 
!    PHASE indicates which dump file from the DUMP_FILES array to use when
!    dumping debugging information.  */
! 
! void
! tree_ssa_dominator_thread_jumps (tree fndecl, enum tree_dump_index phase)
! {
!   /* Indicate that we can thread through blocks with PHI nodes.  */
!   thread_through_phis = 1;
! 
!   /* The jump threader will always perform any necessary rewriting, so
!      we do not expose VAR_TO_RENAME to our caller, we just allocate and
!      deallocate one here.  */
!   vars_to_rename = BITMAP_XMALLOC ();
! 
!   /* Mark loop edges so we avoid threading across loop boundaries.
!      This may result in transformating natural loop into irreducible
!      region.  */
!   mark_dfs_back_edges ();
  
!   tree_ssa_dominator_optimize_1 (fndecl, phase, TV_TREE_SSA_THREAD_JUMPS);
! 
!   BITMAP_XFREE (vars_to_rename);
! }
! 
! /* Optimize function FNDECL based on the dominator tree.  This does
!    simple const/copy propagation and redundant expression elimination using
!    value numbering.
  
     This pass may expose new symbols that need to be renamed into SSA.  For
     every new symbol exposed, its corresponding bit will be set in
--- 265,273 ----
    VARRAY_TREE (table, SSA_NAME_VERSION (var)) = value;
  }
  
! /* Jump threading, redundancy elimination and const/copy propagation. 
  
!    Optimize function FNDECL based on a walk through the dominator tree.
  
     This pass may expose new symbols that need to be renamed into SSA.  For
     every new symbol exposed, its corresponding bit will be set in
*************** void
*** 332,367 ****
  tree_ssa_dominator_optimize (tree fndecl, bitmap vars,
  			     enum tree_dump_index phase)
  {
-   /* Indicate we can not thread through blocks with PHI nodes.  */
-   thread_through_phis = 0;
- 
-   /* Once we have the ability to attach pass-global data to the dominator
-      walker datastructure this (along with other pass-global data) should
-      move into that structure.  */
-   vars_to_rename = vars;
-  
-   tree_ssa_dominator_optimize_1 (fndecl, phase, TV_TREE_SSA_DOMINATOR_OPTS);
- }
- 
- /* Common driver for dominator based jump threading, redundancy elimination
-    and const/copy propagation. 
- 
-    Optimize function FNDECL based on a walk through the dominator tree.
- 
-    PHASE indicates which dump file from the DUMP_FILES array to use when
-    dumping debugging information.  */
- 
- static void
- tree_ssa_dominator_optimize_1 (tree fndecl,
- 			       enum tree_dump_index phase,
- 			       timevar_id_t timevar)
- {
    basic_block bb;
    edge e;
    struct dom_walk_data walk_data;
    tree phi;
  
!   timevar_push (timevar);
  
    /* Set up debugging dump files.  */
    dump_file = dump_begin (phase, &dump_flags);
--- 280,301 ----
  tree_ssa_dominator_optimize (tree fndecl, bitmap vars,
  			     enum tree_dump_index phase)
  {
    basic_block bb;
    edge e;
    struct dom_walk_data walk_data;
    tree phi;
  
!   timevar_push (TV_TREE_SSA_DOMINATOR_OPTS);
! 
!   /* Mark loop edges so we avoid threading across loop boundaries.
!      This may result in transformating natural loop into irreducible
!      region.  */
!   mark_dfs_back_edges ();
! 
!   /* Once we have the ability to attach pass-global data to the dominator
!      walker datastructure this (along with other pass-global data) should
!      move into that structure.  */
!   vars_to_rename = vars;
  
    /* Set up debugging dump files.  */
    dump_file = dump_begin (phase, &dump_flags);
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 390,408 ****
       structure.  */
    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.  */
!   if (thread_through_phis)
!     {
!       walk_data.before_dom_children_walk_stmts = thread_jumps_walk_stmts;
!       walk_data.before_dom_children_after_stmts = NULL;
!     }
!   else
!     {
!       walk_data.before_dom_children_walk_stmts = dom_opt_walk_stmts;
!       walk_data.before_dom_children_after_stmts = cprop_into_phis;
!     }
  
    /* Now initialize the dominator walker.  */
    init_walk_dominator_tree (&walk_data);
--- 324,331 ----
       structure.  */
    walk_data.global_data = NULL;
    walk_data.block_local_data_size = sizeof (struct dom_walk_block_data);
!   walk_data.before_dom_children_walk_stmts = dom_opt_walk_stmts;
!   walk_data.before_dom_children_after_stmts = cprop_into_phis;
  
    /* Now initialize the dominator walker.  */
    init_walk_dominator_tree (&walk_data);
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 440,445 ****
--- 363,371 ----
       blocks.  */
    do
      {
+       size_t old_num_referenced_vars = num_referenced_vars;
+       size_t i;
+ 
        /* Optimize the dominator tree.  */
        cfg_altered = false;
  
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 459,465 ****
--- 385,424 ----
        if (VARRAY_ACTIVE_SIZE (edges_to_redirect) > 0)
  	{
  	  basic_block tgt;
+ 	  unsigned int i;
+ 
+ 	  /* First note any variables which we are going to have to take
+ 	     out of SSA form.  */
+ 	  for (i = 0; i < VARRAY_ACTIVE_SIZE (edges_to_redirect); i++)
+ 	    {
+ 	      e = VARRAY_EDGE (edges_to_redirect, i);
  
+ 	      for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
+ 		{
+ 		  tree result = SSA_NAME_VAR (PHI_RESULT (phi));
+ 		  int j;
+ 
+                   bitmap_set_bit (vars_to_rename, var_ann (result)->uid);
+ 
+ 		  for (j = 0; j < PHI_NUM_ARGS (phi); j++)
+ 		    {
+ 		      tree arg = PHI_ARG_DEF (phi, j);
+ 
+ 		      if (TREE_CODE (arg) != SSA_NAME)
+ 			continue;
+ 
+ 		      arg = SSA_NAME_VAR (arg);
+ 		      bitmap_set_bit (vars_to_rename, var_ann (arg)->uid);
+ 		    }
+ 	        }
+ 	    }
+ 
+ 	  /* Take those selected variables out of SSA form.  This must be
+ 	     done before we start redirecting edges.  */
+ 	  if (bitmap_first_set_bit (vars_to_rename) >= 0)
+ 	    rewrite_vars_out_of_ssa (vars_to_rename);
+ 
+ 	  /* Now redirect the edges.  */
  	  while (VARRAY_ACTIVE_SIZE (edges_to_redirect) > 0)
  	    {
  	      basic_block src;
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 474,488 ****
  			 e->src->index, e->dest->index, tgt->index);
  
  	      src = e->src;
- 	      /* If there are PHI nodes at the original destination, then we need to
- 		 re-rename the variables referenced by those PHI nodes.
- 
- 	    	 Since we only thread through blocks with PHI nodes before doing
- 		 any kind of propagation or redundancy elimination, we know that
- 		 all the PHI arguments are different versions of the same variable,
- 		 so we only need to mark the underlying variable for PHI_RESULT.  */
- 	      for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
- 		bitmap_set_bit (vars_to_rename, var_ann (SSA_NAME_VAR (PHI_RESULT (phi)))->uid);
  
  	      e = redirect_edge_and_branch (e, tgt);
  	      
--- 433,438 ----
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 511,523 ****
  	  free_dominance_info (idom);
  	}
  
        /* If we are going to iterate (CFG_ALTERED is true), then we must
  	 perform any queued renaming before the next iteration.  */
        if (cfg_altered
  	  && bitmap_first_set_bit (vars_to_rename) >= 0)
  	{
  	  rewrite_into_ssa (fndecl, vars_to_rename, TDI_none);
! 	  bitmap_zero (vars_to_rename);
  	  VARRAY_GROW (const_and_copies, highest_ssa_version);
  	  VARRAY_GROW (vrp_data, highest_ssa_version);
  	  VARRAY_GROW (nonzero_vars, highest_ssa_version);
--- 461,479 ----
  	  free_dominance_info (idom);
  	}
  
+       for (i = old_num_referenced_vars; i < num_referenced_vars; i++)
+ 	{
+ 	  bitmap_set_bit (vars_to_rename, i);
+ 	  var_ann (referenced_var (i))->out_of_ssa_tag = 0;
+ 	}
+ 
        /* If we are going to iterate (CFG_ALTERED is true), then we must
  	 perform any queued renaming before the next iteration.  */
        if (cfg_altered
  	  && bitmap_first_set_bit (vars_to_rename) >= 0)
  	{
  	  rewrite_into_ssa (fndecl, vars_to_rename, TDI_none);
! 	  bitmap_clear (vars_to_rename);
  	  VARRAY_GROW (const_and_copies, highest_ssa_version);
  	  VARRAY_GROW (vrp_data, highest_ssa_version);
  	  VARRAY_GROW (nonzero_vars, highest_ssa_version);
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 550,556 ****
    /* And finalize the dominator walker.  */
    fini_walk_dominator_tree (&walk_data);
  
!   timevar_pop (timevar);
  }
  
  /* We are exiting BB, see if the target block begins with a conditional
--- 506,512 ----
    /* And finalize the dominator walker.  */
    fini_walk_dominator_tree (&walk_data);
  
!   timevar_pop (TV_TREE_SSA_DOMINATOR_OPTS);
  }
  
  /* We are exiting BB, see if the target block begins with a conditional
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 559,646 ****
  static void
  thread_across_edge (edge e)
  {
!   /* If we have a single successor, then we may be able to thread
!      the edge out of our block to a destination of our successor.
  
!      Only thread through a successor with PHI nodes if explicitly asked to.  */
!   if (thread_through_phis || ! phi_nodes (e->dest))
!     {
!       tree stmt = last_and_only_stmt (e->dest);
  
!       /* If we stopped at a COND_EXPR, then see if we know which arm will
! 	 be taken.  */
!       if (stmt && TREE_CODE (stmt) == COND_EXPR)
  	{
! 	  tree cached_lhs;
! 	  unsigned int i;
! 	  edge e1;
! 
! 	  /* Do not forward entry edges into the loop.  In the case loop
! 	     has multiple entry edges we may end up in constructing irreducible
! 	     region.  
! 	     ??? We may consider forwarding the edges in the case all incomming
! 	     edges forward to the same destination block.  */
! 	  if (!e->flags & EDGE_DFS_BACK)
! 	    {
! 	      for (e1 = e->dest->pred; e; e = e->pred_next)
! 		if (e1->flags & EDGE_DFS_BACK)
! 		  break;
! 	      if (e1)
! 		return;
! 	    }
  
! 	  /* If we are threading through PHIs, then make sure that none
! 	     of the PHIs set results which are used by the conditional.
  
! 	     Otherwise this optimization would short-circuit loops.  */
! 	  if (thread_through_phis)
  	    {
! 	      varray_type table;
  
! 	      get_stmt_operands (stmt);
! 	      table = use_ops (stmt_ann (stmt));
  
! 	      for (i = 0; table && i < VARRAY_ACTIVE_SIZE (table); i++)
! 		{
! 		  tree *op_p = VARRAY_TREE_PTR (table, i);
! 		  tree def_stmt = SSA_NAME_DEF_STMT (*op_p);
! 	
! 		  /* See if this operand is defined by a PHI node in
! 		     BB's successor.  If it is, then we can not thread
! 		     this jump.  */
! 		  if (TREE_CODE (def_stmt) == PHI_NODE
! 		      && bb_for_stmt (def_stmt) == e->dest)
! 		    return;
! 		}
! 	    }
! 
! 	  cached_lhs = lookup_avail_expr (stmt, NULL, false);
! 	  if (cached_lhs)
! 	    {
! 	      edge taken_edge = find_taken_edge (e->dest, cached_lhs);
! 	      basic_block dest = (taken_edge ? taken_edge->dest : NULL);
  
! 	      if (dest == e->src)
! 		return;
! 
! 	      /* If we have a known destination for the conditional, then
! 		 we can perform this optimization, which saves at least one
! 		 conditional jump each time it applies since we get to
! 		 bypass the conditional at our original destination.  */
! 	      if (dest && ! phi_nodes (dest))
! 		{
! 		  basic_block forwards_to;
! 		  int saved_forwardable = bb_ann (e->src)->forwardable;
! 
! 		  bb_ann (e->src)->forwardable = 0;
! 
! 		  forwards_to = tree_block_forwards_to (dest);
! 
! 		  bb_ann (e->src)->forwardable = saved_forwardable;
! 		  dest = (forwards_to ? forwards_to : dest);
! 		  VARRAY_PUSH_EDGE (edges_to_redirect, e);
! 		  VARRAY_PUSH_BB (redirection_targets, dest);
! 		}
  	    }
  	}
      }
--- 515,591 ----
  static void
  thread_across_edge (edge e)
  {
!   tree stmt = last_and_only_stmt (e->dest);
  
!   /* If we stopped at a COND_EXPR, then see if we know which arm will
!      be taken.  */
!   if (stmt && TREE_CODE (stmt) == COND_EXPR)
!     {
!       tree cached_lhs;
!       unsigned int i;
!       edge e1;
!       varray_type table;
! 
!       /* Do not forward entry edges into the loop.  In the case loop
! 	 has multiple entry edges we may end up in constructing irreducible
! 	 region.  
! 	 ??? We may consider forwarding the edges in the case all incomming
! 	 edges forward to the same destination block.  */
!       if (!e->flags & EDGE_DFS_BACK)
! 	{
! 	  for (e1 = e->dest->pred; e; e = e->pred_next)
! 	    if (e1->flags & EDGE_DFS_BACK)
! 	      break;
! 	  if (e1)
! 	    return;
! 	}
! 
!       /* Make sure that none of the PHIs set results which are used by the
! 	 conditional.
! 
! 	 Otherwise this optimization would short-circuit loops.  */
!       get_stmt_operands (stmt);
!       table = use_ops (stmt_ann (stmt));
! 
!       for (i = 0; table && i < VARRAY_ACTIVE_SIZE (table); i++)
!         {
!           tree *op_p = VARRAY_TREE_PTR (table, i);
!           tree def_stmt = SSA_NAME_DEF_STMT (*op_p);
! 	
!           /* See if this operand is defined by a PHI node in
! 	     BB's successor.  If it is, then we can not thread
! 	     this jump.  */
! 	  if (TREE_CODE (def_stmt) == PHI_NODE
! 	      && bb_for_stmt (def_stmt) == e->dest)
! 	    return;
! 	}
  
!       cached_lhs = lookup_avail_expr (stmt, NULL, false);
!       if (cached_lhs)
  	{
! 	  edge taken_edge = find_taken_edge (e->dest, cached_lhs);
! 	  basic_block dest = (taken_edge ? taken_edge->dest : NULL);
  
! 	  if (dest == e->src)
! 	    return;
  
! 	  /* If we have a known destination for the conditional, then
! 	     we can perform this optimization, which saves at least one
! 	     conditional jump each time it applies since we get to
! 	     bypass the conditional at our original destination.  */
! 	  if (dest && ! phi_nodes (dest))
  	    {
! 	      basic_block forwards_to;
! 	      int saved_forwardable = bb_ann (e->src)->forwardable;
  
! 	      bb_ann (e->src)->forwardable = 0;
  
! 	      forwards_to = tree_block_forwards_to (dest);
  
! 	      bb_ann (e->src)->forwardable = saved_forwardable;
! 	      dest = (forwards_to ? forwards_to : dest);
! 	      VARRAY_PUSH_EDGE (edges_to_redirect, e);
! 	      VARRAY_PUSH_BB (redirection_targets, dest);
  	    }
  	}
      }
*************** dom_opt_walk_stmts (struct dom_walk_data
*** 1151,1240 ****
  	    VARRAY_TREE_INIT (bd->stmts_to_rescan, 20, "stmts_to_rescan");
  	  VARRAY_PUSH_TREE (bd->stmts_to_rescan, bsi_stmt (si));
  	}
-     }
- }
- 
- /* Alternate statement walker for jump threading.  The primary difference
-    between this walker and the previous one is we merely want to record
-    equivalences, not take action on them.  So instead of calling
-    optimize_stmt, we just enter the appropriate equivalences into the
-    hash tables.  */
- 
- static void
- thread_jumps_walk_stmts (struct dom_walk_data *walk_data,
- 			 basic_block bb,
- 			 tree parent_block_last_stmt ATTRIBUTE_UNUSED)
- {
-   block_stmt_iterator si;
- 
-   /* Examine each statement within the basic block.  */
-   for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
-     {
-       struct dom_walk_block_data *bd
- 	= VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
-       tree stmt = bsi_stmt (si);
-       int may_optimize_p;
-       varray_type vdefs;
-       tree cached_lhs = NULL;
- 
-       /* First try to eliminate any conditionals which have a known
- 	 compile time constant value.  */
-       if (TREE_CODE (stmt) == COND_EXPR || TREE_CODE (stmt) == SWITCH_EXPR)
- 	cached_lhs = lookup_avail_expr (stmt, NULL, false);
-       if (! cached_lhs && TREE_CODE (stmt) == COND_EXPR)
- 	cached_lhs = simplify_cond_and_lookup_avail_expr (stmt,
- 							  NULL,
- 							  stmt_ann (stmt),
- 							  false);
- 
-       if (cached_lhs && is_gimple_min_invariant (cached_lhs))
- 	{
- 	  modify_stmt (stmt);
- 
- 	  if (TREE_CODE (stmt) == COND_EXPR)
- 	    {
- 	      COND_EXPR_COND (stmt) = cached_lhs;
- 	      cfg_altered = cleanup_control_expr_graph (bb, si);
- 	    }
- 	  else if (TREE_CODE (stmt) == SWITCH_EXPR)
- 	    {
- 	      SWITCH_COND (stmt) = cached_lhs;
- 	      cfg_altered = cleanup_control_expr_graph (bb, si);
- 	    }
- 
- 	  continue;
- 	}
- 
-       /* This is a simpler test than the one in optimize_stmt because
- 	 we only care about recording equivalences for assignments.
-          RETURN_EXPRs, COND_EXPRs, and SWITCH_EXPRs can be ignored.  */
-       may_optimize_p = (!stmt_ann (stmt)->has_volatile_ops
- 			&& TREE_CODE (stmt) == MODIFY_EXPR
- 			&& ! TREE_SIDE_EFFECTS (TREE_OPERAND (stmt, 1)));
- 
-       vdefs = vdef_ops (stmt_ann (stmt));
- 
-       /* Tighten the set of RHS expressions we can enter into the hash
- 	 tables.  Specifically, we can not enter the RHS into the hash
- 	 table if the LHS is not an SSA_NAME, the LHS occurs in an
- 	 abnormal PHI, or if the statement makes aliased stores
- 	 (in addition to all the conditions for may_optimize_p).  */
-       if (may_optimize_p
- 	  && TREE_CODE (TREE_OPERAND (stmt, 0)) == SSA_NAME
- 	  && ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (stmt, 0))
- 	  && ! stmt_ann (stmt)->makes_aliased_stores
- 	  && ! vdefs)
- 	lookup_avail_expr (stmt, &bd->avail_exprs, true);
- 
-       /* Even if we couldn't enter LHS = RHS into the expression hash tables,
- 	 this statement may still generate other equivalences.  For example,
- 	 an aliased store can indicate that a pointer has a nonzero value.  */
-       if (TREE_CODE (stmt) == MODIFY_EXPR)
- 	record_equivalences_from_stmt (stmt,
- 				       &bd->avail_exprs,
- 				       &bd->nonzero_vars,
- 				       may_optimize_p,
- 				       stmt_ann (stmt));
      }
  }
  
--- 1096,1101 ----
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.150
diff -c -3 -p -r1.342.2.150 tree.h
*** tree.h	8 Dec 2003 20:29:26 -0000	1.342.2.150
--- tree.h	13 Dec 2003 07:03:28 -0000
*************** enum tree_dump_index
*** 3587,3593 ****
    /* Optimization passes.  The ordering and numbering of these phases must
       be the same as the one in optimize_function_tree.  */
    TDI_ssa_1,
-   TDI_thread_jumps,
    TDI_dom_1,
    TDI_ssa_2,
    TDI_dce_1,
--- 3587,3592 ----











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