diff gcc/dse.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
line wrap: on
line diff
--- a/gcc/dse.c	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/dse.c	Fri Oct 27 22:46:09 2017 +0900
@@ -1,6 +1,5 @@
 /* RTL dead store elimination.
-   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2005-2017 Free Software Foundation, Inc.
 
    Contributed by Richard Sandiford <rsandifor@codesourcery.com>
    and Kenneth Zadeck <zadeck@naturalbridge.com>
@@ -26,27 +25,31 @@
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "hashtab.h"
-#include "tm.h"
+#include "backend.h"
+#include "target.h"
 #include "rtl.h"
 #include "tree.h"
+#include "gimple.h"
+#include "predict.h"
+#include "df.h"
+#include "memmodel.h"
 #include "tm_p.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "flags.h"
-#include "df.h"
+#include "gimple-ssa.h"
+#include "expmed.h"
+#include "optabs.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "alias.h"
+#include "stor-layout.h"
+#include "cfgrtl.h"
 #include "cselib.h"
-#include "timevar.h"
 #include "tree-pass.h"
-#include "alloc-pool.h"
-#include "alias.h"
-#include "insn-config.h"
+#include "explow.h"
 #include "expr.h"
-#include "recog.h"
-#include "dse.h"
-#include "optabs.h"
 #include "dbgcnt.h"
-#include "target.h"
+#include "params.h"
+#include "rtl-iter.h"
+#include "cfgcleanup.h"
 
 /* This file contains three techniques for performing Dead Store
    Elimination (dse).
@@ -61,7 +64,7 @@
    frame_pointer.
 
    * The third technique, (which is only done after register allocation)
-   processes the spill spill slots.  This differs from the second
+   processes the spill slots.  This differs from the second
    technique because it takes advantage of the fact that spilling is
    completely free from the effects of aliasing.
 
@@ -93,7 +96,7 @@
    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.
@@ -104,7 +107,7 @@
    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.
@@ -113,18 +116,18 @@
    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
@@ -135,7 +138,7 @@
      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
@@ -199,9 +202,22 @@
    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;
+
+struct insn_info_type;
 
 /* This structure holds information about a candidate store.  */
 struct store_info
@@ -227,9 +243,6 @@
   /* Canonized MEM address for use by canon_true_dependence.  */
   rtx mem_addr;
 
-  /* If this is non-zero, it is the alias set of a spill location.  */
-  alias_set_type alias_set;
-
   /* The offset of the first and byte before the last byte associated
      with the operation.  */
   HOST_WIDE_INT begin, end;
@@ -268,7 +281,7 @@
   /* Set if this store stores the same constant value as REDUNDANT_REASON
      insn stored.  These aren't eliminated early, because doing that
      might prevent the earlier larger store to be eliminated.  */
-  struct insn_info *redundant_reason;
+  struct insn_info_type *redundant_reason;
 };
 
 /* Return a bitmask with the first N low bits set.  */
@@ -276,24 +289,21 @@
 static unsigned HOST_WIDE_INT
 lowpart_bitmask (int n)
 {
-  unsigned HOST_WIDE_INT mask = ~(unsigned HOST_WIDE_INT) 0;
+  unsigned HOST_WIDE_INT mask = HOST_WIDE_INT_M1U;
   return mask >> (HOST_BITS_PER_WIDE_INT - n);
 }
 
-typedef struct store_info *store_info_t;
-static alloc_pool cse_store_info_pool;
-static alloc_pool rtx_store_info_pool;
+static object_allocator<store_info> cse_store_info_pool ("cse_store_info_pool");
+
+static object_allocator<store_info> rtx_store_info_pool ("rtx_store_info_pool");
 
 /* This structure holds information about a load.  These are only
    built for rtx bases.  */
-struct read_info
+struct read_info_type
 {
   /* The id of the mem group of the base address.  */
   int group_id;
 
-  /* If this is non-zero, it is the alias set of a spill location.  */
-  alias_set_type alias_set;
-
   /* The offset of the first and byte after the last byte associated
      with the operation.  If begin == end == 0, the read did not have
      a constant offset.  */
@@ -303,15 +313,15 @@
   rtx mem;
 
   /* The next read_info for this insn.  */
-  struct read_info *next;
+  struct read_info_type *next;
 };
-typedef struct read_info *read_info_t;
-static alloc_pool read_info_pool;
-
+typedef struct read_info_type *read_info_t;
+
+static object_allocator<read_info_type> read_info_type_pool ("read_info_pool");
 
 /* One of these records is created for each insn.  */
 
-struct insn_info
+struct insn_info_type
 {
   /* Set true if the insn contains a store but the insn itself cannot
      be deleted.  This is set if the insn is a parallel and there is
@@ -325,6 +335,11 @@
      contains a wild read, the use_rec will be null.  */
   bool wild_read;
 
+  /* This is true only for CALL instructions which could potentially read
+     any non-frame memory location. This field is used by the global
+     algorithm.  */
+  bool non_frame_wild_read;
+
   /* This field is only used for the processing of const functions.
      These functions cannot read memory, but they can read the stack
      because that is where they may get their parms.  We need to be
@@ -340,9 +355,11 @@
 	either stack pointer or hard frame pointer based.  This means
 	that we have no other choice than also killing all the frame
 	pointer based stores upon encountering a const function call.
-     This field is set after reload for const function calls.  Having
-     this set is less severe than a wild read, it just means that all
-     the frame related stores are killed rather than all the stores.  */
+     This field is set after reload for const function calls and before
+     reload for const tail function calls on targets where arg pointer
+     is the frame pointer.  Having this set is less severe than a wild
+     read, it just means that all the frame related stores are killed
+     rather than all the stores.  */
   bool frame_read;
 
   /* This field is only used for the processing of const functions.
@@ -355,14 +372,14 @@
   bool contains_cselib_groups;
 
   /* The insn. */
-  rtx insn;
+  rtx_insn *insn;
 
   /* The list of mem sets or mem clobbers that are contained in this
      insn.  If the insn is deletable, it contains only one mem set.
      But it could also contain clobbers.  Insns that contain more than
      one mem set are not deletable, but each of those mems are here in
      order to provide info to delete other insns.  */
-  store_info_t store_rec;
+  store_info *store_rec;
 
   /* The linked list of mem uses in this insn.  Only the reads from
      rtx bases are listed here.  The reads to cselib bases are
@@ -370,27 +387,34 @@
      created.  */
   read_info_t read_rec;
 
+  /* The live fixed registers.  We assume only fixed registers can
+     cause trouble by being clobbered from an expanded pattern;
+     storing only the live fixed registers (rather than all registers)
+     means less memory needs to be allocated / copied for the individual
+     stores.  */
+  regset fixed_regs_live;
+
   /* The prev insn in the basic block.  */
-  struct insn_info * prev_insn;
+  struct insn_info_type * 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.  */
-  struct insn_info * next_local_store;
+  struct insn_info_type * next_local_store;
 };
-
-typedef struct insn_info *insn_info_t;
-static alloc_pool insn_info_pool;
+typedef struct insn_info_type *insn_info_t;
+
+static object_allocator<insn_info_type> insn_info_type_pool ("insn_info_pool");
 
 /* The linked list of stores that are under consideration in this
    basic block.  */
 static insn_info_t active_local_stores;
-
-struct bb_info
+static int active_local_stores_len;
+
+struct dse_bb_info_type
 {
-
   /* Pointer to the insn info for the last insn in the block.  These
      are linked so this is how all of the insns are reached.  During
      scanning this is the current insn being scanned.  */
@@ -440,14 +464,16 @@
   /* The following bitvector is indexed by the reg number.  It
      contains the set of regs that are live at the current instruction
      being processed.  While it contains info for all of the
-     registers, only the pseudos are actually examined.  It is used to
-     assure that shift sequences that are inserted do not accidently
-     clobber live hard regs.  */
+     registers, only the hard registers are actually examined.  It is used
+     to assure that shift and/or add sequences that are inserted do not
+     accidentally clobber live hard regs.  */
   bitmap regs_live;
 };
 
-typedef struct bb_info *bb_info_t;
-static alloc_pool bb_info_pool;
+typedef struct dse_bb_info_type *bb_info_t;
+
+static object_allocator<dse_bb_info_type> dse_bb_info_type_pool
+  ("bb_info_pool");
 
 /* Table to hold all bb_infos.  */
 static bb_info_t *bb_table;
@@ -499,6 +525,11 @@
      deleted.  */
   bitmap store1_n, store1_p, store2_n, store2_p;
 
+  /* These bitmaps keep track of offsets in this group escape this function.
+     An offset escapes if it corresponds to a named variable whose
+     addressable flag is set.  */
+  bitmap escaped_n, escaped_p;
+
   /* The positions in this bitmap have the same assignments as the in,
      out, gen and kill bitmaps.  This bitmap is all zeros except for
      the positions that are occupied by stores for this group.  */
@@ -511,20 +542,14 @@
   int *offset_map_n, *offset_map_p;
   int offset_map_size_n, offset_map_size_p;
 };
-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;
+
+static object_allocator<group_info> group_info_pool ("rtx_group_info_pool");
 
 /* 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 *> rtx_group_vec;
 
 
 /* This structure holds the set of changes that are being deferred
@@ -541,39 +566,10 @@
   struct deferred_change *next;
 };
 
-typedef struct deferred_change *deferred_change_t;
-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;
-
-/* The modes of the clear_alias_sets.  */
-static htab_t clear_alias_mode_table;
-
-/* Hash table element to look up the mode for an alias set.  */
-struct clear_alias_mode_holder
-{
-  alias_set_type alias_set;
-  enum machine_mode mode;
-};
-
-static alloc_pool clear_alias_mode_pool;
+static object_allocator<deferred_change> deferred_change_pool
+  ("deferred_change_pool");
+
+static deferred_change *deferred_change_list = NULL;
 
 /* This is true except if cfun->stdarg -- i.e. we cannot do
    this for vararg functions because they play games with the frame.  */
@@ -582,18 +578,14 @@
 /* Counter for stats.  */
 static int globally_deleted;
 static int locally_deleted;
-static int spill_deleted;
 
 static bitmap all_blocks;
 
+/* Locations that are killed by calls in the global phase.  */
+static bitmap kill_on_calls;
+
 /* The number of bits used in the global bitmaps.  */
 static unsigned int current_position;
-
-
-static bool gate_dse (void);
-static bool gate_dse1 (void);
-static bool gate_dse2 (void);
-
 
 /*----------------------------------------------------------------------------
    Zeroth step.
@@ -601,118 +593,65 @@
    Initialization.
 ----------------------------------------------------------------------------*/
 
