OSDN Git Service

PR c/42312
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-pre.c
index 18c442e..a3e7ad8 100644 (file)
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "cfgloop.h"
 #include "tree-ssa-sccvn.h"
+#include "tree-scalar-evolution.h"
 #include "params.h"
 #include "dbgcnt.h"
 
@@ -134,7 +135,7 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Representation of expressions on value numbers:
 
-   Expressions consisting of  value numbers are represented the same
+   Expressions consisting of value numbers are represented the same
    way as our VN internally represents them, with an additional
    "pre_expr" wrapping around them in order to facilitate storing all
    of the expressions in the same sets.  */
@@ -377,6 +378,9 @@ typedef struct bb_bitmap_sets
      the current iteration.  */
   bitmap_set_t new_sets;
 
+  /* A cache for value_dies_in_block_x.  */
+  bitmap expr_dies;
+
   /* True if we have visited this block during ANTIC calculation.  */
   unsigned int visited:1;
 
@@ -392,14 +396,11 @@ 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 BB_VISITED(BB) ((bb_value_sets_t) ((BB)->aux))->visited
+#define EXPR_DIES(BB)  ((bb_value_sets_t) ((BB)->aux))->expr_dies
+#define BB_VISITED(BB) ((bb_value_sets_t) ((BB)->aux))->visited
 #define BB_DEFERRED(BB) ((bb_value_sets_t) ((BB)->aux))->deferred
 
 
-/* Maximal set of values, used to initialize the ANTIC problem, which
-   is an intersection problem.  */
-static bitmap_set_t maximal_set;
-
 /* Basic block list in postorder.  */
 static int *postorder;
 
@@ -906,26 +907,42 @@ print_pre_expr (FILE *outfile, const pre_expr expr)
             VEC_iterate (vn_reference_op_s, ref->operands, i, vro);
             i++)
          {
+           bool closebrace = false;
            if (vro->opcode != SSA_NAME
                && TREE_CODE_CLASS (vro->opcode) != tcc_declaration)
-             fprintf (outfile, "%s ", tree_code_name [vro->opcode]);
+             {
+               fprintf (outfile, "%s", tree_code_name [vro->opcode]);
+               if (vro->op0)
+                 {
+                   fprintf (outfile, "<");
+                   closebrace = true;
+                 }
+             }
            if (vro->op0)
              {
-               if (vro->op1)
-                 fprintf (outfile, "<");
                print_generic_expr (outfile, vro->op0, 0);
                if (vro->op1)
                  {
                    fprintf (outfile, ",");
                    print_generic_expr (outfile, vro->op1, 0);
                  }
-               if (vro->op1)
-                 fprintf (outfile, ">");
+               if (vro->op2)
+                 {
+                   fprintf (outfile, ",");
+                   print_generic_expr (outfile, vro->op2, 0);
+                 }
              }
+           if (closebrace)
+               fprintf (outfile, ">");
            if (i != VEC_length (vn_reference_op_s, ref->operands) - 1)
              fprintf (outfile, ",");
          }
        fprintf (outfile, "}");
+       if (ref->vuse)
+         {
+           fprintf (outfile, "@");
+           print_generic_expr (outfile, ref->vuse, 0);
+         }
       }
       break;
     }
@@ -1139,7 +1156,7 @@ fully_constant_expression (pre_expr e)
            }
          case tcc_reference:
            if (nary->opcode != REALPART_EXPR
-               && nary->opcode != IMAGPART_EXPR 
+               && nary->opcode != IMAGPART_EXPR
                && nary->opcode != VIEW_CONVERT_EXPR)
              return e;
            /* Fallthrough.  */
@@ -1225,51 +1242,81 @@ do_unary:
   return e;
 }
 
-/* Translate the vuses in the VUSES vector backwards through phi nodes
-   in PHIBLOCK, so that they have the value they would have in
-   BLOCK. */
+/* Translate the VUSE backwards through phi nodes in PHIBLOCK, so that
+   it has the value it would have in BLOCK.  Set *SAME_VALID to true
+   in case the new vuse doesn't change the value id of the OPERANDS.  */
 
-static VEC(tree, gc) *
-translate_vuses_through_block (VEC (tree, gc) *vuses,
-                              basic_block phiblock,
-                              basic_block block)
+static tree
+translate_vuse_through_block (VEC (vn_reference_op_s, heap) *operands,
+                             alias_set_type set, tree type, tree vuse,
+                             basic_block phiblock,
+                             basic_block block, bool *same_valid)
 {
-  tree oldvuse;
-  VEC(tree, gc) *result = NULL;
-  int i;
+  gimple phi = SSA_NAME_DEF_STMT (vuse);
+  ao_ref ref;
+  edge e = NULL;
+  bool use_oracle;
+
+  *same_valid = true;
+
+  if (gimple_bb (phi) != phiblock)
+    return vuse;
+
+  use_oracle = ao_ref_init_from_vn_reference (&ref, set, type, operands);
+
+  /* Use the alias-oracle to find either the PHI node in this block,
+     the first VUSE used in this block that is equivalent to vuse or
+     the first VUSE which definition in this block kills the value.  */
+  if (gimple_code (phi) == GIMPLE_PHI)
+    e = find_edge (block, phiblock);
+  else if (use_oracle)
+    while (!stmt_may_clobber_ref_p_1 (phi, &ref))
+      {
+       vuse = gimple_vuse (phi);
+       phi = SSA_NAME_DEF_STMT (vuse);
+       if (gimple_bb (phi) != phiblock)
+         return vuse;
+       if (gimple_code (phi) == GIMPLE_PHI)
+         {
+           e = find_edge (block, phiblock);
+           break;
+         }
+      }
+  else
+    return NULL_TREE;
 
-  for (i = 0; VEC_iterate (tree, vuses, i, oldvuse); i++)
+  if (e)
     {
-      gimple phi = SSA_NAME_DEF_STMT (oldvuse);
-      if (gimple_code (phi) == GIMPLE_PHI
-         && gimple_bb (phi) == phiblock)
+      if (use_oracle)
        {
-         edge e = find_edge (block, gimple_bb (phi));
-         if (e)
-           {
-             tree def = PHI_ARG_DEF (phi, e->dest_idx);
-             if (def != oldvuse)
-               {
-                 if (!result)
-                   result = VEC_copy (tree, gc, vuses);
-                 VEC_replace (tree, result, i, def);
-               }
-           }
+         bitmap visited = NULL;
+         /* Try to find a vuse that dominates this phi node by skipping
+            non-clobbering statements.  */
+         vuse = get_continuation_for_phi (phi, &ref, &visited);
+         if (visited)
+           BITMAP_FREE (visited);
        }
+      else
+       vuse = NULL_TREE;
+      if (!vuse)
+       {
+         /* If we didn't find any, the value ID can't stay the same,
+            but return the translated vuse.  */
+         *same_valid = false;
+         vuse = PHI_ARG_DEF (phi, e->dest_idx);
+       }
+      /* ??? We would like to return vuse here as this is the canonical
+         upmost vdef that this reference is associated with.  But during
+        insertion of the references into the hash tables we only ever
+        directly insert with their direct gimple_vuse, hence returning
+        something else would make us not find the other expression.  */
+      return PHI_ARG_DEF (phi, e->dest_idx);
     }
 
-  /* We avoid creating a new copy of the vuses unless something
-     actually changed, so result can be NULL.  */
-  if (result)
-    {
-      sort_vuses (result);
-      return result;
-    }
-  return vuses;
-
+  return NULL_TREE;
 }
 
