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] CCP and variable reference fixes [patch]


- Removes unnecessary fields from tree_ref structure.  We don't
  need to keep pointers into the expression nor operand for each
  reference.  This makes it possible for a pass to replicate a
  statement and replace references from the original statement
  into the copy.
  
  Useful when a pass needs to try a replacement before committing
  changes.  References inside a statement should be replaced with
  calls to replace_ref_in.


- Changes the way CCP operates.  Instead of traversing
  references, we now traverse statements in a block.  It's
  actually sparser that way.  We were visiting the same statement
  multiple times before.

- Fixes a bug in visit_phi_node.  We were not checking for
  killing definitions reaching the PHI node.  We were also not
  checking whether the PHI node was volatile.


Bootstrapped and tested on x86.

Diego.



	* Makefile.in (tree-ssa-ccp.o): Add dependency on tree-inline.h
	* tree-cfg.c (find_taken_edge): New function.
	(cleanup_cond_expr_graph): Call it.
	(disconnect_unreachable_case_labels): Call it.

	* tree-dfa.c (struct clobber_data_d): Remove field
	parent_expr_p.  Update all users.
	(find_refs_in_expr): Remove argument parent_expr_p.  Update all users.
	(create_ref): Remove arguments parent_expr_p and operand_p.  Update
	all users.
	(replace_ref_in): Rename from replace_ref_operand_with.  Update all
	users.  Find the operand in the statement and replace it with a new
	operand.
	(replace_ref_r): New local function.
	(is_killing_def): Also handle V_PHI references.
	(output_ref): Move from tree-flow-inline.h

	* tree-flow-inline.h (ref_expr): Remove.  Update all users.
	(restore_ref_operand): Remove.  Update all users.
	(set_output_ref): Remove.  Update all users.
	(is_assignment_stmt): New function.
	(is_may_def, is_may_use, is_partial_def, is_partial_use,
	is_volatile_def, is_volatile_use, is_default_def,
	is_clobbering_def, is_initializing_def, is_relocating_def,
	is_addressof_use, is_pure_use): Check reference type first.
	(is_pure_def): New function.

	* tree-flow.h (struct tree_ref_common): Remove fields expr_p,
	operand_p and orig_operand.  Update all users.
	(struct tree_ann_d): Remove field output_ref.  Update all users.

	* tree-ssa-ccp.c: Include tree-inline.h.
	(simulate_block): Simulate every statement in the block, not its
	references
	(simulate_def_use_chains): Simulate statements containing uses
	reached by the definition.
	(substitute_and_fold): Traverse statements, not references.
	Call fold_stmt.
	(visit_phi_node): If PHI node is marked volatile, assume varying.
	(visit_stmt): Rename from visit_expression_for.  Work on a
	statement, not a reference.
	(visit_assignment): Rename from visit_assignment_for.  Work on a
	statement, not a reference.
	(visit_cond_stmt): Rename from visit_condexpr_for.  Work on a
	statement, not a reference.
	(evaluate_stmt): Rename from evaluate_expr.  Work on a statement,
	not a reference.
	(initialize): Initialize special definitions to varying.
	(replace_uses_in): Work on a statement, not an expression.
	(fold_stmt): Rename from ccp_fold.  Work on a statement, not an
	expression.
	(get_rhs): New local function.
	(set_rhs): New local function.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.47
diff -d -u -p -r1.903.2.47 Makefile.in
--- Makefile.in	6 Nov 2002 12:20:55 -0000	1.903.2.47
+++ Makefile.in	7 Nov 2002 04:37:46 -0000
@@ -1567,7 +1567,7 @@ ssa-ccp.o : ssa-ccp.c $(CONFIG_H) system
     $(BASIC_BLOCK_H) ssa.h insn-config.h $(RECOG_H) output.h \
     errors.h $(GGC_H) df.h function.h
 tree-ssa-ccp.o : tree-ssa-ccp.c $(CONFIG_H) system.h errors.h $(TREE_H) \
