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] More jump threading improvements


This patch allows us to thread jumps through blocks which start with
real statements.    It brings the number of missed jump threading
opportunities from ~175 down to ~50 (as measured by the number of
jump threading opportunities found by the first RTL jump threading
pass).  FWIW, when I started looking at the jump threader we were
missing a few thousand jump threading opportunities, so we've come a
long way.


The "trick" here is that we can sometimes ignore statements at the start
of a block.    Given:


LHS = RHS;


If LHS and RHS are both SSA_NAMEs and the RHS represents the 'current' value
of the underlying variable.

This is further extended to arbitrary gimple expressions for RHS if we can
find RHS in the hash table and its representative value is an SSA_NAME
with the same base variable as LHS and where the representative value is
the current value of the underlying variable.

I fully expect to need to tweak this code as we improve the operand interface
and as we move towards a model where the dominator optimizer's hash tables
are based on operand caches rather than full tree nodes (which would also
have the nice effect to reducing the number of varrays and hash tables we
need in the dominator optimizer).

It's also worth noting that as we approach closure on the jump threading
issues I'm going to move to refocus on some compile-time improvements.
The improvements in jump threading are exercising things like the 
into and out-of SSA passes pretty heavily.  I'm sure there's some
improvements that can and should be made in both into and out-of SSA.

This patch also updates copyright dates in the files I've changed
this year...

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

	* tree-flow.h: Update copyright dates.
	(register_new_def): Declare.
	* tree-ssa-dom.c: Update copyright dates.
	Add tracking of current definition of each program variable just
	like we do when rewriting into SSA form.
	(get_value_for, set_value_for): Handle either an SSA_NAME or
	regular variable.
	(tree_ssa_dominator_optimize): Initialize and update CURRDEFS.
	If we thread through a block with real statements, the destination
	of those statements must be rewritten too.
	(thread_across_edge): Skip nop statements at the start of a
	block.
	(dom_opt_initialize_block_local_data): Clear block_defs
	appropriately.
	(record_equivalences_from_phis): Accept walk_data structure.
	Call register_new_def appropriately.
	(optimize_stmt): Call register_new_defs_for_stmt.
	(dom_opt_finalize_block): Restore CURRDEFS appropriately.
	(register_new_definitions_for_stmt): New.
	* tree-ssa.c: Update copyright dates.
	(register_new_def): No longer static.  Accept additional argument
	for the table to hold the new definition.  Callers updated.

	* gimplify.c: Update copyright dates.
	* tree-cfg.c: Likewise.
	* tree.h: Likewise.
 
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimplify.c,v
retrieving revision 1.1.2.134
diff -c -p -r1.1.2.134 gimplify.c
*** gimplify.c	14 Jan 2004 00:06:25 -0000	1.1.2.134
--- gimplify.c	19 Jan 2004 23:03:15 -0000
***************
*** 1,7 ****
  /* Tree lowering pass.  This pass converts the GENERIC functions-as-trees
     tree representation into the GIMPLE form.
  
!    Copyright (C) 2002, 2003 Free Software Foundation, Inc.
     Major work done by Sebastian Pop <s.pop@laposte.net>,
     Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
  
--- 1,7 ----
  /* Tree lowering pass.  This pass converts the GENERIC functions-as-trees
     tree representation into the GIMPLE form.
  
!    Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
     Major work done by Sebastian Pop <s.pop@laposte.net>,
     Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
  
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.259
diff -c -p -r1.1.4.259 tree-cfg.c
*** tree-cfg.c	19 Jan 2004 19:14:11 -0000	1.1.4.259
--- tree-cfg.c	19 Jan 2004 23:03:20 -0000
***************
*** 1,5 ****
  /* Control flow functions for trees.
!    Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
     Contributed by Diego Novillo <dnovillo@redhat.com>
  
  This file is part of GCC.
--- 1,5 ----
  /* Control flow functions for trees.
!    Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
     Contributed by Diego Novillo <dnovillo@redhat.com>
  
  This file is part of GCC.
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.183
diff -c -p -r1.1.4.183 tree-flow.h
*** tree-flow.h	17 Jan 2004 20:26:21 -0000	1.1.4.183
--- tree-flow.h	19 Jan 2004 23:03:22 -0000
***************
*** 1,5 ****
  /* Data and Control Flow Analysis for Trees.
!    Copyright (C) 2001, 2003 Free Software Foundation, Inc.
     Contributed by Diego Novillo <dnovillo@redhat.com>
  
  This file is part of GCC.
--- 1,5 ----
  /* Data and Control Flow Analysis for Trees.
!    Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
     Contributed by Diego Novillo <dnovillo@redhat.com>
  
  This file is part of GCC.
*************** extern bool tree_ssa_useless_type_conver
*** 513,518 ****
--- 513,519 ----
  extern bool tree_ssa_useless_type_conversion_1 (tree, tree);
  extern void verify_ssa (void);
  extern void delete_tree_ssa (void);
+ extern void register_new_def (tree, tree, varray_type *, varray_type);
  
  extern unsigned int highest_ssa_version;
  extern void kill_redundant_phi_nodes (void);
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.114
diff -c -p -r1.1.2.114 tree-ssa-dom.c
*** tree-ssa-dom.c	16 Jan 2004 06:09:23 -0000	1.1.2.114
--- tree-ssa-dom.c	19 Jan 2004 23:03:30 -0000
***************
*** 1,5 ****
  /* SSA Dominator optimizations for trees
!    Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
     Contributed by Diego Novillo <dnovillo@redhat.com>
  
  This file is part of GCC.
--- 1,5 ----
  /* SSA Dominator optimizations for trees
!    Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
     Contributed by Diego Novillo <dnovillo@redhat.com>
  
  This file is part of GCC.
*************** static htab_t false_exprs;
*** 68,73 ****
--- 68,78 ----
     propagation).  */
  static varray_type const_and_copies;
  