-/* Hashtable callbacks for maintaining the "bases" field of
-   store_group_info, given that the addresses are function invariants.  */
-
-static int
-clear_alias_mode_eq (const void *p1, const void *p2)
-{
-  const struct clear_alias_mode_holder * h1
-    = (const struct clear_alias_mode_holder *) p1;
-  const struct clear_alias_mode_holder * h2
-    = (const struct clear_alias_mode_holder *) p2;
-  return h1->alias_set == h2->alias_set;
-}
-
-
-static hashval_t
-clear_alias_mode_hash (const void *p)
-{
-  const struct clear_alias_mode_holder *holder
-    = (const struct clear_alias_mode_holder *) p;
-  return holder->alias_set;
-}
-
-
-/* Find the entry associated with ALIAS_SET.  */
-
-static struct clear_alias_mode_holder *
-clear_alias_set_lookup (alias_set_type alias_set)
-{
-  struct clear_alias_mode_holder tmp_holder;
-  void **slot;
-
-  tmp_holder.alias_set = alias_set;
-  slot = htab_find_slot (clear_alias_mode_table, &tmp_holder, NO_INSERT);
-  gcc_assert (*slot);
-
-  return (struct clear_alias_mode_holder *) *slot;
-}
-
 
 /* 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 : nofree_ptr_hash <group_info>
 {
-  const_group_info_t gi1 = (const_group_info_t) p1;
-  const_group_info_t gi2 = (const_group_info_t) p2;
+  static inline hashval_t hash (const group_info *);
+  static inline bool equal (const group_info *, const group_info *);
+};
+
+inline bool
+invariant_group_base_hasher::equal (const group_info *gi1,
+				    const group_info *gi2)
+{
   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 group_info *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.  */
 
-static group_info_t
+static group_info *
 get_group_info (rtx base)
 {
   struct group_info tmp_gi;
-  group_info_t gi;
-  void **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);
-      gi = (group_info_t) *slot;
-    }
-  else
-    {
-      if (!clear_alias_group)
-	{
-	  clear_alias_group = gi =
-	    (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->group_kill = BITMAP_ALLOC (NULL);
-	  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);
-	}
-      return clear_alias_group;
-    }
+  group_info *gi;
+  group_info **slot;
+
+  gcc_assert (base != NULL_RTX);
+
+  /* Find the store_base_info structure for BASE, creating a new one
+     if necessary.  */
+  tmp_gi.rtx_base = base;
+  slot = rtx_group_table->find_slot (&tmp_gi, INSERT);
+  gi = *slot;
 
   if (gi == NULL)
     {
-      *slot = gi = (group_info_t) pool_alloc (rtx_group_info_pool);
+      *slot = gi = group_info_pool.allocate ();
       gi->rtx_base = 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->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);
@@ -720,7 +659,7 @@
       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;
@@ -734,43 +673,22 @@
 {
   locally_deleted = 0;
   globally_deleted = 0;
-  spill_deleted = 0;
-
-  scratch = BITMAP_ALLOC (NULL);
-
-  rtx_store_info_pool
-    = create_alloc_pool ("rtx_store_info_pool",
-			 sizeof (struct store_info), 100);
-  read_info_pool
-    = create_alloc_pool ("read_info_pool",
-			 sizeof (struct read_info), 100);
-  insn_info_pool
-    = create_alloc_pool ("insn_info_pool",
-			 sizeof (struct insn_info), 100);
-  bb_info_pool
-    = create_alloc_pool ("bb_info_pool",
-			 sizeof (struct bb_info), 100);
-  rtx_group_info_pool
-    = create_alloc_pool ("rtx_group_info_pool",
-			 sizeof (struct group_info), 100);
-  deferred_change_pool
-    = 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);
-
-  bb_table = XCNEWVEC (bb_info_t, last_basic_block);
+
+  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_group_table = new hash_table<invariant_group_base_hasher> (11);
+
+  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;
 }
 
 
@@ -788,17 +706,17 @@
 static void
 free_store_info (insn_info_t insn_info)
 {
-  store_info_t store_info = insn_info->store_rec;
-  while (store_info)
+  store_info *cur = insn_info->store_rec;
+  while (cur)
     {
-      store_info_t next = store_info->next;
-      if (store_info->is_large)
-	BITMAP_FREE (store_info->positions_needed.large.bmap);
-      if (store_info->cse_base)
-	pool_free (cse_store_info_pool, store_info);
+      store_info *next = cur->next;
+      if (cur->is_large)
+	BITMAP_FREE (cur->positions_needed.large.bmap);
+      if (cur->cse_base)
+	cse_store_info_pool.remove (cur);
       else
-	pool_free (rtx_store_info_pool, store_info);
-      store_info = next;
+	rtx_store_info_pool.remove (cur);
+      cur = next;
     }
 
   insn_info->cannot_delete = true;
@@ -806,6 +724,49 @@
   insn_info->store_rec = NULL;
 }
 
+struct note_add_store_info
+{
+  rtx_insn *first, *current;
+  regset fixed_regs_live;
+  bool failure;
+};
+
+/* Callback for emit_inc_dec_insn_before via note_stores.
+   Check if a register is clobbered which is live afterwards.  */
+
+static void
+note_add_store (rtx loc, const_rtx expr ATTRIBUTE_UNUSED, void *data)
+{
+  rtx_insn *insn;
+  note_add_store_info *info = (note_add_store_info *) data;
+
+  if (!REG_P (loc))
+    return;
+
+  /* If this register is referenced by the current or an earlier insn,
+     that's OK.  E.g. this applies to the register that is being incremented
+     with this addition.  */
+  for (insn = info->first;
+       insn != NEXT_INSN (info->current);
+       insn = NEXT_INSN (insn))
+    if (reg_referenced_p (loc, PATTERN (insn)))
+      return;
+
+  /* If we come here, we have a clobber of a register that's only OK
+     if that register is not live.  If we don't have liveness information
+     available, fail now.  */
+  if (!info->fixed_regs_live)
+    {
+      info->failure = true;
+      return;
+    }
+  /* Now check if this is a live fixed register.  */
+  unsigned int end_regno = END_REGNO (loc);
+  for (unsigned int regno = REGNO (loc); regno < end_regno; ++regno)
+    if (REGNO_REG_SET_P (info->fixed_regs_live, regno))
+      info->failure = true;
+}
+
 /* Callback for for_each_inc_dec that emits an INSN that sets DEST to
    SRC + SRCOFF before insn ARG.  */
 
@@ -814,31 +775,75 @@
 			  rtx op ATTRIBUTE_UNUSED,
 			  rtx dest, rtx src, rtx srcoff, void *arg)
 {
-  rtx insn = (rtx)arg;
-
-  if (srcoff)
-    src = gen_rtx_PLUS (GET_MODE (src), src, srcoff);
+  insn_info_t insn_info = (insn_info_t) arg;
+  rtx_insn *insn = insn_info->insn, *new_insn, *cur;
+  note_add_store_info info;
 
   /* We can reuse all operands without copying, because we are about
      to delete the insn that contained it.  */
-
-  emit_insn_before (gen_rtx_SET (VOIDmode, dest, src), insn);
-
-  return -1;
+  if (srcoff)
+    {
+      start_sequence ();
+      emit_insn (gen_add3_insn (dest, src, srcoff));
+      new_insn = get_insns ();
+      end_sequence ();
+    }
+  else
+    new_insn = gen_move_insn (dest, src);
+  info.first = new_insn;
+  info.fixed_regs_live = insn_info->fixed_regs_live;
+  info.failure = false;
+  for (cur = new_insn; cur; cur = NEXT_INSN (cur))
+    {
+      info.current = cur;
+      note_stores (PATTERN (cur), note_add_store, &info);
+    }
+
+  /* If a failure was flagged above, return 1 so that for_each_inc_dec will
+     return it immediately, communicating the failure to its caller.  */
+  if (info.failure)
+    return 1;
+
+  emit_insn_before (new_insn, insn);
+
+  return 0;
 }
 
-/* Before we delete INSN, make sure that the auto inc/dec, if it is
-   there, is split into a separate insn.  */
-
-void
-check_for_inc_dec (rtx insn)
+/* Before we delete INSN_INFO->INSN, make sure that the auto inc/dec, if it
+   is there, is split into a separate insn.
+   Return true on success (or if there was nothing to do), false on failure.  */
+
+static bool
+check_for_inc_dec_1 (insn_info_t insn_info)
 {
+  rtx_insn *insn = insn_info->insn;
   rtx note = find_reg_note (insn, REG_INC, NULL_RTX);
   if (note)
-    for_each_inc_dec (&insn, emit_inc_dec_insn_before, insn);
+    return for_each_inc_dec (PATTERN (insn), emit_inc_dec_insn_before,
+			     insn_info) == 0;
+  return true;
 }
 
 
+/* Entry point for postreload.  If you work on reload_cse, or you need this
+   anywhere else, consider if you can provide register liveness information
+   and add a parameter to this function so that it can be passed down in
+   insn_info.fixed_regs_live.  */
+bool
+check_for_inc_dec (rtx_insn *insn)
+{
+  insn_info_type insn_info;
+  rtx note;
+
+  insn_info.insn = insn;
+  insn_info.fixed_regs_live = NULL;
+  note = find_reg_note (insn, REG_INC, NULL_RTX);
+  if (note)
+    return for_each_inc_dec (PATTERN (insn), emit_inc_dec_insn_before,
+			     &insn_info) == 0;
+  return true;
+}
+
 /* Delete the insn and free all of the fields inside INSN_INFO.  */
 
 static void
@@ -849,17 +854,11 @@
   if (!dbg_cnt (dse))
     return;
 
-  check_for_inc_dec (insn_info->insn);
-  if (dump_file)
-    {
-      fprintf (dump_file, "Locally deleting insn %d ",
-	       INSN_UID (insn_info->insn));
-      if (insn_info->store_rec->alias_set)
-	fprintf (dump_file, "alias set %d\n",
-		 (int) insn_info->store_rec->alias_set);
-      else
-	fprintf (dump_file, "\n");
-    }
+  if (!check_for_inc_dec_1 (insn_info))
+    return;
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "Locally deleting insn %d\n",
+	     INSN_UID (insn_info->insn));
 
   free_store_info (insn_info);
   read_info = insn_info->read_rec;
@@ -867,7 +866,7 @@
   while (read_info)
     {
       read_info_t next = read_info->next;
-      pool_free (read_info_pool, read_info);
+      read_info_type_pool.remove (read_info);
       read_info = next;
     }
   insn_info->read_rec = NULL;
@@ -879,31 +878,76 @@
   insn_info->wild_read = false;
 }
 
+/* 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)
+    {
+      tree *namep = cfun->gimple_df->decls_to_pointers->get (decl);
+      if (namep)
+	return TREE_ADDRESSABLE (*namep);
+    }
+
+  return false;
+}
+
+/* Return whether EXPR can possibly escape the current function scope.  */
+
+static bool
+can_escape (tree expr)
+{
+  tree base;
+  if (!expr)
+    return true;
+  base = get_base_address (expr);
+  if (DECL_P (base)
+      && !may_be_aliased (base)
+      && !(VAR_P (base)
+	   && !DECL_EXTERNAL (base)
+	   && !TREE_STATIC (base)
+	   && local_variable_can_escape (base)))
+    return false;
+  return true;
+}
 
 /* Set the store* bitmaps offset_map_size* fields in GROUP based on
    OFFSET and WIDTH.  */
 
 static void
-set_usage_bits (group_info_t group, HOST_WIDE_INT offset, HOST_WIDE_INT width)
+set_usage_bits (group_info *group, HOST_WIDE_INT offset, HOST_WIDE_INT width,
+                tree expr)
 {
   HOST_WIDE_INT i;
-
+  bool expr_escapes = can_escape (expr);
   if (offset > -MAX_OFFSET && offset + width < MAX_OFFSET)
     for (i=offset; i<offset+width; i++)
       {
 	bitmap store1;
 	bitmap store2;
+        bitmap escaped;
 	int ai;
 	if (i < 0)
 	  {
 	    store1 = group->store1_n;
 	    store2 = group->store2_n;
+	    escaped = group->escaped_n;
 	    ai = -i;
 	  }
 	else
 	  {
 	    store1 = group->store1_p;
 	    store2 = group->store2_p;
+	    escaped = group->escaped_p;
 	    ai = i;
 	  }
 
@@ -922,9 +966,32 @@
 		  group->offset_map_size_p = ai;
 	      }
 	  }
+        if (expr_escapes)
+          bitmap_set_bit (escaped, ai);
       }
 }
 
+static void
+reset_active_stores (void)
+{
+  active_local_stores = NULL;
+  active_local_stores_len = 0;
+}
+
+/* Free all READ_REC of the LAST_INSN of BB_INFO.  */
+
+static void
+free_read_records (bb_info_t bb_info)
+{
+  insn_info_t insn_info = bb_info->last_insn;
+  read_info_t *ptr = &insn_info->read_rec;
+  while (*ptr)
+    {
+      read_info_t next = (*ptr)->next;
+      read_info_type_pool.remove (*ptr);
+      *ptr = next;
+    }
+}
 
 /* Set the BB_INFO so that the last insn is marked as a wild read.  */
 
@@ -932,23 +999,22 @@
 add_wild_read (bb_info_t bb_info)
 {
   insn_info_t insn_info = bb_info->last_insn;
-  read_info_t *ptr = &insn_info->read_rec;
-
-  while (*ptr)
-    {
-      read_info_t next = (*ptr)->next;
-      if ((*ptr)->alias_set == 0)
-        {
-          pool_free (read_info_pool, *ptr);
-          *ptr = next;
-	}
-      else
-	ptr = &(*ptr)->next;
-    }
   insn_info->wild_read = true;
-  active_local_stores = NULL;
+  free_read_records (bb_info);
+  reset_active_stores ();
 }
 
+/* Set the BB_INFO so that the last insn is marked as a wild read of
+   non-frame locations.  */
+
+static void
+add_non_frame_wild_read (bb_info_t bb_info)
+{
+  insn_info_t insn_info = bb_info->last_insn;
+  insn_info->non_frame_wild_read = true;
+  free_read_records (bb_info);
+  reset_active_stores ();
+}
 
 /* Return true if X is a constant or one of the registers that behave
    as a constant over the life of a function.  This is equivalent to
@@ -957,17 +1023,11 @@
 static bool
 const_or_frame_p (rtx x)
 {
-  switch (GET_CODE (x))
+  if (CONSTANT_P (x))
+    return true;
+
+  if (GET_CODE (x) == REG)
     {
-    case CONST:
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST_VECTOR:
-    case SYMBOL_REF:
-    case LABEL_REF:
-      return true;
-
-    case 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
@@ -978,10 +1038,9 @@
 	  || 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
@@ -1004,55 +1063,18 @@
 
 static bool
 canon_address (rtx mem,
-	       alias_set_type *alias_set_out,
 	       int *group_id,
 	       HOST_WIDE_INT *offset,
 	       cselib_val **base)
 {
-  enum machine_mode address_mode
-    = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem));
+  machine_mode address_mode = get_address_mode (mem);
   rtx mem_address = XEXP (mem, 0);
   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);
@@ -1092,7 +1114,7 @@
 
       *offset = 0;
 
-      if (dump_file)
+      if (dump_file && (dump_flags & TDF_DETAILS))
 	{
 	  if (expanded)
 	    {
@@ -1119,9 +1141,9 @@
       if (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (mem))
 	  && const_or_frame_p (address))
 	{
-	  group_info_t group = get_group_info (address);
-
-	  if (dump_file)
+	  group_info *group = get_group_info (address);
+
+	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    fprintf (dump_file, "  gid=%d offset=%d \n",
 		     group->id, (int)*offset);
 	  *base = NULL;
@@ -1135,11 +1157,11 @@
 
   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;
@@ -1155,7 +1177,7 @@
 
   while (ptr)
     {
-      store_info_t store_info = ptr->store_rec;
+      store_info *store_info = ptr->store_rec;
       /* Skip the clobbers.  */
       while (!store_info->is_set)
 	store_info = store_info->next;
@@ -1171,7 +1193,7 @@
 /* Mark byte POS bytes from the beginning of store S_INFO as unneeded.  */
 
 static inline void
-set_position_unneeded (store_info_t s_info, int pos)
+set_position_unneeded (store_info *s_info, int pos)
 {
   if (__builtin_expect (s_info->is_large, false))
     {
@@ -1180,13 +1202,13 @@
     }
   else
     s_info->positions_needed.small_bitmask
-      &= ~(((unsigned HOST_WIDE_INT) 1) << pos);
+      &= ~(HOST_WIDE_INT_1U << pos);
 }
 
 /* Mark the whole store S_INFO as unneeded.  */
 
 static inline void
-set_all_positions_unneeded (store_info_t s_info)
+set_all_positions_unneeded (store_info *s_info)
 {
   if (__builtin_expect (s_info->is_large, false))
     {
@@ -1196,27 +1218,26 @@
       s_info->positions_needed.large.count = end;
     }
   else
-    s_info->positions_needed.small_bitmask = (unsigned HOST_WIDE_INT) 0;
+    s_info->positions_needed.small_bitmask = HOST_WIDE_INT_0U;
 }
 
 /* Return TRUE if any bytes from S_INFO store are needed.  */
 
 static inline bool
-any_positions_needed_p (store_info_t s_info)
+any_positions_needed_p (store_info *s_info)
 {
   if (__builtin_expect (s_info->is_large, false))
     return (s_info->positions_needed.large.count
 	    < s_info->end - s_info->begin);
   else
-    return (s_info->positions_needed.small_bitmask
-	    != (unsigned HOST_WIDE_INT) 0);
+    return (s_info->positions_needed.small_bitmask != HOST_WIDE_INT_0U);
 }
 
 /* Return TRUE if all bytes START through START+WIDTH-1 from S_INFO
    store are needed.  */
 
 static inline bool
-all_positions_needed_p (store_info_t s_info, int start, int width)
+all_positions_needed_p (store_info *s_info, int start, int width)
 {
   if (__builtin_expect (s_info->is_large, false))
     {
@@ -1234,7 +1255,7 @@
 }
 
 
-static rtx get_stored_val (store_info_t, enum machine_mode, HOST_WIDE_INT,
+static rtx get_stored_val (store_info *, machine_mode, HOST_WIDE_INT,
 			   HOST_WIDE_INT, basic_block, bool);
 
 
@@ -1248,9 +1269,8 @@
   rtx mem, rhs, const_rhs, mem_addr;
   HOST_WIDE_INT offset = 0;
   HOST_WIDE_INT width = 0;
-  alias_set_type spill_alias_set;
   insn_info_t insn_info = bb_info->last_insn;
-  store_info_t store_info = NULL;
+  store_info *store_info = NULL;
   int group_id;
   cselib_val *base = NULL;
   insn_info_t ptr, last, redundant_reason;
@@ -1282,7 +1302,7 @@
     {
       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;
@@ -1290,11 +1310,10 @@
 	}
       /* Handle (set (mem:BLK (addr) [... S36 ...]) (const_int 0))
 	 as memset (addr, 0, 36);  */
-      else if (!MEM_SIZE (mem)
-	       || !CONST_INT_P (MEM_SIZE (mem))
+      else if (!MEM_SIZE_KNOWN_P (mem)
+	       || MEM_SIZE (mem) <= 0
+	       || MEM_SIZE (mem) > MAX_OFFSET
 	       || GET_CODE (body) != SET
-	       || INTVAL (MEM_SIZE (mem)) <= 0
-	       || INTVAL (MEM_SIZE (mem)) > MAX_OFFSET
 	       || !CONST_INT_P (SET_SRC (body)))
 	{
 	  if (!store_is_unused)
@@ -1312,68 +1331,43 @@
   if (MEM_VOLATILE_P (mem))
     insn_info->cannot_delete = true;
 
-  if (!canon_address (mem, &spill_alias_set, &group_id, &offset, &base))
+  if (!canon_address (mem, &group_id, &offset, &base))
     {
       clear_rhs_from_active_local_stores ();
       return 0;
     }
 
   if (GET_MODE (mem) == BLKmode)
-    width = INTVAL (MEM_SIZE (mem));
+    width = MEM_SIZE (mem);
   else
-    {
-      width = GET_MODE_SIZE (GET_MODE (mem));
-      gcc_assert ((unsigned) width <= HOST_BITS_PER_WIDE_INT);
-    }
-
-  if (spill_alias_set)
-    {
-      bitmap store1 = clear_alias_group->store1_p;
-      bitmap store2 = clear_alias_group->store2_p;
-
-      gcc_assert (GET_MODE (mem) != BLKmode);
-
-      if (!bitmap_set_bit (store1, spill_alias_set))
-	bitmap_set_bit (store2, spill_alias_set);
-
-      if (clear_alias_group->offset_map_size_p < spill_alias_set)
-	clear_alias_group->offset_map_size_p = spill_alias_set;
-
-      store_info = (store_info_t) pool_alloc (rtx_store_info_pool);
-
-      if (dump_file)
-	fprintf (dump_file, " processing spill store %d(%s)\n",
-		 (int) spill_alias_set, GET_MODE_NAME (GET_MODE (mem)));
-    }
-  else if (group_id >= 0)
+    width = GET_MODE_SIZE (GET_MODE (mem));
+
+  if (group_id >= 0)
     {
       /* In the restrictive case where the base is a constant or the
 	 frame pointer we can do global analysis.  */
 
-      group_info_t group
-	= VEC_index (group_info_t, rtx_group_vec, group_id);
-
-      store_info = (store_info_t) pool_alloc (rtx_store_info_pool);
-      set_usage_bits (group, offset, width);
-
-      if (dump_file)
+      group_info *group
+	= rtx_group_vec[group_id];
+      tree expr = MEM_EXPR (mem);
+
+      store_info = rtx_store_info_pool.allocate ();
+      set_usage_bits (group, offset, width, expr);
+
+      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));
     }
   else
     {
-      rtx base_term = find_base_term (XEXP (mem, 0));
-      if (!base_term
-	  || (GET_CODE (base_term) == ADDRESS
-	      && GET_MODE (base_term) == Pmode
-	      && XEXP (base_term, 0) == stack_pointer_rtx))
+      if (may_be_sp_based_p (XEXP (mem, 0)))
 	insn_info->stack_pointer_based = true;
       insn_info->contains_cselib_groups = true;
 
-      store_info = (store_info_t) pool_alloc (cse_store_info_pool);
+      store_info = cse_store_info_pool.allocate ();
       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));
     }
@@ -1414,27 +1408,21 @@
   last = NULL;
   redundant_reason = NULL;
   mem = canon_rtx (mem);
-  /* For alias_set != 0 canon_true_dependence should be never called.  */
-  if (spill_alias_set)
-    mem_addr = NULL_RTX;
+
+  if (group_id < 0)
+    mem_addr = base->val_rtx;
   else
     {
-      if (group_id < 0)
-	mem_addr = base->val_rtx;
-      else
-	{
-	  group_info_t group
-	    = VEC_index (group_info_t, rtx_group_vec, group_id);
-	  mem_addr = group->canon_base_addr;
-	}
-      if (offset)
-	mem_addr = plus_constant (mem_addr, offset);
+      group_info *group = rtx_group_vec[group_id];
+      mem_addr = group->canon_base_addr;
     }
+  if (offset)
+    mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset);
 
   while (ptr)
     {
       insn_info_t next = ptr->next_local_store;
-      store_info_t s_info = ptr->store_rec;
+      struct store_info *s_info = ptr->store_rec;
       bool del = true;
 
       /* Skip the clobbers. We delete the active insn if this insn
@@ -1443,32 +1431,10 @@
       while (!s_info->is_set)
 	s_info = s_info->next;
 
-      if (s_info->alias_set != spill_alias_set)
-	del = false;
-      else if (s_info->alias_set)
-	{
-	  struct clear_alias_mode_holder *entry
-	    = clear_alias_set_lookup (s_info->alias_set);
-	  /* Generally, spills cannot be processed if and of the
-	     references to the slot have a different mode.  But if
-	     we are in the same block and mode is exactly the same
-	     between this store and one before in the same block,
-	     we can still delete it.  */
-	  if ((GET_MODE (mem) == GET_MODE (s_info->mem))
-	      && (GET_MODE (mem) == entry->mode))
-	    {
-	      del = true;
-	      set_all_positions_unneeded (s_info);
-	    }
-	  if (dump_file)
-	    fprintf (dump_file, "    trying spill store in insn=%d alias_set=%d\n",
-		     INSN_UID (ptr->insn), (int) s_info->alias_set);
-	}
-      else if ((s_info->group_id == group_id)
-	       && (s_info->cse_base == base))
+      if (s_info->group_id == group_id && 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);
@@ -1518,10 +1484,9 @@
 	   the value of store_info.  If it is, set the rhs to NULL to
 	   keep it from being used to remove a load.  */
 	{
-	  if (canon_true_dependence (s_info->mem,
-				     GET_MODE (s_info->mem),
-				     s_info->mem_addr,
-				     mem, mem_addr, rtx_varies_p))
+	  if (canon_output_dependence (s_info->mem, true,
+				       mem, GET_MODE (mem),
+				       mem_addr))
 	    {
 	      s_info->rhs = NULL;
 	      s_info->const_rhs = NULL;
@@ -1530,20 +1495,21 @@
 
       /* An insn can be deleted if every position of every one of
 	 its s_infos is zero.  */
-      if (any_positions_needed_p (s_info)
-	  || ptr->cannot_delete)
+      if (any_positions_needed_p (s_info))
 	del = false;
 
       if (del)
 	{
 	  insn_info_t insn_to_delete = ptr;
 
+	  active_local_stores_len--;
 	  if (last)
 	    last->next_local_store = ptr->next_local_store;
 	  else
 	    active_local_stores = ptr->next_local_store;
 
-	  delete_dead_store_insn (insn_to_delete);
+	  if (!insn_to_delete->cannot_delete)
+	    delete_dead_store_insn (insn_to_delete);
 	}
       else
 	last = ptr;
@@ -1555,14 +1521,13 @@
   store_info->next = insn_info->store_rec;
   insn_info->store_rec = store_info;
   store_info->mem = mem;
-  store_info->alias_set = spill_alias_set;
   store_info->mem_addr = mem_addr;
   store_info->cse_base = base;
   if (width > HOST_BITS_PER_WIDE_INT)
     {
       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
     {
@@ -1603,12 +1568,12 @@
 
 static rtx
 find_shift_sequence (int access_size,
-		     store_info_t store_info,
-		     enum machine_mode read_mode,
+		     store_info *store_info,
+		     machine_mode read_mode,
 		     int shift, bool speed, bool require_cst)
 {
-  enum machine_mode store_mode = GET_MODE (store_info->mem);
-  enum machine_mode new_mode;
+  machine_mode store_mode = GET_MODE (store_info->mem);
+  scalar_int_mode new_mode;
   rtx read_reg = NULL;
 
   /* Some machines like the x86 have shift insns for each size of
@@ -1618,14 +1583,18 @@
      justify the value we want to read but is available in one insn on
      the machine.  */
 
-  for (new_mode = smallest_mode_for_size (access_size * BITS_PER_UNIT,
-					  MODE_INT);
-       GET_MODE_BITSIZE (new_mode) <= BITS_PER_WORD;
-       new_mode = GET_MODE_WIDER_MODE (new_mode))
+  opt_scalar_int_mode new_mode_iter;
+  FOR_EACH_MODE_FROM (new_mode_iter,
+		      smallest_int_mode_for_size (access_size * BITS_PER_UNIT))
     {
-      rtx target, new_reg, shift_seq, insn, new_lhs;
+      rtx target, new_reg, new_lhs;
+      rtx_insn *shift_seq, *insn;
       int cost;
 
+      new_mode = new_mode_iter.require ();
+      if (GET_MODE_BITSIZE (new_mode) > BITS_PER_WORD)
+	break;
+
       /* If a constant was stored into memory, try to simplify it here,
 	 otherwise the cost of the shift might preclude this optimization
 	 e.g. at -Os, even when no actual shift will be needed.  */
@@ -1643,7 +1612,8 @@
 		  byte = subreg_lowpart_offset (read_mode, new_mode);
 		  ret = simplify_subreg (read_mode, ret, new_mode, byte);
 		  if (ret && CONSTANT_P (ret)
-		      && rtx_cost (ret, SET, speed) <= COSTS_N_INSNS (1))
+		      && (set_src_cost (ret, read_mode, speed)
+			  <= COSTS_N_INSNS (1)))
 		    return ret;
 		}
 	    }
@@ -1655,14 +1625,13 @@
       /* Try a wider mode if truncating the store mode to NEW_MODE
 	 requires a real instruction.  */
       if (GET_MODE_BITSIZE (new_mode) < GET_MODE_BITSIZE (store_mode)
-	  && !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (new_mode),
-				     GET_MODE_BITSIZE (store_mode)))
+	  && !TRULY_NOOP_TRUNCATION_MODES_P (new_mode, store_mode))
 	continue;
 
       /* Also try a wider mode if the necessary punning is either not
 	 desirable or not possible.  */
       if (!CONSTANT_P (store_info->rhs)
-	  && !MODES_TIEABLE_P (new_mode, store_mode))
+	  && !targetm.modes_tieable_p (new_mode, store_mode))
 	continue;
 
       new_reg = gen_reg_rtx (new_mode);
@@ -1684,7 +1653,7 @@
       cost = 0;
       for (insn = shift_seq; insn != NULL_RTX; insn = NEXT_INSN (insn))
 	if (INSN_P (insn))
-	  cost += insn_rtx_cost (PATTERN (insn), speed);
+	  cost += insn_cost (insn, speed);
 
       /* The computation up to here is essentially independent
 	 of the arguments and could be precomputed.  It may
@@ -1724,13 +1693,8 @@
   bitmap regs_set = (bitmap) data;
 
   if (REG_P (x)
-      && REGNO (x) < FIRST_PSEUDO_REGISTER)
-    {
-      int regno = REGNO (x);
-      int n = hard_regno_nregs[regno][GET_MODE (x)];
-      while (--n >= 0)
-	bitmap_set_bit (regs_set, regno + n);
-    }
+      && HARD_REGISTER_P (x))
+    bitmap_set_range (regs_set, REGNO (x), REG_NREGS (x));
 }
 
 /* Helper function for replace_read and record_store.
@@ -1739,11 +1703,11 @@
    if not successful.  If REQUIRE_CST is true, return always constant.  */
 
 static rtx