-    $(RTL_H) $(TM_P_H) $(TREE_FLOW_H) diagnostic.h
+    $(RTL_H) $(TM_P_H) $(TREE_FLOW_H) diagnostic.h tree-inline.h
 df.o : df.c $(CONFIG_H) system.h $(RTL_H) insn-config.h $(RECOG_H) \
    function.h $(REGS_H) $(OBSTACK_H) hard-reg-set.h $(BASIC_BLOCK_H) df.h \
    $(FIBHEAP_H)
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.26
diff -d -u -p -r1.1.4.26 tree-cfg.c
--- tree-cfg.c	6 Nov 2002 22:22:34 -0000	1.1.4.26
+++ tree-cfg.c	7 Nov 2002 04:37:47 -0000
@@ -1074,6 +1074,7 @@ cleanup_cond_expr_graph (bb)
 {
   tree cond_expr = first_stmt (bb);
   tree val;
+  edge taken_edge;
 
 #if defined ENABLE_CHECKING
   if (TREE_CODE (cond_expr) != COND_EXPR)
@@ -1081,30 +1082,10 @@ cleanup_cond_expr_graph (bb)
 #endif
 
   val = COND_EXPR_COND (cond_expr);
-  if (really_constant_p (val))
+  taken_edge = find_taken_edge (bb, val);
+  if (taken_edge)
     {
-      bool always_false;
-      edge e, taken_edge, next;
-
-      /* Determine which branch of the if() will be taken.  */
-      taken_edge = NULL;
-      always_false = (simple_cst_equal (val, integer_zero_node) == 1);
-      for (e = bb->succ; e; e = e->succ_next)
-	{
-	  if (((e->flags & EDGE_TRUE_VALUE) && !always_false)
-	      || ((e->flags & EDGE_FALSE_VALUE) && always_false))
-	    {
-	      taken_edge = e;
-	      break;
-	    }
-	}
-
-      if (taken_edge == NULL)
-	{
-	  /* If E is not going to the THEN nor the ELSE clause, then it's
-	     the fallthru edge to the successor block of the if() block.  */
-	  taken_edge = find_edge (bb, successor_block (bb));
-	}
+      edge e, next;
 
       /* Remove all the edges except the one that is always executed.  */
       for (e = bb->succ; e; e = next)
@@ -1162,61 +1143,134 @@ static void
 disconnect_unreachable_case_labels (bb)
      basic_block bb;
 {
-  edge e, default_edge, taken_edge;
+  edge taken_edge;
   tree switch_val;
 
-  default_edge = NULL;
-  taken_edge = NULL;
-
   switch_val = SWITCH_COND (first_stmt (bb));
-  if (!really_constant_p (switch_val))
-    return;
+  taken_edge = find_taken_edge (bb, switch_val);
+  if (taken_edge)
+    {
+      edge e, next;
 
-  /* See if the switch() value matches one of the case labels.  */
-  for (e = bb->succ; e; e = e->succ_next)
+      /* Remove all the edges that go to case labels that will never
+	 be taken.  */
+      for (e = bb->succ; e; e = next)
+	{
+	  next = e->succ_next;
+	  if (e != taken_edge)
+	    remove_edge (e);
+	}
+    }
+}
+
+
+/* Given a control block BB and a constant value VAL, return the edge
+   that will be taken out of BLOCK.  If VAL does not match a unique edge,
+   NULL is returned.  */
+
+edge
+find_taken_edge (bb, val)
+     basic_block bb;
+     tree val;
+{
+  tree stmt;
+  edge e, taken_edge;
+
+  stmt = first_stmt (bb);
+
+#if defined ENABLE_CHECKING
+  if (!is_ctrl_stmt (stmt))
+    abort ();
+#endif
+
+  /* If VAL is not a constant, we can't determine which edge might
+     be taken.  */
+  if (val == NULL || !really_constant_p (val))
+    return NULL;
+
+  taken_edge = NULL;
+  if (TREE_CODE (stmt) == COND_EXPR)
     {
-      tree val;
-      edge dest_edge = e;
-      tree dest_t = first_stmt (dest_edge->dest);
+      bool always_false;
+      bool always_true;
 
-      if (TREE_CODE (dest_t) != CASE_LABEL_EXPR)
-	continue;
+      /* Determine which branch of the if() will be taken.  */
+      always_false = (simple_cst_equal (val, integer_zero_node) == 1);
+      always_true = (simple_cst_equal (val, integer_one_node) == 1);
 
-      val = CASE_LOW (dest_t);
-      if (val == NULL_TREE)
+      /* If VAL is a constant but it can't be reduced to a 0 or a 1, then
+	 we don't really know which edge will be taken at runtime.  This
+	 may happen when comparing addresses (e.g., if (&var1 == 4))  */
+      if (!always_false && !always_true)
+	return NULL;
+
+      for (e = bb->succ; e; e = e->succ_next)
 	{
-	  /* Remember that we found a default label, just in case no other
-	     label matches the switch() value.  */
-	  default_edge = dest_edge;
+	  if (((e->flags & EDGE_TRUE_VALUE) && always_true)
+	      || ((e->flags & EDGE_FALSE_VALUE) && always_false))
+	    {
+	      taken_edge = e;
+	      break;
+	    }
 	}
-      else if (simple_cst_equal (val, switch_val) == 1)
+
+      if (taken_edge == NULL)
 	{
-	  /* We found the unique label that will be taken by the switch.
-	     No need to keep looking.  All the other labels are never
-	     reached directly from the switch().  */
-	  taken_edge = dest_edge;
-	  break;
+	  /* If E is not going to the THEN nor the ELSE clause, then it's
+	     the fallthru edge to the successor block of the if() block.  */
+	  taken_edge = find_edge (bb, successor_block (bb));
 	}
     }
-
-  /* If no case exists for the value used in the switch(), we use the
-     default label.  */
-  if (taken_edge == NULL)
-    taken_edge = default_edge;
-
-  /* Remove all the edges that go to case labels that will never be taken.  */
-  if (taken_edge)
+  else if (TREE_CODE (stmt) == SWITCH_EXPR)
     {
-      edge next;
-      for (e = bb->succ; e; e = next)
+      edge default_edge = NULL;
+
+      /* See if the switch() value matches one of the case labels.  */
+      for (e = bb->succ; e; e = e->succ_next)
 	{
-	  next = e->succ_next;
-	  if (e != taken_edge)
-	    remove_edge (e);
+	  tree label_val;
+	  edge dest_edge = e;
+	  tree dest_t = first_stmt (dest_edge->dest);
+
+	  /* Remember the edge out of the switch() just in case there is no
+	     matching label in the body.  */
+	  if (TREE_CODE (dest_t) != CASE_LABEL_EXPR)
+	    continue;
+
+	  label_val = CASE_LOW (dest_t);
+	  if (label_val == NULL_TREE)
+	    {
+	      /* Remember that we found a default label, just in case no other
+	         label matches the switch() value.  */
+	      default_edge = dest_edge;
+	    }
+	  else if (simple_cst_equal (label_val, val) == 1)
+	    {
+	      /* We found the unique label that will be taken by the switch.
+	         No need to keep looking.  All the other labels are never
+	         reached directly from the switch().  */
+	      taken_edge = dest_edge;
+	      break;
+	    }
 	}
+
+      /* If no case exists for the value used in the switch(), we use the
+         default label.  If the switch() has no label, we use the edge
+	 going out of the switch() body.  */
+      if (taken_edge == NULL)
+	taken_edge = default_edge 
+		     ? default_edge
+		     : find_edge (bb, successor_block (bb));
     }
-}
+  else
+    {
+      /* LOOP_EXPR nodes are always followed by their successor block.  */
+      taken_edge = bb->succ;
+    }
+
 
+  return taken_edge;
+}
 
 
 /*---------------------------------------------------------------------------
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.41
diff -d -u -p -r1.1.4.41 tree-dfa.c
--- tree-dfa.c	6 Nov 2002 22:22:33 -0000	1.1.4.41
+++ tree-dfa.c	7 Nov 2002 04:37:47 -0000
@@ -37,7 +37,6 @@ Boston, MA 02111-1307, USA.  */
 #include "tree-simple.h"
 #include "tree-flow.h"
 #include "tree-inline.h"
-
 #include "tree-alias-common.h"
 
 /* Local declarations.  */
@@ -45,9 +44,13 @@ struct clobber_data_d
 {
   basic_block bb;
   tree *parent_stmt_p;
-  tree *parent_expr_p;
 };
 
+struct replace_data_d
+{
+  tree old;
+  tree new;
+};
 
 /* DFA Statistics.  */
 struct dfa_stats_d
@@ -79,7 +82,7 @@ extern int tree_ssa_dump_flags;
 
 /* Local functions.  */
 static void find_refs_in_expr		PARAMS ((tree *, enum tree_ref_type,
-      						 unsigned, basic_block, tree *,
+      						 unsigned, basic_block,
 						 tree *));
 static void add_referenced_var		PARAMS ((tree));
 static void dump_if_different		PARAMS ((FILE *, const char * const,
@@ -94,10 +97,10 @@ static tree clobber_vars_r		PARAMS ((tre
 static void compute_may_aliases		PARAMS ((void));
 static void find_may_aliases_for	PARAMS ((tree));
 static void add_may_alias		PARAMS ((tree, tree));
-static inline bool may_alias_p			PARAMS ((tree, tree));
-static bool is_visible_to		PARAMS ((tree, tree));
+static inline bool may_alias_p		PARAMS ((tree, tree));
 static size_t tree_ref_size		PARAMS ((enum tree_ref_type));
 static inline tree create_indirect_ref	PARAMS ((tree));
+static tree replace_ref_r		PARAMS ((tree *, int *, void *));
 
 
 /* Global declarations.  */
@@ -167,37 +170,29 @@ find_refs_in_stmt (stmt_p, bb)
   switch (code)
     {
     case COND_EXPR:
-      find_refs_in_expr (&COND_EXPR_COND (stmt), V_USE, 0, bb, stmt_p,
-	                 &COND_EXPR_COND (stmt));
+      find_refs_in_expr (&COND_EXPR_COND (stmt), V_USE, 0, bb, stmt_p);
       break;
 
     case SWITCH_EXPR:
-      find_refs_in_expr (&SWITCH_COND (stmt), V_USE, 0, bb, stmt_p,
-	                 &SWITCH_COND (stmt));
+      find_refs_in_expr (&SWITCH_COND (stmt), V_USE, 0, bb, stmt_p);
       break;
 
     case ASM_EXPR:
-      find_refs_in_expr (&ASM_INPUTS (stmt), V_USE, 0, bb, stmt_p,
-	                 &ASM_INPUTS (stmt));
-      find_refs_in_expr (&ASM_OUTPUTS (stmt), V_DEF, TRM_CLOBBER, bb, stmt_p,
-	                 &ASM_OUTPUTS (stmt));
-      find_refs_in_expr (&ASM_CLOBBERS (stmt), V_DEF, TRM_CLOBBER, bb, stmt_p,
-	                 &ASM_CLOBBERS (stmt));
+      find_refs_in_expr (&ASM_INPUTS (stmt), V_USE, 0, bb, stmt_p);
+      find_refs_in_expr (&ASM_OUTPUTS (stmt), V_DEF, TRM_CLOBBER, bb, stmt_p);
+      find_refs_in_expr (&ASM_CLOBBERS (stmt), V_DEF, TRM_CLOBBER, bb, stmt_p);
       break;
 
     case RETURN_EXPR:
-      find_refs_in_expr (&TREE_OPERAND (stmt, 0), V_USE, 0, bb, stmt_p, 
-	                 &TREE_OPERAND (stmt, 0));
+      find_refs_in_expr (&TREE_OPERAND (stmt, 0), V_USE, 0, bb, stmt_p);
       break;
 
     case GOTO_EXPR:
-      find_refs_in_expr (&GOTO_DESTINATION (stmt), V_USE, 0, bb, stmt_p,
-	                 &GOTO_DESTINATION (stmt));
+      find_refs_in_expr (&GOTO_DESTINATION (stmt), V_USE, 0, bb, stmt_p);
       break;
 
     case LABEL_EXPR:
-      find_refs_in_expr (&LABEL_EXPR_LABEL (stmt), V_USE, 0, bb, stmt_p,
-			 &LABEL_EXPR_LABEL (stmt));
+      find_refs_in_expr (&LABEL_EXPR_LABEL (stmt), V_USE, 0, bb, stmt_p);
       break;
 
       /* These nodes contain no variable references.  */
@@ -207,7 +202,7 @@ find_refs_in_stmt (stmt_p, bb)
       break;
 
     default:
-      find_refs_in_expr (stmt_p, V_USE, 0, bb, stmt_p, stmt_p);
+      find_refs_in_expr (stmt_p, V_USE, 0, bb, stmt_p);
     }
 }
 
@@ -219,29 +214,19 @@ find_refs_in_stmt (stmt_p, bb)
 
    REF_MOD is the set of modifier flags for REF_TYPE.
 
-   BB, PARENT_STMT_P and PARENT_EXPR_P give the location of *EXPR_P in the
-      program.
-      
-   NOTE: PARENT_EXPR_P and PARENT_STMT_P may point to the same tree.  For
-      instance, given the statement 'a = b + c;', they both point to the
-      MODIFY_EXPR tree.
-      
-      However, given 'if (a > b)', PARENT_STMT_P will point to the
-      COND_EXPR tree, while PARENT_EXPR_P will point to the GT_EXPR tree.  */
+   BB and PARENT_STMT_P give the location of *EXPR_P in the program.  */
 
 static void
-find_refs_in_expr (expr_p, ref_type, ref_mod, bb, parent_stmt_p, parent_expr_p)
+find_refs_in_expr (expr_p, ref_type, ref_mod, bb, parent_stmt_p)
      tree *expr_p;
      enum tree_ref_type ref_type;
      unsigned ref_mod;
      basic_block bb;
      tree *parent_stmt_p;
-     tree *parent_expr_p;
 {
   enum tree_code code;
   char class;
   tree expr = *expr_p;
-  tree parent_expr = *parent_expr_p;
   tree parent_stmt = *parent_stmt_p;
 
   if (expr == NULL || expr == error_mark_node)
@@ -260,18 +245,16 @@ find_refs_in_expr (expr_p, ref_type, ref
     return;
 
   /* If this reference is associated with a non SIMPLE expression, then we
-     mark the parent expression non SIMPLE and recursively clobber every
-     variable referenced by PARENT_EXPR.  FIXME: TREE_NOT_GIMPLE must die.  */
-  if (parent_stmt && parent_expr && TREE_NOT_GIMPLE (expr))
+     mark the statement non GIMPLE and recursively clobber every
+     variable referenced by PARENT_STMT.  FIXME  TREE_NOT_GIMPLE must die.  */
+  if (parent_stmt && TREE_NOT_GIMPLE (expr))
     {
       struct clobber_data_d clobber_data;
 
-      TREE_NOT_GIMPLE (parent_expr) = 1;
       TREE_NOT_GIMPLE (parent_stmt) = 1;
       clobber_data.bb = bb;
-      clobber_data.parent_expr_p = parent_expr_p;
       clobber_data.parent_stmt_p = parent_stmt_p;
-      walk_tree (parent_expr_p, clobber_vars_r, &clobber_data, NULL);
+      walk_tree (parent_stmt_p, clobber_vars_r, &clobber_data, NULL);
       return;
     }
 
@@ -285,8 +268,7 @@ find_refs_in_expr (expr_p, ref_type, ref
   /* If we found a _DECL node, create a reference to it and return.  */
   if (code == VAR_DECL || code == PARM_DECL)
     {
-      create_ref (expr, ref_type, ref_mod, bb, parent_stmt_p, parent_expr_p,
-	          expr_p, 1);
+      create_ref (expr, ref_type, ref_mod, bb, parent_stmt_p, 1);
 
       /* If we just created a V_DEF reference for a pointer variable 'p',
 	 we have to clobber the associated '*p' variable, because now 'p'
@@ -298,7 +280,7 @@ find_refs_in_expr (expr_p, ref_type, ref
 	    set_indirect_var (expr, create_indirect_ref (expr));
 
 	  create_ref (indirect_var (expr), V_DEF, TRM_RELOCATE, bb,
-		      parent_stmt_p, parent_expr_p, NULL, 1);
+		      parent_stmt_p, 1);
 	}
 
       return;
@@ -337,8 +319,7 @@ find_refs_in_expr (expr_p, ref_type, ref
       tree ptr_sym = get_base_symbol (ptr);
 
       /* Create a V_USE reference for the pointer variable itself.  */
-      find_refs_in_expr (&TREE_OPERAND (expr, 0), V_USE, 0, bb, parent_stmt_p,
-	                 parent_expr_p);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), V_USE, 0, bb, parent_stmt_p);
 
       /* If this is the first INDIRECT_REF node we find for PTR, set EXPR
 	 to be the indirect variable used to represent all dereferences of
@@ -347,7 +328,7 @@ find_refs_in_expr (expr_p, ref_type, ref
 	set_indirect_var (ptr_sym, expr);
 
       create_ref (indirect_var (ptr_sym), ref_type, ref_mod, bb, parent_stmt_p,
-		  parent_expr_p, expr_p, 1);
+		  1);
 
       return;
     }
@@ -363,12 +344,10 @@ find_refs_in_expr (expr_p, ref_type, ref
       /* Change the reference type to a partial def/use when processing
 	 the LHS of the reference.  */
       find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type,
-	                 ref_mod | TRM_PARTIAL, bb, parent_stmt_p,
-			 parent_expr_p);
+	                 ref_mod | TRM_PARTIAL, bb, parent_stmt_p);
 
       /* References on the RHS of the array are always used as indices.  */
-      find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p,
-			 parent_expr_p);
+      find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p);
       return;
     }
 
@@ -390,8 +369,7 @@ find_refs_in_expr (expr_p, ref_type, ref
       /* Modify the reference to be a partial reference of the LHS of the
 	 expression.  */
       find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type,
-	                 ref_mod | TRM_PARTIAL, bb, parent_stmt_p,
-			 parent_expr_p);
+	                 ref_mod | TRM_PARTIAL, bb, parent_stmt_p);
       return;
     }
 