-/* Like find_leader, but checks for the value existing in SET1 *or*
+/* Like bitmap_find_leader, but checks for the value existing in SET1 *or*
    SET2.  This is used to avoid making a set consisting of the union
    of PA_IN and ANTIC_IN during insert.  */
 
@@ -1296,23 +1343,7 @@ get_expr_type (const pre_expr e)
     case CONSTANT:
       return TREE_TYPE (PRE_EXPR_CONSTANT (e));
     case REFERENCE:
-      {
-       vn_reference_op_t vro;
-
-       gcc_assert (PRE_EXPR_REFERENCE (e)->operands);
-       vro = VEC_index (vn_reference_op_s,
-                        PRE_EXPR_REFERENCE (e)->operands,
-                        0);
-       /* We don't store type along with COMPONENT_REF because it is
-          always the same as FIELD_DECL's type.  */
-       if (!vro->type)
-         {
-           gcc_assert (vro->opcode == COMPONENT_REF);
-           return TREE_TYPE (vro->op0);
-         }
-       return vro->type;
-      }
-
+      return PRE_EXPR_REFERENCE (e)->type;
     case NARY:
       return PRE_EXPR_NARY (e)->type;
     }
@@ -1538,15 +1569,16 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
       {
        vn_reference_t ref = PRE_EXPR_REFERENCE (expr);
        VEC (vn_reference_op_s, heap) *operands = ref->operands;
-       VEC (tree, gc) *vuses = ref->vuses;
-       VEC (tree, gc) *newvuses = vuses;
+       tree vuse = ref->vuse;
+       tree newvuse = vuse;
        VEC (vn_reference_op_s, heap) *newoperands = NULL;
-       bool changed = false;
-       unsigned int i;
+       bool changed = false, same_valid = true;
+       unsigned int i, j;
        vn_reference_op_t operand;
        vn_reference_t newref;
 
-       for (i = 0; VEC_iterate (vn_reference_op_s, operands, i, operand); i++)
+       for (i = 0, j = 0;
+            VEC_iterate (vn_reference_op_s, operands, i, operand); i++, j++)
          {
            pre_expr opresult;
            pre_expr leader;
@@ -1593,6 +1625,9 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
                else if (!opresult)
                  break;
              }
+           /* We can't possibly insert these.  */
+           else if (op1 && !is_gimple_min_invariant (op1))
+             break;
            changed |= op1 != oldop1;
            if (op2 && TREE_CODE (op2) == SSA_NAME)
              {
@@ -1610,6 +1645,9 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
                else if (!opresult)
                  break;
              }
+           /* We can't possibly insert these.  */
+           else if (op2 && !is_gimple_min_invariant (op2))
+             break;
            changed |= op2 != oldop2;
 
            if (!newoperands)
@@ -1621,7 +1659,13 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
            newop.op0 = op0;
            newop.op1 = op1;
            newop.op2 = op2;
-           VEC_replace (vn_reference_op_s, newoperands, i, &newop);
+           VEC_replace (vn_reference_op_s, newoperands, j, &newop);
+           /* If it transforms from an SSA_NAME to an address, fold with
+              a preceding indirect reference.  */
+           if (j > 0 && op0 && TREE_CODE (op0) == ADDR_EXPR
+               && VEC_index (vn_reference_op_s,
+                             newoperands, j - 1)->opcode == INDIRECT_REF)
+             vn_reference_fold_indirect (&newoperands, &j);
          }
        if (i != VEC_length (vn_reference_op_s, operands))
          {
@@ -1630,15 +1674,26 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
            return NULL;
          }
 
-       newvuses = translate_vuses_through_block (vuses, phiblock, pred);
-       changed |= newvuses != vuses;
+       if (vuse)
+         {
+           newvuse = translate_vuse_through_block (newoperands,
+                                                   ref->set, ref->type,
+                                                   vuse, phiblock, pred,
+                                                   &same_valid);
+           if (newvuse == NULL_TREE)
+             {
+               VEC_free (vn_reference_op_s, heap, newoperands);
+               return NULL;
+             }
+         }
 
