OSDN Git Service

2008-05-15 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-pre.c
index 72af731..4119467 100644 (file)
@@ -8,7 +8,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -17,9 +17,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -45,6 +44,8 @@ Boston, MA 02110-1301, USA.  */
 #include "bitmap.h"
 #include "langhooks.h"
 #include "cfgloop.h"
+#include "tree-ssa-sccvn.h"
+#include "params.h"
 
 /* TODO:
 
@@ -111,7 +112,7 @@ Boston, MA 02110-1301, USA.  */
 
    Fourth, we eliminate fully redundant expressions.
    This is a simple statement walk that replaces redundant
-   calculations  with the now available values.  */
+   calculations with the now available values.  */
 
 /* Representations of value numbers:
 
@@ -184,6 +185,12 @@ Boston, MA 02110-1301, USA.  */
 /* Next global expression id number.  */
 static unsigned int next_expression_id;
 
+typedef VEC(tree, gc) *vuse_vec;
+DEF_VEC_P (vuse_vec);
+DEF_VEC_ALLOC_P (vuse_vec, heap);
+
+static VEC(vuse_vec, heap) *expression_vuses;
+
 /* Mapping from expression to id number we can use in bitmap sets.  */
 static VEC(tree, heap) *expressions;
 
@@ -202,6 +209,7 @@ alloc_expression_id (tree expr)
   ann->aux = XNEW (unsigned int);
   * ((unsigned int *)ann->aux) = next_expression_id++;
   VEC_safe_push (tree, heap, expressions, expr);
+  VEC_safe_push (vuse_vec, heap, expression_vuses, NULL);
   return next_expression_id - 1;
 }
 
@@ -239,6 +247,25 @@ expression_for_id (unsigned int id)
   return VEC_index (tree, expressions, id);
 }
 
+/* Return the expression vuses for EXPR, if there are any.  */
+
+static inline vuse_vec
+get_expression_vuses (tree expr)
+{
+  unsigned int expr_id = get_or_alloc_expression_id (expr);
+  return VEC_index (vuse_vec, expression_vuses, expr_id);
+}
+
+/* Set the expression vuses for EXPR to VUSES.  */
+
+static inline void
+set_expression_vuses (tree expr, vuse_vec vuses)
+{
+  unsigned int expr_id = get_or_alloc_expression_id (expr);
+  VEC_replace (vuse_vec, expression_vuses, expr_id, vuses);
+}
+
+
 /* Free the expression id field in all of our expressions,
    and then destroy the expressions array.  */
 
@@ -254,6 +281,7 @@ clear_expression_ids (void)
       tree_common_ann (expr)->aux = NULL;
     }
   VEC_free (tree, heap, expressions);
+  VEC_free (vuse_vec, heap, expression_vuses);
 }
 
 static bool in_fre = false;
@@ -301,10 +329,6 @@ typedef struct bb_bitmap_sets
      the current iteration.  */
   bitmap_set_t new_sets;
 
-  /* These are the loads that will be ANTIC_IN at the top of the
-     block, and are actually generated in the block.  */
-  bitmap_set_t antic_safe_loads;
-
   /* True if we have visited this block during ANTIC calculation.  */
   unsigned int visited:1;
 
@@ -320,7 +344,6 @@ typedef struct bb_bitmap_sets
 #define ANTIC_IN(BB)   ((bb_value_sets_t) ((BB)->aux))->antic_in
 #define PA_IN(BB)      ((bb_value_sets_t) ((BB)->aux))->pa_in
 #define NEW_SETS(BB)   ((bb_value_sets_t) ((BB)->aux))->new_sets
-#define ANTIC_SAFE_LOADS(BB) ((bb_value_sets_t) ((BB)->aux))->antic_safe_loads
 #define BB_VISITED(BB) ((bb_value_sets_t) ((BB)->aux))->visited
 #define BB_DEFERRED(BB) ((bb_value_sets_t) ((BB)->aux))->deferred
 
@@ -353,16 +376,15 @@ static struct
 } pre_stats;
 
 static bool do_partial_partial;
-static tree bitmap_find_leader (bitmap_set_t, tree);
+static tree bitmap_find_leader (bitmap_set_t, tree, tree);
 static void bitmap_value_insert_into_set (bitmap_set_t, tree);
 static void bitmap_value_replace_in_set (bitmap_set_t, tree);
 static void bitmap_set_copy (bitmap_set_t, bitmap_set_t);
 static bool bitmap_set_contains_value (bitmap_set_t, tree);
 static void bitmap_insert_into_set (bitmap_set_t, tree);
 static bitmap_set_t bitmap_set_new (void);
-static bool is_undefined_value (tree);
-static tree create_expression_by_pieces (basic_block, tree, tree);
-static tree find_or_generate_expression (basic_block, tree, tree);
+static tree create_expression_by_pieces (basic_block, tree, tree, tree);
+static tree find_or_generate_expression (basic_block, tree, tree, tree);
 
 /* We can add and remove elements and entries to and from sets
    and hash tables, so we use alloc pools for them.  */
@@ -372,7 +394,6 @@ static alloc_pool binary_node_pool;
 static alloc_pool unary_node_pool;
 static alloc_pool reference_node_pool;
 static alloc_pool comparison_node_pool;
-static alloc_pool modify_expr_node_pool;
 static bitmap_obstack grand_bitmap_obstack;
 
 /* We can't use allocation pools to hold temporary CALL_EXPR objects, since
@@ -387,13 +408,15 @@ static struct obstack temp_call_expr_obstack;
    match the current variable's type.  */
 static tree pretemp;
 static tree storetemp;
-static tree mergephitemp;
 static tree prephitemp;
 
 /* Set of blocks with statements that have had its EH information
    cleaned up.  */
 static bitmap need_eh_cleanup;
 
+/* Which expressions have been seen during a given phi translation.  */
+static bitmap seen_during_translate;
+
 /* The phi_translate_table caches phi translations for a given
    expression and predecessor.  */
 
@@ -420,13 +443,14 @@ typedef struct expr_pred_trans_d
      speed reasons.  */
   hashval_t hashcode;
 } *expr_pred_trans_t;
+typedef const struct expr_pred_trans_d *const_expr_pred_trans_t;
 
 /* Return the hash value for a phi translation table entry.  */
 
 static hashval_t
 expr_pred_trans_hash (const void *p)
 {
-  const expr_pred_trans_t ve = (expr_pred_trans_t) p;
+  const_expr_pred_trans_t const ve = (const_expr_pred_trans_t) p;
   return ve->hashcode;
 }
 