@@ -399,10 +377,8 @@ find_refs_in_expr (expr_p, ref_type, ref
      references.  */
   if (code == INIT_EXPR || code == MODIFY_EXPR)
     {
-      find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p,
-			 parent_expr_p);
-      find_refs_in_expr (&TREE_OPERAND (expr, 0), V_DEF, 0, bb, parent_stmt_p,
-			 parent_expr_p);
+      find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), V_DEF, 0, bb, parent_stmt_p);
       return;
     }
  
@@ -419,11 +395,9 @@ find_refs_in_expr (expr_p, ref_type, ref
       tree callee;
       int flags;
 
-      find_refs_in_expr (&TREE_OPERAND (expr, 0), V_USE, 0, bb, parent_stmt_p,
-			  parent_expr_p);
+      find_refs_in_expr (&TREE_OPERAND (expr, 0), V_USE, 0, bb, parent_stmt_p);
 
-      find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p,
-			  parent_expr_p);
+      find_refs_in_expr (&TREE_OPERAND (expr, 1), V_USE, 0, bb, parent_stmt_p);
 
       callee = get_callee_fndecl (expr);
       flags = (callee) ? flags_from_decl_or_type (callee) : 0;
@@ -432,10 +406,8 @@ find_refs_in_expr (expr_p, ref_type, ref
 	  may-use followed by a clobbering definition of GLOBAL_VAR.  */
       if (! (flags & (ECF_CONST | ECF_PURE)))
 	{
-	  create_ref (global_var, V_USE, TRM_MAY, bb, parent_stmt_p, NULL,
-	              NULL, 1);
-	  create_ref (global_var, V_DEF, TRM_CLOBBER, bb, parent_stmt_p, NULL,
-	              NULL, 1);
+	  create_ref (global_var, V_USE, TRM_MAY, bb, parent_stmt_p, 1);
+	  create_ref (global_var, V_DEF, TRM_CLOBBER, bb, parent_stmt_p, 1);
 	}
 
       return;
@@ -446,7 +418,7 @@ find_refs_in_expr (expr_p, ref_type, ref
   if (code == ADDR_EXPR)
     {
       find_refs_in_expr (&TREE_OPERAND (expr, 0), V_USE, TRM_ADDRESSOF, bb,
-			 parent_stmt_p, parent_expr_p);
+			 parent_stmt_p);
       return;
     }
 
@@ -457,7 +429,7 @@ find_refs_in_expr (expr_p, ref_type, ref
 
       for (op = expr; op; op = TREE_CHAIN (op))
 	find_refs_in_expr (&TREE_VALUE (op), ref_type, ref_mod, bb,
-	                   parent_stmt_p, parent_expr_p);
+	                   parent_stmt_p);
       return;
     }
 
@@ -467,7 +439,7 @@ find_refs_in_expr (expr_p, ref_type, ref
       || code == VA_ARG_EXPR)
     {
       find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type, ref_mod, bb,
-			 parent_stmt_p, parent_expr_p);
+			 parent_stmt_p);
       return;
     }
 
@@ -481,9 +453,9 @@ find_refs_in_expr (expr_p, ref_type, ref
       || code == CONSTRUCTOR)
     {
       find_refs_in_expr (&TREE_OPERAND (expr, 0), ref_type, ref_mod, bb,
-		         parent_stmt_p, parent_expr_p);
+		         parent_stmt_p);
       find_refs_in_expr (&TREE_OPERAND (expr, 1), ref_type, ref_mod, bb,
-	                 parent_stmt_p, parent_expr_p);
+	                 parent_stmt_p);
       return;
     }
 
@@ -796,9 +768,9 @@ tree_ref_size (ref_type)
       bitmask built from the TRM_* constants.  This bitmask is used to set
       the corresponding bitfield in the various tree_ref structures.
 
-   BB, PARENT_STMT_P, PARENT_EXPR_P and OPERAND_P give the exact location
-      of the reference.  The last three can be NULL in the case of
-      artificial references (PHI nodes, default definitions, etc).
+   BB and PARENT_STMT_P give the location of the reference.  PARENT_STMT_P
+      can be NULL in the case of artificial references (PHI nodes, default
+      definitions, etc).
 
    ADD_TO_BB should be 1 if the caller wants the reference to be added
       to the list of references for BB (i.e., bb_refs (BB)).  In that case,
@@ -810,21 +782,17 @@ tree_ref_size (ref_type)
       responsible for the placement of the newly created reference.  */
 
 tree_ref
-create_ref (var, ref_type, ref_mod, bb, parent_stmt_p, parent_expr_p, operand_p,
-            add_to_bb)
+create_ref (var, ref_type, ref_mod, bb, parent_stmt_p, add_to_bb)
      tree var;
      enum tree_ref_type ref_type;
      unsigned ref_mod;
      basic_block bb;
      tree *parent_stmt_p;
-     tree *parent_expr_p;
-     tree *operand_p;
      int add_to_bb;
 {
   size_t size;
   tree_ref ref;
   tree parent_stmt = (parent_stmt_p) ? *parent_stmt_p : NULL_TREE;
-  tree parent_expr = (parent_expr_p) ? *parent_expr_p : NULL_TREE;
 
 #if defined ENABLE_CHECKING
   if (bb == NULL)
@@ -852,9 +820,6 @@ create_ref (var, ref_type, ref_mod, bb, 
   ref->common.type = ref_type;
   ref->common.bb = bb;
   ref->common.stmt_p = parent_stmt_p;
-  ref->common.expr_p = parent_expr_p;
-  ref->common.operand_p = operand_p;
-  ref->common.orig_operand = (operand_p) ? *operand_p : NULL;
 
   /* Set the reference type modifier flags.  */
   if (ref_mod & TRM_MAY)
@@ -926,15 +891,10 @@ create_ref (var, ref_type, ref_mod, bb, 
       /* Add this reference to the list of references for the variable.  */
       add_tree_ref (var, ref);
 
-      /* Add the reference to the list of references for the parent
-	 expression.  */
-      if (parent_expr)
-	add_tree_ref (parent_expr, ref);
-
       /* In some cases the parent statement and parent expression are the
 	 same tree node.  For instance 'a = 5;'.  Avoid adding the same
 	 reference twice to the same list in these cases.  */
-      if (parent_stmt && parent_stmt != parent_expr)
+      if (parent_stmt)
 	add_tree_ref (parent_stmt, ref);
     }
 
@@ -943,19 +903,6 @@ create_ref (var, ref_type, ref_mod, bb, 
   if (add_to_bb)
     add_ref_to_list_end (bb_refs (bb), ref);
 
-  /* If this is an unmodified V_DEF reference, then this reference
-     represents the output of its parent statement (i.e., the reference is
-     the LHS of an assignment).  In this case, tell the parent statement
-     about it.
-
-     This is useful for algorithms like constant propagation when
-     evaluating expressions, the output reference for the expression is
-     where the lattice value of the expression can be stored.  */
-  if (ref_type == V_DEF
-      && ref_mod == 0
-      && !TREE_NOT_GIMPLE (parent_stmt))
-    set_output_ref (parent_stmt, ref);
-
   return ref;
 }
 
@@ -1021,33 +968,119 @@ add_referenced_var (var)
 			     Code replacement
 ---------------------------------------------------------------------------*/
 
-/* Replace the operand for a reference with a new operand.
+/* Replace reference REF in statement STMT with a new variable or constant OP.
 
    FIXME: Need to properly update DFA information (create new references,
    update SSA links, etc).  */
 
 void
-replace_ref_operand_with (ref, op)
+replace_ref_in (stmt, ref, op)
+     tree stmt;
      tree_ref ref;
      tree op;
 {
-  if (ref->common.operand_p)
-    *(ref->common.operand_p) = op;
-}
+  enum tree_code code;
+  struct replace_data_d replace_data;
 
+  STRIP_WFL (stmt);
+  STRIP_NOPS (stmt);
 
-/* Replace the expression for a reference with a new expression.
+#if defined ENABLE_CHECKING
+  if (!really_constant_p (op) && !DECL_P (op))
+    abort ();
 
-   FIXME: Need to properly update DFA information (create new references,
-   update SSA links, etc).  */
+  if (ref_type (ref) != V_DEF && ref_type (ref) != V_USE)
+    abort ();
 
-void
-replace_ref_expr_with (ref, expr)
-     tree_ref ref;
-     tree expr;
+  if (ref_type (ref) == V_DEF && !DECL_P (op))
+    abort ();
+
+  if (DECL_P (stmt))
+    abort ();
+#endif
+
+  replace_data.old = ref_var (ref);
+  replace_data.new = op;
+  code = TREE_CODE (stmt);
+  switch (code)
+    {
+    case INIT_EXPR:
+    case MODIFY_EXPR:
+      if (ref_type (ref) == V_DEF)
+	walk_tree (&TREE_OPERAND (stmt, 0), replace_ref_r, &replace_data, NULL);
+      else
+	walk_tree (&TREE_OPERAND (stmt, 1), replace_ref_r, &replace_data, NULL);
+      break;
+
+    case CALL_EXPR:
+      walk_tree (&TREE_OPERAND (stmt, 0), replace_ref_r, &replace_data, NULL);
+      walk_tree (&TREE_OPERAND (stmt, 1), replace_ref_r, &replace_data, NULL);
+      break;
+
+    case COND_EXPR:
+      walk_tree (&COND_EXPR_COND (stmt), replace_ref_r, &replace_data, NULL);
+      break;
+
+    case SWITCH_EXPR:
+      walk_tree (&SWITCH_COND (stmt), replace_ref_r, &replace_data, NULL);
+      break;
+
+    case ASM_EXPR:
+      if (ref_type (ref) == V_USE)
+	walk_tree (&ASM_INPUTS (stmt), replace_ref_r, &replace_data, NULL);
+      else
+	{
+	  walk_tree (&ASM_OUTPUTS (stmt), replace_ref_r, &replace_data, NULL);
+	  walk_tree (&ASM_CLOBBERS (stmt), replace_ref_r, &replace_data, NULL);
+	}
+      break;
+
+    case RETURN_EXPR:
+      walk_tree (&TREE_OPERAND (stmt, 0), replace_ref_r, &replace_data, NULL);
+      break;
+
+    case GOTO_EXPR:
+      walk_tree (&GOTO_DESTINATION (stmt), replace_ref_r, &replace_data, NULL);
+      break;
+
+    case LABEL_EXPR:
+      walk_tree (&LABEL_EXPR_LABEL (stmt), replace_ref_r, &replace_data, NULL);
+      break;
+
+      /* These nodes contain no variable references.  */
+    case LOOP_EXPR:
+    case BIND_EXPR:
+    case CASE_LABEL_EXPR:
+      break;
+
+    default:
+      abort ();
+    }
+}
+
+
+/* Call back for walk_tree to replace references in expression *TP.  */
+
+static tree
+replace_ref_r (tp, walk_subtrees, data)
+     tree *tp;
+     int *walk_subtrees ATTRIBUTE_UNUSED;
+     void *data;
 {
-  if (ref->common.expr_p)
-    *(ref->common.expr_p) = expr;
+  struct replace_data_d *replace_data = (struct replace_data_d *)data;
+  tree t = *tp;
+  tree old = replace_data->old;
+  tree new = replace_data->new;
+
+  /* INDIRECT_REF nodes cannot be compared directly.  */
+  if (TREE_CODE (old) == INDIRECT_REF
+      && TREE_CODE (t) == INDIRECT_REF
+      && TREE_OPERAND (old, 0) == TREE_OPERAND (t, 0))
+    *tp = new;
+  else if (old == t)
+    *tp = new;
+
+  return NULL_TREE;
 }
 
 
@@ -1166,8 +1199,8 @@ dump_ref (outf, prefix, ref, indent, det
 
   fprintf (outf, "): line %d, bb %d, id %lu, ", lineno, bbix, ref_id (ref));
 
-  if (ref_expr (ref))
-    print_generic_expr (outf, ref_expr (ref), 0);
+  if (ref_stmt (ref))
+    print_generic_stmt (outf, ref_stmt (ref), TDF_SLIM);
   else
     fprintf (outf, "<nil>");
 
@@ -1772,10 +1805,9 @@ clobber_vars_r (tp, walk_subtrees, data)
   /* Create may-use and clobber references for every *_DECL in sight.  */
   if (code == VAR_DECL || code == PARM_DECL)
     {
-      create_ref (*tp, V_USE, TRM_MAY, clobber->bb, clobber->parent_stmt_p,
-		  clobber->parent_expr_p, NULL, 1);
+      create_ref (*tp, V_USE, TRM_MAY, clobber->bb, clobber->parent_stmt_p, 1);
       create_ref (*tp, V_DEF, TRM_CLOBBER, clobber->bb, clobber->parent_stmt_p,
-		  clobber->parent_expr_p, NULL, 1); 
+		  1);
     }
 
   return NULL;
@@ -1849,8 +1881,7 @@ may_alias_p (ptr, var_sym)
   if (var_sym == ptr_sym
       || !POINTER_TYPE_P (TREE_TYPE (ptr_sym))
       || !TREE_ADDRESSABLE (var_sym)
-      || DECL_ARTIFICIAL (var_sym)
-      || !is_visible_to (var_sym, ptr_sym))
+      || DECL_ARTIFICIAL (var_sym))
     return false;
 
   ptr_alias_set = get_alias_set (TREE_TYPE (ptr));