-       if (changed)
+       if (changed || newvuse != vuse)
          {
            unsigned int new_val_id;
            pre_expr constant;
 
-           tree result = vn_reference_lookup_pieces (newvuses,
+           tree result = vn_reference_lookup_pieces (newvuse, ref->set,
+                                                     ref->type,
                                                      newoperands,
                                                      &newref, true);
            if (newref)
@@ -1666,10 +1721,17 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
              }
            else
              {
-               new_val_id = get_next_value_id ();
-               VEC_safe_grow_cleared (bitmap_set_t, heap, value_expressions,
-                                      get_max_value_id() + 1);
-               newref = vn_reference_insert_pieces (newvuses,
+               if (changed || !same_valid)
+                 {
+                   new_val_id = get_next_value_id ();
+                   VEC_safe_grow_cleared (bitmap_set_t, heap,
+                                          value_expressions,
+                                          get_max_value_id() + 1);
+                 }
+               else
+                 new_val_id = ref->value_id;
+               newref = vn_reference_insert_pieces (newvuse, ref->set,
+                                                    ref->type,
                                                     newoperands,
                                                     result, new_val_id);
                newoperands = NULL;
@@ -1844,24 +1906,73 @@ bitmap_find_leader (bitmap_set_t set, unsigned int val, gimple stmt)
 static bool
 value_dies_in_block_x (pre_expr expr, basic_block block)
 {
-  int i;
-  tree vuse;
-  VEC (tree, gc) *vuses = PRE_EXPR_REFERENCE (expr)->vuses;
+  tree vuse = PRE_EXPR_REFERENCE (expr)->vuse;
+  vn_reference_t refx = PRE_EXPR_REFERENCE (expr);
+  gimple def;
+  gimple_stmt_iterator gsi;
+  unsigned id = get_expression_id (expr);
+  bool res = false;
+  ao_ref ref;
 
-  /* 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++)
+  if (!vuse)
+    return false;
+
+  /* Lookup a previously calculated result.  */
+  if (EXPR_DIES (block)
+      && bitmap_bit_p (EXPR_DIES (block), id * 2))
+    return bitmap_bit_p (EXPR_DIES (block), id * 2 + 1);
+
+  /* A memory expression {e, VUSE} dies in the block if there is a
+     statement that may clobber e.  If, starting statement walk from the
+     top of the basic block, a statement uses VUSE there can be no kill
+     inbetween that use and the original statement that loaded {e, VUSE},
+     so we can stop walking.  */
+  ref.base = NULL_TREE;
+  for (gsi = gsi_start_bb (block); !gsi_end_p (gsi); gsi_next (&gsi))
     {
-      gimple def = SSA_NAME_DEF_STMT (vuse);
+      tree def_vuse, def_vdef;
+      def = gsi_stmt (gsi);
+      def_vuse = gimple_vuse (def);
+      def_vdef = gimple_vdef (def);
 
-      if (gimple_bb (def) != block)
-       continue;
-      if (gimple_code (def) == GIMPLE_PHI)
+      /* Not a memory statement.  */
+      if (!def_vuse)
        continue;
-      return true;
+
+      /* Not a may-def.  */
+      if (!def_vdef)
+       {
+         /* A load with the same VUSE, we're done.  */
+         if (def_vuse == vuse)
+           break;
+
+         continue;
+       }
+
+      /* Init ref only if we really need it.  */
+      if (ref.base == NULL_TREE
+         && !ao_ref_init_from_vn_reference (&ref, refx->set, refx->type,
+                                            refx->operands))
+       {
+         res = true;
+         break;
+       }
+      /* If the statement may clobber expr, it dies.  */
+      if (stmt_may_clobber_ref_p_1 (def, &ref))
+       {
+         res = true;
+         break;
+       }
     }
-  return false;
+
+  /* Remember the result.  */
+  if (!EXPR_DIES (block))
+    EXPR_DIES (block) = BITMAP_ALLOC (&grand_bitmap_obstack);
+  bitmap_set_bit (EXPR_DIES (block), id * 2);
+  if (res)
+    bitmap_set_bit (EXPR_DIES (block), id * 2 + 1);
+
+  return res;
 }
 
 
@@ -1923,8 +2034,7 @@ vro_valid_in_sets (bitmap_set_t set1, bitmap_set_t set2,
    ONLY SET2 CAN BE NULL.
    This means that we have a leader for each part of the expression
    (if it consists of values), or the expression is an SSA_NAME.
-   For loads/calls, we also see if the vuses are killed in this block.
-*/
+   For loads/calls, we also see if the vuse is killed in this block.  */
 
 static bool
 valid_in_sets (bitmap_set_t set1, bitmap_set_t set2, pre_expr expr,
@@ -1968,6 +2078,15 @@ valid_in_sets (bitmap_set_t set1, bitmap_set_t set2, pre_expr expr,
            if (!vro_valid_in_sets (set1, set2, vro))
              return false;
          }
+       if (ref->vuse)
+         {
+           gimple def_stmt = SSA_NAME_DEF_STMT (ref->vuse);
+           if (!gimple_nop_p (def_stmt)
+               && gimple_bb (def_stmt) != block
+               && !dominated_by_p (CDI_DOMINATORS,
+                                   block, gimple_bb (def_stmt)))
+             return false;
+         }
        return !value_dies_in_block_x (expr, block);
       }
     default:
@@ -2113,49 +2232,45 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
     {
       VEC(basic_block, heap) * worklist;
       size_t i;
-      basic_block bprime, first;
+      basic_block bprime, first = NULL;
 
       worklist = VEC_alloc (basic_block, heap, EDGE_COUNT (block->succs));
       FOR_EACH_EDGE (e, ei, block->succs)
-       VEC_quick_push (basic_block, worklist, e->dest);
-      first = VEC_index (basic_block, worklist, 0);
-
-      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);
+         if (!first
+             && BB_VISITED (e->dest))
+           first = e->dest;
+         else if (BB_VISITED (e->dest))
+           VEC_quick_push (basic_block, worklist, e->dest);
        }
-      else
+
+      /* Of multiple successors we have to have visited one already.  */
+      if (!first)
        {
-         if (!BB_VISITED (first))
-           bitmap_set_copy (ANTIC_OUT, maximal_set);
-         else
-           bitmap_set_copy (ANTIC_OUT, ANTIC_IN (first));
+         SET_BIT (changed_blocks, block->index);
+         BB_VISITED (block) = 0;
+         BB_DEFERRED (block) = 1;
+         changed = true;
+         VEC_free (basic_block, heap, worklist);
+         goto maybe_dump_sets;
        }
 
-      for (i = 1; VEC_iterate (basic_block, worklist, i, bprime); i++)
+      if (phi_nodes (first))
+       phi_translate_set (ANTIC_OUT, ANTIC_IN (first), block, first);
+      else
+       bitmap_set_copy (ANTIC_OUT, ANTIC_IN (first));
+
+      for (i = 0; VEC_iterate (basic_block, worklist, i, bprime); i++)
        {
          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);
+             phi_translate_set (tmp, ANTIC_IN (bprime), block, bprime);
              bitmap_set_and (ANTIC_OUT, tmp);
              bitmap_set_free (tmp);
            }
          else
-           {
-             if (!BB_VISITED (bprime))
-               bitmap_set_and (ANTIC_OUT, maximal_set);
-             else
-               bitmap_set_and (ANTIC_OUT, ANTIC_IN (bprime));
-           }
+           bitmap_set_and (ANTIC_OUT, ANTIC_IN (bprime));
        }
       VEC_free (basic_block, heap, worklist);
     }