@@ -436,8 +460,8 @@ expr_pred_trans_hash (const void *p)
 static int
 expr_pred_trans_eq (const void *p1, const void *p2)
 {
-  const expr_pred_trans_t ve1 = (expr_pred_trans_t) p1;
-  const expr_pred_trans_t ve2 = (expr_pred_trans_t) p2;
+  const_expr_pred_trans_t const ve1 = (const_expr_pred_trans_t) p1;
+  const_expr_pred_trans_t const ve2 = (const_expr_pred_trans_t) p2;
   basic_block b1 = ve1->pred;
   basic_block b2 = ve2->pred;
   int i;
@@ -483,7 +507,7 @@ phi_trans_lookup (tree e, basic_block pred, VEC (tree, gc) *vuses)
   ept.e = e;
   ept.pred = pred;
   ept.vuses = vuses;
-  ept.hashcode = vn_compute (e, (unsigned long) pred);
+  ept.hashcode = iterative_hash_expr (e, (unsigned long) pred);
   slot = htab_find_slot_with_hash (phi_translate_table, &ept, ept.hashcode,
                                   NO_INSERT);
   if (!slot)
@@ -505,7 +529,7 @@ phi_trans_add (tree e, tree v, basic_block pred, VEC (tree, gc) *vuses)
   new_pair->pred = pred;
   new_pair->vuses = vuses;
   new_pair->v = v;
-  new_pair->hashcode = vn_compute (e, (unsigned long) pred);
+  new_pair->hashcode = iterative_hash_expr (e, (unsigned long) pred);
   slot = htab_find_slot_with_hash (phi_translate_table, new_pair,
                                   new_pair->hashcode, INSERT);
   if (*slot)
@@ -520,8 +544,8 @@ phi_trans_add (tree e, tree v, basic_block pred, VEC (tree, gc) *vuses)
 static inline bool
 constant_expr_p (tree v)
 {
-  return TREE_CODE (v) != VALUE_HANDLE && is_gimple_min_invariant (v);
-/*   return TREE_CODE (v) != VALUE_HANDLE; */
+  return TREE_CODE (v) != VALUE_HANDLE &&
+    (TREE_CODE (v) == FIELD_DECL || is_gimple_min_invariant (v));
 }
 
 /* Add expression E to the expression set of value V.  */
@@ -649,9 +673,8 @@ bitmap_set_and (bitmap_set_t dest, bitmap_set_t orig)
   if (dest != orig)
     {
       bitmap temp = BITMAP_ALLOC (&grand_bitmap_obstack);
-      
+
       bitmap_and_into (dest->values, orig->values);
-      
       bitmap_copy (temp, dest->expressions);
       EXECUTE_IF_SET_IN_BITMAP (temp, 0, i, bi)
        {
@@ -931,19 +954,21 @@ find_leader_in_sets (tree expr, bitmap_set_t set1, bitmap_set_t set2)
 {
   tree result;
 
-  result = bitmap_find_leader (set1, expr);
+  result = bitmap_find_leader (set1, expr, NULL_TREE);
   if (!result && set2)
-    result = bitmap_find_leader (set2, expr);
+    result = bitmap_find_leader (set2, expr, NULL_TREE);
   return result;
 }
 
 /* Translate EXPR using phis in PHIBLOCK, so that it has the values of
-   the phis in PRED.  Return NULL if we can't find a leader for each
-   part of the translated expression.  */
+   the phis in PRED.  SEEN is a bitmap saying which expression we have
+   translated since we started translation of the toplevel expression.
+   Return NULL if we can't find a leader for each part of the
+   translated expression.  */
 
 static tree
-phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
-              basic_block pred, basic_block phiblock)
+phi_translate_1 (tree expr, bitmap_set_t set1, bitmap_set_t set2,
+                basic_block pred, basic_block phiblock, bitmap seen)
 {
   tree phitrans = NULL;
   tree oldexpr = expr;
@@ -951,19 +976,13 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
   if (expr == NULL)
     return NULL;
 
-  if (is_gimple_min_invariant (expr))
+  if (constant_expr_p (expr))
     return expr;
 
   /* Phi translations of a given expression don't change.  */
   if (EXPR_P (expr) || GIMPLE_STMT_P (expr))
     {
-      tree vh;
-
-      vh = get_value_handle (expr);
-      if (vh && TREE_CODE (vh) == VALUE_HANDLE)
-       phitrans = phi_trans_lookup (expr, pred, VALUE_HANDLE_VUSES (vh));
-      else
-       phitrans = phi_trans_lookup (expr, pred, NULL);
+      phitrans = phi_trans_lookup (expr, pred, get_expression_vuses (expr));
     }
   else
     phitrans = phi_trans_lookup (expr, pred, NULL);
@@ -971,6 +990,16 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
   if (phitrans)
     return phitrans;
 
+  /* Prevent cycles when we have recursively dependent leaders.  This
+     can only happen when phi translating the maximal set.  */
+  if (seen)
+    {
+      unsigned int expr_id = get_expression_id (expr);
+      if (bitmap_bit_p (seen, expr_id))
+       return NULL;
+      bitmap_set_bit (seen, expr_id);
+    }
+
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_expression:
@@ -986,14 +1015,13 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
            tree oldsc = CALL_EXPR_STATIC_CHAIN (expr);
            tree newfn, newsc = NULL;
            tree newexpr = NULL_TREE;
-           tree vh = get_value_handle (expr);
            bool invariantarg = false;
            int i, nargs;
-           VEC (tree, gc) *vuses = VALUE_HANDLE_VUSES (vh);
+           VEC (tree, gc) *vuses = get_expression_vuses (expr);
            VEC (tree, gc) *tvuses;
 
-           newfn = phi_translate (find_leader_in_sets (oldfn, set1, set2),
-                                  set1, set2, pred, phiblock);
+           newfn = phi_translate_1 (find_leader_in_sets (oldfn, set1, set2),
+                                    set1, set2, pred, phiblock, seen);
            if (newfn == NULL)
              return NULL;
            if (newfn != oldfn)
@@ -1003,8 +1031,8 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
              }
            if (oldsc)
              {
-               newsc = phi_translate (find_leader_in_sets (oldsc, set1, set2),
-                                      set1, set2, pred, phiblock);
+               newsc = phi_translate_1 (find_leader_in_sets (oldsc, set1, set2),
+                                        set1, set2, pred, phiblock, seen);
                if (newsc == NULL)
                  return NULL;
                if (newsc != oldsc)
@@ -1036,8 +1064,8 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
                    if (AGGREGATE_TYPE_P (TREE_TYPE (oldval)))
                      return NULL;
                    oldval = find_leader_in_sets (oldval, set1, set2);
-                   newval = phi_translate (oldval, set1, set2, pred,
-                                           phiblock);
+                   newval = phi_translate_1 (oldval, set1, set2, pred,
+                                           phiblock, seen);
                    if (newval == NULL)
                      return NULL;
                    if (newval != oldval)
@@ -1068,13 +1096,14 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
 
            tvuses = translate_vuses_through_block (vuses, phiblock, pred);
            if (vuses != tvuses && ! newexpr)
-             newexpr = temp_copy_call_expr (expr);
+             newexpr = temp_copy_call_expr (expr);
 
-           if (newexpr)
+           if (newexpr)
              {
                newexpr->base.ann = NULL;
                vn_lookup_or_add_with_vuses (newexpr, tvuses);
                expr = newexpr;
+               set_expression_vuses (newexpr, tvuses);
              }
            phi_trans_add (oldexpr, expr, pred, tvuses);
          }
@@ -1086,14 +1115,16 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
        VEC (tree, gc) * oldvuses = NULL;
        VEC (tree, gc) * newvuses = NULL;
 
-       oldvuses = VALUE_HANDLE_VUSES (get_value_handle (expr));
+       oldvuses = get_expression_vuses (expr);
        if (oldvuses)
          newvuses = translate_vuses_through_block (oldvuses, phiblock,
                                                    pred);
 
        if (oldvuses != newvuses)
-         vn_lookup_or_add_with_vuses (expr, newvuses);
-
+         {
+           vn_lookup_or_add_with_vuses (expr, newvuses);
+           set_expression_vuses (expr, newvuses);
+         }
        phi_trans_add (oldexpr, expr, pred, newvuses);
       }
       return expr;
@@ -1118,7 +1149,7 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
          return NULL;
 
        oldop0 = find_leader_in_sets (oldop0, set1, set2);
-       newop0 = phi_translate (oldop0, set1, set2, pred, phiblock);
+       newop0 = phi_translate_1 (oldop0, set1, set2, pred, phiblock, seen);
        if (newop0 == NULL)
          return NULL;
 
@@ -1126,7 +1157,7 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
          {
            oldop1 = TREE_OPERAND (expr, 1);
            oldop1 = find_leader_in_sets (oldop1, set1, set2);
-           newop1 = phi_translate (oldop1, set1, set2, pred, phiblock);
+           newop1 = phi_translate_1 (oldop1, set1, set2, pred, phiblock, seen);
 
            if (newop1 == NULL)
              return NULL;
@@ -1135,7 +1166,7 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
            if (oldop2)
              {
                oldop2 = find_leader_in_sets (oldop2, set1, set2);
-               newop2 = phi_translate (oldop2, set1, set2, pred, phiblock);
+               newop2 = phi_translate_1 (oldop2, set1, set2, pred, phiblock, seen);
 
                if (newop2 == NULL)
                  return NULL;
@@ -1144,14 +1175,14 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
            if (oldop3)
              {
                oldop3 = find_leader_in_sets (oldop3, set1, set2);
-               newop3 = phi_translate (oldop3, set1, set2, pred, phiblock);
+               newop3 = phi_translate_1 (oldop3, set1, set2, pred, phiblock, seen);
 
                if (newop3 == NULL)
                  return NULL;
              }
          }
 
-       oldvuses = VALUE_HANDLE_VUSES (get_value_handle (expr));
+       oldvuses = get_expression_vuses (expr);
        if (oldvuses)
          newvuses = translate_vuses_through_block (oldvuses, phiblock,
                                                    pred);
@@ -1186,6 +1217,7 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
              {
                newexpr->base.ann = NULL;
                vn_lookup_or_add_with_vuses (newexpr, newvuses);
+               set_expression_vuses (newexpr, newvuses);
              }
            expr = newexpr;
          }
@@ -1206,12 +1238,12 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
        tree newexpr;
 
        oldop1 = find_leader_in_sets (oldop1, set1, set2);
-       newop1 = phi_translate (oldop1, set1, set2, pred, phiblock);
+       newop1 = phi_translate_1 (oldop1, set1, set2, pred, phiblock, seen);
        if (newop1 == NULL)
          return NULL;
 
        oldop2 = find_leader_in_sets (oldop2, set1, set2);
-       newop2 = phi_translate (oldop2, set1, set2, pred, phiblock);
+       newop2 = phi_translate_1 (oldop2, set1, set2, pred, phiblock, seen);
        if (newop2 == NULL)
          return NULL;
        if (newop1 != oldop1 || newop2 != oldop2)
@@ -1230,7 +1262,7 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
            else
              {
                newexpr->base.ann = NULL;
-               vn_lookup_or_add (newexpr, NULL);
+               vn_lookup_or_add (newexpr);
              }
            expr = newexpr;
          }
@@ -1245,7 +1277,7 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
        tree newexpr;
 
        oldop1 = find_leader_in_sets (oldop1, set1, set2);
-       newop1 = phi_translate (oldop1, set1, set2, pred, phiblock);
+       newop1 = phi_translate_1 (oldop1, set1, set2, pred, phiblock, seen);
        if (newop1 == NULL)
          return NULL;
        if (newop1 != oldop1)
@@ -1263,7 +1295,7 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
            else
              {
                newexpr->base.ann = NULL;
-               vn_lookup_or_add (newexpr, NULL);
+               vn_lookup_or_add (newexpr);
              }
            expr = newexpr;
          }
@@ -1288,10 +1320,18 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
        e = find_edge (pred, bb_for_stmt (phi));
        if (e)
          {
-           if (is_undefined_value (PHI_ARG_DEF (phi, e->dest_idx)))
+           tree val;
+           tree def = PHI_ARG_DEF (phi, e->dest_idx);
+
+           if (is_gimple_min_invariant (def))
+             return def;
+
+           if (TREE_CODE (def) == SSA_NAME && ssa_undefined_value_p (def))
              return NULL;
-           vn_lookup_or_add (PHI_ARG_DEF (phi, e->dest_idx), NULL);
-           return PHI_ARG_DEF (phi, e->dest_idx);
+
+           val = get_value_handle (def);
+           gcc_assert (val);
+           return def;
          }
       }
       return expr;
@@ -1301,6 +1341,20 @@ phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
     }
 }
 
+/* Translate EXPR using phis in PHIBLOCK, so that it has the values of
+   the phis in PRED.
+   Return NULL if we can't find a leader for each part of the
+   translated expression.  */
+
+static tree
+phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
+              basic_block pred, basic_block phiblock)
+{
+  bitmap_clear (seen_during_translate);
+  return phi_translate_1 (expr, set1, set2, pred, phiblock,
+                         seen_during_translate);
+}
+
 /* For each expression in SET, translate the value handles through phi nodes
    in PHIBLOCK using edge PHIBLOCK->PRED, and store the resulting
    expressions in DEST.  */
@@ -1329,14 +1383,8 @@ phi_translate_set (bitmap_set_t dest, bitmap_set_t set, basic_block pred,
         we won't look them up that way, or use the result, anyway.  */
       if (translated && !is_gimple_min_invariant (translated))
        {
-         tree vh = get_value_handle (translated);
-         VEC (tree, gc) *vuses;
-
-         /* The value handle itself may also be an invariant, in
-            which case, it has no vuses.  */
-         vuses = !is_gimple_min_invariant (vh)
-           ? VALUE_HANDLE_VUSES (vh) : NULL;
-         phi_trans_add (expr, translated, pred, vuses);
+         phi_trans_add (expr, translated, pred,
+                        get_expression_vuses (translated));
        }
 
       if (translated != NULL)
@@ -1346,11 +1394,12 @@ phi_translate_set (bitmap_set_t dest, bitmap_set_t set, basic_block pred,
 }
 
 /* Find the leader for a value (i.e., the name representing that
-   value) in a given set, and return it.  Return NULL if no leader is
-   found.  */
+   value) in a given set, and return it.  If STMT is non-NULL it
+   makes sure the defining statement for the leader dominates it.
+   Return NULL if no leader is found.  */
 
 static tree
-bitmap_find_leader (bitmap_set_t set, tree val)
+bitmap_find_leader (bitmap_set_t set, tree val, tree stmt)
 {
   if (val == NULL)
     return NULL;
@@ -1377,12 +1426,23 @@ bitmap_find_leader (bitmap_set_t set, tree val)
 
       EXECUTE_IF_AND_IN_BITMAP (exprset->expressions,
                                set->expressions, 0, i, bi)
-       return expression_for_id (i);
+       {
+         tree val = expression_for_id (i);
+         if (stmt)
+           {
+             tree def_stmt = SSA_NAME_DEF_STMT (val);
+             if (TREE_CODE (def_stmt) != PHI_NODE
+                 && bb_for_stmt (def_stmt) == bb_for_stmt (stmt)
+                 && stmt_ann (def_stmt)->uid >= stmt_ann (stmt)->uid)
+               continue;
+           }
+         return val;
+       }
     }
   return NULL;
 }
 