+ /* Table to store the current reaching definition for every variable in
+    the function.  Given a variable V, its entry will be its immediately
+    reaching SSA_NAME node.  */
+ static varray_type currdefs;
+ 
  /* Table of constant values indexed by SSA_NAME.  If the stored value for a
     particular SSA_NAME is integer_one_node, then that particular SSA_NAME
     is known to have a nonzero value (even if we do not know its precise
*************** struct dom_walk_block_data
*** 189,194 ****
--- 194,204 ----
       in this basic block.  We use this during finalization to know
       which variables need their VRP data updated.  */
    varray_type vrp_variables;
+ 
+   /* Array of tree pairs used to restore the globcal currdefs to its
+      original state after completing optimization of a block and its
+      dominator children.  */
+   varray_type block_defs;
  };
  
  struct eq_expr_value
*************** static tree find_equivalent_equality_com
*** 222,228 ****
  static void record_range (tree, basic_block, varray_type *);
  static bool extract_range_from_cond (tree, tree *, tree *, int *);
  static bool cprop_into_stmt (tree);
! static void record_equivalences_from_phis (basic_block);
  static void record_equivalences_from_incoming_edge (struct dom_walk_data *,
  						    basic_block, tree);
  static bool eliminate_redundant_computations (struct dom_walk_data *,
--- 232,238 ----
  static void record_range (tree, basic_block, varray_type *);
  static bool extract_range_from_cond (tree, tree *, tree *, int *);
  static bool cprop_into_stmt (tree);
! static void record_equivalences_from_phis (struct dom_walk_data *, 
basic_block);
  static void record_equivalences_from_incoming_edge (struct dom_walk_data *,
  						    basic_block, tree);
  static bool eliminate_redundant_computations (struct dom_walk_data *,
*************** static void restore_vars_to_original_val
*** 244,250 ****
  					    unsigned limit, 
  					    varray_type table);
  static void extract_true_false_edges_from_block (basic_block, edge *, edge 
*);
! 
  
  /* Propagate the value VAL (assumed to be a constant or another SSA_NAME)
     into the operand pointed by OP_P.  */
--- 254,260 ----
  					    unsigned limit, 
  					    varray_type table);
  static void extract_true_false_edges_from_block (basic_block, edge *, edge 
*);
! static void register_definitions_for_stmt (tree, varray_type *);
  
  /* Propagate the value VAL (assumed to be a constant or another SSA_NAME)
     into the operand pointed by OP_P.  */
