OSDN Git Service

* config/ia64/ia64.c (ia64_expand_atomic_op): New.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-pre.c
index 66e2b22..abc2a7e 100644 (file)
@@ -714,7 +714,7 @@ set_equal (value_set_t a, value_set_t b)
 }
 
 /* Replace an instance of EXPR's VALUE with EXPR in SET if it exists,
-   and add it otherwise. */
+   and add it otherwise.  */
 
 static void
 bitmap_value_replace_in_set (bitmap_set_t set, tree expr)
@@ -871,6 +871,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
       return NULL;
 
     case tcc_binary:
+    case tcc_comparison:
       {
        tree oldop1 = TREE_OPERAND (expr, 0);
        tree oldop2 = TREE_OPERAND (expr, 1);
@@ -949,6 +950,10 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
     }
 }
 
+/* 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.  */
+
 static void
 phi_translate_set (value_set_t dest, value_set_t set, basic_block pred,
                   basic_block phiblock)
@@ -1057,6 +1062,7 @@ valid_in_set (value_set_t set, tree expr)
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_binary:
+    case tcc_comparison:
       {
        tree op1 = TREE_OPERAND (expr, 0);
        tree op2 = TREE_OPERAND (expr, 1);
@@ -1077,6 +1083,10 @@ valid_in_set (value_set_t set, tree expr)
       gcc_assert (TREE_CODE (expr) == SSA_NAME);
       return true;
 
+    case tcc_declaration:
+      /* VAR_DECL and PARM_DECL are never anticipatable.  */
+      return false;
+
     default:
       /* No other cases should be encountered.  */
       gcc_unreachable (); 
@@ -1102,8 +1112,9 @@ clean (value_set_t set)
     }
 }
 
-DEF_VEC_MALLOC_P (basic_block);
-sbitmap has_abnormal_preds;
+DEF_VEC_P (basic_block);
+DEF_VEC_ALLOC_P (basic_block, heap);
+static sbitmap has_abnormal_preds;
 
 /* Compute the ANTIC set for BLOCK.
 
@@ -1143,24 +1154,24 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
     ;
   /* If we have one successor, we could have some phi nodes to
      translate through.  */
-  else if (EDGE_COUNT (block->succs) == 1)
+  else if (single_succ_p (block))
     {
-      phi_translate_set (ANTIC_OUT, ANTIC_IN(EDGE_SUCC (block, 0)->dest),
-                        block, EDGE_SUCC (block, 0)->dest);
+      phi_translate_set (ANTIC_OUT, ANTIC_IN(single_succ (block)),
+                        block, single_succ (block));
     }
   /* If we have multiple successors, we take the intersection of all of
      them.  */
   else
     {
-      VEC (basic_block) * worklist;
+      VEC(basic_block, heap) * worklist;
       edge e;
       size_t i;
       basic_block bprime, first;
       edge_iterator ei;
 
-      worklist = VEC_alloc (basic_block, 2);
+      worklist = VEC_alloc (basic_block, heap, EDGE_COUNT (block->succs));
       FOR_EACH_EDGE (e, ei, block->succs)
-       VEC_safe_push (basic_block, worklist, e->dest);
+       VEC_quick_push (basic_block, worklist, e->dest);
       first = VEC_index (basic_block, worklist, 0);
       set_copy (ANTIC_OUT, ANTIC_IN (first));
 
@@ -1177,7 +1188,7 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
              node = next;
            }
        }
-      VEC_free (basic_block, worklist);
+      VEC_free (basic_block, heap, worklist);
     }
 
   /* Generate ANTIC_OUT - TMP_GEN.  */
@@ -1261,7 +1272,7 @@ compute_antic (void)
     fprintf (dump_file, "compute_antic required %d iterations\n", num_iterations);
 }
 