@@ -1889,23 +1920,6 @@ find_may_aliases_for (ptr)
 }
 
 
-
-
-/* Return true if SYM1 and SYM2 are visible to each other.  Visibility is
-   determined based on the scopes where each variable is declared.  Both
-   scopes must be the same or one must be enclosed in the other.  */
-
-static bool
-is_visible_to (sym1, sym2)
-     tree sym1;
-     tree sym2;
-{
-  /* FIXME  This should be implemented by traversing the SUPERCONTEXT and
-     SUBBLOCKS links for the each symbol's BIND_EXPR node.  */
-  return true;
-}
-
-
 /* Return true if REF is a V_DEF reference for VAR.  This function handles
    relocations of pointers.  Relocating a pointer, clobbers any dereference
    of the pointer, but it does not affect any of its aliases.  For
@@ -1957,13 +1971,13 @@ is_killing_def (def, use)
   tree use_var = ref_var (use);
 
   if ((ref_type (def) != V_DEF && ref_type (def) != V_PHI)
-      || ref_type (use) != V_USE)
+      || (ref_type (use) != V_USE && ref_type (use) != V_PHI))
     return false;
 
   /* Partial, potential and volatile definitions are no killers.  */
-  if (is_partial_def (def)
-      || is_volatile_def (def)
-      || is_may_def (def))
+  if (is_partial_ref (def)
+      || is_volatile_ref (def)
+      || is_may_ref (def))
     return false;
 
   /* Common case.  Both references are for the same variable.  */
@@ -2111,6 +2125,29 @@ find_decl_location (decl, block)
       tree *loc = find_decl_location (decl, sub);
       if (loc)
 	return loc;
+    }
+
+  return NULL;
+}
+
+
+/* Return the V_DEF reference at the LHS of an assignment statement T.  */
+
+tree_ref
+output_ref (t)
+     tree t;
+{
+  STRIP_WFL (t);
+  STRIP_NOPS (t);
+  if (is_assignment_stmt (t))
+    {
+      ref_list_iterator i;
+      for (i = rli_start (tree_refs (t)); !rli_after_end (i); rli_step (&i))
+	{
+	  tree_ref def = rli_ref (i);
+	  if (ref_type (def) == V_DEF && !def->vdef.m_clobber)
+	    return def;
+	}
     }
 
   return NULL;
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow-inline.h,v
retrieving revision 1.1.2.11
diff -d -u -p -r1.1.2.11 tree-flow-inline.h
--- tree-flow-inline.h	6 Nov 2002 22:22:34 -0000	1.1.2.11
+++ tree-flow-inline.h	7 Nov 2002 04:37:47 -0000
@@ -47,13 +47,6 @@ ref_bb (ref)
 }
 
 static inline tree
-ref_expr (ref)
-     tree_ref ref;
-{
-  return ref->common.expr_p ? *(ref->common.expr_p) : NULL_TREE;
-}
-
-static inline tree
 ref_stmt (ref)
      tree_ref ref;
 {
@@ -176,14 +169,6 @@ set_phi_arg (phi, i, arg)
   VARRAY_GENERIC_PTR (phi->vphi.phi_args, i) = (PTR)arg;
 }
 
-static inline void
-restore_ref_operand (ref)
-     tree_ref ref;
-{
-  if (ref->common.operand_p)
-    *(ref->common.operand_p) = ref->common.orig_operand;
-}
-  
 static inline tree_ann
 tree_annotation (t)
      tree t;
@@ -325,32 +310,6 @@ get_filename (expr)
     return "???";
 }
 
-static inline tree_ref
-output_ref (t)
-     tree t;
-{
-  return tree_annotation (t) ? tree_annotation (t)->output_ref : NULL;
-}
-
-static inline void
-set_output_ref (t, def)
-     tree t;
-     tree_ref def;
-{
-  tree_ann ann;
-#if defined ENABLE_CHECKING
-  {
-    tree w = t;
-    STRIP_WFL (w);
-    STRIP_NOPS (w);
-    if (TREE_CODE (w) != MODIFY_EXPR && TREE_CODE (w) != INIT_EXPR)
-      abort ();
-  }
-#endif
-  ann = tree_annotation (t) ? tree_annotation (t) : create_tree_ann (t);
-  ann->output_ref = def;
-}
-
 static inline void
 set_tree_flag (t, flag)
      tree t;
@@ -772,6 +731,15 @@ is_exec_stmt (t)
 }
 
 static inline bool
