OSDN Git Service

2009-01-06 Thomas Koenig <tkoenig@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / tree-outof-ssa.c
index c65a31a..82cc0ff 100644 (file)
@@ -1,12 +1,12 @@
 /* Convert a program in SSA form into Normal form.
-   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Andrew Macleod <amacleod@redhat.com>
 
 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,
@@ -15,9 +15,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"
@@ -120,6 +119,7 @@ create_temp (tree t)
     }
   DECL_ARTIFICIAL (tmp) = DECL_ARTIFICIAL (t);
   DECL_IGNORED_P (tmp) = DECL_IGNORED_P (t);
+  DECL_GIMPLE_REG_P (tmp) = DECL_GIMPLE_REG_P (t);
   add_referenced_var (tmp);
 
   /* add_referenced_var will create the annotation and set up some
@@ -128,6 +128,8 @@ create_temp (tree t)
   set_symbol_mem_tag (tmp, symbol_mem_tag (t));
   if (is_call_clobbered (t))
     mark_call_clobbered (tmp, var_ann (t)->escape_mask);
+  if (bitmap_bit_p (gimple_call_used_vars (cfun), DECL_UID (t)))
+    bitmap_set_bit (gimple_call_used_vars (cfun), DECL_UID (tmp));
 
   return tmp;
 }
@@ -139,9 +141,9 @@ create_temp (tree t)
 static void
 insert_copy_on_edge (edge e, tree dest, tree src)
 {
-  tree copy;
+  gimple copy;
 
-  copy = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (dest), dest, src);
+  copy = gimple_build_assign (dest, src);
   set_is_used (dest);
 
   if (TREE_CODE (src) == ADDR_EXPR)
@@ -155,11 +157,11 @@ insert_copy_on_edge (edge e, tree dest, tree src)
               "Inserting a copy on edge BB%d->BB%d :",
               e->src->index,
               e->dest->index);
-      print_generic_expr (dump_file, copy, dump_flags);
+      print_gimple_stmt (dump_file, copy, 0, dump_flags);
       fprintf (dump_file, "\n");
     }
 
-  bsi_insert_on_edge (e, copy);
+  gsi_insert_on_edge (e, copy);
 }
 
 
@@ -313,15 +315,17 @@ eliminate_name (elim_graph g, tree T)
 static void
 eliminate_build (elim_graph g, basic_block B)
 {
-  tree phi;
   tree T0, Ti;
   int p0, pi;
+  gimple_stmt_iterator gsi;
 
   clear_elim_graph (g);
   
-  for (phi = phi_nodes (B); phi; phi = PHI_CHAIN (phi))
+  for (gsi = gsi_start_phis (B); !gsi_end_p (gsi); gsi_next (&gsi))
     {
-      T0 = var_to_partition_to_var (g->map, PHI_RESULT (phi));
+      gimple phi = gsi_stmt (gsi);
+
+      T0 = var_to_partition_to_var (g->map, gimple_phi_result (phi));
       
       /* Ignore results which are not in partitions.  */
       if (T0 == NULL_TREE)
@@ -549,7 +553,7 @@ assign_vars (var_map map)
    If the stmt is changed, return true.  */ 
 
 static inline bool
-replace_use_variable (var_map map, use_operand_p p, tree *expr)
+replace_use_variable (var_map map, use_operand_p p, gimple *expr)
 {
   tree new_var;
   tree var = USE_FROM_PTR (p);
@@ -560,11 +564,7 @@ replace_use_variable (var_map map, use_operand_p p, tree *expr)
       int version = SSA_NAME_VERSION (var);
       if (expr[version])
         {
-         tree new_expr = GIMPLE_STMT_OPERAND (expr[version], 1);
-         SET_USE (p, new_expr);
-
-         /* Clear the stmt's RHS, or GC might bite us.  */
-         GIMPLE_STMT_OPERAND (expr[version], 1) = NULL_TREE;
+         SET_USE (p, gimple_assign_rhs_to_tree (expr[version]));
          return true;
        }
     }
@@ -606,26 +606,70 @@ replace_def_variable (var_map map, def_operand_p def_p, tree *expr)
 }
 
 