-/* Determine if VALUE, a memory operation, is ANTIC_IN at the top of
+/* Determine if EXPR, a memory expression, is ANTIC_IN at the top of
    BLOCK by seeing if it is not killed in the block.  Note that we are
    only determining whether there is a store that kills it.  Because
    of the order in which clean iterates over values, we are guaranteed
@@ -1390,19 +1450,19 @@ bitmap_find_leader (bitmap_set_t set, tree val)
    ANTIC_IN set already.  */
 
 static bool
-value_dies_in_block_x (tree vh, basic_block block)
+value_dies_in_block_x (tree expr, basic_block block)
 {
   int i;
   tree vuse;
-  VEC (tree, gc) *vuses = VALUE_HANDLE_VUSES (vh);
-  
+  VEC (tree, gc) *vuses = get_expression_vuses (expr);
+
   /* Conservatively, a value dies if it's vuses are defined in this
      block, unless they come from phi nodes (which are merge operations,
      rather than stores.  */
   for (i = 0; VEC_iterate (tree, vuses, i, vuse); i++)
     {
       tree def = SSA_NAME_DEF_STMT (vuse);
-      
+
       if (bb_for_stmt (def) != block)
        continue;
       if (TREE_CODE (def) == PHI_NODE)
@@ -1431,7 +1491,6 @@ static bool
 valid_in_sets (bitmap_set_t set1, bitmap_set_t set2, tree expr,
               basic_block block)
 {
- tree vh = get_value_handle (expr);
  switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_binary:
@@ -1473,7 +1532,7 @@ valid_in_sets (bitmap_set_t set1, bitmap_set_t set2, tree expr,
                if (!union_contains_value (set1, set2, arg))
                  return false;
              }
-           return !value_dies_in_block_x (vh, block);
+           return !value_dies_in_block_x (expr, block);
          }
        return false;
       }
@@ -1509,9 +1568,7 @@ valid_in_sets (bitmap_set_t set1, bitmap_set_t set2, tree expr,
                    && !union_contains_value (set1, set2, op3))
                  return false;
            }
-         return bitmap_set_contains_value (ANTIC_SAFE_LOADS (block),
-                                           vh)
-           || !value_dies_in_block_x (vh, block);
+           return !value_dies_in_block_x (expr, block);
          }
       }
       return false;
@@ -1523,7 +1580,7 @@ valid_in_sets (bitmap_set_t set1, bitmap_set_t set2, tree expr,
       }
 
     case tcc_declaration:
-      return !value_dies_in_block_x (vh, block);
+      return !value_dies_in_block_x (expr, block);
 
     default:
       /* No other cases should be encountered.  */
@@ -1572,7 +1629,7 @@ clean (bitmap_set_t set, basic_block block)
 }
 
 static sbitmap has_abnormal_preds;
-                             
+
 /* List of blocks that may have changed during ANTIC computation and
    thus need to be iterated over.  */
 
@@ -1679,7 +1736,7 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
       if (phi_nodes (first))
        {
          bitmap_set_t from = ANTIC_IN (first);
-             
+
          if (!BB_VISITED (first))
            from = maximal_set;
          phi_translate_set (ANTIC_OUT, from, block, first);
@@ -1694,22 +1751,22 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
 
       for (i = 1; VEC_iterate (basic_block, worklist, i, bprime); i++)
        {
-         if (phi_nodes (bprime)) 
+         if (phi_nodes (bprime))
            {
              bitmap_set_t tmp = bitmap_set_new ();
              bitmap_set_t from = ANTIC_IN (bprime);
-             
+
              if (!BB_VISITED (bprime))
                from = maximal_set;
              phi_translate_set (tmp, from, block, bprime);
              bitmap_set_and (ANTIC_OUT, tmp);
              bitmap_set_free (tmp);
            }
-         else 
+         else
            {
              if (!BB_VISITED (bprime))
                bitmap_set_and (ANTIC_OUT, maximal_set);
-             else 
+             else
                bitmap_set_and (ANTIC_OUT, ANTIC_IN (bprime));
            }
        }
@@ -1750,9 +1807,6 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
          if (ANTIC_OUT)
            print_bitmap_set (dump_file, ANTIC_OUT, "ANTIC_OUT", block->index);
 
-         if (ANTIC_SAFE_LOADS (block))
-           print_bitmap_set (dump_file, ANTIC_SAFE_LOADS (block),
-                             "ANTIC_SAFE_LOADS", block->index);
          print_bitmap_set (dump_file, ANTIC_IN (block), "ANTIC_IN",
                            block->index);
 
@@ -1796,6 +1850,7 @@ compute_partial_antic_aux (basic_block block,
   bitmap_set_t PA_OUT;
   edge e;
   edge_iterator ei;
+  unsigned long max_pa = PARAM_VALUE (PARAM_MAX_PARTIAL_ANTIC_LENGTH);
 
   old_PA_IN = PA_OUT = NULL;
 
@@ -1804,6 +1859,14 @@ compute_partial_antic_aux (basic_block block,
   if (block_has_abnormal_pred_edge)
     goto maybe_dump_sets;
 
+  /* If there are too many partially anticipatable values in the
+     block, phi_translate_set can take an exponential time: stop
+     before the translation starts.  */
+  if (max_pa
+      && single_succ_p (block)
+      && bitmap_count_bits (PA_IN (single_succ (block))->values) > max_pa)
+    goto maybe_dump_sets;
+
   old_PA_IN = PA_IN (block);
   PA_OUT = bitmap_set_new ();
 
@@ -1812,10 +1875,10 @@ compute_partial_antic_aux (basic_block block,
     ;
   /* If we have one successor, we could have some phi nodes to
      translate through.  Note that we can't phi translate across DFS
-     back edges in partial antic, because it uses a union operation
-     on the successors.  For recurrences like IV's, we will end up generating a
-     new value in the set on each go around (i + 3 (VH.1) VH.1 + 1
-     (VH.2), VH.2 + 1 (VH.3), etc), forever.  */
+     back edges in partial antic, because it uses a union operation on
+     the successors.  For recurrences like IV's, we will end up
+     generating a new value in the set on each go around (i + 3 (VH.1)
+     VH.1 + 1 (VH.2), VH.2 + 1 (VH.3), etc), forever.  */
   else if (single_succ_p (block))
     {
       basic_block succ = single_succ (block);
@@ -1968,9 +2031,8 @@ compute_antic (void)
       gcc_assert (num_iterations < 50);
     }
 
-  if (dump_file && (dump_flags & TDF_STATS))
-    fprintf (dump_file, "compute_antic required %d iterations\n",
-            num_iterations);
+  statistics_histogram_event (cfun, "compute_antic iterations",
+                             num_iterations);
 
   if (do_partial_partial)
     {
@@ -1998,80 +2060,13 @@ compute_antic (void)
          /* Theoretically possible, but *highly* unlikely.  */
          gcc_assert (num_iterations < 50);
        }
-      if (dump_file && (dump_flags & TDF_STATS))
-       fprintf (dump_file, "compute_partial_antic required %d iterations\n",
-                num_iterations);
+      statistics_histogram_event (cfun, "compute_partial_antic iterations",
+                                 num_iterations);
     }
   sbitmap_free (has_abnormal_preds);
   sbitmap_free (changed_blocks);
 }
 
-/*
-   ANTIC_SAFE_LOADS are those loads generated in a block that actually
-   occur before any kill to their vuses in the block, and thus, are
-   safe at the top of the block.  This function computes the set by
-   walking the EXP_GEN set for the block, and checking the VUSES.  
-
-   This set could be computed as ANTIC calculation is proceeding, but
-   but because it does not actually change during that computation, it is
-   quicker to pre-calculate the results and use them than to do it on
-   the fly (particularly in the presence of multiple iteration).  */
-
-static void
-compute_antic_safe (void)
-{
-  basic_block bb;
-  bitmap_iterator bi;
-  unsigned int i;
-  
-  FOR_EACH_BB (bb)
-    {
-      FOR_EACH_EXPR_ID_IN_SET (EXP_GEN (bb), i, bi)
-       {
-         tree expr = expression_for_id (i);
-         if (REFERENCE_CLASS_P (expr))
-           {
-             tree vh = get_value_handle (expr);
-             tree maybe = bitmap_find_leader (AVAIL_OUT (bb), vh);
-             ssa_op_iter i;
-             tree vuse;
-             tree stmt;
-             bool okay = true;
-             
-             if (!maybe)
-               continue;
-             stmt = SSA_NAME_DEF_STMT (maybe);
-             
-             FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, i,
-                                        SSA_OP_VIRTUAL_USES)
-               {                     
-                 tree def = SSA_NAME_DEF_STMT (vuse);
-                 
-                 if (bb_for_stmt (def) != bb)
-                   continue;
-                 
-                 /* See if the vuse is defined by a statement that
-                    comes before us in the block.  Phi nodes are not
-                    stores, so they do not count.  */
-                 if (TREE_CODE (def) != PHI_NODE
-                     && stmt_ann (def)->uid < stmt_ann (stmt)->uid)
-                   {
-                     okay = false;      
-                     break;
-                   }
-               }
-             if (okay)
-               {
-                 if (ANTIC_SAFE_LOADS (bb) == NULL)
-                   ANTIC_SAFE_LOADS (bb) = bitmap_set_new ();
-                 bitmap_value_insert_into_set (ANTIC_SAFE_LOADS (bb),
-                                               expr);
-               }
-           }
-       }
-    }
-}
-
 /* Return true if we can value number the call in STMT.  This is true
    if we have a pure or constant call.  */
 
@@ -2080,18 +2075,28 @@ can_value_number_call (tree stmt)
 {
   tree call = get_call_expr_in (stmt);
 
-  if (call_expr_flags (call)  & (ECF_PURE | ECF_CONST))
+  if (call_expr_flags (call) & (ECF_PURE | ECF_CONST))
     return true;
   return false;
 }
 
+/* Return true if OP is an exception handler related operation, such as
+   FILTER_EXPR or EXC_PTR_EXPR.  */
+
+static bool
+is_exception_related (tree op)
+{
+  return TREE_CODE (op) == FILTER_EXPR || TREE_CODE (op) == EXC_PTR_EXPR;
+}
+
 /* Return true if OP is a tree which we can perform value numbering
    on.  */
 
 static bool
 can_value_number_operation (tree op)
 {
-  return UNARY_CLASS_P (op)
+  return (UNARY_CLASS_P (op)
+         && !is_exception_related (TREE_OPERAND (op, 0)))
     || BINARY_CLASS_P (op)
     || COMPARISON_CLASS_P (op)
     || REFERENCE_CLASS_P (op)
@@ -2112,6 +2117,7 @@ can_PRE_operation (tree op)
     || COMPARISON_CLASS_P (op)
     || TREE_CODE (op) == INDIRECT_REF
     || TREE_CODE (op) == COMPONENT_REF
+    || TREE_CODE (op) == VIEW_CONVERT_EXPR
     || TREE_CODE (op) == CALL_EXPR
     || TREE_CODE (op) == ARRAY_REF;
 }
@@ -2141,14 +2147,15 @@ static VEC(tree, heap) *need_creation;
    are doing.
 */
 static tree
-create_component_ref_by_pieces (basic_block block, tree expr, tree stmts)
+create_component_ref_by_pieces (basic_block block, tree expr, tree stmts,
+                               tree domstmt)
 {
   tree genop = expr;
   tree folded;
 
   if (TREE_CODE (genop) == VALUE_HANDLE)
     {
-      tree found = bitmap_find_leader (AVAIL_OUT (block), expr);
+      tree found = bitmap_find_leader (AVAIL_OUT (block), expr, domstmt);
       if (found)
        return found;
     }
@@ -2168,32 +2175,34 @@ create_component_ref_by_pieces (basic_block block, tree expr, tree stmts)
        tree op1, op2, op3;
        op0 = create_component_ref_by_pieces (block,
                                              TREE_OPERAND (genop, 0),
-                                             stmts);
+                                             stmts, domstmt);
        op1 = TREE_OPERAND (genop, 1);
        if (TREE_CODE (op1) == VALUE_HANDLE)
-         op1 = find_or_generate_expression (block, op1, stmts);
+         op1 = find_or_generate_expression (block, op1, stmts, domstmt);
        op2 = TREE_OPERAND (genop, 2);
        if (op2 && TREE_CODE (op2) == VALUE_HANDLE)
-         op2 = find_or_generate_expression (block, op2, stmts);
+         op2 = find_or_generate_expression (block, op2, stmts, domstmt);
        op3 = TREE_OPERAND (genop, 3);
        if (op3 && TREE_CODE (op3) == VALUE_HANDLE)
-         op3 = find_or_generate_expression (block, op3, stmts);
+         op3 = find_or_generate_expression (block, op3, stmts, domstmt);
+       if (!op0 || !op1)
+         return NULL_TREE;
        folded = build4 (ARRAY_REF, TREE_TYPE (genop), op0, op1,
                              op2, op3);
        return folded;
       }
     case COMPONENT_REF:
       {
-       bitmap_set_t exprset;
-       unsigned int firstbit;
        tree op0;
        tree op1;
        op0 = create_component_ref_by_pieces (block,
                                              TREE_OPERAND (genop, 0),
-                                             stmts);
-       exprset = VALUE_HANDLE_EXPR_SET (TREE_OPERAND (genop, 1));
-       firstbit = bitmap_first_set_bit (exprset->expressions);
-       op1 = expression_for_id (firstbit);
+                                             stmts, domstmt);
+       if (!op0)
+         return NULL_TREE;
+       /* op1 should be a FIELD_DECL, which are represented by
+          themselves.  */
+       op1 = TREE_OPERAND (genop, 1);
        folded = fold_build3 (COMPONENT_REF, TREE_TYPE (genop), op0, op1,
                              NULL_TREE);
        return folded;