-static VEC(tree_on_heap) *inserted_exprs;
+static VEC(tree,heap) *inserted_exprs;
 /* Find a leader for an expression, or generate one using
    create_expression_by_pieces if it's ANTIC but
    complex.  
@@ -1276,14 +1287,14 @@ find_or_generate_expression (basic_block block, tree expr, tree stmts)
 {
   tree genop = bitmap_find_leader (AVAIL_OUT (block), expr);
 
-  /* If it's still NULL, see if it is a complex expression, and if
-     so, generate it recursively, otherwise, abort, because it's
-     not really .  */
+  /* If it's still NULL, it must be a complex expression, so generate
+     it recursively.  */
   if (genop == NULL)
     {
       genop = VALUE_HANDLE_EXPR_SET (expr)->head->expr;
       gcc_assert (UNARY_CLASS_P (genop)
                  || BINARY_CLASS_P (genop)
+                 || COMPARISON_CLASS_P (genop)
                  || REFERENCE_CLASS_P (genop));
       genop = create_expression_by_pieces (block, genop, stmts);
     }
@@ -1297,7 +1308,7 @@ find_or_generate_expression (basic_block block, tree expr, tree stmts)
    EXPR is the expression to insert (in value form)
    STMTS is a statement list to append the necessary insertions into.
 
-   This function will abort if we hit some value that shouldn't be
+   This function will die if we hit some value that shouldn't be
    ANTIC but is (IE there is no leader for it, or its components).
    This function may also generate expressions that are themselves
    partially or fully redundant.  Those that are will be either made
@@ -1308,83 +1319,99 @@ find_or_generate_expression (basic_block block, tree expr, tree stmts)
 static tree
 create_expression_by_pieces (basic_block block, tree expr, tree stmts)
 {
-  tree name = NULL_TREE;
-  tree newexpr = NULL_TREE;
+  tree temp, name;
+  tree folded, forced_stmts, newexpr;
   tree v;
-  
+  tree_stmt_iterator tsi;
+
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_binary:
+    case tcc_comparison:
       {
-       tree_stmt_iterator tsi;
-       tree genop1, genop2;
-       tree temp;
        tree op1 = TREE_OPERAND (expr, 0);
        tree op2 = TREE_OPERAND (expr, 1);
-       genop1 = find_or_generate_expression (block, op1, stmts);
-       genop2 = find_or_generate_expression (block, op2, stmts);
-       temp = create_tmp_var (TREE_TYPE (expr), "pretmp");
-       add_referenced_tmp_var (temp);
-       newexpr = fold (build (TREE_CODE (expr), TREE_TYPE (expr), 
-                              genop1, genop2));
-       newexpr = build (MODIFY_EXPR, TREE_TYPE (expr),
-                        temp, newexpr);
-       NECESSARY (newexpr) = 0;
-       name = make_ssa_name (temp, newexpr);
-       TREE_OPERAND (newexpr, 0) = name;
-       tsi = tsi_last (stmts);
-       tsi_link_after (&tsi, newexpr, TSI_CONTINUE_LINKING);
-       VEC_safe_push (tree_on_heap, inserted_exprs, newexpr);
-       pre_stats.insertions++;
+       tree genop1 = find_or_generate_expression (block, op1, stmts);
+       tree genop2 = find_or_generate_expression (block, op2, stmts);
+       folded = fold (build (TREE_CODE (expr), TREE_TYPE (expr), 
+                             genop1, genop2));
        break;
       }
+
     case tcc_unary:
       {
-       tree_stmt_iterator tsi;
-       tree genop1;
-       tree temp;
        tree op1 = TREE_OPERAND (expr, 0);
-       genop1 = find_or_generate_expression (block, op1, stmts);
-       temp = create_tmp_var (TREE_TYPE (expr), "pretmp");
-       add_referenced_tmp_var (temp);
-       newexpr = fold (build (TREE_CODE (expr), TREE_TYPE (expr), 
-                              genop1));
-       newexpr = build (MODIFY_EXPR, TREE_TYPE (expr),
-                        temp, newexpr);
-       name = make_ssa_name (temp, newexpr);
-       TREE_OPERAND (newexpr, 0) = name;
-       NECESSARY (newexpr) = 0;
-       tsi = tsi_last (stmts);
-       tsi_link_after (&tsi, newexpr, TSI_CONTINUE_LINKING);
-       VEC_safe_push (tree_on_heap, inserted_exprs, newexpr);
-       pre_stats.insertions++;
-
+       tree genop1 = find_or_generate_expression (block, op1, stmts);
+       folded = fold (build (TREE_CODE (expr), TREE_TYPE (expr), 
+                             genop1));
        break;
       }
+
     default:
       gcc_unreachable ();
-      
     }
