re PR target/60693 (ICE on funny memcpy)
[gcc.git] / gcc / dse.c
index 6bc48c8efe1bcff92b371e533b8b05f54739d084..09dc5df6e93e2eea0c5a9b4f285e23513baccbd0 100644 (file)
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -1,6 +1,5 @@
 /* RTL dead store elimination.
-   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-   Free Software Foundation, Inc.
+   Copyright (C) 2005-2014 Free Software Foundation, Inc.
 
    Contributed by Richard Sandiford <rsandifor@codesourcery.com>
    and Kenneth Zadeck <zadeck@naturalbridge.com>
@@ -26,10 +25,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "tm.h"
 #include "rtl.h"
 #include "tree.h"
+#include "stor-layout.h"
 #include "tm_p.h"
 #include "regs.h"
 #include "hard-reg-set.h"
@@ -37,7 +37,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "df.h"
 #include "cselib.h"
-#include "timevar.h"
 #include "tree-pass.h"
 #include "alloc-pool.h"
 #include "alias.h"
@@ -48,7 +47,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "dbgcnt.h"
 #include "target.h"
 #include "params.h"
-#include "tree-flow.h"
+#include "pointer-set.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
 
 /* This file contains three techniques for performing Dead Store
    Elimination (dse).
@@ -95,7 +100,7 @@ along with GCC; see the file COPYING3.  If not see
    5) Delete the insns that the global analysis has indicated are
    unnecessary.
 
-   6) Delete insns that store the same value as preceeding store
+   6) Delete insns that store the same value as preceding store
    where the earlier store couldn't be eliminated.
 
    7) Cleanup.
@@ -106,7 +111,7 @@ along with GCC; see the file COPYING3.  If not see
    the first pass could examine a block in either direction.  The
    forwards ordering is to accommodate cselib.
 
-   We a simplifying assumption: addresses fall into four broad
+   We make a simplifying assumption: addresses fall into four broad
    categories:
 
    1) base has rtx_varies_p == false, offset is constant.
@@ -115,18 +120,18 @@ along with GCC; see the file COPYING3.  If not see
    4) base has rtx_varies_p == true, offset variable.
 
    The local passes are able to process all 4 kinds of addresses.  The
-   global pass only handles (1).
+   global pass only handles 1).
 
    The global problem is formulated as follows:
 
      A store, S1, to address A, where A is not relative to the stack
      frame, can be eliminated if all paths from S1 to the end of the
-     of the function contain another store to A before a read to A.
+     function contain another store to A before a read to A.
 
      If the address A is relative to the stack frame, a store S2 to A
-     can be eliminated if there are no paths from S1 that reach the
+     can be eliminated if there are no paths from S2 that reach the
      end of the function that read A before another store to A.  In
-     this case S2 can be deleted if there are paths to from S2 to the
+     this case S2 can be deleted if there are paths from S2 to the
      end of the function that have no reads or writes to A.  This
      second case allows stores to the stack frame to be deleted that
      would otherwise die when the function returns.  This cannot be
@@ -137,7 +142,7 @@ along with GCC; see the file COPYING3.  If not see
      dataflow problem where the stores are the gens and reads are the
      kills.  Set union problems are rare and require some special
      handling given our representation of bitmaps.  A straightforward
-     implementation of requires a lot of bitmaps filled with 1s.
+     implementation requires a lot of bitmaps filled with 1s.
      These are expensive and cumbersome in our bitmap formulation so
      care has been taken to avoid large vectors filled with 1s.  See
      the comments in bb_info and in the dataflow confluence functions
@@ -201,8 +206,21 @@ along with GCC; see the file COPYING3.  If not see
    that really have constant offsets this size.  */
 #define MAX_OFFSET (64 * 1024)
 
+/* Obstack for the DSE dataflow bitmaps.  We don't want to put these
+   on the default obstack because these bitmaps can grow quite large
+   (~2GB for the small (!) test case of PR54146) and we'll hold on to
+   all that memory until the end of the compiler run.
+   As a bonus, delete_tree_live_info can destroy all the bitmaps by just
+   releasing the whole obstack.  */
+static bitmap_obstack dse_bitmap_obstack;
 
+/* Obstack for other data.  As for above: Kinda nice to be able to
+   throw it all away at the end in one big sweep.  */
+static struct obstack dse_obstack;
+
+/* Scratch bitmap for cselib's cselib_expand_value_rtx.  */
 static bitmap scratch = NULL;
+
 struct insn_info;
 
 /* This structure holds information about a candidate store.  */
@@ -388,7 +406,7 @@ struct insn_info
   struct insn_info * prev_insn;
 
   /* The linked list of insns that are in consideration for removal in
-     the forwards pass thru the basic block.  This pointer may be
+     the forwards pass through the basic block.  This pointer may be
      trash as it is not cleared when a wild read occurs.  The only
      time it is guaranteed to be correct is when the traversal starts
      at active_local_stores.  */
@@ -457,7 +475,7 @@ struct bb_info
      being processed.  While it contains info for all of the
      registers, only the hard registers are actually examined.  It is used
      to assure that shift and/or add sequences that are inserted do not
-     accidently clobber live hard regs.  */
+     accidentally clobber live hard regs.  */
   bitmap regs_live;
 };
 
@@ -535,16 +553,11 @@ typedef struct group_info *group_info_t;
 typedef const struct group_info *const_group_info_t;
 static alloc_pool rtx_group_info_pool;
 
-/* Tables of group_info structures, hashed by base value.  */
-static htab_t rtx_group_table;
-
 /* Index into the rtx_group_vec.  */
 static int rtx_group_next_id;
 
-DEF_VEC_P(group_info_t);
-DEF_VEC_ALLOC_P(group_info_t,heap);
 
-static VEC(group_info_t,heap) *rtx_group_vec;
+static vec<group_info_t> rtx_group_vec;
 
 
 /* This structure holds the set of changes that are being deferred
@@ -566,20 +579,6 @@ static alloc_pool deferred_change_pool;
 
 static deferred_change_t deferred_change_list = NULL;
 
-/* This are used to hold the alias sets of spill variables.  Since
-   these are never aliased and there may be a lot of them, it makes
-   sense to treat them specially.  This bitvector is only allocated in
-   calls from dse_record_singleton_alias_set which currently is only
-   made during reload1.  So when dse is called before reload this
-   mechanism does nothing.  */
-
-static bitmap clear_alias_sets = NULL;
-
-/* The set of clear_alias_sets that have been disqualified because
-   there are loads or stores using a different mode than the alias set
-   was registered with.  */
-static bitmap disqualified_clear_alias_sets = NULL;
-
 /* The group that holds all of the clear_alias_sets.  */
 static group_info_t clear_alias_group;
 
@@ -593,8 +592,6 @@ struct clear_alias_mode_holder
   enum machine_mode mode;
 };
 
-static alloc_pool clear_alias_mode_pool;
-
 /* This is true except if cfun->stdarg -- i.e. we cannot do
    this for vararg functions because they play games with the frame.  */
 static bool stores_off_frame_dead_at_return;