@@ -2202,7 +2211,9 @@ create_component_ref_by_pieces (basic_block block, tree expr, tree stmts)
     case INDIRECT_REF:
       {
        tree op1 = TREE_OPERAND (genop, 0);
-       tree genop1 = find_or_generate_expression (block, op1, stmts);
+       tree genop1 = find_or_generate_expression (block, op1, stmts, domstmt);
+       if (!genop1)
+         return NULL_TREE;
 
        folded = fold_build1 (TREE_CODE (genop), TREE_TYPE (genop),
                              genop1);
@@ -2229,23 +2240,45 @@ create_component_ref_by_pieces (basic_block block, tree expr, tree stmts)
    EXPR is the expression to find a leader or generate for.
    STMTS is the statement list to put the inserted expressions on.
    Returns the SSA_NAME of the LHS of the generated expression or the
-   leader.  */
+   leader.
+   DOMSTMT if non-NULL is a statement that should be dominated by
+   all uses in the generated expression.  If DOMSTMT is non-NULL this
+   routine can fail and return NULL_TREE.  Otherwise it will assert
+   on failure.  */
 
 static tree
-find_or_generate_expression (basic_block block, tree expr, tree stmts)
+find_or_generate_expression (basic_block block, tree expr, tree stmts,
+                            tree domstmt)
 {
-  tree genop = bitmap_find_leader (AVAIL_OUT (block), expr);
+  tree genop = bitmap_find_leader (AVAIL_OUT (block), expr, domstmt);
 
   /* If it's still NULL, it must be a complex expression, so generate
      it recursively.  */
   if (genop == NULL)
     {
       bitmap_set_t exprset = VALUE_HANDLE_EXPR_SET (expr);
-      unsigned int firstbit = bitmap_first_set_bit (exprset->expressions);
+      bool handled = false;
+      bitmap_iterator bi;
+      unsigned int i;
 
-      genop = expression_for_id (firstbit);
-      gcc_assert (can_PRE_operation (genop));
-      genop = create_expression_by_pieces (block, genop, stmts);
+      /* We will hit cases where we have SSA_NAME's in exprset before
+        other operations, because we may have come up with the SCCVN
+        value before getting to the RHS of the expression.  */
+      FOR_EACH_EXPR_ID_IN_SET (exprset, i, bi)
+       {
+         genop = expression_for_id (i);
+         if (can_PRE_operation (genop))
+           {
+             handled = true;
+             genop = create_expression_by_pieces (block, genop, stmts,
+                                                  domstmt);
+             break;
+           }
+       }
+      if (!handled && domstmt)
+       return NULL_TREE;
+
+      gcc_assert (handled);
     }
   return genop;
 }
@@ -2263,10 +2296,15 @@ find_or_generate_expression (basic_block block, tree expr, tree stmts)
    partially or fully redundant.  Those that are will be either made
    fully redundant during the next iteration of insert (for partially
    redundant ones), or eliminated by eliminate (for fully redundant
-   ones).  */
+   ones).
+
+   If DOMSTMT is non-NULL then we make sure that all uses in the
+   expressions dominate that statement.  In this case the function
+   can return NULL_TREE to signal failure.  */
 
 static tree
-create_expression_by_pieces (basic_block block, tree expr, tree stmts)
+create_expression_by_pieces (basic_block block, tree expr, tree stmts,
+                            tree domstmt)
 {
   tree temp, name;
   tree folded, forced_stmts, newexpr;
@@ -2287,7 +2325,9 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
        fn = CALL_EXPR_FN (expr);
        sc = CALL_EXPR_STATIC_CHAIN (expr);
 
-       genfn = find_or_generate_expression (block, fn, stmts);
+       genfn = find_or_generate_expression (block, fn, stmts, domstmt);
+       if (!genfn)
+         return NULL_TREE;
 
        nargs = call_expr_nargs (expr);
        buffer = (tree*) alloca (nargs * sizeof (tree));
@@ -2295,13 +2335,20 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
        for (i = 0; i < nargs; i++)
          {
            tree arg = CALL_EXPR_ARG (expr, i);
-           buffer[i] = find_or_generate_expression (block, arg, stmts);
+           buffer[i] = find_or_generate_expression (block, arg, stmts,
+                                                    domstmt);
+           if (!buffer[i])
+             return NULL_TREE;
          }
 
        folded = build_call_array (TREE_TYPE (expr), genfn, nargs, buffer);
        if (sc)
-         CALL_EXPR_STATIC_CHAIN (folded) =
-           find_or_generate_expression (block, sc, stmts);
+         {
+           CALL_EXPR_STATIC_CHAIN (folded) =
+             find_or_generate_expression (block, sc, stmts, domstmt);
+           if (!CALL_EXPR_STATIC_CHAIN (folded))
+             return NULL_TREE;
+         }
        folded = fold (folded);
        break;
       }
@@ -2311,12 +2358,18 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
        if (TREE_CODE (expr) == COMPONENT_REF
            || TREE_CODE (expr) == ARRAY_REF)
          {
-           folded = create_component_ref_by_pieces (block, expr, stmts);
+           folded = create_component_ref_by_pieces (block, expr, stmts,
+                                                    domstmt);
+           if (!folded)
+             return NULL_TREE;
          }
        else
          {
            tree op1 = TREE_OPERAND (expr, 0);
-           tree genop1 = find_or_generate_expression (block, op1, stmts);
+           tree genop1 = find_or_generate_expression (block, op1, stmts,
+                                                      domstmt);
+           if (!genop1)
+             return NULL_TREE;
 
            folded = fold_build1 (TREE_CODE (expr), TREE_TYPE (expr),
                                  genop1);
@@ -2329,8 +2382,10 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
       {
        tree op1 = TREE_OPERAND (expr, 0);
        tree op2 = TREE_OPERAND (expr, 1);
-       tree genop1 = find_or_generate_expression (block, op1, stmts);
-       tree genop2 = find_or_generate_expression (block, op2, stmts);
+       tree genop1 = find_or_generate_expression (block, op1, stmts, domstmt);
+       tree genop2 = find_or_generate_expression (block, op2, stmts, domstmt);
+       if (!genop1 || !genop2)
+         return NULL_TREE;
        folded = fold_build2 (TREE_CODE (expr), TREE_TYPE (expr),
                              genop1, genop2);
        break;
@@ -2339,7 +2394,9 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
     case tcc_unary:
       {
        tree op1 = TREE_OPERAND (expr, 0);
-       tree genop1 = find_or_generate_expression (block, op1, stmts);
+       tree genop1 = find_or_generate_expression (block, op1, stmts, domstmt);
+       if (!genop1)
+         return NULL_TREE;
        folded = fold_build1 (TREE_CODE (expr), TREE_TYPE (expr),
                              genop1);
        break;
@@ -2366,9 +2423,10 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
          tree stmt = tsi_stmt (tsi);
          tree forcedname = GIMPLE_STMT_OPERAND (stmt, 0);
          tree forcedexpr = GIMPLE_STMT_OPERAND (stmt, 1);
-         tree val = vn_lookup_or_add (forcedexpr, NULL);
+         tree val = vn_lookup_or_add (forcedexpr);
 
          VEC_safe_push (tree, heap, inserted_exprs, stmt);
+         VN_INFO_GET (forcedname)->valnum = forcedname;
          vn_add (forcedname, val);
          bitmap_value_replace_in_set (NEW_SETS (block), forcedname);
          bitmap_value_replace_in_set (AVAIL_OUT (block), forcedname);
@@ -2412,8 +2470,10 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
      here.  */
   v = get_value_handle (expr);
   vn_add (name, v);
+  VN_INFO_GET (name)->valnum = name;
   get_or_alloc_expression_id (name);
-  bitmap_value_replace_in_set (NEW_SETS (block), name);
+  if (!in_fre)
+    bitmap_value_replace_in_set (NEW_SETS (block), name);
   bitmap_value_replace_in_set (AVAIL_OUT (block), name);
 
   pre_stats.insertions++;
@@ -2489,7 +2549,7 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
        {
          builtexpr = create_expression_by_pieces (bprime,
                                                   eprime,
-                                                  stmts);
+                                                  stmts, NULL_TREE);
          gcc_assert (!(pred->flags & EDGE_ABNORMAL));
          bsi_insert_on_edge (pred, stmts);
          avail[bprime->index] = builtexpr;
@@ -2522,6 +2582,8 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
   temp = create_phi_node (temp, block);
 
   NECESSARY (temp) = 0;
+  VN_INFO_GET (PHI_RESULT (temp))->valnum = PHI_RESULT (temp);
+
   VEC_safe_push (tree, heap, inserted_exprs, temp);
   FOR_EACH_EDGE (pred, ei, block->preds)
     add_phi_arg (temp, avail[pred->src->index], pred);
@@ -2649,7 +2711,7 @@ do_regular_insertion (basic_block block, basic_block dom)
              vprime = get_value_handle (eprime);
              gcc_assert (vprime);
              edoubleprime = bitmap_find_leader (AVAIL_OUT (bprime),
-                                                vprime);
+                                                vprime, NULL_TREE);
              if (edoubleprime == NULL)
                {
                  avail[bprime->index] = eprime;
@@ -2778,7 +2840,7 @@ do_partial_partial_insertion (basic_block block, basic_block dom)
              vprime = get_value_handle (eprime);
              gcc_assert (vprime);
              edoubleprime = bitmap_find_leader (AVAIL_OUT (bprime),
-                                                vprime);
+                                                vprime, NULL_TREE);
              if (edoubleprime == NULL)
                {
                  by_all = false;
@@ -2872,21 +2934,28 @@ insert (void)
       new_stuff = false;
       new_stuff = insert_aux (ENTRY_BLOCK_PTR);
     }
-  if (num_iterations > 2 && dump_file && (dump_flags & TDF_STATS))
-    fprintf (dump_file, "insert required %d iterations\n", num_iterations);
+  statistics_histogram_event (cfun, "insert iterations", num_iterations);
 }
 
 
-/* Return true if VAR is an SSA variable with no defining statement in
-   this procedure, *AND* isn't a live-on-entry parameter.  */
+/* Add OP to EXP_GEN (block), and possibly to the maximal set if it is
+   not defined by a phi node.
+   PHI nodes can't go in the maximal sets because they are not in
+   TMP_GEN, so it is possible to get into non-monotonic situations
+   during ANTIC calculation, because it will *add* bits.  */
 
-static bool
-is_undefined_value (tree expr)
+static void
+add_to_exp_gen (basic_block block, tree op)
 {
-  return (TREE_CODE (expr) == SSA_NAME
-         && IS_EMPTY_STMT (SSA_NAME_DEF_STMT (expr))
-         /* PARM_DECLs and hard registers are always defined.  */
-         && TREE_CODE (SSA_NAME_VAR (expr)) != PARM_DECL);
+  if (!in_fre)
+    {
+      if (TREE_CODE (op) == SSA_NAME && ssa_undefined_value_p (op))
+       return;
+      bitmap_value_insert_into_set (EXP_GEN (block), op);
+      if (TREE_CODE (op) != SSA_NAME
+         || TREE_CODE (SSA_NAME_DEF_STMT (op)) != PHI_NODE)
+       bitmap_value_insert_into_set (maximal_set, op);
+    }
 }
 
 
@@ -2900,10 +2969,11 @@ is_undefined_value (tree expr)
    any).  */
 
 static inline void
-add_to_sets (tree var, tree expr, tree stmt, bitmap_set_t s1,
+add_to_sets (tree var, tree expr, VEC(tree, gc) *vuses, bitmap_set_t s1,
             bitmap_set_t s2)
 {
-  tree val = vn_lookup_or_add (expr, stmt);
+  tree val;
+  val = vn_lookup_or_add_with_vuses (expr, vuses);
 
   /* VAR and EXPR may be the same when processing statements for which
      we are not computing value numbers (e.g., non-assignments, or
@@ -2915,11 +2985,6 @@ add_to_sets (tree var, tree expr, tree stmt, bitmap_set_t s1,
   if (s1)
     bitmap_insert_into_set (s1, var);
 
-  /* PHI nodes can't go in the maximal sets because they are not in
-     TMP_GEN, so it is possible to get into non-monotonic situations
-     during ANTIC calculation, because it will *add* bits.  */
-  if (!in_fre && TREE_CODE (SSA_NAME_DEF_STMT (var)) != PHI_NODE)
-    bitmap_value_insert_into_set (maximal_set, var);
   bitmap_value_insert_into_set (s2, var);
 }
 
@@ -2927,17 +2992,17 @@ add_to_sets (tree var, tree expr, tree stmt, bitmap_set_t s1,
    and return it if it exists.  */
 
 static inline tree
-find_existing_value_expr (tree t, tree stmt)
+find_existing_value_expr (tree t, VEC (tree, gc) *vuses)
 {
   bitmap_iterator bi;
   unsigned int bii;
   tree vh;
   bitmap_set_t exprset;
 
-  if (REFERENCE_CLASS_P (t))
-    vh = vn_lookup (t, stmt);
+  if (REFERENCE_CLASS_P (t) || TREE_CODE (t) == CALL_EXPR || DECL_P (t))
+    vh = vn_lookup_with_vuses (t, vuses);
   else
-    vh = vn_lookup (t, NULL);
+    vh = vn_lookup (t);
 
   if (!vh)
     return NULL;
@@ -2956,10 +3021,14 @@ find_existing_value_expr (tree t, tree stmt)
    replaced with the value handles of each of the operands of EXPR.
 
    VUSES represent the virtual use operands associated with EXPR (if
-   any). Insert EXPR's operands into the EXP_GEN set for BLOCK. */
+   any).  Insert EXPR's operands into the EXP_GEN set for BLOCK.
+
+   If CHECK_AVAIL is true, checks availability of each operand in
+   BLOCKs AVAIL_OUT set.  */
 
 static inline tree
-create_value_expr_from (tree expr, basic_block block, tree stmt)
+create_value_expr_from (tree expr, basic_block block, VEC (tree, gc) *vuses,
+                       bool check_avail)
 {
   int i;
   enum tree_code code = TREE_CODE (expr);
@@ -2997,7 +3066,8 @@ create_value_expr_from (tree expr, basic_block block, tree stmt)
 
   for (i = 0; i < TREE_OPERAND_LENGTH (expr); i++)
     {
-      tree val, op;
+      tree val = NULL_TREE;
+      tree op;
 
       op = TREE_OPERAND (expr, i);
       if (op == NULL_TREE)
@@ -3006,157 +3076,35 @@ create_value_expr_from (tree expr, basic_block block, tree stmt)
       /* Recursively value-numberize reference ops and tree lists.  */
       if (REFERENCE_CLASS_P (op))
        {
-         tree tempop = create_value_expr_from (op, block, stmt);
+         tree tempop = create_value_expr_from (op, block, vuses, check_avail);
          op = tempop ? tempop : op;
-         val = vn_lookup_or_add (op, stmt);
+         val = vn_lookup_or_add_with_vuses (op, vuses);
+         set_expression_vuses (op, vuses);
        }
       else
-       /* Create a value handle for OP and add it to VEXPR.  */
-       val = vn_lookup_or_add (op, NULL);
-
-      if (!is_undefined_value (op) && TREE_CODE (op) != TREE_LIST)
-       bitmap_value_insert_into_set (EXP_GEN (block), op);
+       {
+         val = vn_lookup_or_add (op);
+       }
+      if (TREE_CODE (op) != TREE_LIST)
+       add_to_exp_gen (block, op);
 
       if (TREE_CODE (val) == VALUE_HANDLE)
        TREE_TYPE (val) = TREE_TYPE (TREE_OPERAND (vexpr, i));
 
       TREE_OPERAND (vexpr, i) = val;
+
+      if (check_avail
+         && TREE_CODE (val) == VALUE_HANDLE
+         && !bitmap_set_contains_value (AVAIL_OUT (block), val))
+       return NULL_TREE;
     }
-  efi = find_existing_value_expr (vexpr, stmt);
+  efi = find_existing_value_expr (vexpr, vuses);
   if (efi)
     return efi;
   get_or_alloc_expression_id (vexpr);
   return vexpr;
 }
 
-/* Given a statement STMT and its right hand side which is a load, try
-   to look for the expression stored in the location for the load, and
-   return true if a useful equivalence was recorded for LHS.  */
-
-static bool
-try_look_through_load (tree lhs, tree mem_ref, tree stmt, basic_block block)
-{
-  tree store_stmt = NULL;
-  tree rhs;
-  ssa_op_iter i;
-  tree vuse;
-
-  FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, i, SSA_OP_VIRTUAL_USES)
-    {
-      tree def_stmt;
-
-      gcc_assert (TREE_CODE (vuse) == SSA_NAME);
-      def_stmt = SSA_NAME_DEF_STMT (vuse);
-
-      /* If there is no useful statement for this VUSE, we'll not find a
-        useful expression to return either.  Likewise, if there is a
-        statement but it is not a simple assignment or it has virtual
-        uses, we can stop right here.  Note that this means we do
-        not look through PHI nodes, which is intentional.  */
-      if (!def_stmt
-         || TREE_CODE (def_stmt) != GIMPLE_MODIFY_STMT
-         || !ZERO_SSA_OPERANDS (def_stmt, SSA_OP_VIRTUAL_USES))
-       return false;
-
-      /* If this is not the same statement as one we have looked at for
-        another VUSE of STMT already, we have two statements producing
-        something that reaches our STMT.  */
-      if (store_stmt && store_stmt != def_stmt)
-       return false;
-      else
-       {
-         /* Is this a store to the exact same location as the one we are
-            loading from in STMT?  */
-         if (!operand_equal_p (GIMPLE_STMT_OPERAND (def_stmt, 0), mem_ref, 0))
-           return false;
-
-         /* Otherwise remember this statement and see if all other VUSEs
-            come from the same statement.  */
-         store_stmt = def_stmt;
-       }
-    }
-
-  /* Alright then, we have visited all VUSEs of STMT and we've determined
-     that all of them come from the same statement STORE_STMT.  See if there
-     is a useful expression we can deduce from STORE_STMT.  */
-  rhs = GIMPLE_STMT_OPERAND (store_stmt, 1);
-  if ((TREE_CODE (rhs) == SSA_NAME
-       && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs))
-      || is_gimple_min_invariant (rhs)
-      || TREE_CODE (rhs) == ADDR_EXPR
-      || TREE_INVARIANT (rhs))
-    {
-
-      /* Yay!  Compute a value number for the RHS of the statement and
-        add its value to the AVAIL_OUT set for the block.  Add the LHS
-        to TMP_GEN.  */
-      add_to_sets (lhs, rhs, store_stmt, TMP_GEN (block), AVAIL_OUT (block));
-      if (TREE_CODE (rhs) == SSA_NAME
-         && !is_undefined_value (rhs))
-       bitmap_value_insert_into_set (EXP_GEN (block), rhs);
-      return true;
-    }
-
-  return false;
-}
-
-/* Return a copy of NODE that is stored in the temporary alloc_pool's.
-   This is made recursively true, so that the operands are stored in
-   the pool as well.  */
-
-static tree
-poolify_tree (tree node)
-{
-  switch  (TREE_CODE (node))
-    {
-    case INDIRECT_REF:
-      {
-       tree temp = (tree) pool_alloc (reference_node_pool);
-       memcpy (temp, node, tree_size (node));
-       TREE_OPERAND (temp, 0) = poolify_tree (TREE_OPERAND (temp, 0));
-       return temp;
-      }
-      break;
-    case GIMPLE_MODIFY_STMT:
-      {
-       tree temp = (tree) pool_alloc (modify_expr_node_pool);
-       memcpy (temp, node, tree_size (node));
-       GIMPLE_STMT_OPERAND (temp, 0) =
-         poolify_tree (GIMPLE_STMT_OPERAND (temp, 0));
-       GIMPLE_STMT_OPERAND (temp, 1) =
-         poolify_tree (GIMPLE_STMT_OPERAND (temp, 1));
-       return temp;
-      }
-      break;
-    case SSA_NAME:
-    case INTEGER_CST:
-    case STRING_CST:
-    case REAL_CST:
-    case PARM_DECL:
-    case VAR_DECL:
-    case RESULT_DECL:
-      return node;
-    default:
-      gcc_unreachable ();
-    }
-}
-
-static tree modify_expr_template;
-
-/* Allocate a GIMPLE_MODIFY_STMT with TYPE, and operands OP1, OP2 in the
-   alloc pools and return it.  */
-static tree
-poolify_modify_stmt (tree op1, tree op2)
-{
-  if (modify_expr_template == NULL)
-    modify_expr_template = build_gimple_modify_stmt (op1, op2);
-
-  GIMPLE_STMT_OPERAND (modify_expr_template, 0) = op1;
-  GIMPLE_STMT_OPERAND (modify_expr_template, 1) = op2;
-
-  return poolify_tree (modify_expr_template);
-}
-
 
 /* For each real store operation of the form
    *a = <value> that we see, create a corresponding fake store of the
@@ -3187,16 +3135,15 @@ insert_fake_stores (void)
             virtual uses occur in abnormal phis.  */
 
          if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