@@ -2469,19 +2584,8 @@ can_value_number_call (gimple stmt)
   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 (gimple stmt)
-{
-  return (is_gimple_assign (stmt)
-         && (gimple_assign_rhs_code (stmt) == FILTER_EXPR
-             || gimple_assign_rhs_code (stmt) == EXC_PTR_EXPR));
-}
-
-/* Return true if OP is a tree which we can perform PRE on
-   on.  This may not match the operations we can value number, but in
+/* Return true if OP is a tree which we can perform PRE on.
+   This may not match the operations we can value number, but in
    a perfect world would.  */
 
 static bool
@@ -2502,6 +2606,7 @@ can_PRE_operation (tree op)
    for performing quick dead code elimination of insertions we made
    that didn't turn out to be necessary.   */
 static VEC(gimple,heap) *inserted_exprs;
+static bitmap inserted_phi_names;
 
 /* Pool allocated fake store expressions are placed onto this
    worklist, which, after performing dead code elimination, is walked
@@ -2551,6 +2656,36 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
        return folded;
       }
       break;
+    case TARGET_MEM_REF:
+      {
+       vn_reference_op_t nextop = VEC_index (vn_reference_op_s, ref->operands,
+                                             *operand);
+       pre_expr op0expr;
+       tree genop0 = NULL_TREE;
+       tree baseop = create_component_ref_by_pieces_1 (block, ref, operand,
+                                                       stmts, domstmt);
+       if (!baseop)
+         return NULL_TREE;
+       if (currop->op0)
+         {
+           op0expr = get_or_alloc_expr_for (currop->op0);
+           genop0 = find_or_generate_expression (block, op0expr,
+                                                 stmts, domstmt);
+           if (!genop0)
+             return NULL_TREE;
+         }
+       if (DECL_P (baseop))
+         return build6 (TARGET_MEM_REF, currop->type,
+                        baseop, NULL_TREE,
+                        genop0, currop->op1, currop->op2,
+                        unshare_expr (nextop->op1));
+       else
+         return build6 (TARGET_MEM_REF, currop->type,
+                        NULL_TREE, baseop,
+                        genop0, currop->op1, currop->op2,
+                        unshare_expr (nextop->op1));
+      }
+      break;
     case ADDR_EXPR:
       if (currop->op0)
        {
@@ -2629,7 +2764,8 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
        pre_expr op1expr;
        tree genop2 = currop->op1;
        pre_expr op2expr;
-       tree genop3;
+       tree genop3 = currop->op2;
+       pre_expr op3expr;
        genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
                                                   stmts, domstmt);
        if (!genop0)
@@ -2646,8 +2782,17 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
            if (!genop2)
              return NULL_TREE;
          }
-
-       genop3 = currop->op2;
+       if (genop3)
+         {
+           tree elmt_type = TREE_TYPE (TREE_TYPE (genop0));
+           genop3 = size_binop (EXACT_DIV_EXPR, genop3,
+                                size_int (TYPE_ALIGN_UNIT (elmt_type)));
+           op3expr = get_or_alloc_expr_for (genop3);
+           genop3 = find_or_generate_expression (block, op3expr, stmts,
+                                                 domstmt);
+           if (!genop3)
+             return NULL_TREE;
+         }
        return build4 (currop->opcode, currop->type, genop0, genop1,
                       genop2, genop3);
       }
@@ -2806,8 +2951,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
                             gimple_seq *stmts, gimple domstmt, tree type)
 {
   tree temp, name;
-  tree folded, newexpr;
-  gimple_seq forced_stmts;
+  tree folded;
+  gimple_seq forced_stmts = NULL;
   unsigned int value_id;
   gimple_stmt_iterator gsi;
   tree exprtype = type ? type : get_expr_type (expr);
@@ -2853,7 +2998,7 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
                genop2 = fold_convert (sizetype, genop2);
              else
                genop2 = fold_convert (TREE_TYPE (nary->op[1]), genop2);
-             
+
              folded = fold_build2 (nary->opcode, nary->type,
                                    genop1, genop2);
            }
@@ -2879,13 +3024,16 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
     default:
       return NULL_TREE;
     }
-  folded = fold_convert (exprtype, folded);
+
+  if (!useless_type_conversion_p (exprtype, TREE_TYPE (folded)))
+    folded = fold_convert (exprtype, folded);
+
   /* Force the generated expression to be a sequence of GIMPLE
      statements.
      We have to call unshare_expr because force_gimple_operand may
      modify the tree we pass to it.  */
-  newexpr = force_gimple_operand (unshare_expr (folded), &forced_stmts,
-                                 false, NULL);
+  folded = force_gimple_operand (unshare_expr (folded), &forced_stmts,
+                                false, NULL);
 
   /* If we have any intermediate expressions to the value sets, add them
      to the value sets and chain them in the instruction stream.  */
@@ -2929,7 +3077,7 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
       || TREE_CODE (exprtype) == VECTOR_TYPE)
     DECL_GIMPLE_REG_P (temp) = 1;
 
-  newstmt = gimple_build_assign (temp, newexpr);
+  newstmt = gimple_build_assign (temp, folded);
   name = make_ssa_name (temp, newstmt);
   gimple_assign_set_lhs (newstmt, name);
   gimple_set_plf (newstmt, NECESSARY, false);
@@ -2966,6 +3114,62 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
 }
 
 