-/* Remove any PHI node which is a virtual PHI.  */
+/* Remove each argument from PHI.  If an arg was the last use of an SSA_NAME, 
+   check to see if this allows another PHI node to be removed.  */
+
+static void
+remove_gimple_phi_args (gimple phi)
+{
+  use_operand_p arg_p;
+  ssa_op_iter iter;
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "Removing Dead PHI definition: ");
+      print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
+    }
+
+  FOR_EACH_PHI_ARG (arg_p, phi, iter, SSA_OP_USE)
+    {
+      tree arg = USE_FROM_PTR (arg_p);
+      if (TREE_CODE (arg) == SSA_NAME)
+        {
+         /* Remove the reference to the existing argument.  */
+         SET_USE (arg_p, NULL_TREE);
+         if (has_zero_uses (arg))
+           {
+             gimple stmt;
+             gimple_stmt_iterator gsi;
+
+             stmt = SSA_NAME_DEF_STMT (arg);
+
+             /* Also remove the def if it is a PHI node.  */
+             if (gimple_code (stmt) == GIMPLE_PHI)
+               {
+                 remove_gimple_phi_args (stmt);
+                 gsi = gsi_for_stmt (stmt);
+                 remove_phi_node (&gsi, true);
+               }
+
+           }
+       }
+    }
+}
+
+/* Remove any PHI node which is a virtual PHI, or a PHI with no uses.  */
 
 static void