-             && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == INDIRECT_REF
-             && !AGGREGATE_TYPE_P (TREE_TYPE (GIMPLE_STMT_OPERAND (stmt, 0)))
-             && TREE_CODE (TREE_TYPE (GIMPLE_STMT_OPERAND
-                                       (stmt, 0))) != COMPLEX_TYPE)
+             && (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == INDIRECT_REF
+                 || handled_component_p (GIMPLE_STMT_OPERAND (stmt, 0)))
+             && !AGGREGATE_TYPE_P (TREE_TYPE (GIMPLE_STMT_OPERAND (stmt, 0))))
            {
              ssa_op_iter iter;
              def_operand_p defp;
              tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
              tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-             tree new_tree;
+             tree new_tree, new_lhs;
              bool notokay = false;
 
              FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_VIRTUAL_DEFS)
@@ -3215,16 +3162,17 @@ insert_fake_stores (void)
              if (!storetemp || TREE_TYPE (rhs) != TREE_TYPE (storetemp))
                {
                  storetemp = create_tmp_var (TREE_TYPE (rhs), "storetmp");
-                 if (TREE_CODE (TREE_TYPE (storetemp)) == VECTOR_TYPE)
+                 if (TREE_CODE (TREE_TYPE (storetemp)) == VECTOR_TYPE
+                     || TREE_CODE (TREE_TYPE (storetemp)) == COMPLEX_TYPE)
                    DECL_GIMPLE_REG_P (storetemp) = 1;
                  get_var_ann (storetemp);
                }
 
-             new_tree = poolify_modify_stmt (storetemp, lhs);
+             new_tree = build_gimple_modify_stmt (NULL_TREE, lhs);
+             new_lhs = make_ssa_name (storetemp, new_tree);
+             GIMPLE_STMT_OPERAND (new_tree, 0) = new_lhs;
 
-             lhs = make_ssa_name (storetemp, new_tree);
-             GIMPLE_STMT_OPERAND (new_tree, 0) = lhs;
-             create_ssa_artificial_load_stmt (new_tree, stmt);
+             create_ssa_artificial_load_stmt (new_tree, stmt, false);
 
              NECESSARY (new_tree) = 0;
              VEC_safe_push (tree, heap, inserted_exprs, new_tree);
@@ -3249,77 +3197,203 @@ realify_fake_stores (void)
     {
       if (NECESSARY (stmt))
        {
-         block_stmt_iterator bsi;
-         tree newstmt, tmp;
+         block_stmt_iterator bsi, bsi2;
+         tree rhs;
 
          /* Mark the temp variable as referenced */
          add_referenced_var (SSA_NAME_VAR (GIMPLE_STMT_OPERAND (stmt, 0)));
 
-         /* Put the new statement in GC memory, fix up the
-            SSA_NAME_DEF_STMT on it, and then put it in place of
-            the old statement before the store in the IR stream
+         /* Put the statement before the store in the IR stream
             as a plain ssa name copy.  */
          bsi = bsi_for_stmt (stmt);
          bsi_prev (&bsi);
-         tmp = GIMPLE_STMT_OPERAND (bsi_stmt (bsi), 1);
-         newstmt = build_gimple_modify_stmt (GIMPLE_STMT_OPERAND (stmt, 0),
-                                             tmp);
-         SSA_NAME_DEF_STMT (GIMPLE_STMT_OPERAND (newstmt, 0)) = newstmt;
-         bsi_insert_before (&bsi, newstmt, BSI_SAME_STMT);
-         bsi = bsi_for_stmt (stmt);
-         bsi_remove (&bsi, true);
+         rhs = GIMPLE_STMT_OPERAND (bsi_stmt (bsi), 1);
+         GIMPLE_STMT_OPERAND (stmt, 1) = rhs;
+         bsi2 = bsi_for_stmt (stmt);
+         bsi_remove (&bsi2, true);
+         bsi_insert_before (&bsi, stmt, BSI_SAME_STMT);
        }
       else
        release_defs (stmt);
     }
 }
 
-/* Tree-combine a value number expression *EXPR_P that does a type
-   conversion with the value number expression of its operand.
-   Returns true, if *EXPR_P simplifies to a value number or
-   gimple min-invariant expression different from EXPR_P and
-   sets *EXPR_P to the simplified expression value number.
-   Otherwise returns false and does not change *EXPR_P.  */
+/* Given an SSA_NAME, see if SCCVN has a value number for it, and if
+   so, return the value handle for this value number, creating it if
+   necessary.
+   Return NULL if SCCVN has no info for us.  */
+
+static tree
+get_sccvn_value (tree name)
+{
+  if (TREE_CODE (name) == SSA_NAME
+      && VN_INFO (name)->valnum != name
+      && VN_INFO (name)->valnum != VN_TOP)
+    {
+      tree val = VN_INFO (name)->valnum;
+      bool is_invariant = is_gimple_min_invariant (val);
+      tree valvh = !is_invariant ? get_value_handle (val) : NULL_TREE;
+
+      /* We may end up with situations where SCCVN has chosen a
+        representative for the equivalence set that we have not
+        visited yet.  In this case, just create the value handle for
+        it.  */
+      if (!valvh && !is_invariant)
+       {
+         /* We lookup with the LHS, so do not use vn_lookup_or_add_with_stmt
+            here, as that will result in useless reference lookups.  */
+         valvh = vn_lookup_or_add (val);
+       }
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "SCCVN says ");
+         print_generic_expr (dump_file, name, 0);
+         fprintf (dump_file, " value numbers to ");
+         if (valvh && !is_invariant)
+           {
+             print_generic_expr (dump_file, val, 0);
+             fprintf (dump_file, " (");
+             print_generic_expr (dump_file, valvh, 0);
+             fprintf (dump_file, ")\n");
+           }
+         else
+           print_generic_stmt (dump_file, val, 0);
+       }
+      if (valvh)
+       return valvh;
+      else
+       return val;
+    }
+  return NULL_TREE;
+}
+
+/* Create value handles for PHI in BLOCK.  */
+
+static void
+make_values_for_phi (tree phi, basic_block block)
+{
+  tree result = PHI_RESULT (phi);
+  /* We have no need for virtual phis, as they don't represent
+     actual computations.  */
+  if (is_gimple_reg (result))
+    {
+      tree sccvnval = get_sccvn_value (result);
+      if (sccvnval)
+       {
+         vn_add (result, sccvnval);
+         bitmap_insert_into_set (PHI_GEN (block), result);
+         bitmap_value_insert_into_set (AVAIL_OUT (block), result);
+       }
+      else
+       add_to_sets (result, result, NULL,
+                    PHI_GEN (block), AVAIL_OUT (block));
+    }
+}
+
+/* Create value handles for STMT in BLOCK.  Return true if we handled
+   the statement.  */
 
 static bool