-  v = get_value_handle (expr);
-  vn_add (name, v, NULL);
 
-  /* The value may already exist in either NEW_SETS, or AVAIL_OUT, because
+  /* 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);
+
+  /* If we have any intermediate expressions to the value sets, add them
+     to the value sets and chain them on in the instruction stream.  */
+  if (forced_stmts)
+    {
+      tsi = tsi_start (forced_stmts);
+      for (; !tsi_end_p (tsi); tsi_next (&tsi))
+       {
+         tree stmt = tsi_stmt (tsi);
+         tree forcedname = TREE_OPERAND (stmt, 0);
+         tree forcedexpr = TREE_OPERAND (stmt, 1);
+         tree val = vn_lookup_or_add (forcedexpr, NULL);
+         vn_add (forcedname, val, NULL);
+         bitmap_value_replace_in_set (NEW_SETS (block), forcedname);
+         bitmap_value_replace_in_set (AVAIL_OUT (block), forcedname);
+       }
+      tsi = tsi_last (stmts);
+      tsi_link_after (&tsi, forced_stmts, TSI_CONTINUE_LINKING);
+    }
+
+  /* Build and insert the assignment of the end result to the temporary
+     that we will return.  */
+  temp = create_tmp_var (TREE_TYPE (expr), "pretmp");
+  add_referenced_tmp_var (temp);
+  newexpr = build (MODIFY_EXPR, TREE_TYPE (expr), temp, newexpr);
+  name = make_ssa_name (temp, newexpr);
+  TREE_OPERAND (newexpr, 0) = name;
+  NECESSARY (newexpr) = 0;
+  tsi = tsi_last (stmts);
+  tsi_link_after (&tsi, newexpr, TSI_CONTINUE_LINKING);
+  VEC_safe_push (tree, heap, inserted_exprs, newexpr);
+
+  /* Add a value handle to the temporary.
+     The value may already exist in either NEW_SETS, or AVAIL_OUT, because
      we are creating the expression by pieces, and this particular piece of
      the expression may have been represented.  There is no harm in replacing
      here.  */
+  v = get_value_handle (expr);
+  vn_add (name, v, NULL);
   bitmap_value_replace_in_set (NEW_SETS (block), name); 
   bitmap_value_replace_in_set (AVAIL_OUT (block), name);
+
+  pre_stats.insertions++;
   if (dump_file && (dump_flags & TDF_DETAILS))
     {                              
       fprintf (dump_file, "Inserted ");
       print_generic_expr (dump_file, newexpr, 0);
       fprintf (dump_file, " in predecessor %d\n", block->index);
     }
+
   return name;
 }
 
 /* Return the folded version of T if T, when folded, is a gimple
-   min_invariant.  Otherwise, return T. */ 
+   min_invariant.  Otherwise, return T.  */ 
 
 static tree
 fully_constant_expression (tree t)