+/* Returns true if we want to inhibit the insertions of PHI nodes
+   for the given EXPR for basic block BB (a member of a loop).
+   We want to do this, when we fear that the induction variable we
+   create might inhibit vectorization.  */
+
+static bool
+inhibit_phi_insertion (basic_block bb, pre_expr expr)
+{
+  vn_reference_t vr = PRE_EXPR_REFERENCE (expr);
+  VEC (vn_reference_op_s, heap) *ops = vr->operands;
+  vn_reference_op_t op;
+  unsigned i;
+
+  /* If we aren't going to vectorize we don't inhibit anything.  */
+  if (!flag_tree_vectorize)
+    return false;
+
+  /* Otherwise we inhibit the insertion when the address of the
+     memory reference is a simple induction variable.  In other
+     cases the vectorizer won't do anything anyway (either it's
+     loop invariant or a complicated expression).  */
+  for (i = 0; VEC_iterate (vn_reference_op_s, ops, i, op); ++i)
+    {
+      switch (op->opcode)
+       {
+       case ARRAY_REF:
+       case ARRAY_RANGE_REF:
+         if (TREE_CODE (op->op0) != SSA_NAME)
+           break;
+         /* Fallthru.  */
+       case SSA_NAME:
+         {
+           basic_block defbb = gimple_bb (SSA_NAME_DEF_STMT (op->op0));
+           affine_iv iv;
+           /* Default defs are loop invariant.  */
+           if (!defbb)
+             break;
+           /* Defined outside this loop, also loop invariant.  */
+           if (!flow_bb_inside_loop_p (bb->loop_father, defbb))
+             break;
+           /* If it's a simple induction variable inhibit insertion,
+              the vectorizer might be interested in this one.  */
+           if (simple_iv (bb->loop_father, bb->loop_father,
+                          op->op0, &iv, true))
+             return true;
+           /* No simple IV, vectorizer can't do anything, hence no
+              reason to inhibit the transformation for this operand.  */
+           break;
+         }
+       default:
+         break;
+       }
+    }
+  return false;
+}
+
 /* Insert the to-be-made-available values of expression EXPRNUM for each
    predecessor, stored in AVAIL, into the predecessors of BLOCK, and
    merge the result with a phi node, given the same value number as
@@ -2996,8 +3200,7 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
     }
 
   /* Make sure we aren't creating an induction variable.  */
-  if (block->loop_depth > 0 && EDGE_COUNT (block->preds) == 2
-      && expr->kind != REFERENCE)
+  if (block->loop_depth > 0 && EDGE_COUNT (block->preds) == 2)
     {
       bool firstinsideloop = false;
       bool secondinsideloop = false;
@@ -3006,7 +3209,9 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
       secondinsideloop = flow_bb_inside_loop_p (block->loop_father,
                                                EDGE_PRED (block, 1)->src);
       /* Induction variables only have one edge inside the loop.  */
-      if (firstinsideloop ^ secondinsideloop)
+      if ((firstinsideloop ^ secondinsideloop)
+         && (expr->kind != REFERENCE
+             || inhibit_phi_insertion (block, expr)))
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "Skipping insertion of phi for partial redundancy: Looks like an induction variable\n");
@@ -3052,7 +3257,7 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
          if (!useless_type_conversion_p (type, TREE_TYPE (constant)))
            {
              tree builtexpr = fold_convert (type, constant);
-             if (!is_gimple_min_invariant (builtexpr)) 
+             if (!is_gimple_min_invariant (builtexpr))
                {
                  tree forcedexpr = force_gimple_operand (builtexpr,
                                                          &stmts, true,
@@ -3147,15 +3352,18 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
   VN_INFO_GET (gimple_phi_result (phi))->valnum = gimple_phi_result (phi);
   VN_INFO (gimple_phi_result (phi))->value_id = val;
   VEC_safe_push (gimple, heap, inserted_exprs, phi);
+  bitmap_set_bit (inserted_phi_names,
+                 SSA_NAME_VERSION (gimple_phi_result (phi)));
   FOR_EACH_EDGE (pred, ei, block->preds)
     {
       pre_expr ae = avail[pred->src->index];
       gcc_assert (get_expr_type (ae) == type
                  || useless_type_conversion_p (type, get_expr_type (ae)));
       if (ae->kind == CONSTANT)
-       add_phi_arg (phi, PRE_EXPR_CONSTANT (ae), pred);
+       add_phi_arg (phi, PRE_EXPR_CONSTANT (ae), pred, UNKNOWN_LOCATION);
       else
-       add_phi_arg (phi, PRE_EXPR_NAME (avail[pred->src->index]), pred);
+       add_phi_arg (phi, PRE_EXPR_NAME (avail[pred->src->index]), pred,
+                    UNKNOWN_LOCATION);
     }
 
   newphi = get_or_alloc_expr_for_name (gimple_phi_result (phi));
@@ -3234,6 +3442,7 @@ do_regular_insertion (basic_block block, basic_block dom)
          pre_expr eprime = NULL;
          edge_iterator ei;
          pre_expr edoubleprime = NULL;
+         bool do_insertion = false;
 
          val = get_expr_value_id (expr);
          if (bitmap_set_contains_value (PHI_GEN (block), val))
@@ -3285,6 +3494,10 @@ do_regular_insertion (basic_block block, basic_block dom)
                {
                  avail[bprime->index] = edoubleprime;
                  by_some = true;
+                 /* We want to perform insertions to remove a redundancy on
+                    a path in the CFG we want to optimize for speed.  */
+                 if (optimize_edge_for_speed_p (pred))
+                   do_insertion = true;
                  if (first_s == NULL)
                    first_s = edoubleprime;
                  else if (!pre_expr_eq (first_s, edoubleprime))
@@ -3295,7 +3508,8 @@ do_regular_insertion (basic_block block, basic_block dom)
             already existing along every predecessor, and
             it's defined by some predecessor, it is
             partially redundant.  */
-         if (!cant_insert && !all_same && by_some && dbg_cnt (treepre_insert))
+         if (!cant_insert && !all_same && by_some && do_insertion
+             && dbg_cnt (treepre_insert))
            {
              if (insert_into_preds_of_block (block, get_expression_id (expr),
                                              avail))
@@ -3507,11 +3721,7 @@ insert (void)
 }
 
 
-/* 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.  */
+/* Add OP to EXP_GEN (block), and possibly to the maximal set.  */
 
 static void
 add_to_exp_gen (basic_block block, tree op)
@@ -3523,9 +3733,6 @@ add_to_exp_gen (basic_block block, tree op)
        return;
       result = get_or_alloc_expr_for_name (op);
       bitmap_value_insert_into_set (EXP_GEN (block), result);
-      if (TREE_CODE (op) != SSA_NAME
-         || gimple_code (SSA_NAME_DEF_STMT (op)) != GIMPLE_PHI)
-       bitmap_value_insert_into_set (maximal_set, result);
     }
 }
 
@@ -3544,6 +3751,19 @@ make_values_for_phi (gimple phi, basic_block block)
       add_to_value (get_expr_value_id (e), e);
       bitmap_insert_into_set (PHI_GEN (block), e);
       bitmap_value_insert_into_set (AVAIL_OUT (block), e);
+      if (!in_fre)
+       {
+         unsigned i;
+         for (i = 0; i < gimple_phi_num_args (phi); ++i)
+           {
+             tree arg = gimple_phi_arg_def (phi, i);
+             if (TREE_CODE (arg) == SSA_NAME)
+               {
+                 e = get_or_alloc_expr_for_name (arg);
+                 add_to_value (get_expr_value_id (e), e);
+               }
+           }
+       }
     }
 }
 