*************** propagate_value (tree *op_p, tree val)
*** 264,279 ****
  static inline tree
  get_value_for (tree var, varray_type table)
  {
!   return VARRAY_TREE (table, SSA_NAME_VERSION (var));
! }
  
  
  /* Associate VALUE to variable VAR in TABLE.  */
  
  static inline void
  set_value_for (tree var, tree value, varray_type table)
  {
!   VARRAY_TREE (table, SSA_NAME_VERSION (var)) = value;
  }
  
  /* Jump threading, redundancy elimination and const/copy propagation. 
--- 274,306 ----
  static inline tree
  get_value_for (tree var, varray_type table)
  {
!   unsigned int indx;
! 
!   if (TREE_CODE (var) == SSA_NAME)
!     indx = SSA_NAME_VERSION (var);
!   else if (DECL_P (var))
!     indx = var_ann (var)->uid;
!   else
!     abort ();
  
+   return VARRAY_TREE (table, indx);
+ }
  
  /* Associate VALUE to variable VAR in TABLE.  */
  
  static inline void
  set_value_for (tree var, tree value, varray_type table)
  {
!   unsigned int indx;
! 
!   if (TREE_CODE (var) == SSA_NAME)
!     indx = SSA_NAME_VERSION (var);
!   else if (DECL_P (var))
!     indx = var_ann (var)->uid;
!   else
!     abort ();
! 
!   VARRAY_TREE (table, indx) = value;
  }
  
  /* Jump threading, redundancy elimination and const/copy propagation. 
*************** tree_ssa_dominator_optimize (void)
*** 310,315 ****
--- 337,343 ----
    VARRAY_TREE_INIT (nonzero_vars, highest_ssa_version, "nonzero_vars");
    VARRAY_EDGE_INIT (redirection_edges, 20, "redirection_edges");
    VARRAY_GENERIC_PTR_INIT (vrp_data, highest_ssa_version, "vrp_data");
+   VARRAY_TREE_INIT (currdefs, num_referenced_vars, "currdefs");
  
  
    /* Setup callbacks for the generic dominator tree walker.  */
*************** tree_ssa_dominator_optimize (void)
*** 371,376 ****
--- 399,406 ----
  	     out of SSA form.  */
  	  for (i = 0; i < VARRAY_ACTIVE_SIZE (redirection_edges); i += 2)
  	    {
+ 	      block_stmt_iterator bsi;
+ 
  	      e = VARRAY_EDGE (redirection_edges, i);
  	      tgt = VARRAY_EDGE (redirection_edges, i + 1)->dest;
  
*************** tree_ssa_dominator_optimize (void)
*** 393,398 ****
--- 423,457 ----
  		    }
  	        }
  
+ 	      /* Similarly for any real statements at the start of the
+ 		 block we threaded through.  */
+ 	      for (bsi = bsi_start (e->dest); ! bsi_end_p (bsi); bsi_next (&bsi))
+ 		{
+ 		  unsigned int j;
+ 		  def_optype defs;
+ 		  vdef_optype vdefs;
+ 		  tree stmt = bsi_stmt (bsi);
+ 
+ 		  if (TREE_CODE (stmt) == COND_EXPR)
+ 		    break;
+ 
+ 		  get_stmt_operands (stmt);
+ 
+ 		  defs = STMT_DEF_OPS (stmt);
+ 		  for (j = 0; j < NUM_DEFS (defs); j++)
+ 		    {
+ 		      tree op = SSA_NAME_VAR (DEF_OP (defs, j));
+ 		      bitmap_set_bit (vars_to_rename, var_ann (op)->uid);
+ 		    }
+ 
+ 		  vdefs = STMT_VDEF_OPS (stmt);
+ 		  for (j = 0; j < NUM_VDEFS (vdefs); j++)
+ 		    {
+ 		      tree op = VDEF_RESULT (vdefs, j);
+ 		      bitmap_set_bit (vars_to_rename, var_ann (op)->uid);
+ 		    }
+ 		}
+ 
  	      /* Similarly for our destination.  */
  	      for (phi = phi_nodes (tgt); phi; phi = TREE_CHAIN (phi))
  		{
*************** tree_ssa_dominator_optimize (void)
*** 509,517 ****
--- 568,578 ----
  	  VARRAY_GROW (const_and_copies, highest_ssa_version);
  	  VARRAY_GROW (vrp_data, highest_ssa_version);
  	  VARRAY_GROW (nonzero_vars, highest_ssa_version);
+ 	  VARRAY_GROW (currdefs, num_referenced_vars);
  	  VARRAY_CLEAR (const_and_copies);
  	  VARRAY_CLEAR (vrp_data);
  	  VARRAY_CLEAR (nonzero_vars);
+ 	  VARRAY_CLEAR (currdefs);
  	}
      }
    while (cfg_altered);
*************** tree_ssa_dominator_optimize (void)
*** 528,533 ****
--- 589,595 ----
    htab_delete (false_exprs);
  
    VARRAY_FREE (redirection_edges);
+   VARRAY_CLEAR (currdefs);
  
    /* And finalize the dominator walker.  */
    fini_walk_dominator_tree (&walk_data);
*************** struct tree_opt_pass pass_dominator = 
*** 563,571 ****
  static void
  thread_across_edge (struct dom_walk_data *walk_data, edge e)
  {
-   tree stmt = last_and_only_stmt (e->dest);
    struct dom_walk_block_data *bd
      = VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
  
    /* If we stopped at a COND_EXPR, then see if we know which arm will
       be taken.  */
--- 625,763 ----
  static void
  thread_across_edge (struct dom_walk_data *walk_data, edge e)
  {
    struct dom_walk_block_data *bd
      = VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
+   block_stmt_iterator bsi;
+   tree stmt = NULL;
+ 
+   for (bsi = bsi_start (e->dest); ! bsi_end_p (bsi); bsi_next (&bsi))
+     {
+       tree lhs, cached_lhs, prev_value;
+ 
+       stmt = bsi_stmt (bsi);
+ 
+       /* Ignore empty statements and labels.  */
+       if (IS_EMPTY_STMT (stmt) || TREE_CODE (stmt) == LABEL_EXPR)
+ 	continue;
+ 
+       /* If this is not a MODIFY_EXPR which sets an SSA_NAME to a new
+ 	 value, then stop our search here.  Ideally when we stop a
+ 	 search we stop on a COND_EXPR.  */
+       if (TREE_CODE (stmt) != MODIFY_EXPR
+ 	  || TREE_CODE (TREE_OPERAND (stmt, 0)) != SSA_NAME)
+ 	break;
+ 
+       /* At this point we have a statement which assigns an RHS to an
+ 	 SSA_VAR on the LHS.  We want to prove that the RHS is already
+ 	 available and that its value is held in the current definition
+ 	 of the LHS -- meaning that this assignment is a NOP when
+ 	 reached via edge E.  */
+       if (TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME)
+ 	cached_lhs = TREE_OPERAND (stmt, 1);
+       else
+ 	cached_lhs = lookup_avail_expr (stmt, NULL, false);
+ 
+       lhs = TREE_OPERAND (stmt, 0);
+ 
+       /* This can happen if we thread around to the start of a loop.  */
+       if (lhs == cached_lhs)
+ 	break;
+ 
+       /* If we did not find RHS in the hash table, then try again after
+ 	 temporarily const/copy propagating the operands.  */
+       if (!cached_lhs)
+ 	{
+ 	  /* Copy the operands.  */
+ 	  stmt_ann_t ann = stmt_ann (stmt);
+ 	  use_optype uses = USE_OPS (ann);
+ 	  vuse_optype vuses = VUSE_OPS (ann);
+ 	  tree *uses_copy = xcalloc (NUM_USES (uses),  sizeof (tree));
+ 	  tree *vuses_copy = xcalloc (NUM_VUSES (vuses), sizeof (tree));
+ 	  unsigned int i;
+ 
+ 	  /* Make a copy of the uses into USES_COPY, then cprop into
+ 	     the use operands.  */
+ 	  for (i = 0; i < NUM_USES (uses); i++)
+ 	    {
+ 	      tree tmp = NULL;
+ 
+ 	      uses_copy[i] = USE_OP (uses, i);
+ 	      if (TREE_CODE (USE_OP (uses, i)) == SSA_NAME)
+ 		tmp = get_value_for (USE_OP (uses, i), const_and_copies);
+ 	      if (tmp)
+ 		*USE_OP_PTR (uses, i) = tmp;
+ 	    }
+ 
+ 	  /* Similarly for virtual uses.  */
+ 	  for (i = 0; i < NUM_VUSES (vuses); i++)
+ 	    {
+ 	      tree tmp = NULL;
+ 
+ 	      vuses_copy[i] = VUSE_OP (vuses, i);
+ 	      if (TREE_CODE (VUSE_OP (vuses, i)) == SSA_NAME)
+ 		tmp = get_value_for (VUSE_OP (vuses, i), const_and_copies);
+ 	      if (tmp)
+ 		VUSE_OP (vuses, i) = tmp;
+ 	    }
+ 
+ 	  /* Try to lookup the new expression.  */
+ 	  cached_lhs = lookup_avail_expr (stmt, NULL, false);
+ 
+ 	  /* Restore the statement's original uses/defs.  */
+ 	  for (i = 0; i < NUM_USES (uses); i++)
+ 	    *USE_OP_PTR (uses, i) = uses_copy[i];
+ 
+ 	  for (i = 0; i < NUM_VUSES (vuses); i++)
+ 	    VUSE_OP (vuses, i) = vuses_copy[i];
+ 
+ 	  free (uses_copy);
+ 	  free (vuses_copy);
+ 
+ 	  /* If we still did not find the expression in the hash table,
+ 	     then we can not ignore this statement.  */
+ 	  if (! cached_lhs)
+ 	    break;
+ 	}
+ 
+       /* If the expression in the hash table was not assigned to an
+ 	 SSA_NAME, then we can not ignore this statement.  */
+       if (TREE_CODE (cached_lhs) != SSA_NAME)
+ 	break;
+ 
+       /* If we have different underlying variables, then we can not
+ 	 ignore this statement.  */
+       if (SSA_NAME_VAR (cached_lhs) != SSA_NAME_VAR (lhs))
+ 	break;
+ 
+       /* If CACHED_LHS does not represent the current value of the undering
+ 	 variable in CACHED_LHS/LHS, then we can not ignore this statement.  */
+       if (get_value_for (SSA_NAME_VAR (lhs), currdefs) != cached_lhs)
+ 	break;
+ 
+       /* If we got here, then we can ignore this statement and continue
+ 	 walking through the statements in the block looking for a threadable
+ 	 COND_EXPR.
+ 
+ 	 We want to record an equivalence lhs = cache_lhs so that if
+ 	 the result of this statement is used later we can copy propagate
+ 	 suitably.  */
+       prev_value = get_value_for (lhs, const_and_copies);
+ 
+       if (TREE_CODE (cached_lhs) == SSA_NAME)
+ 	{
+ 	  tree tmp = get_value_for (cached_lhs, const_and_copies);
+ 
+ 	  if (tmp)
+ 	    cached_lhs = tmp;
+ 	}
+ 	  
+       set_value_for (lhs, cached_lhs, const_and_copies);
+ 
+       if (! bd->const_and_copies)
+ 	VARRAY_TREE_INIT (bd->const_and_copies, 2, "block_const_and_copies");
+       VARRAY_PUSH_TREE (bd->const_and_copies, lhs);
+       VARRAY_PUSH_TREE (bd->const_and_copies, prev_value);
+     }
  
    /* If we stopped at a COND_EXPR, then see if we know which arm will
       be taken.  */
*************** thread_across_edge (struct dom_walk_data
*** 593,599 ****
  	    return;
  	}
  
- 
        /* Each PHI creates a temporary equivalence, record them.  */
        for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
  	{
--- 785,790 ----
*************** dom_opt_initialize_block_local_data (str
*** 773,778 ****
--- 964,971 ----
  	VARRAY_CLEAR (bd->stmts_to_rescan);
        if (bd->vrp_variables)
  	VARRAY_CLEAR (bd->vrp_variables);
+       if (bd->block_defs)
+ 	VARRAY_CLEAR (bd->block_defs);
      }
  }
  
*************** dom_opt_initialize_block (struct dom_wal
*** 792,798 ****
  					  parent_block_last_stmt);
  
    /* PHI nodes can create equivalences too.  */
!   record_equivalences_from_phis (bb);
  }
  
  /* Remove all the expressions in LOCALS from TABLE, stopping when there are
--- 985,991 ----
  					  parent_block_last_stmt);
  
    /* PHI nodes can create equivalences too.  */
!   record_equivalences_from_phis (walk_data, bb);
  }
  
  /* Remove all the expressions in LOCALS from TABLE, stopping when there are
*************** dom_opt_finalize_block (struct dom_walk_
*** 1005,1010 ****
--- 1198,1223 ----
    restore_vars_to_original_value (bd->nonzero_vars, 0, nonzero_vars);
    restore_vars_to_original_value (bd->const_and_copies, 0, const_and_copies);
  
+   /* Restore CURRDEFS to its original state.  */
+   while (bd->block_defs && 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);
+     }
+ 
    /* Remove VRP records associated with this basic block.  They are no
       longer valid.
  
*************** dom_opt_finalize_block (struct dom_walk_
*** 1053,1060 ****
     all the alternatives are equal, then the PHI node creates an
     equivalence.  */
  static void
! record_equivalences_from_phis (basic_block bb)
  {
    tree phi;
  
    for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
--- 1266,1275 ----
     all the alternatives are equal, then the PHI node creates an
     equivalence.  */
  static void
! record_equivalences_from_phis (struct dom_walk_data *walk_data, basic_block 
bb)
  {
+   struct dom_walk_block_data *bd
+     = VARRAY_TOP_GENERIC_PTR (walk_data->block_data_stack);
    tree phi;
  
    for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
*************** record_equivalences_from_phis (basic_blo
*** 1098,1103 ****
--- 1313,1321 ----
        if (i == PHI_NUM_ARGS (phi)
  	  && may_propagate_copy (lhs, rhs))
  	set_value_for (lhs, rhs, const_and_copies);
+ 
+       register_new_def (SSA_NAME_VAR (PHI_RESULT (phi)), PHI_RESULT (phi),
+ 			&bd->block_defs, currdefs);
      }
  }
  
*************** optimize_stmt (struct dom_walk_data *wal
*** 2415,2420 ****
--- 2633,2640 ----
  				   may_optimize_p,
  				   ann);
  
+   register_definitions_for_stmt (stmt, &bd->block_defs);
+ 
    /* If STMT is a COND_EXPR and it was modified, then we may know
       where it goes.  If that is the case, then mark the CFG as altered.
  
*************** propagate_copy (tree *op_p, tree var)
*** 3006,3008 ****
--- 3226,3261 ----
  
    *op_p = var;
  }
+ 
+ /* Given STMT and a pointer to the block local defintions BLOCK_DEFS_P,
+    register register all objects set by this statement into BLOCK_DEFS_P
+    and CURRDEFS.  */
+ 
+ static void
+ register_definitions_for_stmt (tree stmt, varray_type *block_defs_p)
+ {
+   def_optype defs;
+   vdef_optype vdefs;
+   unsigned int i;
+ 
+   defs = STMT_DEF_OPS (stmt);
+   for (i = 0; i < NUM_DEFS (defs); i++)
+     {
+       tree def = DEF_OP (defs, i);
+ 
+       /* FIXME: We shouldn't be registering new defs if the variable
+ 	 doesn't need to be renamed.  */
+       register_new_def (SSA_NAME_VAR (def), def, block_defs_p, currdefs);
+     }
+ 
+   /* Register new virtual definitions made by the statement.  */
+   vdefs = STMT_VDEF_OPS (stmt);
+   for (i = 0; i < NUM_VDEFS (vdefs); i++)
+     {
+       /* FIXME: We shouldn't be registering new defs if the variable
+ 	 doesn't need to be renamed.  */
+       register_new_def (SSA_NAME_VAR (VDEF_RESULT (vdefs, i)),
+ 			VDEF_RESULT (vdefs, i), block_defs_p, currdefs);
+     }
+ }
+ 
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.188
diff -c -p -r1.1.4.188 tree-ssa.c
*** tree-ssa.c	17 Jan 2004 20:26:21 -0000	1.1.4.188
--- tree-ssa.c	19 Jan 2004 23:03:36 -0000
***************
*** 1,5 ****
  /* SSA for trees.
!    Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
     Contributed by Diego Novillo <dnovillo@redhat.com>
  
  This file is part of GCC.
--- 1,5 ----
  /* SSA for trees.
!    Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
     Contributed by Diego Novillo <dnovillo@redhat.com>
  
  This file is part of GCC.
*************** static bool prepare_operand_for_rename (
*** 178,184 ****
  static void insert_phi_nodes (bitmap *);
  static void rewrite_stmt (block_stmt_iterator, varray_type *);
  static inline void rewrite_operand (tree *);
- static void register_new_def (tree, tree, varray_type *);
  static void insert_phi_nodes_for (tree, bitmap *);
  static tree get_reaching_def (tree);
  static tree get_value_for (tree, varray_type);
--- 178,183 ----
*************** rewrite_initialize_block (struct dom_wal
*** 839,845 ****
      {
        tree result = PHI_RESULT (phi);
  
!       register_new_def (SSA_NAME_VAR (result), result, &bd->block_defs);
      }
  }
  
--- 838,845 ----
      {
        tree result = PHI_RESULT (phi);
  
!       register_new_def (SSA_NAME_VAR (result), result,
! 			&bd->block_defs, currdefs);
      }
  }
  
*************** rewrite_stmt (block_stmt_iterator si, va
*** 3333,3339 ****
  
        /* FIXME: We shouldn't be registering new defs if the variable
  	 doesn't need to be renamed.  */
!       register_new_def (SSA_NAME_VAR (*def_p), *def_p, block_defs_p);
      }
  
    /* Register new virtual definitions made by the statement.  */
--- 3333,3340 ----
  
        /* FIXME: We shouldn't be registering new defs if the variable
  	 doesn't need to be renamed.  */
!       register_new_def (SSA_NAME_VAR (*def_p), *def_p,
! 			block_defs_p, currdefs);
      }
  
    /* Register new virtual definitions made by the statement.  */
*************** rewrite_stmt (block_stmt_iterator si, va
*** 3347,3353 ****
        /* FIXME: We shouldn't be registering new defs if the variable
  	 doesn't need to be renamed.  */
        register_new_def (SSA_NAME_VAR (VDEF_RESULT (vdefs, i)), 
! 			VDEF_RESULT (vdefs, i), block_defs_p);
      }
  }
  
--- 3348,3354 ----
        /* FIXME: We shouldn't be registering new defs if the variable
  	 doesn't need to be renamed.  */
        register_new_def (SSA_NAME_VAR (VDEF_RESULT (vdefs, i)), 
! 			VDEF_RESULT (vdefs, i), block_defs_p, currdefs);
      }
  }
  
*************** rewrite_operand (tree *op_p)
*** 3377,3386 ****
     current reaching definition into the stack pointed by BLOCK_DEFS_P.
     IS_REAL_OPERAND is true when DEF is a real definition.  */
  
! static void
! register_new_def (tree var, tree def, varray_type *block_defs_p)
  {
!   tree currdef = get_value_for (var, currdefs);
  
    if (! *block_defs_p)
      VARRAY_TREE_INIT (*block_defs_p, 20, "block_defs");
--- 3378,3388 ----
     current reaching definition into the stack pointed by BLOCK_DEFS_P.
     IS_REAL_OPERAND is true when DEF is a real definition.  */
  
! void
! register_new_def (tree var, tree def,
! 		  varray_type *block_defs_p, varray_type table)
  {
!   tree currdef = get_value_for (var, table);
  
    if (! *block_defs_p)
      VARRAY_TREE_INIT (*block_defs_p, 20, "block_defs");
*************** register_new_def (tree var, tree def, va
*** 3398,3404 ****
    VARRAY_PUSH_TREE (*block_defs_p, currdef);
  
    /* Set the current reaching definition for VAR to be DEF.  */
!   set_value_for (var, def, currdefs);
  }
  
  
--- 3400,3406 ----
    VARRAY_PUSH_TREE (*block_defs_p, currdef);
  
    /* Set the current reaching definition for VAR to be DEF.  */
!   set_value_for (var, def, table);
  }
  
  
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.161
diff -c -p -r1.342.2.161 tree.h
*** tree.h	18 Jan 2004 22:38:19 -0000	1.342.2.161
--- tree.h	19 Jan 2004 23:03:44 -0000
***************
*** 1,6 ****
  /* Front-end tree definitions for GNU compiler.
     Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
!    2001, 2002, 2003 Free Software Foundation, Inc.
  
  This file is part of GCC.
  
--- 1,6 ----
  /* Front-end tree definitions for GNU compiler.
     Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
!    2001, 2002, 2003, 2004 Free Software Foundation, Inc.
  
  This file is part of GCC.
  





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