+is_assignment_stmt (t)
+     tree t;
+{
+  STRIP_WFL (t);
+  STRIP_NOPS (t);
+  return (TREE_CODE (t) == MODIFY_EXPR || TREE_CODE (t) == INIT_EXPR);
+}
+
+static inline bool
 is_may_ref (ref)
      tree_ref ref;
 {
@@ -782,14 +750,14 @@ static inline bool
 is_may_def (ref)
      tree_ref ref;
 {
-  return is_may_ref (ref) && ref_type (ref) == V_DEF;
+  return ref_type (ref) == V_DEF && is_may_ref (ref);
 }
 
 static inline bool
 is_may_use (ref)
      tree_ref ref;
 {
-  return is_may_ref (ref) && ref_type (ref) == V_USE;
+  return ref_type (ref) == V_USE && is_may_ref (ref);
 }
 
 static inline bool
@@ -803,14 +771,14 @@ static inline bool
 is_partial_def (ref)
      tree_ref ref;
 {
-  return is_partial_ref (ref) && ref_type (ref) == V_DEF;
+  return ref_type (ref) == V_DEF && is_partial_ref (ref);
 }
 
 static inline bool
 is_partial_use (ref)
      tree_ref ref;
 {
-  return is_partial_ref (ref) && ref_type (ref) == V_USE;
+  return ref_type (ref) == V_USE && is_partial_ref (ref);
 }
 
 static inline bool
@@ -824,60 +792,74 @@ static inline bool
 is_volatile_def (ref)
      tree_ref ref;
 {
-  return is_volatile_ref (ref) && ref_type (ref) == V_DEF;
+  return ref_type (ref) == V_DEF && is_volatile_ref (ref);
 }
 
 static inline bool
 is_volatile_use (ref)
      tree_ref ref;
 {
-  return is_volatile_ref (ref) && ref_type (ref) == V_USE;
+  return ref_type (ref) == V_USE && is_volatile_ref (ref);
 }
 
 static inline bool
 is_default_def (ref)
      tree_ref ref;
 {
-  return ref->vdef.m_default && ref_type (ref) == V_DEF;
+  return ref_type (ref) == V_DEF && ref->vdef.m_default;
 }
 
 static inline bool
 is_clobbering_def (ref)
      tree_ref ref;
 {
-  return ref->vdef.m_clobber && ref_type (ref) == V_DEF;
+  return ref_type (ref) == V_DEF && ref->vdef.m_clobber;
 }
 
 static inline bool
 is_initializing_def (ref)
      tree_ref ref;
 {
-  return ref->vdef.m_initial && ref_type (ref) == V_DEF;
+  return ref_type (ref) == V_DEF && ref->vdef.m_initial;
 }
 
 static inline bool
 is_relocating_def (ref)
      tree_ref ref;
 {
-  return ref->vdef.m_relocate && ref_type (ref) == V_DEF;
+  return ref_type (ref) == V_DEF && ref->vdef.m_relocate;
 }
 
 static inline bool
 is_addressof_use (ref)
      tree_ref ref;
 {
-  return ref->vuse.m_addressof && ref_type (ref) == V_USE;
+  return ref_type (ref) == V_USE && ref->vuse.m_addressof;
 }
 
 static inline bool
 is_pure_use (ref)
      tree_ref ref;
 {
-  return !ref->vuse.m_addressof
+  return ref_type (ref) == V_USE
+	 && !ref->vuse.m_addressof
          && !is_may_ref (ref)
 	 && !is_partial_ref (ref)
-	 && !is_volatile_ref (ref)
-	 && ref_type (ref) == V_USE;
+	 && !is_volatile_ref (ref);
+}
+
+static inline bool
+is_pure_def (ref)
+     tree_ref ref;
+{
+  return ref_type (ref) == V_DEF
+	 && !ref->vdef.m_default
+	 && !ref->vdef.m_clobber
+	 && !ref->vdef.m_initial
+	 && !ref->vdef.m_relocate
+         && !is_may_ref (ref)
+	 && !is_partial_ref (ref)
+	 && !is_volatile_ref (ref);
 }
 
 /* Return TRUE if we reached the end of the list with iterator I.  */
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.33
diff -d -u -p -r1.1.4.33 tree-flow.h
--- tree-flow.h	6 Nov 2002 22:22:34 -0000	1.1.4.33
+++ tree-flow.h	7 Nov 2002 04:37:47 -0000
@@ -46,11 +46,7 @@ enum tree_ref_type {
      represents a killing definition of the associated variable via an
      assignment expression (i.e., all the bits of the variable are
      modified).  Note that unmodified V_DEF references are only allowed for
-     MODIFY_EXPR and INIT_EXPR expressions.
-
-     In this case, this reference will represent the output value of the
-     associated expression.  For instance, 'a = 3' creates a V_DEF
-     reference for 'a' and calling output_ref('a = 3') returns this V_DEF.  */
+     MODIFY_EXPR and INIT_EXPR expressions.  */
   V_DEF,
 
   /* A V_USE reference represents a read operation from the associated
@@ -120,28 +116,14 @@ struct tree_ref_common GTY(())
   /* Reference type.  */
   enum tree_ref_type type;
 
-  /* Variable being referenced.  This may be a _DECL or an INDIRECT_REF
-     node.  */
+  /* Variable being referenced.  This may be a _DECL, an INDIRECT_REF
+     node or an expression (in the case of E_* references).  */
   tree var;
 
   /* Statement containing the reference.  Maybe NULL for special references
      (e.g., default definitions inserted at the start of every function).  */
   tree * GTY((skip (""))) stmt_p;
 
-  /* Expression tree containing the reference.  Maybe NULL for special
-     references (e.g., default definitions inserted at the start of every
-     function).  */
-  tree * GTY((skip (""))) expr_p;
-
-  /* Pointer to operand of EXPR containing VAR.  Used when substituting the
-     operand with some other value in transformations like constant
-     propagation.  Maybe NULL for special references (e.g., default
-     definitions inserted at the start of every function).  */
-  tree * GTY((skip (""))) operand_p;
-
-  /* Original value stored in *OPERAND_P.  Used by restore_ref_operand.  */
-  tree orig_operand;
-
   /* Basic block containing the reference.  */
   basic_block GTY((skip (""))) bb;
 
@@ -395,12 +377,9 @@ typedef union tree_ref_d *tree_ref;
 static inline enum tree_ref_type ref_type	PARAMS ((tree_ref));
 static inline tree ref_var			PARAMS ((tree_ref));
 static inline tree ref_stmt			PARAMS ((tree_ref));
-static inline tree ref_expr			PARAMS ((tree_ref));
 static inline basic_block ref_bb		PARAMS ((tree_ref));
 static inline unsigned long ref_id		PARAMS ((tree_ref));
-static inline void restore_ref_operand		PARAMS ((tree_ref));
-extern void replace_ref_operand_with		PARAMS ((tree_ref, tree));
-extern void replace_ref_expr_with		PARAMS ((tree_ref, tree));
+extern void replace_ref_in			PARAMS ((tree, tree_ref, tree));
 extern void replace_ref_stmt_with		PARAMS ((tree_ref, tree));
 
 
@@ -433,6 +412,7 @@ static inline bool is_initializing_def		
 static inline bool is_relocating_def		PARAMS ((tree_ref));
 static inline bool is_addressof_use		PARAMS ((tree_ref));
 static inline bool is_pure_use			PARAMS ((tree_ref));
+static inline bool is_pure_def			PARAMS ((tree_ref));
 
 /* For phi_node_arg.  */
 static inline edge phi_arg_edge			PARAMS ((phi_node_arg));
@@ -511,10 +491,6 @@ struct tree_ann_d GTY(())
   /* Flags used to mark optimization-dependent state.  See TF_* below.  */
   HOST_WIDE_INT flags;
 
-  /* Output reference.  This is the V_DEF reference at the LHS of
-     assignments (MODIFY_EXPR and INIT_EXPR).  */
-  tree_ref output_ref;
-
   /* Set of variables that may be aliases of this variable.  */
   varray_type may_aliases;
 };
@@ -546,8 +522,6 @@ static inline void set_tree_flag	PARAMS 
 static inline void clear_tree_flag	PARAMS ((tree, enum tree_flags));
 static inline enum tree_flags tree_flags PARAMS ((tree));
 static inline void reset_tree_flags	PARAMS ((tree));
-static inline tree_ref output_ref	PARAMS ((tree));
-static inline void set_output_ref	PARAMS ((tree, tree_ref));
 static inline tree indirect_var		PARAMS ((tree));
 static inline void set_indirect_var	PARAMS ((tree, tree));
 static inline tree may_alias		PARAMS ((tree, size_t));
@@ -555,6 +529,7 @@ static inline size_t num_may_alias	PARAM
 static inline int get_lineno		PARAMS ((tree));
 static inline const char *get_filename	PARAMS ((tree));
 static inline bool is_exec_stmt		PARAMS ((tree));
+static inline bool is_assignment_stmt	PARAMS ((tree));
 
 
 /*---------------------------------------------------------------------------
@@ -679,6 +654,7 @@ extern tree last_stmt			PARAMS ((basic_b
 extern tree *last_stmt_ptr			PARAMS ((basic_block));
 extern basic_block latch_block		PARAMS ((basic_block));
 extern bool is_latch_block		PARAMS ((basic_block));
+extern edge find_taken_edge		PARAMS ((basic_block, tree));
 
 
 /* In tree-dfa.c  */
@@ -687,7 +663,7 @@ extern void find_refs_in_stmt           
 extern tree_ann create_tree_ann 	PARAMS ((tree));
 extern tree_ref create_ref		PARAMS ((tree, enum tree_ref_type,
       						 unsigned, basic_block, tree *,
-						 tree *, tree *, int));
+						 int));
 extern void debug_ref			PARAMS ((tree_ref));
 extern void dump_ref			PARAMS ((FILE *, const char *, tree_ref,
       						 int, int));
@@ -726,8 +702,9 @@ extern bool ref_defines			PARAMS ((tree_
 extern bool is_killing_def		PARAMS ((tree_ref, tree_ref));
 extern int get_alias_index		PARAMS ((tree, tree));
 extern enum tree_ref_structure_enum tree_ref_structure PARAMS ((tree_ref));
-void remove_decl			PARAMS ((tree));
-tree * find_decl_location		PARAMS ((tree, tree));
+extern void remove_decl			PARAMS ((tree));
+extern tree * find_decl_location	PARAMS ((tree, tree));
+extern tree_ref output_ref		PARAMS ((tree));
 
 
 /* In tree-ssa.c  */
Index: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-ccp.c,v
retrieving revision 1.1.2.29
diff -d -u -p -r1.1.2.29 tree-ssa-ccp.c
--- tree-ssa-ccp.c	5 Nov 2002 23:50:39 -0000	1.1.2.29
+++ tree-ssa-ccp.c	7 Nov 2002 04:37:47 -0000
@@ -45,6 +45,7 @@ Software Foundation, 59 Temple Place - S
 #include "hard-reg-set.h"
 #include "basic-block.h"
 #include "diagnostic.h"
+#include "tree-inline.h"
 #include "tree-flow.h"
 #include "tree-simple.h"
 
@@ -88,27 +89,28 @@ static struct edge_list *edges;
    nodes that need to be visited are accessed using imm_uses (D).  */
 ref_list ssa_edges;
 
-static void initialize                 PARAMS ((void));
-static void finalize                   PARAMS ((void));
-static void visit_phi_node             PARAMS ((tree_ref));
-static value cp_lattice_meet           PARAMS ((value, value));
-static void visit_expression_for       PARAMS ((tree_ref));
-static void visit_condexpr_for         PARAMS ((tree_ref));
-static void visit_assignment_for       PARAMS ((tree_ref));
-static void add_outgoing_control_edges PARAMS ((basic_block));
-static void add_control_edge           PARAMS ((edge));
-static void def_to_undefined           PARAMS ((tree_ref));
-static void def_to_varying             PARAMS ((tree_ref));
-static void set_lattice_value          PARAMS ((tree_ref, value));
-static void simulate_block             PARAMS ((basic_block));
-static void simulate_def_use_chains    PARAMS ((tree_ref));
-static void substitute_and_fold        PARAMS ((void));
-static value evaluate_expr             PARAMS ((tree));
-static void dump_lattice_value         PARAMS ((FILE *, const char *, value));
-static tree widen_bitfield             PARAMS ((tree, tree, tree));
-static void replace_uses_in            PARAMS ((tree));
-static void restore_expr               PARAMS ((tree));
-static tree ccp_fold                   PARAMS ((tree));
+static void initialize			PARAMS ((void));
+static void finalize			PARAMS ((void));
+static void visit_phi_node		PARAMS ((tree_ref));
+static value cp_lattice_meet		PARAMS ((value, value));
+static void visit_stmt			PARAMS ((tree));
+static void visit_cond_stmt		PARAMS ((tree));
+static void visit_assignment		PARAMS ((tree));
+static void add_outgoing_control_edges	PARAMS ((basic_block));
+static void add_control_edge		PARAMS ((edge));
+static void def_to_undefined		PARAMS ((tree_ref));
+static void def_to_varying		PARAMS ((tree_ref));
+static void set_lattice_value		PARAMS ((tree_ref, value));
+static void simulate_block		PARAMS ((basic_block));
+static void simulate_def_use_chains	PARAMS ((tree_ref));
+static void substitute_and_fold		PARAMS ((void));
+static value evaluate_stmt		PARAMS ((tree));
+static void dump_lattice_value		PARAMS ((FILE *, const char *, value));
+static tree widen_bitfield		PARAMS ((tree, tree, tree));
+static bool replace_uses_in		PARAMS ((tree));
+static void fold_stmt			PARAMS ((tree));
+static tree get_rhs			PARAMS ((tree));
+static void set_rhs			PARAMS ((tree, tree));
 
 
 /* Debugging dumps.  */
@@ -137,7 +139,6 @@ tree_ssa_ccp (fndecl)
 	{
 	  /* Pull the next block to simulate off the worklist.  */
 	  basic_block dest_block;
-
 	  dest_block = ((edge)VARRAY_TOP_GENERIC_PTR (edge_info))->dest;
 	  VARRAY_POP (edge_info);
 	  simulate_block (dest_block);
@@ -177,7 +178,7 @@ tree_ssa_ccp (fndecl)
 }
 
 
-/* Simulate the execution of BLOCK.  Evaluate the expression associated
+/* Simulate the execution of BLOCK.  Evaluate the statement associated
    with each variable reference inside the block.  */
 
 static void
@@ -191,53 +192,43 @@ simulate_block (block)
   if (block == EXIT_BLOCK_PTR)
     return;
 
-  /* Similarly, if the block contains no references, we have nothing to do.  */
-  blockrefs = bb_refs (block);
-  if (blockrefs == NULL)
-    return;
+#if defined ENABLE_CHECKING
+  if (block->index < 0 || block->index > last_basic_block)
+    abort ();
+#endif
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "\nSimulating block %d\n", block->index);
 
   /* Always simulate PHI nodes, even if we have simulated this block
      before.  Note that all PHI nodes are consecutive within a block.  */
+  blockrefs = bb_refs (block);
   for (i = rli_start (blockrefs); !rli_after_end (i); rli_step (&i))
     if (ref_type (rli_ref (i)) == V_PHI)
       visit_phi_node (rli_ref (i));
 
-#if defined ENABLE_CHECKING
-  if (block->index < 0 || block->index > last_basic_block)
-    abort ();
-#endif
-
   /* If this is the first time we've simulated this block, then we
-     must simulate each of its insns.  */
+     must simulate each of its statements.  */
   if (!TEST_BIT (executable_blocks, block->index))
     {
-      edge succ_edge = block->succ;
+      gimple_stmt_iterator j;
 
       /* Note that we have simulated this block.  */
       SET_BIT (executable_blocks, block->index);
 
-      for (i = rli_start (blockrefs); !rli_after_end (i); rli_step (&i))
-	{
-	  /* Simulate each reference within the block.  */
-	  if (ref_type (rli_ref (i)) != V_PHI)
-	    visit_expression_for (rli_ref (i));
-	} 
+      for (j = gsi_start_bb (block); !gsi_after_end (j); gsi_step_bb (&j))
+	visit_stmt (gsi_stmt (j));
 
-      /* If we haven't looked at the next block, and it has a
-	 single successor, add it onto the worklist.  This is because
-	 if we only have one successor, we know it gets executed,
-	 so we don't have to wait for cprop to tell us. */
-      if (succ_edge && succ_edge->succ_next == NULL)
-	add_control_edge (succ_edge);
+      /* If the block has a single successor, it will always get executed.
+	 Add it to the worklist.  */
+      if (block->succ && block->succ->succ_next == NULL)
+	add_control_edge (block->succ);
     }
 }
 
 
 /* Follow the def-use chains for definition DEF and simulate all the
-   expressions reached by it.  */
+   statements reached by it.  */
 
 static void
 simulate_def_use_chains (def)