-try_combine_conversion (tree *expr_p)
+make_values_for_stmt (tree stmt, basic_block block)
 {
-  tree expr = *expr_p;
-  tree t;
-  bitmap_set_t exprset;
-  unsigned int firstbit;
-
-  if (!((TREE_CODE (expr) == NOP_EXPR
-        || TREE_CODE (expr) == CONVERT_EXPR
-        || TREE_CODE (expr) == REALPART_EXPR
-        || TREE_CODE (expr) == IMAGPART_EXPR)
-       && TREE_CODE (TREE_OPERAND (expr, 0)) == VALUE_HANDLE
-       && !VALUE_HANDLE_VUSES (TREE_OPERAND (expr, 0))))
-    return false;
 
-  exprset = VALUE_HANDLE_EXPR_SET (TREE_OPERAND (expr, 0));
-  firstbit = bitmap_first_set_bit (exprset->expressions);
-  t = fold_unary (TREE_CODE (expr), TREE_TYPE (expr),
-                 expression_for_id (firstbit));
-  if (!t)
-    return false;
+  tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+  tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
+  tree valvh = NULL_TREE;
+  tree lhsval;
+  VEC (tree, gc) *vuses = NULL;
 
-  /* Strip useless type conversions, which is safe in the optimizers but
-     not generally in fold.  */
-  STRIP_USELESS_TYPE_CONVERSION (t);
+  valvh = get_sccvn_value (lhs);
 
-  /* Disallow value expressions we have no value number for already, as
-     we would miss a leader for it here.  */
-  if (!(TREE_CODE (t) == VALUE_HANDLE
-       || is_gimple_min_invariant (t)))
-    t = vn_lookup (t, NULL);
+  if (valvh)
+    {
+      vn_add (lhs, valvh);
+      bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
+      /* Shortcut for FRE. We have no need to create value expressions,
+        just want to know what values are available where.  */
+      if (in_fre)
+       return true;
 
-  if (t && t != expr)
+    }
+  else if (in_fre)
     {
-      *expr_p = t;
+      /* For FRE, if SCCVN didn't find anything, we aren't going to
+        either, so just make up a new value number if necessary and
+        call it a day */
+      if (get_value_handle (lhs) == NULL)
+       vn_lookup_or_add (lhs);
+      bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
+      return true;
+    }
+
+  lhsval = valvh ? valvh : get_value_handle (lhs);
+  vuses = copy_vuses_from_stmt (stmt);
+  STRIP_USELESS_TYPE_CONVERSION (rhs);
+  if (can_value_number_operation (rhs)
+      && (!lhsval || !is_gimple_min_invariant (lhsval))
+      && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
+    {
+      /* For value numberable operation, create a
+        duplicate expression with the operands replaced
+        with the value handles of the original RHS.  */
+      tree newt = create_value_expr_from (rhs, block, vuses, false);
+      if (newt)
+       {
+         set_expression_vuses (newt, vuses);
+         /* If we already have a value number for the LHS, reuse
+            it rather than creating a new one.  */
+         if (lhsval)
+           {
+             set_value_handle (newt, lhsval);
+             if (!is_gimple_min_invariant (lhsval))
+               add_to_value (lhsval, newt);
+           }
+         else
+           {
+             tree val = vn_lookup_or_add_with_vuses (newt, vuses);
+             vn_add (lhs, val);
+           }
+
+         add_to_exp_gen (block, newt);
+       }
+
+      bitmap_insert_into_set (TMP_GEN (block), lhs);
+      bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
+      return true;
+    }
+  else if ((TREE_CODE (rhs) == SSA_NAME
+           && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs))
+          || is_gimple_min_invariant (rhs)
+          || TREE_CODE (rhs) == ADDR_EXPR
+          || DECL_P (rhs))
+    {
+
+      if (lhsval)
+       {
+         set_expression_vuses (rhs, vuses);
+         set_value_handle (rhs, lhsval);
+         if (!is_gimple_min_invariant (lhsval))
+           add_to_value (lhsval, rhs);
+         bitmap_insert_into_set (TMP_GEN (block), lhs);
+         bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
+       }
+      else
+       {
+         /* Compute a value number for the RHS of the statement
+            and add its value to the AVAIL_OUT set for the block.
+            Add the LHS to TMP_GEN.  */
+         set_expression_vuses (rhs, vuses);
+         add_to_sets (lhs, rhs, vuses, TMP_GEN (block),
+                      AVAIL_OUT (block));
+       }
+      /* None of the rest of these can be PRE'd.  */
+      if (TREE_CODE (rhs) == SSA_NAME && !ssa_undefined_value_p (rhs))
+       add_to_exp_gen (block, rhs);
       return true;
     }
   return false;
+
 }
 
 /* Compute the AVAIL set for all basic blocks.
@@ -3339,6 +3413,7 @@ compute_avail (void)
   basic_block *worklist;
   size_t sp = 0;
   tree param;
+
   /* For arguments with default definitions, we pretend they are
      defined in the entry block.  */
   for (param = DECL_ARGUMENTS (current_function_decl);
@@ -3349,10 +3424,12 @@ compute_avail (void)
        {
          tree def = gimple_default_def (cfun, param);
 
-         vn_lookup_or_add (def, NULL);
-         bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR), def);
+         vn_lookup_or_add (def);
          if (!in_fre)
-           bitmap_value_insert_into_set (maximal_set, def);
+           {
+             bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR), def);
+             bitmap_value_insert_into_set (maximal_set, def);
+           }
          bitmap_value_insert_into_set (AVAIL_OUT (ENTRY_BLOCK_PTR), def);
        }
     }
@@ -3365,10 +3442,12 @@ compute_avail (void)
        {
          tree def = gimple_default_def (cfun, param);
 
-         vn_lookup_or_add (def, NULL);
-         bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR), def);
+         vn_lookup_or_add (def);
          if (!in_fre)
-           bitmap_value_insert_into_set (maximal_set, def);
+           {
+             bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR), def);
+             bitmap_value_insert_into_set (maximal_set, def);
+           }
          bitmap_value_insert_into_set (AVAIL_OUT (ENTRY_BLOCK_PTR), def);
        }
     }
@@ -3402,15 +3481,7 @@ compute_avail (void)
 
       /* Generate values for PHI nodes.  */
       for (phi = phi_nodes (block); phi; phi = PHI_CHAIN (phi))
-       {
-         /* We have no need for virtual phis, as they don't represent
-            actual computations.  */
-         if (is_gimple_reg (PHI_RESULT (phi)))
-           {
-             add_to_sets (PHI_RESULT (phi), PHI_RESULT (phi), NULL,
-                          PHI_GEN (block), AVAIL_OUT (block));
-           }
-       }
+       make_values_for_phi (phi, block);
 
       /* Now compute value numbers and populate value sets with all
         the expressions computed in BLOCK.  */
@@ -3439,11 +3510,25 @@ compute_avail (void)
              stmt = TREE_OPERAND (stmt, 0);
              if (stmt && TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
                {
-                 lhs  = GIMPLE_STMT_OPERAND (stmt, 0);
+                 lhs = GIMPLE_STMT_OPERAND (stmt, 0);
                  rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-                 if (TREE_CODE (rhs) == SSA_NAME
-                     && !is_undefined_value (rhs))
-                   bitmap_value_insert_into_set (EXP_GEN (block), rhs);
+                 if (TREE_CODE (lhs) == SSA_NAME
+                     && is_gimple_min_invariant (VN_INFO (lhs)->valnum))
+                   {
+                     if (dump_file && (dump_flags & TDF_DETAILS))
+                       {
+                         fprintf (dump_file, "SCCVN says ");
+                         print_generic_expr (dump_file, lhs, 0);
+                         fprintf (dump_file, " value numbers to ");
+                         print_generic_stmt (dump_file, VN_INFO (lhs)->valnum,
+                                             0);
+                       }
+                     vn_add (lhs, VN_INFO (lhs)->valnum);
+                     continue;
+                   }
+
+                 if (TREE_CODE (rhs) == SSA_NAME)
+                   add_to_exp_gen (block, rhs);
 
                  FOR_EACH_SSA_TREE_OPERAND (op, realstmt, iter, SSA_OP_DEF)
                    add_to_sets (op, op, NULL, TMP_GEN (block),
@@ -3453,65 +3538,12 @@ compute_avail (void)
            }
 
          else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
-             && !ann->has_volatile_ops
-             && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == SSA_NAME
-             && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI
-                  (GIMPLE_STMT_OPERAND (stmt, 0)))
+                  && !ann->has_volatile_ops
+                  && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == SSA_NAME
+                  && !tree_could_throw_p (stmt))
            {
-             tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
-             tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-
-             /* Try to look through loads.  */
-             if (TREE_CODE (lhs) == SSA_NAME
-                 && !ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_USES)
-                 && try_look_through_load (lhs, rhs, stmt, block))
+             if (make_values_for_stmt (stmt, block))
                continue;
-
-             STRIP_USELESS_TYPE_CONVERSION (rhs);
-             if (can_value_number_operation (rhs))
-               {
-                 /* For value numberable operation, create a
-                    duplicate expression with the operands replaced
-                    with the value handles of the original RHS.  */
-                 tree newt = create_value_expr_from (rhs, block, stmt);
-                 if (newt)
-                   {
-                     /* If we can combine a conversion expression
-                        with the expression for its operand just
-                        record the value number for it.  */
-                     if (try_combine_conversion (&newt))
-                       vn_add (lhs, newt);
-                     else
-                       {
-                         tree val = vn_lookup_or_add (newt, stmt);
-                         vn_add (lhs, val);
-                         if (!in_fre)
-                           bitmap_value_insert_into_set (maximal_set, newt);
-                         bitmap_value_insert_into_set (EXP_GEN (block), newt);
-                       }
-                     bitmap_insert_into_set (TMP_GEN (block), lhs);
-                     bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
-                     continue;
-                   }
-               }
-             else if ((TREE_CODE (rhs) == SSA_NAME
-                       && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs))
-                      || is_gimple_min_invariant (rhs)
-                      || TREE_CODE (rhs) == ADDR_EXPR
-                      || TREE_INVARIANT (rhs)
-                      || DECL_P (rhs))
-               {
-                 /* Compute a value number for the RHS of the statement
-                    and add its value to the AVAIL_OUT set for the block.
-                    Add the LHS to TMP_GEN.  */
-                 add_to_sets (lhs, rhs, stmt, TMP_GEN (block),
-                              AVAIL_OUT (block));
-
-                 if (TREE_CODE (rhs) == SSA_NAME
-                     && !is_undefined_value (rhs))
-                   bitmap_value_insert_into_set (EXP_GEN (block), rhs);
-                 continue;
-               }
            }
 
          /* For any other statement that we don't recognize, simply
@@ -3520,8 +3552,9 @@ compute_avail (void)
          FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
            add_to_sets (op, op, NULL, TMP_GEN (block), AVAIL_OUT (block));
 
+         /* Also add all referenced SSA_NAMEs to EXP_GEN.  */
          FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
-           add_to_sets (op, op, NULL, NULL , AVAIL_OUT (block));
+           add_to_exp_gen (block, op);
        }
 
       /* Put the dominator children of BLOCK on the worklist of blocks
@@ -3535,13 +3568,44 @@ compute_avail (void)
   free (worklist);
 }
 
+/* Insert the expression for SSA_VN that SCCVN thought would be simpler
+   than the available expressions for it.  The insertion point is
+   right before the first use in STMT.  Returns the SSA_NAME that should
+   be used for replacement.  */
+
+static tree
+do_SCCVN_insertion (tree stmt, tree ssa_vn)
+{
+  basic_block bb = bb_for_stmt (stmt);
+  block_stmt_iterator bsi;
+  tree expr, stmts;
+
+  /* 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));
+
+  /* Then use create_expression_by_pieces to generate a valid
+     expression to insert at this point of the IL stream.  */
+  stmts = alloc_stmt_list ();
+  expr = create_expression_by_pieces (bb, expr, stmts, stmt);
+  if (expr == NULL_TREE)
+    return NULL_TREE;
+  bsi = bsi_for_stmt (stmt);
+  bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
+
+  return expr;
+}
 
 /* Eliminate fully redundant computations.  */
 
