[PATCH][tuples] Tuplify SCCVN

Richard Guenther rguenther@suse.de
Fri Jun 27 17:25:00 GMT 2008


On Fri, 27 Jun 2008, Diego Novillo wrote:

> On Tue, Jun 24, 2008 at 10:32, Richard Guenther <rguenther@suse.de> wrote:
>
>> Ok for tuples?  (I appreciate a review as I'm only getting familiar
>> with the new API)
>
> Yes.  The GIMPLE bits look fine.  Thanks for the conversion.

This is what I committed (it needed changes with your gimple_subcode
reorg).  I'm somewhat stuck with FRE and hope Danny gets along
committing his PRE/FRE rewrite on the trunk soon - that should
really help.

Richard.

2008-06-24  Richard Guenther  <rguenther@suse.de>

 	* tree-ssa-sccvn.c (vn_get_expr_for): New function.
 	(vuses_to_vec): Tuplify.
 	(copy_vuses_from_stmt): Likewise.
 	(vdefs_to_vec): Likewise.
 	(copy_vdefs_from_stmt): Likewise.
 	(shared_vuses_from_stmt): Likewise.
 	(copy_reference_ops_from_call): New function split out from
 	copy_reference_ops_from_ref.
 	(create_reference_ops_from_call): New function.
 	(shared_reference_ops_from_call): Likewise.
 	(get_def_ref_stmt_vuses): Tuplify.
 	(vn_reference_lookup): Likewise.
 	(vn_nary_op_lookup_stmt): New function.
 	(vn_nary_op_insert_stmt): Likewise.
 	(vn_phi_lookup): Tuplify.
 	(vn_phi_insert): Likewise.
 	(defs_to_varying): Likewise.
 	(visit_unary_op): Likewise.
 	(visit_binary_op): Likewise.
 	(visit_reference_op_call): New function.
 	(visit_reference_op_load): Tuplify.
 	(visit_reference_op_store): Likewise.
 	(visit_phi): Likewise.
 	(stmt_has_constants): New function.
 	(simplify_binary_expression): Tuplify.
 	(simplify_unary_expression): Likewise.
 	(try_to_simplify): Likewise.
 	(visit_use): Likewise.
 	(compare_ops): Likewise.
 	(DFS): Likewise.
 	(run_scc_vn): Likewise.
 	* tree-ssa-sccvn.h (shared_vuses_from_stmt): Adjust prototype.
 	(copy_vuses_from_stmt): Likewise.
 	(vn_get_expr_for): Declare.
 	(vn_nary_op_lookup_stmt): Likewise.
 	(vn_nary_op_insert_stmt): Likewise.
 	* tree-dfa.c (get_single_def_stmt): Tuplify.
 	(get_single_def_stmt_from_phi): Likewise.
 	(get_single_def_stmt_with_phi): Likewise.
 	* tree-ssa-pre.c (do_SCCVN_insertion): Use vn_get_expr_for.
 	(eliminate): Likewise.
 	(execute_pre): Enable SCCVN.
 	(gate_fre): Enable.
 	* tree-flow.h (get_single_def_stmt): Adjust prototype.
 	(get_single_def_stmt_from_phi): Likewise.
 	(get_single_def_stmt_with_phi): Likewise.
 	(vn_lookup_or_add_with_stmt): Likewise.
 	(vn_lookup_with_stmt): Likewise.
 	* gimple.c (gimple_fold): Fix.
 	* tree-vn.c (vn_add): Disable call to add_to_value.
 	(vn_add_with_vuses): Likewise.
 	(vn_lookup_with_stmt): Tuplify.
 	(vn_lookup_or_add_with_stmt): Likewise.

Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig	2008-06-25 17:43:11.000000000 +0200
--- gcc/tree-ssa-sccvn.c	2008-06-26 12:07:10.000000000 +0200
*************** along with GCC; see the file COPYING3.
*** 46,53 ****
   #include "tree-ssa-propagate.h"
   #include "tree-ssa-sccvn.h"

- /* FIXME tuples.  */
- #if 0
   /* This algorithm is based on the SCC algorithm presented by Keith
      Cooper and L. Taylor Simpson in "SCC-Based Value numbering"
      (http://citeseer.ist.psu.edu/41805.html).  In
--- 46,51 ----
*************** VN_INFO_GET (tree name)
*** 274,279 ****
--- 272,326 ----
   }


+ /* Get the representative expression for the SSA_NAME NAME.  Returns
+    the representative SSA_NAME if there is no expression associated with it.  */
+ 
+ tree
+ vn_get_expr_for (tree name)
+ {
+   vn_ssa_aux_t vn = VN_INFO (name);
+   gimple def_stmt;
+   tree expr;
+ 
+   if (vn->valnum == VN_TOP)
+     return name;
+ 
+   /* If the value-number is a constant it is the representative
+      expression.  */
+   if (TREE_CODE (vn->valnum) != SSA_NAME)
+     return vn->valnum;
+ 
+   /* Get to the information of the value of this SSA_NAME.  */
+   vn = VN_INFO (vn->valnum);
+ 
+   /* If the value-number is a constant it is the representative
+      expression.  */
+   if (TREE_CODE (vn->valnum) != SSA_NAME)
+     return vn->valnum;
+ 
+   /* Else if we have an expression, return it.  */
+   if (vn->expr != NULL_TREE)
+     return vn->expr;
+ 
+   /* Otherwise use the defining statement to build the expression.  */
+   def_stmt = SSA_NAME_DEF_STMT (vn->valnum);
+ 
+   /* If the value number is a default-definition use it directly.  */
+   if (gimple_nop_p (def_stmt))
+     return vn->valnum;
+ 
+   /* ???  This will return NULL_TREE if the stmt cannot be simplified.  */
+   expr = gimple_fold (def_stmt);
+   if (!expr)
+     return vn->valnum;
+ 
+   /* Cache the expression.  */
+   vn->expr = expr;
+ 
+   return expr;
+ }
+ 
+
   /* Free a phi operation structure VP.  */

   static void