@@ -253,11 +244,13 @@ simulate_def_use_chains (def)
     {
       tree_ref ref = rli_ref (i);
 
-      /* Note that we only visit unmodified V_USE references.  We don't
-	 want to deal with any modifiers here.  */
+      /* Visit the statement containing the use reached by DEF, only if the
+	 destination block is marked executable.  Note that we only visit
+	 unmodified V_USE references.  We don't want to deal with any
+	 modifiers here.  */
       if (is_pure_use (ref)
 	  && TEST_BIT (executable_blocks, ref_bb (ref)->index))
-	visit_expression_for (ref);
+	visit_stmt (ref_stmt (ref));
 
       /* PHI nodes are always visited, regardless of whether or not the
 	 destination block is executable.  */
@@ -275,52 +268,40 @@ substitute_and_fold ()
   basic_block bb;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
-    fprintf (dump_file, "\nSubstituing constants and folding expressions\n\n");
+    fprintf (dump_file, "\nSubstituing constants and folding statements\n\n");
 
-  /* Substitute constants in every expression of every basic block.  */
+  /* Substitute constants in every statement of every basic block.  */
   FOR_EACH_BB (bb)
     {
-      tree new_expr;
-      ref_list_iterator i;
+      gimple_stmt_iterator i;
 
-      for (i = rli_start (bb_refs (bb)); !rli_after_end (i); rli_step (&i))
+      for (i = gsi_start_bb (bb); !gsi_after_end (i); gsi_step_bb (&i))
 	{
-	  tree_ref ref = rli_ref (i);
-	  tree expr = ref_expr (ref);
-	  tree stmt = ref_stmt (ref);
-
-	  /* Skip references not attached to statements and expressions.  */
-	  if (expr == NULL_TREE)
-	    continue;
-
-	  /* We are only interested in expressions that contain unmodified
-	     V_USE references.  */
-	  if (!is_pure_use (ref))
-	    continue;
+	  tree stmt = gsi_stmt (i);
 
 	  /* Skip statements that have been folded already.  */
-	  if (tree_flags (stmt) & TF_FOLDED)
+	  if (tree_flags (stmt) & TF_FOLDED
+	      || !is_exec_stmt (stmt))
 	    continue;
 
-	  /* Replace the expression with its folded version in the statement
-	     and mark it folded.  Note that in the case of assignment
-	     expressions, we fold their RHS (fold() does not handle
-	     assignments).  */
+	  /* Replace the statement with its folded version and mark it
+	     folded.  */
 	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    {
-	      fprintf (dump_file, "Line %d: replaced ", get_lineno (expr));
-	      print_generic_stmt (dump_file, expr, TDF_SLIM);
+	      fprintf (dump_file, "Line %d: replaced ", get_lineno (stmt));
+	      print_generic_stmt (dump_file, stmt, TDF_SLIM);
 	    }
 
-	  replace_uses_in (expr);
-	  new_expr = ccp_fold (expr);
-	  replace_ref_expr_with (ref, new_expr);
-	  set_tree_flag (stmt, TF_FOLDED);
+	  if (replace_uses_in (stmt))
+	    {
+	      fold_stmt (stmt);
+	      set_tree_flag (stmt, TF_FOLDED);
+	    }
 
 	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    {
 	      fprintf (dump_file, " with ");
-	      print_generic_stmt (dump_file, new_expr, TDF_SLIM);
+	      print_generic_stmt (dump_file, stmt, TDF_SLIM);
 	      fprintf (dump_file, "\n");
 	    }
 	}
@@ -346,41 +327,55 @@ visit_phi_node (phi_node)
   phi_val.lattice_val = UNDEFINED;
   phi_val.const_value = NULL_TREE;
 
-  /* Compute the meet operator over all the PHI arguments. */
-  for (i = 0; i < num_phi_args (phi_node); i++)
-    {
-      phi_node_arg arg = phi_arg (phi_node, i);
-      edge e = phi_arg_edge (arg);
+  if (!is_volatile_ref (phi_node))
+    for (i = 0; i < num_phi_args (phi_node); i++)
+      {
+	/* Compute the meet operator over all the PHI arguments. */
 
-      if (dump_file && (dump_flags & TDF_DETAILS))
-	{
-	  fprintf (dump_file, "\n    Argument #%d (%d -> %d %sexecutable)\n",
-	           i, e->src->index, e->dest->index,
-		   (e->flags & EDGE_EXECUTABLE) ? "" : "not ");
-	}
+	phi_node_arg arg = phi_arg (phi_node, i);
+	edge e = phi_arg_edge (arg);
 
-      /* If the incoming edge is executable, Compute the meet operator for
-	 the existing value of the PHI node and the current PHI argument.  */
-      if (e->flags & EDGE_EXECUTABLE)
-	{
-	  tree_ref rdef;
-	  value rdef_val;
-	  
-	  rdef = phi_arg_def (arg);
-	  rdef_val = values[ref_id (rdef)];
-	  phi_val = cp_lattice_meet (phi_val, rdef_val);
+	if (dump_file && (dump_flags & TDF_DETAILS))
+	  {
+	    fprintf (dump_file, "\n    Argument #%d (%d -> %d %sexecutable)\n",
+		    i, e->src->index, e->dest->index,
+		    (e->flags & EDGE_EXECUTABLE) ? "" : "not ");
+	  }
 
-	  if (dump_file && (dump_flags & TDF_DETAILS))
-	    {
-	      dump_ref (dump_file, "\t", phi_arg_def (arg), 0, 0);
-	      dump_lattice_value (dump_file, "\tValue: ", rdef_val);
-	      fprintf (dump_file, "\n");
-	    }
+	/* If the incoming edge is executable, Compute the meet operator for
+	   the existing value of the PHI node and the current PHI argument.  */
+	if (e->flags & EDGE_EXECUTABLE)
+	  {
+	    tree_ref rdef;
+	    value rdef_val;
+	    
+	    rdef = phi_arg_def (arg);
 
-	  if (phi_val.lattice_val == VARYING)
-	    break;
-	}
-    }
+	    if (is_killing_def (rdef, phi_node))
+	      {
+		rdef_val = values[ref_id (rdef)];
+		phi_val = cp_lattice_meet (phi_val, rdef_val);
+	      }
+	    else
+	      {
+		/* If RDEF is a non-killing definition, we cannot assume
+		   anything about this PHI's node value.  In that case, set
+		   its value to VARYING.  */
+		phi_val.lattice_val = VARYING;
+		phi_val.const_value = NULL_TREE;
+	      }
+
+	    if (dump_file && (dump_flags & TDF_DETAILS))
+	      {
+		dump_ref (dump_file, "\t", phi_arg_def (arg), 0, 0);
+		dump_lattice_value (dump_file, "\tValue: ", rdef_val);
+		fprintf (dump_file, "\n");
+	      }
+
+	    if (phi_val.lattice_val == VARYING)
+	      break;
+	  }
+      }
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -436,99 +431,73 @@ cp_lattice_meet (val1, val2)
 }
 
 
-/* Evaluate the expression associated with REF.  If the expression produces
-   an output value and its evaluation changes the lattice value of its
-   output, do the following:
+/* Evaluate statement STMT.  If the statement produces an output value and
+   its evaluation changes the lattice value of its output, do the following:
 
-   - If the expression is an assignment, add all the SSA edges starting at
+   - If the statement is an assignment, add all the SSA edges starting at
      this definition.
 
-   - If the expression controls a conditional branch:
-   	. If the expression evaluates to non-constant, add all edges to
+   - If the statement is a conditional branch:
+   	. If the statement evaluates to non-constant, add all edges to
 	  worklist.
-	. If the expression is constant, add the edge executed as the
+	. If the statement is constant, add the edge executed as the
 	  result of the branch.  */
 
 static void
-visit_expression_for (ref)
-     tree_ref ref;
+visit_stmt (stmt)
+     tree stmt;
 {
-  tree expr;
-
-#if defined ENABLE_CHECKING
-  /* PHI references should be handled by visit_phi_node.  */
-  if (ref_type (ref) == V_PHI)
-    abort ();
-#endif
-
-  /* First examine the reference to see if it's a special definition
-     (clobbering, partial or may-def), mark it varying and add SSA edges
-     that may be coming out of it.  */
-  if (is_clobbering_def (ref)
-      || is_partial_def (ref)
-      || is_may_def (ref)
-      || is_relocating_def (ref))
-    def_to_varying (ref);
-
-  expr = ref_expr (ref);
-  
-  /* No need to do anything if the reference is not associated with an
-     expression.  */
-  if (expr == NULL)
+  /* FIXME: This is lame.  All statements should be in GIMPLE form.  */
+  if (TREE_NOT_GIMPLE (stmt))
     return;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      fprintf (dump_file, "\nVisiting expression: ");
-      print_generic_expr (dump_file, expr, 0);
-      dump_ref (dump_file, "\nfor reference: ", ref, 0, 0);
+      fprintf (dump_file, "\nVisiting statement: ");
+      print_generic_stmt (dump_file, stmt, TDF_SLIM);
+      fprintf (dump_file, "\n");
     }
   
-  /* Now examine the expression.  If the expression produces an output
-     value, evaluate the expression to see if the lattice value of its
-     output has changed.  */
-  if (output_ref (expr))
-    visit_assignment_for (ref);
+  /* Now examine the statement.  If the statement produces an output
+     value, evaluate it to see if the lattice value of its output has
+     changed.  */
+  if (is_assignment_stmt (stmt))
+    visit_assignment (stmt);
 
-  /* If the expression is the predicate of a control statement, see if we
-     can determine which branch will be taken.  */
-  else if (is_simple_condexpr (expr) && ref_bb (ref)->flags & BB_CONTROL_EXPR)
-    visit_condexpr_for (ref);
+  /* If STMT is a control statement, see if we can determine which branch
+     will be taken.  */
+  else if (is_ctrl_stmt (stmt))
+    visit_cond_stmt (stmt);
 
-  /* If the expression is a computed goto, mark all the output edges
+  /* If STMT is a computed goto, mark all the output edges
      executable.  */
-  else if (is_computed_goto (ref_stmt (ref)))
-    add_outgoing_control_edges (ref_bb (ref));
+  else if (is_computed_goto (stmt))
+    add_outgoing_control_edges (bb_for_stmt (stmt));
 }
 
 
