diff gcc/store-motion.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/store-motion.c	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/store-motion.c	Fri Oct 27 22:46:09 2017 +0900
@@ -1,6 +1,5 @@
 /* Store motion via Lazy Code Motion on the reverse CFG.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 1997-2017 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,30 +20,22 @@
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "diagnostic-core.h"
-#include "toplev.h"
-
+#include "backend.h"
 #include "rtl.h"
 #include "tree.h"
-#include "tm_p.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "flags.h"
-#include "insn-config.h"
-#include "recog.h"
-#include "basic-block.h"
-#include "output.h"
-#include "function.h"
+#include "predict.h"
+#include "df.h"
+#include "toplev.h"
+
+#include "cfgrtl.h"
+#include "cfganal.h"
+#include "lcm.h"
+#include "cfgcleanup.h"
 #include "expr.h"
-#include "except.h"
-#include "ggc.h"
-#include "intl.h"
-#include "timevar.h"
 #include "tree-pass.h"
-#include "hashtab.h"
-#include "df.h"
 #include "dbgcnt.h"
+#include "rtl-iter.h"
+#include "print-rtl.h"
 
 /* This pass implements downward store motion.
    As of May 1, 2009, the pass is not enabled by default on any target,
@@ -55,8 +46,7 @@
      a compile time hog that needs a rewrite (maybe cache st_exprs to
      invalidate REG_EQUAL/REG_EQUIV notes for?).
    - pattern_regs in st_expr should be a regset (on its own obstack).
-   - antic_stores and avail_stores should be VECs instead of lists.
-   - store_motion_mems should be a VEC instead of a list.
+   - store_motion_mems should be a vec instead of a list.
    - there should be an alloc pool for struct st_expr objects.
    - investigate whether it is helpful to make the address of an st_expr
      a cselib VALUE.
@@ -73,11 +63,11 @@
   /* Pattern of this mem.  */
   rtx pattern;
   /* List of registers mentioned by the mem.  */
-  rtx pattern_regs;
+  vec<rtx> pattern_regs;
   /* INSN list of stores that are locally anticipatable.  */
-  rtx antic_stores;
+  vec<rtx_insn *> antic_stores;
   /* INSN list of stores that are locally available.  */
-  rtx avail_stores;
+  vec<rtx_insn *> avail_stores;
   /* Next in the list.  */
   struct st_expr * next;
   /* Store ID in the dataflow bitmaps.  */
@@ -93,9 +83,6 @@
 /* Head of the list of load/store memory refs.  */
 static struct st_expr * store_motion_mems = NULL;
 
-/* Hashtable for the load/store memory refs.  */
-static htab_t store_motion_mems_table = NULL;
-
 /* These bitmaps will hold the local dataflow properties per basic block.  */
 static sbitmap *st_kill, *st_avloc, *st_antloc, *st_transp;
 
@@ -111,22 +98,30 @@
 /* Contains the edge_list returned by pre_edge_lcm.  */
 static struct edge_list *edge_list;
 
-static hashval_t
-pre_st_expr_hash (const void *p)
+/* Hashtable helpers.  */
+
+struct st_expr_hasher : nofree_ptr_hash <st_expr>
+{
+  static inline hashval_t hash (const st_expr *);
+  static inline bool equal (const st_expr *, const st_expr *);
+};
+
+inline hashval_t
+st_expr_hasher::hash (const st_expr *x)
 {
   int do_not_record_p = 0;
-  const struct st_expr *const x = (const struct st_expr *) p;
   return hash_rtx (x->pattern, GET_MODE (x->pattern), &do_not_record_p, NULL, false);
 }
 
-static int
-pre_st_expr_eq (const void *p1, const void *p2)
+inline bool
+st_expr_hasher::equal (const st_expr *ptr1, const st_expr *ptr2)
 {
-  const struct st_expr *const ptr1 = (const struct st_expr *) p1,
-    *const ptr2 = (const struct st_expr *) p2;
   return exp_equiv_p (ptr1->pattern, ptr2->pattern, 0, true);
 }
 
+/* Hashtable for the load/store memory refs.  */
+static hash_table<st_expr_hasher> *store_motion_mems_table;
+
 /* This will search the st_expr list for a matching expression. If it
    doesn't find one, we create one and initialize it.  */
 
@@ -136,24 +131,24 @@
   int do_not_record_p = 0;
   struct st_expr * ptr;
   unsigned int hash;
-  void **slot;
+  st_expr **slot;
   struct st_expr e;
 
   hash = hash_rtx (x, GET_MODE (x), &do_not_record_p,
 		   NULL,  /*have_reg_qty=*/false);
 
   e.pattern = x;
-  slot = htab_find_slot_with_hash (store_motion_mems_table, &e, hash, INSERT);
+  slot = store_motion_mems_table->find_slot_with_hash (&e, hash, INSERT);
   if (*slot)
-    return (struct st_expr *)*slot;
+    return *slot;
 
   ptr = XNEW (struct st_expr);
 
   ptr->next         = store_motion_mems;
   ptr->pattern      = x;
-  ptr->pattern_regs = NULL_RTX;
-  ptr->antic_stores = NULL_RTX;
-  ptr->avail_stores = NULL_RTX;
+  ptr->pattern_regs.create (0);
+  ptr->antic_stores.create (0);
+  ptr->avail_stores.create (0);
   ptr->reaching_reg = NULL_RTX;
   ptr->index        = 0;
   ptr->hash_index   = hash;
@@ -168,8 +163,9 @@
 static void
 free_st_expr_entry (struct st_expr * ptr)
 {
-  free_INSN_LIST_list (& ptr->antic_stores);
-  free_INSN_LIST_list (& ptr->avail_stores);
+  ptr->antic_stores.release ();
+  ptr->avail_stores.release ();
+  ptr->pattern_regs.release ();
 
   free (ptr);
 }
@@ -179,8 +175,7 @@
 static void
 free_store_motion_mems (void)
 {
-  if (store_motion_mems_table)
-    htab_delete (store_motion_mems_table);
+  delete store_motion_mems_table;
   store_motion_mems_table = NULL;
 
   while (store_motion_mems)
@@ -238,18 +233,11 @@
       print_rtl (file, ptr->pattern);
 
       fprintf (file, "\n	 ANTIC stores : ");
-
-      if (ptr->antic_stores)
-	print_rtl (file, ptr->antic_stores);
-      else
-	fprintf (file, "(nil)");
+      print_rtx_insn_vec (file, ptr->antic_stores);
 
       fprintf (file, "\n	 AVAIL stores : ");
 
-      if (ptr->avail_stores)
-	print_rtl (file, ptr->avail_stores);
-      else
-	fprintf (file, "(nil)");
+	print_rtx_insn_vec (file, ptr->avail_stores);
 
       fprintf (file, "\n\n");
     }
@@ -261,42 +249,30 @@
    due to set of registers in bitmap REGS_SET.  */
 
 static bool
-store_ops_ok (const_rtx x, int *regs_set)
+store_ops_ok (const vec<rtx> &x, int *regs_set)
 {
-  const_rtx reg;
-
-  for (; x; x = XEXP (x, 1))
-    {
-      reg = XEXP (x, 0);
-      if (regs_set[REGNO(reg)])
-	return false;
-    }
+  unsigned int i;
+  rtx temp;
+  FOR_EACH_VEC_ELT (x, i, temp)
+    if (regs_set[REGNO (temp)])
+      return false;
 
   return true;
 }
 
-/* Helper for extract_mentioned_regs.  */
-
-static int
-extract_mentioned_regs_1 (rtx *loc, void *data)
-{
-  rtx *mentioned_regs_p = (rtx *) data;
-
-  if (REG_P (*loc))
-    *mentioned_regs_p = alloc_EXPR_LIST (0, *loc, *mentioned_regs_p);
-
-  return 0;
-}
-
 /* Returns a list of registers mentioned in X.
    FIXME: A regset would be prettier and less expensive.  */
 
-static rtx
-extract_mentioned_regs (rtx x)
+static void
+extract_mentioned_regs (rtx x, vec<rtx> *mentioned_regs)
 {
-  rtx mentioned_regs = NULL;
-  for_each_rtx (&x, extract_mentioned_regs_1, &mentioned_regs);
-  return mentioned_regs;
+  subrtx_var_iterator::array_type array;
+  FOR_EACH_SUBRTX_VAR (iter, array, x, NONCONST)
+    {
+      rtx x = *iter;
+      if (REG_P (x))
+	mentioned_regs->safe_push (x);
+    }
 }
 
 /* Check to see if the load X is aliased with STORE_PATTERN.
@@ -309,8 +285,7 @@
   if (after)
     return anti_dependence (x, store_pattern);
   else
-    return true_dependence (store_pattern, GET_MODE (store_pattern), x,
-			    rtx_addr_varies_p);
+    return true_dependence (store_pattern, GET_MODE (store_pattern), x);
 }
 
 /* Go through the entire rtx X, looking for any loads which might alias
@@ -394,9 +369,10 @@
    after the insn.  Return true if it does.  */
 
 static bool
-store_killed_in_insn (const_rtx x, const_rtx x_regs, const_rtx insn, int after)
+store_killed_in_insn (const_rtx x, const vec<rtx> &x_regs,
+		      const rtx_insn *insn, int after)
 {
-  const_rtx reg, base, note, pat;
+  const_rtx note, pat;
 
   if (! NONDEBUG_INSN_P (insn))
     return false;
@@ -410,15 +386,11 @@
 
       /* But even a const call reads its parameters.  Check whether the
 	 base of some of registers used in mem is stack pointer.  */
-      for (reg = x_regs; reg; reg = XEXP (reg, 1))
-	{
-	  base = find_base_term (XEXP (reg, 0));
-	  if (!base
-	      || (GET_CODE (base) == ADDRESS
-		  && GET_MODE (base) == Pmode
-		  && XEXP (base, 0) == stack_pointer_rtx))
-	    return true;
-	}
+      rtx temp;
+      unsigned int i;
+      FOR_EACH_VEC_ELT (x_regs, i, temp)
+	if (may_be_sp_based_p (temp))
+	  return true;
 
       return false;
     }
@@ -462,10 +434,11 @@
    is killed, return the last insn in that it occurs in FAIL_INSN.  */
 
 static bool
-store_killed_after (const_rtx x, const_rtx x_regs, const_rtx insn, const_basic_block bb,
+store_killed_after (const_rtx x, const vec<rtx> &x_regs,
+		    const rtx_insn *insn, const_basic_block bb,
 		    int *regs_set_after, rtx *fail_insn)
 {
-  rtx last = BB_END (bb), act;
+  rtx_insn *last = BB_END (bb), *act;
 
   if (!store_ops_ok (x_regs, regs_set_after))
     {
@@ -491,10 +464,11 @@
    within basic block BB. X_REGS is list of registers mentioned in X.
    REGS_SET_BEFORE is bitmap of registers set before or in this insn.  */
 static bool
-store_killed_before (const_rtx x, const_rtx x_regs, const_rtx insn, const_basic_block bb,
+store_killed_before (const_rtx x, const vec<rtx> &x_regs,
+		     const rtx_insn *insn, const_basic_block bb,
 		     int *regs_set_before)
 {
-  rtx first = BB_HEAD (bb);
+  rtx_insn *first = BB_HEAD (bb);
 
   if (!store_ops_ok (x_regs, regs_set_before))
     return true;
@@ -540,10 +514,10 @@
    */
 
 static void
-find_moveable_store (rtx insn, int *regs_set_before, int *regs_set_after)
+find_moveable_store (rtx_insn *insn, int *regs_set_before, int *regs_set_after)
 {
   struct st_expr * ptr;
-  rtx dest, set, tmp;
+  rtx dest, set;
   int check_anticipatable, check_available;
   basic_block bb = BLOCK_FOR_INSN (insn);
 
@@ -576,43 +550,45 @@
      assumes that we can do this.  But sometimes the target machine has
      oddities like MEM read-modify-write instruction.  See for example
      PR24257.  */
-  if (!can_assign_to_reg_without_clobbers_p (SET_SRC (set)))
+  if (!can_assign_to_reg_without_clobbers_p (SET_SRC (set),
+					      GET_MODE (SET_SRC (set))))
     return;
 
   ptr = st_expr_entry (dest);
-  if (!ptr->pattern_regs)
-    ptr->pattern_regs = extract_mentioned_regs (dest);
+  if (ptr->pattern_regs.is_empty ())
+    extract_mentioned_regs (dest, &ptr->pattern_regs);
 
   /* Do not check for anticipatability if we either found one anticipatable
      store already, or tested for one and found out that it was killed.  */
   check_anticipatable = 0;
-  if (!ptr->antic_stores)
+  if (ptr->antic_stores.is_empty ())
     check_anticipatable = 1;
   else
     {
-      tmp = XEXP (ptr->antic_stores, 0);
+      rtx_insn *tmp = ptr->antic_stores.last ();
       if (tmp != NULL_RTX
 	  && BLOCK_FOR_INSN (tmp) != bb)
 	check_anticipatable = 1;
     }
   if (check_anticipatable)
     {
+      rtx_insn *tmp;
       if (store_killed_before (dest, ptr->pattern_regs, insn, bb, regs_set_before))
-	tmp = NULL_RTX;
+	tmp = NULL;
       else
 	tmp = insn;
-      ptr->antic_stores = alloc_INSN_LIST (tmp, ptr->antic_stores);
+      ptr->antic_stores.safe_push (tmp);
     }
 
   /* It is not necessary to check whether store is available if we did
      it successfully before; if we failed before, do not bother to check
      until we reach the insn that caused us to fail.  */
   check_available = 0;
-  if (!ptr->avail_stores)
+  if (ptr->avail_stores.is_empty ())
     check_available = 1;
   else
     {
-      tmp = XEXP (ptr->avail_stores, 0);
+      rtx_insn *tmp = ptr->avail_stores.last ();
       if (BLOCK_FOR_INSN (tmp) != bb)
 	check_available = 1;
     }
@@ -622,6 +598,7 @@
 	 failed last time.  */
       if (LAST_AVAIL_CHECK_FAILURE (ptr))
 	{
+	  rtx_insn *tmp;
 	  for (tmp = BB_END (bb);
 	       tmp != insn && tmp != LAST_AVAIL_CHECK_FAILURE (ptr);
 	       tmp = PREV_INSN (tmp))
@@ -635,7 +612,7 @@
 					      &LAST_AVAIL_CHECK_FAILURE (ptr));
     }
   if (!check_available)
-    ptr->avail_stores = alloc_INSN_LIST (insn, ptr->avail_stores);
+    ptr->avail_stores.safe_push (insn);
 }
 
 /* Find available and anticipatable stores.  */
@@ -645,23 +622,20 @@
 {
   int ret;
   basic_block bb;
-#ifdef ENABLE_CHECKING
-  unsigned regno;
-#endif
-  rtx insn, tmp;
-  df_ref *def_rec;
+  rtx_insn *insn;
+  rtx_insn *tmp;
+  df_ref def;
   int *last_set_in, *already_set;
   struct st_expr * ptr, **prev_next_ptr_ptr;
   unsigned int max_gcse_regno = max_reg_num ();
 
   store_motion_mems = NULL;
-  store_motion_mems_table = htab_create (13, pre_st_expr_hash,
-					 pre_st_expr_eq, NULL);
+  store_motion_mems_table = new hash_table<st_expr_hasher> (13);
   last_set_in = XCNEWVEC (int, max_gcse_regno);
   already_set = XNEWVEC (int, max_gcse_regno);
 
   /* Find all the stores we care about.  */
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     {
       /* First compute the registers set in this block.  */
       FOR_BB_INSNS (bb, insn)
@@ -670,8 +644,8 @@
 	  if (! NONDEBUG_INSN_P (insn))
 	    continue;
 
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	    last_set_in[DF_REF_REGNO (*def_rec)] = INSN_UID (insn);
+	  FOR_EACH_INSN_DEF (def, insn)
+	    last_set_in[DF_REF_REGNO (def)] = INSN_UID (insn);
 	}
 
       /* Now find the stores.  */
@@ -681,31 +655,32 @@
 	  if (! NONDEBUG_INSN_P (insn))
 	    continue;
 
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	    already_set[DF_REF_REGNO (*def_rec)] = INSN_UID (insn);
+	  FOR_EACH_INSN_DEF (def, insn)
+	    already_set[DF_REF_REGNO (def)] = INSN_UID (insn);
 
 	  /* Now that we've marked regs, look for stores.  */
 	  find_moveable_store (insn, already_set, last_set_in);
 
 	  /* Unmark regs that are no longer set.  */
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	    if (last_set_in[DF_REF_REGNO (*def_rec)] == INSN_UID (insn))
-	      last_set_in[DF_REF_REGNO (*def_rec)] = 0;
+	  FOR_EACH_INSN_DEF (def, insn)
+	    if (last_set_in[DF_REF_REGNO (def)] == INSN_UID (insn))
+	      last_set_in[DF_REF_REGNO (def)] = 0;
 	}
 
-#ifdef ENABLE_CHECKING
-      /* last_set_in should now be all-zero.  */
-      for (regno = 0; regno < max_gcse_regno; regno++)
-	gcc_assert (!last_set_in[regno]);
-#endif
+      if (flag_checking)
+	{
+	  /* last_set_in should now be all-zero.  */
+	  for (unsigned regno = 0; regno < max_gcse_regno; regno++)
+	    gcc_assert (!last_set_in[regno]);
+	}
 
       /* Clear temporary marks.  */
       for (ptr = first_st_expr (); ptr != NULL; ptr = next_st_expr (ptr))
 	{
 	  LAST_AVAIL_CHECK_FAILURE (ptr) = NULL_RTX;
-	  if (ptr->antic_stores
-	      && (tmp = XEXP (ptr->antic_stores, 0)) == NULL_RTX)
-	    ptr->antic_stores = XEXP (ptr->antic_stores, 1);
+	  if (!ptr->antic_stores.is_empty ()
+	      && (tmp = ptr->antic_stores.last ()) == NULL)
+	    ptr->antic_stores.pop ();
 	}
     }
 
@@ -715,11 +690,10 @@
        ptr != NULL;
        ptr = *prev_next_ptr_ptr)
     {
-      if (! ptr->avail_stores)
+      if (ptr->avail_stores.is_empty ())
 	{
 	  *prev_next_ptr_ptr = ptr->next;
-	  htab_remove_elt_with_hash (store_motion_mems_table,
-				     ptr, ptr->hash_index);
+	  store_motion_mems_table->remove_elt_with_hash (ptr, ptr->hash_index);
 	  free_st_expr_entry (ptr);
 	}
       else
@@ -745,11 +719,11 @@
    the BB_HEAD if needed.  */
 
 static void
-insert_insn_start_basic_block (rtx insn, basic_block bb)
+insert_insn_start_basic_block (rtx_insn *insn, basic_block bb)
 {
   /* Insert at start of successor block.  */
-  rtx prev = PREV_INSN (BB_HEAD (bb));
-  rtx before = BB_HEAD (bb);
+  rtx_insn *prev = PREV_INSN (BB_HEAD (bb));
+  rtx_insn *before = BB_HEAD (bb);
   while (before != 0)
     {
       if (! LABEL_P (before)
@@ -779,7 +753,8 @@
 static int
 insert_store (struct st_expr * expr, edge e)
 {
-  rtx reg, insn;
+  rtx reg;
+  rtx_insn *insn;
   basic_block bb;
   edge tmp;
   edge_iterator ei;
@@ -805,18 +780,18 @@
 	int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest);
 
 	gcc_assert (index != EDGE_INDEX_NO_EDGE);
-	if (! TEST_BIT (st_insert_map[index], expr->index))
+	if (! bitmap_bit_p (st_insert_map[index], expr->index))
 	  break;
       }
 
   /* If tmp is NULL, we found an insertion on every edge, blank the
      insertion vector for these edges, and insert at the start of the BB.  */
-  if (!tmp && bb != EXIT_BLOCK_PTR)
+  if (!tmp && bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
     {
       FOR_EACH_EDGE (tmp, ei, e->dest->preds)
 	{
 	  int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest);
-	  RESET_BIT (st_insert_map[index], expr->index);
+	  bitmap_clear_bit (st_insert_map[index], expr->index);
 	}
       insert_insn_start_basic_block (insn, bb);
       return 0;
@@ -850,48 +825,50 @@
   edge_iterator *stack, ei;
   int sp;
   edge act;
-  sbitmap visited = sbitmap_alloc (last_basic_block);
-  rtx last, insn, note;
+  auto_sbitmap visited (last_basic_block_for_fn (cfun));
+  rtx note;
+  rtx_insn *insn;
   rtx mem = smexpr->pattern;
 
-  stack = XNEWVEC (edge_iterator, n_basic_blocks);
+  stack = XNEWVEC (edge_iterator, n_basic_blocks_for_fn (cfun));
   sp = 0;
   ei = ei_start (bb->succs);
 
-  sbitmap_zero (visited);
+  bitmap_clear (visited);
 
-  act = (EDGE_COUNT (ei_container (ei)) > 0 ? EDGE_I (ei_container (ei), 0) : NULL);
-  while (1)
+  act = (EDGE_COUNT (ei_container (ei))
+	 ? EDGE_I (ei_container (ei), 0)
+	 : NULL);
+  for (;;)
     {
       if (!act)
 	{
 	  if (!sp)
 	    {
 	      free (stack);
-	      sbitmap_free (visited);
 	      return;
 	    }
 	  act = ei_edge (stack[--sp]);
 	}
       bb = act->dest;
 
-      if (bb == EXIT_BLOCK_PTR
-	  || TEST_BIT (visited, bb->index))
+      if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
+	  || bitmap_bit_p (visited, bb->index))
 	{
 	  if (!ei_end_p (ei))
 	      ei_next (&ei);
 	  act = (! ei_end_p (ei)) ? ei_edge (ei) : NULL;
 	  continue;
 	}
-      SET_BIT (visited, bb->index);
+      bitmap_set_bit (visited, bb->index);
 
-      if (TEST_BIT (st_antloc[bb->index], smexpr->index))
+      rtx_insn *last;
+      if (bitmap_bit_p (st_antloc[bb->index], smexpr->index))
 	{
-	  for (last = smexpr->antic_stores;
-	       BLOCK_FOR_INSN (XEXP (last, 0)) != bb;
-	       last = XEXP (last, 1))
-	    continue;
-	  last = XEXP (last, 0);
+	  unsigned int i;
+	  FOR_EACH_VEC_ELT_REVERSE (smexpr->antic_stores, i, last)
+	    if (BLOCK_FOR_INSN (last) == bb)
+	      break;
 	}
       else
 	last = NEXT_INSN (BB_END (bb));
@@ -904,7 +881,8 @@
 	      continue;
 
 	    if (dump_file)
-	      fprintf (dump_file, "STORE_MOTION  drop REG_EQUAL note at insn %d:\n",
+	      fprintf (dump_file,
+		       "STORE_MOTION  drop REG_EQUAL note at insn %d:\n",
 		       INSN_UID (insn));
 	    remove_note (insn, note);
 	  }
@@ -918,7 +896,9 @@
 	  if (act)
 	    stack[sp++] = ei;
 	  ei = ei_start (bb->succs);
-	  act = (EDGE_COUNT (ei_container (ei)) > 0 ? EDGE_I (ei_container (ei), 0) : NULL);
+	  act = (EDGE_COUNT (ei_container (ei))
+		 ? EDGE_I (ei_container (ei), 0)
+		 : NULL);
 	}
     }
 }
@@ -926,17 +906,21 @@
 /* This routine will replace a store with a SET to a specified register.  */
 
 static void
-replace_store_insn (rtx reg, rtx del, basic_block bb, struct st_expr *smexpr)
+replace_store_insn (rtx reg, rtx_insn *del, basic_block bb,
+		    struct st_expr *smexpr)
 {
-  rtx insn, mem, note, set, ptr;
+  rtx_insn *insn;
+  rtx mem, note, set;
 
   mem = smexpr->pattern;
   insn = gen_move_insn (reg, SET_SRC (single_set (del)));
 
-  for (ptr = smexpr->antic_stores; ptr; ptr = XEXP (ptr, 1))
-    if (XEXP (ptr, 0) == del)
+  unsigned int i;
+  rtx_insn *temp;
+  FOR_EACH_VEC_ELT_REVERSE (smexpr->antic_stores, i, temp)
+    if (temp == del)
       {
-	XEXP (ptr, 0) = insn;
+	smexpr->antic_stores[i] = insn;
 	break;
       }
 
@@ -989,16 +973,17 @@
 static void
 delete_store (struct st_expr * expr, basic_block bb)
 {
-  rtx reg, i, del;
+  rtx reg;
 
   if (expr->reaching_reg == NULL_RTX)
     expr->reaching_reg = gen_reg_rtx_and_attrs (expr->pattern);
 
   reg = expr->reaching_reg;
 
-  for (i = expr->avail_stores; i; i = XEXP (i, 1))
+  unsigned int len = expr->avail_stores.length ();
+  for (unsigned int i = len - 1; i < len; i--)
     {
-      del = XEXP (i, 0);
+      rtx_insn *del = expr->avail_stores[i];
       if (BLOCK_FOR_INSN (del) == bb)
 	{
 	  /* We know there is only one since we deleted redundant
@@ -1016,68 +1001,71 @@
 {
   basic_block bb;
   int *regs_set_in_block;
-  rtx insn, st;
+  rtx_insn *insn;
   struct st_expr * ptr;
   unsigned int max_gcse_regno = max_reg_num ();
 
   /* Build the gen_vector. This is any store in the table which is not killed
      by aliasing later in its block.  */
-  st_avloc = sbitmap_vector_alloc (last_basic_block, num_stores);
-  sbitmap_vector_zero (st_avloc, last_basic_block);
+  st_avloc = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
+				   num_stores);
+  bitmap_vector_clear (st_avloc, last_basic_block_for_fn (cfun));
 
-  st_antloc = sbitmap_vector_alloc (last_basic_block, num_stores);
-  sbitmap_vector_zero (st_antloc, last_basic_block);
+  st_antloc = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
+				    num_stores);
+  bitmap_vector_clear (st_antloc, last_basic_block_for_fn (cfun));
 
   for (ptr = first_st_expr (); ptr != NULL; ptr = next_st_expr (ptr))
     {
-      for (st = ptr->avail_stores; st != NULL; st = XEXP (st, 1))
+      unsigned int len = ptr->avail_stores.length ();
+      for (unsigned int i = len - 1; i < len; i--)
 	{
-	  insn = XEXP (st, 0);
+	  insn = ptr->avail_stores[i];
 	  bb = BLOCK_FOR_INSN (insn);
 
 	  /* If we've already seen an available expression in this block,
 	     we can delete this one (It occurs earlier in the block). We'll
 	     copy the SRC expression to an unused register in case there
 	     are any side effects.  */
-	  if (TEST_BIT (st_avloc[bb->index], ptr->index))
+	  if (bitmap_bit_p (st_avloc[bb->index], ptr->index))
 	    {
 	      rtx r = gen_reg_rtx_and_attrs (ptr->pattern);
 	      if (dump_file)
 		fprintf (dump_file, "Removing redundant store:\n");
-	      replace_store_insn (r, XEXP (st, 0), bb, ptr);
+	      replace_store_insn (r, insn, bb, ptr);
 	      continue;
 	    }
-	  SET_BIT (st_avloc[bb->index], ptr->index);
+	  bitmap_set_bit (st_avloc[bb->index], ptr->index);
 	}
 
-      for (st = ptr->antic_stores; st != NULL; st = XEXP (st, 1))
+      unsigned int i;
+      FOR_EACH_VEC_ELT_REVERSE (ptr->antic_stores, i, insn)
 	{
-	  insn = XEXP (st, 0);
 	  bb = BLOCK_FOR_INSN (insn);
-	  SET_BIT (st_antloc[bb->index], ptr->index);
+	  bitmap_set_bit (st_antloc[bb->index], ptr->index);
 	}
     }
 
-  st_kill = sbitmap_vector_alloc (last_basic_block, num_stores);
-  sbitmap_vector_zero (st_kill, last_basic_block);
+  st_kill = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), num_stores);
+  bitmap_vector_clear (st_kill, last_basic_block_for_fn (cfun));
 
-  st_transp = sbitmap_vector_alloc (last_basic_block, num_stores);
-  sbitmap_vector_zero (st_transp, last_basic_block);
+  st_transp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), num_stores);
+  bitmap_vector_clear (st_transp, last_basic_block_for_fn (cfun));
   regs_set_in_block = XNEWVEC (int, max_gcse_regno);
 
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     {
       memset (regs_set_in_block, 0, sizeof (int) * max_gcse_regno);
 
       FOR_BB_INSNS (bb, insn)
 	if (NONDEBUG_INSN_P (insn))
 	  {
-	    df_ref *def_rec;
-	    for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
+	    df_ref def;
+	    FOR_EACH_INSN_DEF (def, insn)
 	      {
-		unsigned int ref_regno = DF_REF_REGNO (*def_rec);
+		unsigned int ref_regno = DF_REF_REGNO (def);
 		if (ref_regno < max_gcse_regno)
-		  regs_set_in_block[DF_REF_REGNO (*def_rec)] = 1;
+		  regs_set_in_block[DF_REF_REGNO (def)] = 1;
 	      }
 	  }
 
@@ -1088,12 +1076,12 @@
 	    {
 	      /* It should not be necessary to consider the expression
 		 killed if it is both anticipatable and available.  */
-	      if (!TEST_BIT (st_antloc[bb->index], ptr->index)
-		  || !TEST_BIT (st_avloc[bb->index], ptr->index))
-		SET_BIT (st_kill[bb->index], ptr->index);
+	      if (!bitmap_bit_p (st_antloc[bb->index], ptr->index)
+		  || !bitmap_bit_p (st_avloc[bb->index], ptr->index))
+		bitmap_set_bit (st_kill[bb->index], ptr->index);
 	    }
 	  else
-	    SET_BIT (st_transp[bb->index], ptr->index);
+	    bitmap_set_bit (st_transp[bb->index], ptr->index);
 	}
     }
 
@@ -1101,10 +1089,14 @@
 
   if (dump_file)
     {
-      dump_sbitmap_vector (dump_file, "st_antloc", "", st_antloc, last_basic_block);
-      dump_sbitmap_vector (dump_file, "st_kill", "", st_kill, last_basic_block);
-      dump_sbitmap_vector (dump_file, "st_transp", "", st_transp, last_basic_block);
-      dump_sbitmap_vector (dump_file, "st_avloc", "", st_avloc, last_basic_block);
+      dump_bitmap_vector (dump_file, "st_antloc", "", st_antloc,
+			  last_basic_block_for_fn (cfun));
+      dump_bitmap_vector (dump_file, "st_kill", "", st_kill,
+			  last_basic_block_for_fn (cfun));
+      dump_bitmap_vector (dump_file, "st_transp", "", st_transp,
+			  last_basic_block_for_fn (cfun));
+      dump_bitmap_vector (dump_file, "st_avloc", "", st_avloc,
+			  last_basic_block_for_fn (cfun));
     }
 }
 
@@ -1152,7 +1144,7 @@
   num_stores = compute_store_table ();
   if (num_stores == 0)
     {
-      htab_delete (store_motion_mems_table);
+      delete store_motion_mems_table;
       store_motion_mems_table = NULL;
       end_alias_analysis ();
       return 0;
@@ -1173,7 +1165,7 @@
       /* If any of the edges we have above are abnormal, we can't move this
 	 store.  */
       for (x = NUM_EDGES (edge_list) - 1; x >= 0; x--)
-	if (TEST_BIT (st_insert_map[x], ptr->index)
+	if (bitmap_bit_p (st_insert_map[x], ptr->index)
 	    && (INDEX_EDGE (edge_list, x)->flags & EDGE_ABNORMAL))
 	  break;
 
@@ -1189,15 +1181,15 @@
 
       /* Now we want to insert the new stores which are going to be needed.  */
 
-      FOR_EACH_BB (bb)
-	if (TEST_BIT (st_delete_map[bb->index], ptr->index))
+      FOR_EACH_BB_FN (bb, cfun)
+	if (bitmap_bit_p (st_delete_map[bb->index], ptr->index))
 	  {
 	    delete_store (ptr, bb);
 	    n_stores_deleted++;
 	  }
 
       for (x = 0; x < NUM_EDGES (edge_list); x++)
-	if (TEST_BIT (st_insert_map[x], ptr->index))
+	if (bitmap_bit_p (st_insert_map[x], ptr->index))
 	  {
 	    did_edge_inserts |= insert_store (ptr, INDEX_EDGE (edge_list, x));
 	    n_stores_created++;
@@ -1215,7 +1207,7 @@
   if (dump_file)
     {
       fprintf (dump_file, "STORE_MOTION of %s, %d basic blocks, ",
-	       current_function_name (), n_basic_blocks);
+	       current_function_name (), n_basic_blocks_for_fn (cfun));
       fprintf (dump_file, "%d insns deleted, %d insns created\n",
 	       n_stores_deleted, n_stores_created);
     }
@@ -1224,15 +1216,6 @@
 }
 
 
-static bool
-gate_rtl_store_motion (void)
-{
-  return optimize > 0 && flag_gcse_sm
-    && !cfun->calls_setjmp
-    && optimize_function_for_speed_p (cfun)
-    && dbg_cnt (store_motion);
-}
-
 static unsigned int
 execute_rtl_store_motion (void)
 {
@@ -1242,24 +1225,50 @@
   return 0;
 }
 
-struct rtl_opt_pass pass_rtl_store_motion =
+namespace {
+
+const pass_data pass_data_rtl_store_motion =
 {
- {
-  RTL_PASS,
-  "store_motion",                       /* name */
-  gate_rtl_store_motion,                /* gate */
-  execute_rtl_store_motion,		/* execute */
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  TV_LSM,                               /* tv_id */
-  PROP_cfglayout,                       /* properties_required */
-  0,                                    /* properties_provided */
-  0,                                    /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  TODO_df_finish | TODO_verify_rtl_sharing |
-  TODO_dump_func |
-  TODO_verify_flow | TODO_ggc_collect   /* todo_flags_finish */
- }
+  RTL_PASS, /* type */
+  "store_motion", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_LSM, /* tv_id */
+  PROP_cfglayout, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_df_finish, /* todo_flags_finish */
 };
 
+class pass_rtl_store_motion : public rtl_opt_pass
+{
+public:
+  pass_rtl_store_motion (gcc::context *ctxt)
+    : rtl_opt_pass (pass_data_rtl_store_motion, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *);
+  virtual unsigned int execute (function *)
+    {
+      return execute_rtl_store_motion ();
+    }
+
+}; // class pass_rtl_store_motion
+
+bool
+pass_rtl_store_motion::gate (function *fun)
+{
+  return optimize > 0 && flag_gcse_sm
+    && !fun->calls_setjmp
+    && optimize_function_for_speed_p (fun)
+    && dbg_cnt (store_motion);
+}
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_rtl_store_motion (gcc::context *ctxt)
+{
+  return new pass_rtl_store_motion (ctxt);
+}