-eliminate_virtual_phis (void)
+eliminate_useless_phis (void)
 {
   basic_block bb;
-  tree phi, next;
+  gimple_stmt_iterator gsi;
+  tree result;
 
   FOR_EACH_BB (bb)
     {
-      for (phi = phi_nodes (bb); phi; phi = next)
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
         {
-         next = PHI_CHAIN (phi);
-         if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
+         gimple phi = gsi_stmt (gsi);
+         result = gimple_phi_result (phi);
+         if (!is_gimple_reg (SSA_NAME_VAR (result)))
            {
 #ifdef ENABLE_CHECKING
-             int i;
-             /* There should be no arguments of this PHI which are in
-                the partition list, or we get incorrect results.  */
-             for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+             size_t i;
+             /* There should be no arguments which are not virtual, or the
+                results will be incorrect.  */
+             for (i = 0; i < gimple_phi_num_args (phi); i++)
                {
                  tree arg = PHI_ARG_DEF (phi, i);
                  if (TREE_CODE (arg) == SSA_NAME 
@@ -634,12 +678,23 @@ eliminate_virtual_phis (void)
                      fprintf (stderr, "Argument of PHI is not virtual (");
                      print_generic_expr (stderr, arg, TDF_SLIM);
                      fprintf (stderr, "), but the result is :");
-                     print_generic_stmt (stderr, phi, TDF_SLIM);
+                     print_gimple_stmt (stderr, phi, 0, TDF_SLIM);
                      internal_error ("SSA corruption");
                    }
                }
 #endif
-             remove_phi_node (phi, NULL_TREE, true);
+             remove_phi_node (&gsi, true);
+           }
+          else
+           {
+             /* Also remove real PHIs with no uses.  */
+             if (has_zero_uses (result))
+               {
+                 remove_gimple_phi_args (phi);
+                 remove_phi_node (&gsi, true);
+               }
+             else
+               gsi_next (&gsi);
            }
        }
     }
@@ -653,13 +708,13 @@ eliminate_virtual_phis (void)
    variable.  */
 
 static void
-rewrite_trees (var_map map, tree *values)
+rewrite_trees (var_map map, gimple *values)
 {
   elim_graph g;
   basic_block bb;
-  block_stmt_iterator si;
+  gimple_stmt_iterator gsi;
   edge e;
-  tree phi;
+  gimple_seq phi;
   bool changed;
  
 #ifdef ENABLE_CHECKING
@@ -668,14 +723,14 @@ rewrite_trees (var_map map, tree *values)
      create incorrect code.  */
   FOR_EACH_BB (bb)
     {
-      tree phi;
-      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
-         tree T0 = var_to_partition_to_var (map, PHI_RESULT (phi));
+         gimple phi = gsi_stmt (gsi);
+         tree T0 = var_to_partition_to_var (map, gimple_phi_result (phi));
          if (T0 == NULL_TREE)
            {
-             int i;
-             for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+             size_t i;
+             for (i = 0; i < gimple_phi_num_args (phi); i++)
                {
                  tree arg = PHI_ARG_DEF (phi, i);
 
@@ -685,7 +740,7 @@ rewrite_trees (var_map map, tree *values)
                      fprintf (stderr, "Argument of PHI is in a partition :(");
                      print_generic_expr (stderr, arg, TDF_SLIM);
                      fprintf (stderr, "), but the result is not :");
-                     print_generic_stmt (stderr, phi, TDF_SLIM);
+                     print_gimple_stmt (stderr, phi, 0, TDF_SLIM);
                      internal_error ("SSA corruption");
                    }
                }
@@ -699,21 +754,18 @@ rewrite_trees (var_map map, tree *values)
   g->map = map;
   FOR_EACH_BB (bb)
     {
-      for (si = bsi_start (bb); !bsi_end_p (si); )
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
        {
-         tree stmt = bsi_stmt (si);
+         gimple stmt = gsi_stmt (gsi);
          use_operand_p use_p, copy_use_p;
          def_operand_p def_p;
          bool remove = false, is_copy = false;
          int num_uses = 0;
-         stmt_ann_t ann;
          ssa_op_iter iter;
 
-         ann = stmt_ann (stmt);
          changed = false;
 
-         if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT 
-             && (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == SSA_NAME))
+         if (gimple_assign_copy_p (stmt))
            is_copy = true;
 
          copy_use_p = NULL_USE_OPERAND_P;
@@ -757,9 +809,14 @@ rewrite_trees (var_map map, tree *values)
 
          /* Remove any stmts marked for removal.  */
          if (remove)
-           bsi_remove (&si, true);
+           gsi_remove (&gsi, true);
          else
-           bsi_next (&si);
+           {
+             if (changed)
+               if (maybe_clean_or_replace_eh_stmt (stmt, stmt))
+                 gimple_purge_dead_eh_edges (bb);
+             gsi_next (&gsi);
+           }
        }
 
       phi = phi_nodes (bb);
@@ -777,7 +834,7 @@ rewrite_trees (var_map map, tree *values)
 /* These are the local work structures used to determine the best place to 
    insert the copies that were placed on edges by the SSA->normal pass..  */
 static VEC(edge,heap) *edge_leader;
-static VEC(tree,heap) *stmt_list;
+static VEC(gimple_seq,heap) *stmt_list;
 static bitmap leader_has_match = NULL;
 static edge leader_match = NULL;
 
@@ -796,22 +853,19 @@ same_stmt_list_p (edge e)
 /* Return TRUE if S1 and S2 are equivalent copies.  */
 
 static inline bool
-identical_copies_p (tree s1, tree s2)
+identical_copies_p (const_gimple s1, const_gimple s2)
 {
 #ifdef ENABLE_CHECKING
-  gcc_assert (TREE_CODE (s1) == GIMPLE_MODIFY_STMT);
-  gcc_assert (TREE_CODE (s2) == GIMPLE_MODIFY_STMT);
-  gcc_assert (DECL_P (GIMPLE_STMT_OPERAND (s1, 0)));
-  gcc_assert (DECL_P (GIMPLE_STMT_OPERAND (s2, 0)));
+  gcc_assert (is_gimple_assign (s1));
+  gcc_assert (is_gimple_assign (s2));
+  gcc_assert (DECL_P (gimple_assign_lhs (s1)));
+  gcc_assert (DECL_P (gimple_assign_lhs (s2)));
 #endif
 
-  if (GIMPLE_STMT_OPERAND (s1, 0) != GIMPLE_STMT_OPERAND (s2, 0))
+  if (gimple_assign_lhs (s1) != gimple_assign_lhs (s2))
     return false;
 
-  s1 = GIMPLE_STMT_OPERAND (s1, 1);
-  s2 = GIMPLE_STMT_OPERAND (s2, 1);
-
-  if (s1 != s2)
+  if (gimple_assign_rhs1 (s1) != gimple_assign_rhs1 (s2))
     return false;
 
   return true;
@@ -822,24 +876,21 @@ identical_copies_p (tree s1, tree s2)
    contain the same sequence of copies.  */
 
 static inline bool 
-identical_stmt_lists_p (edge e1, edge e2)
+identical_stmt_lists_p (const_edge e1, const_edge e2)
 {
-  tree t1 = PENDING_STMT (e1);
-  tree t2 = PENDING_STMT (e2);
-  tree_stmt_iterator tsi1, tsi2;
-
-  gcc_assert (TREE_CODE (t1) == STATEMENT_LIST);
-  gcc_assert (TREE_CODE (t2) == STATEMENT_LIST);
+  gimple_seq t1 = PENDING_STMT (e1);
+  gimple_seq t2 = PENDING_STMT (e2);
+  gimple_stmt_iterator gsi1, gsi2;
 
-  for (tsi1 = tsi_start (t1), tsi2 = tsi_start (t2);
-       !tsi_end_p (tsi1) && !tsi_end_p (tsi2); 
-       tsi_next (&tsi1), tsi_next (&tsi2))
+  for (gsi1 = gsi_start (t1), gsi2 = gsi_start (t2);
+       !gsi_end_p (gsi1) && !gsi_end_p (gsi2); 
+       gsi_next (&gsi1), gsi_next (&gsi2))
     {
-      if (!identical_copies_p (tsi_stmt (tsi1), tsi_stmt (tsi2)))
+      if (!identical_copies_p (gsi_stmt (gsi1), gsi_stmt (gsi2)))
         break;
     }
 
-  if (!tsi_end_p (tsi1) || ! tsi_end_p (tsi2))
+  if (!gsi_end_p (gsi1) || !gsi_end_p (gsi2))
     return false;
 
   return true;
@@ -852,7 +903,7 @@ static void
 init_analyze_edges_for_bb (void)
 {
   edge_leader = VEC_alloc (edge, heap, 25);
-  stmt_list = VEC_alloc (tree, heap, 25);
+  stmt_list = VEC_alloc (gimple_seq, heap, 25);
   leader_has_match = BITMAP_ALLOC (NULL);
 }
 
@@ -863,10 +914,166 @@ static void
 fini_analyze_edges_for_bb (void)
 {
   VEC_free (edge, heap, edge_leader);
-  VEC_free (tree, heap, stmt_list);
+  VEC_free (gimple_seq, heap, stmt_list);
   BITMAP_FREE (leader_has_match);
 }
 
+/* A helper function to be called via walk_tree.  Return DATA if it is
+  contained in subtree TP.  */
+static tree
+contains_tree_r (tree * tp, int *walk_subtrees, void *data)
+{
+  if (*tp == data)
+    {
+      *walk_subtrees = 0;
+      return (tree) data;
+    }
+  else
+    return NULL_TREE;
+}
+
+/* A threshold for the number of insns contained in the latch block.
+   It is used to prevent blowing the loop with too many copies from
+   the latch.  */
+#define MAX_STMTS_IN_LATCH 2
+
+/* Return TRUE if the stmts on SINGLE-EDGE can be moved to the
+   body of the loop.  This should be permitted only if SINGLE-EDGE is a
+   single-basic-block latch edge and thus cleaning the latch will help
+   to create a single-basic-block loop.  Otherwise return FALSE.  */
+
+static bool
+process_single_block_loop_latch (edge single_edge)
+{
+  gimple_seq stmts;
+  basic_block b_exit, b_pheader, b_loop = single_edge->src;
+  edge_iterator ei;
+  edge e;
+  gimple_stmt_iterator gsi, gsi_exit;
+  gimple_stmt_iterator tsi;
+  tree expr;
+  gimple stmt;
+  unsigned int count = 0;
+
+  if (single_edge == NULL || (single_edge->dest != single_edge->src)
+      || (EDGE_COUNT (b_loop->succs) != 2)
+      || (EDGE_COUNT (b_loop->preds) != 2))
+    return false;
+
+  /* Get the stmts on the latch edge.  */
+  stmts = PENDING_STMT (single_edge);
+
+  /* Find the successor edge which is not the latch edge.  */
+  FOR_EACH_EDGE (e, ei, b_loop->succs) 
+   if (e->dest != b_loop)
+    break;
+
+  b_exit = e->dest;
+
+  /* Check that the exit block has only the loop as a predecessor,
+     and that there are no pending stmts on that edge as well.   */
+  if (EDGE_COUNT (b_exit->preds) != 1 || PENDING_STMT (e))
+    return false;
+
+  /* Find the predecessor edge which is not the latch edge.  */
+  FOR_EACH_EDGE (e, ei, b_loop->preds) 
+   if (e->src != b_loop)
+    break;
+
+  b_pheader = e->src;
+
+  if (b_exit == b_pheader || b_exit == b_loop || b_pheader == b_loop)
+    return false;
+
+  gsi_exit = gsi_after_labels (b_exit);
+
+  /* Get the last stmt in the loop body.  */
+  gsi = gsi_last_bb (single_edge->src);
+  stmt = gsi_stmt (gsi);
+
+  if (gimple_code (stmt) != GIMPLE_COND)
+    return false;
+
+
+  expr = build2 (gimple_cond_code (stmt), boolean_type_node,
+                 gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
+  /* Iterate over the insns on the latch and count them.  */
+  for (tsi = gsi_start (stmts); !gsi_end_p (tsi); gsi_next (&tsi))
+    {
+      gimple stmt1 = gsi_stmt (tsi);
+      tree var;
+
+      count++;
+      /* Check that the condition does not contain any new definition
+         created in the latch as the stmts from the latch intended
+         to precede it.  */
+      if (gimple_code (stmt1) != GIMPLE_ASSIGN)
+        return false;
+      var = gimple_assign_lhs (stmt1);
+      if (TREE_THIS_VOLATILE (var)
+         || TYPE_VOLATILE (TREE_TYPE (var))
+         || walk_tree (&expr, contains_tree_r, var, NULL))
+       return false;
+    }
+  /* Check that the latch does not contain more than MAX_STMTS_IN_LATCH
+     insns.  The purpose of this restriction is to prevent blowing the
+     loop with too many copies from the latch.  */
+  if (count > MAX_STMTS_IN_LATCH)
+    return false;
+
+  /* Apply the transformation - clean up the latch block:  
+
+     var = something; 
+     L1:
+     x1 = expr;
+     if (cond) goto L2 else goto L3;
+     L2:
+     var = x1;
+     goto L1
+     L3:
+     ...
+
+     ==>
+
+     var = something;
+     L1:
+     x1 = expr;
+     tmp_var = var;
+     var = x1;
+     if (cond) goto L1 else goto L2;
+     L2:
+     var = tmp_var;
+     ... 
+   */
+  for (tsi = gsi_start (stmts); !gsi_end_p (tsi); gsi_next (&tsi))
+    {
+      gimple stmt1 = gsi_stmt (tsi);
+      tree var, tmp_var;
+      gimple copy;
+
+      /* Create a new variable to load back the value of var in case
+         we exit the loop.  */
+      var = gimple_assign_lhs (stmt1);
+      tmp_var = create_temp (var);
+      copy = gimple_build_assign (tmp_var, var);
+      set_is_used (tmp_var);
+      gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
+      copy = gimple_build_assign (var, tmp_var);
+      gsi_insert_before (&gsi_exit, copy, GSI_SAME_STMT);
+    }
+
+  PENDING_STMT (single_edge) = 0;
+  /* Insert the new stmts to the loop body.  */
+  gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT);
+
+  if (dump_file)
+    fprintf (dump_file,
+            "\nCleaned-up latch block of loop with single BB: %d\n\n",
+            single_edge->dest->index);
+
+  return true;
+}
 
 /* Look at all the incoming edges to block BB, and decide where the best place
    to insert the stmts on each edge are, and perform those insertions.  */
@@ -879,8 +1086,8 @@ analyze_edges_for_bb (basic_block bb)
   int count;
   unsigned int x;
   bool have_opportunity;
-  block_stmt_iterator bsi;
-  tree stmt;
+  gimple_stmt_iterator gsi;
+  gimple stmt;
   edge single_edge = NULL;
   bool is_label;
   edge leader;
@@ -902,7 +1109,7 @@ analyze_edges_for_bb (basic_block bb)
     {
       FOR_EACH_EDGE (e, ei, bb->preds)
        if (PENDING_STMT (e))
-         bsi_commit_one_edge_insert (e, NULL);
+         gsi_commit_one_edge_insert (e, NULL);
       return;
     }
 
@@ -915,18 +1122,19 @@ analyze_edges_for_bb (basic_block bb)
          gcc_assert (!(e->flags & EDGE_ABNORMAL));
          if (e->flags & EDGE_FALLTHRU)
            {
-             bsi = bsi_start (e->src);
-             if (!bsi_end_p (bsi))
+             gsi = gsi_start_bb (e->src);
+             if (!gsi_end_p (gsi))
                {
-                 stmt = bsi_stmt (bsi);
-                 bsi_next (&bsi);
-                 gcc_assert (stmt != NULL_TREE);
-                 is_label = (TREE_CODE (stmt) == LABEL_EXPR);
+                 stmt = gsi_stmt (gsi);
+                 gsi_next (&gsi);
+                 gcc_assert (stmt != NULL);
+                 is_label = (gimple_code (stmt) == GIMPLE_LABEL);
                  /* Punt if it has non-label stmts, or isn't local.  */
-                 if (!is_label || DECL_NONLOCAL (TREE_OPERAND (stmt, 0)) 
-                     || !bsi_end_p (bsi))
+                 if (!is_label
+                     || DECL_NONLOCAL (gimple_label_label (stmt)) 
+                     || !gsi_end_p (gsi))
                    {
-                     bsi_commit_one_edge_insert (e, NULL);
+                     gsi_commit_one_edge_insert (e, NULL);
                      continue;
                    }
                }
@@ -940,14 +1148,19 @@ analyze_edges_for_bb (basic_block bb)
   if (count < 2)
     {
       if (single_edge)
-        bsi_commit_one_edge_insert (single_edge, NULL);
+      {
+       /* Add stmts to the edge unless processed specially as a
+          single-block loop latch edge. */
+       if (!process_single_block_loop_latch (single_edge))
+         gsi_commit_one_edge_insert (single_edge, NULL);
+      }
       return;
     }
 
   /* Ensure that we have empty worklists.  */
 #ifdef ENABLE_CHECKING
   gcc_assert (VEC_length (edge, edge_leader) == 0);
-  gcc_assert (VEC_length (tree, stmt_list) == 0);
+  gcc_assert (VEC_length (gimple_seq, stmt_list) == 0);
   gcc_assert (bitmap_empty_p (leader_has_match));
 #endif
 
@@ -980,7 +1193,7 @@ analyze_edges_for_bb (basic_block bb)
          if (!found)
            {
              VEC_safe_push (edge, heap, edge_leader, e);
-             VEC_safe_push (tree, heap, stmt_list, PENDING_STMT (e));
+             VEC_safe_push (gimple_seq, heap, stmt_list, PENDING_STMT (e));
            }
        }
      }
@@ -989,9 +1202,9 @@ analyze_edges_for_bb (basic_block bb)
   if (!have_opportunity)
     {
       for (x = 0; VEC_iterate (edge, edge_leader, x, leader); x++)
-       bsi_commit_one_edge_insert (leader, NULL);
+       gsi_commit_one_edge_insert (leader, NULL);
       VEC_truncate (edge, edge_leader, 0);
-      VEC_truncate (tree, stmt_list, 0);
+      VEC_truncate (gimple_seq, stmt_list, 0);
       bitmap_clear (leader_has_match);
       return;
     }
@@ -1006,8 +1219,8 @@ analyze_edges_for_bb (basic_block bb)
     if (bitmap_bit_p (leader_has_match, x))
       {
        edge new_edge;
-       block_stmt_iterator bsi;
-       tree curr_stmt_list;
+       gimple_stmt_iterator gsi;
+       gimple_seq curr_stmt_list;
 
        leader_match = leader;
 
@@ -1017,7 +1230,7 @@ analyze_edges_for_bb (basic_block bb)
           and use the saved stmt list.  */
        PENDING_STMT (leader) = NULL;
        leader->aux = leader;
-       curr_stmt_list = VEC_index (tree, stmt_list, x);
+       curr_stmt_list = VEC_index (gimple_seq, stmt_list, x);
 
         new_edge = make_forwarder_block (leader->dest, same_stmt_list_p, 
                                         NULL);
@@ -1027,7 +1240,7 @@ analyze_edges_for_bb (basic_block bb)
            fprintf (dump_file, "Splitting BB %d for Common stmt list.  ", 
                     leader->dest->index);
            fprintf (dump_file, "Original block is now BB%d.\n", bb->index);
-           print_generic_stmt (dump_file, curr_stmt_list, TDF_VOPS);
+           print_gimple_seq (dump_file, curr_stmt_list, 0, TDF_VOPS);
          }
 
        FOR_EACH_EDGE (e, ei, new_edge->src->preds)
@@ -1038,22 +1251,22 @@ analyze_edges_for_bb (basic_block bb)
                       e->src->index, e->dest->index);
          }
 
-       bsi = bsi_last (leader->dest);
-       bsi_insert_after (&bsi, curr_stmt_list, BSI_NEW_STMT);
+       gsi = gsi_last_bb (leader->dest);
+       gsi_insert_seq_after (&gsi, curr_stmt_list, GSI_NEW_STMT);
 
        leader_match = NULL;
        /* We should never get a new block now.  */
       }
     else
       {
-       PENDING_STMT (leader) = VEC_index (tree, stmt_list, x);
-       bsi_commit_one_edge_insert (leader, NULL);
+       PENDING_STMT (leader) = VEC_index (gimple_seq, stmt_list, x);
+       gsi_commit_one_edge_insert (leader, NULL);
       }
 
    
   /* Clear the working data structures.  */
   VEC_truncate (edge, edge_leader, 0);
-  VEC_truncate (tree, stmt_list, 0);
+  VEC_truncate (gimple_seq, stmt_list, 0);
   bitmap_clear (leader_has_match);
 }
 
@@ -1133,9 +1346,9 @@ static void
 remove_ssa_form (bool perform_ter)
 {
   basic_block bb;
-  tree phi, next;
-  tree *values = NULL;
+  gimple *values = NULL;
   var_map map;
+  gimple_stmt_iterator gsi;
 
   map = coalesce_ssa_name ();
 
@@ -1172,16 +1385,8 @@ remove_ssa_form (bool perform_ter)
 
   /* Remove PHI nodes which have been translated back to real variables.  */
   FOR_EACH_BB (bb)
-    {
-      for (phi = phi_nodes (bb); phi; phi = next)
-       {
-         next = PHI_CHAIN (phi);
-         remove_phi_node (phi, NULL_TREE, true);
-       }
-    }
-
-  /* we no longer maintain the SSA operand cache at this point.  */
-  fini_ssa_operands ();
+    for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi);)
+      remove_phi_node (&gsi, true);
 
   /* If any copies were inserted on edges, analyze and insert them now.  */
   perform_edge_inserts ();
@@ -1203,25 +1408,25 @@ static void
 insert_backedge_copies (void)
 {
   basic_block bb;
+  gimple_stmt_iterator gsi;
 
   FOR_EACH_BB (bb)
     {
-      tree phi;
-
-      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
-         tree result = PHI_RESULT (phi);
+         gimple phi = gsi_stmt (gsi);
+         tree result = gimple_phi_result (phi);
          tree result_var;
-         int i;
+         size_t i;
 
          if (!is_gimple_reg (result))
            continue;
 
          result_var = SSA_NAME_VAR (result);
-         for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+         for (i = 0; i < gimple_phi_num_args (phi); i++)
            {
-             tree arg = PHI_ARG_DEF (phi, i);
-             edge e = PHI_ARG_EDGE (phi, i);
+             tree arg = gimple_phi_arg_def (phi, i);
+             edge e = gimple_phi_arg_edge (phi, i);
 
              /* If the argument is not an SSA_NAME, then we will need a 
                 constant initialization.  If the argument is an SSA_NAME with
@@ -1231,12 +1436,13 @@ insert_backedge_copies (void)
                  && (TREE_CODE (arg) != SSA_NAME
                      || SSA_NAME_VAR (arg) != result_var))
                {
-                 tree stmt, name, last = NULL;
-                 block_stmt_iterator bsi;
+                 tree name;
+                 gimple stmt, last = NULL;
+                 gimple_stmt_iterator gsi2;
 
-                 bsi = bsi_last (PHI_ARG_EDGE (phi, i)->src);
-                 if (!bsi_end_p (bsi))
-                   last = bsi_stmt (bsi);
+                 gsi2 = gsi_last_bb (gimple_phi_arg_edge (phi, i)->src);
+                 if (!gsi_end_p (gsi2))
+                   last = gsi_stmt (gsi2);
 
                  /* In theory the only way we ought to get back to the
                     start of a loop should be with a COND_EXPR or GOTO_EXPR.
@@ -1257,17 +1463,17 @@ insert_backedge_copies (void)
 
                  /* Create a new instance of the underlying variable of the 
                     PHI result.  */
-                 stmt = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (result_var),
-                                NULL_TREE, PHI_ARG_DEF (phi, i));
+                 stmt = gimple_build_assign (result_var,
+                                             gimple_phi_arg_def (phi, i));
                  name = make_ssa_name (result_var, stmt);
-                 GIMPLE_STMT_OPERAND (stmt, 0) = name;
+                 gimple_assign_set_lhs (stmt, name);
 
                  /* Insert the new statement into the block and update
                     the PHI node.  */
                  if (last && stmt_ends_bb_p (last))
-                   bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
+                   gsi_insert_before (&gsi2, stmt, GSI_NEW_STMT);
                  else
-                   bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
+                   gsi_insert_after (&gsi2, stmt, GSI_NEW_STMT);
                  SET_PHI_ARG_DEF (phi, i, name);
                }
            }