@@ -643,23 +640,31 @@ clear_alias_set_lookup (alias_set_type alias_set)
 /* Hashtable callbacks for maintaining the "bases" field of
    store_group_info, given that the addresses are function invariants.  */
 
-static int
-invariant_group_base_eq (const void *p1, const void *p2)
+struct invariant_group_base_hasher : typed_noop_remove <group_info>
+{
+  typedef group_info value_type;
+  typedef group_info compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline bool
+invariant_group_base_hasher::equal (const value_type *gi1,
+                                   const compare_type *gi2)
 {
-  const_group_info_t gi1 = (const_group_info_t) p1;
-  const_group_info_t gi2 = (const_group_info_t) p2;
   return rtx_equal_p (gi1->rtx_base, gi2->rtx_base);
 }
 
-
-static hashval_t
-invariant_group_base_hash (const void *p)
+inline hashval_t
+invariant_group_base_hasher::hash (const value_type *gi)
 {
-  const_group_info_t gi = (const_group_info_t) p;
   int do_not_record;
   return hash_rtx (gi->rtx_base, Pmode, &do_not_record, NULL, false);
 }
 
+/* Tables of group_info structures, hashed by base value.  */
+static hash_table <invariant_group_base_hasher> rtx_group_table;
+
 
 /* Get the GROUP for BASE.  Add a new group if it is not there.  */
 
@@ -668,14 +673,14 @@ get_group_info (rtx base)
 {
   struct group_info tmp_gi;
   group_info_t gi;
-  void **slot;
+  group_info **slot;
 
   if (base)
     {
       /* Find the store_base_info structure for BASE, creating a new one
         if necessary.  */
       tmp_gi.rtx_base = base;
-      slot = htab_find_slot (rtx_group_table, &tmp_gi, INSERT);
+      slot = rtx_group_table.find_slot (&tmp_gi, INSERT);
       gi = (group_info_t) *slot;
     }
   else
@@ -686,19 +691,19 @@ get_group_info (rtx base)
            (group_info_t) pool_alloc (rtx_group_info_pool);
          memset (gi, 0, sizeof (struct group_info));
          gi->id = rtx_group_next_id++;
-         gi->store1_n = BITMAP_ALLOC (NULL);
-         gi->store1_p = BITMAP_ALLOC (NULL);
-         gi->store2_n = BITMAP_ALLOC (NULL);
-         gi->store2_p = BITMAP_ALLOC (NULL);
-         gi->escaped_p = BITMAP_ALLOC (NULL);
-         gi->escaped_n = BITMAP_ALLOC (NULL);
-         gi->group_kill = BITMAP_ALLOC (NULL);
+         gi->store1_n = BITMAP_ALLOC (&dse_bitmap_obstack);
+         gi->store1_p = BITMAP_ALLOC (&dse_bitmap_obstack);
+         gi->store2_n = BITMAP_ALLOC (&dse_bitmap_obstack);
+         gi->store2_p = BITMAP_ALLOC (&dse_bitmap_obstack);
+         gi->escaped_p = BITMAP_ALLOC (&dse_bitmap_obstack);
+         gi->escaped_n = BITMAP_ALLOC (&dse_bitmap_obstack);
+         gi->group_kill = BITMAP_ALLOC (&dse_bitmap_obstack);
          gi->process_globally = false;
          gi->offset_map_size_n = 0;
          gi->offset_map_size_p = 0;
          gi->offset_map_n = NULL;
          gi->offset_map_p = NULL;
-         VEC_safe_push (group_info_t, heap, rtx_group_vec, gi);
+         rtx_group_vec.safe_push (gi);
        }
       return clear_alias_group;
     }
@@ -710,13 +715,13 @@ get_group_info (rtx base)
       gi->id = rtx_group_next_id++;
       gi->base_mem = gen_rtx_MEM (BLKmode, base);
       gi->canon_base_addr = canon_rtx (base);
-      gi->store1_n = BITMAP_ALLOC (NULL);
-      gi->store1_p = BITMAP_ALLOC (NULL);
-      gi->store2_n = BITMAP_ALLOC (NULL);
-      gi->store2_p = BITMAP_ALLOC (NULL);
-      gi->escaped_p = BITMAP_ALLOC (NULL);
-      gi->escaped_n = BITMAP_ALLOC (NULL);
-      gi->group_kill = BITMAP_ALLOC (NULL);
+      gi->store1_n = BITMAP_ALLOC (&dse_bitmap_obstack);
+      gi->store1_p = BITMAP_ALLOC (&dse_bitmap_obstack);
+      gi->store2_n = BITMAP_ALLOC (&dse_bitmap_obstack);
+      gi->store2_p = BITMAP_ALLOC (&dse_bitmap_obstack);
+      gi->escaped_p = BITMAP_ALLOC (&dse_bitmap_obstack);
+      gi->escaped_n = BITMAP_ALLOC (&dse_bitmap_obstack);
+      gi->group_kill = BITMAP_ALLOC (&dse_bitmap_obstack);
       gi->process_globally = false;
       gi->frame_related =
        (base == frame_pointer_rtx) || (base == hard_frame_pointer_rtx);
@@ -724,7 +729,7 @@ get_group_info (rtx base)
       gi->offset_map_size_p = 0;
       gi->offset_map_n = NULL;
       gi->offset_map_p = NULL;
-      VEC_safe_push (group_info_t, heap, rtx_group_vec, gi);
+      rtx_group_vec.safe_push (gi);
     }
 
   return gi;
@@ -740,8 +745,11 @@ dse_step0 (void)
   globally_deleted = 0;
   spill_deleted = 0;
 
-  scratch = BITMAP_ALLOC (NULL);
-  kill_on_calls = BITMAP_ALLOC (NULL);
+  bitmap_obstack_initialize (&dse_bitmap_obstack);
+  gcc_obstack_init (&dse_obstack);
+
+  scratch = BITMAP_ALLOC (&reg_obstack);
+  kill_on_calls = BITMAP_ALLOC (&dse_bitmap_obstack);
 
   rtx_store_info_pool
     = create_alloc_pool ("rtx_store_info_pool",
@@ -762,20 +770,16 @@ dse_step0 (void)
     = create_alloc_pool ("deferred_change_pool",
                         sizeof (struct deferred_change), 10);
 
-  rtx_group_table = htab_create (11, invariant_group_base_hash,
-                                invariant_group_base_eq, NULL);
+  rtx_group_table.create (11);
 
-  bb_table = XCNEWVEC (bb_info_t, last_basic_block);
+  bb_table = XNEWVEC (bb_info_t, last_basic_block_for_fn (cfun));
   rtx_group_next_id = 0;
 
   stores_off_frame_dead_at_return = !cfun->stdarg;
 
   init_alias_analysis ();
 
-  if (clear_alias_sets)
-    clear_alias_group = get_group_info (NULL);
-  else
-    clear_alias_group = NULL;
+  clear_alias_group = NULL;
 }
 
 
@@ -943,7 +947,7 @@ delete_dead_store_insn (insn_info_t insn_info)
 
   if (!check_for_inc_dec_1 (insn_info))
     return;
-  if (dump_file)
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "Locally deleting insn %d ",
               INSN_UID (insn_info->insn));
@@ -972,7 +976,32 @@ delete_dead_store_insn (insn_info_t insn_info)
   insn_info->wild_read = false;
 }
 
-/* Check if EXPR can possibly escape the current function scope.  */
+/* Return whether DECL, a local variable, can possibly escape the current
+   function scope.  */
+
+static bool
+local_variable_can_escape (tree decl)
+{
+  if (TREE_ADDRESSABLE (decl))
+    return true;
+
+  /* If this is a partitioned variable, we need to consider all the variables
+     in the partition.  This is necessary because a store into one of them can
+     be replaced with a store into another and this may not change the outcome
+     of the escape analysis.  */
+  if (cfun->gimple_df->decls_to_pointers != NULL)
+    {
+      void *namep
+       = pointer_map_contains (cfun->gimple_df->decls_to_pointers, decl);
+      if (namep)
+       return TREE_ADDRESSABLE (*(tree *)namep);
+    }
+
+  return false;
+}
+
+/* Return whether EXPR can possibly escape the current function scope.  */
+
 static bool
 can_escape (tree expr)
 {
@@ -981,7 +1010,11 @@ can_escape (tree expr)
     return true;
   base = get_base_address (expr);
   if (DECL_P (base)
-      && !may_be_aliased (base))
+      && !may_be_aliased (base)
+      && !(TREE_CODE (base) == VAR_DECL
+          && !DECL_EXTERNAL (base)
+          && !TREE_STATIC (base)
+          && local_variable_can_escape (base)))
     return false;
   return true;
 }
@@ -1094,17 +1127,11 @@ add_non_frame_wild_read (bb_info_t bb_info)
 static bool
 const_or_frame_p (rtx x)
 {
-  switch (GET_CODE (x))
-    {
-    case CONST:
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST_VECTOR:
-    case SYMBOL_REF:
-    case LABEL_REF:
-      return true;
+  if (CONSTANT_P (x))
+    return true;
 
-    case REG:
+  if (GET_CODE (x) == REG)
+    {
       /* Note that we have to test for the actual rtx used for the frame
         and arg pointers and not just the register number in case we have
         eliminated the frame and/or arg pointer and are using it
@@ -1115,10 +1142,9 @@ const_or_frame_p (rtx x)
          || x == pic_offset_table_rtx)
        return true;
       return false;
-
-    default:
-      return false;
     }
+  
+  return false;
 }
 
 /* Take all reasonable action to put the address of MEM into the form
@@ -1151,44 +1177,11 @@ canon_address (rtx mem,
   rtx expanded_address, address;
   int expanded;
 
-  /* Make sure that cselib is has initialized all of the operands of
-     the address before asking it to do the subst.  */
-
-  if (clear_alias_sets)
-    {
-      /* If this is a spill, do not do any further processing.  */
-      alias_set_type alias_set = MEM_ALIAS_SET (mem);
-      if (dump_file)
-       fprintf (dump_file, "found alias set %d\n", (int) alias_set);
-      if (bitmap_bit_p (clear_alias_sets, alias_set))
-       {
-         struct clear_alias_mode_holder *entry
-           = clear_alias_set_lookup (alias_set);
-
-         /* If the modes do not match, we cannot process this set.  */
-         if (entry->mode != GET_MODE (mem))
-           {
-             if (dump_file)
-               fprintf (dump_file,
-                        "disqualifying alias set %d, (%s) != (%s)\n",
-                        (int) alias_set, GET_MODE_NAME (entry->mode),
-                        GET_MODE_NAME (GET_MODE (mem)));
-
-             bitmap_set_bit (disqualified_clear_alias_sets, alias_set);
-             return false;
-           }
-
-         *alias_set_out = alias_set;
-         *group_id = clear_alias_group->id;
-         return true;
-       }
-    }
-
   *alias_set_out = 0;
 
   cselib_lookup (mem_address, address_mode, 1, GET_MODE (mem));
 
-  if (dump_file)
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "  mem: ");
       print_inline_rtx (dump_file, mem_address, 0);
@@ -1228,7 +1221,7 @@ canon_address (rtx mem,
 
       *offset = 0;
 
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        {
          if (expanded)
            {
@@ -1257,7 +1250,7 @@ canon_address (rtx mem,
        {
          group_info_t group = get_group_info (address);
 
-         if (dump_file)
+         if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "  gid=%d offset=%d \n",
                     group->id, (int)*offset);
          *base = NULL;
@@ -1271,11 +1264,11 @@ canon_address (rtx mem,
 
   if (*base == NULL)
     {
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, " no cselib val - should be a wild read.\n");
       return false;
     }
-  if (dump_file)
+  if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "  varying cselib base=%u:%u offset = %d\n",
             (*base)->uid, (*base)->hash, (int)*offset);
   return true;
@@ -1418,7 +1411,7 @@ record_store (rtx body, bb_info_t bb_info)
     {
       if (GET_CODE (XEXP (mem, 0)) == SCRATCH)
        {
-         if (dump_file)
+         if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, " adding wild read for (clobber (mem:BLK (scratch))\n");
          add_wild_read (bb_info);
          insn_info->cannot_delete = true;
@@ -1456,10 +1449,7 @@ record_store (rtx body, bb_info_t bb_info)
   if (GET_MODE (mem) == BLKmode)
     width = MEM_SIZE (mem);
   else
-    {
-      width = GET_MODE_SIZE (GET_MODE (mem));
-      gcc_assert ((unsigned) width <= HOST_BITS_PER_WIDE_INT);
-    }
+    width = GET_MODE_SIZE (GET_MODE (mem));
 
   if (spill_alias_set)
     {
@@ -1476,7 +1466,7 @@ record_store (rtx body, bb_info_t bb_info)
 
       store_info = (store_info_t) pool_alloc (rtx_store_info_pool);
 
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, " processing spill store %d(%s)\n",
                 (int) spill_alias_set, GET_MODE_NAME (GET_MODE (mem)));
     }
@@ -1486,13 +1476,13 @@ record_store (rtx body, bb_info_t bb_info)
         frame pointer we can do global analysis.  */
 
       group_info_t group
-       = VEC_index (group_info_t, rtx_group_vec, group_id);
+       = rtx_group_vec[group_id];
       tree expr = MEM_EXPR (mem);
 
       store_info = (store_info_t) pool_alloc (rtx_store_info_pool);
       set_usage_bits (group, offset, width, expr);
 
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, " processing const base store gid=%d[%d..%d)\n",
                 group_id, (int)offset, (int)(offset+width));
     }
@@ -1505,7 +1495,7 @@ record_store (rtx body, bb_info_t bb_info)
       store_info = (store_info_t) pool_alloc (cse_store_info_pool);
       group_id = -1;
 
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, " processing cselib store [%d..%d)\n",
                 (int)offset, (int)(offset+width));
     }
@@ -1556,7 +1546,7 @@ record_store (rtx body, bb_info_t bb_info)
       else
        {
          group_info_t group
-           = VEC_index (group_info_t, rtx_group_vec, group_id);
+           = rtx_group_vec[group_id];
          mem_addr = group->canon_base_addr;
        }
       if (offset)
@@ -1592,7 +1582,7 @@ record_store (rtx body, bb_info_t bb_info)
              del = true;
              set_all_positions_unneeded (s_info);
            }
-         if (dump_file)
+         if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "    trying spill store in insn=%d alias_set=%d\n",
                     INSN_UID (ptr->insn), (int) s_info->alias_set);
        }
@@ -1600,7 +1590,7 @@ record_store (rtx body, bb_info_t bb_info)
               && (s_info->cse_base == base))
        {
          HOST_WIDE_INT i;
-         if (dump_file)
+         if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "    trying store in insn=%d gid=%d[%d..%d)\n",
                     INSN_UID (ptr->insn), s_info->group_id,
                     (int)s_info->begin, (int)s_info->end);
@@ -1695,7 +1685,7 @@ record_store (rtx body, bb_info_t bb_info)
     {
       store_info->is_large = true;
       store_info->positions_needed.large.count = 0;
-      store_info->positions_needed.large.bmap = BITMAP_ALLOC (NULL);
+      store_info->positions_needed.large.bmap = BITMAP_ALLOC (&dse_bitmap_obstack);
     }
   else
     {
@@ -1991,7 +1981,7 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
      in cache, so it is not going to be an expensive one.  Thus, we
      are not willing to do a multi insn shift or worse a subroutine
      call to get rid of the read.  */
-  if (dump_file)
+  if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "trying to replace %smode load in insn %d"
             " from %smode store in insn %d\n",
             GET_MODE_NAME (read_mode), INSN_UID (read_insn->insn),
@@ -2004,7 +1994,7 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
   if (read_reg == NULL_RTX)
     {
       end_sequence ();
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, " -- could not extract bits of stored value\n");
       return false;
     }
@@ -2021,7 +2011,7 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
         live at this point.  For instance, this can happen if one of
         the insns sets the CC and the CC happened to be live at that
         point.  This does occasionally happen, see PR 37922.  */
-      bitmap regs_set = BITMAP_ALLOC (NULL);
+      bitmap regs_set = BITMAP_ALLOC (&reg_obstack);
 
       for (this_insn = insns; this_insn != NULL_RTX; this_insn = NEXT_INSN (this_insn))
        note_stores (PATTERN (this_insn), look_for_hardregs, regs_set);
@@ -2029,7 +2019,7 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
       bitmap_and_into (regs_set, regs_live);
       if (!bitmap_empty_p (regs_set))
        {
-         if (dump_file)
+         if (dump_file && (dump_flags & TDF_DETAILS))
            {
              fprintf (dump_file,
                       "abandoning replacement because sequence clobbers live hardregs:");
@@ -2084,7 +2074,7 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
         rest of dse, play like this read never happened.  */
       read_insn->read_rec = read_info->next;
       pool_free (read_info_pool, read_info);
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        {
          fprintf (dump_file, " -- replaced the loaded MEM with ");
          print_simple_rtl (dump_file, read_reg);
@@ -2094,7 +2084,7 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
     }
   else
     {
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        {
          fprintf (dump_file, " -- replacing the loaded MEM with ");
          print_simple_rtl (dump_file, read_reg);
@@ -2130,7 +2120,7 @@ check_mem_read_rtx (rtx *loc, void *data)
   if ((MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER)
       || (MEM_VOLATILE_P (mem)))
     {
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, " adding wild read, volatile or barrier.\n");
       add_wild_read (bb_info);
       insn_info->cannot_delete = true;
@@ -2144,7 +2134,7 @@ check_mem_read_rtx (rtx *loc, void *data)
 
   if (!canon_address (mem, &spill_alias_set, &group_id, &offset, &base))
     {
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, " adding wild read, canon_address failure.\n");
       add_wild_read (bb_info);
       return 0;
@@ -2173,7 +2163,7 @@ check_mem_read_rtx (rtx *loc, void *data)
       else
        {
          group_info_t group
-           = VEC_index (group_info_t, rtx_group_vec, group_id);
+           = rtx_group_vec[group_id];
          mem_addr = group->canon_base_addr;
        }
       if (offset)
@@ -2188,7 +2178,7 @@ check_mem_read_rtx (rtx *loc, void *data)
       insn_info_t i_ptr = active_local_stores;
       insn_info_t last = NULL;
 
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, " processing spill load %d\n",
                 (int) spill_alias_set);
 
@@ -2202,7 +2192,7 @@ check_mem_read_rtx (rtx *loc, void *data)
 
          if (store_info->alias_set == spill_alias_set)
            {
-             if (dump_file)
+             if (dump_file && (dump_flags & TDF_DETAILS))
                dump_insn_info ("removing from active", i_ptr);
 
              active_local_stores_len--;
@@ -2223,7 +2213,7 @@ check_mem_read_rtx (rtx *loc, void *data)
       insn_info_t i_ptr = active_local_stores;
       insn_info_t last = NULL;
 
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        {
          if (width == -1)
            fprintf (dump_file, " processing const load gid=%d[BLK]\n",
@@ -2292,7 +2282,7 @@ check_mem_read_rtx (rtx *loc, void *data)
 
          if (remove)
            {
-             if (dump_file)
+             if (dump_file && (dump_flags & TDF_DETAILS))
                dump_insn_info ("removing from active", i_ptr);
 
              active_local_stores_len--;
@@ -2310,7 +2300,7 @@ check_mem_read_rtx (rtx *loc, void *data)
     {
       insn_info_t i_ptr = active_local_stores;
       insn_info_t last = NULL;
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        {
          fprintf (dump_file, " processing cselib load mem:");
          print_inline_rtx (dump_file, mem, 0);
@@ -2322,7 +2312,7 @@ check_mem_read_rtx (rtx *loc, void *data)
          bool remove = false;
          store_info_t store_info = i_ptr->store_rec;
 
-         if (dump_file)
+         if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, " processing cselib load against insn %d\n",
                     INSN_UID (i_ptr->insn));
 
@@ -2352,7 +2342,7 @@ check_mem_read_rtx (rtx *loc, void *data)
 
          if (remove)
            {
-             if (dump_file)
+             if (dump_file && (dump_flags & TDF_DETAILS))
                dump_insn_info ("removing from active", i_ptr);
 
              active_local_stores_len--;
@@ -2466,7 +2456,7 @@ scan_insn (bb_info_t bb_info, rtx insn)
   int mems_found = 0;
   memset (insn_info, 0, sizeof (struct insn_info));
 
-  if (dump_file)
+  if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "\n**scanning insn=%d\n",
             INSN_UID (insn));
 
@@ -2480,17 +2470,6 @@ scan_insn (bb_info_t bb_info, rtx insn)
       return;
     }
 
-  /* Cselib clears the table for this case, so we have to essentially
-     do the same.  */
-  if (NONJUMP_INSN_P (insn)
-      && GET_CODE (PATTERN (insn)) == ASM_OPERANDS
-      && MEM_VOLATILE_P (PATTERN (insn)))
-    {
-      add_wild_read (bb_info);
-      insn_info->cannot_delete = true;
-      return;
-    }
-
   /* Look at all of the uses in the insn.  */
   note_uses (&PATTERN (insn), check_mem_read_use, bb_info);
 
@@ -2508,14 +2487,8 @@ scan_insn (bb_info_t bb_info, rtx insn)
       const_call = RTL_CONST_CALL_P (insn);
       if (!const_call)
        {
-         rtx call = PATTERN (insn);
-         if (GET_CODE (call) == PARALLEL)
-           call = XVECEXP (call, 0, 0);
-         if (GET_CODE (call) == SET)
-           call = SET_SRC (call);
-         if (GET_CODE (call) == CALL
-             && MEM_P (XEXP (call, 0))
-             && GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
+         rtx call = get_call_rtx_from (insn);
+         if (call && GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
            {
              rtx symbol = XEXP (XEXP (call, 0), 0);
              if (SYMBOL_REF_DECL (symbol)
@@ -2535,7 +2508,7 @@ scan_insn (bb_info_t bb_info, rtx insn)
          insn_info_t i_ptr = active_local_stores;
          insn_info_t last = NULL;
 
-         if (dump_file)
+         if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "%s call %d\n",
                     const_call ? "const" : "memset", INSN_UID (insn));
 
@@ -2563,14 +2536,13 @@ scan_insn (bb_info_t bb_info, rtx insn)
                    store_info = store_info->next;
 
                  if (store_info->group_id >= 0
-                     && VEC_index (group_info_t, rtx_group_vec,
-                                   store_info->group_id)->frame_related)
+                     && rtx_group_vec[store_info->group_id]->frame_related)
                    remove_store = true;
                }
 
              if (remove_store)
                {
-                 if (dump_file)
+                 if (dump_file && (dump_flags & TDF_DETAILS))
                    dump_insn_info ("removing from active", i_ptr);
 
                  active_local_stores_len--;
@@ -2597,7 +2569,7 @@ scan_insn (bb_info_t bb_info, rtx insn)
                  set_mem_size (mem, INTVAL (args[2]));
                  body = gen_rtx_SET (VOIDmode, mem, args[1]);
                  mems_found += record_store (body, bb_info);
-                 if (dump_file)
+                 if (dump_file && (dump_flags & TDF_DETAILS))
                    fprintf (dump_file, "handling memset as BLKmode store\n");
                  if (mems_found == 1)
                    {
@@ -2628,7 +2600,7 @@ scan_insn (bb_info_t bb_info, rtx insn)
      them.  */
   if ((GET_CODE (PATTERN (insn)) == CLOBBER)
       || volatile_refs_p (PATTERN (insn))
-      || insn_could_throw_p (insn)
+      || (!cfun->can_delete_dead_exceptions && !insn_nothrow_p (insn))
       || (RTX_FRAME_RELATED_P (insn))
       || find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX))
     insn_info->cannot_delete = true;
@@ -2643,7 +2615,7 @@ scan_insn (bb_info_t bb_info, rtx insn)
   else
     mems_found += record_store (body, bb_info);
 
-  if (dump_file)
+  if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "mems_found = %d, cannot_delete = %s\n",
             mems_found, insn_info->cannot_delete ? "true" : "false");
 
@@ -2719,14 +2691,14 @@ static void
 dse_step1 (void)
 {
   basic_block bb;
-  bitmap regs_live = BITMAP_ALLOC (NULL);
+  bitmap regs_live = BITMAP_ALLOC (&reg_obstack);
 
   cselib_init (0);
   all_blocks = BITMAP_ALLOC (NULL);
   bitmap_set_bit (all_blocks, ENTRY_BLOCK);
   bitmap_set_bit (all_blocks, EXIT_BLOCK);
 
-  FOR_ALL_BB (bb)
+  FOR_ALL_BB_FN (bb, cfun)
     {
       insn_info_t ptr;
       bb_info_t bb_info = (bb_info_t) pool_alloc (bb_info_pool);
@@ -2774,7 +2746,7 @@ dse_step1 (void)
          if (stores_off_frame_dead_at_return
              && (EDGE_COUNT (bb->succs) == 0
                  || (single_succ_p (bb)
-                     && single_succ (bb) == EXIT_BLOCK_PTR
+                     && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun)
                      && ! crtl->calls_eh_return)))
            {
              insn_info_t i_ptr = active_local_stores;
@@ -2791,7 +2763,7 @@ dse_step1 (void)
                    if (store_info->group_id >= 0)
                      {
                        group_info_t group
-                         = VEC_index (group_info_t, rtx_group_vec, store_info->group_id);
+                         = rtx_group_vec[store_info->group_id];
                        if (group->frame_related && !i_ptr->cannot_delete)
                          delete_dead_store_insn (i_ptr);
                      }
@@ -2829,7 +2801,7 @@ dse_step1 (void)
                      && s_info->redundant_reason->insn
                      && !ptr->cannot_delete)
                    {
-                     if (dump_file)
+                     if (dump_file && (dump_flags & TDF_DETAILS))
                        fprintf (dump_file, "Locally deleting insn %d "
                                            "because insn %d stores the "
                                            "same value and couldn't be "
@@ -2838,8 +2810,6 @@ dse_step1 (void)
                                 INSN_UID (s_info->redundant_reason->insn));
                      delete_dead_store_insn (ptr);
                    }
-                 if (s_info)
-                   s_info->redundant_reason = NULL;
                  free_store_info (ptr);
                }
              else
@@ -2864,7 +2834,7 @@ dse_step1 (void)
 
   BITMAP_FREE (regs_live);
   cselib_finish ();
-  htab_empty (rtx_group_table);
+  rtx_group_table.empty ();
 }
 
 \f
@@ -2882,7 +2852,7 @@ dse_step2_init (void)
   unsigned int i;
   group_info_t group;
 
-  FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
+  FOR_EACH_VEC_ELT (rtx_group_vec, i, group)
     {
       /* For all non stack related bases, we only consider a store to
         be deletable if there are two or more stores for that
@@ -2902,16 +2872,18 @@ dse_step2_init (void)
        {
          bitmap_ior_into (group->store2_n, group->store1_n);
          bitmap_ior_into (group->store2_p, group->store1_p);
-         if (dump_file)
+         if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "group %d is frame related ", i);
        }
 
       group->offset_map_size_n++;
-      group->offset_map_n = XNEWVEC (int, group->offset_map_size_n);
+      group->offset_map_n = XOBNEWVEC (&dse_obstack, int,
+                                      group->offset_map_size_n);
       group->offset_map_size_p++;
-      group->offset_map_p = XNEWVEC (int, group->offset_map_size_p);
+      group->offset_map_p = XOBNEWVEC (&dse_obstack, int,
+                                      group->offset_map_size_p);
       group->process_globally = false;
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        {
          fprintf (dump_file, "group %d(%d+%d): ", i,
                   (int)bitmap_count_bits (group->store2_n),
@@ -2933,7 +2905,7 @@ dse_step2_nospill (void)
   /* Position 0 is unused because 0 is used in the maps to mean
      unused.  */
   current_position = 1;
-  FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
+  FOR_EACH_VEC_ELT (rtx_group_vec, i, group)
     {
       bitmap_iterator bi;
       unsigned int j;
@@ -2941,8 +2913,8 @@ dse_step2_nospill (void)
       if (group == clear_alias_group)
        continue;
 
-      memset (group->offset_map_n, 0, sizeof(int) * group->offset_map_size_n);
-      memset (group->offset_map_p, 0, sizeof(int) * group->offset_map_size_p);
+      memset (group->offset_map_n, 0, sizeof (int) * group->offset_map_size_n);
+      memset (group->offset_map_p, 0, sizeof (int) * group->offset_map_size_p);
       bitmap_clear (group->group_kill);
 
       EXECUTE_IF_SET_IN_BITMAP (group->store2_n, 0, j, bi)
@@ -2966,47 +2938,6 @@ dse_step2_nospill (void)
 }
 
 
-/* Init the offset tables for the spill case.  */
-
-static bool
-dse_step2_spill (void)
-{
-  unsigned int j;
-  group_info_t group = clear_alias_group;
-  bitmap_iterator bi;
-
-  /* Position 0 is unused because 0 is used in the maps to mean
-     unused.  */
-  current_position = 1;
-
-  if (dump_file)
-    {
-      bitmap_print (dump_file, clear_alias_sets,
-                   "clear alias sets              ", "\n");
-      bitmap_print (dump_file, disqualified_clear_alias_sets,
-                   "disqualified clear alias sets ", "\n");
-    }
-
-  memset (group->offset_map_n, 0, sizeof(int) * group->offset_map_size_n);
-  memset (group->offset_map_p, 0, sizeof(int) * group->offset_map_size_p);
-  bitmap_clear (group->group_kill);
-
-  /* Remove the disqualified positions from the store2_p set.  */
-  bitmap_and_compl_into (group->store2_p, disqualified_clear_alias_sets);
-
-  /* We do not need to process the store2_n set because
-     alias_sets are always positive.  */
-  EXECUTE_IF_SET_IN_BITMAP (group->store2_p, 0, j, bi)
-    {
-      bitmap_set_bit (group->group_kill, current_position);
-      group->offset_map_p[j] = current_position++;
-      group->process_globally = true;
-    }
-
-  return current_position != 1;
-}
-
-
 \f
 /*----------------------------------------------------------------------------
   Third step.
@@ -3047,7 +2978,7 @@ scan_stores_nospill (store_info_t store_info, bitmap gen, bitmap kill)
     {
       HOST_WIDE_INT i;
       group_info_t group_info
-       = VEC_index (group_info_t, rtx_group_vec, store_info->group_id);
+       = rtx_group_vec[store_info->group_id];
       if (group_info->process_globally)
        for (i = store_info->begin; i < store_info->end; i++)
          {
@@ -3101,7 +3032,7 @@ scan_reads_nospill (insn_info_t insn_info, bitmap gen, bitmap kill)
   /* If this insn reads the frame, kill all the frame related stores.  */
   if (insn_info->frame_read)
     {
-      FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
+      FOR_EACH_VEC_ELT (rtx_group_vec, i, group)
        if (group->process_globally && group->frame_related)
          {
            if (kill)
@@ -3116,7 +3047,7 @@ scan_reads_nospill (insn_info_t insn_info, bitmap gen, bitmap kill)
       if (kill)
         bitmap_ior_into (kill, kill_on_calls);
       bitmap_and_compl_into (gen, kill_on_calls);
-      FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
+      FOR_EACH_VEC_ELT (rtx_group_vec, i, group)
        if (group->process_globally && !group->frame_related)
          {
            if (kill)
@@ -3126,7 +3057,7 @@ scan_reads_nospill (insn_info_t insn_info, bitmap gen, bitmap kill)
     }
   while (read_info)
     {
-      FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
+      FOR_EACH_VEC_ELT (rtx_group_vec, i, group)
        {
          if (group->process_globally)
            {
@@ -3262,7 +3193,7 @@ dse_step3_scan (bool for_spills, basic_block bb)
       if (bb_info->kill)
        bitmap_clear (bb_info->kill);
       else
-       bb_info->kill = BITMAP_ALLOC (NULL);
+       bb_info->kill = BITMAP_ALLOC (&dse_bitmap_obstack);
     }
   else
     if (bb_info->kill)
@@ -3306,7 +3237,7 @@ dse_step3_exit_block_scan (bb_info_t bb_info)
       unsigned int i;
       group_info_t group;
 
-      FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
+      FOR_EACH_VEC_ELT (rtx_group_vec, i, group)
        {
          if (group->process_globally && group->frame_related)
            bitmap_ior_into (bb_info->gen, group->group_kill);
@@ -3326,9 +3257,9 @@ mark_reachable_blocks (sbitmap unreachable_blocks, basic_block bb)
   edge e;
   edge_iterator ei;
 
-  if (TEST_BIT (unreachable_blocks, bb->index))
+  if (bitmap_bit_p (unreachable_blocks, bb->index))
     {
-      RESET_BIT (unreachable_blocks, bb->index);
+      bitmap_clear_bit (unreachable_blocks, bb->index);
       FOR_EACH_EDGE (e, ei, bb->preds)
        {
          mark_reachable_blocks (unreachable_blocks, e->src);
@@ -3342,20 +3273,20 @@ static void
 dse_step3 (bool for_spills)
 {
   basic_block bb;
-  sbitmap unreachable_blocks = sbitmap_alloc (last_basic_block);
+  sbitmap unreachable_blocks = sbitmap_alloc (last_basic_block_for_fn (cfun));
   sbitmap_iterator sbi;
   bitmap all_ones = NULL;
   unsigned int i;
 
-  sbitmap_ones (unreachable_blocks);
+  bitmap_ones (unreachable_blocks);
 
-  FOR_ALL_BB (bb)
+  FOR_ALL_BB_FN (bb, cfun)
     {
       bb_info_t bb_info = bb_table[bb->index];
       if (bb_info->gen)
        bitmap_clear (bb_info->gen);
       else
-       bb_info->gen = BITMAP_ALLOC (NULL);
+       bb_info->gen = BITMAP_ALLOC (&dse_bitmap_obstack);
 
       if (bb->index == ENTRY_BLOCK)
        ;
@@ -3377,7 +3308,7 @@ dse_step3 (bool for_spills)
   /* For any block in an infinite loop, we must initialize the out set
      to all ones.  This could be expensive, but almost never occurs in
      practice. However, it is common in regression tests.  */
-  EXECUTE_IF_SET_IN_SBITMAP (unreachable_blocks, 0, i, sbi)
+  EXECUTE_IF_SET_IN_BITMAP (unreachable_blocks, 0, i, sbi)
     {
       if (bitmap_bit_p (all_blocks, i))
        {
@@ -3387,13 +3318,13 @@ dse_step3 (bool for_spills)
              unsigned int j;
              group_info_t group;
 
-             all_ones = BITMAP_ALLOC (NULL);
-             FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, j, group)
+             all_ones = BITMAP_ALLOC (&dse_bitmap_obstack);
+             FOR_EACH_VEC_ELT (rtx_group_vec, j, group)
                bitmap_ior_into (all_ones, group->group_kill);
            }
          if (!bb_info->out)
            {
-             bb_info->out = BITMAP_ALLOC (NULL);
+             bb_info->out = BITMAP_ALLOC (&dse_bitmap_obstack);
              bitmap_copy (bb_info->out, all_ones);
            }
        }
@@ -3429,7 +3360,7 @@ dse_confluence_0 (basic_block bb)
 
   if (!bb_info->out)
     {
-      bb_info->out = BITMAP_ALLOC (NULL);
+      bb_info->out = BITMAP_ALLOC (&dse_bitmap_obstack);
       bitmap_copy (bb_info->out, bb_table[EXIT_BLOCK]->gen);
     }
 }
@@ -3450,7 +3381,7 @@ dse_confluence_n (edge e)
        bitmap_and_into (src_info->out, dest_info->in);
       else
        {
-         src_info->out = BITMAP_ALLOC (NULL);
+         src_info->out = BITMAP_ALLOC (&dse_bitmap_obstack);
          bitmap_copy (src_info->out, dest_info->in);
        }
     }
@@ -3489,7 +3420,7 @@ dse_transfer_function (int bb_index)
                                         bb_info->out, bb_info->kill);
          else
            {
-             bb_info->in = BITMAP_ALLOC (NULL);
+             bb_info->in = BITMAP_ALLOC (&dse_bitmap_obstack);
              bitmap_ior_and_compl (bb_info->in, bb_info->gen,
                                    bb_info->out, bb_info->kill);
              return true;
@@ -3507,7 +3438,7 @@ dse_transfer_function (int bb_index)
        return false;
       else
        {
-         bb_info->in = BITMAP_ALLOC (NULL);
+         bb_info->in = BITMAP_ALLOC (&dse_bitmap_obstack);
          bitmap_copy (bb_info->in, bb_info->gen);
          return true;
        }
@@ -3523,12 +3454,12 @@ dse_step4 (void)
                      dse_confluence_n, dse_transfer_function,
                      all_blocks, df_get_postorder (DF_BACKWARD),
                      df_get_n_blocks (DF_BACKWARD));
-  if (dump_file)
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
       basic_block bb;
 
       fprintf (dump_file, "\n\n*** Global dataflow info after analysis.\n");
-      FOR_ALL_BB (bb)
+      FOR_ALL_BB_FN (bb, cfun)
        {
          bb_info_t bb_info = bb_table[bb->index];
 
@@ -3566,7 +3497,7 @@ static void
 dse_step5_nospill (void)
 {
   basic_block bb;
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     {
       bb_info_t bb_info = bb_table[bb->index];
       insn_info_t insn_info = bb_info->last_insn;
@@ -3604,17 +3535,17 @@ dse_step5_nospill (void)
                {
                  HOST_WIDE_INT i;
                  group_info_t group_info
-                   = VEC_index (group_info_t, rtx_group_vec, store_info->group_id);
+                   = rtx_group_vec[store_info->group_id];
 
                  for (i = store_info->begin; i < store_info->end; i++)
                    {
                      int index = get_bitmap_index (group_info, i);
 
-                     if (dump_file)
+                     if (dump_file && (dump_flags & TDF_DETAILS))
                        fprintf (dump_file, "i = %d, index = %d\n", (int)i, index);
                      if (index == 0 || !bitmap_bit_p (v, index))
                        {
-                         if (dump_file)
+                         if (dump_file && (dump_flags & TDF_DETAILS))
                            fprintf (dump_file, "failing at i = %d\n", (int)i);
                          deleted = false;
                          break;
@@ -3642,7 +3573,7 @@ dse_step5_nospill (void)
              scan_stores_nospill (insn_info->store_rec, v, NULL);
              if (insn_info->wild_read)
                {
-                 if (dump_file)
+                 if (dump_file && (dump_flags & TDF_DETAILS))
                    fprintf (dump_file, "wild read\n");
                  bitmap_clear (v);
                }
@@ -3651,7 +3582,7 @@ dse_step5_nospill (void)
                {
                  if (dump_file && !insn_info->non_frame_wild_read)
                    fprintf (dump_file, "regular read\n");
-                  else if (dump_file)
+                  else if (dump_file && (dump_flags & TDF_DETAILS))
                    fprintf (dump_file, "non-frame wild read\n");
                  scan_reads_nospill (insn_info, v, NULL);
                }
@@ -3663,72 +3594,6 @@ dse_step5_nospill (void)
 }
 
 
-static void
-dse_step5_spill (void)
-{
-  basic_block bb;
-  FOR_EACH_BB (bb)
-    {
-      bb_info_t bb_info = bb_table[bb->index];
-      insn_info_t insn_info = bb_info->last_insn;
-      bitmap v = bb_info->out;
-
-      while (insn_info)
-       {
-         bool deleted = false;
-         /* There may have been code deleted by the dce pass run before
-            this phase.  */
-         if (insn_info->insn
-             && INSN_P (insn_info->insn)
-             && (!insn_info->cannot_delete)
-             && (!bitmap_empty_p (v)))
-           {
-             /* Try to delete the current insn.  */
-             store_info_t store_info = insn_info->store_rec;
-             deleted = true;
-
-             while (store_info)
-               {
-                 if (store_info->alias_set)
-                   {
-                     int index = get_bitmap_index (clear_alias_group,
-                                                   store_info->alias_set);
-                     if (index == 0 || !bitmap_bit_p (v, index))
-                       {
-                         deleted = false;
-                         break;
-                       }
-                   }
-                 else
-                   deleted = false;
-                 store_info = store_info->next;
-               }
-             if (deleted && dbg_cnt (dse)
-                 && check_for_inc_dec_1 (insn_info))
-               {
-                 if (dump_file)
-                   fprintf (dump_file, "Spill deleting insn %d\n",
-                            INSN_UID (insn_info->insn));
-                 delete_insn (insn_info->insn);
-                 spill_deleted++;
-                 insn_info->insn = NULL;
-               }
-           }
-
-         if (insn_info->insn
-             && INSN_P (insn_info->insn)
-             && (!deleted))
-           {
-             scan_stores_spill (insn_info->store_rec, v, NULL);
-             scan_reads_spill (insn_info->read_rec, v, NULL);
-           }
-
-         insn_info = insn_info->prev_insn;
-       }
-    }
-}
-
-
 \f
 /*----------------------------------------------------------------------------
    Sixth step.
@@ -3742,7 +3607,7 @@ dse_step6 (void)
 {
   basic_block bb;
 
-  FOR_ALL_BB (bb)
+  FOR_ALL_BB_FN (bb, cfun)
     {
       bb_info_t bb_info = bb_table[bb->index];
       insn_info_t insn_info = bb_info->last_insn;
@@ -3765,7 +3630,7 @@ dse_step6 (void)
                  && INSN_P (s_info->redundant_reason->insn))
                {
                  rtx rinsn = s_info->redundant_reason->insn;
-                 if (dump_file)
+                 if (dump_file && (dump_flags & TDF_DETAILS))
                    fprintf (dump_file, "Locally deleting insn %d "
                                        "because insn %d stores the "
                                        "same value and couldn't be "
@@ -3787,53 +3652,17 @@ dse_step6 (void)
 ----------------------------------------------------------------------------*/
 
 static void
-dse_step7 (bool global_done)
+dse_step7 (void)
 {
-  unsigned int i;
-  group_info_t group;
-  basic_block bb;
-
-  FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
-    {
-      free (group->offset_map_n);
-      free (group->offset_map_p);
-      BITMAP_FREE (group->store1_n);
-      BITMAP_FREE (group->store1_p);
-      BITMAP_FREE (group->store2_n);
-      BITMAP_FREE (group->store2_p);
-      BITMAP_FREE (group->escaped_n);
-      BITMAP_FREE (group->escaped_p);
-      BITMAP_FREE (group->group_kill);
-    }
-
-  if (global_done)
-    FOR_ALL_BB (bb)
-      {
-       bb_info_t bb_info = bb_table[bb->index];
-       BITMAP_FREE (bb_info->gen);
-       if (bb_info->kill)
-         BITMAP_FREE (bb_info->kill);
-       if (bb_info->in)
-         BITMAP_FREE (bb_info->in);
-       if (bb_info->out)
-         BITMAP_FREE (bb_info->out);
-      }
-
-  if (clear_alias_sets)
-    {
-      BITMAP_FREE (clear_alias_sets);
-      BITMAP_FREE (disqualified_clear_alias_sets);
-      free_alloc_pool (clear_alias_mode_pool);
-      htab_delete (clear_alias_mode_table);
-    }
+  bitmap_obstack_release (&dse_bitmap_obstack);
+  obstack_free (&dse_obstack, NULL);
 
   end_alias_analysis ();
   free (bb_table);
-  htab_delete (rtx_group_table);
-  VEC_free (group_info_t, heap, rtx_group_vec);
+  rtx_group_table.dispose ();
+  rtx_group_vec.release ();
   BITMAP_FREE (all_blocks);
   BITMAP_FREE (scratch);
-  BITMAP_FREE (kill_on_calls);
 
   free_alloc_pool (rtx_store_info_pool);
   free_alloc_pool (read_info_pool);
@@ -3853,8 +3682,6 @@ dse_step7 (bool global_done)
 static unsigned int
 rest_of_handle_dse (void)
 {
-  bool did_global = false;
-
   df_set_flags (DF_DEFER_INSN_RESCAN);
 
   /* Need the notes since we must track live hardregs in the forwards
@@ -3869,36 +3696,15 @@ rest_of_handle_dse (void)
     {
       df_set_flags (DF_LR_RUN_DCE);
       df_analyze ();
-      did_global = true;
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "doing global processing\n");
       dse_step3 (false);
       dse_step4 ();
       dse_step5_nospill ();
     }
 
-  /* For the instance of dse that runs after reload, we make a special
-     pass to process the spills.  These are special in that they are
-     totally transparent, i.e, there is no aliasing issues that need
-     to be considered.  This means that the wild reads that kill
-     everything else do not apply here.  */
-  if (clear_alias_sets && dse_step2_spill ())
-    {
-      if (!did_global)
-       {
-         df_set_flags (DF_LR_RUN_DCE);
-         df_analyze ();
-       }
-      did_global = true;
-      if (dump_file)
-       fprintf (dump_file, "doing global spill processing\n");
-      dse_step3 (true);
-      dse_step4 ();
-      dse_step5_spill ();
-    }
-
   dse_step6 ();
-  dse_step7 (did_global);
+  dse_step7 ();
 
   if (dump_file)
     fprintf (dump_file, "dse: local deletions = %d, global deletions = %d, spill deletions = %d\n",
@@ -3920,42 +3726,78 @@ gate_dse2 (void)
     && dbg_cnt (dse2);
 }
 
-struct rtl_opt_pass pass_rtl_dse1 =
-{
- {
-  RTL_PASS,
-  "dse1",                               /* name */
-  gate_dse1,                            /* gate */
-  rest_of_handle_dse,                   /* execute */
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  TV_DSE1,                              /* tv_id */
-  0,                                    /* properties_required */
-  0,                                    /* properties_provided */
-  0,                                    /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  TODO_df_finish | TODO_verify_rtl_sharing |
-  TODO_ggc_collect                      /* todo_flags_finish */
- }
+namespace {
+
+const pass_data pass_data_rtl_dse1 =
+{
+  RTL_PASS, /* type */
+  "dse1", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_DSE1, /* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  ( TODO_df_finish | TODO_verify_rtl_sharing ), /* todo_flags_finish */
 };
 
-struct rtl_opt_pass pass_rtl_dse2 =
-{
- {
-  RTL_PASS,
-  "dse2",                               /* name */
-  gate_dse2,                            /* gate */
-  rest_of_handle_dse,                   /* execute */
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  TV_DSE2,                              /* tv_id */
-  0,                                    /* properties_required */
-  0,                                    /* properties_provided */
-  0,                                    /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  TODO_df_finish | TODO_verify_rtl_sharing |
-  TODO_ggc_collect                      /* todo_flags_finish */
- }
+class pass_rtl_dse1 : public rtl_opt_pass
+{
+public:
+  pass_rtl_dse1 (gcc::context *ctxt)
+    : rtl_opt_pass (pass_data_rtl_dse1, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_dse1 (); }
+  unsigned int execute () { return rest_of_handle_dse (); }
+
+}; // class pass_rtl_dse1
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_rtl_dse1 (gcc::context *ctxt)
+{
+  return new pass_rtl_dse1 (ctxt);
+}
+
+namespace {
+
+const pass_data pass_data_rtl_dse2 =
+{
+  RTL_PASS, /* type */
+  "dse2", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_DSE2, /* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  ( TODO_df_finish | TODO_verify_rtl_sharing ), /* todo_flags_finish */
 };
+
+class pass_rtl_dse2 : public rtl_opt_pass
+{
+public:
+  pass_rtl_dse2 (gcc::context *ctxt)
+    : rtl_opt_pass (pass_data_rtl_dse2, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_dse2 (); }
+  unsigned int execute () { return rest_of_handle_dse (); }
+
+}; // class pass_rtl_dse2
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_rtl_dse2 (gcc::context *ctxt)
+{
+  return new pass_rtl_dse2 (ctxt);
+}