-/* Visit the assignment expression holding reference REF.  */
+/* Visit the assignment statement STMT.  Set the value of its LHS to the
+   value computed by the RHS.  */
 
 static void
-visit_assignment_for (ref)
-     tree_ref ref;
+visit_assignment (stmt)
+     tree stmt;
 {
-  tree expr;
   value val;
 
-  expr = ref_expr (ref);
-  STRIP_WFL (expr);
-  STRIP_NOPS (expr);
-
 #if defined ENABLE_CHECKING
-  if (TREE_CODE (expr) != MODIFY_EXPR
-      && TREE_CODE (expr) != INIT_EXPR)
+  if (!is_assignment_stmt (stmt))
     abort ();
 #endif
 
-  /* Evaluate the expression.  */
-  val = evaluate_expr (expr);
+  /* Evaluate the statement.  */
+  val = evaluate_stmt (stmt);
 
   /* FIXME: Hack.  If this was a definition of a bitfield, we need to widen
      the constant value into the type of the destination variable.  This
      should not be necessary if GCC represented bitfields properly.  */
   {
-    tree lhs = TREE_OPERAND (expr, 0);
+    tree lhs = TREE_OPERAND (stmt, 0);
     if (val.lattice_val == CONSTANT
 	&& TREE_CODE (lhs) == COMPONENT_REF
 	&& DECL_BIT_FIELD (TREE_OPERAND (lhs, 1)))
@@ -543,55 +512,44 @@ visit_assignment_for (ref)
 	    val.const_value = NULL;
 	  }
       }
-    }
+  }
 
-  /* Set the lattice value of the expression's output.  */
-  set_lattice_value (output_ref (expr), val);
+  /* Set the lattice value of the statement's output.  */
+  set_lattice_value (output_ref (stmt), val);
 }
 
 
-/* Visit the conditional expression that contains reference REF.  If it
-   evaluates to a constant value, mark outgoing edges appropriately.  */
+/* Visit the conditional statement STMT.  If it evaluates to a constant value,
+   mark outgoing edges appropriately.  */
 
 static void
-visit_condexpr_for (ref)
-     tree_ref ref;
+visit_cond_stmt (stmt)
+     tree stmt;
 {
-  edge curredge;
+  edge e;
   value val;
-  basic_block block = ref_bb (ref);
-  tree expr = ref_expr (ref);
-
-  val = evaluate_expr (expr);
+  basic_block block;
 
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {
-      tree t = ref_stmt (ref);
-      STRIP_WFL (t);
-      STRIP_NOPS (t);
-      fprintf (dump_file, "Predicate is for a control statement: %s\n",
-	       tree_code_name[TREE_CODE (t)]);
-      dump_lattice_value (dump_file, "value: ", val);
-      fprintf (dump_file, "\n");
-    }
+#if defined ENABLE_CHECKING
+  if (!is_ctrl_stmt (stmt))
+    abort ();
+#endif
 
-  /* Mark successor blocks on executable edges as executable (if they
-     have not already been marked).   */
-  for (curredge = block->succ; curredge; curredge = curredge->succ_next)
-    {
-      /* If this is an edge for TRUE values but the predicate is false,
-	 then skip it.  */
-      if ((curredge->flags & EDGE_TRUE_VALUE)
-	  && simple_cst_equal (val.const_value, integer_zero_node) == 1)
-	continue;
+  block = bb_for_stmt (stmt);
+  val = evaluate_stmt (stmt);
 
-      /* Similarly for FALSE edges.  */
-      if ((curredge->flags & EDGE_FALSE_VALUE)
-	  && simple_cst_equal (val.const_value, integer_one_node) == 1)
-	continue;
+  /* If the predicate is undefined, do nothing.  */
+  if (val.lattice_val == UNDEFINED)
+    return;
 
-      add_control_edge (curredge);
-    }
+  /* Find which edge out of the conditional block will be taken and add it
+     to the worklist.  If no single edge can be determined statically, add
+     all outgoing edges from BLOCK.  */
+  e = find_taken_edge (block, val.const_value);
+  if (e)
+    add_control_edge (e);
+  else
+    add_outgoing_control_edges (block);
 }
 
 
@@ -627,38 +585,28 @@ add_control_edge (e)
 }
 
 
-/* Evaluate the expression EXPR.  */
+/* Evaluate statement STMT.  */
 
 static value
-evaluate_expr (expr)
-     tree expr;
+evaluate_stmt (stmt)
+     tree stmt;
 {
   value val;
-  tree simplified;
-
-#if defined ENABLE_CHECKING
-  /* FIXME: This test is lame.  All expressions should be in GIMPLE form.  */
-  if (TREE_NOT_GIMPLE (expr))
-    abort ();
-#endif
+  tree simplified, copy;
 
   val.lattice_val = VARYING;
   val.const_value = NULL_TREE;
-  simplified = NULL_TREE;
 
-  /* Replace all V_USE references in the expression with their immediate
-     reaching definition.  */
-  replace_uses_in (expr);
-
-  /* Fold the expression.  */
-  simplified = ccp_fold (deep_copy_node (expr));
-
-  STRIP_WFL (simplified);
-  STRIP_NOPS (simplified);
-  if (TREE_CODE (simplified) == INIT_EXPR
-      || TREE_CODE (simplified) == MODIFY_EXPR)
-    simplified = TREE_OPERAND (simplified, 1);
+  /* Evaluate a copy of the original statement.  */
+  STRIP_WFL (stmt);
+  STRIP_NOPS (stmt);
+  copy = stmt;
+  walk_tree (&copy, copy_tree_r, NULL, NULL);
+  if (replace_uses_in (copy))
+    fold_stmt (copy);
 
+  /* Extract the folded value from the statement.  */
+  simplified = get_rhs (copy);
   if (simplified && really_constant_p (simplified))
     {
       val.lattice_val = CONSTANT;
@@ -668,8 +616,8 @@ evaluate_expr (expr)
   /* Debugging dumps.  */
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      fprintf (dump_file, "Expression evaluates to ");
-      print_generic_expr (dump_file, expr, 0);
+      fprintf (dump_file, "Statement evaluates to ");
+      print_generic_stmt (dump_file, copy, TDF_SLIM);
       fprintf (dump_file, " which is ");
       if (val.lattice_val == CONSTANT)
 	{
@@ -684,7 +632,6 @@ evaluate_expr (expr)
       fprintf (dump_file, "\n");
     }
 
-  restore_expr (expr);
 
   return val;
 }
@@ -822,6 +769,14 @@ initialize ()
 		  values[id].const_value = DECL_INITIAL (var);
 		}
 	    }
+
+	  /* Special definitions (clobbering, partial or may-def) are all
+	     considered VARYING.  */
+	  else if (!is_pure_def (r))
+	    {
+	      values[id].lattice_val = VARYING;
+	      values[id].const_value = NULL_TREE;
+	    }
 	}
     }
 
@@ -929,14 +884,15 @@ set_lattice_value (def, val)
 }
 
 
-/* Replace USE reference in the expression EXPR with their immediate reaching
-   definition.  */
+/* Replace USE references in statement STMT with their immediate reaching
+   definition.  Return true if at least one reference was replaced.  */
 
