]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree-into-ssa.c
Simple patch only add assumed-rank to the list of possible attributes.
[thirdparty/gcc.git] / gcc / tree-into-ssa.c
index 01203dece183b52cbbaf6c2dcfffaa2d1cb0b080..c24931effac557712b658821309dfece5bdf787c 100644 (file)
@@ -1,5 +1,5 @@
 /* Rewrite a program in Normal form into SSA.
-   Copyright (C) 2001-2014 Free Software Foundation, Inc.
+   Copyright (C) 2001-2020 Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
@@ -21,38 +21,26 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "rtl.h"
 #include "tree.h"
-#include "flags.h"
-#include "tm_p.h"
-#include "langhooks.h"
-#include "basic-block.h"
-#include "function.h"
-#include "gimple-pretty-print.h"
-#include "hash-table.h"
-#include "tree-ssa-alias.h"
-#include "internal-fn.h"
-#include "gimple-expr.h"
-#include "is-a.h"
 #include "gimple.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "gimple-pretty-print.h"
+#include "diagnostic-core.h"
+#include "langhooks.h"
+#include "cfganal.h"
 #include "gimple-iterator.h"
-#include "gimple-ssa.h"
 #include "tree-cfg.h"
-#include "tree-phinodes.h"
-#include "ssa-iterators.h"
-#include "stringpool.h"
-#include "tree-ssanames.h"
 #include "tree-into-ssa.h"
-#include "expr.h"
 #include "tree-dfa.h"
 #include "tree-ssa.h"
-#include "tree-inline.h"
-#include "tree-pass.h"
-#include "cfgloop.h"
 #include "domwalk.h"
-#include "params.h"
-#include "diagnostic-core.h"
-#include "tree-into-ssa.h"
+#include "statistics.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "asan.h"
 
 #define PERCENT(x,y) ((float)(x) * 100.0 / (float)(y))
 
@@ -64,7 +52,7 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Structure to map a variable VAR to the set of blocks that contain
    definitions for VAR.  */
-struct def_blocks_d
+struct def_blocks
 {
   /* Blocks that contain definitions of VAR.  Bit I will be set if the
      Ith block contains a definition of VAR.  */
@@ -78,9 +66,6 @@ struct def_blocks_d
   bitmap livein_blocks;
 };
 
-typedef struct def_blocks_d *def_blocks_p;
-
-
 /* Stack of trees used to restore the global currdefs to its original
    state after completing rewriting of a block and its dominator
    children.  Its elements have the following properties:
@@ -113,12 +98,12 @@ static sbitmap interesting_blocks;
 /* Set of SSA names that have been marked to be released after they
    were registered in the replacement table.  They will be finally
    released after we finish updating the SSA web.  */
-static bitmap names_to_release;
+bitmap names_to_release;
 
 /* vec of vec of PHIs to rewrite in a basic block.  Element I corresponds
    the to basic block with index I.  Allocated once per compilation, *not*
    released between different functions.  */
-static vec<gimple_vec> phis_to_rewrite;
+static vec< vec<gphi *> > phis_to_rewrite;
 
 /* The bitmap of non-NULL elements of PHIS_TO_REWRITE.  */
 static bitmap blocks_with_phis_to_rewrite;
@@ -168,7 +153,7 @@ enum need_phi_state {
 };
 
 /* Information stored for both SSA names and decls.  */
-struct common_info_d
+struct common_info
 {
   /* This field indicates whether or not the variable may need PHI nodes.
      See the enum's definition for more detailed information about the
@@ -179,33 +164,24 @@ struct common_info_d
   tree current_def;
 
   /* Definitions for this var.  */
-  struct def_blocks_d def_blocks;
+  struct def_blocks def_blocks;
 };
 
-/* The information associated with decls and SSA names.  */
-typedef struct common_info_d *common_info_p;
-
 /* Information stored for decls.  */
-struct var_info_d
+struct var_info
 {
   /* The variable.  */
   tree var;
 
   /* Information stored for both SSA names and decls.  */
-  struct common_info_d info;
+  common_info info;
 };
 
-/* The information associated with decls.  */
-typedef struct var_info_d *var_info_p;
-
 
 /* VAR_INFOS hashtable helpers.  */
 
-struct var_info_hasher : typed_free_remove <var_info_d>
+struct var_info_hasher : free_ptr_hash <var_info>
 {
-  typedef var_info_d *value_type;
-  typedef var_info_d *compare_type;
-  typedef int store_values_directly;
   static inline hashval_t hash (const value_type &);
   static inline bool equal (const value_type &, const compare_type &);
 };
@@ -240,13 +216,10 @@ struct ssa_name_info
   bitmap repl_set;
 
   /* Information stored for both SSA names and decls.  */
-  struct common_info_d info;
+  common_info info;
 };
 
-/* The information associated with names.  */
-typedef struct ssa_name_info *ssa_name_info_p;
-
-static vec<ssa_name_info_p> info_for_ssa_name;
+static vec<ssa_name_info *> info_for_ssa_name;
 static unsigned current_info_for_ssa_name_age;
 
 static bitmap_obstack update_ssa_obstack;
@@ -300,7 +273,7 @@ marked_for_renaming (tree sym)
    decided in mark_def_sites.  */
 
 static inline bool
-rewrite_uses_p (gimple stmt)
+rewrite_uses_p (gimple *stmt)
 {
   return gimple_visited_p (stmt);
 }
@@ -309,7 +282,7 @@ rewrite_uses_p (gimple stmt)
 /* Set the rewrite marker on STMT to the value given by REWRITE_P.  */
 
 static inline void
-set_rewrite_uses (gimple stmt, bool rewrite_p)
+set_rewrite_uses (gimple *stmt, bool rewrite_p)
 {
   gimple_set_visited (stmt, rewrite_p);
 }
@@ -324,7 +297,7 @@ set_rewrite_uses (gimple stmt, bool rewrite_p)
    registered, but they don't need to have their uses renamed.  */
 
 static inline bool
-register_defs_p (gimple stmt)
+register_defs_p (gimple *stmt)
 {
   return gimple_plf (stmt, GF_PLF_1) != 0;
 }
@@ -333,7 +306,7 @@ register_defs_p (gimple stmt)
 /* If REGISTER_DEFS_P is true, mark STMT to have its DEFs registered.  */
 
 static inline void
-set_register_defs (gimple stmt, bool register_defs_p)
+set_register_defs (gimple *stmt, bool register_defs_p)
 {
   gimple_set_plf (stmt, GF_PLF_1, register_defs_p);
 }
@@ -341,7 +314,7 @@ set_register_defs (gimple stmt, bool register_defs_p)
 
 /* Get the information associated with NAME.  */
 
-static inline ssa_name_info_p
+static inline ssa_name_info *
 get_ssa_name_ann (tree name)
 {
   unsigned ver = SSA_NAME_VERSION (name);
@@ -378,16 +351,16 @@ get_ssa_name_ann (tree name)
 
 /* Return and allocate the auxiliar information for DECL.  */
 
-static inline var_info_p
+static inline var_info *
 get_var_info (tree decl)
 {
-  struct var_info_d vi;
-  var_info_d **slot;
+  var_info vi;
+  var_info **slot;
   vi.var = decl;
   slot = var_infos->find_slot_with_hash (&vi, DECL_UID (decl), INSERT);
   if (*slot == NULL)
     {
-      var_info_p v = XCNEW (struct var_info_d);
+      var_info *v = XCNEW (var_info);
       v->var = decl;
       *slot = v;
       return v;
@@ -411,7 +384,7 @@ clear_ssa_name_info (void)
 
 /* Get access to the auxiliar information stored per SSA name or decl.  */
 
-static inline common_info_p
+static inline common_info *
 get_common_info (tree var)
 {
   if (TREE_CODE (var) == SSA_NAME)
@@ -444,12 +417,12 @@ set_current_def (tree var, tree def)
 static void
 initialize_flags_in_bb (basic_block bb)
 {
-  gimple stmt;
+  gimple *stmt;
   gimple_stmt_iterator gsi;
 
   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     {
-      gimple phi = gsi_stmt (gsi);
+      gimple *phi = gsi_stmt (gsi);
       set_rewrite_uses (phi, false);
       set_register_defs (phi, false);
     }
@@ -482,10 +455,10 @@ mark_block_for_update (basic_block bb)
    where VAR is live on entry (livein).  If no entry is found in
    DEF_BLOCKS, a new one is created and returned.  */
 
-static inline struct def_blocks_d *
-get_def_blocks_for (common_info_p info)
+static inline def_blocks *
+get_def_blocks_for (common_info *info)
 {
-  struct def_blocks_d *db_p = &info->def_blocks;
+  def_blocks *db_p = &info->def_blocks;
   if (!db_p->def_blocks)
     {
       db_p->def_blocks = BITMAP_ALLOC (&update_ssa_obstack);
@@ -503,8 +476,8 @@ get_def_blocks_for (common_info_p info)
 static void
 set_def_block (tree var, basic_block bb, bool phi_p)
 {
-  struct def_blocks_d *db_p;
-  common_info_p info;
+  def_blocks *db_p;
+  common_info *info;
 
   info = get_common_info (var);
   db_p = get_def_blocks_for (info);
@@ -538,8 +511,8 @@ set_def_block (tree var, basic_block bb, bool phi_p)
 static void
 set_livein_block (tree var, basic_block bb)
 {
-  common_info_p info;
-  struct def_blocks_d *db_p;
+  common_info *info;
+  def_blocks *db_p;
 
   info = get_common_info (var);
   db_p = get_def_blocks_for (info);
@@ -573,9 +546,9 @@ static inline bool
 is_old_name (tree name)
 {
   unsigned ver = SSA_NAME_VERSION (name);
-  if (!new_ssa_names)
+  if (!old_ssa_names)
     return false;
-  return (ver < SBITMAP_SIZE (new_ssa_names)
+  return (ver < SBITMAP_SIZE (old_ssa_names)
          && bitmap_bit_p (old_ssa_names, ver));
 }
 
@@ -665,7 +638,7 @@ add_new_name_mapping (tree new_tree, tree old)
    we create.  */
 
 static void
-mark_def_sites (basic_block bb, gimple stmt, bitmap kills)
+mark_def_sites (basic_block bb, gimple *stmt, bitmap kills)
 {
   tree def;
   use_operand_p use_p;
@@ -697,6 +670,8 @@ mark_def_sites (basic_block bb, gimple stmt, bitmap kills)
   FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
     {
       tree sym = USE_FROM_PTR (use_p);
+      if (TREE_CODE (sym) == SSA_NAME)
+       continue;
       gcc_checking_assert (DECL_P (sym));
       if (!bitmap_bit_p (kills, DECL_UID (sym)))
        set_livein_block (sym, bb);
@@ -707,6 +682,8 @@ mark_def_sites (basic_block bb, gimple stmt, bitmap kills)
      each def to the set of killed symbols.  */
   FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
     {
+      if (TREE_CODE (def) == SSA_NAME)
+       continue;
       gcc_checking_assert (DECL_P (def));
       set_def_block (def, bb, false);
       bitmap_set_bit (kills, DECL_UID (def));
@@ -937,10 +914,10 @@ prune_unused_phi_nodes (bitmap phis, bitmap kills, bitmap uses)
    where VAR is live on entry (livein).  Return NULL, if no entry is
    found in DEF_BLOCKS.  */
 
-static inline struct def_blocks_d *
+static inline def_blocks *
 find_def_blocks_for (tree var)
 {
-  def_blocks_p p = &get_common_info (var)->def_blocks;
+  def_blocks *p = &get_common_info (var)->def_blocks;
   if (!p->def_blocks)
     return NULL;
   return p;
@@ -950,9 +927,9 @@ find_def_blocks_for (tree var)
 /* Marks phi node PHI in basic block BB for rewrite.  */
 
 static void
-mark_phi_for_rewrite (basic_block bb, gimple phi)
+mark_phi_for_rewrite (basic_block bb, gphi *phi)
 {
-  gimple_vec phis;
+  vec<gphi *> phis;
   unsigned n, idx = bb->index;
 
   if (rewrite_uses_p (phi))
@@ -963,14 +940,18 @@ mark_phi_for_rewrite (basic_block bb, gimple phi)
   if (!blocks_with_phis_to_rewrite)
     return;
 
-  bitmap_set_bit (blocks_with_phis_to_rewrite, idx);
-
-  n = (unsigned) last_basic_block_for_fn (cfun) + 1;
-  if (phis_to_rewrite.length () < n)
-    phis_to_rewrite.safe_grow_cleared (n);
+  if (bitmap_set_bit (blocks_with_phis_to_rewrite, idx))
+    {
+      n = (unsigned) last_basic_block_for_fn (cfun) + 1;
+      if (phis_to_rewrite.length () < n)
+       phis_to_rewrite.safe_grow_cleared (n);
 
-  phis = phis_to_rewrite[idx];
-  phis.reserve (10);
+      phis = phis_to_rewrite[idx];
+      gcc_assert (!phis.exists ());
+      phis.create (10);
+    }
+  else
+    phis = phis_to_rewrite[idx];
 
   phis.safe_push (phi);
   phis_to_rewrite[idx] = phis;
@@ -991,10 +972,10 @@ insert_phi_nodes_for (tree var, bitmap phi_insertion_points, bool update_p)
 {
   unsigned bb_index;
   edge e;
-  gimple phi;
+  gphi *phi;
   basic_block bb;
   bitmap_iterator bi;
-  struct def_blocks_d *def_map = find_def_blocks_for (var);
+  def_blocks *def_map = find_def_blocks_for (var);
 
   /* Remove the blocks where we already have PHI nodes for VAR.  */
   bitmap_and_compl_into (phi_insertion_points, def_map->phi_blocks);
@@ -1051,8 +1032,8 @@ insert_phi_nodes_for (tree var, bitmap phi_insertion_points, bool update_p)
          tracked_var = target_for_debug_bind (var);
          if (tracked_var)
            {
-             gimple note = gimple_build_debug_bind (tracked_var,
-                                                    PHI_RESULT (phi),
+             gimple *note = gimple_build_debug_bind (tracked_var,
+                                                     PHI_RESULT (phi),
                                                     phi);
              gimple_stmt_iterator si = gsi_after_labels (bb);
              gsi_insert_before (&si, note, GSI_SAME_STMT);
@@ -1070,8 +1051,8 @@ insert_phi_nodes_for (tree var, bitmap phi_insertion_points, bool update_p)
 static int
 insert_phi_nodes_compare_var_infos (const void *a, const void *b)
 {
-  const struct var_info_d *defa = *(struct var_info_d * const *)a;
-  const struct var_info_d *defb = *(struct var_info_d * const *)b;
+  const var_info *defa = *(var_info * const *)a;
+  const var_info *defb = *(var_info * const *)b;
   if (DECL_UID (defa->var) < DECL_UID (defb->var))
     return -1;
   else
@@ -1087,11 +1068,64 @@ insert_phi_nodes (bitmap_head *dfs)
 {
   hash_table<var_info_hasher>::iterator hi;
   unsigned i;
-  var_info_p info;
+  var_info *info;
 
   timevar_push (TV_TREE_INSERT_PHI_NODES);
 
-  auto_vec<var_info_p> vars (var_infos->elements ());
+  /* When the gimplifier introduces SSA names it cannot easily avoid
+     situations where abnormal edges added by CFG construction break
+     the use-def dominance requirement.  For this case rewrite SSA
+     names with broken use-def dominance out-of-SSA and register them
+     for PHI insertion.  We only need to do this if abnormal edges
+     can appear in the function.  */
+  tree name;
+  if (cfun->calls_setjmp
+      || cfun->has_nonlocal_label)
+    FOR_EACH_SSA_NAME (i, name, cfun)
+      {
+       gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+       if (SSA_NAME_IS_DEFAULT_DEF (name))
+         continue;
+
+       basic_block def_bb = gimple_bb (def_stmt);
+       imm_use_iterator it;
+       gimple *use_stmt;
+       bool need_phis = false;
+       FOR_EACH_IMM_USE_STMT (use_stmt, it, name)
+         {
+           basic_block use_bb = gimple_bb (use_stmt);
+           if (use_bb != def_bb
+               && ! dominated_by_p (CDI_DOMINATORS, use_bb, def_bb))
+             need_phis = true;
+         }
+       if (need_phis)
+         {
+           tree var = create_tmp_reg (TREE_TYPE (name));
+           use_operand_p use_p;
+           FOR_EACH_IMM_USE_STMT (use_stmt, it, name)
+             {
+               basic_block use_bb = gimple_bb (use_stmt);
+               FOR_EACH_IMM_USE_ON_STMT (use_p, it)
+                   SET_USE (use_p, var);
+               update_stmt (use_stmt);
+               set_livein_block (var, use_bb);
+               set_rewrite_uses (use_stmt, true);
+               bitmap_set_bit (interesting_blocks, use_bb->index);
+             }
+           def_operand_p def_p;
+           ssa_op_iter dit;
+           FOR_EACH_SSA_DEF_OPERAND (def_p, def_stmt, dit, SSA_OP_DEF)
+             if (DEF_FROM_PTR (def_p) == name)
+               SET_DEF (def_p, var);
+           update_stmt (def_stmt);
+           set_def_block (var, def_bb, false);
+           set_register_defs (def_stmt, true);
+           bitmap_set_bit (interesting_blocks, def_bb->index);
+           release_ssa_name (name);
+         }
+      }
+
+  auto_vec<var_info *> vars (var_infos->elements ());
   FOR_EACH_HASH_TABLE_ELEMENT (*var_infos, info, var_info_p, hi)
     if (info->info.need_phi_state != NEED_PHI_STATE_NO)
       vars.quick_push (info);
@@ -1117,7 +1151,7 @@ insert_phi_nodes (bitmap_head *dfs)
 static void
 register_new_def (tree def, tree sym)
 {
-  common_info_p info = get_common_info (sym);
+  common_info *info = get_common_info (sym);
   tree currdef;
 
   /* If this variable is set in a single basic block and all uses are
@@ -1185,7 +1219,7 @@ register_new_def (tree def, tree sym)
 static tree
 get_reaching_def (tree var)
 {
-  common_info_p info = get_common_info (var);
+  common_info *info = get_common_info (var);
   tree currdef;
 
   /* Lookup the current reaching definition for VAR.  */
@@ -1196,6 +1230,8 @@ get_reaching_def (tree var)
   if (currdef == NULL_TREE)
     {
       tree sym = DECL_P (var) ? var : SSA_NAME_VAR (var);
+      if (! sym)
+       sym = create_tmp_reg (TREE_TYPE (var));
       currdef = get_or_create_ssa_default_def (cfun, sym);
     }
 
@@ -1208,7 +1244,7 @@ get_reaching_def (tree var)
 /* Helper function for rewrite_stmt.  Rewrite uses in a debug stmt.  */
 
 static void
-rewrite_debug_stmt_uses (gimple stmt)
+rewrite_debug_stmt_uses (gimple *stmt)
 {
   use_operand_p use_p;
   ssa_op_iter iter;
@@ -1217,7 +1253,7 @@ rewrite_debug_stmt_uses (gimple stmt)
   FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
     {
       tree var = USE_FROM_PTR (use_p), def;
-      common_info_p info = get_common_info (var);
+      common_info *info = get_common_info (var);
       gcc_checking_assert (DECL_P (var));
       def = info->current_def;
       if (!def)
@@ -1235,7 +1271,7 @@ rewrite_debug_stmt_uses (gimple stmt)
                   !gsi_end_p (gsi) && lim > 0;
                   gsi_next (&gsi), lim--)
                {
-                 gimple gstmt = gsi_stmt (gsi);
+                 gimple *gstmt = gsi_stmt (gsi);
                  if (!gimple_debug_source_bind_p (gstmt))
                    break;
                  if (gimple_debug_source_bind_get_value (gstmt) == var)
@@ -1250,12 +1286,12 @@ rewrite_debug_stmt_uses (gimple stmt)
              /* If not, add a new source bind stmt.  */
              if (def == NULL_TREE)
                {
-                 gimple def_temp;
+                 gimple *def_temp;
                  def = make_node (DEBUG_EXPR_DECL);
                  def_temp = gimple_build_debug_source_bind (def, var, NULL);
                  DECL_ARTIFICIAL (def) = 1;
                  TREE_TYPE (def) = TREE_TYPE (var);
-                 DECL_MODE (def) = DECL_MODE (var);
+                 SET_DECL_MODE (def, DECL_MODE (var));
                  gsi =
                 gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
                  gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
@@ -1284,7 +1320,7 @@ rewrite_debug_stmt_uses (gimple stmt)
            ;
          else
            {
-             struct def_blocks_d *db_p = get_def_blocks_for (info);
+             def_blocks *db_p = get_def_blocks_for (info);
 
              /* If there are some non-debug uses in the current bb,
                 it is fine.  */
@@ -1317,7 +1353,7 @@ rewrite_stmt (gimple_stmt_iterator *si)
   use_operand_p use_p;
   def_operand_p def_p;
   ssa_op_iter iter;
-  gimple stmt = gsi_stmt (*si);
+  gimple *stmt = gsi_stmt (*si);
 
   /* If mark_def_sites decided that we don't need to rewrite this
      statement, ignore it.  */
@@ -1341,6 +1377,8 @@ rewrite_stmt (gimple_stmt_iterator *si)
        FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
          {
            tree var = USE_FROM_PTR (use_p);
+           if (TREE_CODE (var) == SSA_NAME)
+             continue;
            gcc_checking_assert (DECL_P (var));
            SET_USE (use_p, get_reaching_def (var));
          }
@@ -1354,6 +1392,8 @@ rewrite_stmt (gimple_stmt_iterator *si)
        tree name;
        tree tracked_var;
 
+       if (TREE_CODE (var) == SSA_NAME)
+         continue;
        gcc_checking_assert (DECL_P (var));
 
        if (gimple_clobber_p (stmt)
@@ -1361,8 +1401,7 @@ rewrite_stmt (gimple_stmt_iterator *si)
          {
            /* If we rewrite a DECL into SSA form then drop its
               clobber stmts and replace uses with a new default def.  */
-           gcc_checking_assert (TREE_CODE (var) == VAR_DECL
-                                && !gimple_vdef (stmt));
+           gcc_checking_assert (VAR_P (var) && !gimple_vdef (stmt));
            gsi_replace (si, gimple_build_nop (), true);
            register_new_def (get_or_create_ssa_default_def (cfun, var), var);
            break;
@@ -1375,7 +1414,7 @@ rewrite_stmt (gimple_stmt_iterator *si)
        tracked_var = target_for_debug_bind (var);
        if (tracked_var)
          {
-           gimple note = gimple_build_debug_bind (tracked_var, name, stmt);
+           gimple *note = gimple_build_debug_bind (tracked_var, name, stmt);
            gsi_insert_after (si, note, GSI_SAME_STMT);
          }
       }
@@ -1395,8 +1434,8 @@ rewrite_add_phi_arguments (basic_block bb)
 
   FOR_EACH_EDGE (e, ei, bb->succs)
     {
-      gimple phi;
-      gimple_stmt_iterator gsi;
+      gphi *phi;
+      gphi_iterator gsi;
 
       for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi);
           gsi_next (&gsi))
@@ -1404,7 +1443,7 @@ rewrite_add_phi_arguments (basic_block bb)
          tree currdef, res;
          location_t loc;
 
-         phi = gsi_stmt (gsi);
+         phi = gsi.phi ();
          res = gimple_phi_result (phi);
          currdef = get_reaching_def (SSA_NAME_VAR (res));
          /* Virtual operand PHI args do not need a location.  */
@@ -1420,9 +1459,10 @@ rewrite_add_phi_arguments (basic_block bb)
 class rewrite_dom_walker : public dom_walker
 {
 public:
-  rewrite_dom_walker (cdi_direction direction) : dom_walker (direction) {}
+  rewrite_dom_walker (cdi_direction direction)
+    : dom_walker (direction, ALL_BLOCKS, NULL) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 };
 
@@ -1431,11 +1471,9 @@ public:
    (BLOCK_DEFS).  Register new definitions for every PHI node in the
    block.  */
 
-void
+edge
 rewrite_dom_walker::before_dom_children (basic_block bb)
 {
-  gimple_stmt_iterator gsi;
-
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "\n\nRenaming block #%d\n\n", bb->index);
 
@@ -1445,7 +1483,8 @@ rewrite_dom_walker::before_dom_children (basic_block bb)
   /* Step 1.  Register new definitions for every PHI node in the block.
      Conceptually, all the PHI nodes are executed in parallel and each PHI
      node introduces a new version for the associated variable.  */
-  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+  for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+       gsi_next (&gsi))
     {
       tree result = gimple_phi_result (gsi_stmt (gsi));
       register_new_def (result, SSA_NAME_VAR (result));
@@ -1455,7 +1494,8 @@ rewrite_dom_walker::before_dom_children (basic_block bb)
      with its immediate reaching definitions.  Update the current definition
      of a variable when a new real or virtual definition is found.  */
   if (bitmap_bit_p (interesting_blocks, bb->index))
-    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+        gsi_next (&gsi))
       rewrite_stmt (&gsi);
 
   /* Step 3.  Visit all the successor blocks of BB looking for PHI nodes.
@@ -1463,6 +1503,8 @@ rewrite_dom_walker::before_dom_children (basic_block bb)
      reaching definition for the variable and the edge through which that
      definition is reaching the PHI node.  */
   rewrite_add_phi_arguments (bb);
+
+  return NULL;
 }
 
 
@@ -1567,10 +1609,10 @@ dump_defs_stack (FILE *file, int n)
        }
 
       fprintf (file, "    Previous CURRDEF (");
-      print_generic_expr (file, var, 0);
+      print_generic_expr (file, var);
       fprintf (file, ") = ");
       if (name)
-       print_generic_expr (file, name, 0);
+       print_generic_expr (file, name);
       else
        fprintf (file, "<NIL>");
       fprintf (file, "\n");
@@ -1604,12 +1646,12 @@ dump_currdefs (FILE *file)
   fprintf (file, "\n\nCurrent reaching definitions\n\n");
   FOR_EACH_VEC_ELT (symbols_to_rename, i, var)
     {
-      common_info_p info = get_common_info (var);
+      common_info *info = get_common_info (var);
       fprintf (file, "CURRDEF (");
-      print_generic_expr (file, var, 0);
+      print_generic_expr (file, var);
       fprintf (file, ") = ");
       if (info->current_def)
-       print_generic_expr (file, info->current_def, 0);
+       print_generic_expr (file, info->current_def);
       else
        fprintf (file, "<NIL>");
       fprintf (file, "\n");
@@ -1691,9 +1733,9 @@ debug_tree_ssa_stats (void)
 /* Callback for htab_traverse to dump the VAR_INFOS hash table.  */
 
 int
-debug_var_infos_r (var_info_d **slot, FILE *file)
+debug_var_infos_r (var_info **slot, FILE *file)
 {
-  struct var_info_d *info = *slot;
+  var_info *info = *slot;
 
   fprintf (file, "VAR: ");
   print_generic_expr (file, info->var, dump_flags);
@@ -1733,7 +1775,7 @@ debug_var_infos (void)
 static inline void
 register_new_update_single (tree new_name, tree old_name)
 {
-  common_info_p info = get_common_info (old_name);
+  common_info *info = get_common_info (old_name);
   tree currdef = info->current_def;
 
   /* Push the current reaching definition into BLOCK_DEFS_STACK.
@@ -1820,17 +1862,38 @@ maybe_replace_use_in_debug_stmt (use_operand_p use_p)
 }
 
 
+/* If DEF has x_5 = ASAN_POISON () as its current def, add
+   ASAN_POISON_USE (x_5) stmt before GSI to denote the stmt writes into
+   a poisoned (out of scope) variable.  */
+
+static void
+maybe_add_asan_poison_write (tree def, gimple_stmt_iterator *gsi)
+{
+  tree cdef = get_current_def (def);
+  if (cdef != NULL
+      && TREE_CODE (cdef) == SSA_NAME
+      && gimple_call_internal_p (SSA_NAME_DEF_STMT (cdef), IFN_ASAN_POISON))
+    {
+      gcall *call
+       = gimple_build_call_internal (IFN_ASAN_POISON_USE, 1, cdef);
+      gimple_set_location (call, gimple_location (gsi_stmt (*gsi)));
+      gsi_insert_before (gsi, call, GSI_SAME_STMT);
+    }
+}
+
+
 /* If the operand pointed to by DEF_P is an SSA name in NEW_SSA_NAMES
    or OLD_SSA_NAMES, or if it is a symbol marked for renaming,
    register it as the current definition for the names replaced by
-   DEF_P.  */
+   DEF_P.  Returns whether the statement should be removed.  */
 
-static inline void
-maybe_register_def (def_operand_p def_p, gimple stmt,
+static inline bool
+maybe_register_def (def_operand_p def_p, gimple *stmt,
                    gimple_stmt_iterator gsi)
 {
   tree def = DEF_FROM_PTR (def_p);
   tree sym = DECL_P (def) ? def : SSA_NAME_VAR (def);
+  bool to_delete = false;
 
   /* If DEF is a naked symbol that needs renaming, create a new
      name for it.  */
@@ -1838,15 +1901,28 @@ maybe_register_def (def_operand_p def_p, gimple stmt,
     {
       if (DECL_P (def))
        {
-         tree tracked_var;
-
-         def = make_ssa_name (def, stmt);
+         if (gimple_clobber_p (stmt) && is_gimple_reg (sym))
+           {
+             gcc_checking_assert (VAR_P (sym));
+             /* Replace clobber stmts with a default def. This new use of a
+                default definition may make it look like SSA_NAMEs have
+                conflicting lifetimes, so we need special code to let them
+                coalesce properly.  */
+             to_delete = true;
+             def = get_or_create_ssa_default_def (cfun, sym);
+           }
+         else
+           {
+             if (asan_sanitize_use_after_scope ())
+               maybe_add_asan_poison_write (def, &gsi);
+             def = make_ssa_name (def, stmt);
+           }
          SET_DEF (def_p, def);
 
-         tracked_var = target_for_debug_bind (sym);
+         tree tracked_var = target_for_debug_bind (sym);
          if (tracked_var)
            {
-             gimple note = gimple_build_debug_bind (tracked_var, def, stmt);
+             gimple *note = gimple_build_debug_bind (tracked_var, def, stmt);
              /* If stmt ends the bb, insert the debug stmt on the single
                 non-EH edge from the stmt.  */
              if (gsi_one_before_end_p (gsi) && stmt_ends_bb_p (stmt))
@@ -1901,6 +1977,8 @@ maybe_register_def (def_operand_p def_p, gimple stmt,
       if (is_old_name (def))
        register_new_update_single (def, def);
     }
+
+  return to_delete;
 }
 
 
@@ -1909,10 +1987,10 @@ maybe_register_def (def_operand_p def_p, gimple stmt,
    OLD_SSA_NAMES used by SI will be updated to their current reaching
    definition.  Names in OLD_SSA_NAMES or NEW_SSA_NAMES defined by SI
    will be registered as a new definition for their corresponding name
-   in OLD_SSA_NAMES.  */
+   in OLD_SSA_NAMES.  Returns whether STMT should be removed.  */
 
-static void
-rewrite_update_stmt (gimple stmt, gimple_stmt_iterator gsi)
+static bool
+rewrite_update_stmt (gimple *stmt, gimple_stmt_iterator gsi)
 {
   use_operand_p use_p;
   def_operand_p def_p;
@@ -1920,7 +1998,7 @@ rewrite_update_stmt (gimple stmt, gimple_stmt_iterator gsi)
 
   /* Only update marked statements.  */
   if (!rewrite_uses_p (stmt) && !register_defs_p (stmt))
-    return;
+    return false;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -1971,9 +2049,12 @@ rewrite_update_stmt (gimple stmt, gimple_stmt_iterator gsi)
   /* Register definitions of names in NEW_SSA_NAMES and OLD_SSA_NAMES.
      Also register definitions for names whose underlying symbol is
      marked for renaming.  */
+  bool to_delete = false;
   if (register_defs_p (stmt))
     FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_ALL_DEFS)
-      maybe_register_def (def_p, stmt, gsi);
+      to_delete |= maybe_register_def (def_p, stmt, gsi);
+
+  return to_delete;
 }
 
 
@@ -1991,8 +2072,8 @@ rewrite_update_phi_arguments (basic_block bb)
 
   FOR_EACH_EDGE (e, ei, bb->succs)
     {
-      gimple phi;
-      gimple_vec phis;
+      gphi *phi;
+      vec<gphi *> phis;
 
       if (!bitmap_bit_p (blocks_with_phis_to_rewrite, e->dest->index))
        continue;
@@ -2034,7 +2115,7 @@ rewrite_update_phi_arguments (basic_block bb)
           /* Update the argument if there is a reaching def.  */
          if (reaching_def)
            {
-             source_location locus;
+             location_t locus;
              int arg_i = PHI_ARG_INDEX_FROM_USE (arg_p);
 
              SET_USE (arg_p, reaching_def);
@@ -2044,13 +2125,14 @@ rewrite_update_phi_arguments (basic_block bb)
                locus = UNKNOWN_LOCATION;
              else
                {
-                 gimple stmt = SSA_NAME_DEF_STMT (reaching_def);
+                 gimple *stmt = SSA_NAME_DEF_STMT (reaching_def);
+                 gphi *other_phi = dyn_cast <gphi *> (stmt);
 
                  /* Single element PHI nodes  behave like copies, so get the
                     location from the phi argument.  */
-                 if (gimple_code (stmt) == GIMPLE_PHI
-                     && gimple_phi_num_args (stmt) == 1)
-                   locus = gimple_phi_arg_location (stmt, 0);
+                 if (other_phi
+                     && gimple_phi_num_args (other_phi) == 1)
+                   locus = gimple_phi_arg_location (other_phi, 0);
                  else
                    locus = gimple_location (stmt);
                }
@@ -2068,9 +2150,10 @@ rewrite_update_phi_arguments (basic_block bb)
 class rewrite_update_dom_walker : public dom_walker
 {
 public:
-  rewrite_update_dom_walker (cdi_direction direction) : dom_walker (direction) {}
+  rewrite_update_dom_walker (cdi_direction direction)
+    : dom_walker (direction, ALL_BLOCKS, NULL) {}
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 };
 
@@ -2079,11 +2162,10 @@ public:
    for new SSA names produced in this block (BLOCK_DEFS).  Register
    new definitions for every PHI node in the block.  */
 
-void
+edge
 rewrite_update_dom_walker::before_dom_children (basic_block bb)
 {
   bool is_abnormal_phi;
-  gimple_stmt_iterator gsi;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "Registering new PHI nodes in block #%d\n",
@@ -2093,7 +2175,7 @@ rewrite_update_dom_walker::before_dom_children (basic_block bb)
   block_defs_stack.safe_push (NULL_TREE);
 
   if (!bitmap_bit_p (blocks_to_update, bb->index))
-    return;
+    return NULL;
 
   /* Mark the LHS if any of the arguments flows through an abnormal
      edge.  */
@@ -2104,10 +2186,11 @@ rewrite_update_dom_walker::before_dom_children (basic_block bb)
      register it as a new definition for its corresponding name.  Also
      register definitions for names whose underlying symbols are
      marked for renaming.  */
-  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+  for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+       gsi_next (&gsi))
     {
       tree lhs, lhs_sym;
-      gimple phi = gsi_stmt (gsi);
+      gphi *phi = gsi.phi ();
 
       if (!register_defs_p (phi))
        continue;
@@ -2139,12 +2222,17 @@ rewrite_update_dom_walker::before_dom_children (basic_block bb)
   if (bitmap_bit_p (interesting_blocks, bb->index))
     {
       gcc_checking_assert (bitmap_bit_p (blocks_to_update, bb->index));
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-        rewrite_update_stmt (gsi_stmt (gsi), gsi);
+      for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
+       if (rewrite_update_stmt (gsi_stmt (gsi), gsi))
+         gsi_remove (&gsi, true);
+       else
+         gsi_next (&gsi);
     }
 
   /* Step 3.  Update PHI nodes.  */
   rewrite_update_phi_arguments (bb);
+
+  return NULL;
 }
 
 /* Called after visiting block BB.  Unwind BLOCK_DEFS_STACK to restore
@@ -2222,7 +2310,7 @@ public:
   mark_def_dom_walker (cdi_direction direction);
   ~mark_def_dom_walker ();
 
-  virtual void before_dom_children (basic_block);
+  virtual edge before_dom_children (basic_block);
 
 private:
   /* Notice that this bitmap is indexed using variable UIDs, so it must be
@@ -2232,7 +2320,7 @@ private:
 };
 
 mark_def_dom_walker::mark_def_dom_walker (cdi_direction direction)
-  : dom_walker (direction), m_kills (BITMAP_ALLOC (NULL))
+  : dom_walker (direction, ALL_BLOCKS, NULL), m_kills (BITMAP_ALLOC (NULL))
 {
 }
 
@@ -2244,7 +2332,7 @@ mark_def_dom_walker::~mark_def_dom_walker ()
 /* Block processing routine for mark_def_sites.  Clear the KILLS bitmap
    at the start of each block, and call mark_def_sites for each statement.  */
 
-void
+edge
 mark_def_dom_walker::before_dom_children (basic_block bb)
 {
   gimple_stmt_iterator gsi;
@@ -2252,6 +2340,7 @@ mark_def_dom_walker::before_dom_children (basic_block bb)
   bitmap_clear (m_kills);
   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     mark_def_sites (bb, gsi_stmt (gsi), m_kills);
+  return NULL;
 }
 
 /* Initialize internal data needed during renaming.  */
@@ -2339,7 +2428,11 @@ pass_build_ssa::execute (function *fun)
 {
   bitmap_head *dfs;
   basic_block bb;
-  unsigned i;
+
+  /* Increase the set of variables we can rewrite into SSA form
+     by clearing TREE_ADDRESSABLE and transform the IL to support this.  */
+  if (optimize)
+    execute_update_addresses_taken ();
 
   /* Initialize operand data structures.  */
   init_ssa_operands (fun);
@@ -2383,20 +2476,43 @@ pass_build_ssa::execute (function *fun)
   /* Try to get rid of all gimplifier generated temporaries by making
      its SSA names anonymous.  This way we can garbage collect them
      all after removing unused locals which we do in our TODO.  */
-  for (i = 1; i < num_ssa_names; ++i)
+  unsigned i;
+  tree name;
+
+  FOR_EACH_SSA_NAME (i, name, cfun)
     {
-      tree decl, name = ssa_name (i);
-      if (!name
-         || SSA_NAME_IS_DEFAULT_DEF (name))
+      if (SSA_NAME_IS_DEFAULT_DEF (name))
        continue;
-      decl = SSA_NAME_VAR (name);
+      tree decl = SSA_NAME_VAR (name);
       if (decl
-         && TREE_CODE (decl) == VAR_DECL
+         && VAR_P (decl)
          && !VAR_DECL_IS_VIRTUAL_OPERAND (decl)
          && DECL_IGNORED_P (decl))
        SET_SSA_NAME_VAR_OR_IDENTIFIER (name, DECL_NAME (decl));
     }
 
+  /* Initialize SSA_NAME_POINTS_TO_READONLY_MEMORY.  */
+  tree fnspec = lookup_attribute ("fn spec",
+                                 TYPE_ATTRIBUTES (TREE_TYPE (fun->decl)));
+  if (fnspec)
+    {
+      fnspec = TREE_VALUE (TREE_VALUE (fnspec));
+      unsigned i = 1;
+      for (tree arg = DECL_ARGUMENTS (cfun->decl);
+          arg; arg = DECL_CHAIN (arg), ++i)
+       {
+         if (i >= (unsigned) TREE_STRING_LENGTH (fnspec))
+           break;
+         if (TREE_STRING_POINTER (fnspec)[i]  == 'R'
+             || TREE_STRING_POINTER (fnspec)[i] == 'r')
+           {
+             tree name = ssa_default_def (fun, arg);
+             if (name)
+               SSA_NAME_POINTS_TO_READONLY_MEMORY (name) = 1;
+           }
+       }
+    }
+
   return 0;
 }
 
@@ -2413,7 +2529,8 @@ make_pass_build_ssa (gcc::context *ctxt)
    renamer.  BLOCKS is the set of blocks that need updating.  */
 
 static void
-mark_def_interesting (tree var, gimple stmt, basic_block bb, bool insert_phi_p)
+mark_def_interesting (tree var, gimple *stmt, basic_block bb,
+                     bool insert_phi_p)
 {
   gcc_checking_assert (bitmap_bit_p (blocks_to_update, bb->index));
   set_register_defs (stmt, true);
@@ -2444,7 +2561,8 @@ mark_def_interesting (tree var, gimple stmt, basic_block bb, bool insert_phi_p)
    nodes.  */
 
 static inline void
-mark_use_interesting (tree var, gimple stmt, basic_block bb, bool insert_phi_p)
+mark_use_interesting (tree var, gimple *stmt, basic_block bb,
+                     bool insert_phi_p)
 {
   basic_block def_bb = gimple_bb (stmt);
 
@@ -2452,7 +2570,7 @@ mark_use_interesting (tree var, gimple stmt, basic_block bb, bool insert_phi_p)
   mark_block_for_update (bb);
 
   if (gimple_code (stmt) == GIMPLE_PHI)
-    mark_phi_for_rewrite (def_bb, stmt);
+    mark_phi_for_rewrite (def_bb, as_a <gphi *> (stmt));
   else
     {
       set_rewrite_uses (stmt, true);
@@ -2468,17 +2586,15 @@ mark_use_interesting (tree var, gimple stmt, basic_block bb, bool insert_phi_p)
      replace it).  */
   if (insert_phi_p)
     {
-      struct def_blocks_d *db_p = get_def_blocks_for (get_common_info (var));
+      def_blocks *db_p = get_def_blocks_for (get_common_info (var));
       if (!bitmap_bit_p (db_p->def_blocks, bb->index))
        set_livein_block (var, bb);
     }
 }
 
-
-/* Do a dominator walk starting at BB processing statements that
-   reference symbols in SSA operands.  This is very similar to
-   mark_def_sites, but the scan handles statements whose operands may
-   already be SSA names.
+/* Processing statements in BB that reference symbols in SSA operands.
+   This is very similar to mark_def_sites, but the scan handles
+   statements whose operands may already be SSA names.
 
    If INSERT_PHI_P is true, mark those uses as live in the
    corresponding block.  This is later used by the PHI placement
@@ -2491,10 +2607,8 @@ mark_use_interesting (tree var, gimple stmt, basic_block bb, bool insert_phi_p)
           that.  */
 
 static void
-prepare_block_for_update (basic_block bb, bool insert_phi_p)
+prepare_block_for_update_1 (basic_block bb, bool insert_phi_p)
 {
-  basic_block son;
-  gimple_stmt_iterator si;
   edge e;
   edge_iterator ei;
 
@@ -2502,9 +2616,10 @@ prepare_block_for_update (basic_block bb, bool insert_phi_p)
 
   /* Process PHI nodes marking interesting those that define or use
      the symbols that we are interested in.  */
-  for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+  for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
+       gsi_next (&si))
     {
-      gimple phi = gsi_stmt (si);
+      gphi *phi = si.phi ();
       tree lhs_sym, lhs = gimple_phi_result (phi);
 
       if (TREE_CODE (lhs) == SSA_NAME
@@ -2528,9 +2643,10 @@ prepare_block_for_update (basic_block bb, bool insert_phi_p)
     }
 
   /* Process the statements.  */
-  for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+  for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
+       gsi_next (&si))
     {
-      gimple stmt;
+      gimple *stmt;
       ssa_op_iter i;
       use_operand_p use_p;
       def_operand_p def_p;
@@ -2574,13 +2690,51 @@ prepare_block_for_update (basic_block bb, bool insert_phi_p)
        }
     }
 
-  /* Now visit all the blocks dominated by BB.  */
-  for (son = first_dom_son (CDI_DOMINATORS, bb);
-       son;
-       son = next_dom_son (CDI_DOMINATORS, son))
-    prepare_block_for_update (son, insert_phi_p);
 }
 
+/* Do a dominator walk starting at BB processing statements that
+   reference symbols in SSA operands.  This is very similar to
+   mark_def_sites, but the scan handles statements whose operands may
+   already be SSA names.
+
+   If INSERT_PHI_P is true, mark those uses as live in the
+   corresponding block.  This is later used by the PHI placement
+   algorithm to make PHI pruning decisions.
+
+   FIXME.  Most of this would be unnecessary if we could associate a
+          symbol to all the SSA names that reference it.  But that
+          sounds like it would be expensive to maintain.  Still, it
+          would be interesting to see if it makes better sense to do
+          that.  */
+static void
+prepare_block_for_update (basic_block bb, bool insert_phi_p)
+{
+  size_t sp = 0;
+  basic_block *worklist;
+
+  /* Allocate the worklist.  */
+  worklist = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
+  /* Add the BB to the worklist.  */
+  worklist[sp++] = bb;
+
+  while (sp)
+    {
+      basic_block bb;
+      basic_block son;
+
+      /* Pick a block from the worklist.  */
+      bb = worklist[--sp];
+
+      prepare_block_for_update_1 (bb, insert_phi_p);
+
+      /* Now add all the blocks dominated by BB to the worklist.  */
+      for (son = first_dom_son (CDI_DOMINATORS, bb);
+          son;
+          son = next_dom_son (CDI_DOMINATORS, son))
+       worklist[sp++] = son;
+    }
+  free (worklist);
+}
 
 /* Helper for prepare_names_to_update.  Mark all the use sites for
    NAME as interesting.  BLOCKS and INSERT_PHI_P are as in
@@ -2592,15 +2746,20 @@ prepare_use_sites_for (tree name, bool insert_phi_p)
   use_operand_p use_p;
   imm_use_iterator iter;
 
+  /* If we rename virtual operands do not update them.  */
+  if (virtual_operand_p (name)
+      && cfun->gimple_df->rename_vops)
+    return;
+
   FOR_EACH_IMM_USE_FAST (use_p, iter, name)
     {
-      gimple stmt = USE_STMT (use_p);
+      gimple *stmt = USE_STMT (use_p);
       basic_block bb = gimple_bb (stmt);
 
       if (gimple_code (stmt) == GIMPLE_PHI)
        {
          int ix = PHI_ARG_INDEX_FROM_USE (use_p);
-         edge e = gimple_phi_arg_edge (stmt, ix);
+         edge e = gimple_phi_arg_edge (as_a <gphi *> (stmt), ix);
          mark_use_interesting (name, stmt, e->src, insert_phi_p);
        }
       else
@@ -2620,13 +2779,18 @@ prepare_use_sites_for (tree name, bool insert_phi_p)
 static void
 prepare_def_site_for (tree name, bool insert_phi_p)
 {
-  gimple stmt;
+  gimple *stmt;
   basic_block bb;
 
   gcc_checking_assert (names_to_release == NULL
                       || !bitmap_bit_p (names_to_release,
                                         SSA_NAME_VERSION (name)));
 
+  /* If we rename virtual operands do not update them.  */
+  if (virtual_operand_p (name)
+      && cfun->gimple_df->rename_vops)
+    return;
+
   stmt = SSA_NAME_DEF_STMT (name);
   bb = gimple_bb (stmt);
   if (bb)
@@ -2684,13 +2848,13 @@ dump_names_replaced_by (FILE *file, tree name)
   bitmap old_set;
   bitmap_iterator bi;
 
-  print_generic_expr (file, name, 0);
+  print_generic_expr (file, name);
   fprintf (file, " -> { ");
 
   old_set = names_replaced_by (name);
   EXECUTE_IF_SET_IN_BITMAP (old_set, 0, i, bi)
     {
-      print_generic_expr (file, ssa_name (i), 0);
+      print_generic_expr (file, ssa_name (i));
       fprintf (file, " ");
     }
 
@@ -2742,7 +2906,7 @@ dump_update_ssa (FILE *file)
       fprintf (file, "\nSSA names to release after updating the SSA web\n\n");
       EXECUTE_IF_SET_IN_BITMAP (names_to_release, 0, i, bi)
        {
-         print_generic_expr (file, ssa_name (i), 0);
+         print_generic_expr (file, ssa_name (i));
          fprintf (file, " ");
        }
       fprintf (file, "\n");
@@ -2811,11 +2975,7 @@ delete_update_ssa (void)
 
   if (blocks_with_phis_to_rewrite)
     EXECUTE_IF_SET_IN_BITMAP (blocks_with_phis_to_rewrite, 0, i, bi)
-      {
-       gimple_vec phis = phis_to_rewrite[i];
-       phis.release ();
-       phis_to_rewrite[i].create (0);
-      }
+      phis_to_rewrite[i].release ();
 
   BITMAP_FREE (blocks_with_phis_to_rewrite);
   BITMAP_FREE (blocks_to_update);
@@ -2831,7 +2991,7 @@ delete_update_ssa (void)
    update_ssa's tables.  */
 
 tree
-create_new_def_for (tree old_name, gimple stmt, def_operand_p def)
+create_new_def_for (tree old_name, gimple *stmt, def_operand_p def)
 {
   tree new_name;
 
@@ -2889,7 +3049,7 @@ mark_virtual_operand_for_renaming (tree name)
   bool used = false;
   imm_use_iterator iter;
   use_operand_p use_p;
-  gimple stmt;
+  gimple *stmt;
 
   gcc_assert (VAR_DECL_IS_VIRTUAL_OPERAND (name_var));
   FOR_EACH_IMM_USE_STMT (stmt, iter, name)
@@ -2907,7 +3067,7 @@ mark_virtual_operand_for_renaming (tree name)
    removed.  */
 
 void
-mark_virtual_phi_result_for_renaming (gimple phi)
+mark_virtual_phi_result_for_renaming (gphi *phi)
 {
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -2986,7 +3146,7 @@ insert_updated_phi_nodes_for (tree var, bitmap_head *dfs, bitmap blocks,
                               unsigned update_flags)
 {
   basic_block entry;
-  struct def_blocks_d *db;
+  def_blocks *db;
   bitmap idf, pruned_idf;
   bitmap_iterator bi;
   unsigned i;
@@ -3161,6 +3321,46 @@ update_ssa (unsigned update_flags)
   if (!need_ssa_update_p (cfun))
     return;
 
+  if (flag_checking)
+    {
+      timevar_push (TV_TREE_STMT_VERIFY);
+
+      bool err = false;
+
+      FOR_EACH_BB_FN (bb, cfun)
+       {
+         gimple_stmt_iterator gsi;
+         for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+           {
+             gimple *stmt = gsi_stmt (gsi);
+
+             ssa_op_iter i;
+             use_operand_p use_p;
+             FOR_EACH_SSA_USE_OPERAND (use_p, stmt, i, SSA_OP_ALL_USES)
+               {
+                 tree use = USE_FROM_PTR (use_p);
+                 if (TREE_CODE (use) != SSA_NAME)
+                   continue;
+
+                 if (SSA_NAME_IN_FREE_LIST (use))
+                   {
+                     error ("statement uses released SSA name");
+                     debug_gimple_stmt (stmt);
+                     fprintf (stderr, "The use of ");
+                     print_generic_expr (stderr, use);
+                     fprintf (stderr," should have been replaced\n");
+                     err = true;
+                   }
+               }
+           }
+       }
+
+      if (err)
+       internal_error ("cannot update SSA form");
+
+      timevar_pop (TV_TREE_STMT_VERIFY);
+    }
+
   timevar_push (TV_TREE_SSA_INCREMENTAL);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3194,6 +3394,8 @@ update_ssa (unsigned update_flags)
      OLD_SSA_NAMES.  */
   if (bitmap_first_set_bit (new_ssa_names) >= 0)
     {
+      statistics_counter_event (cfun, "Incremental SSA update", 1);
+
       prepare_names_to_update (insert_phi_p);
 
       /* If all the names in NEW_SSA_NAMES had been marked for
@@ -3207,6 +3409,8 @@ update_ssa (unsigned update_flags)
   /* Next, determine the block at which to start the renaming process.  */
   if (cfun->gimple_df->ssa_renaming_needed)
     {
+      statistics_counter_event (cfun, "Symbol to SSA rewrite", 1);
+
       /* If we rename bare symbols initialize the mapping to
          auxiliar info we need to keep track of.  */
       var_infos = new hash_table<var_info_hasher> (47);
@@ -3224,29 +3428,28 @@ update_ssa (unsigned update_flags)
         placement heuristics.  */
       prepare_block_for_update (start_bb, insert_phi_p);
 
-#ifdef ENABLE_CHECKING
-      for (i = 1; i < num_ssa_names; ++i)
-       {
-         tree name = ssa_name (i);
-         if (!name
-             || virtual_operand_p (name))
-           continue;
+      tree name;
 
-         /* For all but virtual operands, which do not have SSA names
-            with overlapping life ranges, ensure that symbols marked
-            for renaming do not have existing SSA names associated with
-            them as we do not re-write them out-of-SSA before going
-            into SSA for the remaining symbol uses.  */
-         if (marked_for_renaming (SSA_NAME_VAR (name)))
-           {
-             fprintf (stderr, "Existing SSA name for symbol marked for "
-                      "renaming: ");
-             print_generic_expr (stderr, name, TDF_SLIM);
-             fprintf (stderr, "\n");
-             internal_error ("SSA corruption");
-           }
-       }
-#endif
+      if (flag_checking)
+       FOR_EACH_SSA_NAME (i, name, cfun)
+         {
+           if (virtual_operand_p (name))
+             continue;
+
+           /* For all but virtual operands, which do not have SSA names
+              with overlapping life ranges, ensure that symbols marked
+              for renaming do not have existing SSA names associated with
+              them as we do not re-write them out-of-SSA before going
+              into SSA for the remaining symbol uses.  */
+           if (marked_for_renaming (SSA_NAME_VAR (name)))
+             {
+               fprintf (stderr, "Existing SSA name for symbol marked for "
+                        "renaming: ");
+               print_generic_expr (stderr, name, TDF_SLIM);
+               fprintf (stderr, "\n");
+               internal_error ("SSA corruption");
+             }
+         }
     }
   else
     {
@@ -3279,12 +3482,11 @@ update_ssa (unsigned update_flags)
             will grow while we are traversing it (but it will not
             gain any new members).  Copy OLD_SSA_NAMES to a temporary
             for traversal.  */
-         sbitmap tmp = sbitmap_alloc (SBITMAP_SIZE (old_ssa_names));
+         auto_sbitmap tmp (SBITMAP_SIZE (old_ssa_names));
          bitmap_copy (tmp, old_ssa_names);
          EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, sbi)
            insert_updated_phi_nodes_for (ssa_name (i), dfs, blocks_to_update,
                                          update_flags);
-         sbitmap_free (tmp);
        }
 
       symbols_to_rename.qsort (insert_updated_phi_nodes_compare_uids);