@@ -3564,46 +3784,25 @@ compute_avail (void)
   basic_block block, son;
   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);
-       param;
-       param = TREE_CHAIN (param))
-    {
-      if (gimple_default_def (cfun, param) != NULL)
-       {
-         tree def = gimple_default_def (cfun, param);
-         pre_expr e = get_or_alloc_expr_for_name (def);
+  unsigned i;
 
-         add_to_value (get_expr_value_id (e), e);
-         if (!in_fre)
-           {
-             bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR), e);
-             bitmap_value_insert_into_set (maximal_set, e);
-           }
-         bitmap_value_insert_into_set (AVAIL_OUT (ENTRY_BLOCK_PTR), e);
-       }
-    }
-
-  /* Likewise for the static chain decl. */
-  if (cfun->static_chain_decl)
+  /* We pretend that default definitions are defined in the entry block.
+     This includes function arguments and the static chain decl.  */
+  for (i = 1; i < num_ssa_names; ++i)
     {
-      param = cfun->static_chain_decl;
-      if (gimple_default_def (cfun, param) != NULL)
-       {
-         tree def = gimple_default_def (cfun, param);
-         pre_expr e = get_or_alloc_expr_for_name (def);
+      tree name = ssa_name (i);
+      pre_expr e;
+      if (!name
+         || !SSA_NAME_IS_DEFAULT_DEF (name)
+         || has_zero_uses (name)
+         || !is_gimple_reg (name))
+       continue;
 
-         add_to_value (get_expr_value_id (e), e);
-         if (!in_fre)
-           {
-             bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR), e);
-             bitmap_value_insert_into_set (maximal_set, e);
-           }
-         bitmap_value_insert_into_set (AVAIL_OUT (ENTRY_BLOCK_PTR), e);
-       }
+      e = get_or_alloc_expr_for_name (name);
+      add_to_value (get_expr_value_id (e), e);
+      if (!in_fre)
+       bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR), e);
+      bitmap_value_insert_into_set (AVAIL_OUT (ENTRY_BLOCK_PTR), e);
     }
 
   /* Allocate the worklist.  */
@@ -3680,7 +3879,8 @@ compute_avail (void)
                  continue;
 
                copy_reference_ops_from_call (stmt, &ops);
-               vn_reference_lookup_pieces (shared_vuses_from_stmt (stmt),
+               vn_reference_lookup_pieces (gimple_vuse (stmt), 0,
+                                           gimple_expr_type (stmt),
                                            ops, &ref, false);
                VEC_free (vn_reference_op_s, heap, ops);
                if (!ref)
@@ -3705,11 +3905,7 @@ compute_avail (void)
                get_or_alloc_expression_id (result);
                add_to_value (get_expr_value_id (result), result);
                if (!in_fre)
-                 {
-                   bitmap_value_insert_into_set (EXP_GEN (block),
-                                                 result);
-                   bitmap_value_insert_into_set (maximal_set, result);
-                 }
+                 bitmap_value_insert_into_set (EXP_GEN (block), result);
                continue;
              }
 
@@ -3719,8 +3915,6 @@ compute_avail (void)
                switch (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)))
                  {
                  case tcc_unary:
-                   if (is_exception_related (stmt))
-                     continue;
                  case tcc_binary:
                  case tcc_comparison:
                    {
@@ -3756,8 +3950,8 @@ compute_avail (void)
                      vn_reference_op_t vro;
 
                      vn_reference_lookup (gimple_assign_rhs1 (stmt),
-                                          shared_vuses_from_stmt (stmt),
-                                          false, &ref);
+                                          gimple_vuse (stmt),
+                                          true, &ref);
                      if (!ref)
                        continue;
 
@@ -3791,10 +3985,7 @@ compute_avail (void)
                get_or_alloc_expression_id (result);
                add_to_value (get_expr_value_id (result), result);
                if (!in_fre)
-                 {
-                   bitmap_value_insert_into_set (EXP_GEN (block), result);
-                   bitmap_value_insert_into_set (maximal_set, result);
-                 }
+                 bitmap_value_insert_into_set (EXP_GEN (block), result);
 
                continue;
              }