-static void
+static unsigned int
 eliminate (void)
 {
   basic_block b;
+  unsigned int todo = 0;
 
   FOR_EACH_BB (b)
     {
@@ -3565,7 +3629,21 @@ eliminate (void)
              tree sprime;
 
              sprime = bitmap_find_leader (AVAIL_OUT (b),
-                                          vn_lookup (lhs, NULL));
+                                          get_value_handle (lhs), NULL_TREE);
+
+             /* If there is no existing usable leader but SCCVN thinks
+                it has an expression it wants to use as replacement,
+                insert that.  */
+             if (!sprime
+                 || sprime == lhs)
+               {
+                 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);
+               }
+
              if (sprime
                  && sprime != lhs
                  && (TREE_CODE (*rhs_p) != SSA_NAME
@@ -3589,8 +3667,8 @@ eliminate (void)
                     which may require adding a simple cast, which fold_convert
                     will do for us.  */
                  if (TREE_CODE (*rhs_p) != SSA_NAME
-                     && !tree_ssa_useless_type_conversion_1 (TREE_TYPE (*rhs_p),
-                                                             TREE_TYPE (sprime)))
+                     && !useless_type_conversion_p (TREE_TYPE (*rhs_p),
+                                                   TREE_TYPE (sprime)))
                    sprime = fold_convert (TREE_TYPE (*rhs_p), sprime);
 
                  pre_stats.eliminations++;
@@ -3608,8 +3686,46 @@ eliminate (void)
                    }
                }
            }
+         /* Visit COND_EXPRs and fold the comparison with the
+            available value-numbers.  */
+         else if (TREE_CODE (stmt) == COND_EXPR
+                  && COMPARISON_CLASS_P (COND_EXPR_COND (stmt)))
+           {
+             tree cond = COND_EXPR_COND (stmt);
+             tree op0 = TREE_OPERAND (cond, 0);
+             tree op1 = TREE_OPERAND (cond, 1);
+             tree result;
+
+             if (TREE_CODE (op0) == SSA_NAME)
+               op0 = VN_INFO (op0)->valnum;
+             if (TREE_CODE (op1) == SSA_NAME)
+               op1 = VN_INFO (op1)->valnum;
+             result = fold_binary (TREE_CODE (cond), TREE_TYPE (cond),
+                                   op0, op1);
+             if (result && TREE_CODE (result) == INTEGER_CST)
+               {
+                 COND_EXPR_COND (stmt) = result;
+                 update_stmt (stmt);
+                 todo = TODO_cleanup_cfg;
+               }
+           }
+         else if (TREE_CODE (stmt) == COND_EXPR
+                  && TREE_CODE (COND_EXPR_COND (stmt)) == SSA_NAME)
+           {
+             tree op = COND_EXPR_COND (stmt);
+             op = VN_INFO (op)->valnum;
+             if (TREE_CODE (op) == INTEGER_CST)
+               {
+                 COND_EXPR_COND (stmt) = integer_zerop (op)
+                   ? boolean_false_node : boolean_true_node;
+                 update_stmt (stmt);
+                 todo = TODO_cleanup_cfg;
+               }
+           }
        }
     }
+
+  return todo;
 }
 
 /* Borrow a bit of tree-ssa-dce.c for the moment.
@@ -3685,14 +3801,14 @@ remove_dead_inserted_code (void)
       else
        {
          /* Propagate through the operands.  Examine all the USE, VUSE and
-            VDEF operands in this statement.  Mark all the statements 
+            VDEF operands in this statement.  Mark all the statements
             which feed this statement's uses as necessary.  */
          ssa_op_iter iter;
          tree use;
 
          /* The operands of VDEF expressions are also needed as they
             represent potential definitions that may reach this
-            statement (VDEF operands allow us to follow def-def 
+            statement (VDEF operands allow us to follow def-def
             links).  */
 
          FOR_EACH_SSA_TREE_OPERAND (use, t, iter, SSA_OP_ALL_USES)
@@ -3740,16 +3856,15 @@ init_pre (bool do_fre)
 
   next_expression_id = 0;
   expressions = NULL;
+  expression_vuses = NULL;
   in_fre = do_fre;
 
   inserted_exprs = NULL;
   need_creation = NULL;
   pretemp = NULL_TREE;
   storetemp = NULL_TREE;
-  mergephitemp = NULL_TREE;
   prephitemp = NULL_TREE;
 
-  vn_init ();
   if (!do_fre)
     loop_optimizer_init (LOOPS_NORMAL);
 
@@ -3758,7 +3873,7 @@ init_pre (bool do_fre)
 
 
   postorder = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS);
-  post_order_compute (postorder, false);
+  post_order_compute (postorder, false, false);
 
   FOR_ALL_BB (bb)
     bb->aux = xcalloc (1, sizeof (struct bb_bitmap_sets));
@@ -3769,6 +3884,7 @@ init_pre (bool do_fre)
   bitmap_obstack_initialize (&grand_bitmap_obstack);
   phi_translate_table = htab_create (5110, expr_pred_trans_hash,
                                     expr_pred_trans_eq, free);
+  seen_during_translate = BITMAP_ALLOC (&grand_bitmap_obstack);
   bitmap_set_pool = create_alloc_pool ("Bitmap sets",
                                       sizeof (struct bitmap_set), 30);
   binary_node_pool = create_alloc_pool ("Binary tree nodes",
@@ -3779,11 +3895,7 @@ init_pre (bool do_fre)
                                           tree_code_size (ARRAY_REF), 30);
   comparison_node_pool = create_alloc_pool ("Comparison tree nodes",
                                            tree_code_size (EQ_EXPR), 30);
-  modify_expr_node_pool = create_alloc_pool ("GIMPLE_MODIFY_STMT nodes",
-                                            tree_code_size (GIMPLE_MODIFY_STMT),
-                                            30);
   obstack_init (&temp_call_expr_obstack);
-  modify_expr_template = NULL;
 
   FOR_ALL_BB (bb)
     {
@@ -3815,7 +3927,6 @@ fini_pre (void)
   free_alloc_pool (reference_node_pool);
   free_alloc_pool (unary_node_pool);
   free_alloc_pool (comparison_node_pool);
-  free_alloc_pool (modify_expr_node_pool);
   htab_delete (phi_translate_table);
   remove_fake_exit_edges ();
 
@@ -3826,7 +3937,6 @@ fini_pre (void)
     }
 
   free_dominance_info (CDI_POST_DOMINATORS);
-  vn_delete ();
 
   if (!bitmap_empty_p (need_eh_cleanup))
     {
@@ -3856,9 +3966,10 @@ fini_pre (void)
 /* Main entry point to the SSA-PRE pass.  DO_FRE is true if the caller
    only wants to do full redundancy elimination.  */
 
-static void
+static unsigned int
 execute_pre (bool do_fre)
 {
+  unsigned int todo = 0;
 
   do_partial_partial = optimize > 2;
   init_pre (do_fre);
@@ -3867,6 +3978,14 @@ execute_pre (bool do_fre)
     insert_fake_stores ();
 
   /* Collect and value number expressions computed in each basic block.  */
+  if (!run_scc_vn (do_fre))
+    {
+      if (!do_fre)
+       remove_dead_inserted_code ();
+      fini_pre ();
+      return 0;
+    }
+  switch_to_PRE_table ();
   compute_avail ();
 
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3890,25 +4009,22 @@ execute_pre (bool do_fre)
      computing ANTIC, either, even though it's plenty fast.  */
   if (!do_fre && n_basic_blocks < 4000)
     {
-      compute_antic_safe ();
       compute_antic ();
       insert ();
     }
 
   /* Remove all the redundant expressions.  */
-  eliminate ();
+  todo |= eliminate ();
 
-  if (dump_file && (dump_flags & TDF_STATS))
-    {
-      fprintf (dump_file, "Insertions: %d\n", pre_stats.insertions);
-      fprintf (dump_file, "PA inserted: %d\n", pre_stats.pa_insert);
-      fprintf (dump_file, "New PHIs: %d\n", pre_stats.phis);
-      fprintf (dump_file, "Eliminated: %d\n", pre_stats.eliminations);
-      fprintf (dump_file, "Constified: %d\n", pre_stats.constified);
-    }
+  statistics_counter_event (cfun, "Insertions", pre_stats.insertions);
+  statistics_counter_event (cfun, "PA inserted", pre_stats.pa_insert);
+  statistics_counter_event (cfun, "New PHIs", pre_stats.phis);
+  statistics_counter_event (cfun, "Eliminated", pre_stats.eliminations);
+  statistics_counter_event (cfun, "Constified", pre_stats.constified);
   bsi_commit_edge_inserts ();
 
   clear_expression_ids ();
+  free_scc_vn ();
   if (!do_fre)
     {
       remove_dead_inserted_code ();
@@ -3916,6 +4032,8 @@ execute_pre (bool do_fre)
     }
 
   fini_pre ();
+
+  return todo;
 }
 
 /* Gate and execute functions for PRE.  */
@@ -3923,8 +4041,7 @@ execute_pre (bool do_fre)
 static unsigned int
 do_pre (void)
 {
-  execute_pre (false);
-  return 0;
+  return TODO_rebuild_alias | execute_pre (false);
 }
 
 static bool
@@ -3933,8 +4050,10 @@ gate_pre (void)
   return flag_tree_pre != 0;
 }
 
-struct tree_opt_pass pass_pre =
+struct gimple_opt_pass pass_pre =
 {
+ {
+  GIMPLE_PASS,
   "pre",                               /* name */
   gate_pre,                            /* gate */
   do_pre,                              /* execute */
@@ -3948,8 +4067,8 @@ struct tree_opt_pass pass_pre =
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   TODO_update_ssa_only_virtuals | TODO_dump_func | TODO_ggc_collect
-  | TODO_verify_ssa, /* todo_flags_finish */
-  0                                    /* letter */
+  | TODO_verify_ssa /* todo_flags_finish */
+ }
 };
 
 
@@ -3958,8 +4077,7 @@ struct tree_opt_pass pass_pre =
 static unsigned int
 execute_fre (void)
 {
-  execute_pre (true);
-  return 0;
+  return execute_pre (true);
 }
 
 static bool
@@ -3968,8 +4086,10 @@ gate_fre (void)
   return flag_tree_fre != 0;
 }
 
-struct tree_opt_pass pass_fre =
+struct gimple_opt_pass pass_fre =
 {
+ {
+  GIMPLE_PASS,
   "fre",                               /* name */
   gate_fre,                            /* gate */
   execute_fre,                         /* execute */
@@ -3981,6 +4101,6 @@ struct tree_opt_pass pass_fre =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa, /* todo_flags_finish */
-  0                                    /* letter */
+  TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */
+ }
 };