*************** vn_reference_eq (const void *p1, const v
*** 391,397 ****
   /* Place the vuses from STMT into *result */

   static inline void
! vuses_to_vec (tree stmt, VEC (tree, gc) **result)
   {
     ssa_op_iter iter;
     tree vuse;
--- 438,444 ----
   /* Place the vuses from STMT into *result */

   static inline void
! vuses_to_vec (gimple stmt, VEC (tree, gc) **result)
   {
     ssa_op_iter iter;
     tree vuse;
*************** vuses_to_vec (tree stmt, VEC (tree, gc)
*** 411,417 ****
      the vector.  */

   VEC (tree, gc) *
! copy_vuses_from_stmt (tree stmt)
   {
     VEC (tree, gc) *vuses = NULL;

--- 458,464 ----
      the vector.  */

   VEC (tree, gc) *
! copy_vuses_from_stmt (gimple stmt)
   {
     VEC (tree, gc) *vuses = NULL;

*************** copy_vuses_from_stmt (tree stmt)
*** 423,429 ****
   /* Place the vdefs from STMT into *result */

   static inline void
! vdefs_to_vec (tree stmt, VEC (tree, gc) **result)
   {
     ssa_op_iter iter;
     tree vdef;
--- 470,476 ----
   /* Place the vdefs from STMT into *result */

   static inline void
! vdefs_to_vec (gimple stmt, VEC (tree, gc) **result)
   {
     ssa_op_iter iter;
     tree vdef;
*************** vdefs_to_vec (tree stmt, VEC (tree, gc)
*** 441,447 ****
      the vector.  */

   static VEC (tree, gc) *
! copy_vdefs_from_stmt (tree stmt)
   {
     VEC (tree, gc) *vdefs = NULL;

--- 488,494 ----
      the vector.  */

   static VEC (tree, gc) *
! copy_vdefs_from_stmt (gimple stmt)
   {
     VEC (tree, gc) *vdefs = NULL;

*************** static VEC (tree, gc) *shared_lookup_vop
*** 458,464 ****
      variable.  */

   VEC (tree, gc) *
! shared_vuses_from_stmt (tree stmt)
   {
     VEC_truncate (tree, shared_lookup_vops, 0);
     vuses_to_vec (stmt, &shared_lookup_vops);
--- 505,511 ----
      variable.  */

   VEC (tree, gc) *
! shared_vuses_from_stmt (gimple stmt)
   {
     VEC_truncate (tree, shared_lookup_vops, 0);
     vuses_to_vec (stmt, &shared_lookup_vops);
*************** shared_vuses_from_stmt (tree stmt)
*** 466,511 ****
     return shared_lookup_vops;
   }

! /* Copy the operations present in load/store/call REF into RESULT, a vector of
      vn_reference_op_s's.  */

   static void
   copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
   {
-   /* Calls are different from all other reference operations.  */
-   if (TREE_CODE (ref) == CALL_EXPR)
-     {
-       vn_reference_op_s temp;
-       tree callfn;
-       call_expr_arg_iterator iter;
-       tree callarg;
- 
-       /* Copy the call_expr opcode, type, function being called, and
- 	 arguments.  */
-       memset (&temp, 0, sizeof (temp));
-       temp.type = TREE_TYPE (ref);
-       temp.opcode = CALL_EXPR;
-       VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
- 
-       callfn = get_callee_fndecl (ref);
-       if (!callfn)
- 	callfn = CALL_EXPR_FN (ref);
-       temp.type = TREE_TYPE (callfn);
-       temp.opcode = TREE_CODE (callfn);
-       temp.op0 = callfn;
-       VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
- 
-       FOR_EACH_CALL_EXPR_ARG (callarg, iter, ref)
- 	{
- 	  memset (&temp, 0, sizeof (temp));
- 	  temp.type = TREE_TYPE (callarg);
- 	  temp.opcode = TREE_CODE (callarg);
- 	  temp.op0 = callarg;
- 	  VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
- 	}
-       return;
-     }
-
     if (TREE_CODE (ref) == TARGET_MEM_REF)
       {
         vn_reference_op_s temp;
--- 513,524 ----
     return shared_lookup_vops;
   }

! /* Copy the operations present in load/store REF into RESULT, a vector of
      vn_reference_op_s's.  */

   static void
   copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
   {
     if (TREE_CODE (ref) == TARGET_MEM_REF)
       {
         vn_reference_op_s temp;
*************** copy_reference_ops_from_ref (tree ref, V
*** 612,617 ****
--- 625,666 ----
       }
   }

+ /* Copy the operations present in load/store/call REF into RESULT, a vector of
+    vn_reference_op_s's.  */
+ 
+ static void
+ copy_reference_ops_from_call (gimple call,
+ 			      VEC(vn_reference_op_s, heap) **result)
+ {
+   vn_reference_op_s temp;
+   tree callfn;
+   unsigned i;
+ 
+   /* Copy the call_expr opcode, type, function being called, and
+      arguments.  */
+   memset (&temp, 0, sizeof (temp));
+   temp.type = gimple_call_return_type (call);
+   temp.opcode = CALL_EXPR;
+   VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
+ 
+   callfn = gimple_call_fn (call);
+   temp.type = TREE_TYPE (callfn);
+   temp.opcode = TREE_CODE (callfn);
+   temp.op0 = callfn;
+   VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
+ 
+   for (i = 0; i < gimple_call_num_args (call); ++i)
+     {
+       tree callarg = gimple_call_arg (call, i);
+       memset (&temp, 0, sizeof (temp));
+       temp.type = TREE_TYPE (callarg);
+       temp.opcode = TREE_CODE (callarg);
+       temp.op0 = callarg;
+       VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
+     }
+   return;
+ }
+
   /* Create a vector of vn_reference_op_s structures from REF, a
      REFERENCE_CLASS_P tree.  The vector is not shared. */

*************** create_reference_ops_from_ref (tree ref)
*** 624,629 ****
--- 673,690 ----
     return result;
   }

+ /* Create a vector of vn_reference_op_s structures from CALL, a
+    call statement.  The vector is not shared.  */
+ 
+ static VEC(vn_reference_op_s, heap) *
+ create_reference_ops_from_call (gimple call)
+ {
+   VEC (vn_reference_op_s, heap) *result = NULL;
+ 
+   copy_reference_ops_from_call (call, &result);
+   return result;
+ }
+
   static VEC(vn_reference_op_s, heap) *shared_lookup_references;

   /* Create a vector of vn_reference_op_s structures from REF, a
*************** shared_reference_ops_from_ref (tree ref)
*** 640,645 ****
--- 701,720 ----
     return shared_lookup_references;
   }

+ /* Create a vector of vn_reference_op_s structures from CALL, a
+    call statement.  The vector is shared among all callers of
+    this function.  */
+ 
+ static VEC(vn_reference_op_s, heap) *
+ shared_reference_ops_from_call (gimple call)
+ {
+   if (!call)
+     return NULL;
+   VEC_truncate (vn_reference_op_s, shared_lookup_references, 0);
+   copy_reference_ops_from_call (call, &shared_lookup_references);
+   return shared_lookup_references;
+ }
+

   /* Transform any SSA_NAME's in a vector of vn_reference_op_s
      structures into their value numbers.  This is done in-place, and
*************** valueize_vuses (VEC (tree, gc) *orig)
*** 692,707 ****
      Take into account only definitions that alias REF if following
      back-edges.  */

! static tree
   get_def_ref_stmt_vuses (tree ref, VEC (tree, gc) *vuses)
   {
!   tree def_stmt, vuse;
     unsigned int i;

     gcc_assert (VEC_length (tree, vuses) >= 1);

     def_stmt = SSA_NAME_DEF_STMT (VEC_index (tree, vuses, 0));
!   if (TREE_CODE (def_stmt) == PHI_NODE)
       {
         /* We can only handle lookups over PHI nodes for a single
   	 virtual operand.  */
--- 767,783 ----
      Take into account only definitions that alias REF if following
      back-edges.  */

! static gimple
   get_def_ref_stmt_vuses (tree ref, VEC (tree, gc) *vuses)
   {
!   gimple def_stmt;
!   tree vuse;
     unsigned int i;

     gcc_assert (VEC_length (tree, vuses) >= 1);

     def_stmt = SSA_NAME_DEF_STMT (VEC_index (tree, vuses, 0));
!   if (gimple_code (def_stmt) == GIMPLE_PHI)
       {
         /* We can only handle lookups over PHI nodes for a single
   	 virtual operand.  */
*************** get_def_ref_stmt_vuses (tree ref, VEC (t
*** 711,733 ****
   	  goto cont;
   	}
         else
! 	return NULL_TREE;
       }

     /* Verify each VUSE reaches the same defining stmt.  */
     for (i = 1; VEC_iterate (tree, vuses, i, vuse); ++i)
       {
!       tree tmp = SSA_NAME_DEF_STMT (vuse);
         if (tmp != def_stmt)
! 	return NULL_TREE;
       }

     /* Now see if the definition aliases ref, and loop until it does.  */
   cont:
     while (def_stmt
! 	 && TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT
! 	 && !get_call_expr_in (def_stmt)
! 	 && !refs_may_alias_p (ref, GIMPLE_STMT_OPERAND (def_stmt, 0)))
       def_stmt = get_single_def_stmt_with_phi (ref, def_stmt);

     return def_stmt;
--- 787,808 ----
   	  goto cont;
   	}
         else
! 	return NULL;
       }

     /* Verify each VUSE reaches the same defining stmt.  */
     for (i = 1; VEC_iterate (tree, vuses, i, vuse); ++i)
       {
!       gimple tmp = SSA_NAME_DEF_STMT (vuse);
         if (tmp != def_stmt)
! 	return NULL;
       }

     /* Now see if the definition aliases ref, and loop until it does.  */
   cont:
     while (def_stmt
! 	 && is_gimple_assign (def_stmt)
! 	 && !refs_may_alias_p (ref, gimple_get_lhs (def_stmt)))
       def_stmt = get_single_def_stmt_with_phi (ref, def_stmt);

     return def_stmt;
*************** tree
*** 763,769 ****
   vn_reference_lookup (tree op, VEC (tree, gc) *vuses, bool maywalk)
   {
     struct vn_reference_s vr1;
!   tree result, def_stmt;

     vr1.vuses = valueize_vuses (vuses);
     vr1.operands = valueize_refs (shared_reference_ops_from_ref (op));
--- 838,845 ----
   vn_reference_lookup (tree op, VEC (tree, gc) *vuses, bool maywalk)
   {
     struct vn_reference_s vr1;
!   tree result;
!   gimple def_stmt;

     vr1.vuses = valueize_vuses (vuses);
     vr1.operands = valueize_refs (shared_reference_ops_from_ref (op));
*************** vn_reference_lookup (tree op, VEC (tree,
*** 776,787 ****
         && maywalk
         && vr1.vuses
         && VEC_length (tree, vr1.vuses) >= 1
-       && !get_call_expr_in (op)
         && (def_stmt = get_def_ref_stmt_vuses (op, vr1.vuses))
!       && TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT
!       /* If there is a call involved, op must be assumed to
! 	 be clobbered.  */
!       && !get_call_expr_in (def_stmt))
       {
         /* We are now at an aliasing definition for the vuses we want to
   	 look up.  Re-do the lookup with the vdefs for this stmt.  */
--- 852,859 ----
         && maywalk
         && vr1.vuses
         && VEC_length (tree, vr1.vuses) >= 1
         && (def_stmt = get_def_ref_stmt_vuses (op, vr1.vuses))
!       && is_gimple_assign (def_stmt))
       {
         /* We are now at an aliasing definition for the vuses we want to
   	 look up.  Re-do the lookup with the vdefs for this stmt.  */
*************** vn_nary_op_lookup (tree op)
*** 912,917 ****
--- 984,1016 ----
     return ((vn_nary_op_t)*slot)->result;
   }

+ /* Lookup the rhs of STMT in the current hash table, and return the resulting
+    value number if it exists in the hash table.  Return NULL_TREE if
+    it does not exist in the hash table. */
+ 
+ tree
+ vn_nary_op_lookup_stmt (gimple stmt)
+ {
+   void **slot;
+   struct vn_nary_op_s vno1;
+   unsigned i;
+ 
+   vno1.opcode = gimple_assign_rhs_code (stmt);
+   vno1.length = gimple_num_ops (stmt) - 1;
+   vno1.type = TREE_TYPE (gimple_assign_lhs (stmt));
+   for (i = 0; i < vno1.length; ++i)
+     vno1.op[i] = gimple_op (stmt, i + 1);
+   vno1.hashcode = vn_nary_op_compute_hash (&vno1);
+   slot = htab_find_slot_with_hash (current_info->nary, &vno1, vno1.hashcode,
+ 				   NO_INSERT);
+   if (!slot && current_info == optimistic_info)
+     slot = htab_find_slot_with_hash (valid_info->nary, &vno1, vno1.hashcode,
+ 				     NO_INSERT);
+   if (!slot)
+     return NULL_TREE;
+   return ((vn_nary_op_t)*slot)->result;
+ }
+
   /* Insert OP into the current hash table with a value number of
      RESULT.  */

*************** vn_nary_op_insert (tree op, tree result)
*** 940,945 ****
--- 1039,1072 ----
     *slot = vno1;
   }

+ /* Insert the rhs of STMT into the current hash table with a value number of
+    RESULT.  */
+ 
+ void
+ vn_nary_op_insert_stmt (gimple stmt, tree result)
+ {
+   unsigned length = gimple_num_ops (stmt) - 1;
+   void **slot;
+   vn_nary_op_t vno1;
+   unsigned i;
+ 
+   vno1 = obstack_alloc (&current_info->nary_obstack,
+ 			(sizeof (struct vn_nary_op_s)
+ 			 - sizeof (tree) * (4 - length)));
+   vno1->opcode = gimple_assign_rhs_code (stmt);
+   vno1->length = length;
+   vno1->type = TREE_TYPE (gimple_assign_lhs (stmt));
+   for (i = 0; i < vno1->length; ++i)
+     vno1->op[i] = gimple_op (stmt, i + 1);
+   vno1->result = result;
+   vno1->hashcode = vn_nary_op_compute_hash (vno1);
+   slot = htab_find_slot_with_hash (current_info->nary, vno1, vno1->hashcode,
+ 				   INSERT);
+   gcc_assert (!*slot);
+ 
+   *slot = vno1;
+ }
+
   /* Compute a hashcode for PHI operation VP1 and return it.  */

   static inline hashval_t
*************** static VEC(tree, heap) *shared_lookup_ph
*** 1005,1020 ****
      it does not exist in the hash table. */

   static tree
! vn_phi_lookup (tree phi)
   {
     void **slot;
     struct vn_phi_s vp1;
!   int i;

     VEC_truncate (tree, shared_lookup_phiargs, 0);

     /* Canonicalize the SSA_NAME's to their value number.  */
!   for (i = 0; i < PHI_NUM_ARGS (phi); i++)
       {
         tree def = PHI_ARG_DEF (phi, i);
         def = TREE_CODE (def) == SSA_NAME ? SSA_VAL (def) : def;
--- 1132,1147 ----
      it does not exist in the hash table. */

   static tree
! vn_phi_lookup (gimple phi)
   {
     void **slot;
     struct vn_phi_s vp1;
!   unsigned i;

     VEC_truncate (tree, shared_lookup_phiargs, 0);

     /* Canonicalize the SSA_NAME's to their value number.  */
!   for (i = 0; i < gimple_phi_num_args (phi); i++)
       {
         tree def = PHI_ARG_DEF (phi, i);
         def = TREE_CODE (def) == SSA_NAME ? SSA_VAL (def) : def;
*************** vn_phi_lookup (tree phi)
*** 1037,1051 ****
      RESULT.  */

   static void
! vn_phi_insert (tree phi, tree result)
   {
     void **slot;
     vn_phi_t vp1 = (vn_phi_t) pool_alloc (current_info->phis_pool);
!   int i;
     VEC (tree, heap) *args = NULL;

     /* Canonicalize the SSA_NAME's to their value number.  */
!   for (i = 0; i < PHI_NUM_ARGS (phi); i++)
       {
         tree def = PHI_ARG_DEF (phi, i);
         def = TREE_CODE (def) == SSA_NAME ? SSA_VAL (def) : def;
--- 1164,1178 ----
      RESULT.  */

   static void
! vn_phi_insert (gimple phi, tree result)
   {
     void **slot;
     vn_phi_t vp1 = (vn_phi_t) pool_alloc (current_info->phis_pool);
!   unsigned i;
     VEC (tree, heap) *args = NULL;

     /* Canonicalize the SSA_NAME's to their value number.  */
!   for (i = 0; i < gimple_phi_num_args (phi); i++)
       {
         tree def = PHI_ARG_DEF (phi, i);
         def = TREE_CODE (def) == SSA_NAME ? SSA_VAL (def) : def;
*************** set_ssa_val_to (tree from, tree to)
*** 1125,1131 ****
      Return true if a value number changed. */

   static bool
! defs_to_varying (tree stmt)
   {
     bool changed = false;
     ssa_op_iter iter;
--- 1252,1258 ----
      Return true if a value number changed. */

   static bool
! defs_to_varying (gimple stmt)
   {
     bool changed = false;
     ssa_op_iter iter;
*************** defs_to_varying (tree stmt)
*** 1142,1148 ****
   }

   static bool expr_has_constants (tree expr);
! static tree try_to_simplify (tree stmt, tree rhs);

   /* Visit a copy between LHS and RHS, return true if the value number
      changed.  */
--- 1269,1275 ----
   }

   static bool expr_has_constants (tree expr);
! static tree try_to_simplify (gimple stmt);

   /* Visit a copy between LHS and RHS, return true if the value number
      changed.  */
*************** static tree try_to_simplify (tree stmt,
*** 1150,1156 ****
   static bool
   visit_copy (tree lhs, tree rhs)
   {
-
     /* Follow chains of copies to their destination.  */
     while (SSA_VAL (rhs) != rhs && TREE_CODE (SSA_VAL (rhs)) == SSA_NAME)
       rhs = SSA_VAL (rhs);
--- 1277,1282 ----
*************** visit_copy (tree lhs, tree rhs)
*** 1167,1176 ****
      value number of LHS has changed as a result.  */

   static bool
! visit_unary_op (tree lhs, tree op)
   {
     bool changed = false;
!   tree result = vn_nary_op_lookup (op);

     if (result)
       {
--- 1293,1302 ----
      value number of LHS has changed as a result.  */

   static bool
! visit_unary_op (tree lhs, gimple stmt)
   {
     bool changed = false;
!   tree result = vn_nary_op_lookup_stmt (stmt);

     if (result)
       {
*************** visit_unary_op (tree lhs, tree op)
*** 1179,1185 ****
     else
       {
         changed = set_ssa_val_to (lhs, lhs);
!       vn_nary_op_insert (op, lhs);
       }

     return changed;
--- 1305,1311 ----
     else
       {
         changed = set_ssa_val_to (lhs, lhs);
!       vn_nary_op_insert_stmt (stmt, lhs);
       }

     return changed;
*************** visit_unary_op (tree lhs, tree op)
*** 1189,1198 ****
      value number of LHS has changed as a result.  */

   static bool
! visit_binary_op (tree lhs, tree op)
   {
     bool changed = false;
!   tree result = vn_nary_op_lookup (op);

     if (result)
       {
--- 1315,1324 ----
      value number of LHS has changed as a result.  */

   static bool
! visit_binary_op (tree lhs, gimple stmt)
   {
     bool changed = false;
!   tree result = vn_nary_op_lookup_stmt (stmt);

     if (result)
       {
*************** visit_binary_op (tree lhs, tree op)
*** 1201,1207 ****
     else
       {
         changed = set_ssa_val_to (lhs, lhs);
!       vn_nary_op_insert (op, lhs);
       }

     return changed;
--- 1327,1374 ----
     else
       {
         changed = set_ssa_val_to (lhs, lhs);
!       vn_nary_op_insert_stmt (stmt, lhs);
!     }
! 
!   return changed;
! }
! 
! /* Visit a call STMT storing into LHS.  Return true if the value number
!    of the LHS has changed as a result.  */
! 
! static bool
! visit_reference_op_call (tree lhs, gimple stmt)
! {
!   bool changed = false;
!   struct vn_reference_s vr1;
!   tree result;
! 
!   vr1.vuses = valueize_vuses (shared_vuses_from_stmt (stmt));
!   vr1.operands = valueize_refs (shared_reference_ops_from_call (stmt));
!   vr1.hashcode = vn_reference_compute_hash (&vr1);
!   result = vn_reference_lookup_1 (&vr1);
!   if (result)
!     {
!       changed = set_ssa_val_to (lhs, result);
!       if (TREE_CODE (result) == SSA_NAME
! 	  && VN_INFO (result)->has_constants)
! 	VN_INFO (lhs)->has_constants = true;
!     }
!   else
!     {
!       void **slot;
!       vn_reference_t vr2;
!       changed = set_ssa_val_to (lhs, lhs);
!       vr2 = (vn_reference_t) pool_alloc (current_info->references_pool);
!       vr2->vuses = valueize_vuses (copy_vuses_from_stmt (stmt));
!       vr2->operands = valueize_refs (create_reference_ops_from_call (stmt));
!       vr2->hashcode = vr1.hashcode;
!       vr2->result = lhs;
!       slot = htab_find_slot_with_hash (current_info->references,
! 				       vr2, vr2->hashcode, INSERT);
!       if (*slot)
! 	free_reference (*slot);
!       *slot = vr2;
       }

     return changed;
*************** visit_binary_op (tree lhs, tree op)
*** 1211,1217 ****
      and return true if the value number of the LHS has changed as a result.  */

   static bool
! visit_reference_op_load (tree lhs, tree op, tree stmt)
   {
     bool changed = false;
     tree result = vn_reference_lookup (op, shared_vuses_from_stmt (stmt), true);
--- 1378,1384 ----
      and return true if the value number of the LHS has changed as a result.  */

   static bool
! visit_reference_op_load (tree lhs, tree op, gimple stmt)
   {
     bool changed = false;
     tree result = vn_reference_lookup (op, shared_vuses_from_stmt (stmt), true);
*************** visit_reference_op_load (tree lhs, tree
*** 1231,1237 ****
   	  && !is_gimple_min_invariant (val)
   	  && TREE_CODE (val) != SSA_NAME)
           {
! 	  tree tem = try_to_simplify (stmt, val);
   	  if (tem)
   	    val = tem;
   	}
--- 1398,1404 ----
   	  && !is_gimple_min_invariant (val)
   	  && TREE_CODE (val) != SSA_NAME)
           {
! 	  tree tem = try_to_simplify (stmt);
   	  if (tem)
   	    val = tem;
   	}
*************** visit_reference_op_load (tree lhs, tree
*** 1243,1249 ****
   	 a new SSA_NAME we create.  */
         if (!result && may_insert)
           {
! 	  result = make_ssa_name (SSA_NAME_VAR (lhs), NULL_TREE);
   	  /* Initialize value-number information properly.  */
   	  VN_INFO_GET (result)->valnum = result;
   	  VN_INFO (result)->expr = val;
--- 1410,1416 ----
   	 a new SSA_NAME we create.  */
         if (!result && may_insert)
           {
! 	  result = make_ssa_name (SSA_NAME_VAR (lhs), NULL);
   	  /* Initialize value-number information properly.  */
   	  VN_INFO_GET (result)->valnum = result;
   	  VN_INFO (result)->expr = val;
*************** visit_reference_op_load (tree lhs, tree
*** 1299,1305 ****
      and return true if the value number of the LHS has changed as a result.  */

   static bool
! visit_reference_op_store (tree lhs, tree op, tree stmt)
   {
     bool changed = false;
     tree result;
--- 1466,1472 ----
      and return true if the value number of the LHS has changed as a result.  */

   static bool
! visit_reference_op_store (tree lhs, tree op, gimple stmt)
   {
     bool changed = false;
     tree result;
*************** visit_reference_op_store (tree lhs, tree
*** 1397,1409 ****
      changed.  */

   static bool
! visit_phi (tree phi)
   {
     bool changed = false;
     tree result;
     tree sameval = VN_TOP;
     bool allsame = true;
!   int i;

     /* TODO: We could check for this in init_sccvn, and replace this
        with a gcc_assert.  */
--- 1564,1576 ----
      changed.  */

   static bool
! visit_phi (gimple phi)
   {
     bool changed = false;
     tree result;
     tree sameval = VN_TOP;
     bool allsame = true;
!   unsigned i;

     /* TODO: We could check for this in init_sccvn, and replace this
        with a gcc_assert.  */
*************** visit_phi (tree phi)
*** 1412,1418 ****

     /* See if all non-TOP arguments have the same value.  TOP is
        equivalent to everything, so we can ignore it.  */
!   for (i = 0; i < PHI_NUM_ARGS (phi); i++)
       {
         tree def = PHI_ARG_DEF (phi, i);

--- 1579,1585 ----

     /* See if all non-TOP arguments have the same value.  TOP is
        equivalent to everything, so we can ignore it.  */
!   for (i = 0; i < gimple_phi_num_args (phi); i++)
       {
         tree def = PHI_ARG_DEF (phi, i);

*************** expr_has_constants (tree expr)
*** 1499,1504 ****
--- 1666,1697 ----
     return false;
   }

+ /* Return true if STMT contains constants.  */
+ 
+ static bool
+ stmt_has_constants (gimple stmt)
+ {
+   if (gimple_code (stmt) != GIMPLE_ASSIGN)
+     return false;
+ 
+   switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
+     {
+     case GIMPLE_UNARY_RHS:
+       return is_gimple_min_invariant (gimple_assign_rhs1 (stmt));
+ 
+     case GIMPLE_BINARY_RHS:
+       return (is_gimple_min_invariant (gimple_assign_rhs1 (stmt))
+ 	      || is_gimple_min_invariant (gimple_assign_rhs2 (stmt)));
+     case GIMPLE_SINGLE_RHS:
+       /* Constants inside reference ops are rarely interesting, but
+ 	 it can take a lot of looking to find them.  */
+       return is_gimple_min_invariant (gimple_assign_rhs1 (stmt));
+     default:
+       gcc_unreachable ();
+     }
+   return false;
+ }
+
   /* Replace SSA_NAMES in expr with their value numbers, and return the
      result.
      This is performed in place. */
*************** valueize_expr (tree expr)
*** 1531,1541 ****
      simplified. */

   static tree
! simplify_binary_expression (tree stmt, tree rhs)
   {
     tree result = NULL_TREE;
!   tree op0 = TREE_OPERAND (rhs, 0);
!   tree op1 = TREE_OPERAND (rhs, 1);

     /* This will not catch every single case we could combine, but will
        catch those with constants.  The goal here is to simultaneously
--- 1724,1734 ----
      simplified. */

   static tree
! simplify_binary_expression (gimple stmt)
   {
     tree result = NULL_TREE;
!   tree op0 = gimple_assign_rhs1 (stmt);
!   tree op1 = gimple_assign_rhs2 (stmt);

     /* This will not catch every single case we could combine, but will
        catch those with constants.  The goal here is to simultaneously
*************** simplify_binary_expression (tree stmt, t
*** 1544,1550 ****
     if (TREE_CODE (op0) == SSA_NAME)
       {
         if (VN_INFO (op0)->has_constants)
! 	op0 = valueize_expr (VN_INFO (op0)->expr);
         else if (SSA_VAL (op0) != VN_TOP && SSA_VAL (op0) != op0)
   	op0 = SSA_VAL (op0);
       }
--- 1737,1743 ----
     if (TREE_CODE (op0) == SSA_NAME)
       {
         if (VN_INFO (op0)->has_constants)
! 	op0 = valueize_expr (vn_get_expr_for (op0));
         else if (SSA_VAL (op0) != VN_TOP && SSA_VAL (op0) != op0)
   	op0 = SSA_VAL (op0);
       }
*************** simplify_binary_expression (tree stmt, t
*** 1552,1570 ****
     if (TREE_CODE (op1) == SSA_NAME)
       {
         if (VN_INFO (op1)->has_constants)
! 	op1 = valueize_expr (VN_INFO (op1)->expr);
         else if (SSA_VAL (op1) != VN_TOP && SSA_VAL (op1) != op1)
   	op1 = SSA_VAL (op1);
       }

     /* Avoid folding if nothing changed.  */
!   if (op0 == TREE_OPERAND (rhs, 0)
!       && op1 == TREE_OPERAND (rhs, 1))
       return NULL_TREE;

     fold_defer_overflow_warnings ();

!   result = fold_binary (TREE_CODE (rhs), TREE_TYPE (rhs), op0, op1);

     fold_undefer_overflow_warnings (result && valid_gimple_expression_p (result),
   				  stmt, 0);
--- 1745,1764 ----
     if (TREE_CODE (op1) == SSA_NAME)
       {
         if (VN_INFO (op1)->has_constants)
! 	op1 = valueize_expr (vn_get_expr_for (op1));
         else if (SSA_VAL (op1) != VN_TOP && SSA_VAL (op1) != op1)
   	op1 = SSA_VAL (op1);
       }

     /* Avoid folding if nothing changed.  */
!   if (op0 == gimple_assign_rhs1 (stmt)
!       && op1 == gimple_assign_rhs2 (stmt))
       return NULL_TREE;

     fold_defer_overflow_warnings ();

!   result = fold_binary (gimple_assign_rhs_code (stmt),
! 			TREE_TYPE (gimple_get_lhs (stmt)), op0, op1);

     fold_undefer_overflow_warnings (result && valid_gimple_expression_p (result),
   				  stmt, 0);
*************** simplify_binary_expression (tree stmt, t
*** 1583,1606 ****
      simplified. */

   static tree
! simplify_unary_expression (tree rhs)
   {
     tree result = NULL_TREE;
!   tree op0 = TREE_OPERAND (rhs, 0);

     if (TREE_CODE (op0) != SSA_NAME)
       return NULL_TREE;

     if (VN_INFO (op0)->has_constants)
!     op0 = valueize_expr (VN_INFO (op0)->expr);
!   else if (CONVERT_EXPR_P (rhs)
! 	   || TREE_CODE (rhs) == REALPART_EXPR
! 	   || TREE_CODE (rhs) == IMAGPART_EXPR
! 	   || TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
       {
         /* We want to do tree-combining on conversion-like expressions.
            Make sure we feed only SSA_NAMEs or constants to fold though.  */
!       tree tem = valueize_expr (VN_INFO (op0)->expr);
         if (UNARY_CLASS_P (tem)
   	  || BINARY_CLASS_P (tem)
   	  || TREE_CODE (tem) == VIEW_CONVERT_EXPR
--- 1777,1800 ----
      simplified. */

   static tree
! simplify_unary_expression (gimple stmt)
   {
     tree result = NULL_TREE;
!   tree op0 = gimple_assign_rhs1 (stmt);

     if (TREE_CODE (op0) != SSA_NAME)
       return NULL_TREE;

     if (VN_INFO (op0)->has_constants)
!     op0 = valueize_expr (vn_get_expr_for (op0));
!   else if (gimple_assign_cast_p (stmt)
! 	   || gimple_assign_rhs_code (stmt) == REALPART_EXPR
! 	   || gimple_assign_rhs_code (stmt) == IMAGPART_EXPR
! 	   || gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR)
       {
         /* We want to do tree-combining on conversion-like expressions.
            Make sure we feed only SSA_NAMEs or constants to fold though.  */
!       tree tem = valueize_expr (vn_get_expr_for (op0));
         if (UNARY_CLASS_P (tem)
   	  || BINARY_CLASS_P (tem)
   	  || TREE_CODE (tem) == VIEW_CONVERT_EXPR
*************** simplify_unary_expression (tree rhs)
*** 1610,1619 ****
       }

     /* Avoid folding if nothing changed, but remember the expression.  */
!   if (op0 == TREE_OPERAND (rhs, 0))
!     return rhs;

!   result = fold_unary (TREE_CODE (rhs), TREE_TYPE (rhs), op0);
     if (result)
       {
         STRIP_USELESS_TYPE_CONVERSION (result);
--- 1804,1814 ----
       }

     /* Avoid folding if nothing changed, but remember the expression.  */
!   if (op0 == gimple_assign_rhs1 (stmt))
!     return NULL_TREE;

!   result = fold_unary (gimple_assign_rhs_code (stmt),
! 		       TREE_TYPE (gimple_get_lhs (stmt)), op0);
     if (result)
       {
         STRIP_USELESS_TYPE_CONVERSION (result);
*************** simplify_unary_expression (tree rhs)
*** 1621,1645 ****
           return result;
       }

!   return rhs;
   }

   /* Try to simplify RHS using equivalences and constant folding.  */

   static tree
! try_to_simplify (tree stmt, tree rhs)
   {
     tree tem;

     /* For stores we can end up simplifying a SSA_NAME rhs.  Just return
        in this case, there is no point in doing extra work.  */
!   if (TREE_CODE (rhs) == SSA_NAME)
!     return rhs;

!   switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
       {
       case tcc_declaration:
!       tem = get_symbol_constant_value (rhs);
         if (tem)
   	return tem;
         break;
--- 1816,1841 ----
           return result;
       }

!   return NULL_TREE;
   }

   /* Try to simplify RHS using equivalences and constant folding.  */

   static tree
! try_to_simplify (gimple stmt)
   {
     tree tem;

     /* For stores we can end up simplifying a SSA_NAME rhs.  Just return
        in this case, there is no point in doing extra work.  */
!   if (gimple_assign_copy_p (stmt)
!       && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
!     return NULL_TREE;

!   switch (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)))
       {
       case tcc_declaration:
!       tem = get_symbol_constant_value (gimple_assign_rhs1 (stmt));
         if (tem)
   	return tem;
         break;
*************** try_to_simplify (tree stmt, tree rhs)
*** 1647,1675 ****
       case tcc_reference:
         /* Do not do full-blown reference lookup here, but simplify
   	 reads from constant aggregates.  */
!       tem = fold_const_aggregate_ref (rhs);
         if (tem)
   	return tem;

         /* Fallthrough for some codes that can operate on registers.  */
!       if (!(TREE_CODE (rhs) == REALPART_EXPR
! 	    || TREE_CODE (rhs) == IMAGPART_EXPR
! 	    || TREE_CODE (rhs) == VIEW_CONVERT_EXPR))
   	break;
         /* We could do a little more with unary ops, if they expand
   	 into binary ops, but it's debatable whether it is worth it. */
       case tcc_unary:
!       return simplify_unary_expression (rhs);
         break;
       case tcc_comparison:
       case tcc_binary:
!       return simplify_binary_expression (stmt, rhs);
         break;
       default:
         break;
       }

!   return rhs;
   }

   /* Visit and value number USE, return true if the value number
--- 1843,1871 ----
       case tcc_reference:
         /* Do not do full-blown reference lookup here, but simplify
   	 reads from constant aggregates.  */
!       tem = fold_const_aggregate_ref (gimple_assign_rhs1 (stmt));
         if (tem)
   	return tem;

         /* Fallthrough for some codes that can operate on registers.  */
!       if (!(TREE_CODE (gimple_assign_rhs1 (stmt)) == REALPART_EXPR
! 	    || TREE_CODE (gimple_assign_rhs1 (stmt)) == IMAGPART_EXPR
! 	    || TREE_CODE (gimple_assign_rhs1 (stmt)) == VIEW_CONVERT_EXPR))
   	break;
         /* We could do a little more with unary ops, if they expand
   	 into binary ops, but it's debatable whether it is worth it. */
       case tcc_unary:
!       return simplify_unary_expression (stmt);
         break;
       case tcc_comparison:
       case tcc_binary:
!       return simplify_binary_expression (stmt);
         break;
       default:
         break;
       }

!   return NULL_TREE;
   }

   /* Visit and value number USE, return true if the value number
*************** static bool
*** 1679,1745 ****
   visit_use (tree use)
   {
     bool changed = false;
!   tree stmt = SSA_NAME_DEF_STMT (use);
!   stmt_ann_t ann;

     VN_INFO (use)->use_processed = true;

     gcc_assert (!SSA_NAME_IN_FREE_LIST (use));
     if (dump_file && (dump_flags & TDF_DETAILS)
!       && !IS_EMPTY_STMT (stmt))
       {
         fprintf (dump_file, "Value numbering ");
         print_generic_expr (dump_file, use, 0);
         fprintf (dump_file, " stmt = ");
!       print_generic_stmt (dump_file, stmt, 0);
       }

-   /* RETURN_EXPR may have an embedded MODIFY_STMT.  */
-   if (TREE_CODE (stmt) == RETURN_EXPR
-       && TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT)
-     stmt = TREE_OPERAND (stmt, 0);
- 
-   ann = stmt_ann (stmt);
-
     /* Handle uninitialized uses.  */
!   if (IS_EMPTY_STMT (stmt))
!     {
!       changed = set_ssa_val_to (use, use);
!     }
     else
       {
!       if (TREE_CODE (stmt) == PHI_NODE)
! 	{
! 	  changed = visit_phi (stmt);
! 	}
!       else if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT
! 	       || (ann && ann->has_volatile_ops)
! 	       || tree_could_throw_p (stmt))
! 	{
! 	  changed = defs_to_varying (stmt);
! 	}
!       else
   	{
! 	  tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
! 	  tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
   	  tree simplified;

- 	  STRIP_USELESS_TYPE_CONVERSION (rhs);
-
   	  /* Shortcut for copies. Simplifying copies is pointless,
   	     since we copy the expression and value they represent.  */
! 	  if (TREE_CODE (rhs) == SSA_NAME && TREE_CODE (lhs) == SSA_NAME)
   	    {
! 	      changed = visit_copy (lhs, rhs);
   	      goto done;
   	    }
! 	  simplified = try_to_simplify (stmt, rhs);
! 	  if (simplified && simplified != rhs)
   	    {
   	      if (dump_file && (dump_flags & TDF_DETAILS))
   		{
! 		  fprintf (dump_file, "RHS ");
! 		  print_generic_expr (dump_file, rhs, 0);
   		  fprintf (dump_file, " simplified to ");
   		  print_generic_expr (dump_file, simplified, 0);
   		  if (TREE_CODE (lhs) == SSA_NAME)
--- 1875,1928 ----
   visit_use (tree use)
   {
     bool changed = false;
!   gimple stmt = SSA_NAME_DEF_STMT (use);

     VN_INFO (use)->use_processed = true;

     gcc_assert (!SSA_NAME_IN_FREE_LIST (use));
     if (dump_file && (dump_flags & TDF_DETAILS)
!       && !SSA_NAME_IS_DEFAULT_DEF (use))
       {
         fprintf (dump_file, "Value numbering ");
         print_generic_expr (dump_file, use, 0);
         fprintf (dump_file, " stmt = ");
!       print_gimple_stmt (dump_file, stmt, 0, 0);
       }

     /* Handle uninitialized uses.  */
!   if (SSA_NAME_IS_DEFAULT_DEF (use))
!     changed = set_ssa_val_to (use, use);
     else
       {
!       if (gimple_code (stmt) == GIMPLE_PHI)
! 	changed = visit_phi (stmt);
!       else if ((gimple_code (stmt) != GIMPLE_ASSIGN
! 		&& (gimple_code (stmt) != GIMPLE_CALL
! 		    || gimple_call_lhs (stmt) == NULL_TREE))
! 	       || gimple_has_volatile_ops (stmt)
! 	       || stmt_could_throw_p (stmt))
! 	changed = defs_to_varying (stmt);
!       else if (gimple_code (stmt) == GIMPLE_ASSIGN)
   	{
! 	  tree lhs = gimple_assign_lhs (stmt);
   	  tree simplified;

   	  /* Shortcut for copies. Simplifying copies is pointless,
   	     since we copy the expression and value they represent.  */
! 	  if (gimple_assign_copy_p (stmt)
! 	      && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
! 	      && TREE_CODE (lhs) == SSA_NAME)
   	    {
! 	      changed = visit_copy (lhs, gimple_assign_rhs1 (stmt));
   	      goto done;
   	    }
! 	  simplified = try_to_simplify (stmt);
! 	  if (simplified)
   	    {
   	      if (dump_file && (dump_flags & TDF_DETAILS))
   		{
! 		  fprintf (dump_file, "RHS of ");
! 		  print_gimple_stmt (dump_file, stmt, 0, 0);
   		  fprintf (dump_file, " simplified to ");
   		  print_generic_expr (dump_file, simplified, 0);
   		  if (TREE_CODE (lhs) == SSA_NAME)
*************** visit_use (tree use)
*** 1753,1768 ****
   	     screw up phi congruence because constants are not
   	     uniquely associated with a single ssa name that can be
   	     looked up.  */
! 	  if (simplified && is_gimple_min_invariant (simplified)
! 	      && TREE_CODE (lhs) == SSA_NAME
! 	      && simplified != rhs)
   	    {
   	      VN_INFO (lhs)->expr = simplified;
   	      VN_INFO (lhs)->has_constants = true;
   	      changed = set_ssa_val_to (lhs, simplified);
   	      goto done;
   	    }
! 	  else if (simplified && TREE_CODE (simplified) == SSA_NAME
   		   && TREE_CODE (lhs) == SSA_NAME)
   	    {
   	      changed = visit_copy (lhs, simplified);
--- 1936,1952 ----
   	     screw up phi congruence because constants are not
   	     uniquely associated with a single ssa name that can be
   	     looked up.  */
! 	  if (simplified
! 	      && is_gimple_min_invariant (simplified)
! 	      && TREE_CODE (lhs) == SSA_NAME)
   	    {
   	      VN_INFO (lhs)->expr = simplified;
   	      VN_INFO (lhs)->has_constants = true;
   	      changed = set_ssa_val_to (lhs, simplified);
   	      goto done;
   	    }
! 	  else if (simplified
! 		   && TREE_CODE (simplified) == SSA_NAME
   		   && TREE_CODE (lhs) == SSA_NAME)
   	    {
   	      changed = visit_copy (lhs, simplified);
*************** visit_use (tree use)
*** 1777,1789 ****
   		     valuizing may change the IL stream.  */
   		  VN_INFO (lhs)->expr = unshare_expr (simplified);
   		}
- 	      rhs = simplified;
- 	    }
- 	  else if (expr_has_constants (rhs) && TREE_CODE (lhs) == SSA_NAME)
- 	    {
- 	      VN_INFO (lhs)->has_constants = true;
- 	      VN_INFO (lhs)->expr = unshare_expr (rhs);
   	    }
   	  else if (TREE_CODE (lhs) == SSA_NAME)
   	    {
   	      /* We reset expr and constantness here because we may
--- 1961,1970 ----
   		     valuizing may change the IL stream.  */
   		  VN_INFO (lhs)->expr = unshare_expr (simplified);
   		}
   	    }
+ 	  else if (stmt_has_constants (stmt)
+ 		   && TREE_CODE (lhs) == SSA_NAME)
+ 	    VN_INFO (lhs)->has_constants = true;
   	  else if (TREE_CODE (lhs) == SSA_NAME)
   	    {
   	      /* We reset expr and constantness here because we may
*************** visit_use (tree use)
*** 1792,1847 ****
   		 even if they were optimistically constant. */

   	      VN_INFO (lhs)->has_constants = false;
! 	      VN_INFO (lhs)->expr = lhs;
   	    }

   	  if (TREE_CODE (lhs) == SSA_NAME
   	      /* We can substitute SSA_NAMEs that are live over
   		 abnormal edges with their constant value.  */
! 	      && !is_gimple_min_invariant (rhs)
   	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
   	    changed = defs_to_varying (stmt);
   	  else if (REFERENCE_CLASS_P (lhs) || DECL_P (lhs))
   	    {
! 	      changed = visit_reference_op_store (lhs, rhs, stmt);
   	    }
   	  else if (TREE_CODE (lhs) == SSA_NAME)
   	    {
! 	      if (is_gimple_min_invariant (rhs))
   		{
   		  VN_INFO (lhs)->has_constants = true;
! 		  VN_INFO (lhs)->expr = rhs;
! 		  changed = set_ssa_val_to (lhs, rhs);
   		}
   	      else
   		{
! 		  switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
   		    {
! 		    case tcc_unary:
! 		      changed = visit_unary_op (lhs, rhs);
! 		      break;
! 		    case tcc_binary:
! 		      changed = visit_binary_op (lhs, rhs);
! 		      break;
! 		      /* If tcc_vl_expr ever encompasses more than
! 			 CALL_EXPR, this will need to be changed.  */
! 		    case tcc_vl_exp:
! 		      if (call_expr_flags (rhs)  & (ECF_PURE | ECF_CONST))
! 			changed = visit_reference_op_load (lhs, rhs, stmt);
! 		      else
! 			changed = defs_to_varying (stmt);
   		      break;
! 		    case tcc_declaration:
! 		    case tcc_reference:
! 		      changed = visit_reference_op_load (lhs, rhs, stmt);
   		      break;
! 		    case tcc_expression:
! 		      if (TREE_CODE (rhs) == ADDR_EXPR)
   			{
! 			  changed = visit_unary_op (lhs, rhs);
! 			  goto done;
   			}
! 		      /* Fallthrough.  */
   		    default:
   		      changed = defs_to_varying (stmt);
   		      break;
--- 1973,2033 ----
   		 even if they were optimistically constant. */

   	      VN_INFO (lhs)->has_constants = false;
! 	      VN_INFO (lhs)->expr = NULL_TREE;
   	    }

   	  if (TREE_CODE (lhs) == SSA_NAME
   	      /* We can substitute SSA_NAMEs that are live over
   		 abnormal edges with their constant value.  */
! 	      && !(gimple_assign_copy_p (stmt)
! 		   && is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
! 	      && !(simplified
! 		   && is_gimple_min_invariant (simplified))
   	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
   	    changed = defs_to_varying (stmt);
   	  else if (REFERENCE_CLASS_P (lhs) || DECL_P (lhs))
   	    {
! 	      changed = visit_reference_op_store (lhs, gimple_assign_rhs1 (stmt), stmt);
   	    }
   	  else if (TREE_CODE (lhs) == SSA_NAME)
   	    {
! 	      if ((gimple_assign_copy_p (stmt)
! 		   && is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
! 		  || (simplified
! 		      && is_gimple_min_invariant (simplified)))
   		{
   		  VN_INFO (lhs)->has_constants = true;
! 		  if (simplified)
! 		    changed = set_ssa_val_to (lhs, simplified);
! 		  else
! 		    changed = set_ssa_val_to (lhs, gimple_assign_rhs1 (stmt));
   		}
   	      else
   		{
! 		  switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
   		    {
! 		    case GIMPLE_UNARY_RHS:
! 		      changed = visit_unary_op (lhs, stmt);
   		      break;
! 		    case GIMPLE_BINARY_RHS:
! 		      changed = visit_binary_op (lhs, stmt);
   		      break;
! 		    case GIMPLE_SINGLE_RHS:
! 		      switch (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)))
   			{
! 			case tcc_declaration:
! 			case tcc_reference:
! 			  changed = visit_reference_op_load
! 			      (lhs, gimple_assign_rhs1 (stmt), stmt);
! 			  break;
! 			case tcc_expression:
! 			  if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
! 			    changed = visit_unary_op (lhs, stmt);
! 			  break;
! 			default:
! 			  changed = defs_to_varying (stmt);
   			}
! 		      break;
   		    default:
   		      changed = defs_to_varying (stmt);
   		      break;
*************** visit_use (tree use)
*** 1851,1856 ****
--- 2037,2075 ----
   	  else
   	    changed = defs_to_varying (stmt);
   	}
+       else if (is_gimple_call (stmt))
+ 	{
+ 	  tree lhs = gimple_call_lhs (stmt);
+ 
+ 	  /* ???  We could try to simplify calls.  */
+ 
+ 	  if (stmt_has_constants (stmt)
+ 	      && TREE_CODE (lhs) == SSA_NAME)
+ 	    VN_INFO (lhs)->has_constants = true;
+ 	  else if (TREE_CODE (lhs) == SSA_NAME)
+ 	    {
+ 	      /* We reset expr and constantness here because we may
+ 		 have been value numbering optimistically, and
+ 		 iterating. They may become non-constant in this case,
+ 		 even if they were optimistically constant. */
+ 	      VN_INFO (lhs)->has_constants = false;
+ 	      VN_INFO (lhs)->expr = NULL_TREE;
+ 	    }
+ 
+ 	  if (TREE_CODE (lhs) == SSA_NAME
+ 	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
+ 	    changed = defs_to_varying (stmt);
+ 	  /* ???  We should handle stores from calls.  */
+ 	  else if (TREE_CODE (lhs) == SSA_NAME)
+ 	    {
+ 	      if (gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST))
+ 		changed = visit_reference_op_call (lhs, stmt);
+ 	      else
+ 		changed = defs_to_varying (stmt);
+ 	    }
+ 	  else
+ 	    changed = defs_to_varying (stmt);
+ 	}
       }
    done:
     return changed;
*************** compare_ops (const void *pa, const void
*** 1863,1878 ****
   {
     const tree opa = *((const tree *)pa);
     const tree opb = *((const tree *)pb);
!   tree opstmta = SSA_NAME_DEF_STMT (opa);
!   tree opstmtb = SSA_NAME_DEF_STMT (opb);
     basic_block bba;
     basic_block bbb;

!   if (IS_EMPTY_STMT (opstmta) && IS_EMPTY_STMT (opstmtb))
       return 0;
!   else if (IS_EMPTY_STMT (opstmta))
       return -1;
!   else if (IS_EMPTY_STMT (opstmtb))
       return 1;

     bba = gimple_bb (opstmta);
--- 2082,2097 ----
   {
     const tree opa = *((const tree *)pa);
     const tree opb = *((const tree *)pb);
!   gimple opstmta = SSA_NAME_DEF_STMT (opa);
!   gimple opstmtb = SSA_NAME_DEF_STMT (opb);
     basic_block bba;
     basic_block bbb;

!   if (gimple_nop_p (opstmta) && gimple_nop_p (opstmtb))
       return 0;
!   else if (gimple_nop_p (opstmta))
       return -1;
!   else if (gimple_nop_p (opstmtb))
       return 1;

     bba = gimple_bb (opstmta);
*************** compare_ops (const void *pa, const void
*** 1887,1899 ****

     if (bba == bbb)
       {
!       if (TREE_CODE (opstmta) == PHI_NODE && TREE_CODE (opstmtb) == PHI_NODE)
   	return 0;
!       else if (TREE_CODE (opstmta) == PHI_NODE)
   	return -1;
!       else if (TREE_CODE (opstmtb) == PHI_NODE)
   	return 1;
!       return gimple_stmt_uid (opstmta) - gimple_stmt_uid (opstmtb);
       }
     return rpo_numbers[bba->index] - rpo_numbers[bbb->index];
   }
--- 2106,2119 ----

     if (bba == bbb)
       {
!       if (gimple_code (opstmta) == GIMPLE_PHI
! 	  && gimple_code (opstmtb) == GIMPLE_PHI)
   	return 0;
!       else if (gimple_code (opstmta) == GIMPLE_PHI)
   	return -1;
!       else if (gimple_code (opstmtb) == GIMPLE_PHI)
   	return 1;
!       return gimple_uid (opstmta) - gimple_uid (opstmtb);
       }
     return rpo_numbers[bba->index] - rpo_numbers[bbb->index];
   }
*************** DFS (tree name)
*** 2019,2025 ****
     VEC(ssa_op_iter, heap) *itervec = NULL;
     VEC(tree, heap) *namevec = NULL;
     use_operand_p usep = NULL;
!   tree defstmt, use;
     ssa_op_iter iter;

   start_over:
--- 2239,2246 ----
     VEC(ssa_op_iter, heap) *itervec = NULL;
     VEC(tree, heap) *namevec = NULL;
     use_operand_p usep = NULL;
!   gimple defstmt;
!   tree use;
     ssa_op_iter iter;

   start_over:
*************** start_over:
*** 2033,2042 ****
     defstmt = SSA_NAME_DEF_STMT (name);

     /* Recursively DFS on our operands, looking for SCC's.  */
!   if (!IS_EMPTY_STMT (defstmt))
       {
         /* Push a new iterator.  */
!       if (TREE_CODE (defstmt) == PHI_NODE)
   	usep = op_iter_init_phiuse (&iter, defstmt, SSA_OP_ALL_USES);
         else
   	usep = op_iter_init_use (&iter, defstmt, SSA_OP_ALL_USES);
--- 2254,2263 ----
     defstmt = SSA_NAME_DEF_STMT (name);

     /* Recursively DFS on our operands, looking for SCC's.  */
!   if (!gimple_nop_p (defstmt))
       {
         /* Push a new iterator.  */
!       if (gimple_code (defstmt) == GIMPLE_PHI)
   	usep = op_iter_init_phiuse (&iter, defstmt, SSA_OP_ALL_USES);
         else
   	usep = op_iter_init_use (&iter, defstmt, SSA_OP_ALL_USES);
*************** run_scc_vn (bool may_insert_arg)
*** 2286,2297 ****
   	  tree name = ssa_name (i);
   	  if (name && VN_INFO (name)->visited
   	      && (SSA_VAL (name) != name
! 		  || is_gimple_min_invariant (VN_INFO (name)->expr)))
   	    {
   	      print_generic_expr (dump_file, name, 0);
   	      fprintf (dump_file, " = ");
! 	      if (is_gimple_min_invariant (VN_INFO (name)->expr))
! 		print_generic_expr (dump_file, VN_INFO (name)->expr, 0);
   	      else
   		print_generic_expr (dump_file, SSA_VAL (name), 0);
   	      fprintf (dump_file, "\n");
--- 2507,2518 ----
   	  tree name = ssa_name (i);
   	  if (name && VN_INFO (name)->visited
   	      && (SSA_VAL (name) != name
! 		  || is_gimple_min_invariant (vn_get_expr_for (name))))
   	    {
   	      print_generic_expr (dump_file, name, 0);
   	      fprintf (dump_file, " = ");
! 	      if (is_gimple_min_invariant (vn_get_expr_for (name)))
! 		print_generic_expr (dump_file, vn_get_expr_for (name), 0);
   	      else
   		print_generic_expr (dump_file, SSA_VAL (name), 0);
   	      fprintf (dump_file, "\n");
*************** run_scc_vn (bool may_insert_arg)
*** 2302,2305 ****
     may_insert = false;
     return true;
   }
- #endif
--- 2523,2525 ----
Index: gcc/tree-ssa-sccvn.h
===================================================================
*** gcc/tree-ssa-sccvn.h.orig	2008-06-25 17:43:11.000000000 +0200
--- gcc/tree-ssa-sccvn.h	2008-06-26 12:03:24.000000000 +0200
*************** typedef struct vn_ssa_aux
*** 54,68 ****
   /* Return the value numbering info for an SSA_NAME.  */
   extern vn_ssa_aux_t VN_INFO (tree);
   extern vn_ssa_aux_t VN_INFO_GET (tree);
   bool run_scc_vn (bool);
   void free_scc_vn (void);
   void switch_to_PRE_table (void);
   tree vn_nary_op_lookup (tree);
   void vn_nary_op_insert (tree, tree);
   tree vn_reference_lookup (tree, VEC (tree, gc) *, bool);
   void vn_reference_insert (tree, tree, VEC (tree, gc) *);
! VEC (tree, gc) *shared_vuses_from_stmt (tree);
! VEC (tree, gc) *copy_vuses_from_stmt (tree);


   #endif /* TREE_SSA_SCCVN_H  */
--- 54,71 ----
   /* Return the value numbering info for an SSA_NAME.  */
   extern vn_ssa_aux_t VN_INFO (tree);
   extern vn_ssa_aux_t VN_INFO_GET (tree);
+ tree vn_get_expr_for (tree);
   bool run_scc_vn (bool);
   void free_scc_vn (void);
   void switch_to_PRE_table (void);
   tree vn_nary_op_lookup (tree);
+ tree vn_nary_op_lookup_stmt (gimple);
   void vn_nary_op_insert (tree, tree);
+ void vn_nary_op_insert_stmt (gimple, tree);
   tree vn_reference_lookup (tree, VEC (tree, gc) *, bool);
   void vn_reference_insert (tree, tree, VEC (tree, gc) *);
! VEC (tree, gc) *shared_vuses_from_stmt (gimple);
! VEC (tree, gc) *copy_vuses_from_stmt (gimple);


   #endif /* TREE_SSA_SCCVN_H  */
Index: gcc/tree-dfa.c
===================================================================
*** gcc/tree-dfa.c.orig	2008-06-25 17:43:11.000000000 +0200
--- gcc/tree-dfa.c	2008-06-26 12:03:24.000000000 +0200
*************** refs_may_alias_p (tree ref1, tree ref2)
*** 1092,1099 ****
     return true;
   }

- /* FIXME tuples */
- #if 0
   /* Given a stmt STMT that references memory, return the single stmt
      that is reached by following the VUSE -> VDEF link.  Returns
      NULL_TREE, if there is no single stmt that defines all VUSEs of
--- 1092,1097 ----
*************** refs_may_alias_p (tree ref1, tree ref2)
*** 1102,1126 ****
      a PHI node as well.  Note that if all VUSEs are default definitions
      this function will return an empty statement.  */

! tree
! get_single_def_stmt (tree stmt)
   {
!   tree def_stmt = NULL_TREE;
     tree use;
     ssa_op_iter iter;

     FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_VIRTUAL_USES)
       {
!       tree tmp = SSA_NAME_DEF_STMT (use);

         /* ???  This is too simplistic for multiple virtual operands
   	 reaching different PHI nodes of the same basic blocks or for
   	 reaching all default definitions.  */
         if (def_stmt
   	  && def_stmt != tmp
! 	  && !(IS_EMPTY_STMT (def_stmt)
! 	       && IS_EMPTY_STMT (tmp)))
! 	return NULL_TREE;

         def_stmt = tmp;
       }
--- 1100,1124 ----
      a PHI node as well.  Note that if all VUSEs are default definitions
      this function will return an empty statement.  */

! gimple
! get_single_def_stmt (gimple stmt)
   {
!   gimple def_stmt = NULL;
     tree use;
     ssa_op_iter iter;

     FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_VIRTUAL_USES)
       {
!       gimple tmp = SSA_NAME_DEF_STMT (use);

         /* ???  This is too simplistic for multiple virtual operands
   	 reaching different PHI nodes of the same basic blocks or for
   	 reaching all default definitions.  */
         if (def_stmt
   	  && def_stmt != tmp
! 	  && !(gimple_nop_p (def_stmt)
! 	       && gimple_nop_p (tmp)))
! 	return NULL;

         def_stmt = tmp;
       }
*************** get_single_def_stmt (tree stmt)
*** 1134,1158 ****
      from a non-backedge.  Returns NULL_TREE if such statement within
      the above conditions cannot be found.  */

! tree
! get_single_def_stmt_from_phi (tree ref, tree phi)
   {
     tree def_arg = NULL_TREE;
!   int i;

     /* Find the single PHI argument that is not flowing in from a
        back edge and verify that the loop-carried definitions do
        not alias the reference we look for.  */
!   for (i = 0; i < PHI_NUM_ARGS (phi); ++i)
       {
         tree arg = PHI_ARG_DEF (phi, i);
!       tree def_stmt;

!       if (!(PHI_ARG_EDGE (phi, i)->flags & EDGE_DFS_BACK))
   	{
   	  /* Multiple non-back edges?  Do not try to handle this.  */
   	  if (def_arg)
! 	    return NULL_TREE;
   	  def_arg = arg;
   	  continue;
   	}
--- 1132,1156 ----
      from a non-backedge.  Returns NULL_TREE if such statement within
      the above conditions cannot be found.  */

! gimple
! get_single_def_stmt_from_phi (tree ref, gimple phi)
   {
     tree def_arg = NULL_TREE;
!   unsigned i;

     /* Find the single PHI argument that is not flowing in from a
        back edge and verify that the loop-carried definitions do
        not alias the reference we look for.  */
!   for (i = 0; i < gimple_phi_num_args (phi); ++i)
       {
         tree arg = PHI_ARG_DEF (phi, i);
!       gimple def_stmt;

!       if (!(gimple_phi_arg_edge (phi, i)->flags & EDGE_DFS_BACK))
   	{
   	  /* Multiple non-back edges?  Do not try to handle this.  */
   	  if (def_arg)
! 	    return NULL;
   	  def_arg = arg;
   	  continue;
   	}
*************** get_single_def_stmt_from_phi (tree ref,
*** 1162,1175 ****
         def_stmt = SSA_NAME_DEF_STMT (arg);
         do
   	{
! 	  if (TREE_CODE (def_stmt) != GIMPLE_MODIFY_STMT
! 	      || refs_may_alias_p (ref, GIMPLE_STMT_OPERAND (def_stmt, 0)))
! 	    return NULL_TREE;
   	  /* ???  This will only work, reaching the PHI node again if
   	     there is a single virtual operand on def_stmt.  */
   	  def_stmt = get_single_def_stmt (def_stmt);
   	  if (!def_stmt)
! 	    return NULL_TREE;
   	}
         while (def_stmt != phi);
       }
--- 1160,1173 ----
         def_stmt = SSA_NAME_DEF_STMT (arg);
         do
   	{
! 	  if (!is_gimple_assign (def_stmt)
! 	      || refs_may_alias_p (ref, gimple_assign_lhs (def_stmt)))
! 	    return NULL;
   	  /* ???  This will only work, reaching the PHI node again if
   	     there is a single virtual operand on def_stmt.  */
   	  def_stmt = get_single_def_stmt (def_stmt);
   	  if (!def_stmt)
! 	    return NULL;
   	}
         while (def_stmt != phi);
       }
*************** get_single_def_stmt_from_phi (tree ref,
*** 1182,1189 ****
      Take into account only definitions that alias REF if following
      back-edges when looking through a loop PHI node.  */

! tree
! get_single_def_stmt_with_phi (tree ref, tree stmt)
   {
     switch (NUM_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_USES))
       {
--- 1180,1187 ----
      Take into account only definitions that alias REF if following
      back-edges when looking through a loop PHI node.  */

! gimple
! get_single_def_stmt_with_phi (tree ref, gimple stmt)
   {
     switch (NUM_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_USES))
       {
*************** get_single_def_stmt_with_phi (tree ref,
*** 1192,1202 ****

       case 1:
         {
! 	tree def_stmt = SSA_NAME_DEF_STMT (SINGLE_SSA_TREE_OPERAND
   					     (stmt, SSA_OP_VIRTUAL_USES));
   	/* We can handle lookups over PHI nodes only for a single
   	   virtual operand.  */
! 	if (TREE_CODE (def_stmt) == PHI_NODE)
   	  return get_single_def_stmt_from_phi (ref, def_stmt);
   	return def_stmt;
         }
--- 1190,1200 ----

       case 1:
         {
! 	gimple def_stmt = SSA_NAME_DEF_STMT (SINGLE_SSA_TREE_OPERAND
   					     (stmt, SSA_OP_VIRTUAL_USES));
   	/* We can handle lookups over PHI nodes only for a single
   	   virtual operand.  */
! 	if (gimple_code (def_stmt) == GIMPLE_PHI)
   	  return get_single_def_stmt_from_phi (ref, def_stmt);
   	return def_stmt;
         }
*************** get_single_def_stmt_with_phi (tree ref,
*** 1205,1208 ****
         return get_single_def_stmt (stmt);
       }
   }
- #endif
--- 1203,1205 ----
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c.orig	2008-06-25 17:43:11.000000000 +0200
--- gcc/tree-ssa-pre.c	2008-06-26 12:03:24.000000000 +0200
*************** do_SCCVN_insertion (tree stmt, tree ssa_
*** 3583,3589 ****

     /* First create a value expression from the expression we want
        to insert and associate it with the value handle for SSA_VN.  */
!   expr = create_value_expr_from (VN_INFO (ssa_vn)->expr, bb, NULL, true);
     if (expr == NULL_TREE)
       return NULL_TREE;
     set_value_handle (expr, get_value_handle (ssa_vn));
--- 3583,3589 ----

     /* First create a value expression from the expression we want
        to insert and associate it with the value handle for SSA_VN.  */
!   expr = create_value_expr_from (vn_get_expr_for (ssa_vn), bb, NULL, true);
     if (expr == NULL_TREE)
       return NULL_TREE;
     set_value_handle (expr, get_value_handle (ssa_vn));
*************** eliminate (void)
*** 3641,3647 ****
   		  tree val = VN_INFO (lhs)->valnum;
   		  if (val != VN_TOP
   		      && VN_INFO (val)->needs_insertion
! 		      && can_PRE_operation (VN_INFO (val)->expr))
   		    sprime = do_SCCVN_insertion (stmt, val);
   		}

--- 3641,3647 ----
   		  tree val = VN_INFO (lhs)->valnum;
   		  if (val != VN_TOP
   		      && VN_INFO (val)->needs_insertion
! 		      && can_PRE_operation (vn_get_expr_for (val)))
   		    sprime = do_SCCVN_insertion (stmt, val);
   		}

*************** static unsigned int
*** 3972,3977 ****
--- 3972,3981 ----
   execute_pre (bool do_fre ATTRIBUTE_UNUSED)
   {
     /* FIXME tuples.  */
+   if (run_scc_vn (do_fre))
+     free_scc_vn ();
+ 
+   /* FIXME tuples.  */
   #if 0
     unsigned int todo = 0;

*************** execute_pre (bool do_fre ATTRIBUTE_UNUSE
*** 4038,4045 ****
     fini_pre ();

     return todo;
- #else
-   gimple_unreachable ();
   #endif
     return 0;
   }
--- 4042,4047 ----
*************** execute_fre (void)
*** 4091,4102 ****
   static bool
   gate_fre (void)
   {
-   /* FIXME tuples */
- #if 0
     return flag_tree_fre != 0;
- #else
-   return 0;
- #endif
   }

   struct gimple_opt_pass pass_fre =
--- 4093,4099 ----
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h.orig	2008-06-25 17:43:11.000000000 +0200
--- gcc/tree-flow.h	2008-06-26 12:03:24.000000000 +0200
*************** extern void set_default_def (tree, tree)
*** 775,783 ****
   extern tree gimple_default_def (struct function *, tree);
   extern bool stmt_references_abnormal_ssa_name (gimple);
   extern bool refs_may_alias_p (tree, tree);
! extern tree get_single_def_stmt (tree);
! extern tree get_single_def_stmt_from_phi (tree, tree);
! extern tree get_single_def_stmt_with_phi (tree, tree);

   /* In tree-phinodes.c  */
   extern void reserve_phi_args_for_new_edge (basic_block);
--- 775,783 ----
   extern tree gimple_default_def (struct function *, tree);
   extern bool stmt_references_abnormal_ssa_name (gimple);
   extern bool refs_may_alias_p (tree, tree);
! extern gimple get_single_def_stmt (gimple);
! extern gimple get_single_def_stmt_from_phi (tree, gimple);
! extern gimple get_single_def_stmt_with_phi (tree, gimple);

   /* In tree-phinodes.c  */
   extern void reserve_phi_args_for_new_edge (basic_block);
*************** static inline tree get_value_handle (tre
*** 1093,1103 ****
   void sort_vuses (VEC (tree, gc) *);
   void sort_vuses_heap (VEC (tree, heap) *);
   tree vn_lookup_or_add (tree);
! tree vn_lookup_or_add_with_stmt (tree, tree);
   tree vn_lookup_or_add_with_vuses (tree, VEC (tree, gc) *);
   void vn_add (tree, tree);
   void vn_add_with_vuses (tree, tree, VEC (tree, gc) *);
! tree vn_lookup_with_stmt (tree, tree);
   tree vn_lookup (tree);
   tree vn_lookup_with_vuses (tree, VEC (tree, gc) *);

--- 1093,1103 ----
   void sort_vuses (VEC (tree, gc) *);
   void sort_vuses_heap (VEC (tree, heap) *);
   tree vn_lookup_or_add (tree);
! tree vn_lookup_or_add_with_stmt (tree, gimple);
   tree vn_lookup_or_add_with_vuses (tree, VEC (tree, gc) *);
   void vn_add (tree, tree);
   void vn_add_with_vuses (tree, tree, VEC (tree, gc) *);
! tree vn_lookup_with_stmt (tree, gimple);
   tree vn_lookup (tree);
   tree vn_lookup_with_vuses (tree, VEC (tree, gc) *);

Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c.orig	2008-06-26 11:59:53.000000000 +0200
--- gcc/gimple.c	2008-06-26 12:03:24.000000000 +0200
*************** gimple_set_bb (gimple stmt, basic_block
*** 1893,1900 ****
   tree
   gimple_fold (const_gimple stmt)
   {
-   tree t;
-
     switch (gimple_code (stmt))
       {
       case GIMPLE_COND:
--- 1893,1898 ----
*************** gimple_fold (const_gimple stmt)
*** 1902,1929 ****
   			  boolean_type_node,
   			  gimple_cond_lhs (stmt),
   			  gimple_cond_rhs (stmt));
-       break;

       case GIMPLE_ASSIGN:
!       if (gimple_num_ops (stmt) > 2)
! 	return fold_binary (gimple_assign_rhs_code (stmt),
! 			    TREE_TYPE (gimple_assign_lhs (stmt)),
! 			    gimple_assign_rhs1 (stmt),
! 			    gimple_assign_rhs2 (stmt));
!       else
! 	return fold_unary (gimple_assign_rhs_code (stmt),
! 			   TREE_TYPE (gimple_assign_lhs (stmt)),
! 			   gimple_assign_rhs1 (stmt));
         break;

       case GIMPLE_SWITCH:
         return gimple_switch_index (stmt);
-       break;

       case GIMPLE_CALL:
!       t = gimple_call_fn (stmt);
!       return fold_unary (TREE_CODE (t), TREE_TYPE (t), t);
!       break;

       default:
         break;
--- 1900,1929 ----
   			  boolean_type_node,
   			  gimple_cond_lhs (stmt),
   			  gimple_cond_rhs (stmt));

       case GIMPLE_ASSIGN:
!       switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
! 	{
! 	case GIMPLE_UNARY_RHS:
! 	  return fold_unary (gimple_assign_rhs_code (stmt),
! 			     TREE_TYPE (gimple_assign_lhs (stmt)),
! 			     gimple_assign_rhs1 (stmt));
! 	case GIMPLE_BINARY_RHS:
! 	  return fold_binary (gimple_assign_rhs_code (stmt),
! 			      TREE_TYPE (gimple_assign_lhs (stmt)),
! 			      gimple_assign_rhs1 (stmt),
! 			      gimple_assign_rhs2 (stmt));
! 	case GIMPLE_SINGLE_RHS:
! 	  return fold (gimple_assign_rhs1 (stmt));
! 	default:;
! 	}
         break;

       case GIMPLE_SWITCH:
         return gimple_switch_index (stmt);

       case GIMPLE_CALL:
!       return NULL_TREE;

       default:
         break;
Index: gcc/tree-vn.c
===================================================================
*** gcc/tree-vn.c.orig	2008-06-25 17:43:11.000000000 +0200
--- gcc/tree-vn.c	2008-06-26 12:03:24.000000000 +0200
*************** vn_add (tree expr, tree val)
*** 208,215 ****
--- 208,218 ----
         gcc_unreachable ();
       }
     set_value_handle (expr, val);
+   /* FIXME: tuples.  */
+ #if 0
     if (TREE_CODE (val) == VALUE_HANDLE)
       add_to_value (val, expr);
+ #endif
   }

   /* Insert EXPR into the value numbering tables with value VAL, and
*************** vn_add_with_vuses (tree expr, tree val,
*** 228,235 ****
--- 231,241 ----
     vn_reference_insert (expr, val, vuses);

     set_value_handle (expr, val);
+   /* FIXME: tuples.  */
+ #if 0
     if (TREE_CODE (val) == VALUE_HANDLE)
       add_to_value (val, expr);
+ #endif
   }


*************** vn_lookup (tree expr)
*** 281,287 ****
      hash value for EXPR for reference operations.  */

   tree
! vn_lookup_with_stmt (tree expr, tree stmt)
   {
     if (stmt == NULL)
       return vn_lookup (expr);
--- 287,293 ----
      hash value for EXPR for reference operations.  */

   tree
! vn_lookup_with_stmt (tree expr, gimple stmt)
   {
     if (stmt == NULL)
       return vn_lookup (expr);
*************** vn_lookup_or_add (tree expr)
*** 347,353 ****
      STMT to get the set of vuses.  */

   tree
! vn_lookup_or_add_with_stmt (tree expr, tree stmt)
   {
     tree v;
     if (!stmt)
--- 353,359 ----
      STMT to get the set of vuses.  */

   tree
! vn_lookup_or_add_with_stmt (tree expr, gimple stmt)
   {
     tree v;
     if (!stmt)



More information about the Gcc-patches mailing list