@@ -1449,6 +1476,7 @@ insert_into_preds_of_block (basic_block block, value_set_node_t node,
       bprime = pred->src;
       eprime = avail[bprime->index];
       if (BINARY_CLASS_P (eprime)
+         || COMPARISON_CLASS_P (eprime)
          || UNARY_CLASS_P (eprime))
        {
          builtexpr = create_expression_by_pieces (bprime,
@@ -1473,7 +1501,7 @@ insert_into_preds_of_block (basic_block block, value_set_node_t node,
   add_referenced_tmp_var (temp);
   temp = create_phi_node (temp, block);
   NECESSARY (temp) = 0; 
-  VEC_safe_push (tree_on_heap, inserted_exprs, temp);
+  VEC_safe_push (treeheap, inserted_exprs, temp);
   FOR_EACH_EDGE (pred, ei, block->preds)
     add_phi_arg (temp, avail[pred->src->index], pred);
   
@@ -1554,7 +1582,7 @@ insert_aux (basic_block block)
                  bitmap_value_replace_in_set (AVAIL_OUT (block), ssa_name (i));
                }
            }
-         if (EDGE_COUNT (block->preds) > 1)
+         if (!single_pred_p (block))
            {
              value_set_node_t node;
              for (node = ANTIC_IN (block)->head;
@@ -1562,6 +1590,7 @@ insert_aux (basic_block block)
                   node = node->next)
                {
                  if (BINARY_CLASS_P (node->expr)
+                     || COMPARISON_CLASS_P (node->expr)
                      || UNARY_CLASS_P (node->expr))
                    {
                      tree *avail;
@@ -1653,7 +1682,7 @@ insert_aux (basic_block block)
                      /* If all edges produce the same value and that value is
                         an invariant, then the PHI has the same value on all
                         edges.  Note this.  */
-                     else if (all_same && eprime 
+                     else if (!cant_insert && all_same && eprime 
                               && is_gimple_min_invariant (eprime)
                               && !is_gimple_min_invariant (val))
                        {
@@ -1729,17 +1758,17 @@ is_undefined_value (tree expr)
    any). They are used when computing the hash value for EXPR.  */
 
 static inline void
-add_to_sets (tree var, tree expr, vuse_optype vuses, bitmap_set_t s1,
+add_to_sets (tree var, tree expr, tree stmt, bitmap_set_t s1,
             bitmap_set_t s2)
 {
-  tree val = vn_lookup_or_add (expr, vuses);
+  tree val = vn_lookup_or_add (expr, stmt);
 
   /* VAR and EXPR may be the same when processing statements for which
      we are not computing value numbers (e.g., non-assignments, or
      statements that make aliased stores).  In those cases, we are
      only interested in making VAR available as its own value.  */
   if (var != expr)
-    vn_add (var, val, NULL);
+    vn_add (var, val, NULL_TREE);
 
   if (s1)
     bitmap_insert_into_set (s1, var);
@@ -1750,43 +1779,69 @@ add_to_sets (tree var, tree expr, vuse_optype vuses, bitmap_set_t s1,
 /* Given a unary or binary expression EXPR, create and return a new
    expression with the same structure as EXPR but with its operands
    replaced with the value handles of each of the operands of EXPR.
-   Insert EXPR's operands into the EXP_GEN set for BLOCK.
 
    VUSES represent the virtual use operands associated with EXPR (if
-   any). They are used when computing the hash value for EXPR.  */
+   any). They are used when computing the hash value for EXPR.
+   Insert EXPR's operands into the EXP_GEN set for BLOCK. */
 
 static inline tree
-create_value_expr_from (tree expr, basic_block block, vuse_optype vuses)
+create_value_expr_from (tree expr, basic_block block, tree stmt)
 {
   int i;
   enum tree_code code = TREE_CODE (expr);
   tree vexpr;
+  alloc_pool pool;
 
   gcc_assert (TREE_CODE_CLASS (code) == tcc_unary
              || TREE_CODE_CLASS (code) == tcc_binary
+             || TREE_CODE_CLASS (code) == tcc_comparison
              || TREE_CODE_CLASS (code) == tcc_reference);
 
   if (TREE_CODE_CLASS (code) == tcc_unary)
-    vexpr = pool_alloc (unary_node_pool);
+    pool = unary_node_pool;
   else if (TREE_CODE_CLASS (code) == tcc_reference)
-    vexpr = pool_alloc (reference_node_pool);
+    pool = reference_node_pool;
   else
-    vexpr = pool_alloc (binary_node_pool);
+    pool = binary_node_pool;
 
+  vexpr = pool_alloc (pool);
   memcpy (vexpr, expr, tree_size (expr));
 
   for (i = 0; i < TREE_CODE_LENGTH (code); i++)
     {
-      tree op = TREE_OPERAND (expr, i);
-      if (op != NULL)
+      tree val, op;
+      
+      op = TREE_OPERAND (expr, i);
+      if (op == NULL_TREE)
+       continue;
+
+      /* If OP is a constant that has overflowed, do not value number
+        this expression.  */
+      if (CONSTANT_CLASS_P (op)
+         && TREE_OVERFLOW (op))
+       {
+         pool_free (pool, vexpr);
+         return NULL;
+       }
+
+      /* Recursively value-numberize reference ops */
+      if (REFERENCE_CLASS_P (op))
        {
-         tree val = vn_lookup_or_add (op, vuses);
-         if (!is_undefined_value (op))
-           value_insert_into_set (EXP_GEN (block), op);
-         if (TREE_CODE (val) == VALUE_HANDLE)
-           TREE_TYPE (val) = TREE_TYPE (TREE_OPERAND (vexpr, i));
-         TREE_OPERAND (vexpr, i) = val;
+         tree tempop = create_value_expr_from (op, block, stmt);
+         op = tempop ? tempop : op;
+         val = vn_lookup_or_add (op, stmt);
        }
+      else       
+       /* Create a value handle for OP and add it to VEXPR.  */
+       val = vn_lookup_or_add (op, NULL);
+
+      if (!is_undefined_value (op))
+       value_insert_into_set (EXP_GEN (block), op);
+
+      if (TREE_CODE (val) == VALUE_HANDLE)
+       TREE_TYPE (val) = TREE_TYPE (TREE_OPERAND (vexpr, i));
+
+      TREE_OPERAND (vexpr, i) = val;
     }
 
   return vexpr;
@@ -1819,9 +1874,8 @@ compute_avail (void)
     {
       if (default_def (param) != NULL)
        {
-         tree val;
          tree def = default_def (param);
-         val = vn_lookup_or_add (def, NULL);
+         vn_lookup_or_add (def, NULL);
          bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR), def);
          bitmap_value_insert_into_set (AVAIL_OUT (ENTRY_BLOCK_PTR), def);
        }
@@ -1866,11 +1920,11 @@ compute_avail (void)
       for (bsi = bsi_start (block); !bsi_end_p (bsi); bsi_next (&bsi))
        {
          stmt_ann_t ann;
-         size_t j;
+         ssa_op_iter iter;
+         tree op;
 
          stmt = bsi_stmt (bsi);
          ann = stmt_ann (stmt);
-         get_stmt_operands (stmt);
 
          /* We are only interested in assignments of the form
             X_i = EXPR, where EXPR represents an "interesting"
@@ -1883,16 +1937,36 @@ compute_avail (void)
            {
              tree lhs = TREE_OPERAND (stmt, 0);
              tree rhs = TREE_OPERAND (stmt, 1);
-             vuse_optype vuses = STMT_VUSE_OPS (stmt);
 
              STRIP_USELESS_TYPE_CONVERSION (rhs);
-             if (TREE_CODE (rhs) == SSA_NAME
-                 || is_gimple_min_invariant (rhs))
+             if (UNARY_CLASS_P (rhs)
+                 || BINARY_CLASS_P (rhs)
+                 || COMPARISON_CLASS_P (rhs)
+                 || REFERENCE_CLASS_P (rhs))
+               {
+                 /* For binary, unary, and reference expressions,
+                    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)
+                   {
+                     add_to_sets (lhs, newt, stmt, TMP_GEN (block),
+                                  AVAIL_OUT (block));
+                     value_insert_into_set (EXP_GEN (block), newt);
+                     continue;
+                   }
+               }
+             else if (TREE_CODE (rhs) == SSA_NAME
+                      || 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, vuses, TMP_GEN (block), 
+                 add_to_sets (lhs, rhs, stmt, TMP_GEN (block), 
                               AVAIL_OUT (block));
                  
                  if (TREE_CODE (rhs) == SSA_NAME
@@ -1900,36 +1974,16 @@ compute_avail (void)
                    value_insert_into_set (EXP_GEN (block), rhs);
                  continue;
                }          
-             else if (UNARY_CLASS_P (rhs) || BINARY_CLASS_P (rhs)
-                      || TREE_CODE (rhs) == INDIRECT_REF)
-               {
-                 /* For binary, unary, and reference expressions,
-                    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);
-                 add_to_sets (lhs, newt, vuses, TMP_GEN (block),
-                              AVAIL_OUT (block));
-                 value_insert_into_set (EXP_GEN (block), newt);
-                 continue;
-               }
            }
 
          /* For any other statement that we don't recognize, simply
             make the names generated by the statement available in
             AVAIL_OUT and TMP_GEN.  */
-         for (j = 0; j < NUM_DEFS (STMT_DEF_OPS (stmt)); j++)
-           {
-             tree def = DEF_OP (STMT_DEF_OPS (stmt), j);
-             add_to_sets (def, def, NULL, TMP_GEN (block),
-                           AVAIL_OUT (block));
-           }
+         FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
+           add_to_sets (op, op, NULL, TMP_GEN (block), AVAIL_OUT (block));
 
-         for (j = 0; j < NUM_USES (STMT_USE_OPS (stmt)); j++)
-           {
-             tree use = USE_OP (STMT_USE_OPS (stmt), j);
-             add_to_sets (use, use, NULL, NULL, AVAIL_OUT (block));
-           }
+         FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
+           add_to_sets (op, op, NULL, NULL , AVAIL_OUT (block));
        }
 
       /* Put the dominator children of BLOCK on the worklist of blocks
@@ -1994,7 +2048,7 @@ eliminate (void)
                    NECESSARY (SSA_NAME_DEF_STMT (sprime)) = 1;
                  pre_stats.eliminations++;
                  propagate_tree_value (rhs_p, sprime);
-                 modify_stmt (stmt);
+                 update_stmt (stmt);
 
                  /* If we removed EH side effects from the statement, clean
                     its EH information.  */
@@ -2016,27 +2070,25 @@ eliminate (void)
    this may be a bit faster, and we may want critical edges kept split.  */
 
 /* If OP's defining statement has not already been determined to be necessary,
-   mark that statement necessary. and place it on the WORKLIST.  */ 
+   mark that statement necessary. Return the stmt, if it is newly
+   necessary.  */ 
 
-static inline void
-mark_operand_necessary (tree op, VEC(tree_on_heap) **worklist)
+static inline tree
+mark_operand_necessary (tree op)
 {
   tree stmt;
-  int ver;
 
   gcc_assert (op);
 
-  ver = SSA_NAME_VERSION (op);
-
   stmt = SSA_NAME_DEF_STMT (op);
   gcc_assert (stmt);
 
   if (NECESSARY (stmt)
       || IS_EMPTY_STMT (stmt))
-    return;
+    return NULL;
 
   NECESSARY (stmt) = 1;
-  VEC_safe_push (tree_on_heap, *worklist, stmt);
+  return stmt;
 }
 
 /* Because we don't follow exactly the standard PRE algorithm, and decide not
@@ -2047,18 +2099,19 @@ mark_operand_necessary (tree op, VEC(tree_on_heap) **worklist)
 static void
 remove_dead_inserted_code (void)
 {
-  VEC (tree_on_heap) *worklist = NULL;
+  VEC(tree,heap) *worklist = NULL;
   int i;
   tree t;
 
-  for (i = 0; VEC_iterate (tree_on_heap, inserted_exprs, i, t); i++)
+  worklist = VEC_alloc (tree, heap, VEC_length (tree, inserted_exprs));
+  for (i = 0; VEC_iterate (tree, inserted_exprs, i, t); i++)
     {
       if (NECESSARY (t))
-       VEC_safe_push (tree_on_heap, worklist, t);
+       VEC_quick_push (tree, worklist, t);
     }
-  while (VEC_length (tree_on_heap, worklist) > 0)
+  while (VEC_length (tree, worklist) > 0)
     {
-      t = VEC_pop (tree_on_heap, worklist);
+      t = VEC_pop (tree, worklist);
       if (TREE_CODE (t) == PHI_NODE)
        {
          /* PHI nodes are somewhat special in that each PHI alternative has
@@ -2068,11 +2121,17 @@ remove_dead_inserted_code (void)
             predecessor block associated with each PHI alternative as
             necessary.  */
          int k;
+
+         VEC_reserve (tree, heap, worklist, PHI_NUM_ARGS (t));
          for (k = 0; k < PHI_NUM_ARGS (t); k++)
             {
              tree arg = PHI_ARG_DEF (t, k);
              if (TREE_CODE (arg) == SSA_NAME)
-               mark_operand_necessary (arg, &worklist);
+               {
+                 arg = mark_operand_necessary (arg);
+                 if (arg)
+                   VEC_quick_push (tree, worklist, arg);
+               }
            }
        }
       else
@@ -2083,18 +2142,20 @@ remove_dead_inserted_code (void)
          ssa_op_iter iter;
          tree use;
 
-         get_stmt_operands (t);
-
          /* The operands of V_MAY_DEF expressions are also needed as they
             represent potential definitions that may reach this
             statement (V_MAY_DEF operands allow us to follow def-def 
             links).  */
 
          FOR_EACH_SSA_TREE_OPERAND (use, t, iter, SSA_OP_ALL_USES)
-           mark_operand_necessary (use, &worklist);
+           {
+             tree n = mark_operand_necessary (use);
+             if (n)
+               VEC_safe_push (tree, heap, worklist, n);
+           }
        }
     }
-  for (i = 0; VEC_iterate (tree_on_heap, inserted_exprs, i, t); i++)
+  for (i = 0; VEC_iterate (tree, inserted_exprs, i, t); i++)
     {
       if (!NECESSARY (t))
        {
@@ -2106,7 +2167,7 @@ remove_dead_inserted_code (void)
            }
          if (TREE_CODE (t) == PHI_NODE)
            {
-             remove_phi_node (t, NULL, bb_for_stmt (t));
+             remove_phi_node (t, NULL);
            }
          else
            {
@@ -2115,7 +2176,7 @@ remove_dead_inserted_code (void)
            }
        }
     }
-  VEC_free (tree_on_heap, worklist);
+  VEC_free (treeheap, worklist);
 }
 /* Initialize data structures used by PRE.  */
 
@@ -2138,9 +2199,9 @@ init_pre (bool do_fre)
      ENTRY_BLOCK_PTR (FIXME, if ENTRY_BLOCK_PTR had an index number
      different than -1 we wouldn't have to hack this.  tree-ssa-dce.c
      needs a similar change).  */
-  if (EDGE_COUNT (EDGE_SUCC (ENTRY_BLOCK_PTR, 0)->dest->preds) > 1)
-    if (!(EDGE_SUCC (ENTRY_BLOCK_PTR, 0)->flags & EDGE_ABNORMAL))
-      split_edge (EDGE_SUCC (ENTRY_BLOCK_PTR, 0));
+  if (!single_pred_p (single_succ (ENTRY_BLOCK_PTR)))
+    if (!(single_succ_edge (ENTRY_BLOCK_PTR)->flags & EDGE_ABNORMAL))
+      split_edge (single_succ_edge (ENTRY_BLOCK_PTR));
 
   FOR_ALL_BB (bb)
     bb->aux = xcalloc (1, sizeof (struct bb_value_sets));
@@ -2182,7 +2243,7 @@ fini_pre (bool do_fre)
   basic_block bb;
   unsigned int i;
 
-  VEC_free (tree_on_heap, inserted_exprs);
+  VEC_free (treeheap, inserted_exprs);
   bitmap_obstack_release (&grand_bitmap_obstack);
   free_alloc_pool (value_set_pool);
   free_alloc_pool (bitmap_set_pool);
@@ -2273,10 +2334,10 @@ execute_pre (bool do_fre)
 
   if (dump_file && (dump_flags & TDF_STATS))
     {
-      fprintf (dump_file, "Insertions:%d\n", pre_stats.insertions);
-      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);
+      fprintf (dump_file, "Insertions: %d\n", pre_stats.insertions);
+      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);
     }
   
   bsi_commit_edge_inserts ();
@@ -2323,7 +2384,7 @@ struct tree_opt_pass pass_pre =
 /* Gate and execute functions for FRE.  */
 
 static void
-do_fre (void)
+execute_fre (void)
 {
   execute_pre (true);
 }
@@ -2338,7 +2399,7 @@ struct tree_opt_pass pass_fre =
 {
   "fre",                               /* name */
   gate_fre,                            /* gate */
-  do_fre,                              /* execute */
+  execute_fre,                         /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */