OSDN Git Service

2008-04-03 Jan Hubicka <jh@suse.cz>
[pf3gnuchains/gcc-fork.git] / gcc / tree-outof-ssa.c
index 40d6c93..12ce1b9 100644 (file)
@@ -1,12 +1,12 @@
 /* Convert a program in SSA form into Normal form.
-   Copyright (C) 2004, 2005 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,46 +15,25 @@ 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"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "flags.h"
-#include "rtl.h"
-#include "tm_p.h"
 #include "ggc.h"
-#include "langhooks.h"
-#include "hard-reg-set.h"
 #include "basic-block.h"
-#include "output.h"
-#include "expr.h"
-#include "function.h"
 #include "diagnostic.h"
 #include "bitmap.h"
 #include "tree-flow.h"
-#include "tree-gimple.h"
-#include "tree-inline.h"
-#include "varray.h"
 #include "timevar.h"
-#include "hashtab.h"
 #include "tree-dump.h"
 #include "tree-ssa-live.h"
 #include "tree-pass.h"
 #include "toplev.h"
 
-/* Flags to pass to remove_ssa_form.  */
-
-#define SSANORM_PERFORM_TER            0x1
-#define SSANORM_COMBINE_TEMPS          0x2
-#define SSANORM_COALESCE_PARTITIONS    0x4
-
-DEF_VEC_I(int);
-DEF_VEC_ALLOC_I(int,heap);
 
 /* Used to hold all the components required to do SSA PHI elimination.
    The node and pred/succ list is a simple linear list of nodes and
@@ -104,36 +83,6 @@ typedef struct _elim_graph {
 } *elim_graph;
 
 
-/* Local functions.  */
-static tree create_temp (tree);
-static void insert_copy_on_edge (edge, tree, tree);
-static elim_graph new_elim_graph (int);
-static inline void delete_elim_graph (elim_graph);
-static inline void clear_elim_graph (elim_graph);
-static inline int elim_graph_size (elim_graph);
-static inline void elim_graph_add_node (elim_graph, tree);
-static inline void elim_graph_add_edge (elim_graph, int, int);
-static inline int elim_graph_remove_succ_edge (elim_graph, int);
-
-static inline void eliminate_name (elim_graph, tree);
-static void eliminate_build (elim_graph, basic_block);
-static void elim_forward (elim_graph, int);
-static int elim_unvisited_predecessor (elim_graph, int);
-static void elim_backward (elim_graph, int);
-static void elim_create (elim_graph, int);
-static void eliminate_phi (edge, elim_graph);
-static tree_live_info_p coalesce_ssa_name (var_map, int);
-static void assign_vars (var_map);
-static bool replace_use_variable (var_map, use_operand_p, tree *);
-static bool replace_def_variable (var_map, def_operand_p, tree *);
-static void eliminate_virtual_phis (void);
-static void coalesce_abnormal_edges (var_map, conflict_graph, root_var_p);
-static void print_exprs (FILE *, const char *, tree, const char *, tree,
-                        const char *);
-static void print_exprs_edge (FILE *, edge, const char *, tree, const char *,
-                             tree);
-
-
 /* Create a temporary variable based on the type of variable T.  Use T's name
    as the prefix.  */
 
@@ -170,12 +119,13 @@ create_temp (tree t)
     }
   DECL_ARTIFICIAL (tmp) = DECL_ARTIFICIAL (t);
   DECL_IGNORED_P (tmp) = DECL_IGNORED_P (t);
-  add_referenced_tmp_var (tmp);
+  DECL_GIMPLE_REG_P (tmp) = DECL_GIMPLE_REG_P (t);
+  add_referenced_var (tmp);
 
-  /* add_referenced_tmp_var will create the annotation and set up some
+  /* add_referenced_var will create the annotation and set up some
      of the flags in the annotation.  However, some flags we need to
      inherit from our original variable.  */
-  var_ann (tmp)->type_mem_tag = var_ann (t)->type_mem_tag;
+  set_symbol_mem_tag (tmp, symbol_mem_tag (t));
   if (is_call_clobbered (t))
     mark_call_clobbered (tmp, var_ann (t)->escape_mask);
 
@@ -191,7 +141,7 @@ insert_copy_on_edge (edge e, tree dest, tree src)
 {
   tree copy;
 
-  copy = build2 (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
+  copy = build_gimple_modify_stmt (dest, src);
   set_is_used (dest);
 
   if (TREE_CODE (src) == ADDR_EXPR)
@@ -492,6 +442,7 @@ elim_create (elim_graph g, int T)
   
 }
 
+
 /* Eliminate all the phi nodes on edge E in graph G.  */
 
 static void
@@ -500,1349 +451,198 @@ eliminate_phi (edge e, elim_graph g)
   int x;
   basic_block B = e->dest;
 
-  gcc_assert (VEC_length (tree, g->const_copies) == 0);
-
-  /* Abnormal edges already have everything coalesced.  */
-  if (e->flags & EDGE_ABNORMAL)
-    return;
-
-  g->e = e;
-
-  eliminate_build (g, B);
-
-  if (elim_graph_size (g) != 0)
-    {
-      tree var;
-
-      sbitmap_zero (g->visited);
-      VEC_truncate (int, g->stack, 0);
-
-      for (x = 0; VEC_iterate (tree, g->nodes, x, var); x++)
-        {
-         int p = var_to_partition (g->map, var);
-         if (!TEST_BIT (g->visited, p))
-           elim_forward (g, p);
-       }
-       
-      sbitmap_zero (g->visited);
-      while (VEC_length (int, g->stack) > 0)
-       {
-         x = VEC_pop (int, g->stack);
-         if (!TEST_BIT (g->visited, x))
-           elim_create (g, x);
-       }
-    }
-
-  /* If there are any pending constant copies, issue them now.  */
-  while (VEC_length (tree, g->const_copies) > 0)
-    {
-      tree src, dest;
-      src = VEC_pop (tree, g->const_copies);
-      dest = VEC_pop (tree, g->const_copies);
-      insert_copy_on_edge (e, dest, src);
-    }
-}
-
-
-/* Shortcut routine to print messages to file F of the form:
-   "STR1 EXPR1 STR2 EXPR2 STR3."  */
-
-static void
-print_exprs (FILE *f, const char *str1, tree expr1, const char *str2,
-            tree expr2, const char *str3)
-{
-  fprintf (f, "%s", str1);
-  print_generic_expr (f, expr1, TDF_SLIM);
-  fprintf (f, "%s", str2);
-  print_generic_expr (f, expr2, TDF_SLIM);
-  fprintf (f, "%s", str3);
-}
-
-
-/* Shortcut routine to print abnormal edge messages to file F of the form:
-   "STR1 EXPR1 STR2 EXPR2 across edge E.  */
-
-static void
-print_exprs_edge (FILE *f, edge e, const char *str1, tree expr1, 
-                 const char *str2, tree expr2)
-{
-  print_exprs (f, str1, expr1, str2, expr2, " across an abnormal edge");
-  fprintf (f, " from BB%d->BB%d\n", e->src->index,
-              e->dest->index);
-}
-
-
-/* Coalesce partitions in MAP which are live across abnormal edges in GRAPH.
-   RV is the root variable groupings of the partitions in MAP.  Since code 
-   cannot be inserted on these edges, failure to coalesce something across
-   an abnormal edge is an error.  */
-
-static void
-coalesce_abnormal_edges (var_map map, conflict_graph graph, root_var_p rv)
-{
-  basic_block bb;
-  edge e;
-  tree phi, var, tmp;
-  int x, y, z;
-  edge_iterator ei;
-
-  /* Code cannot be inserted on abnormal edges. Look for all abnormal 
-     edges, and coalesce any PHI results with their arguments across 
-     that edge.  */
-
-  FOR_EACH_BB (bb)
-    FOR_EACH_EDGE (e, ei, bb->succs)
-      if (e->dest != EXIT_BLOCK_PTR && e->flags & EDGE_ABNORMAL)
-       for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
-         {
-           /* Visit each PHI on the destination side of this abnormal
-              edge, and attempt to coalesce the argument with the result.  */
-           var = PHI_RESULT (phi);
-           x = var_to_partition (map, var);
-
-           /* Ignore results which are not relevant.  */
-           if (x == NO_PARTITION)
-             continue;
-
-           tmp = PHI_ARG_DEF (phi, e->dest_idx);
-#ifdef ENABLE_CHECKING
-           if (!phi_ssa_name_p (tmp))
-             {
-               print_exprs_edge (stderr, e,
-                                 "\nConstant argument in PHI. Can't insert :",
-                                 var, " = ", tmp);
-               internal_error ("SSA corruption");
-             }
-#else
-           gcc_assert (phi_ssa_name_p (tmp));
-#endif
-           y = var_to_partition (map, tmp);
-           gcc_assert (x != NO_PARTITION);
-           gcc_assert (y != NO_PARTITION);
-#ifdef ENABLE_CHECKING
-           if (root_var_find (rv, x) != root_var_find (rv, y))
-             {
-               print_exprs_edge (stderr, e, "\nDifferent root vars: ",
-                                 root_var (rv, root_var_find (rv, x)), 
-                                 " and ", 
-                                 root_var (rv, root_var_find (rv, y)));
-               internal_error ("SSA corruption");
-             }
-#else
-           gcc_assert (root_var_find (rv, x) == root_var_find (rv, y));
-#endif
-
-           if (x != y)
-             {
-#ifdef ENABLE_CHECKING
-               if (conflict_graph_conflict_p (graph, x, y))
-                 {
-                   print_exprs_edge (stderr, e, "\n Conflict ", 
-                                     partition_to_var (map, x),
-                                     " and ", partition_to_var (map, y));
-                   internal_error ("SSA corruption");
-                 }
-#else
-               gcc_assert (!conflict_graph_conflict_p (graph, x, y));
-#endif
-               
-               /* Now map the partitions back to their real variables.  */
-               var = partition_to_var (map, x);
-               tmp = partition_to_var (map, y);
-               if (dump_file && (dump_flags & TDF_DETAILS))
-                 {
-                   print_exprs_edge (dump_file, e, 
-                                     "ABNORMAL: Coalescing ",
-                                     var, " and ", tmp);
-                 }
-               z = var_union (map, var, tmp);
-#ifdef ENABLE_CHECKING
-               if (z == NO_PARTITION)
-                 {
-                   print_exprs_edge (stderr, e, "\nUnable to coalesce", 
-                                     partition_to_var (map, x), " and ", 
-                                     partition_to_var (map, y));
-                   internal_error ("SSA corruption");
-                 }
-#else
-               gcc_assert (z != NO_PARTITION);
-#endif
-               gcc_assert (z == x || z == y);
-               if (z == x)
-                 conflict_graph_merge_regs (graph, x, y);
-               else
-                 conflict_graph_merge_regs (graph, y, x);
-             }
-         }
-}
-
-/* Coalesce potential copies via PHI arguments.  */
-
-static void
-coalesce_phi_operands (var_map map, coalesce_list_p cl)
-{
-  basic_block bb;
-  tree phi;
-
-  FOR_EACH_BB (bb)
-    {
-      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
-       {
-         tree res = PHI_RESULT (phi);
-         int p = var_to_partition (map, res);
-         int x;
-
-         if (p == NO_PARTITION)
-           continue;
-
-         for (x = 0; x < PHI_NUM_ARGS (phi); x++)
-           {
-             tree arg = PHI_ARG_DEF (phi, x);
-             int p2;
-
-             if (TREE_CODE (arg) != SSA_NAME)
-               continue;
-             if (SSA_NAME_VAR (res) != SSA_NAME_VAR (arg))
-               continue;
-             p2 = var_to_partition (map, PHI_ARG_DEF (phi, x));
-             if (p2 != NO_PARTITION)
-               {
-                 edge e = PHI_ARG_EDGE (phi, x);
-                 add_coalesce (cl, p, p2,
-                               coalesce_cost (EDGE_FREQUENCY (e),
-                                              maybe_hot_bb_p (bb),
-                                              EDGE_CRITICAL_P (e)));
-               }
-           }
-       }
-    }
-}
-
-/* Coalesce all the result decls together.  */
-
-static void
-coalesce_result_decls (var_map map, coalesce_list_p cl)
-{
-  unsigned int i, x;
-  tree var = NULL;
-
-  for (i = x = 0; x < num_var_partitions (map); x++)
-    {
-      tree p = partition_to_var (map, x);
-      if (TREE_CODE (SSA_NAME_VAR (p)) == RESULT_DECL)
-       {
-         if (var == NULL_TREE)
-           {
-             var = p;
-             i = x;
-           }
-         else
-           add_coalesce (cl, i, x,
-                         coalesce_cost (EXIT_BLOCK_PTR->frequency,
-                                        maybe_hot_bb_p (EXIT_BLOCK_PTR),
-                                        false));
-       }
-    }
-}
-
-/* Coalesce matching constraints in asms.  */
-
-static void
-coalesce_asm_operands (var_map map, coalesce_list_p cl)
-{
-  basic_block bb;
-
-  FOR_EACH_BB (bb)
-    {
-      block_stmt_iterator bsi;
-      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-       {
-         tree stmt = bsi_stmt (bsi);
-         unsigned long noutputs, i;
-         tree *outputs, link;
-
-         if (TREE_CODE (stmt) != ASM_EXPR)
-           continue;
-
-         noutputs = list_length (ASM_OUTPUTS (stmt));
-         outputs = (tree *) alloca (noutputs * sizeof (tree));
-         for (i = 0, link = ASM_OUTPUTS (stmt); link;
-              ++i, link = TREE_CHAIN (link))
-           outputs[i] = TREE_VALUE (link);
-
-         for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
-           {
-             const char *constraint
-               = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
-             tree input = TREE_VALUE (link);
-             char *end;
-             unsigned long match;
-             int p1, p2;
-
-             if (TREE_CODE (input) != SSA_NAME && !DECL_P (input))
-               continue;
-
-             match = strtoul (constraint, &end, 10);
-             if (match >= noutputs || end == constraint)
-               continue;
-
-             if (TREE_CODE (outputs[match]) != SSA_NAME
-                 && !DECL_P (outputs[match]))
-               continue;
-
-             p1 = var_to_partition (map, outputs[match]);
-             if (p1 == NO_PARTITION)
-               continue;
-             p2 = var_to_partition (map, input);
-             if (p2 == NO_PARTITION)
-               continue;
-
-             add_coalesce (cl, p1, p2, coalesce_cost (REG_BR_PROB_BASE,
-                                                      maybe_hot_bb_p (bb),
-                                                      false));
-           }
-       }
-    }
-}
-
-/* Reduce the number of live ranges in MAP.  Live range information is 
-   returned if FLAGS indicates that we are combining temporaries, otherwise 
-   NULL is returned.  The only partitions which are associated with actual 
-   variables at this point are those which are forced to be coalesced for 
-   various reason. (live on entry, live across abnormal edges, etc.).  */
-
-static tree_live_info_p
-coalesce_ssa_name (var_map map, int flags)
-{
-  unsigned num, x;
-  sbitmap live;
-  root_var_p rv;
-  tree_live_info_p liveinfo;
-  conflict_graph graph;
-  coalesce_list_p cl = NULL;
-  sbitmap_iterator sbi;
-
-  if (num_var_partitions (map) <= 1)
-    return NULL;
-
-  liveinfo = calculate_live_on_entry (map);
-  calculate_live_on_exit (liveinfo);
-  rv = root_var_init (map);
-
-  /* Remove single element variable from the list.  */
-  root_var_compact (rv);
-
-  cl = create_coalesce_list (map);
-
-  coalesce_phi_operands (map, cl);
-  coalesce_result_decls (map, cl);
-  coalesce_asm_operands (map, cl);
-
-  /* Build a conflict graph.  */
-  graph = build_tree_conflict_graph (liveinfo, rv, cl);
-
-  if (cl)
-    {
-      if (dump_file && (dump_flags & TDF_DETAILS))
-       {
-         fprintf (dump_file, "Before sorting:\n");
-         dump_coalesce_list (dump_file, cl);
-       }
-
-      sort_coalesce_list (cl);
-
-      if (dump_file && (dump_flags & TDF_DETAILS))
-       {
-         fprintf (dump_file, "\nAfter sorting:\n");
-         dump_coalesce_list (dump_file, cl);
-       }
-    }
-
-  /* Put the single element variables back in.  */
-  root_var_decompact (rv);
-
-  /* First, coalesce all live on entry variables to their root variable. 
-     This will ensure the first use is coming from the correct location.  */
-
-  num = num_var_partitions (map);
-  live = sbitmap_alloc (num);
-  sbitmap_zero (live);
-
-  /* Set 'live' vector to indicate live on entry partitions.  */
-  for (x = 0 ; x < num; x++)
-    {
-      tree var = partition_to_var (map, x);
-      if (default_def (SSA_NAME_VAR (var)) == var)
-       SET_BIT (live, x);
-    }
-
-  if ((flags & SSANORM_COMBINE_TEMPS) == 0)
-    {
-      delete_tree_live_info (liveinfo);
-      liveinfo = NULL;
-    }
-
-  /* Assign root variable as partition representative for each live on entry
-     partition.  */
-  EXECUTE_IF_SET_IN_SBITMAP (live, 0, x, sbi)
-    {
-      tree var = root_var (rv, root_var_find (rv, x));
-      var_ann_t ann = var_ann (var);
-      /* If these aren't already coalesced...  */
-      if (partition_to_var (map, x) != var)
-       {
-         /* This root variable should have not already been assigned
-            to another partition which is not coalesced with this one.  */
-         gcc_assert (!ann->out_of_ssa_tag);
-
-         if (dump_file && (dump_flags & TDF_DETAILS))
-           {
-             print_exprs (dump_file, "Must coalesce ", 
-                          partition_to_var (map, x),
-                          " with the root variable ", var, ".\n");
-           }
-
-         change_partition_var (map, var, x);
-       }
-    }
-
-  sbitmap_free (live);
-
-  /* Coalesce partitions live across abnormal edges.  */
-  coalesce_abnormal_edges (map, graph, rv);
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    dump_var_map (dump_file, map);
-
-  /* Coalesce partitions.  */
-  coalesce_tpa_members (rv, graph, map, cl,
-                       ((dump_flags & TDF_DETAILS) ? dump_file
-                        : NULL));
-
-  if (flags & SSANORM_COALESCE_PARTITIONS)
-    coalesce_tpa_members (rv, graph, map, NULL,
-                         ((dump_flags & TDF_DETAILS) ? dump_file
-                          : NULL));
-  if (cl)
-    delete_coalesce_list (cl);
-  root_var_delete (rv);
-  conflict_graph_delete (graph);
-
-  return liveinfo;
-}
-
-
-/* Take the ssa-name var_map MAP, and assign real variables to each 
-   partition.  */
-
-static void
-assign_vars (var_map map)
-{
-  int x, i, num, rep;
-  tree t, var;
-  var_ann_t ann;
-  root_var_p rv;
-
-  rv = root_var_init (map);
-  if (!rv) 
-    return;
-
-  /* Coalescing may already have forced some partitions to their root 
-     variable. Find these and tag them.  */
-
-  num = num_var_partitions (map);
-  for (x = 0; x < num; x++)
-    {
-      var = partition_to_var (map, x);
-      if (TREE_CODE (var) != SSA_NAME)
-       {
-         /* Coalescing will already have verified that more than one
-            partition doesn't have the same root variable. Simply marked
-            the variable as assigned.  */
-         ann = var_ann (var);
-         ann->out_of_ssa_tag = 1;
-         if (dump_file && (dump_flags & TDF_DETAILS))
-           {
-             fprintf (dump_file, "partition %d has variable ", x);
-             print_generic_expr (dump_file, var, TDF_SLIM);
-             fprintf (dump_file, " assigned to it.\n");
-           }
-
-       }
-    }
-
-  num = root_var_num (rv);
-  for (x = 0; x < num; x++)
-    {
-      var = root_var (rv, x);
-      ann = var_ann (var);
-      for (i = root_var_first_partition (rv, x);
-          i != ROOT_VAR_NONE;
-          i = root_var_next_partition (rv, i))
-       {
-         t = partition_to_var (map, i);
-
-         if (t == var || TREE_CODE (t) != SSA_NAME)
-           continue;
-
-         rep = var_to_partition (map, t);
-         
-         if (!ann->out_of_ssa_tag)
-           {
-             if (dump_file && (dump_flags & TDF_DETAILS))
-               print_exprs (dump_file, "", t, "  --> ", var, "\n");
-             change_partition_var (map, var, rep);
-             continue;
-           }
-
-         if (dump_file && (dump_flags & TDF_DETAILS))
-           print_exprs (dump_file, "", t, " not coalesced with ", var, 
-                        "");
-
-         var = create_temp (t);
-         change_partition_var (map, var, rep);
-         ann = var_ann (var);
-
-         if (dump_file && (dump_flags & TDF_DETAILS))
-           {
-             fprintf (dump_file, " -->  New temp:  '");
-             print_generic_expr (dump_file, var, TDF_SLIM);
-             fprintf (dump_file, "'\n");
-           }
-       }
-    }
-
-  root_var_delete (rv);
-}
-
-
-/* Replace use operand P with whatever variable it has been rewritten to based 
-   on the partitions in MAP.  EXPR is an optional expression vector over SSA 
-   versions which is used to replace P with an expression instead of a variable.
-   If the stmt is changed, return true.  */ 
-
-static inline bool
-replace_use_variable (var_map map, use_operand_p p, tree *expr)
-{
-  tree new_var;
-  tree var = USE_FROM_PTR (p);
-
-  /* Check if we are replacing this variable with an expression.  */
-  if (expr)
-    {
-      int version = SSA_NAME_VERSION (var);
-      if (expr[version])
-        {
-         tree new_expr = TREE_OPERAND (expr[version], 1);
-         SET_USE (p, new_expr);
-         /* Clear the stmt's RHS, or GC might bite us.  */
-         TREE_OPERAND (expr[version], 1) = NULL_TREE;
-         return true;
-       }
-    }
-
-  new_var = var_to_partition_to_var (map, var);
-  if (new_var)
-    {
-      SET_USE (p, new_var);
-      set_is_used (new_var);
-      return true;
-    }
-  return false;
-}
-
-
-/* Replace def operand DEF_P with whatever variable it has been rewritten to 
-   based on the partitions in MAP.  EXPR is an optional expression vector over
-   SSA versions which is used to replace DEF_P with an expression instead of a 
-   variable.  If the stmt is changed, return true.  */ 
-
-static inline bool
-replace_def_variable (var_map map, def_operand_p def_p, tree *expr)
-{
-  tree new_var;
-  tree var = DEF_FROM_PTR (def_p);
-
-  /* Check if we are replacing this variable with an expression.  */
-  if (expr)
-    {
-      int version = SSA_NAME_VERSION (var);
-      if (expr[version])
-        {
-         tree new_expr = TREE_OPERAND (expr[version], 1);
-         SET_DEF (def_p, new_expr);
-         /* Clear the stmt's RHS, or GC might bite us.  */
-         TREE_OPERAND (expr[version], 1) = NULL_TREE;
-         return true;
-       }
-    }
-
-  new_var = var_to_partition_to_var (map, var);
-  if (new_var)
-    {
-      SET_DEF (def_p, new_var);
-      set_is_used (new_var);
-      return true;
-    }
-  return false;
-}
-
-
-/* Remove any PHI node which is a virtual PHI.  */
-
-static void
-eliminate_virtual_phis (void)
-{
-  basic_block bb;
-  tree phi, next;
-
-  FOR_EACH_BB (bb)
-    {
-      for (phi = phi_nodes (bb); phi; phi = next)
-        {
-         next = PHI_CHAIN (phi);
-         if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
-           {
-#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++)
-               {
-                 tree arg = PHI_ARG_DEF (phi, i);
-                 if (TREE_CODE (arg) == SSA_NAME 
-                     && is_gimple_reg (SSA_NAME_VAR (arg)))
-                   {
-                     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);
-                     internal_error ("SSA corruption");
-                   }
-               }
-#endif
-             remove_phi_node (phi, NULL_TREE);
-           }
-       }
-    }
-}
-
-
-/* This routine will coalesce variables in MAP of the same type which do not 
-   interfere with each other. LIVEINFO is the live range info for variables
-   of interest.  This will both reduce the memory footprint of the stack, and 
-   allow us to coalesce together local copies of globals and scalarized 
-   component refs.  */
-
-static void
-coalesce_vars (var_map map, tree_live_info_p liveinfo)
-{
-  basic_block bb;
-  type_var_p tv;
-  tree var;
-  unsigned x, p, p2;
-  coalesce_list_p cl;
-  conflict_graph graph;
-
-  cl = create_coalesce_list (map);
-
-  /* Merge all the live on entry vectors for coalesced partitions.  */
-  for (x = 0; x < num_var_partitions (map); x++)
-    {
-      var = partition_to_var (map, x);
-      p = var_to_partition (map, var);
-      if (p != x)
-        live_merge_and_clear (liveinfo, p, x);
-    }
-
-  /* When PHI nodes are turned into copies, the result of each PHI node
-     becomes live on entry to the block. Mark these now.  */
-  FOR_EACH_BB (bb)
-    {
-      tree phi, arg;
-      unsigned p;
-      
-      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
-       {
-         p = var_to_partition (map, PHI_RESULT (phi));
-
-         /* Skip virtual PHI nodes.  */
-         if (p == (unsigned)NO_PARTITION)
-           continue;
-
-         make_live_on_entry (liveinfo, bb, p);
-
-         /* Each argument is a potential copy operation. Add any arguments 
-            which are not coalesced to the result to the coalesce list.  */
-         for (x = 0; x < (unsigned)PHI_NUM_ARGS (phi); x++)
-           {
-             arg = PHI_ARG_DEF (phi, x);
-             if (!phi_ssa_name_p (arg))
-               continue;
-             p2 = var_to_partition (map, arg);
-             if (p2 == (unsigned)NO_PARTITION)
-               continue;
-             if (p != p2)
-               {
-                 edge e = PHI_ARG_EDGE (phi, x);
-
-                 add_coalesce (cl, p, p2, 
-                               coalesce_cost (EDGE_FREQUENCY (e),
-                                              maybe_hot_bb_p (bb),
-                                              EDGE_CRITICAL_P (e)));
-               }
-           }
-       }
-   }
-
-  
-  /* Re-calculate live on exit info.  */
-  calculate_live_on_exit (liveinfo);
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {
-      fprintf (dump_file, "Live range info for variable memory coalescing.\n");
-      dump_live_info (dump_file, liveinfo, LIVEDUMP_ALL);
-
-      fprintf (dump_file, "Coalesce list from phi nodes:\n");
-      dump_coalesce_list (dump_file, cl);
-    }
-
-
-  tv = type_var_init (map);
-  if (dump_file)
-    type_var_dump (dump_file, tv);
-  type_var_compact (tv);
-  if (dump_file)
-    type_var_dump (dump_file, tv);
-
-  graph = build_tree_conflict_graph (liveinfo, tv, cl);
-
-  type_var_decompact (tv);
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {
-      fprintf (dump_file, "type var list now looks like:n");
-      type_var_dump (dump_file, tv);
-
-      fprintf (dump_file, "Coalesce list after conflict graph build:\n");
-      dump_coalesce_list (dump_file, cl);
-    }
-
-  sort_coalesce_list (cl);
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {
-      fprintf (dump_file, "Coalesce list after sorting:\n");
-      dump_coalesce_list (dump_file, cl);
-    }
-
-  coalesce_tpa_members (tv, graph, map, cl, 
-                       ((dump_flags & TDF_DETAILS) ? dump_file : NULL));
-
-  type_var_delete (tv);
-  delete_coalesce_list (cl);
-}
-
-
-/* Temporary Expression Replacement (TER)
-
-   Replace SSA version variables during out-of-ssa with their defining
-   expression if there is only one use of the variable.
-
-   A pass is made through the function, one block at a time.  No cross block
-   information is tracked.
-
-   Variables which only have one use, and whose defining stmt is considered
-   a replaceable expression (see check_replaceable) are entered into 
-   consideration by adding a list of dependent partitions to the version_info
-   vector for that ssa_name_version.  This information comes from the partition
-   mapping for each USE.  At the same time, the partition_dep_list vector for 
-   these partitions have this version number entered into their lists.
-
-   When the use of a replaceable ssa_variable is encountered, the dependence
-   list in version_info[] is moved to the "pending_dependence" list in case
-   the current expression is also replaceable. (To be determined later in 
-   processing this stmt.) version_info[] for the version is then updated to 
-   point to the defining stmt and the 'replaceable' bit is set.
-
-   Any partition which is defined by a statement 'kills' any expression which
-   is dependent on this partition.  Every ssa version in the partitions' 
-   dependence list is removed from future consideration.
-
-   All virtual references are lumped together.  Any expression which is
-   dependent on any virtual variable (via a VUSE) has a dependence added
-   to the special partition defined by VIRTUAL_PARTITION.
-
-   Whenever a V_MAY_DEF is seen, all expressions dependent this 
-   VIRTUAL_PARTITION are removed from consideration.
-
-   At the end of a basic block, all expression are removed from consideration
-   in preparation for the next block.  
-   
-   The end result is a vector over SSA_NAME_VERSION which is passed back to
-   rewrite_out_of_ssa.  As the SSA variables are being rewritten, instead of
-   replacing the SSA_NAME tree element with the partition it was assigned, 
-   it is replaced with the RHS of the defining expression.  */
-
-
-/* Dependency list element.  This can contain either a partition index or a
-   version number, depending on which list it is in.  */
-
-typedef struct value_expr_d 
-{
-  int value;
-  struct value_expr_d *next;
-} *value_expr_p;
-
-
-/* Temporary Expression Replacement (TER) table information.  */
-
-typedef struct temp_expr_table_d 
-{
-  var_map map;
-  void **version_info;
-  bitmap *expr_vars;
-  value_expr_p *partition_dep_list;
-  bitmap replaceable;
-  bool saw_replaceable;
-  int virtual_partition;
-  bitmap partition_in_use;
-  value_expr_p free_list;
-  value_expr_p pending_dependence;
-} *temp_expr_table_p;
-
-/* Used to indicate a dependency on V_MAY_DEFs.  */
-#define VIRTUAL_PARTITION(table)       (table->virtual_partition)
-
-static temp_expr_table_p new_temp_expr_table (var_map);
-static tree *free_temp_expr_table (temp_expr_table_p);
-static inline value_expr_p new_value_expr (temp_expr_table_p);
-static inline void free_value_expr (temp_expr_table_p, value_expr_p);
-static inline value_expr_p find_value_in_list (value_expr_p, int, 
-                                              value_expr_p *);
-static inline void add_value_to_list (temp_expr_table_p, value_expr_p *, int);
-static inline void add_info_to_list (temp_expr_table_p, value_expr_p *, 
-                                    value_expr_p);
-static value_expr_p remove_value_from_list (value_expr_p *, int);
-static void add_dependance (temp_expr_table_p, int, tree);
-static bool check_replaceable (temp_expr_table_p, tree);
-static void finish_expr (temp_expr_table_p, int, bool);
-static void mark_replaceable (temp_expr_table_p, tree);
-static inline void kill_expr (temp_expr_table_p, int, bool);
-static inline void kill_virtual_exprs (temp_expr_table_p, bool);
-static void find_replaceable_in_bb (temp_expr_table_p, basic_block);
-static tree *find_replaceable_exprs (var_map);
-static void dump_replaceable_exprs (FILE *, tree *);
-
-
-/* Create a new TER table for MAP.  */
-
-static temp_expr_table_p
-new_temp_expr_table (var_map map)
-{
-  temp_expr_table_p t;
-
-  t = XNEW (struct temp_expr_table_d);
-  t->map = map;
-
-  t->version_info = XCNEWVEC (void *, num_ssa_names + 1);
-  t->expr_vars = XCNEWVEC (bitmap, num_ssa_names + 1);
-  t->partition_dep_list = XCNEWVEC (value_expr_p,
-                                    num_var_partitions (map) + 1);
-
-  t->replaceable = BITMAP_ALLOC (NULL);
-  t->partition_in_use = BITMAP_ALLOC (NULL);
-
-  t->saw_replaceable = false;
-  t->virtual_partition = num_var_partitions (map);
-  t->free_list = NULL;
-  t->pending_dependence = NULL;
-
-  return t;
-}
-
-
-/* Free TER table T.  If there are valid replacements, return the expression 
-   vector.  */
-
-static tree *
-free_temp_expr_table (temp_expr_table_p t)
-{
-  value_expr_p p;
-  tree *ret = NULL;
-  unsigned i;
-
-#ifdef ENABLE_CHECKING
-  unsigned x;
-  for (x = 0; x <= num_var_partitions (t->map); x++)
-    gcc_assert (!t->partition_dep_list[x]);
-#endif
-
-  while ((p = t->free_list))
-    {
-      t->free_list = p->next;
-      free (p);
-    }
-
-  BITMAP_FREE (t->partition_in_use);
-  BITMAP_FREE (t->replaceable);
-
-  for (i = 0; i <= num_ssa_names; i++)
-    if (t->expr_vars[i])
-      BITMAP_FREE (t->expr_vars[i]);
-  free (t->expr_vars);
-
-  free (t->partition_dep_list);
-  if (t->saw_replaceable)
-    ret = (tree *)t->version_info;
-  else
-    free (t->version_info);
-  
-  free (t);
-  return ret;
-}
-
-
-/* Allocate a new value list node. Take it from the free list in TABLE if 
-   possible.  */
-
-static inline value_expr_p
-new_value_expr (temp_expr_table_p table)
-{
-  value_expr_p p;
-  if (table->free_list)
-    {
-      p = table->free_list;
-      table->free_list = p->next;
-    }
-  else
-    p = (value_expr_p) xmalloc (sizeof (struct value_expr_d));
-
-  return p;
-}
-
-
-/* Add value list node P to the free list in TABLE.  */
-
-static inline void
-free_value_expr (temp_expr_table_p table, value_expr_p p)
-{
-  p->next = table->free_list;
-  table->free_list = p;
-}
-
-
-/* Find VALUE if it's in LIST.  Return a pointer to the list object if found,  
-   else return NULL.  If LAST_PTR is provided, it will point to the previous 
-   item upon return, or NULL if this is the first item in the list.  */
-
-static inline value_expr_p
-find_value_in_list (value_expr_p list, int value, value_expr_p *last_ptr)
-{
-  value_expr_p curr;
-  value_expr_p last = NULL;
-
-  for (curr = list; curr; last = curr, curr = curr->next)
-    {
-      if (curr->value == value)
-        break;
-    }
-  if (last_ptr)
-    *last_ptr = last;
-  return curr;
-}
-
-
-/* Add VALUE to LIST, if it isn't already present.  TAB is the expression 
-   table */
-
-static inline void
-add_value_to_list (temp_expr_table_p tab, value_expr_p *list, int value)
-{
-  value_expr_p info;
-
-  if (!find_value_in_list (*list, value, NULL))
-    {
-      info = new_value_expr (tab);
-      info->value = value;
-      info->next = *list;
-      *list = info;
-    }
-}
-
-
-/* Add value node INFO if it's value isn't already in LIST.  Free INFO if
-   it is already in the list. TAB is the expression table.  */
-
-static inline void
-add_info_to_list (temp_expr_table_p tab, value_expr_p *list, value_expr_p info)
-{
-  if (find_value_in_list (*list, info->value, NULL))
-    free_value_expr (tab, info);
-  else
-    {
-      info->next = *list;
-      *list = info;
-    }
-}
-
-
-/* Look for VALUE in LIST.  If found, remove it from the list and return it's 
-   pointer.  */
-
-static value_expr_p
-remove_value_from_list (value_expr_p *list, int value)
-{
-  value_expr_p info, last;
-
-  info = find_value_in_list (*list, value, &last);
-  if (!info)
-    return NULL;
-  if (!last)
-    *list = info->next;
-  else
-    last->next = info->next;
-  return info;
-}
-
-
-/* Add a dependency between the def of ssa VERSION and VAR.  If VAR is 
-   replaceable by an expression, add a dependence each of the elements of the 
-   expression.  These are contained in the pending list.  TAB is the
-   expression table.  */
-
-static void
-add_dependance (temp_expr_table_p tab, int version, tree var)
-{
-  int i, x;
-  value_expr_p info;
-
-  i = SSA_NAME_VERSION (var);
-  if (bitmap_bit_p (tab->replaceable, i))
-    {
-      /* This variable is being substituted, so use whatever dependences
-         were queued up when we marked this as replaceable earlier.  */
-      while ((info = tab->pending_dependence))
-        {
-         tab->pending_dependence = info->next;
-         /* Get the partition this variable was dependent on. Reuse this
-            object to represent the current  expression instead.  */
-         x = info->value;
-         info->value = version;
-         add_info_to_list (tab, &(tab->partition_dep_list[x]), info);
-          add_value_to_list (tab, 
-                            (value_expr_p *)&(tab->version_info[version]), x);
-         bitmap_set_bit (tab->partition_in_use, x);
-       }
-    }
-  else
-    {
-      i = var_to_partition (tab->map, var);
-      gcc_assert (i != NO_PARTITION);
-      add_value_to_list (tab, &(tab->partition_dep_list[i]), version);
-      add_value_to_list (tab, 
-                        (value_expr_p *)&(tab->version_info[version]), i);
-      bitmap_set_bit (tab->partition_in_use, i);
-    }
-}
-
-
-/* Check if expression STMT is suitable for replacement in table TAB.  If so, 
-   create an expression entry.  Return true if this stmt is replaceable.  */
-
-static bool
-check_replaceable (temp_expr_table_p tab, tree stmt)
-{
-  tree var, def, basevar;
-  int version;
-  var_map map = tab->map;
-  ssa_op_iter iter;
-  tree call_expr;
-  bitmap def_vars = BITMAP_ALLOC (NULL), use_vars;
-
-  if (TREE_CODE (stmt) != MODIFY_EXPR)
-    return false;
-  
-  /* Punt if there is more than 1 def, or more than 1 use.  */
-  def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
-  if (!def)
-    return false;
-
-  if (version_ref_count (map, def) != 1)
-    return false;
-
-  /* There must be no V_MAY_DEFS or V_MUST_DEFS.  */
-  if (!(ZERO_SSA_OPERANDS (stmt, (SSA_OP_VMAYDEF | SSA_OP_VMUSTDEF))))
-    return false;
-
-  /* Float expressions must go through memory if float-store is on.  */
-  if (flag_float_store && FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (stmt, 1))))
-    return false;
-
-  /* Calls to functions with side-effects cannot be replaced.  */
-  if ((call_expr = get_call_expr_in (stmt)) != NULL_TREE)
-    {
-      int call_flags = call_expr_flags (call_expr);
-      if (TREE_SIDE_EFFECTS (call_expr)
-         && !(call_flags & (ECF_PURE | ECF_CONST | ECF_NORETURN)))
-       return false;
-    }
-
-  version = SSA_NAME_VERSION (def);
-  basevar = SSA_NAME_VAR (def);
-  bitmap_set_bit (def_vars, DECL_UID (basevar));
-
-  /* Add this expression to the dependency list for each use partition.  */
-  FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
-    {
-      add_dependance (tab, version, var);
-
-      use_vars = tab->expr_vars[SSA_NAME_VERSION (var)];
-      if (use_vars)
-       bitmap_ior_into (def_vars, use_vars);
-    }
-  tab->expr_vars[version] = def_vars;
-
-  /* If there are VUSES, add a dependence on virtual defs.  */
-  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE))
-    {
-      add_value_to_list (tab, (value_expr_p *)&(tab->version_info[version]), 
-                        VIRTUAL_PARTITION (tab));
-      add_value_to_list (tab, 
-                        &(tab->partition_dep_list[VIRTUAL_PARTITION (tab)]), 
-                        version);
-      bitmap_set_bit (tab->partition_in_use, VIRTUAL_PARTITION (tab));
-    }
-
-  return true;
-}
+  gcc_assert (VEC_length (tree, g->const_copies) == 0);
 
+  /* Abnormal edges already have everything coalesced.  */
+  if (e->flags & EDGE_ABNORMAL)
+    return;
 
-/* This function will remove the expression for VERSION from replacement 
-   consideration.n table TAB  If 'replace' is true, it is marked as 
-   replaceable, otherwise not.  */
+  g->e = e;
 
-static void
-finish_expr (temp_expr_table_p tab, int version, bool replace)
-{
-  value_expr_p info, tmp;
-  int partition;
+  eliminate_build (g, B);
 
-  /* Remove this expression from its dependent lists.  The partition dependence
-     list is retained and transfered later to whomever uses this version.  */
-  for (info = (value_expr_p) tab->version_info[version]; info; info = tmp)
+  if (elim_graph_size (g) != 0)
     {
-      partition = info->value;
-      gcc_assert (tab->partition_dep_list[partition]);
-      tmp = remove_value_from_list (&(tab->partition_dep_list[partition]), 
-                                   version);
-      gcc_assert (tmp);
-      free_value_expr (tab, tmp);
-      /* Only clear the bit when the dependency list is emptied via 
-         a replacement. Otherwise kill_expr will take care of it.  */
-      if (!(tab->partition_dep_list[partition]) && replace)
-        bitmap_clear_bit (tab->partition_in_use, partition);
-      tmp = info->next;
-      if (!replace)
-        free_value_expr (tab, info);
-    }
+      tree var;
 
-  if (replace)
-    {
-      tab->saw_replaceable = true;
-      bitmap_set_bit (tab->replaceable, version);
+      sbitmap_zero (g->visited);
+      VEC_truncate (int, g->stack, 0);
+
+      for (x = 0; VEC_iterate (tree, g->nodes, x, var); x++)
+        {
+         int p = var_to_partition (g->map, var);
+         if (!TEST_BIT (g->visited, p))
+           elim_forward (g, p);
+       }
+       
+      sbitmap_zero (g->visited);
+      while (VEC_length (int, g->stack) > 0)
+       {
+         x = VEC_pop (int, g->stack);
+         if (!TEST_BIT (g->visited, x))
+           elim_create (g, x);
+       }
     }
-  else
+
+  /* If there are any pending constant copies, issue them now.  */
+  while (VEC_length (tree, g->const_copies) > 0)
     {
-      gcc_assert (!bitmap_bit_p (tab->replaceable, version));
-      tab->version_info[version] = NULL;
+      tree src, dest;
+      src = VEC_pop (tree, g->const_copies);
+      dest = VEC_pop (tree, g->const_copies);
+      insert_copy_on_edge (e, dest, src);
     }
 }
 
 
-/* Mark the expression associated with VAR as replaceable, and enter
-   the defining stmt into the version_info table TAB.  */
+/* Take the ssa-name var_map MAP, and assign real variables to each 
+   partition.  */
 
 static void
-mark_replaceable (temp_expr_table_p tab, tree var)
+assign_vars (var_map map)
 {
-  value_expr_p info;
-  int version = SSA_NAME_VERSION (var);
-  finish_expr (tab, version, true);
+  int x, num;
+  tree var, root;
+  var_ann_t ann;
 
-  /* Move the dependence list to the pending list.  */
-  if (tab->version_info[version])
+  num = num_var_partitions (map);
+  for (x = 0; x < num; x++)
     {
-      info = (value_expr_p) tab->version_info[version]; 
-      for ( ; info->next; info = info->next)
-       continue;
-      info->next = tab->pending_dependence;
-      tab->pending_dependence = (value_expr_p)tab->version_info[version];
+      var = partition_to_var (map, x);
+      if (TREE_CODE (var) != SSA_NAME)
+       {
+         ann = var_ann (var);
+         /* It must already be coalesced.  */
+         gcc_assert (ann->out_of_ssa_tag == 1);
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "partition %d already has variable ", x);
+             print_generic_expr (dump_file, var, TDF_SLIM);
+             fprintf (dump_file, " assigned to it.\n");
+           }
+       }
+      else
+        {
+         root = SSA_NAME_VAR (var);
+         ann = var_ann (root);
+         /* If ROOT is already associated, create a new one.  */
+         if (ann->out_of_ssa_tag)
+           {
+             root = create_temp (root);
+             ann = var_ann (root);
+           }
+         /* ROOT has not been coalesced yet, so use it.  */
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "Partition %d is assigned to var ", x);
+             print_generic_stmt (dump_file, root, TDF_SLIM);
+           }
+         change_partition_var (map, root, x);
+       }
     }
-
-  tab->version_info[version] = SSA_NAME_DEF_STMT (var);
 }
 
 
-/* This function marks any expression in TAB which is dependent on PARTITION
-   as NOT replaceable.  CLEAR_BIT is used to determine whether partition_in_use
-   should have its bit cleared.  Since this routine can be called within an
-   EXECUTE_IF_SET_IN_BITMAP, the bit can't always be cleared.  */
+/* Replace use operand P with whatever variable it has been rewritten to based 
+   on the partitions in MAP.  EXPR is an optional expression vector over SSA 
+   versions which is used to replace P with an expression instead of a variable.
+   If the stmt is changed, return true.  */ 
 
-static inline void
-kill_expr (temp_expr_table_p tab, int partition, bool clear_bit)
+static inline bool
+replace_use_variable (var_map map, use_operand_p p, tree *expr)
 {
-  value_expr_p ptr;
-
-  /* Mark every active expr dependent on this var as not replaceable.  */
-  while ((ptr = tab->partition_dep_list[partition]) != NULL)
-    finish_expr (tab, ptr->value, false);
-
-  if (clear_bit)
-    bitmap_clear_bit (tab->partition_in_use, partition);
-}
+  tree new_var;
+  tree var = USE_FROM_PTR (p);
 
+  /* Check if we are replacing this variable with an expression.  */
+  if (expr)
+    {
+      int version = SSA_NAME_VERSION (var);
+      if (expr[version])
+        {
+         tree new_expr = GIMPLE_STMT_OPERAND (expr[version], 1);
+         SET_USE (p, new_expr);
 
-/* This function kills all expressions in TAB which are dependent on virtual 
-   DEFs.  CLEAR_BIT determines whether partition_in_use gets cleared.  */
+         /* Clear the stmt's RHS, or GC might bite us.  */
+         GIMPLE_STMT_OPERAND (expr[version], 1) = NULL_TREE;
+         return true;
+       }
+    }
 
-static inline void
-kill_virtual_exprs (temp_expr_table_p tab, bool clear_bit)
-{
-  kill_expr (tab, VIRTUAL_PARTITION (tab), clear_bit);
+  new_var = var_to_partition_to_var (map, var);
+  if (new_var)
+    {
+      SET_USE (p, new_var);
+      set_is_used (new_var);
+      return true;
+    }
+  return false;
 }
 
 
-/* This function processes basic block BB, and looks for variables which can
-   be replaced by their expressions.  Results are stored in TAB.  */
+/* Replace def operand DEF_P with whatever variable it has been rewritten to 
+   based on the partitions in MAP.  EXPR is an optional expression vector over
+   SSA versions which is used to replace DEF_P with an expression instead of a 
+   variable.  If the stmt is changed, return true.  */ 
 
-static void
-find_replaceable_in_bb (temp_expr_table_p tab, basic_block bb)
+static inline bool
+replace_def_variable (var_map map, def_operand_p def_p, tree *expr)
 {
-  block_stmt_iterator bsi;
-  tree stmt, def, use;
-  stmt_ann_t ann;
-  int partition;
-  var_map map = tab->map;
-  value_expr_p p;
-  ssa_op_iter iter;
-
-  for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-    {
-      stmt = bsi_stmt (bsi);
-      ann = stmt_ann (stmt);
-
-      /* Determine if this stmt finishes an existing expression.  */
-      FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
-       {
-         unsigned ver = SSA_NAME_VERSION (use);
-
-         if (tab->version_info[ver])
-           {
-             bool same_root_var = false;
-             ssa_op_iter iter2;
-             bitmap vars = tab->expr_vars[ver];
-
-             /* See if the root variables are the same.  If they are, we
-                do not want to do the replacement to avoid problems with
-                code size, see PR tree-optimization/17549.  */
-             FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter2, SSA_OP_DEF)
-               {
-                 if (bitmap_bit_p (vars, DECL_UID (SSA_NAME_VAR (def))))
-                   {
-                     same_root_var = true;
-                     break;
-                   }
-               }
-
-             /* Mark expression as replaceable unless stmt is volatile
-                or DEF sets the same root variable as STMT.  */
-             if (!ann->has_volatile_ops && !same_root_var)
-               mark_replaceable (tab, use);
-             else
-               finish_expr (tab, ver, false);
-           }
-       }
-      
-      /* Next, see if this stmt kills off an active expression.  */
-      FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
-       {
-         partition = var_to_partition (map, def);
-         if (partition != NO_PARTITION && tab->partition_dep_list[partition])
-           kill_expr (tab, partition, true);
-       }
-
-      /* Now see if we are creating a new expression or not.  */
-      if (!ann->has_volatile_ops)
-       check_replaceable (tab, stmt);
+  tree new_var;
+  tree var = DEF_FROM_PTR (def_p);
 
-      /* Free any unused dependency lists.  */
-      while ((p = tab->pending_dependence))
-       {
-         tab->pending_dependence = p->next;
-         free_value_expr (tab, p);
-       }
+  /* Do nothing if we are replacing this variable with an expression.  */
+  if (expr && expr[SSA_NAME_VERSION (var)])
+    return true;
 
-      /* A V_{MAY,MUST}_DEF kills any expression using a virtual operand.  */
-      if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
-        kill_virtual_exprs (tab, true);
+  new_var = var_to_partition_to_var (map, var);
+  if (new_var)
+    {
+      SET_DEF (def_p, new_var);
+      set_is_used (new_var);
+      return true;
     }
+  return false;
 }
 
 
-/* This function is the driver routine for replacement of temporary expressions
-   in the SSA->normal phase, operating on MAP.  If there are replaceable 
-   expressions, a table is returned which maps SSA versions to the 
-   expressions they should be replaced with.  A NULL_TREE indicates no 
-   replacement should take place.  If there are no replacements at all, 
-   NULL is returned by the function, otherwise an expression vector indexed
-   by SSA_NAME version numbers.  */
+/* Remove any PHI node which is a virtual PHI.  */
 
-static tree *
-find_replaceable_exprs (var_map map)
+static void
+eliminate_virtual_phis (void)
 {
   basic_block bb;
-  unsigned i;
-  temp_expr_table_p table;
-  tree *ret;
+  tree phi, next;
 
-  table = new_temp_expr_table (map);
   FOR_EACH_BB (bb)
     {
-      bitmap_iterator bi;
-
-      find_replaceable_in_bb (table, bb);
-      EXECUTE_IF_SET_IN_BITMAP ((table->partition_in_use), 0, i, bi)
+      for (phi = phi_nodes (bb); phi; phi = next)
         {
-         kill_expr (table, i, false);
+         next = PHI_CHAIN (phi);
+         if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
+           {
+#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++)
+               {
+                 tree arg = PHI_ARG_DEF (phi, i);
+                 if (TREE_CODE (arg) == SSA_NAME 
+                     && is_gimple_reg (SSA_NAME_VAR (arg)))
+                   {
+                     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);
+                     internal_error ("SSA corruption");
+                   }
+               }
+#endif
+             remove_phi_node (phi, NULL_TREE, true);
+           }
        }
     }
-
-  ret = free_temp_expr_table (table);
-  return ret;
-}
-
-
-/* Dump TER expression table EXPR to file F.  */
-
-static void
-dump_replaceable_exprs (FILE *f, tree *expr)
-{
-  tree stmt, var;
-  int x;
-  fprintf (f, "\nReplacing Expressions\n");
-  for (x = 0; x < (int)num_ssa_names + 1; x++)
-    if (expr[x])
-      {
-        stmt = expr[x];
-       var = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
-       gcc_assert (var != NULL_TREE);
-       print_generic_expr (f, var, TDF_SLIM);
-       fprintf (f, " replace with --> ");
-       print_generic_expr (f, TREE_OPERAND (stmt, 1), TDF_SLIM);
-       fprintf (f, "\n");
-      }
-  fprintf (f, "\n");
 }
 
 
@@ -1869,15 +669,12 @@ rewrite_trees (var_map map, tree *values)
   FOR_EACH_BB (bb)
     {
       tree phi;
-
       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
        {
          tree T0 = var_to_partition_to_var (map, PHI_RESULT (phi));
-      
          if (T0 == NULL_TREE)
            {
              int i;
-
              for (i = 0; i < PHI_NUM_ARGS (phi); i++)
                {
                  tree arg = PHI_ARG_DEF (phi, i);
@@ -1915,8 +712,8 @@ rewrite_trees (var_map map, tree *values)
          ann = stmt_ann (stmt);
          changed = false;
 
-         if (TREE_CODE (stmt) == MODIFY_EXPR 
-             && (TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME))
+         if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT 
+             && (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == SSA_NAME))
            is_copy = true;
 
          copy_use_p = NULL_USE_OPERAND_P;
@@ -1962,7 +759,12 @@ rewrite_trees (var_map map, tree *values)
          if (remove)
            bsi_remove (&si, true);
          else
-           bsi_next (&si);
+           {
+             if (changed)
+               if (maybe_clean_or_replace_eh_stmt (stmt, stmt))
+                 tree_purge_dead_eh_edges (bb);
+             bsi_next (&si);
+           }
        }
 
       phi = phi_nodes (bb);
@@ -1977,9 +779,6 @@ rewrite_trees (var_map map, tree *values)
   delete_elim_graph (g);
 }
 
-
-DEF_VEC_ALLOC_P(edge,heap);
-
 /* 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;
@@ -1989,8 +788,10 @@ static edge leader_match = NULL;
 
 
 /* Pass this function to make_forwarder_block so that all the edges with
-   matching PENDING_STMT lists to 'curr_stmt_list' get redirected.  */
-static bool 
+   matching PENDING_STMT lists to 'curr_stmt_list' get redirected.  E is the
+   edge to test for a match.  */
+
+static inline bool 
 same_stmt_list_p (edge e)
 {
   return (e->aux == (PTR) leader_match) ? true : false;
@@ -1998,21 +799,22 @@ 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_tree s1, const_tree s2)
 {
 #ifdef ENABLE_CHECKING
-  gcc_assert (TREE_CODE (s1) == MODIFY_EXPR);
-  gcc_assert (TREE_CODE (s2) == MODIFY_EXPR);
-  gcc_assert (DECL_P (TREE_OPERAND (s1, 0)));
-  gcc_assert (DECL_P (TREE_OPERAND (s2, 0)));
+  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)));
 #endif
 
-  if (TREE_OPERAND (s1, 0) != TREE_OPERAND (s2, 0))
+  if (GIMPLE_STMT_OPERAND (s1, 0) != GIMPLE_STMT_OPERAND (s2, 0))
     return false;
 
-  s1 = TREE_OPERAND (s1, 1);
-  s2 = TREE_OPERAND (s2, 1);
+  s1 = GIMPLE_STMT_OPERAND (s1, 1);
+  s2 = GIMPLE_STMT_OPERAND (s2, 1);
 
   if (s1 != s2)
     return false;
@@ -2021,11 +823,11 @@ identical_copies_p (tree s1, tree s2)
 }
 
 
-/* Compare the PENDING_STMT list for two edges, and return true if the lists
+/* Compare the PENDING_STMT list for edges E1 and E2. Return true if the lists
    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);
@@ -2070,6 +872,158 @@ fini_analyze_edges_for_bb (void)
   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 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)
+{
+  tree stmts;
+  basic_block b_exit, b_pheader, b_loop = single_edge->src;
+  edge_iterator ei;
+  edge e;
+  block_stmt_iterator bsi, bsi_exit;
+  tree_stmt_iterator tsi;
+  tree expr, 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;
+
+  bsi_exit = bsi_after_labels (b_exit);
+
+  /* Get the last stmt in the loop body.  */
+  bsi = bsi_last (single_edge->src);
+  stmt = bsi_stmt (bsi);
+
+  if (TREE_CODE (stmt) != COND_EXPR)
+    return false;
+
+  expr = COND_EXPR_COND (stmt);
+  /* Iterate over the insns on the latch and count them.  */
+  for (tsi = tsi_start (stmts); !tsi_end_p (tsi); tsi_next (&tsi))
+    {
+      tree stmt1 = tsi_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 (TREE_CODE (stmt1) != GIMPLE_MODIFY_STMT)
+        return false;
+      var = GIMPLE_STMT_OPERAND (stmt1, 0);
+      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 = tsi_start (stmts); !tsi_end_p (tsi); tsi_next (&tsi))
+    {
+      tree stmt1 = tsi_stmt (tsi);
+      tree var, tmp_var, copy;
+
+      /* Create a new variable to load back the value of var in case
+         we exit the loop.  */
+      var = GIMPLE_STMT_OPERAND (stmt1, 0);
+      tmp_var = create_temp (var);
+      copy = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (tmp_var), tmp_var, var);
+      set_is_used (tmp_var);
+      bsi_insert_before (&bsi, copy, BSI_SAME_STMT);
+      copy = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (tmp_var), var, tmp_var);
+      bsi_insert_before (&bsi_exit, copy, BSI_SAME_STMT);
+    }
+
+  PENDING_STMT (single_edge) = 0;
+  /* Insert the new stmts to the loop body.  */
+  bsi_insert_before (&bsi, stmts, BSI_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.  */
@@ -2108,6 +1062,7 @@ analyze_edges_for_bb (basic_block bb)
          bsi_commit_one_edge_insert (e, NULL);
       return;
     }
+
   /* Find out how many edges there are with interesting pending stmts on them.  
      Commit the stmts on edges we are not interested in.  */
   FOR_EACH_EDGE (e, ei, bb->preds)
@@ -2142,7 +1097,12 @@ 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))
+         bsi_commit_one_edge_insert (single_edge, NULL);
+      }
       return;
     }
 
@@ -2198,11 +1158,9 @@ analyze_edges_for_bb (basic_block bb)
       return;
     }
 
-
   if (dump_file)
     fprintf (dump_file, "\nOpportunities in BB %d for stmt/block reduction:\n",
             bb->index);
-
   
   /* For each common list, create a forwarding block and issue the stmt's
      in that block.  */
@@ -2216,7 +1174,7 @@ analyze_edges_for_bb (basic_block bb)
        leader_match = leader;
 
        /* The tree_* cfg manipulation routines use the PENDING_EDGE field
-          for various PHI manipulations, so it gets cleared whhen calls are 
+          for various PHI manipulations, so it gets cleared when calls are 
           made to make_forwarder_block(). So make sure the edge is clear, 
           and use the saved stmt list.  */
        PENDING_STMT (leader) = NULL;
@@ -2329,32 +1287,23 @@ perform_edge_inserts (void)
 }
 
 
-/* Remove the variables specified in MAP from SSA form.  FLAGS indicate what
-   options should be used.  */
+/* Remove the ssa-names in the current function and translate them into normal
+   compiler variables.  PERFORM_TER is true if Temporary Expression Replacement
+   should also be used.  */
 
 static void
-remove_ssa_form (var_map map, int flags)
+remove_ssa_form (bool perform_ter)
 {
-  tree_live_info_p liveinfo;
   basic_block bb;
   tree phi, next;
   tree *values = NULL;
+  var_map map;
 
-  /* If we are not combining temps, don't calculate live ranges for variables
-     with only one SSA version.  */
-  if ((flags & SSANORM_COMBINE_TEMPS) == 0)
-    compact_var_map (map, VARMAP_NO_SINGLE_DEFS);
-  else
-    compact_var_map (map, VARMAP_NORMAL);
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    dump_var_map (dump_file, map);
-
-  liveinfo = coalesce_ssa_name (map, flags);
+  map = coalesce_ssa_name ();
 
-  /* Make sure even single occurrence variables are in the list now.  */
-  if ((flags & SSANORM_COMBINE_TEMPS) == 0)
-    compact_var_map (map, VARMAP_NORMAL);
+  /* Return to viewing the variable list as just all reference variables after
+     coalescing has been performed.  */
+  partition_view_normal (map, false);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -2362,7 +1311,7 @@ remove_ssa_form (var_map map, int flags)
       dump_var_map (dump_file, map);
     }
 
-  if (flags & SSANORM_PERFORM_TER)
+  if (perform_ter)
     {
       values = find_replaceable_exprs (map);
       if (values && dump_file && (dump_flags & TDF_DETAILS))
@@ -2374,45 +1323,32 @@ remove_ssa_form (var_map map, int flags)
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      fprintf (dump_file, "After Root variable replacement:\n");
+      fprintf (dump_file, "After Base variable replacement:\n");
       dump_var_map (dump_file, map);
     }
 
-  if ((flags & SSANORM_COMBINE_TEMPS) && liveinfo)
-    {
-      coalesce_vars (map, liveinfo);
-      if (dump_file && (dump_flags & TDF_DETAILS))
-       {
-         fprintf (dump_file, "After variable memory coalescing:\n");
-         dump_var_map (dump_file, map);
-       }
-    }
-  
-  if (liveinfo)
-    delete_tree_live_info (liveinfo);
-
   rewrite_trees (map, values);
 
   if (values)
     free (values);
 
-  /* Remove phi nodes which have been translated back to real variables.  */
+  /* 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);
+         remove_phi_node (phi, NULL_TREE, true);
        }
     }
 
-  /* we no longer maintain the SSA operand cache at this point.  */
-  fini_ssa_operands ();
-
   /* If any copies were inserted on edges, analyze and insert them now.  */
   perform_edge_inserts ();
+
+  delete_var_map (map);
 }
 
+
 /* Search every PHI node for arguments associated with backedges which
    we can trivially determine will need a copy (the argument is either
    not an SSA_NAME or the argument has a different underlying variable
@@ -2446,15 +1382,13 @@ insert_backedge_copies (void)
              tree arg = PHI_ARG_DEF (phi, i);
              edge e = 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 a different underlying variable and
-                we are not combining temporaries, then we will
-                need a copy statement.  */
+             /* If the argument is not an SSA_NAME, then we will need a 
+                constant initialization.  If the argument is an SSA_NAME with
+                a different underlying variable then a copy statement will be 
+                needed.  */
              if ((e->flags & EDGE_DFS_BACK)
                  && (TREE_CODE (arg) != SSA_NAME
-                     || (!flag_tree_combine_temps
-                         && SSA_NAME_VAR (arg) != result_var)))
+                     || SSA_NAME_VAR (arg) != result_var))
                {
                  tree stmt, name, last = NULL;
                  block_stmt_iterator bsi;
@@ -2466,7 +1400,6 @@ insert_backedge_copies (void)
                  /* 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.
                     However, better safe than sorry. 
-
                     If the block ends with a control statement or
                     something that might throw, then we have to
                     insert this assignment before the last
@@ -2481,12 +1414,12 @@ insert_backedge_copies (void)
                        continue;
                    }
 
-                 /* Create a new instance of the underlying
-                    variable of the PHI result.  */
-                 stmt = build2 (MODIFY_EXPR, TREE_TYPE (result_var),
-                                NULL_TREE, PHI_ARG_DEF (phi, i));
+                 /* Create a new instance of the underlying variable of the 
+                    PHI result.  */
+                 stmt = build_gimple_modify_stmt (NULL_TREE,
+                                                  PHI_ARG_DEF (phi, i));
                  name = make_ssa_name (result_var, stmt);
-                 TREE_OPERAND (stmt, 0) = name;
+                 GIMPLE_STMT_OPERAND (stmt, 0) = name;
 
                  /* Insert the new statement into the block and update
                     the PHI node.  */
@@ -2501,17 +1434,13 @@ insert_backedge_copies (void)
     }
 }
 
-/* Take the current function out of SSA form, as described in
+/* Take the current function out of SSA form, translating PHIs as described in
    R. Morgan, ``Building an Optimizing Compiler'',
    Butterworth-Heinemann, Boston, MA, 1998. pp 176-186.  */
 
-static void
+static unsigned int
 rewrite_out_of_ssa (void)
 {
-  var_map map;
-  int var_flags = 0;
-  int ssa_flags = 0;
-
   /* If elimination of a PHI requires inserting a copy on a backedge,
      then we will have to split the backedge which has numerous
      undesirable performance effects.
@@ -2520,41 +1449,27 @@ rewrite_out_of_ssa (void)
      copies into the loop itself.  */
   insert_backedge_copies ();
 
-  if (!flag_tree_live_range_split)
-    ssa_flags |= SSANORM_COALESCE_PARTITIONS;
-    
   eliminate_virtual_phis ();
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
 
-  /* We cannot allow unssa to un-gimplify trees before we instrument them.  */
-  if (flag_tree_ter && !flag_mudflap)
-    var_flags = SSA_VAR_MAP_REF_COUNT;
-
-  map = create_ssa_var_map (var_flags);
-
-  if (flag_tree_combine_temps)
-    ssa_flags |= SSANORM_COMBINE_TEMPS;
-  if (flag_tree_ter && !flag_mudflap)
-    ssa_flags |= SSANORM_PERFORM_TER;
-
-  remove_ssa_form (map, ssa_flags);
+  remove_ssa_form (flag_tree_ter && !flag_mudflap);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
 
-  /* Flush out flow graph and SSA data.  */
-  delete_var_map (map);
-
-  in_ssa_p = false;
+  cfun->gimple_df->in_ssa_p = false;
+  return 0;
 }
 
 
 /* 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 */
@@ -2570,6 +1485,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 */
+ }
 };