-static void
-replace_uses_in (expr)
-     tree expr;
+static bool
+replace_uses_in (stmt)
+     tree stmt;
 {
-  ref_list refs = tree_refs (expr);
+  bool replaced = false;
+  ref_list refs = tree_refs (stmt);
   ref_list_iterator i;
 
   for (i = rli_start (refs); !rli_after_end (i); rli_step (&i))
@@ -949,8 +905,8 @@ replace_uses_in (expr)
       if (!is_pure_use (use))
 	continue;
 
-      /* The lattice value of a USE reference is the value of its
-	 immediately reaching definition.  */
+      /* The lattice value of a USE reference is the value of its immediately
+	 reaching definition.  */
       rdef = imm_reaching_def (use);
 
       /* We are only interested in killing definitions.  If we are reached
@@ -962,74 +918,78 @@ replace_uses_in (expr)
       rdef_id = ref_id (rdef);
       if (values[rdef_id].lattice_val == CONSTANT)
 	{
-#if defined ENABLE_CHECKING
-	  if (values[rdef_id].const_value == NULL_TREE)
-	    abort ();
-#endif
-	  /* The reference is a constant, substitute it into the
-	     expression.  */
-	  replace_ref_operand_with (use, values[rdef_id].const_value);
-	}
-      else
-	{
-	  /* The reference is not a constant, restore its original value.  */
-	  restore_ref_operand (use);
+	  replace_ref_in (stmt, use, values[rdef_id].const_value);
+	  replaced = true;
 	}
     }
+
+  return replaced;
 }
 
 
-/* Restore expression EXPR to its original form.  */
+/* Fold statement STMT.  */
 
 static void
-restore_expr (expr)
-     tree expr;
+fold_stmt (stmt)
+     tree stmt;
 {
-  ref_list refs = tree_refs (expr);
-  ref_list_iterator i;
+  tree rhs, result;
 
-  for (i = rli_start (refs); !rli_after_end (i); rli_step (&i))
+  STRIP_WFL (stmt);
+  STRIP_NOPS (stmt);
+  rhs = get_rhs (stmt);
+  if (rhs)
     {
-      /* Only restore pure V_USE references (those are the only types
-	 of references changed by replace_uses_in.  */
-      if (is_pure_use (rli_ref (i)))
-	restore_ref_operand (rli_ref (i));
+      result = fold (rhs);
+      set_rhs (stmt, result);
     }
 }
 
 
-/* Fold EXPR.  If EXPR is an assignment, fold its RHS and return a new
-   assignment with the folded RHS (fold does not handle assignment
-   expressions).  */
+/* Get the main expression from statement STMT.  */
 
 static tree
-ccp_fold (expr)
-     tree expr;
+get_rhs (stmt)
+     tree stmt;
 {
-  tree result, to_fold, w_expr;
+  enum tree_code code = TREE_CODE (stmt);
 
-  /* If the expression is an assignment, get its RHS.  */
-  w_expr = expr;
-  STRIP_WFL (w_expr);
-  STRIP_NOPS (w_expr);
-  if (TREE_CODE (w_expr) == MODIFY_EXPR
-      || TREE_CODE (w_expr) == INIT_EXPR)
-    to_fold = TREE_OPERAND (w_expr, 1);
+  if (code == MODIFY_EXPR || code == INIT_EXPR)
+    return TREE_OPERAND (stmt, 1);
+  if (code == COND_EXPR)
+    return COND_EXPR_COND (stmt);
+  else if (code == SWITCH_EXPR)
+    return SWITCH_COND (stmt);
+  else if (code == RETURN_EXPR)
+    return TREE_OPERAND (stmt, 0);
+  else if (code == GOTO_EXPR)
+    return GOTO_DESTINATION (stmt);
+  else if (code == LABEL_EXPR)
+    return LABEL_EXPR_LABEL (stmt);
   else
-    to_fold = expr;
+    return stmt;
+}
 
-  result = fold (to_fold);
 
-  /* If we folded the RHS of the original expression, store the folded
-     expression there and return the original expression (which will have
-     the new folded RHS).  */
-  if (TREE_CODE (w_expr) == MODIFY_EXPR
-      || TREE_CODE (w_expr) == INIT_EXPR)
-    {
-      TREE_OPERAND (w_expr, 1) = result;
-      return expr;
-    }
-  else
-    /* Otherwise, return the folded expression.  */
-    return result;
+/* Set the main expression of STMT to EXPR.  */
+
+static void
+set_rhs (stmt, expr)
+     tree stmt;
+     tree expr;
+{
+  enum tree_code code = TREE_CODE (stmt);
+
+  if (code == MODIFY_EXPR || code == INIT_EXPR)
+    TREE_OPERAND (stmt, 1) = expr;
+  if (code == COND_EXPR)
+    COND_EXPR_COND (stmt) = expr;
+  else if (code == SWITCH_EXPR)
+    SWITCH_COND (stmt) = expr;
+  else if (code == RETURN_EXPR)
+    TREE_OPERAND (stmt, 0) = expr;
+  else if (code == GOTO_EXPR)
+    GOTO_DESTINATION (stmt) = expr;
+  else if (code == LABEL_EXPR)
+    LABEL_EXPR_LABEL (stmt) = expr;
 }
Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-pre.c,v
retrieving revision 1.1.4.32
diff -d -u -p -r1.1.4.32 tree-ssa-pre.c
--- tree-ssa-pre.c	6 Nov 2002 22:22:34 -0000	1.1.4.32
+++ tree-ssa-pre.c	7 Nov 2002 04:37:48 -0000
@@ -772,27 +772,21 @@ insert_occ_in_preorder_dt_order_1 (ei, f
 	{
 	  tree *killexpr  = VARRAY_GENERIC_PTR (ei->kills, i);
 	  
-	  newref = create_ref (*killexpr,
-			       E_KILL, 0, block, killexpr,
-			       killexpr, NULL, true);
+	  newref = create_ref (*killexpr, E_KILL, 0, block, killexpr, 1);
 	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
 	  fibheap_insert (fh, preorder_count++, newref);
 	}
       else if (VARRAY_GENERIC_PTR (ei->lefts, i) != NULL)
 	{
 	  tree *leftexpr = VARRAY_GENERIC_PTR (ei->lefts, i);
-	  newref = create_ref (*leftexpr, 
-			       E_LEFT, 0, block, leftexpr,
-			       leftexpr, NULL, true);
+	  newref = create_ref (*leftexpr, E_LEFT, 0, block, leftexpr, 1);
 	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
 	  fibheap_insert (fh, preorder_count++, newref);
 	}
       else
 	{
 	  tree *occurexpr = VARRAY_GENERIC_PTR (ei->occurs, i);
-	  newref = create_ref (*occurexpr,
-				  E_USE, 0, block, occurexpr, 
-				  occurexpr, NULL, true);
+	  newref = create_ref (*occurexpr, E_USE, 0, block, occurexpr, 1);
 	  VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
 	  set_expruse_def (newref, NULL);
 	  set_exprref_class (newref, 0);
@@ -812,8 +806,7 @@ insert_occ_in_preorder_dt_order_1 (ei, f
         {
           if (phi_at_block (ei, succ->dest) != NULL)
             {
-              tree_ref newref = create_ref (NULL, E_USE, 0, block, 0, 
-					    0, 0, true);
+              tree_ref newref = create_ref (NULL, E_USE, 0, block, 0, 1);
               tree_ref phi = phi_at_block (ei, succ->dest);
 	      VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
               set_expruse_def (newref, NULL);
@@ -837,8 +830,7 @@ insert_occ_in_preorder_dt_order_1 (ei, f
 	  if (preorder_count != 0)
 	    {
 	      tree_ref newref;
-	      newref = create_ref (NULL, E_EXIT, 0, block, 
-				   NULL, NULL, NULL, true);
+	      newref = create_ref (NULL, E_EXIT, 0, block, NULL, 1);
 	      VARRAY_PUSH_GENERIC_PTR (ei->erefs, newref);
 	      fibheap_insert (fh, preorder_count++, newref);
 	    }
@@ -1564,10 +1556,7 @@ temp_fix_refs (lookin, lookfor, replacew
     {
       tree_ref ref = rli_ref (rli);
       if (ref_stmt (ref) == lookfor)
-	{
-	  ref->common.stmt_p = replacewith;
-	  ref->common.expr_p = replacewith;
-	}
+	ref->common.stmt_p = replacewith;
     }
 }
 
@@ -1820,10 +1809,8 @@ done:
                     expruse_def (X) = new occurrence. 
 		  */		  
 
-		  set_expruse_def (X,create_ref (expr, E_USE, 0,
-						 ref_bb (X), newexprplace,
-						 newexprplace, newexprplace, 
-						 true));
+		  set_expruse_def (X,create_ref (expr, E_USE, 0, ref_bb (X),
+			                         newexprplace, 1));
 		  set_bb_for_stmt (*newexprplace, ref_bb (X));
 		  
 		  VARRAY_PUSH_GENERIC_PTR (ei->erefs, expruse_def (X));
@@ -1920,9 +1907,7 @@ expr_phi_insertion (dfs, ei)
 
   EXECUTE_IF_SET_IN_SBITMAP(dfphis, 0, i, 
   {
-    tree_ref ref = create_ref (ei->expr, E_PHI, 0,
-                                BASIC_BLOCK (i), 
-                                NULL, NULL, NULL, true);
+    tree_ref ref = create_ref (ei->expr, E_PHI, 0, BASIC_BLOCK (i), NULL, 1);
     VARRAY_PUSH_GENERIC_PTR (ei->erefs, ref);
     set_exprref_processed (ref, false);
     set_exprref_processed2 (ref, false);
@@ -2730,7 +2715,6 @@ code_motion (ei, temp)
 
 	      
 	      use->common.stmt_p = &TREE_OPERAND (newstmt, 1);
-	      use->common.expr_p = &TREE_OPERAND (newstmt, 1);
 
 	      /* REMOVE AFTER DFA UPDATE */
 	      temp_fix_refs (use_stmt, newstmt, &TREE_OPERAND (newstmt, 1));
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.28
diff -d -u -p -r1.1.4.28 tree-ssa.c
--- tree-ssa.c	5 Nov 2002 23:50:39 -0000	1.1.4.28
+++ tree-ssa.c	7 Nov 2002 04:37:48 -0000
@@ -808,7 +808,7 @@ add_phi_node (bb, var)
 	 first executable statement.  This is for debugging convenience.
 	 This way, the PHI node will have line number information.  */
       stmt_p = !bb_empty_p (bb) ? bb->head_tree_p : NULL;
-      phi = create_ref (var, V_PHI, 0, bb, stmt_p, NULL, NULL, false);
+      phi = create_ref (var, V_PHI, 0, bb, stmt_p, 0);
       add_ref_to_list_begin (bb_refs (bb), phi);
 
       VARRAY_TREE (added, bb->index) = var;
@@ -951,7 +951,7 @@ create_default_def (var)
     mod = TRM_DEFAULT;
 
   /* Create a default definition and set it to be CURRDEF(var).  */
-  def = create_ref (var, V_DEF, mod, decl_bb, NULL, NULL, NULL, false);
+  def = create_ref (var, V_DEF, mod, decl_bb, NULL, 0);
   add_ref_to_list_begin (bb_refs (decl_bb), def);
   set_currdef_for (var, def);
 


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