-get_stored_val (store_info_t store_info, enum machine_mode read_mode,
+get_stored_val (store_info *store_info, machine_mode read_mode,
 		HOST_WIDE_INT read_begin, HOST_WIDE_INT read_end,
 		basic_block bb, bool require_cst)
 {
-  enum machine_mode store_mode = GET_MODE (store_info->mem);
+  machine_mode store_mode = GET_MODE (store_info->mem);
   int shift;
   int access_size; /* In bytes.  */
   rtx read_reg;
@@ -1771,27 +1735,27 @@
     {
       /* The store is a memset (addr, const_val, const_size).  */
       gcc_assert (CONST_INT_P (store_info->rhs));
-      store_mode = int_mode_for_mode (read_mode);
-      if (store_mode == BLKmode)
+      scalar_int_mode int_store_mode;
+      if (!int_mode_for_mode (read_mode).exists (&int_store_mode))
 	read_reg = NULL_RTX;
       else if (store_info->rhs == const0_rtx)
-	read_reg = extract_low_bits (read_mode, store_mode, const0_rtx);
-      else if (GET_MODE_BITSIZE (store_mode) > HOST_BITS_PER_WIDE_INT
+	read_reg = extract_low_bits (read_mode, int_store_mode, const0_rtx);
+      else if (GET_MODE_BITSIZE (int_store_mode) > HOST_BITS_PER_WIDE_INT
 	       || BITS_PER_UNIT >= HOST_BITS_PER_WIDE_INT)
 	read_reg = NULL_RTX;
       else
 	{
 	  unsigned HOST_WIDE_INT c
 	    = INTVAL (store_info->rhs)
-	      & (((HOST_WIDE_INT) 1 << BITS_PER_UNIT) - 1);
+	      & ((HOST_WIDE_INT_1 << BITS_PER_UNIT) - 1);
 	  int shift = BITS_PER_UNIT;
 	  while (shift < HOST_BITS_PER_WIDE_INT)
 	    {
 	      c |= (c << shift);
 	      shift <<= 1;
 	    }
-	  read_reg = GEN_INT (trunc_int_for_mode (c, store_mode));
-	  read_reg = extract_low_bits (read_mode, store_mode, read_reg);
+	  read_reg = gen_int_mode (c, int_store_mode);
+	  read_reg = extract_low_bits (read_mode, int_store_mode, read_reg);
 	}
     }
   else if (store_info->const_rhs
@@ -1839,13 +1803,14 @@
    went ok.  */
 
 static bool
-replace_read (store_info_t store_info, insn_info_t store_insn,
+replace_read (store_info *store_info, insn_info_t store_insn,
 	      read_info_t read_info, insn_info_t read_insn, rtx *loc,
 	      bitmap regs_live)
 {
-  enum machine_mode store_mode = GET_MODE (store_info->mem);
-  enum machine_mode read_mode = GET_MODE (read_info->mem);
-  rtx insns, this_insn, read_reg;
+  machine_mode store_mode = GET_MODE (store_info->mem);
+  machine_mode read_mode = GET_MODE (read_info->mem);
+  rtx_insn *insns, *this_insn;
+  rtx read_reg;
   basic_block bb;
 
   if (!dbg_cnt (dse))
@@ -1860,7 +1825,7 @@
      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),
@@ -1873,7 +1838,7 @@
   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;
     }
@@ -1890,7 +1855,7 @@
 	 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);
@@ -1898,7 +1863,7 @@
       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:");
@@ -1913,8 +1878,7 @@
 
   if (validate_change (read_insn->insn, loc, read_reg, 0))
     {
-      deferred_change_t deferred_change =
-	(deferred_change_t) pool_alloc (deferred_change_pool);
+      deferred_change *change = deferred_change_pool.allocate ();
 
       /* Insert this right before the store insn where it will be safe
 	 from later insns that might change it before the read.  */
@@ -1944,16 +1908,16 @@
 	 block we can put them back.  */
 
       *loc = read_info->mem;
-      deferred_change->next = deferred_change_list;
-      deferred_change_list = deferred_change;
-      deferred_change->loc = loc;
-      deferred_change->reg = read_reg;
+      change->next = deferred_change_list;
+      deferred_change_list = change;
+      change->loc = loc;
+      change->reg = read_reg;
 
       /* Get rid of the read_info, from the point of view of the
 	 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)
+      read_info_type_pool.remove (read_info);
+      if (dump_file && (dump_flags & TDF_DETAILS))
 	{
 	  fprintf (dump_file, " -- replaced the loaded MEM with ");
 	  print_simple_rtl (dump_file, read_reg);
@@ -1963,7 +1927,7 @@
     }
   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);
@@ -1973,50 +1937,43 @@
     }
 }
 
-/* A for_each_rtx callback in which DATA is the bb_info.  Check to see
-   if LOC is a mem and if it is look at the address and kill any
-   appropriate stores that may be active.  */
-
-static int
-check_mem_read_rtx (rtx *loc, void *data)
+/* Check the address of MEM *LOC and kill any appropriate stores that may
+   be active.  */
+
+static void
+check_mem_read_rtx (rtx *loc, bb_info_t bb_info)
 {
   rtx mem = *loc, mem_addr;
-  bb_info_t bb_info;
   insn_info_t insn_info;
   HOST_WIDE_INT offset = 0;
   HOST_WIDE_INT width = 0;
-  alias_set_type spill_alias_set = 0;
   cselib_val *base = NULL;
   int group_id;
   read_info_t read_info;
 
-  if (!mem || !MEM_P (mem))
-    return 0;
-
-  bb_info = (bb_info_t) data;
   insn_info = bb_info->last_insn;
 
   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;
-      return 0;
+      return;
     }
 
   /* If it is reading readonly mem, then there can be no conflict with
      another write. */
   if (MEM_READONLY_P (mem))
-    return 0;
-
-  if (!canon_address (mem, &spill_alias_set, &group_id, &offset, &base))
+    return;
+
+  if (!canon_address (mem, &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;
+      return;
     }
 
   if (GET_MODE (mem) == BLKmode)
@@ -2024,74 +1981,31 @@
   else
     width = GET_MODE_SIZE (GET_MODE (mem));
 
-  read_info = (read_info_t) pool_alloc (read_info_pool);
+  read_info = read_info_type_pool.allocate ();
   read_info->group_id = group_id;
   read_info->mem = mem;
-  read_info->alias_set = spill_alias_set;
   read_info->begin = offset;
   read_info->end = offset + width;
   read_info->next = insn_info->read_rec;
   insn_info->read_rec = read_info;
-  /* For alias_set != 0 canon_true_dependence should be never called.  */
-  if (spill_alias_set)
-    mem_addr = NULL_RTX;
+  if (group_id < 0)
+    mem_addr = base->val_rtx;
   else
     {
-      if (group_id < 0)
-	mem_addr = base->val_rtx;
-      else
-	{
-	  group_info_t group
-	    = VEC_index (group_info_t, rtx_group_vec, group_id);
-	  mem_addr = group->canon_base_addr;
-	}
-      if (offset)
-	mem_addr = plus_constant (mem_addr, offset);
+      group_info *group = rtx_group_vec[group_id];
+      mem_addr = group->canon_base_addr;
     }
-
-  /* We ignore the clobbers in store_info.  The is mildly aggressive,
-     but there really should not be a clobber followed by a read.  */
-
-  if (spill_alias_set)
-    {
-      insn_info_t i_ptr = active_local_stores;
-      insn_info_t last = NULL;
-
-      if (dump_file)
-	fprintf (dump_file, " processing spill load %d\n",
-		 (int) spill_alias_set);
-
-      while (i_ptr)
-	{
-	  store_info_t store_info = i_ptr->store_rec;
-
-	  /* Skip the clobbers.  */
-	  while (!store_info->is_set)
-	    store_info = store_info->next;
-
-	  if (store_info->alias_set == spill_alias_set)
-	    {
-	      if (dump_file)
-		dump_insn_info ("removing from active", i_ptr);
-
-	      if (last)
-		last->next_local_store = i_ptr->next_local_store;
-	      else
-		active_local_stores = i_ptr->next_local_store;
-	    }
-	  else
-	    last = i_ptr;
-	  i_ptr = i_ptr->next_local_store;
-	}
-    }
-  else if (group_id >= 0)
+  if (offset)
+    mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset);
+
+  if (group_id >= 0)
     {
       /* This is the restricted case where the base is a constant or
 	 the frame pointer and offset is a constant.  */
       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",
@@ -2104,7 +2018,7 @@
       while (i_ptr)
 	{
 	  bool remove = false;
-	  store_info_t store_info = i_ptr->store_rec;
+	  store_info *store_info = i_ptr->store_rec;
 
 	  /* Skip the clobbers.  */
 	  while (!store_info->is_set)
@@ -2118,7 +2032,7 @@
 	      = canon_true_dependence (store_info->mem,
 				       GET_MODE (store_info->mem),
 				       store_info->mem_addr,
-				       mem, mem_addr, rtx_varies_p);
+				       mem, mem_addr);
 
 	  else if (group_id == store_info->group_id)
 	    {
@@ -2129,7 +2043,7 @@
 		  = canon_true_dependence (store_info->mem,
 					   GET_MODE (store_info->mem),
 					   store_info->mem_addr,
-					   mem, mem_addr, rtx_varies_p);
+					   mem, mem_addr);
 
 	      /* If this read is just reading back something that we just
 		 stored, rewrite the read.  */
@@ -2143,7 +2057,7 @@
 						 width)
 		      && replace_read (store_info, i_ptr, read_info,
 				       insn_info, loc, bb_info->regs_live))
-		    return 0;
+		    return;
 
 		  /* The bases are the same, just see if the offsets
 		     overlap.  */
@@ -2160,9 +2074,10 @@
 
 	  if (remove)
 	    {
-	      if (dump_file)
+	      if (dump_file && (dump_flags & TDF_DETAILS))
 		dump_insn_info ("removing from active", i_ptr);
 
+	      active_local_stores_len--;
 	      if (last)
 		last->next_local_store = i_ptr->next_local_store;
 	      else
@@ -2177,7 +2092,7 @@
     {
       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);
@@ -2187,9 +2102,9 @@
       while (i_ptr)
 	{
 	  bool remove = false;
-	  store_info_t store_info = i_ptr->store_rec;
-
-	  if (dump_file)
+	  store_info *store_info = i_ptr->store_rec;
+
+	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    fprintf (dump_file, " processing cselib load against insn %d\n",
 		     INSN_UID (i_ptr->insn));
 
@@ -2209,19 +2124,19 @@
 					 offset - store_info->begin, width)
 	      && replace_read (store_info, i_ptr,  read_info, insn_info, loc,
 			       bb_info->regs_live))
-	    return 0;
-
-	  if (!store_info->alias_set)
-	    remove = canon_true_dependence (store_info->mem,
-					    GET_MODE (store_info->mem),
-					    store_info->mem_addr,
-					    mem, mem_addr, rtx_varies_p);
+	    return;
+
+	  remove = canon_true_dependence (store_info->mem,
+					  GET_MODE (store_info->mem),
+					  store_info->mem_addr,
+					  mem, mem_addr);
 
 	  if (remove)
 	    {
-	      if (dump_file)
+	      if (dump_file && (dump_flags & TDF_DETAILS))
 		dump_insn_info ("removing from active", i_ptr);
 
+	      active_local_stores_len--;
 	      if (last)
 		last->next_local_store = i_ptr->next_local_store;
 	      else
@@ -2232,17 +2147,22 @@
 	  i_ptr = i_ptr->next_local_store;
 	}
     }
-  return 0;
 }
 
-/* A for_each_rtx callback in which DATA points the INSN_INFO for
+/* A note_uses callback in which DATA points the INSN_INFO for
    as check_mem_read_rtx.  Nullify the pointer if i_m_r_m_r returns
    true for any part of *LOC.  */
 
 static void
 check_mem_read_use (rtx *loc, void *data)
 {
-  for_each_rtx (loc, check_mem_read_rtx, data);
+  subrtx_ptr_iterator::array_type array;
+  FOR_EACH_SUBRTX_PTR (iter, array, loc, NONCONST)
+    {
+      rtx *loc = *iter;
+      if (MEM_P (*loc))
+	check_mem_read_rtx (loc, (bb_info_t) data);
+    }
 }
 
 
@@ -2252,22 +2172,27 @@
 static bool
 get_call_args (rtx call_insn, tree fn, rtx *args, int nargs)
 {
-  CUMULATIVE_ARGS args_so_far;
+  CUMULATIVE_ARGS args_so_far_v;
+  cumulative_args_t args_so_far;
   tree arg;
   int idx;
 
-  INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (fn), NULL_RTX, 0, 3);
+  INIT_CUMULATIVE_ARGS (args_so_far_v, TREE_TYPE (fn), NULL_RTX, 0, 3);
+  args_so_far = pack_cumulative_args (&args_so_far_v);
 
   arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
   for (idx = 0;
        arg != void_list_node && idx < nargs;
        arg = TREE_CHAIN (arg), idx++)
     {
-      enum machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
+      scalar_int_mode mode;
       rtx reg, link, tmp;
-      reg = targetm.calls.function_arg (&args_so_far, mode, NULL_TREE, true);
-      if (!reg || !REG_P (reg) || GET_MODE (reg) != mode
-	  || GET_MODE_CLASS (mode) != MODE_INT)
+
+      if (!is_int_mode (TYPE_MODE (TREE_VALUE (arg)), &mode))
+	return false;
+
+      reg = targetm.calls.function_arg (args_so_far, mode, NULL_TREE, true);
+      if (!reg || !REG_P (reg) || GET_MODE (reg) != mode)
 	return false;
 
       for (link = CALL_INSN_FUNCTION_USAGE (call_insn);
@@ -2275,15 +2200,14 @@
 	   link = XEXP (link, 1))
 	if (GET_CODE (XEXP (link, 0)) == USE)
 	  {
+	    scalar_int_mode arg_mode;
 	    args[idx] = XEXP (XEXP (link, 0), 0);
 	    if (REG_P (args[idx])
 		&& REGNO (args[idx]) == REGNO (reg)
 		&& (GET_MODE (args[idx]) == mode
-		    || (GET_MODE_CLASS (GET_MODE (args[idx])) == MODE_INT
-			&& (GET_MODE_SIZE (GET_MODE (args[idx]))
-			    <= UNITS_PER_WORD)
-			&& (GET_MODE_SIZE (GET_MODE (args[idx]))
-			    > GET_MODE_SIZE (mode)))))
+		    || (is_int_mode (GET_MODE (args[idx]), &arg_mode)
+			&& (GET_MODE_SIZE (arg_mode) <= UNITS_PER_WORD)
+			&& (GET_MODE_SIZE (arg_mode) > GET_MODE_SIZE (mode)))))
 	      break;
 	  }
       if (!link)
@@ -2294,32 +2218,43 @@
 	{
 	  if (!tmp || !CONST_INT_P (tmp))
 	    return false;
-	  tmp = GEN_INT (trunc_int_for_mode (INTVAL (tmp), mode));
+	  tmp = gen_int_mode (INTVAL (tmp), mode);
 	}
       if (tmp)
 	args[idx] = tmp;
 
-      targetm.calls.function_arg_advance (&args_so_far, mode, NULL_TREE, true);
+      targetm.calls.function_arg_advance (args_so_far, mode, NULL_TREE, true);
     }
   if (arg != void_list_node || idx != nargs)
     return false;
   return true;
 }
 
+/* Return a bitmap of the fixed registers contained in IN.  */
+
+static bitmap
+copy_fixed_regs (const_bitmap in)
+{
+  bitmap ret;
+
+  ret = ALLOC_REG_SET (NULL);
+  bitmap_and (ret, in, fixed_reg_set_regset);
+  return ret;
+}
 
 /* Apply record_store to all candidate stores in INSN.  Mark INSN
    if some part of it is not a candidate store and assigns to a
    non-register target.  */
 
 static void
-scan_insn (bb_info_t bb_info, rtx insn)
+scan_insn (bb_info_t bb_info, rtx_insn *insn)
 {
   rtx body;
-  insn_info_t insn_info = (insn_info_t) pool_alloc (insn_info_pool);
+  insn_info_type *insn_info = insn_info_type_pool.allocate ();
   int mems_found = 0;
-  memset (insn_info, 0, sizeof (struct insn_info));
-
-  if (dump_file)
+  memset (insn_info, 0, sizeof (struct insn_info_type));
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "\n**scanning insn=%d\n",
 	     INSN_UID (insn));
 
@@ -2333,23 +2268,13 @@
       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);
 
   if (CALL_P (insn))
     {
       bool const_call;
+      rtx call, sym;
       tree memset_call = NULL_TREE;
 
       insn_info->cannot_delete = true;
@@ -2359,41 +2284,33 @@
 	 been pushed onto the stack.
 	 memset and bzero don't read memory either.  */
       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 symbol = XEXP (XEXP (call, 0), 0);
-	      if (SYMBOL_REF_DECL (symbol)
-		  && TREE_CODE (SYMBOL_REF_DECL (symbol)) == FUNCTION_DECL)
-		{
-		  if ((DECL_BUILT_IN_CLASS (SYMBOL_REF_DECL (symbol))
-		       == BUILT_IN_NORMAL
-		       && (DECL_FUNCTION_CODE (SYMBOL_REF_DECL (symbol))
-			   == BUILT_IN_MEMSET))
-		      || SYMBOL_REF_DECL (symbol) == block_clear_fn)
-		    memset_call = SYMBOL_REF_DECL (symbol);
-		}
-	    }
-	}
+      if (!const_call
+	  && (call = get_call_rtx_from (insn))
+	  && (sym = XEXP (XEXP (call, 0), 0))
+	  && GET_CODE (sym) == SYMBOL_REF
+	  && SYMBOL_REF_DECL (sym)
+	  && TREE_CODE (SYMBOL_REF_DECL (sym)) == FUNCTION_DECL
+	  && DECL_BUILT_IN_CLASS (SYMBOL_REF_DECL (sym)) == BUILT_IN_NORMAL
+	  && DECL_FUNCTION_CODE (SYMBOL_REF_DECL (sym)) == BUILT_IN_MEMSET)
+	memset_call = SYMBOL_REF_DECL (sym);
+
       if (const_call || memset_call)
 	{
 	  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));
 
 	  /* See the head comment of the frame_read field.  */
-	  if (reload_completed)
+	  if (reload_completed
+	      /* Tail calls are storing their arguments using
+		 arg pointer.  If it is a frame pointer on the target,
+		 even before reload we need to kill frame pointer based
+		 stores.  */
+	      || (SIBLING_CALL_P (insn)
+		  && HARD_FRAME_POINTER_IS_ARG_POINTER))
 	    insn_info->frame_read = true;
 
 	  /* Loop over the active stores and remove those which are
@@ -2409,23 +2326,23 @@
 	      /* If the frame is read, the frame related stores are killed.  */
 	      else if (insn_info->frame_read)
 		{
-		  store_info_t store_info = i_ptr->store_rec;
+		  store_info *store_info = i_ptr->store_rec;
 
 		  /* Skip the clobbers.  */
 		  while (!store_info->is_set)
 		    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--;
 		  if (last)
 		    last->next_local_store = i_ptr->next_local_store;
 		  else
@@ -2446,23 +2363,38 @@
 		  && INTVAL (args[2]) > 0)
 		{
 		  rtx mem = gen_rtx_MEM (BLKmode, args[0]);
-		  set_mem_size (mem, args[2]);
-		  body = gen_rtx_SET (VOIDmode, mem, args[1]);
+		  set_mem_size (mem, INTVAL (args[2]));
+		  body = gen_rtx_SET (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)
 		    {
+		      if (active_local_stores_len++
+			  >= PARAM_VALUE (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES))
+			{
+			  active_local_stores_len = 1;
+			  active_local_stores = NULL;
+			}
+		      insn_info->fixed_regs_live
+			= copy_fixed_regs (bb_info->regs_live);
 		      insn_info->next_local_store = active_local_stores;
 		      active_local_stores = insn_info;
 		    }
 		}
+	      else
+		clear_rhs_from_active_local_stores ();
 	    }
 	}
-
+      else if (SIBLING_CALL_P (insn) && reload_completed)
+	/* Arguments for a sibling call that are pushed to memory are passed
+	   using the incoming argument pointer of the current function.  After
+	   reload that might be (and likely is) frame pointer based.  */
+	add_wild_read (bb_info);
       else
-	/* Every other call, including pure functions, may read memory.  */
-	add_wild_read (bb_info);
+	/* Every other call, including pure functions, may read any memory
+           that is not relative to the frame.  */
+        add_non_frame_wild_read (bb_info);
 
       return;
     }
@@ -2471,7 +2403,7 @@
      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;
@@ -2486,7 +2418,7 @@
   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");
 
@@ -2496,6 +2428,13 @@
      it as cannot delete.  This simplifies the processing later.  */
   if (mems_found == 1)
     {
+      if (active_local_stores_len++
+	  >= PARAM_VALUE (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES))
+	{
+	  active_local_stores_len = 1;
+	  active_local_stores = NULL;
+	}
+      insn_info->fixed_regs_live = copy_fixed_regs (bb_info->regs_live);
       insn_info->next_local_store = active_local_stores;
       active_local_stores = insn_info;
     }
@@ -2516,7 +2455,7 @@
 
   while (insn_info)
     {
-      store_info_t store_info = insn_info->store_rec;
+      store_info *store_info = insn_info->store_rec;
       bool del = false;
 
       /* If ANY of the store_infos match the cselib group that is
@@ -2534,6 +2473,7 @@
 
       if (del)
 	{
+	  active_local_stores_len--;
 	  if (last)
 	    last->next_local_store = insn_info->next_local_store;
 	  else
@@ -2554,19 +2494,19 @@
 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);
-
-      memset (bb_info, 0, sizeof (struct bb_info));
+      bb_info_t bb_info = dse_bb_info_type_pool.allocate ();
+
+      memset (bb_info, 0, sizeof (dse_bb_info_type));
       bitmap_set_bit (all_blocks, bb->index);
       bb_info->regs_live = regs_live;
 
@@ -2578,12 +2518,10 @@
 
       if (bb->index >= NUM_FIXED_BLOCKS)
 	{
-	  rtx insn;
-
-	  cse_store_info_pool
-	    = create_alloc_pool ("cse_store_info_pool",
-				 sizeof (struct store_info), 100);
+	  rtx_insn *insn;
+
 	  active_local_stores = NULL;
+	  active_local_stores_len = 0;
 	  cselib_clear_table ();
 
 	  /* Scan the insns.  */
@@ -2608,27 +2546,23 @@
 	  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;
 	      while (i_ptr)
 		{
-		  store_info_t store_info = i_ptr->store_rec;
+		  store_info *store_info = i_ptr->store_rec;
 
 		  /* Skip the clobbers.  */
 		  while (!store_info->is_set)
 		    store_info = store_info->next;
-		  if (store_info->alias_set && !i_ptr->cannot_delete)
-		    delete_dead_store_insn (i_ptr);
-		  else
-		    if (store_info->group_id >= 0)
-		      {
-			group_info_t group
-			  = VEC_index (group_info_t, rtx_group_vec, store_info->group_id);
-			if (group->frame_related && !i_ptr->cannot_delete)
-			  delete_dead_store_insn (i_ptr);
-		      }
+		  if (store_info->group_id >= 0)
+		    {
+		      group_info *group = rtx_group_vec[store_info->group_id];
+		      if (group->frame_related && !i_ptr->cannot_delete)
+			delete_dead_store_insn (i_ptr);
+		    }
 
 		  i_ptr = i_ptr->next_local_store;
 		}
@@ -2638,12 +2572,12 @@
 	     replace_read.  Cselib is finished with this block.  */
 	  while (deferred_change_list)
 	    {
-	      deferred_change_t next = deferred_change_list->next;
+	      deferred_change *next = deferred_change_list->next;
 
 	      /* There is no reason to validate this change.  That was
 		 done earlier.  */
 	      *deferred_change_list->loc = deferred_change_list->reg;
-	      pool_free (deferred_change_pool, deferred_change_list);
+	      deferred_change_pool.remove (deferred_change_list);
 	      deferred_change_list = next;
 	    }
 
@@ -2655,7 +2589,7 @@
 	    {
 	      if (ptr->contains_cselib_groups)
 		{
-		  store_info_t s_info = ptr->store_rec;
+		  store_info *s_info = ptr->store_rec;
 		  while (s_info && !s_info->is_set)
 		    s_info = s_info->next;
 		  if (s_info
@@ -2663,7 +2597,7 @@
 		      && 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 "
@@ -2672,13 +2606,11 @@
 				 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
 		{
-		  store_info_t s_info;
+		  store_info *s_info;
 
 		  /* Free at least positions_needed bitmaps.  */
 		  for (s_info = ptr->store_rec; s_info; s_info = s_info->next)
@@ -2691,14 +2623,14 @@
 	      ptr = ptr->prev_insn;
 	    }
 
-	  free_alloc_pool (cse_store_info_pool);
+	  cse_store_info_pool.release ();
 	}
       bb_info->regs_live = NULL;
     }
 
   BITMAP_FREE (regs_live);
   cselib_finish ();
-  htab_empty (rtx_group_table);
+  rtx_group_table->empty ();
 }
 
 
@@ -2714,9 +2646,9 @@
 dse_step2_init (void)
 {
   unsigned int i;
-  group_info_t group;
-
-  FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
+  group_info *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
@@ -2736,16 +2668,18 @@
 	{
 	  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),
@@ -2757,38 +2691,38 @@
 }
 
 
-/* Init the offset tables for the normal case.  */
+/* Init the offset tables.  */
 
 static bool
-dse_step2_nospill (void)
+dse_step2 (void)
 {
   unsigned int i;
-  group_info_t group;
+  group_info *group;
   /* 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;
 
-      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)
 	{
 	  bitmap_set_bit (group->group_kill, current_position);
+          if (bitmap_bit_p (group->escaped_n, j))
+	    bitmap_set_bit (kill_on_calls, current_position);
 	  group->offset_map_n[j] = current_position++;
 	  group->process_globally = true;
 	}
       EXECUTE_IF_SET_IN_BITMAP (group->store2_p, 0, j, bi)
 	{
 	  bitmap_set_bit (group->group_kill, current_position);
+          if (bitmap_bit_p (group->escaped_p, j))
+	    bitmap_set_bit (kill_on_calls, current_position);
 	  group->offset_map_p[j] = current_position++;
 	  group->process_globally = true;
 	}
@@ -2797,47 +2731,6 @@
 }
 
 
-/* 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;
-}
-
-
 
 /*----------------------------------------------------------------------------
   Third step.
@@ -2846,90 +2739,11 @@
 ----------------------------------------------------------------------------*/
 
 
-/* Note that this is NOT a general purpose function.  Any mem that has
-   an alias set registered here expected to be COMPLETELY unaliased:
-   i.e it's addresses are not and need not be examined.
-
-   It is known that all references to this address will have this
-   alias set and there are NO other references to this address in the
-   function.
-
-   Currently the only place that is known to be clean enough to use
-   this interface is the code that assigns the spill locations.
-
-   All of the mems that have alias_sets registered are subjected to a
-   very powerful form of dse where function calls, volatile reads and
-   writes, and reads from random location are not taken into account.
-
-   It is also assumed that these locations go dead when the function
-   returns.  This assumption could be relaxed if there were found to
-   be places that this assumption was not correct.
-
-   The MODE is passed in and saved.  The mode of each load or store to
-   a mem with ALIAS_SET is checked against MEM.  If the size of that
-   load or store is different from MODE, processing is halted on this
-   alias set.  For the vast majority of aliases sets, all of the loads
-   and stores will use the same mode.  But vectors are treated
-   differently: the alias set is established for the entire vector,
-   but reload will insert loads and stores for individual elements and
-   we do not necessarily have the information to track those separate
-   elements.  So when we see a mode mismatch, we just bail.  */
-
-
-void
-dse_record_singleton_alias_set (alias_set_type alias_set,
-				enum machine_mode mode)
-{
-  struct clear_alias_mode_holder tmp_holder;
-  struct clear_alias_mode_holder *entry;
-  void **slot;
-
-  /* If we are not going to run dse, we need to return now or there
-     will be problems with allocating the bitmaps.  */
-  if ((!gate_dse()) || !alias_set)
-    return;
-
-  if (!clear_alias_sets)
-    {
-      clear_alias_sets = BITMAP_ALLOC (NULL);
-      disqualified_clear_alias_sets = BITMAP_ALLOC (NULL);
-      clear_alias_mode_table = htab_create (11, clear_alias_mode_hash,
-					    clear_alias_mode_eq, NULL);
-      clear_alias_mode_pool = create_alloc_pool ("clear_alias_mode_pool",
-						 sizeof (struct clear_alias_mode_holder), 100);
-    }
-
-  bitmap_set_bit (clear_alias_sets, alias_set);
-
-  tmp_holder.alias_set = alias_set;
-
-  slot = htab_find_slot (clear_alias_mode_table, &tmp_holder, INSERT);
-  gcc_assert (*slot == NULL);
-
-  *slot = entry =
-    (struct clear_alias_mode_holder *) pool_alloc (clear_alias_mode_pool);
-  entry->alias_set = alias_set;
-  entry->mode = mode;
-}
-
-
-/* Remove ALIAS_SET from the sets of stack slots being considered.  */
-
-void
-dse_invalidate_singleton_alias_set (alias_set_type alias_set)
-{
-  if ((!gate_dse()) || !alias_set)
-    return;
-
-  bitmap_clear_bit (clear_alias_sets, alias_set);
-}
-
-
 /* Look up the bitmap index for OFFSET in GROUP_INFO.  If it is not
    there, return 0.  */
 
 static int
-get_bitmap_index (group_info_t group_info, HOST_WIDE_INT offset)
+get_bitmap_index (group_info *group_info, HOST_WIDE_INT offset)
 {
   if (offset < 0)
     {
@@ -2951,13 +2765,13 @@
    may be NULL. */
 
 static void
-scan_stores_nospill (store_info_t store_info, bitmap gen, bitmap kill)
+scan_stores (store_info *store_info, bitmap gen, bitmap kill)
 {
   while (store_info)
     {
       HOST_WIDE_INT i;
-      group_info_t group_info
-	= VEC_index (group_info_t, rtx_group_vec, store_info->group_id);
+      group_info *group_info
+	= rtx_group_vec[store_info->group_id];
       if (group_info->process_globally)
 	for (i = store_info->begin; i < store_info->end; i++)
 	  {
@@ -2974,44 +2788,20 @@
 }
 
 
-/* Process the STORE_INFOs into the bitmaps into GEN and KILL.  KILL
-   may be NULL. */
-
-static void
-scan_stores_spill (store_info_t store_info, bitmap gen, bitmap kill)
-{
-  while (store_info)
-    {
-      if (store_info->alias_set)
-	{
-	  int index = get_bitmap_index (clear_alias_group,
-					store_info->alias_set);
-	  if (index != 0)
-	    {
-	      bitmap_set_bit (gen, index);
-	      if (kill)
-		bitmap_clear_bit (kill, index);
-	    }
-	}
-      store_info = store_info->next;
-    }
-}
-
-
 /* Process the READ_INFOs into the bitmaps into GEN and KILL.  KILL
    may be NULL.  */
 
 static void
-scan_reads_nospill (insn_info_t insn_info, bitmap gen, bitmap kill)
+scan_reads (insn_info_t insn_info, bitmap gen, bitmap kill)
 {
   read_info_t read_info = insn_info->read_rec;
   int i;
-  group_info_t group;
+  group_info *group;
 
   /* 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)
@@ -3019,10 +2809,24 @@
 	    bitmap_and_compl_into (gen, group->group_kill);
 	  }
     }
-
+  if (insn_info->non_frame_wild_read)
+    {
+      /* Kill all non-frame related stores.  Kill all stores of variables that
+         escape.  */
+      if (kill)
+        bitmap_ior_into (kill, kill_on_calls);
+      bitmap_and_compl_into (gen, kill_on_calls);
+      FOR_EACH_VEC_ELT (rtx_group_vec, i, group)
+	if (group->process_globally && !group->frame_related)
+	  {
+	    if (kill)
+	      bitmap_ior_into (kill, group->group_kill);
+	    bitmap_and_compl_into (gen, group->group_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)
 	    {
@@ -3064,8 +2868,7 @@
 		      && canon_true_dependence (group->base_mem,
 						GET_MODE (group->base_mem),
 						group->canon_base_addr,
-						read_info->mem, NULL_RTX,
-						rtx_varies_p))
+						read_info->mem, NULL_RTX))
 		    {
 		      if (kill)
 			bitmap_ior_into (kill, group->group_kill);
@@ -3079,30 +2882,6 @@
     }
 }
 
-/* Process the READ_INFOs into the bitmaps into GEN and KILL.  KILL
-   may be NULL.  */
-
-static void
-scan_reads_spill (read_info_t read_info, bitmap gen, bitmap kill)
-{
-  while (read_info)
-    {
-      if (read_info->alias_set)
-	{
-	  int index = get_bitmap_index (clear_alias_group,
-					read_info->alias_set);
-	  if (index != 0)
-	    {
-	      if (kill)
-		bitmap_set_bit (kill, index);
-	      bitmap_clear_bit (gen, index);
-	    }
-	}
-
-      read_info = read_info->next;
-    }
-}
-
 
 /* Return the insn in BB_INFO before the first wild read or if there
    are no wild reads in the block, return the last insn.  */
@@ -3141,16 +2920,12 @@
    anything that happens is hidden by the wild read.  */
 
 static void
-dse_step3_scan (bool for_spills, basic_block bb)
+dse_step3_scan (basic_block bb)
 {
   bb_info_t bb_info = bb_table[bb->index];
   insn_info_t insn_info;
 
-  if (for_spills)
-    /* There are no wild reads in the spill case.  */
-    insn_info = bb_info->last_insn;
-  else
-    insn_info = find_insn_before_first_wild_read (bb_info);
+  insn_info = find_insn_before_first_wild_read (bb_info);
 
   /* In the spill case or in the no_spill case if there is no wild
      read in the block, we will need a kill set.  */
@@ -3159,7 +2934,7 @@
       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)
@@ -3171,17 +2946,8 @@
 	 this phase.  */
       if (insn_info->insn && INSN_P (insn_info->insn))
 	{
-	  /* Process the read(s) last.  */
-	  if (for_spills)
-	    {
-	      scan_stores_spill (insn_info->store_rec, bb_info->gen, bb_info->kill);
-	      scan_reads_spill (insn_info->read_rec, bb_info->gen, bb_info->kill);
-	    }
-	  else
-	    {
-	      scan_stores_nospill (insn_info->store_rec, bb_info->gen, bb_info->kill);
-	      scan_reads_nospill (insn_info, bb_info->gen, bb_info->kill);
-	    }
+	  scan_stores (insn_info->store_rec, bb_info->gen, bb_info->kill);
+	  scan_reads (insn_info, bb_info->gen, bb_info->kill);
 	}
 
       insn_info = insn_info->prev_insn;
@@ -3201,9 +2967,9 @@
   if (stores_off_frame_dead_at_return)
     {
       unsigned int i;
-      group_info_t group;
-
-      FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
+      group_info *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);
@@ -3223,9 +2989,9 @@
   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);
@@ -3236,30 +3002,30 @@
 /* Build the transfer functions for the function.  */
 
 static void
-dse_step3 (bool for_spills)
+dse_step3 ()
 {
   basic_block bb;
-  sbitmap unreachable_blocks = sbitmap_alloc (last_basic_block);
   sbitmap_iterator sbi;
   bitmap all_ones = NULL;
   unsigned int i;
 
-  sbitmap_ones (unreachable_blocks);
-
-  FOR_ALL_BB (bb)
+  auto_sbitmap unreachable_blocks (last_basic_block_for_fn (cfun));
+  bitmap_ones (unreachable_blocks);
+
+  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)
 	;
       else if (bb->index == EXIT_BLOCK)
 	dse_step3_exit_block_scan (bb_info);
       else
-	dse_step3_scan (for_spills, bb);
+	dse_step3_scan (bb);
       if (EDGE_COUNT (bb->succs) == 0)
 	mark_reachable_blocks (unreachable_blocks, bb);
 
@@ -3274,7 +3040,7 @@
   /* 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))
 	{
@@ -3282,15 +3048,15 @@
 	  if (!all_ones)
 	    {
 	      unsigned int j;
-	      group_info_t group;
-
-	      all_ones = BITMAP_ALLOC (NULL);
-	      FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, j, group)
+	      group_info *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);
 	    }
 	}
@@ -3298,7 +3064,6 @@
 
   if (all_ones)
     BITMAP_FREE (all_ones);
-  sbitmap_free (unreachable_blocks);
 }
 
 
@@ -3326,7 +3091,7 @@
 
   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);
     }
 }
@@ -3347,7 +3112,7 @@
 	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);
 	}
     }
@@ -3386,7 +3151,7 @@
 					 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;
@@ -3404,7 +3169,7 @@
 	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;
 	}
@@ -3420,12 +3185,12 @@
 		      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];
 
@@ -3460,10 +3225,10 @@
 
 
 static void
-dse_step5_nospill (void)
+dse_step5 (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;
@@ -3486,7 +3251,7 @@
 	      && (!insn_info->cannot_delete)
 	      && (!bitmap_empty_p (v)))
 	    {
-	      store_info_t store_info = insn_info->store_rec;
+	      store_info *store_info = insn_info->store_rec;
 
 	      /* Try to delete the current insn.  */
 	      deleted = true;
@@ -3495,34 +3260,28 @@
 	      while (!store_info->is_set)
 		store_info = store_info->next;
 
-	      if (store_info->alias_set)
-		deleted = false;
-	      else
+	      HOST_WIDE_INT i;
+	      group_info *group_info = rtx_group_vec[store_info->group_id];
+
+	      for (i = store_info->begin; i < store_info->end; i++)
 		{
-		  HOST_WIDE_INT i;
-		  group_info_t group_info
-		    = VEC_index (group_info_t, 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 && (dump_flags & TDF_DETAILS))
+		    fprintf (dump_file, "i = %d, index = %d\n", (int)i, index);
+		  if (index == 0 || !bitmap_bit_p (v, index))
 		    {
-		      int index = get_bitmap_index (group_info, i);
-
-		      if (dump_file)
-			fprintf (dump_file, "i = %d, index = %d\n", (int)i, index);
-		      if (index == 0 || !bitmap_bit_p (v, index))
-			{
-			  if (dump_file)
-			    fprintf (dump_file, "failing at i = %d\n", (int)i);
-			  deleted = false;
-			  break;
-			}
+		      if (dump_file && (dump_flags & TDF_DETAILS))
+			fprintf (dump_file, "failing at i = %d\n", (int)i);
+		      deleted = false;
+		      break;
 		    }
 		}
 	      if (deleted)
 		{
-		  if (dbg_cnt (dse))
+		  if (dbg_cnt (dse)
+		      && check_for_inc_dec_1 (insn_info))
 		    {
-		      check_for_inc_dec (insn_info->insn);
 		      delete_insn (insn_info->insn);
 		      insn_info->insn = NULL;
 		      globally_deleted++;
@@ -3536,18 +3295,28 @@
 	      && INSN_P (insn_info->insn)
 	      && (!deleted))
 	    {
-	      scan_stores_nospill (insn_info->store_rec, v, NULL);
+	      scan_stores (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);
 		}
-	      else if (insn_info->read_rec)
+	      else if (insn_info->read_rec
+		       || insn_info->non_frame_wild_read
+		       || insn_info->frame_read)
 		{
-		  if (dump_file)
-		    fprintf (dump_file, "regular read\n");
-		  scan_reads_nospill (insn_info, v, NULL);
+		  if (dump_file && (dump_flags & TDF_DETAILS))
+		    {
+		      if (!insn_info->non_frame_wild_read
+			  && !insn_info->frame_read)
+			fprintf (dump_file, "regular read\n");
+		      if (insn_info->non_frame_wild_read)
+			fprintf (dump_file, "non-frame wild read\n");
+		      if (insn_info->frame_read)
+			fprintf (dump_file, "frame read\n");
+		    }
+		  scan_reads (insn_info, v, NULL);
 		}
 	    }
 
@@ -3557,72 +3326,6 @@
 }
 
 
-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))
-		{
-		  if (dump_file)
-		    fprintf (dump_file, "Spill deleting insn %d\n",
-			     INSN_UID (insn_info->insn));
-		  check_for_inc_dec (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;
-	}
-    }
-}
-
-
 
 /*----------------------------------------------------------------------------
    Sixth step.
@@ -3636,7 +3339,7 @@
 {
   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;
@@ -3649,7 +3352,7 @@
 	      && INSN_P (insn_info->insn)
 	      && !insn_info->cannot_delete)
 	    {
-	      store_info_t s_info = insn_info->store_rec;
+	      store_info *s_info = insn_info->store_rec;
 
 	      while (s_info && !s_info->is_set)
 		s_info = s_info->next;
@@ -3658,8 +3361,8 @@
 		  && s_info->redundant_reason->insn
 		  && INSN_P (s_info->redundant_reason->insn))
 		{
-		  rtx rinsn = s_info->redundant_reason->insn;
-		  if (dump_file)
+		  rtx_insn *rinsn = s_info->redundant_reason->insn;
+		  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 "
@@ -3681,57 +3384,25 @@
 ----------------------------------------------------------------------------*/
 
 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->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);
+  delete rtx_group_table;
+  rtx_group_table = NULL;
+  rtx_group_vec.release ();
   BITMAP_FREE (all_blocks);
   BITMAP_FREE (scratch);
 
-  free_alloc_pool (rtx_store_info_pool);
-  free_alloc_pool (read_info_pool);
-  free_alloc_pool (insn_info_pool);
-  free_alloc_pool (bb_info_pool);
-  free_alloc_pool (rtx_group_info_pool);
-  free_alloc_pool (deferred_change_pool);
+  rtx_store_info_pool.release ();
+  read_info_type_pool.release ();
+  insn_info_type_pool.release ();
+  dse_bb_info_type_pool.release ();
+  group_info_pool.release ();
+  deferred_change_pool.release ();
 }
 
 
@@ -3744,8 +3415,6 @@
 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
@@ -3756,105 +3425,110 @@
   dse_step0 ();
   dse_step1 ();
   dse_step2_init ();
-  if (dse_step2_nospill ())
+  if (dse_step2 ())
     {
       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_step3 ();
       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_step5 ();
     }
 
   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",
-	     locally_deleted, globally_deleted, spill_deleted);
+    fprintf (dump_file, "dse: local deletions = %d, global deletions = %d\n",
+	     locally_deleted, globally_deleted);
+
+  /* DSE can eliminate potentially-trapping MEMs.
+     Remove any EH edges associated with them.  */
+  if ((locally_deleted || globally_deleted)
+      && cfun->can_throw_non_call_exceptions
+      && purge_all_dead_edges ())
+    cleanup_cfg (0);
+
   return 0;
 }
 
-static bool
-gate_dse (void)
+namespace {
+
+const pass_data pass_data_rtl_dse1 =
 {
-  return gate_dse1 () || gate_dse2 ();
-}
-
-static bool
-gate_dse1 (void)
+  RTL_PASS, /* type */
+  "dse1", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_DSE1, /* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_df_finish, /* todo_flags_finish */
+};
+
+class pass_rtl_dse1 : public rtl_opt_pass
 {
-  return optimize > 0 && flag_dse
-    && dbg_cnt (dse1);
-}
-
-static bool
-gate_dse2 (void)
-{
-  return optimize > 0 && flag_dse
-    && dbg_cnt (dse2);
-}
-
-struct rtl_opt_pass pass_rtl_dse1 =
+public:
+  pass_rtl_dse1 (gcc::context *ctxt)
+    : rtl_opt_pass (pass_data_rtl_dse1, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *)
+    {
+      return optimize > 0 && flag_dse && dbg_cnt (dse1);
+    }
+
+  virtual unsigned int execute (function *) { return rest_of_handle_dse (); }
+
+}; // class pass_rtl_dse1
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_rtl_dse1 (gcc::context *ctxt)
 {
- {
-  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_dump_func |
-  TODO_df_finish | TODO_verify_rtl_sharing |
-  TODO_ggc_collect                      /* todo_flags_finish */
- }
+  return new pass_rtl_dse1 (ctxt);
+}
+
+namespace {
+
+const pass_data pass_data_rtl_dse2 =
+{
+  RTL_PASS, /* type */
+  "dse2", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_DSE2, /* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_df_finish, /* todo_flags_finish */
 };
 
-struct rtl_opt_pass pass_rtl_dse2 =
+class pass_rtl_dse2 : public rtl_opt_pass
 {
- {
-  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_dump_func |
-  TODO_df_finish | TODO_verify_rtl_sharing |
-  TODO_ggc_collect                      /* todo_flags_finish */
- }
-};
+public:
+  pass_rtl_dse2 (gcc::context *ctxt)
+    : rtl_opt_pass (pass_data_rtl_dse2, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *)
+    {
+      return optimize > 0 && flag_dse && dbg_cnt (dse2);
+    }
+
+  virtual unsigned int execute (function *) { 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);
+}