@@ -1290,15 +1496,17 @@ rewrite_out_of_ssa (void)
      copies into the loop itself.  */
   insert_backedge_copies ();
 
-  eliminate_virtual_phis ();
+
+  /* Eliminate PHIs which are of no use, such as virtual or dead phis.  */
+  eliminate_useless_phis ();
 
   if (dump_file && (dump_flags & TDF_DETAILS))
-    dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
+    gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS);
 
   remove_ssa_form (flag_tree_ter && !flag_mudflap);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
-    dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
+    gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS);
 
   cfun->gimple_df->in_ssa_p = false;
   return 0;
@@ -1307,8 +1515,10 @@ rewrite_out_of_ssa (void)
 
 /* Define the parameters of the out of SSA pass.  */
 
-struct tree_opt_pass pass_del_ssa = 
+struct gimple_opt_pass pass_del_ssa = 
 {
+ {
+  GIMPLE_PASS,
   "optimized",                         /* name */
   NULL,                                        /* gate */
   rewrite_out_of_ssa,                  /* execute */
@@ -1316,7 +1526,7 @@ struct tree_opt_pass pass_del_ssa =
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   TV_TREE_SSA_TO_NORMAL,               /* tv_id */
-  PROP_cfg | PROP_ssa | PROP_alias,    /* properties_required */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
   0,                                   /* properties_provided */
   /* ??? If TER is enabled, we also kill gimple.  */
   PROP_ssa,                            /* properties_destroyed */
@@ -1324,6 +1534,6 @@ struct tree_opt_pass pass_del_ssa =
     | TODO_verify_stmts,               /* todo_flags_start */
   TODO_dump_func
   | TODO_ggc_collect
-  | TODO_remove_unused_locals,         /* todo_flags_finish */
-  0                                    /* letter */
+  | TODO_remove_unused_locals          /* todo_flags_finish */
+ }
 };