@@ -3850,16 +4041,18 @@ do_SCCVN_insertion (gimple stmt, tree ssa_vn)
 static unsigned int
 eliminate (void)
 {
+  VEC (gimple, heap) *to_remove = NULL;
   basic_block b;
   unsigned int todo = 0;
+  gimple_stmt_iterator gsi;
+  gimple stmt;
+  unsigned i;
 
   FOR_EACH_BB (b)
     {
-      gimple_stmt_iterator i;
-
-      for (i = gsi_start_bb (b); !gsi_end_p (i);)
+      for (gsi = gsi_start_bb (b); !gsi_end_p (gsi); gsi_next (&gsi))
        {
-         gimple stmt = gsi_stmt (i);
+         stmt = gsi_stmt (gsi);
 
          /* Lookup the RHS of the expression, see if we have an
             available computation for it.  If so, replace the RHS with
@@ -3899,8 +4092,10 @@ eliminate (void)
                 value is constant, use that constant.  */
              if (!sprime && is_gimple_min_invariant (VN_INFO (lhs)->valnum))
                {
-                 sprime = fold_convert (TREE_TYPE (lhs),
-                                        VN_INFO (lhs)->valnum);
+                 sprime = VN_INFO (lhs)->valnum;
+                 if (!useless_type_conversion_p (TREE_TYPE (lhs),
+                                                 TREE_TYPE (sprime)))
+                   sprime = fold_convert (TREE_TYPE (lhs), sprime);
 
                  if (dump_file && (dump_flags & TDF_DETAILS))
                    {
@@ -3912,10 +4107,9 @@ eliminate (void)
                      print_gimple_stmt (dump_file, stmt, 0, 0);
                    }
                  pre_stats.eliminations++;
-                 propagate_tree_value_into_stmt (&i, sprime);
-                 stmt = gsi_stmt (i);
+                 propagate_tree_value_into_stmt (&gsi, sprime);
+                 stmt = gsi_stmt (gsi);
                  update_stmt (stmt);
-                 gsi_next (&i);
                  continue;
                }
 
@@ -3961,8 +4155,8 @@ eliminate (void)
                    sprime = fold_convert (gimple_expr_type (stmt), sprime);
 
                  pre_stats.eliminations++;
-                 propagate_tree_value_into_stmt (&i, sprime);
-                 stmt = gsi_stmt (i);
+                 propagate_tree_value_into_stmt (&gsi, sprime);
+                 stmt = gsi_stmt (gsi);
                  update_stmt (stmt);
 
                  /* If we removed EH side effects from the statement, clean
@@ -3987,45 +4181,20 @@ eliminate (void)
              tree rhs = gimple_assign_rhs1 (stmt);
              tree val;
              val = vn_reference_lookup (gimple_assign_lhs (stmt),
-                                        shared_vuses_from_stmt (stmt),
-                                        true, NULL);
+                                        gimple_vuse (stmt), true, NULL);
              if (TREE_CODE (rhs) == SSA_NAME)
                rhs = VN_INFO (rhs)->valnum;
              if (val
                  && operand_equal_p (val, rhs, 0))
                {
-                 def_operand_p def;
-                 use_operand_p use;
-                 vuse_vec_p usevec;
-                 ssa_op_iter oi;
-                 imm_use_iterator ui;
-                 gimple use_stmt;
-
                  if (dump_file && (dump_flags & TDF_DETAILS))
                    {
-                     fprintf (dump_file, "Deleted dead store ");
+                     fprintf (dump_file, "Deleted redundant store ");
                      print_gimple_stmt (dump_file, stmt, 0, 0);
                    }
 
-                 /* Propagate all may-uses to the uses of their defs.  */
-                 FOR_EACH_SSA_VDEF_OPERAND (def, usevec, stmt, oi)
-                   {
-                     tree vuse = VUSE_ELEMENT_VAR (*usevec, 0);
-                     tree vdef = DEF_FROM_PTR (def);
-
-                     /* If the vdef is used in an abnormal PHI node we
-                        have to propagate that flag to the vuse as well.  */
-                     if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (vdef))
-                       SSA_NAME_OCCURS_IN_ABNORMAL_PHI (vuse) = 1;
-
-                     FOR_EACH_IMM_USE_STMT (use_stmt, ui, vdef)
-                       FOR_EACH_IMM_USE_ON_STMT (use, ui)
-                         SET_USE (use, vuse);
-                   }
-
-                 gsi_remove (&i, true);
-                 release_defs (stmt);
-                 continue;
+                 /* Queue stmt for removal.  */
+                 VEC_safe_push (gimple, heap, to_remove, stmt);
                }
            }
          /* Visit COND_EXPRs and fold the comparison with the
@@ -4052,11 +4221,136 @@ eliminate (void)
                  todo = TODO_cleanup_cfg;
                }
            }
+         /* Visit indirect calls and turn them into direct calls if
+            possible.  */
+         if (gimple_code (stmt) == GIMPLE_CALL
+             && TREE_CODE (gimple_call_fn (stmt)) == SSA_NAME)
+           {
+             tree fn = VN_INFO (gimple_call_fn (stmt))->valnum;
+             if (TREE_CODE (fn) == ADDR_EXPR
+                 && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
+               {
+                 if (dump_file && (dump_flags & TDF_DETAILS))
+                   {
+                     fprintf (dump_file, "Replacing call target with ");
+                     print_generic_expr (dump_file, fn, 0);
+                     fprintf (dump_file, " in ");
+                     print_gimple_stmt (dump_file, stmt, 0, 0);
+                   }
 
-         gsi_next (&i);
+                 gimple_call_set_fn (stmt, fn);
+                 update_stmt (stmt);
+                 if (maybe_clean_or_replace_eh_stmt (stmt, stmt))
+                   {
+                     bitmap_set_bit (need_eh_cleanup,
+                                     gimple_bb (stmt)->index);
+                     if (dump_file && (dump_flags & TDF_DETAILS))
+                       fprintf (dump_file, "  Removed EH side effects.\n");
+                   }
+
+                 /* Changing an indirect call to a direct call may
+                    have exposed different semantics.  This may
+                    require an SSA update.  */
+                 todo |= TODO_update_ssa_only_virtuals;
+               }
+           }
+       }
+
+      for (gsi = gsi_start_phis (b); !gsi_end_p (gsi);)
+       {
+         gimple stmt, phi = gsi_stmt (gsi);
+         tree sprime = NULL_TREE, res = PHI_RESULT (phi);
+         pre_expr sprimeexpr, resexpr;
+         gimple_stmt_iterator gsi2;
+
+         /* We want to perform redundant PHI elimination.  Do so by
+            replacing the PHI with a single copy if possible.
+            Do not touch inserted, single-argument or virtual PHIs.  */
+         if (gimple_phi_num_args (phi) == 1
+             || !is_gimple_reg (res)
+             || bitmap_bit_p (inserted_phi_names, SSA_NAME_VERSION (res)))
+           {
+             gsi_next (&gsi);
+             continue;
+           }
+
+         resexpr = get_or_alloc_expr_for_name (res);
+         sprimeexpr = bitmap_find_leader (AVAIL_OUT (b),
+                                          get_expr_value_id (resexpr), NULL);
+         if (sprimeexpr)
+           {
+             if (sprimeexpr->kind == CONSTANT)
+               sprime = PRE_EXPR_CONSTANT (sprimeexpr);
+             else if (sprimeexpr->kind == NAME)
+               sprime = PRE_EXPR_NAME (sprimeexpr);
+             else
+               gcc_unreachable ();
+           }
+         if (!sprimeexpr
+             || sprime == res)
+           {
+             gsi_next (&gsi);
+             continue;
+           }
+
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "Replaced redundant PHI node defining ");
+             print_generic_expr (dump_file, res, 0);
+             fprintf (dump_file, " with ");
+             print_generic_expr (dump_file, sprime, 0);
+             fprintf (dump_file, "\n");
+           }
+
+         remove_phi_node (&gsi, false);
+
+         if (!useless_type_conversion_p (TREE_TYPE (res), TREE_TYPE (sprime)))
+           sprime = fold_convert (TREE_TYPE (res), sprime);
+         stmt = gimple_build_assign (res, sprime);
+         SSA_NAME_DEF_STMT (res) = stmt;
+         if (TREE_CODE (sprime) == SSA_NAME)
+           gimple_set_plf (SSA_NAME_DEF_STMT (sprime),
+                           NECESSARY, true);
+         gsi2 = gsi_after_labels (b);
+         gsi_insert_before (&gsi2, stmt, GSI_NEW_STMT);
+         /* Queue the copy for eventual removal.  */
+         VEC_safe_push (gimple, heap, to_remove, stmt);
+         pre_stats.eliminations++;
        }
     }
 
+  /* We cannot remove stmts during BB walk, especially not release SSA
+     names there as this confuses the VN machinery.  The stmts ending
+     up in to_remove are either stores or simple copies.  */
+  for (i = 0; VEC_iterate (gimple, to_remove, i, stmt); ++i)
+    {
+      tree lhs = gimple_assign_lhs (stmt);
+      use_operand_p use_p;
+      gimple use_stmt;
+
+      /* If there is a single use only, propagate the equivalency
+        instead of keeping the copy.  */
+      if (TREE_CODE (lhs) == SSA_NAME
+         && single_imm_use (lhs, &use_p, &use_stmt)
+         && may_propagate_copy (USE_FROM_PTR (use_p),
+                                gimple_assign_rhs1 (stmt)))
+       {
+         SET_USE (use_p, gimple_assign_rhs1 (stmt));
+         update_stmt (use_stmt);
+       }
+
+      /* If this is a store or a now unused copy, remove it.  */
+      if (TREE_CODE (lhs) != SSA_NAME
+         || has_zero_uses (lhs))
+       {
+         gsi = gsi_for_stmt (stmt);
+         unlink_stmt_vdef (stmt);
+         gsi_remove (&gsi, true);
+         release_defs (stmt);
+       }
+    }
+  VEC_free (gimple, heap, to_remove);
+
   return todo;
 }
 
@@ -4168,8 +4462,10 @@ remove_dead_inserted_code (void)
          if (gimple_code (t) == GIMPLE_PHI)
            remove_phi_node (&gsi, true);
          else
-           gsi_remove (&gsi, true);
-         release_defs (t);
+           {
+             gsi_remove (&gsi, true);
+             release_defs (t);
+           }
        }
     }
   VEC_free (gimple, heap, worklist);
@@ -4211,6 +4507,7 @@ init_pre (bool do_fre)
   calculate_dominance_info (CDI_DOMINATORS);
 
   bitmap_obstack_initialize (&grand_bitmap_obstack);
+  inserted_phi_names = BITMAP_ALLOC (&grand_bitmap_obstack);
   phi_translate_table = htab_create (5110, expr_pred_trans_hash,
                                     expr_pred_trans_eq, free);
   expression_to_id = htab_create (num_ssa_names * 3,
@@ -4228,7 +4525,6 @@ init_pre (bool do_fre)
       TMP_GEN (bb) = bitmap_set_new ();
       AVAIL_OUT (bb) = bitmap_set_new ();
     }
-  maximal_set = in_fre ? NULL : bitmap_set_new ();
 
   need_eh_cleanup = BITMAP_ALLOC (NULL);
 }
@@ -4275,11 +4571,11 @@ fini_pre (bool do_fre)
    only wants to do full redundancy elimination.  */
 
 static unsigned int
-execute_pre (bool do_fre ATTRIBUTE_UNUSED)
+execute_pre (bool do_fre)
 {
   unsigned int todo = 0;
 
-  do_partial_partial = optimize > 2;
+  do_partial_partial = optimize > 2 && optimize_function_for_speed_p (cfun);
 
   /* This has to happen before SCCVN runs because
      loop_optimizer_init may create new phis, etc.  */
@@ -4293,10 +4589,11 @@ execute_pre (bool do_fre ATTRIBUTE_UNUSED)
          remove_dead_inserted_code ();
          loop_optimizer_finalize ();
        }
-      
+
       return 0;
     }
   init_pre (do_fre);
+  scev_initialize ();
 
 
   /* Collect and value number expressions computed in each basic block.  */
@@ -4309,10 +4606,9 @@ execute_pre (bool do_fre ATTRIBUTE_UNUSED)
       FOR_ALL_BB (bb)
        {
          print_bitmap_set (dump_file, EXP_GEN (bb), "exp_gen", bb->index);
-         print_bitmap_set (dump_file, TMP_GEN (bb), "tmp_gen",
-                                 bb->index);
-         print_bitmap_set (dump_file, AVAIL_OUT (bb), "avail_out",
-                                 bb->index);
+         print_bitmap_set (dump_file, PHI_GEN (bb), "phi_gen", bb->index);
+         print_bitmap_set (dump_file, TMP_GEN (bb), "tmp_gen", bb->index);
+         print_bitmap_set (dump_file, AVAIL_OUT (bb), "avail_out", bb->index);
        }
     }
 
@@ -4347,6 +4643,7 @@ execute_pre (bool do_fre ATTRIBUTE_UNUSED)
   if (!do_fre)
     remove_dead_inserted_code ();
 
+  scev_finalize ();
   fini_pre (do_fre);
 
   return todo;
@@ -4357,14 +4654,13 @@ execute_pre (bool do_fre ATTRIBUTE_UNUSED)
 static unsigned int
 do_pre (void)
 {
-  return TODO_rebuild_alias | execute_pre (false);
+  return execute_pre (false);
 }
 
 static bool
 gate_pre (void)
 {
-  /* PRE tends to generate bigger code.  */
-  return flag_tree_pre != 0 && optimize_function_for_speed_p (cfun);
+  return flag_tree_pre != 0;
 }
 
 struct gimple_opt_pass pass_pre =
@@ -4379,10 +4675,10 @@ struct gimple_opt_pass pass_pre =
   0,                                   /* static_pass_number */
   TV_TREE_PRE,                         /* tv_id */
   PROP_no_crit_edges | PROP_cfg
-    | PROP_ssa | PROP_alias,           /* properties_required */
+    | PROP_ssa,                                /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
+  TODO_rebuild_alias,                  /* todo_flags_start */
   TODO_update_ssa_only_virtuals | TODO_dump_func | TODO_ggc_collect
   | TODO_verify_ssa /* todo_flags_finish */
  }
@@ -4414,7 +4710,7 @@ struct gimple_opt_pass pass_fre =
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   TV_TREE_FRE,                         /* tv_id */
-  PROP_cfg | PROP_ssa | PROP_alias,    /* properties_required */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */