Patchwork [cxx-conversion] various hash tables, part 2/2

login
register
mail settings
Submitter Lawrence Crowl
Date Dec. 2, 2012, 1:48 a.m.
Message ID <CAGqM8fY8vKnbi-D62hLpur2W04-oVy0i237NZH_Dq_yP7Q87QQ@mail.gmail.com>
Download mbox | patch
Permalink /patch/203174/
State New
Headers show

Comments

Lawrence Crowl - Dec. 2, 2012, 1:48 a.m.
Change various hash tables from htab_t to hash_table.
Each file is independent.

cselib.c cselib_hash_table
gcse.c pre_ldst_table
gimple-ssa-strength-reduction.c base_cand_map
haifa-sched.c delay_htab
haifa-sched.c delay_htab_i2
ira-color.c allocno_hard_regs_htab
ira-costs.c cost_classes_htab
loop-invariant.c merge_identical_invariants::eq
loop-iv.c bivs
loop-unroll.c opt_info::insns_to_split
loop-unroll.c opt_info::insns_with_var_to_expand
passes.c name_to_pass_map
plugin.c event_tab
postreload-gcse.c expr_table
store-motion.c store_motion_mems_table
tree-cfg.c discriminator_per_locus
tree-scalar-evolution.c resolve_mixers::cache
tree-ssa-dom.c avail_exprs

Remove unused:
dse.c bitmap clear_alias_sets
dse.c bitmap disqualified_clear_alias_sets
dse.c alloc_pool clear_alias_mode_pool
dse.c dse_step2_spill
dse.c dse_step5_spill
graphds.h htab_t graph::indices


Tested on x86-64.

Okay for branch?


 /* Register PASS with NAME.  */

@@ -612,11 +619,11 @@ register_pass_name (struct opt_pass *pas
   struct pass_registry **slot;
   struct pass_registry pr;

-  if (!name_to_pass_map)
-    name_to_pass_map = htab_create (256, passr_hash, passr_eq, NULL);
+  if (!name_to_pass_map.is_created ())
+    name_to_pass_map.create (256);

   pr.unique_name = name;
-  slot = (struct pass_registry **) htab_find_slot (name_to_pass_map,
&pr, INSERT);
+  slot = name_to_pass_map.find_slot (&pr, INSERT);
   if (!*slot)
     {
       struct pass_registry *new_pr;
@@ -637,10 +644,9 @@ static vec<char_ptr> pass_tab = vNULL;

 /* Callback function for traversing NAME_TO_PASS_MAP.  */

-static int
-pass_traverse (void **slot, void *data ATTRIBUTE_UNUSED)
+int
+passes_pass_traverse (pass_registry **p, void *data ATTRIBUTE_UNUSED)
 {
-  struct pass_registry **p = (struct pass_registry **)slot;
   struct opt_pass *pass = (*p)->pass;

   gcc_assert (pass->static_pass_number > 0);
@@ -661,7 +667,7 @@ create_pass_tab (void)
     return;

   pass_tab.safe_grow_cleared (passes_by_id_size + 1);
-  htab_traverse (name_to_pass_map, pass_traverse, NULL);
+  name_to_pass_map.traverse <void *, passes_pass_traverse> (NULL);
 }

 static bool override_gate_status (struct opt_pass *, tree, bool);
@@ -746,8 +752,7 @@ get_pass_by_name (const char *name)
   struct pass_registry **slot, pr;

   pr.unique_name = name;
-  slot = (struct pass_registry **) htab_find_slot (name_to_pass_map,
-                                                   &pr, NO_INSERT);
+  slot = name_to_pass_map.find_slot (&pr, NO_INSERT);

   if (!slot || !*slot)
     return NULL;
Diego Novillo - Dec. 3, 2012, 7:46 p.m.
On 2012-12-01 20:48 , Lawrence Crowl wrote:

> +inline bool
> +cselib_hasher::equal (const value_type *v, const compare_type *x_arg)
> +{
> +  struct elt_loc_list *l;
> +  rtx x = CONST_CAST_RTX (x_arg);
> +  enum machine_mode mode = GET_MODE (x);
> +
> +  gcc_assert (!CONST_SCALAR_INT_P (x) && GET_CODE (x) != CONST_FIXED);
> +
> +  if (mode != GET_MODE (v->val_rtx))
> +    return 0;
> +
> +  /* Unwrap X if necessary.  */
> +  if (GET_CODE (x) == CONST
> +      && (CONST_SCALAR_INT_P (XEXP (x, 0))
> +	  || GET_CODE (XEXP (x, 0)) == CONST_FIXED))
> +    x = XEXP (x, 0);
> +
> +  /* We don't guarantee that distinct rtx's have different hash values,
> +     so we need to do a comparison.  */
> +  for (l = v->locs; l; l = l->next)
> +    if (rtx_equal_for_cselib_1 (l->loc, x, find_slot_memmode))
> +      {
> +	promote_debug_loc (l);
> +	return 1;
> +      }
> +
> +  return 0;

s/1/true/
s/0/false/

> @@ -504,8 +557,10 @@ cselib_get_next_uid (void)
>     return next_uid;
>   }
>
> +#if 0
>   /* See the documentation of cselib_find_slot below.  */
>   static enum machine_mode find_slot_memmode;
> +#endif

Remove?


> +#if 0
>   /* The equality test for our hash table.  The first argument ENTRY is a table
>      element (i.e. a cselib_val), while the second arg X is an rtx.  We know
>      that all callers of htab_find_slot_with_hash will wrap CONST_INTs into a
> @@ -570,6 +626,7 @@ get_value_hash (const void *entry)
>     const cselib_val *const v = (const cselib_val *) entry;
>     return v->hash;
>   }
> +#endif

Remove?



OK otherwise.

This only leaves the GC htabs, right?  What was the issue there? 
gengtype being silly?


Diego.
Lawrence Crowl - Dec. 3, 2012, 7:54 p.m.
On 12/3/12, Diego Novillo <dnovillo@google.com> wrote:
> On 2012-12-01 20:48 , Lawrence Crowl wrote:
>> +inline bool
>> +cselib_hasher::equal (const value_type *v, const compare_type *x_arg)
>> +{
>> +  struct elt_loc_list *l;
>> +  rtx x = CONST_CAST_RTX (x_arg);
>> +  enum machine_mode mode = GET_MODE (x);
>> +
>> +  gcc_assert (!CONST_SCALAR_INT_P (x) && GET_CODE (x) != CONST_FIXED);
>> +
>> +  if (mode != GET_MODE (v->val_rtx))
>> +    return 0;
>> +
>> +  /* Unwrap X if necessary.  */
>> +  if (GET_CODE (x) == CONST
>> +      && (CONST_SCALAR_INT_P (XEXP (x, 0))
>> +	  || GET_CODE (XEXP (x, 0)) == CONST_FIXED))
>> +    x = XEXP (x, 0);
>> +
>> +  /* We don't guarantee that distinct rtx's have different hash values,
>> +     so we need to do a comparison.  */
>> +  for (l = v->locs; l; l = l->next)
>> +    if (rtx_equal_for_cselib_1 (l->loc, x, find_slot_memmode))
>> +      {
>> +	promote_debug_loc (l);
>> +	return 1;
>> +      }
>> +
>> +  return 0;
>
> s/1/true/
> s/0/false/

Done.

>> @@ -504,8 +557,10 @@ cselib_get_next_uid (void)
>>     return next_uid;
>>   }
>>
>> +#if 0
>>   /* See the documentation of cselib_find_slot below.  */
>>   static enum machine_mode find_slot_memmode;
>> +#endif
>
> Remove?

Done.

>> +#if 0
>>   /* The equality test for our hash table.  The first argument ENTRY is a
>> table
>>      element (i.e. a cselib_val), while the second arg X is an rtx.  We
>> know
>>      that all callers of htab_find_slot_with_hash will wrap CONST_INTs
>> into a
>> @@ -570,6 +626,7 @@ get_value_hash (const void *entry)
>>     const cselib_val *const v = (const cselib_val *) entry;
>>     return v->hash;
>>   }
>> +#endif
>
> Remove?

Done.

> OK otherwise.
>
> This only leaves the GC htabs, right?

No, there are still more non-GC htabs.

> What was the issue there?  gengtype being silly?

Yes.

Patch

Index: gcc/ChangeLog

2012-11-30  Lawrence Crowl  <crowl@google.com>

	* cselib.c (htab_t cselib_hash_table):
	Change type to hash_table.  Update dependent calls and types.

	* dse.c (bitmap clear_alias_sets): Remove unused.
	(bitmap disqualified_clear_alias_sets): Likewise.
	(alloc_pool clear_alias_mode_pool): Likewise.
	(dse_step2_spill): Likewise.
	(dse_step5_spill): Likewise.

	* gcse.c (htab_t pre_ldst_table):
	Change type to hash_table.  Update dependent calls and types.

	* gimple-ssa-strength-reduction.c (htab_t base_cand_map):
	Change type to hash_table.  Update dependent calls and types.
	(base_cand_dump_callback): Rename to ssa_base_cand_dump_callback to
	avoid potential global name collision.

	* graphds.h (htab_t graph::indices): Remove unused.

	* haifa-sched.c (htab_t delay_htab):
	Change type to hash_table.  Update dependent calls and types.
	(htab_t delay_htab_i2): Likewise.

	* ira-color.c (htab_t allocno_hard_regs_htab):
	Change type to hash_table.  Update dependent calls and types.

	* ira-costs.c (htab_t cost_classes_htab):
	Change type to hash_table.  Update dependent calls and types.

	* loop-invariant.c (htab_t merge_identical_invariants::eq):
	Change type to hash_table.  Update dependent calls and types.

	* loop-iv.c (htab_t bivs):
	Change type to hash_table.  Update dependent calls and types.

	* loop-unroll.c (htab_t opt_info::insns_to_split):
	Change type to hash_table.  Update dependent calls and types.
	(htab_t opt_info::insns_with_var_to_expand): Likewise.

	* passes.c (htab_t name_to_pass_map):
	Change type to hash_table.  Update dependent calls and types.
	(pass_traverse): Rename to passes_pass_traverse.

	* plugin.c (htab_t event_tab):
	Change type to hash_table.  Update dependent calls and types.

	* postreload-gcse.c (htab_t expr_table):
	Change type to hash_table.  Update dependent calls and types.
	(dump_hash_table_entry): Rename dump_expr_hash_table_entry.

	* store-motion.c (htab_t store_motion_mems_table):
	Change type to hash_table.  Update dependent calls and types.

	* tree-cfg.c (htab_t discriminator_per_locus):
	Change type to hash_table.  Update dependent calls and types.

	* tree-scalar-evolution.c (htab_t resolve_mixers::cache):
	Change type to hash_table.  Update dependent calls and types.

	* tree-ssa-dom.c (htab_t avail_exprs):
	Change type to hash_table.  Update dependent calls and types.

	* Makefile.in: Add new dependences on $(HASH_TABLE_H).

Index: gcc/postreload-gcse.c
===================================================================
--- gcc/postreload-gcse.c	(revision 193902)
+++ gcc/postreload-gcse.c	(working copy)
@@ -24,6 +24,7 @@  along with GCC; see the file COPYING3.
 #include "tm.h"
 #include "diagnostic-core.h"

+#include "hash-table.h"
 #include "rtl.h"
 #include "tree.h"
 #include "tm_p.h"
@@ -88,9 +89,6 @@  static struct
    type 'struct expr', and for each expression there is a single linked
    list of occurrences.  */

-/* The table itself.  */
-static htab_t expr_table;
-
 /* Expression elements in the hash table.  */
 struct expr
 {
@@ -104,6 +102,56 @@  struct expr
   struct occr *avail_occr;
 };

+/* Hashtable helpers.  */
+
+struct expr_hasher : typed_noop_remove <expr>
+{
+  typedef expr value_type;
+  typedef expr compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+
+/* Hash expression X.
+   DO_NOT_RECORD_P is a boolean indicating if a volatile operand is found
+   or if the expression contains something we don't want to insert in the
+   table.  */
+
+static hashval_t
+hash_expr (rtx x, int *do_not_record_p)
+{
+  *do_not_record_p = 0;
+  return hash_rtx (x, GET_MODE (x), do_not_record_p,
+		   NULL,  /*have_reg_qty=*/false);
+}
+
+/* Callback for hashtab.
+   Return the hash value for expression EXP.  We don't actually hash
+   here, we just return the cached hash value.  */
+
+inline hashval_t
+expr_hasher::hash (const value_type *exp)
+{
+  return exp->hash;
+}
+
+/* Callback for hashtab.
+   Return nonzero if exp1 is equivalent to exp2.  */
+
+inline bool
+expr_hasher::equal (const value_type *exp1, const compare_type *exp2)
+{
+  int equiv_p = exp_equiv_p (exp1->expr, exp2->expr, 0, true);
+
+  gcc_assert (!equiv_p || exp1->hash == exp2->hash);
+  return equiv_p;
+}
+
+/* The table itself.  */
+static hash_table <expr_hasher> expr_table;
+
+
 static struct obstack expr_obstack;

 /* Occurrence of an expression.
@@ -184,11 +232,8 @@  static void reset_opr_set_tables (void);

 /* Hash table support.  */
 static hashval_t hash_expr (rtx, int *);
-static hashval_t hash_expr_for_htab (const void *);
-static int expr_equiv_p (const void *, const void *);
 static void insert_expr_in_table (rtx, rtx);
 static struct expr *lookup_expr_in_table (rtx);
-static int dump_hash_table_entry (void **, void *);
 static void dump_hash_table (FILE *);

 /* Helpers for eliminate_partially_redundant_load.  */
@@ -235,8 +280,7 @@  alloc_mem (void)
      make the hash table too small, but unnecessarily making it too large
      also doesn't help.  The i/4 is a gcse.c relic, and seems like a
      reasonable choice.  */
-  expr_table = htab_create (MAX (i / 4, 13),
-			    hash_expr_for_htab, expr_equiv_p, NULL);
+  expr_table.create (MAX (i / 4, 13));

   /* We allocate everything on obstacks because we often can roll back
      the whole obstack to some point.  Freeing obstacks is very fast.  */
@@ -263,7 +307,7 @@  free_mem (void)
 {
   free (uid_cuid);

-  htab_delete (expr_table);
+  expr_table.dispose ();

   obstack_free (&expr_obstack, NULL);
   obstack_free (&occr_obstack, NULL);
@@ -274,45 +318,6 @@  free_mem (void)
 }
 

-/* Hash expression X.
-   DO_NOT_RECORD_P is a boolean indicating if a volatile operand is found
-   or if the expression contains something we don't want to insert in the
-   table.  */
-
-static hashval_t
-hash_expr (rtx x, int *do_not_record_p)
-{
-  *do_not_record_p = 0;
-  return hash_rtx (x, GET_MODE (x), do_not_record_p,
-		   NULL,  /*have_reg_qty=*/false);
-}
-
-/* Callback for hashtab.
-   Return the hash value for expression EXP.  We don't actually hash
-   here, we just return the cached hash value.  */
-
-static hashval_t
-hash_expr_for_htab (const void *expp)
-{
-  const struct expr *const exp = (const struct expr *) expp;
-  return exp->hash;
-}
-
-/* Callback for hashtab.
-   Return nonzero if exp1 is equivalent to exp2.  */
-
-static int
-expr_equiv_p (const void *exp1p, const void *exp2p)
-{
-  const struct expr *const exp1 = (const struct expr *) exp1p;
-  const struct expr *const exp2 = (const struct expr *) exp2p;
-  int equiv_p = exp_equiv_p (exp1->expr, exp2->expr, 0, true);
-
-  gcc_assert (!equiv_p || exp1->hash == exp2->hash);
-  return equiv_p;
-}
-
-
 /* Insert expression X in INSN in the hash TABLE.
    If it is already present, record it as the last occurrence in INSN's
    basic block.  */
@@ -344,8 +349,7 @@  insert_expr_in_table (rtx x, rtx insn)
   cur_expr->hash = hash;
   cur_expr->avail_occr = NULL;

-  slot = (struct expr **) htab_find_slot_with_hash (expr_table, cur_expr,
-						    hash, INSERT);
+  slot = expr_table.find_slot_with_hash (cur_expr, hash, INSERT);

   if (! (*slot))
     /* The expression isn't found, so insert it.  */
@@ -413,8 +417,7 @@  lookup_expr_in_table (rtx pat)
   tmp_expr->hash = hash;
   tmp_expr->avail_occr = NULL;

-  slot = (struct expr **) htab_find_slot_with_hash (expr_table, tmp_expr,
-                                                    hash, INSERT);
+  slot = expr_table.find_slot_with_hash (tmp_expr, hash, INSERT);
   obstack_free (&expr_obstack, tmp_expr);

   if (!slot)
@@ -428,18 +431,17 @@  lookup_expr_in_table (rtx pat)
    expression hash table to FILE.  */

 /* This helper is called via htab_traverse.  */
-static int
-dump_hash_table_entry (void **slot, void *filep)
+int
+dump_expr_hash_table_entry (expr **slot, FILE *file)
 {
-  struct expr *expr = (struct expr *) *slot;
-  FILE *file = (FILE *) filep;
+  struct expr *exprs = *slot;
   struct occr *occr;

   fprintf (file, "expr: ");
-  print_rtl (file, expr->expr);
-  fprintf (file,"\nhashcode: %u\n", expr->hash);
+  print_rtl (file, exprs->expr);
+  fprintf (file,"\nhashcode: %u\n", exprs->hash);
   fprintf (file,"list of occurrences:\n");
-  occr = expr->avail_occr;
+  occr = exprs->avail_occr;
   while (occr)
     {
       rtx insn = occr->insn;
@@ -456,13 +458,13 @@  dump_hash_table (FILE *file)
 {
   fprintf (file, "\n\nexpression hash table\n");
   fprintf (file, "size %ld, %ld elements, %f collision/search ratio\n",
-           (long) htab_size (expr_table),
-           (long) htab_elements (expr_table),
-           htab_collisions (expr_table));
-  if (htab_elements (expr_table) > 0)
+           (long) expr_table.size (),
+           (long) expr_table.elements (),
+           expr_table.collisions ());
+  if (expr_table.elements () > 0)
     {
       fprintf (file, "\n\ntable entries:\n");
-      htab_traverse (expr_table, dump_hash_table_entry, file);
+      expr_table.traverse <FILE *, dump_expr_hash_table_entry> (file);
     }
   fprintf (file, "\n");
 }
@@ -1224,13 +1226,13 @@  eliminate_partially_redundant_loads (voi
    marked for later deletion.  */

 /* This helper is called via htab_traverse.  */
-static int
-delete_redundant_insns_1 (void **slot, void *data ATTRIBUTE_UNUSED)
+int
+delete_redundant_insns_1 (expr **slot, void *data ATTRIBUTE_UNUSED)
 {
-  struct expr *expr = (struct expr *) *slot;
+  struct expr *exprs = *slot;
   struct occr *occr;

-  for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
+  for (occr = exprs->avail_occr; occr != NULL; occr = occr->next)
     {
       if (occr->deleted_p && dbg_cnt (gcse2_delete))
 	{
@@ -1252,7 +1254,7 @@  delete_redundant_insns_1 (void **slot, v
 static void
 delete_redundant_insns (void)
 {
-  htab_traverse (expr_table, delete_redundant_insns_1, NULL);
+  expr_table.traverse <void *, delete_redundant_insns_1> (NULL);
   if (dump_file)
     fprintf (dump_file, "\n");
 }
@@ -1278,7 +1280,7 @@  gcse_after_reload_main (rtx f ATTRIBUTE_
   if (dump_file)
     dump_hash_table (dump_file);

-  if (htab_elements (expr_table) > 0)
+  if (expr_table.elements () > 0)
     {
       eliminate_partially_redundant_loads ();
       delete_redundant_insns ();
Index: gcc/tree-scalar-evolution.c
===================================================================
--- gcc/tree-scalar-evolution.c	(revision 193902)
+++ gcc/tree-scalar-evolution.c	(working copy)
@@ -257,6 +257,7 @@  along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "gimple-pretty-print.h"
 #include "tree-flow.h"
 #include "cfgloop.h"
@@ -318,7 +319,7 @@  new_scev_info_str (basic_block instantia

 /* Computes a hash function for database element ELT.  */

-static hashval_t
+static inline hashval_t
 hash_scev_info (const void *elt)
 {
   return SSA_NAME_VERSION (((const struct scev_info_str *) elt)->var);
@@ -326,7 +327,7 @@  hash_scev_info (const void *elt)

 /* Compares database elements E1 and E2.  */

-static int
+static inline int
 eq_scev_info (const void *e1, const void *e2)
 {
   const struct scev_info_str *elt1 = (const struct scev_info_str *) e1;
@@ -344,6 +345,39 @@  del_scev_info (void *e)
   ggc_free (e);
 }

+/* Hashtable helpers.  */
+
+struct scev_info_hasher
+{
+  typedef scev_info_str value_type;
+  typedef scev_info_str compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+  static inline void remove (value_type *);
+};
+
+inline hashval_t
+scev_info_hasher::hash (const value_type *elt)
+{
+  return hash_scev_info (elt);
+}
+
+inline bool
+scev_info_hasher::equal (const value_type *elt1, const compare_type *elt2)
+{
+  return eq_scev_info (elt1, elt2);
+}
+
+/* Deletes database element E.  */
+
+inline void
+scev_info_hasher::remove (value_type *e)
+{
+  del_scev_info (e);
+}
+
+typedef hash_table <scev_info_hasher> scev_info_hash_table_type;
+
 /* Get the scalar evolution of VAR for INSTANTIATED_BELOW basic block.
    A first query on VAR returns chrec_not_analyzed_yet.  */

@@ -2082,14 +2116,14 @@  analyze_scalar_evolution_in_loop (struct
    INSTANTIATED_BELOW block.  */

 static tree
-get_instantiated_value (htab_t cache, basic_block instantiated_below,
-			tree version)
+get_instantiated_value (scev_info_hash_table_type cache,
+			basic_block instantiated_below, tree version)
 {
   struct scev_info_str *info, pattern;

   pattern.var = version;
   pattern.instantiated_below = instantiated_below;
-  info = (struct scev_info_str *) htab_find (cache, &pattern);
+  info = cache.find (&pattern);

   if (info)
     return info->chrec;
@@ -2101,19 +2135,19 @@  get_instantiated_value (htab_t cache, ba
    INSTANTIATED_BELOW to VAL.  */

 static void
-set_instantiated_value (htab_t cache, basic_block instantiated_below,
-			tree version, tree val)
+set_instantiated_value (scev_info_hash_table_type cache,
+			basic_block instantiated_below, tree version, tree val)
 {
   struct scev_info_str *info, pattern;
-  PTR *slot;
+  scev_info_str **slot;

   pattern.var = version;
   pattern.instantiated_below = instantiated_below;
-  slot = htab_find_slot (cache, &pattern, INSERT);
+  slot = cache.find_slot (&pattern, INSERT);

   if (!*slot)
     *slot = new_scev_info_str (instantiated_below, version);
-  info = (struct scev_info_str *) *slot;
+  info = *slot;
   info->chrec = val;
 }

@@ -2148,7 +2182,7 @@  loop_closed_phi_def (tree var)
 }

 static tree instantiate_scev_r (basic_block, struct loop *, tree, bool,
-				htab_t, int);
+				scev_info_hash_table_type, int);

 /* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
    and EVOLUTION_LOOP, that were left under a symbolic form.
@@ -2167,7 +2201,8 @@  static tree instantiate_scev_r (basic_bl
 static tree
 instantiate_scev_name (basic_block instantiate_below,
 		       struct loop *evolution_loop, tree chrec,
-		       bool fold_conversions, htab_t cache, int size_expr)
+		       bool fold_conversions, scev_info_hash_table_type cache,
+		       int size_expr)
 {
   tree res;
   struct loop *def_loop;
@@ -2259,7 +2294,8 @@  instantiate_scev_name (basic_block insta
 static tree
 instantiate_scev_poly (basic_block instantiate_below,
 		       struct loop *evolution_loop, tree chrec,
-		       bool fold_conversions, htab_t cache, int size_expr)
+		       bool fold_conversions, scev_info_hash_table_type cache,
+		       int size_expr)
 {
   tree op1;
   tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
@@ -2311,9 +2347,11 @@  instantiate_scev_poly (basic_block insta

 static tree
 instantiate_scev_binary (basic_block instantiate_below,
-			 struct loop *evolution_loop, tree chrec, enum tree_code code,
+			 struct loop *evolution_loop, tree chrec,
+			 enum tree_code code,
 			 tree type, tree c0, tree c1,
-			 bool fold_conversions, htab_t cache, int size_expr)
+			 bool fold_conversions, scev_info_hash_table_type cache,
+			 int size_expr)
 {
   tree op1;
   tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
@@ -2371,7 +2409,8 @@  instantiate_scev_binary (basic_block ins
 static tree
 instantiate_array_ref (basic_block instantiate_below,
 		       struct loop *evolution_loop, tree chrec,
-		       bool fold_conversions, htab_t cache, int size_expr)
+		       bool fold_conversions, scev_info_hash_table_type cache,
+		       int size_expr)
 {
   tree res;
   tree index = TREE_OPERAND (chrec, 1);
@@ -2408,7 +2447,8 @@  static tree
 instantiate_scev_convert (basic_block instantiate_below,
 			  struct loop *evolution_loop, tree chrec,
 			  tree type, tree op,
-			  bool fold_conversions, htab_t cache, int size_expr)
+			  bool fold_conversions,
+			  scev_info_hash_table_type cache, int size_expr)
 {
   tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, op,
 				 fold_conversions, cache, size_expr);
@@ -2455,7 +2495,8 @@  static tree
 instantiate_scev_not (basic_block instantiate_below,
 		      struct loop *evolution_loop, tree chrec,
 		      enum tree_code code, tree type, tree op,
-		      bool fold_conversions, htab_t cache, int size_expr)
+		      bool fold_conversions, scev_info_hash_table_type cache,
+		      int size_expr)
 {
   tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, op,
 				 fold_conversions, cache, size_expr);
@@ -2502,7 +2543,8 @@  instantiate_scev_not (basic_block instan
 static tree
 instantiate_scev_3 (basic_block instantiate_below,
 		    struct loop *evolution_loop, tree chrec,
-		    bool fold_conversions, htab_t cache, int size_expr)
+		    bool fold_conversions, scev_info_hash_table_type cache,
+		    int size_expr)
 {
   tree op1, op2;
   tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
@@ -2549,7 +2591,8 @@  instantiate_scev_3 (basic_block instanti
 static tree
 instantiate_scev_2 (basic_block instantiate_below,
 		    struct loop *evolution_loop, tree chrec,
-		    bool fold_conversions, htab_t cache, int size_expr)
+		    bool fold_conversions, scev_info_hash_table_type cache,
+		    int size_expr)
 {
   tree op1;
   tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
@@ -2588,7 +2631,8 @@  instantiate_scev_2 (basic_block instanti
 static tree
 instantiate_scev_1 (basic_block instantiate_below,
 		    struct loop *evolution_loop, tree chrec,
-		    bool fold_conversions, htab_t cache, int size_expr)
+		    bool fold_conversions, scev_info_hash_table_type cache,
+		    int size_expr)
 {
   tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
 				 TREE_OPERAND (chrec, 0),
@@ -2620,7 +2664,8 @@  instantiate_scev_1 (basic_block instanti
 static tree
 instantiate_scev_r (basic_block instantiate_below,
 		    struct loop *evolution_loop, tree chrec,
-		    bool fold_conversions, htab_t cache, int size_expr)
+		    bool fold_conversions, scev_info_hash_table_type cache,
+		    int size_expr)
 {
   /* Give up if the expression is larger than the MAX that we allow.  */
   if (size_expr++ > PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE))
@@ -2717,7 +2762,8 @@  instantiate_scev (basic_block instantiat
 		  tree chrec)
 {
   tree res;
-  htab_t cache = htab_create (10, hash_scev_info, eq_scev_info, del_scev_info);
+  scev_info_hash_table_type cache;
+  cache.create (10);

   if (dump_file && (dump_flags & TDF_SCEV))
     {
@@ -2739,7 +2785,7 @@  instantiate_scev (basic_block instantiat
       fprintf (dump_file, "))\n");
     }

-  htab_delete (cache);
+  cache.dispose ();

   return res;
 }
@@ -2752,10 +2798,11 @@  instantiate_scev (basic_block instantiat
 tree
 resolve_mixers (struct loop *loop, tree chrec)
 {
-  htab_t cache = htab_create (10, hash_scev_info, eq_scev_info, del_scev_info);
+  scev_info_hash_table_type cache;
+  cache.create (10);
   tree ret = instantiate_scev_r (block_before_loop (loop), loop, chrec, true,
 				 cache, 0);
-  htab_delete (cache);
+  cache.dispose ();
   return ret;
 }

Index: gcc/graphds.h
===================================================================
--- gcc/graphds.h	(revision 193902)
+++ gcc/graphds.h	(working copy)
@@ -47,7 +47,6 @@  struct graph
   int n_vertices;	/* Number of vertices.  */
   struct vertex *vertices;
 			/* The vertices.  */
-  htab_t indices;	/* Fast lookup for indices.  */
 };

 struct graph *new_graph (int);
Index: gcc/haifa-sched.c
===================================================================
--- gcc/haifa-sched.c	(revision 193902)
+++ gcc/haifa-sched.c	(working copy)
@@ -147,7 +147,7 @@  along with GCC; see the file COPYING3.
 #include "cfgloop.h"
 #include "ira.h"
 #include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
-#include "hashtab.h"
+#include "hash-table.h"
 #include "dumpfile.h"

 #ifdef INSN_SCHEDULING
@@ -583,22 +583,72 @@  struct delay_pair
   int stages;
 };

+/* Helpers for delay hashing.  */
+
+struct delay_i1_hasher : typed_noop_remove <delay_pair>
+{
+  typedef delay_pair value_type;
+  typedef void compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Returns a hash value for X, based on hashing just I1.  */
+
+inline hashval_t
+delay_i1_hasher::hash (const value_type *x)
+{
+  return htab_hash_pointer (x->i1);
+}
+
+/* Return true if I1 of pair X is the same as that of pair Y.  */
+
+inline bool
+delay_i1_hasher::equal (const value_type *x, const compare_type *y)
+{
+  return x->i1 == y;
+}
+
+struct delay_i2_hasher : typed_free_remove <delay_pair>
+{
+  typedef delay_pair value_type;
+  typedef void compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Returns a hash value for X, based on hashing just I2.  */
+
+inline hashval_t
+delay_i2_hasher::hash (const value_type *x)
+{
+  return htab_hash_pointer (x->i2);
+}
+
+/* Return true if I2 of pair X is the same as that of pair Y.  */
+
+inline bool
+delay_i2_hasher::equal (const value_type *x, const compare_type *y)
+{
+  return x->i2 == y;
+}
+
 /* Two hash tables to record delay_pairs, one indexed by I1 and the other
    indexed by I2.  */
-static htab_t delay_htab;
-static htab_t delay_htab_i2;
+static hash_table <delay_i1_hasher> delay_htab;
+static hash_table <delay_i2_hasher> delay_htab_i2;

 /* Called through htab_traverse.  Walk the hashtable using I2 as
    index, and delete all elements involving an UID higher than
    that pointed to by *DATA.  */
-static int
-htab_i2_traverse (void **slot, void *data)
+int
+haifa_htab_i2_traverse (delay_pair **slot, int *data)
 {
-  int maxuid = *(int *)data;
-  struct delay_pair *p = *(struct delay_pair **)slot;
+  int maxuid = *data;
+  struct delay_pair *p = *slot;
   if (INSN_UID (p->i2) >= maxuid || INSN_UID (p->i1) >= maxuid)
     {
-      htab_clear_slot (delay_htab_i2, slot);
+      delay_htab_i2.clear_slot (slot);
     }
   return 1;
 }
@@ -606,16 +656,15 @@  htab_i2_traverse (void **slot, void *dat
 /* Called through htab_traverse.  Walk the hashtable using I2 as
    index, and delete all elements involving an UID higher than
    that pointed to by *DATA.  */
-static int
-htab_i1_traverse (void **slot, void *data)
+int
+haifa_htab_i1_traverse (delay_pair **pslot, int *data)
 {
-  int maxuid = *(int *)data;
-  struct delay_pair **pslot = (struct delay_pair **)slot;
+  int maxuid = *data;
   struct delay_pair *p, *first, **pprev;

   if (INSN_UID ((*pslot)->i1) >= maxuid)
     {
-      htab_clear_slot (delay_htab, slot);
+      delay_htab.clear_slot (pslot);
       return 1;
     }
   pprev = &first;
@@ -629,7 +678,7 @@  htab_i1_traverse (void **slot, void *dat
     }
   *pprev = NULL;
   if (first == NULL)
-    htab_clear_slot (delay_htab, slot);
+    delay_htab.clear_slot (pslot);
   else
     *pslot = first;
   return 1;
@@ -640,38 +689,8 @@  htab_i1_traverse (void **slot, void *dat
 void
 discard_delay_pairs_above (int max_uid)
 {
-  htab_traverse (delay_htab, htab_i1_traverse, &max_uid);
-  htab_traverse (delay_htab_i2, htab_i2_traverse, &max_uid);
-}
-
-/* Returns a hash value for X (which really is a delay_pair), based on
-   hashing just I1.  */
-static hashval_t
-delay_hash_i1 (const void *x)
-{
-  return htab_hash_pointer (((const struct delay_pair *) x)->i1);
-}
-
-/* Returns a hash value for X (which really is a delay_pair), based on
-   hashing just I2.  */
-static hashval_t
-delay_hash_i2 (const void *x)
-{
-  return htab_hash_pointer (((const struct delay_pair *) x)->i2);
-}
-
-/* Return nonzero if I1 of pair X is the same as that of pair Y.  */
-static int
-delay_i1_eq (const void *x, const void *y)
-{
-  return ((const struct delay_pair *) x)->i1 == y;
-}
-
-/* Return nonzero if I2 of pair X is the same as that of pair Y.  */
-static int
-delay_i2_eq (const void *x, const void *y)
-{
-  return ((const struct delay_pair *) x)->i2 == y;
+  delay_htab.traverse <int *, haifa_htab_i1_traverse> (&max_uid);
+  delay_htab_i2.traverse <int *, haifa_htab_i2_traverse> (&max_uid);
 }

 /* This function can be called by a port just before it starts the final
@@ -701,19 +720,15 @@  record_delay_slot_pair (rtx i1, rtx i2,
   p->cycles = cycles;
   p->stages = stages;

-  if (!delay_htab)
+  if (!delay_htab.is_created ())
     {
-      delay_htab = htab_create (10, delay_hash_i1, delay_i1_eq, NULL);
-      delay_htab_i2 = htab_create (10, delay_hash_i2, delay_i2_eq, free);
+      delay_htab.create (10);
+      delay_htab_i2.create (10);
     }
-  slot = ((struct delay_pair **)
-	  htab_find_slot_with_hash (delay_htab, i1, htab_hash_pointer (i1),
-				    INSERT));
+  slot = delay_htab.find_slot_with_hash (i1, htab_hash_pointer (i1), INSERT);
   p->next_same_i1 = *slot;
   *slot = p;
-  slot = ((struct delay_pair **)
-	  htab_find_slot_with_hash (delay_htab_i2, i2, htab_hash_pointer (i2),
-				    INSERT));
+  slot = delay_htab_i2.find_slot_with_hash (i2, htab_hash_pointer
(i2), INSERT);
   *slot = p;
 }

@@ -724,12 +739,10 @@  real_insn_for_shadow (rtx insn)
 {
   struct delay_pair *pair;

-  if (delay_htab == NULL)
+  if (!delay_htab.is_created ())
     return NULL_RTX;

-  pair
-    = (struct delay_pair *)htab_find_with_hash (delay_htab_i2, insn,
-						htab_hash_pointer (insn));
+  pair = delay_htab_i2.find_with_hash (insn, htab_hash_pointer (insn));
   if (!pair || pair->stages > 0)
     return NULL_RTX;
   return pair->i1;
@@ -757,12 +770,10 @@  add_delay_dependencies (rtx insn)
   sd_iterator_def sd_it;
   dep_t dep;

-  if (!delay_htab)
+  if (!delay_htab.is_created ())
     return;

-  pair
-    = (struct delay_pair *)htab_find_with_hash (delay_htab_i2, insn,
-						htab_hash_pointer (insn));
+  pair = delay_htab_i2.find_with_hash (insn, htab_hash_pointer (insn));
   if (!pair)
     return;
   add_dependence (insn, pair->i1, REG_DEP_ANTI);
@@ -773,8 +784,7 @@  add_delay_dependencies (rtx insn)
     {
       rtx pro = DEP_PRO (dep);
       struct delay_pair *other_pair
-	= (struct delay_pair *)htab_find_with_hash (delay_htab_i2, pro,
-						    htab_hash_pointer (pro));
+	= delay_htab_i2.find_with_hash (pro, htab_hash_pointer (pro));
       if (!other_pair || other_pair->stages)
 	continue;
       if (pair_delay (other_pair) >= pair_delay (pair))
@@ -1397,12 +1407,11 @@  dep_cost_1 (dep_t link, dw_t dw)
   if (DEP_COST (link) != UNKNOWN_DEP_COST)
     return DEP_COST (link);

-  if (delay_htab)
+  if (delay_htab.is_created ())
     {
       struct delay_pair *delay_entry;
       delay_entry
-	= (struct delay_pair *)htab_find_with_hash (delay_htab_i2, used,
-						    htab_hash_pointer (used));
+	= delay_htab_i2.find_with_hash (used, htab_hash_pointer (used));
       if (delay_entry)
 	{
 	  if (delay_entry->i1 == insn)
@@ -5734,12 +5743,12 @@  prune_ready_list (state_t temp_state, bo
 	    {
 	      int delay_cost = 0;

-	      if (delay_htab)
+	      if (delay_htab.is_created ())
 		{
 		  struct delay_pair *delay_entry;
 		  delay_entry
-		    = (struct delay_pair *)htab_find_with_hash (delay_htab, insn,
-								htab_hash_pointer (insn));
+		    = delay_htab.find_with_hash (insn,
+						 htab_hash_pointer (insn));
 		  while (delay_entry && delay_cost == 0)
 		    {
 		      delay_cost = estimate_shadow_tick (delay_entry);
@@ -6197,14 +6206,13 @@  schedule_block (basic_block *target_bb,
 	      goto restart_choose_ready;
 	    }

-	  if (delay_htab)
+	  if (delay_htab.is_created ())
 	    {
 	      /* If this insn is the first part of a delay-slot pair, record a
 		 backtrack point.  */
 	      struct delay_pair *delay_entry;
 	      delay_entry
-		= (struct delay_pair *)htab_find_with_hash (delay_htab, insn,
-							    htab_hash_pointer (insn));
+		= delay_htab.find_with_hash (insn, htab_hash_pointer (insn));
 	      if (delay_entry)
 		{
 		  save_backtrack_point (delay_entry, ls);
@@ -6769,10 +6777,10 @@  sched_finish (void)
 void
 free_delay_pairs (void)
 {
-  if (delay_htab)
+  if (delay_htab.is_created ())
     {
-      htab_empty (delay_htab);
-      htab_empty (delay_htab_i2);
+      delay_htab.empty ();
+      delay_htab_i2.empty ();
     }
 }

Index: gcc/ira-color.c
===================================================================
--- gcc/ira-color.c	(revision 193902)
+++ gcc/ira-color.c	(working copy)
@@ -30,6 +30,7 @@  along with GCC; see the file COPYING3.
 #include "flags.h"
 #include "sbitmap.h"
 #include "bitmap.h"
+#include "hash-table.h"
 #include "hard-reg-set.h"
 #include "basic-block.h"
 #include "expr.h"
@@ -174,33 +175,36 @@  static vec<ira_allocno_t> allocno_stack_
 /* Vector of unique allocno hard registers.  */
 static vec<allocno_hard_regs_t> allocno_hard_regs_vec;

-/* Returns hash value for allocno hard registers V.  */
-static hashval_t
-allocno_hard_regs_hash (const void *v)
+struct allocno_hard_regs_hasher : typed_noop_remove <allocno_hard_regs>
 {
-  const struct allocno_hard_regs *hv = (const struct allocno_hard_regs *) v;
+  typedef allocno_hard_regs value_type;
+  typedef allocno_hard_regs compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};

+/* Returns hash value for allocno hard registers V.  */
+inline hashval_t
+allocno_hard_regs_hasher::hash (const value_type *hv)
+{
   return iterative_hash (&hv->set, sizeof (HARD_REG_SET), 0);
 }

 /* Compares allocno hard registers V1 and V2.  */
-static int
-allocno_hard_regs_eq (const void *v1, const void *v2)
+inline bool
+allocno_hard_regs_hasher::equal (const value_type *hv1, const
compare_type *hv2)
 {
-  const struct allocno_hard_regs *hv1 = (const struct allocno_hard_regs *) v1;
-  const struct allocno_hard_regs *hv2 = (const struct allocno_hard_regs *) v2;
-
   return hard_reg_set_equal_p (hv1->set, hv2->set);
 }

 /* Hash table of unique allocno hard registers.  */
-static htab_t allocno_hard_regs_htab;
+static hash_table <allocno_hard_regs_hasher> allocno_hard_regs_htab;

 /* Return allocno hard registers in the hash table equal to HV.  */
 static allocno_hard_regs_t
 find_hard_regs (allocno_hard_regs_t hv)
 {
-  return (allocno_hard_regs_t) htab_find (allocno_hard_regs_htab, hv);
+  return allocno_hard_regs_htab.find (hv);
 }

 /* Insert allocno hard registers HV in the hash table (if it is not
@@ -208,11 +212,11 @@  find_hard_regs (allocno_hard_regs_t hv)
 static allocno_hard_regs_t
 insert_hard_regs (allocno_hard_regs_t hv)
 {
-  PTR *slot = htab_find_slot (allocno_hard_regs_htab, hv, INSERT);
+  allocno_hard_regs **slot = allocno_hard_regs_htab.find_slot (hv, INSERT);

   if (*slot == NULL)
     *slot = hv;
-  return (allocno_hard_regs_t) *slot;
+  return *slot;
 }

 /* Initialize data concerning allocno hard registers.  */
@@ -220,8 +224,7 @@  static void
 init_allocno_hard_regs (void)
 {
   allocno_hard_regs_vec.create (200);
-  allocno_hard_regs_htab
-    = htab_create (200, allocno_hard_regs_hash, allocno_hard_regs_eq, NULL);
+  allocno_hard_regs_htab.create (200);
 }

 /* Add (or update info about) allocno hard registers with SET and
@@ -259,7 +262,7 @@  finish_allocno_hard_regs (void)
        allocno_hard_regs_vec.iterate (i, &hv);
        i++)
     ira_free (hv);
-  htab_delete (allocno_hard_regs_htab);
+  allocno_hard_regs_htab.dispose ();
   allocno_hard_regs_vec.release ();
 }

Index: gcc/tree-ssa-dom.c
===================================================================
--- gcc/tree-ssa-dom.c	(revision 193902)
+++ gcc/tree-ssa-dom.c	(working copy)
@@ -22,6 +22,7 @@  along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "tm.h"
 #include "tree.h"
 #include "flags.h"
@@ -102,15 +103,6 @@  struct edge_info
   vec<cond_equivalence> cond_equivalences;
 };

-/* Hash table with expressions made available during the renaming process.
-   When an assignment of the form X_i = EXPR is found, the statement is
-   stored in this table.  If the same expression EXPR is later found on the
-   RHS of another statement, it is replaced with X_i (thus performing
-   global redundancy elimination).  Similarly as we pass through conditionals
-   we record the conditional itself as having either a true or false value
-   in this table.  */
-static htab_t avail_exprs;
-
 /* Stack of available expressions in AVAIL_EXPRs.  Each block pushes any
    expressions it enters into the hash table along with a marker entry
    (null).  When we finish processing the block, we pop off entries and
@@ -141,6 +133,81 @@  struct expr_hash_elt
   struct expr_hash_elt *stamp;
 };

+/* Hashtable helpers.  */
+
+static bool hashable_expr_equal_p (const struct hashable_expr *,
+				   const struct hashable_expr *);
+static void free_expr_hash_elt (void *);
+
+struct expr_elt_hasher
+{
+  typedef expr_hash_elt value_type;
+  typedef expr_hash_elt compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+  static inline void remove (value_type *);
+};
+
+inline hashval_t
+expr_elt_hasher::hash (const value_type *p)
+{
+  return p->hash;
+}
+
+inline bool
+expr_elt_hasher::equal (const value_type *p1, const compare_type *p2)
+{
+  gimple stmt1 = p1->stmt;
+  const struct hashable_expr *expr1 = &p1->expr;
+  const struct expr_hash_elt *stamp1 = p1->stamp;
+  gimple stmt2 = p2->stmt;
+  const struct hashable_expr *expr2 = &p2->expr;
+  const struct expr_hash_elt *stamp2 = p2->stamp;
+
+  /* This case should apply only when removing entries from the table.  */
+  if (stamp1 == stamp2)
+    return true;
+
+  /* FIXME tuples:
+     We add stmts to a hash table and them modify them. To detect the case
+     that we modify a stmt and then search for it, we assume that the hash
+     is always modified by that change.
+     We have to fully check why this doesn't happen on trunk or rewrite
+     this in a more  reliable (and easier to understand) way. */
+  if (((const struct expr_hash_elt *)p1)->hash
+      != ((const struct expr_hash_elt *)p2)->hash)
+    return false;
+
+  /* In case of a collision, both RHS have to be identical and have the
+     same VUSE operands.  */
+  if (hashable_expr_equal_p (expr1, expr2)
+      && types_compatible_p (expr1->type, expr2->type))
+    {
+      /* Note that STMT1 and/or STMT2 may be NULL.  */
+      return ((stmt1 ? gimple_vuse (stmt1) : NULL_TREE)
+	      == (stmt2 ? gimple_vuse (stmt2) : NULL_TREE));
+    }
+
+  return false;
+}
+
+/* Delete an expr_hash_elt and reclaim its storage.  */
+
+inline void
+expr_elt_hasher::remove (value_type *element)
+{
+  free_expr_hash_elt (element);
+}
+
+/* Hash table with expressions made available during the renaming process.
+   When an assignment of the form X_i = EXPR is found, the statement is
+   stored in this table.  If the same expression EXPR is later found on the
+   RHS of another statement, it is replaced with X_i (thus performing
+   global redundancy elimination).  Similarly as we pass through conditionals
+   we record the conditional itself as having either a true or false value
+   in this table.  */
+static hash_table <expr_elt_hasher> avail_exprs;
+
 /* Stack of dest,src pairs that need to be restored during finalization.

    A NULL entry is used to mark the end of pairs which need to be
@@ -170,9 +237,7 @@  static struct opt_stats_d opt_stats;
 static void optimize_stmt (basic_block, gimple_stmt_iterator);
 static tree lookup_avail_expr (gimple, bool);
 static hashval_t avail_expr_hash (const void *);
-static hashval_t real_avail_expr_hash (const void *);
-static int avail_expr_eq (const void *, const void *);
-static void htab_statistics (FILE *, htab_t);
+static void htab_statistics (FILE *, hash_table <expr_elt_hasher>);
 static void record_cond (cond_equivalence *);
 static void record_const_or_copy (tree, tree);
 static void record_equality (tree, tree);
@@ -723,7 +788,7 @@  tree_ssa_dominator_optimize (void)
   memset (&opt_stats, 0, sizeof (opt_stats));

   /* Create our hash tables.  */
-  avail_exprs = htab_create (1024, real_avail_expr_hash,
avail_expr_eq, free_expr_hash_elt);
+  avail_exprs.create (1024);
   avail_exprs_stack.create (20);
   const_and_copies_stack.create (20);
   need_eh_cleanup = BITMAP_ALLOC (NULL);
@@ -831,7 +896,7 @@  tree_ssa_dominator_optimize (void)
   loop_optimizer_finalize ();

   /* Delete our main hashtable.  */
-  htab_delete (avail_exprs);
+  avail_exprs.dispose ();

   /* And finalize the dominator walker.  */
   fini_walk_dominator_tree (&walk_data);
@@ -936,7 +1001,7 @@  remove_local_expressions_from_table (voi
   while (avail_exprs_stack.length () > 0)
     {
       expr_hash_elt_t victim = avail_exprs_stack.pop ();
-      void **slot;
+      expr_hash_elt **slot;

       if (victim == NULL)
 	break;
@@ -950,10 +1015,9 @@  remove_local_expressions_from_table (voi
           print_expr_hash_elt (dump_file, victim);
         }

-      slot = htab_find_slot_with_hash (avail_exprs,
-				       victim, victim->hash, NO_INSERT);
-      gcc_assert (slot && *slot == (void *) victim);
-      htab_clear_slot (avail_exprs, slot);
+      slot = avail_exprs.find_slot_with_hash (victim, victim->hash, NO_INSERT);
+      gcc_assert (slot && *slot == victim);
+      avail_exprs.clear_slot (slot);
     }
 }

@@ -1171,12 +1235,12 @@  debug_dominator_optimization_stats (void
 /* Dump statistics for the hash table HTAB.  */

 static void
-htab_statistics (FILE *file, htab_t htab)
+htab_statistics (FILE *file, hash_table <expr_elt_hasher> htab)
 {
   fprintf (file, "size %ld, %ld elements, %f collision/search ratio\n",
-	   (long) htab_size (htab),
-	   (long) htab_elements (htab),
-	   htab_collisions (htab));
+	   (long) htab.size (),
+	   (long) htab.elements (),
+	   htab.collisions ());
 }


@@ -1188,15 +1252,14 @@  static void
 record_cond (cond_equivalence *p)
 {
   struct expr_hash_elt *element = XCNEW (struct expr_hash_elt);
-  void **slot;
+  expr_hash_elt **slot;

   initialize_hash_element_from_expr (&p->cond, p->value, element);

-  slot = htab_find_slot_with_hash (avail_exprs, (void *)element,
-				   element->hash, INSERT);
+  slot = avail_exprs.find_slot_with_hash (element, element->hash, INSERT);
   if (*slot == NULL)
     {
-      *slot = (void *) element;
+      *slot = element;

       if (dump_file && (dump_flags & TDF_DETAILS))
         {
@@ -2372,7 +2435,7 @@  optimize_stmt (basic_block bb, gimple_st
 static tree
 lookup_avail_expr (gimple stmt, bool insert)
 {
-  void **slot;
+  expr_hash_elt **slot;
   tree lhs;
   tree temp;
   struct expr_hash_elt element;
@@ -2400,8 +2463,8 @@  lookup_avail_expr (gimple stmt, bool ins
     return NULL_TREE;

   /* Finally try to find the expression in the main expression hash table.  */
-  slot = htab_find_slot_with_hash (avail_exprs, &element, element.hash,
-				   (insert ? INSERT : NO_INSERT));
+  slot = avail_exprs.find_slot_with_hash (&element, element.hash,
+					  (insert ? INSERT : NO_INSERT));
   if (slot == NULL)
     {
       free_expr_hash_elt_contents (&element);
@@ -2412,7 +2475,7 @@  lookup_avail_expr (gimple stmt, bool ins
       struct expr_hash_elt *element2 = XNEW (struct expr_hash_elt);
       *element2 = element;
       element2->stamp = element2;
-      *slot = (void *) element2;
+      *slot = element2;

       if (dump_file && (dump_flags & TDF_DETAILS))
         {
@@ -2479,49 +2542,6 @@  avail_expr_hash (const void *p)
   return val;
 }

-static hashval_t
-real_avail_expr_hash (const void *p)
-{
-  return ((const struct expr_hash_elt *)p)->hash;
-}
-
-static int
-avail_expr_eq (const void *p1, const void *p2)
-{
-  gimple stmt1 = ((const struct expr_hash_elt *)p1)->stmt;
-  const struct hashable_expr *expr1 = &((const struct expr_hash_elt
*)p1)->expr;
-  const struct expr_hash_elt *stamp1 = ((const struct expr_hash_elt
*)p1)->stamp;
-  gimple stmt2 = ((const struct expr_hash_elt *)p2)->stmt;
-  const struct hashable_expr *expr2 = &((const struct expr_hash_elt
*)p2)->expr;
-  const struct expr_hash_elt *stamp2 = ((const struct expr_hash_elt
*)p2)->stamp;
-
-  /* This case should apply only when removing entries from the table.  */
-  if (stamp1 == stamp2)
-    return true;
-
-  /* FIXME tuples:
-     We add stmts to a hash table and them modify them. To detect the case
-     that we modify a stmt and then search for it, we assume that the hash
-     is always modified by that change.
-     We have to fully check why this doesn't happen on trunk or rewrite
-     this in a more  reliable (and easier to understand) way. */
-  if (((const struct expr_hash_elt *)p1)->hash
-      != ((const struct expr_hash_elt *)p2)->hash)
-    return false;
-
-  /* In case of a collision, both RHS have to be identical and have the
-     same VUSE operands.  */
-  if (hashable_expr_equal_p (expr1, expr2)
-      && types_compatible_p (expr1->type, expr2->type))
-    {
-      /* Note that STMT1 and/or STMT2 may be NULL.  */
-      return ((stmt1 ? gimple_vuse (stmt1) : NULL_TREE)
-	      == (stmt2 ? gimple_vuse (stmt2) : NULL_TREE));
-    }
-
-  return false;
-}
-
 /* PHI-ONLY copy and constant propagation.  This pass is meant to clean
    up degenerate PHIs created by or exposed by jump threading.  */

Index: gcc/dse.c
===================================================================
--- gcc/dse.c	(revision 193902)
+++ gcc/dse.c	(working copy)
@@ -573,20 +573,6 @@  static alloc_pool deferred_change_pool;

 static deferred_change_t deferred_change_list = NULL;

-/* This are used to hold the alias sets of spill variables.  Since
-   these are never aliased and there may be a lot of them, it makes
-   sense to treat them specially.  This bitvector is only allocated in
-   calls from dse_record_singleton_alias_set which currently is only
-   made during reload1.  So when dse is called before reload this
-   mechanism does nothing.  */
-
-static bitmap clear_alias_sets = NULL;
-
-/* The set of clear_alias_sets that have been disqualified because
-   there are loads or stores using a different mode than the alias set
-   was registered with.  */
-static bitmap disqualified_clear_alias_sets = NULL;
-
 /* The group that holds all of the clear_alias_sets.  */
 static group_info_t clear_alias_group;

@@ -600,8 +586,6 @@  struct clear_alias_mode_holder
   enum machine_mode mode;
 };

-static alloc_pool clear_alias_mode_pool;
-
 /* This is true except if cfun->stdarg -- i.e. we cannot do
    this for vararg functions because they play games with the frame.  */
 static bool stores_off_frame_dead_at_return;
@@ -789,10 +773,7 @@  dse_step0 (void)

   init_alias_analysis ();

-  if (clear_alias_sets)
-    clear_alias_group = get_group_info (NULL);
-  else
-    clear_alias_group = NULL;
+  clear_alias_group = NULL;
 }


@@ -1190,39 +1171,6 @@  canon_address (rtx mem,
   rtx expanded_address, address;
   int expanded;

-  /* Make sure that cselib is has initialized all of the operands of
-     the address before asking it to do the subst.  */
-
-  if (clear_alias_sets)
-    {
-      /* If this is a spill, do not do any further processing.  */
-      alias_set_type alias_set = MEM_ALIAS_SET (mem);
-      if (dump_file)
-	fprintf (dump_file, "found alias set %d\n", (int) alias_set);
-      if (bitmap_bit_p (clear_alias_sets, alias_set))
-	{
-	  struct clear_alias_mode_holder *entry
-	    = clear_alias_set_lookup (alias_set);
-
-	  /* If the modes do not match, we cannot process this set.  */
-	  if (entry->mode != GET_MODE (mem))
-	    {
-	      if (dump_file)
-		fprintf (dump_file,
-			 "disqualifying alias set %d, (%s) != (%s)\n",
-			 (int) alias_set, GET_MODE_NAME (entry->mode),
-			 GET_MODE_NAME (GET_MODE (mem)));
-
-	      bitmap_set_bit (disqualified_clear_alias_sets, alias_set);
-	      return false;
-	    }
-
-	  *alias_set_out = alias_set;
-	  *group_id = clear_alias_group->id;
-	  return true;
-	}
-    }
-
   *alias_set_out = 0;

   cselib_lookup (mem_address, address_mode, 1, GET_MODE (mem));
@@ -2999,47 +2947,6 @@  dse_step2_nospill (void)
 }


-/* Init the offset tables for the spill case.  */
-
-static bool
-dse_step2_spill (void)
-{
-  unsigned int j;
-  group_info_t group = clear_alias_group;
-  bitmap_iterator bi;
-
-  /* Position 0 is unused because 0 is used in the maps to mean
-     unused.  */
-  current_position = 1;
-
-  if (dump_file)
-    {
-      bitmap_print (dump_file, clear_alias_sets,
-		    "clear alias sets              ", "\n");
-      bitmap_print (dump_file, disqualified_clear_alias_sets,
-		    "disqualified clear alias sets ", "\n");
-    }
-
-  memset (group->offset_map_n, 0, sizeof(int) * group->offset_map_size_n);
-  memset (group->offset_map_p, 0, sizeof(int) * group->offset_map_size_p);
-  bitmap_clear (group->group_kill);
-
-  /* Remove the disqualified positions from the store2_p set.  */
-  bitmap_and_compl_into (group->store2_p, disqualified_clear_alias_sets);
-
-  /* We do not need to process the store2_n set because
-     alias_sets are always positive.  */
-  EXECUTE_IF_SET_IN_BITMAP (group->store2_p, 0, j, bi)
-    {
-      bitmap_set_bit (group->group_kill, current_position);
-      group->offset_map_p[j] = current_position++;
-      group->process_globally = true;
-    }
-
-  return current_position != 1;
-}
-
-
 
 /*----------------------------------------------------------------------------
   Third step.
@@ -3696,72 +3603,6 @@  dse_step5_nospill (void)
 }


-static void
-dse_step5_spill (void)
-{
-  basic_block bb;
-  FOR_EACH_BB (bb)
-    {
-      bb_info_t bb_info = bb_table[bb->index];
-      insn_info_t insn_info = bb_info->last_insn;
-      bitmap v = bb_info->out;
-
-      while (insn_info)
-	{
-	  bool deleted = false;
-	  /* There may have been code deleted by the dce pass run before
-	     this phase.  */
-	  if (insn_info->insn
-	      && INSN_P (insn_info->insn)
-	      && (!insn_info->cannot_delete)
-	      && (!bitmap_empty_p (v)))
-	    {
-	      /* Try to delete the current insn.  */
-	      store_info_t store_info = insn_info->store_rec;
-	      deleted = true;
-
-	      while (store_info)
-		{
-		  if (store_info->alias_set)
-		    {
-		      int index = get_bitmap_index (clear_alias_group,
-						    store_info->alias_set);
-		      if (index == 0 || !bitmap_bit_p (v, index))
-			{
-			  deleted = false;
-			  break;
-			}
-		    }
-		  else
-		    deleted = false;
-		  store_info = store_info->next;
-		}
-	      if (deleted && dbg_cnt (dse)
-		  && check_for_inc_dec_1 (insn_info))
-		{
-		  if (dump_file)
-		    fprintf (dump_file, "Spill deleting insn %d\n",
-			     INSN_UID (insn_info->insn));
-		  delete_insn (insn_info->insn);
-		  spill_deleted++;
-		  insn_info->insn = NULL;
-		}
-	    }
-
-	  if (insn_info->insn
-	      && INSN_P (insn_info->insn)
-	      && (!deleted))
-	    {
-	      scan_stores_spill (insn_info->store_rec, v, NULL);
-	      scan_reads_spill (insn_info->read_rec, v, NULL);
-	    }
-
-	  insn_info = insn_info->prev_insn;
-	}
-    }
-}
-
-
 
 /*----------------------------------------------------------------------------
    Sixth step.
@@ -3825,14 +3666,6 @@  dse_step7 (void)
   bitmap_obstack_release (&dse_bitmap_obstack);
   obstack_free (&dse_obstack, NULL);

-  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);
-    }
-
   end_alias_analysis ();
   free (bb_table);
   rtx_group_table.dispose ();
@@ -3858,8 +3691,6 @@  dse_step7 (void)
 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
@@ -3874,7 +3705,6 @@  rest_of_handle_dse (void)
     {
       df_set_flags (DF_LR_RUN_DCE);
       df_analyze ();
-      did_global = true;
       if (dump_file)
 	fprintf (dump_file, "doing global processing\n");
       dse_step3 (false);
@@ -3882,26 +3712,6 @@  rest_of_handle_dse (void)
       dse_step5_nospill ();
     }

-  /* For the instance of dse that runs after reload, we make a special
-     pass to process the spills.  These are special in that they are
-     totally transparent, i.e, there is no aliasing issues that need
-     to be considered.  This means that the wild reads that kill
-     everything else do not apply here.  */
-  if (clear_alias_sets && dse_step2_spill ())
-    {
-      if (!did_global)
-	{
-	  df_set_flags (DF_LR_RUN_DCE);
-	  df_analyze ();
-	}
-      did_global = true;
-      if (dump_file)
-	fprintf (dump_file, "doing global spill processing\n");
-      dse_step3 (true);
-      dse_step4 ();
-      dse_step5_spill ();
-    }
-
   dse_step6 ();
   dse_step7 ();

Index: gcc/gimple-ssa-strength-reduction.c
===================================================================
--- gcc/gimple-ssa-strength-reduction.c	(revision 193902)
+++ gcc/gimple-ssa-strength-reduction.c	(working copy)
@@ -55,6 +55,7 @@  along with GCC; see the file COPYING3.
 #include "pointer-set.h"
 #include "expmed.h"
 #include "params.h"
+#include "hash-table.h"
 
 /* Information about a strength reduction candidate.  Each statement
    in the candidate table represents an expression of one of the
@@ -287,9 +288,6 @@  static struct pointer_map_t *stmt_cand_m
 /* Obstack for candidates.  */
 static struct obstack cand_obstack;

-/* Hash table embodying a mapping from base exprs to chains of candidates.  */
-static htab_t base_cand_map;
-
 /* Obstack for candidate chains.  */
 static struct obstack chain_obstack;

@@ -311,32 +309,31 @@  lookup_cand (cand_idx idx)
   return cand_vec[idx - 1];
 }

-/* Callback to produce a hash value for a candidate chain header.  */
+/* Helper for hashing a candidate chain header.  */

-static hashval_t
-base_cand_hash (const void *p)
+struct cand_chain_hasher : typed_noop_remove <cand_chain>
 {
-  tree base_expr = ((const_cand_chain_t) p)->base_expr;
-  return iterative_hash_expr (base_expr, 0);
-}
-
-/* Callback when an element is removed from the hash table.
-   We never remove entries until the entire table is released.  */
+  typedef cand_chain value_type;
+  typedef cand_chain compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};

-static void
-base_cand_free (void *p ATTRIBUTE_UNUSED)
+inline hashval_t
+cand_chain_hasher::hash (const value_type *p)
 {
+  tree base_expr = p->base_expr;
+  return iterative_hash_expr (base_expr, 0);
 }

-/* Callback to return true if two candidate chain headers are equal.  */
-
-static int
-base_cand_eq (const void *p1, const void *p2)
+inline bool
+cand_chain_hasher::equal (const value_type *chain1, const compare_type *chain2)
 {
-  const_cand_chain_t const chain1 = (const_cand_chain_t) p1;
-  const_cand_chain_t const chain2 = (const_cand_chain_t) p2;
   return operand_equal_p (chain1->base_expr, chain2->base_expr, 0);
 }
+
+/* Hash table embodying a mapping from base exprs to chains of candidates.  */
+static hash_table <cand_chain_hasher> base_cand_map;
 
 /* Use the base expr from candidate C to look for possible candidates
    that can serve as a basis for C.  Each potential basis must also
@@ -357,7 +354,7 @@  find_basis_for_candidate (slsr_cand_t c)
   int max_iters = PARAM_VALUE (PARAM_MAX_SLSR_CANDIDATE_SCAN);

   mapping_key.base_expr = c->base_expr;
-  chain = (cand_chain_t) htab_find (base_cand_map, &mapping_key);
+  chain = base_cand_map.find (&mapping_key);

   for (; chain && iters < max_iters; chain = chain->next, ++iters)
     {
@@ -393,13 +390,13 @@  static void
 record_potential_basis (slsr_cand_t c)
 {
   cand_chain_t node;
-  void **slot;
+  cand_chain **slot;

   node = (cand_chain_t) obstack_alloc (&chain_obstack, sizeof (cand_chain));
   node->base_expr = c->base_expr;
   node->cand = c;
   node->next = NULL;
-  slot = htab_find_slot (base_cand_map, node, INSERT);
+  slot = base_cand_map.find_slot (node, INSERT);

   if (*slot)
     {
@@ -1435,10 +1432,10 @@  dump_cand_vec (void)

 /* Callback used to dump the candidate chains hash table.  */

-static int
-base_cand_dump_callback (void **slot, void *ignored ATTRIBUTE_UNUSED)
+int
+ssa_base_cand_dump_callback (cand_chain **slot, void *ignored ATTRIBUTE_UNUSED)
 {
-  const_cand_chain_t chain = *((const_cand_chain_t *) slot);
+  const_cand_chain_t chain = *slot;
   cand_chain_t p;

   print_generic_expr (dump_file, chain->base_expr, 0);
@@ -1457,7 +1454,7 @@  static void
 dump_cand_chains (void)
 {
   fprintf (dump_file, "\nStrength reduction candidate chains:\n\n");
-  htab_traverse_noresize (base_cand_map, base_cand_dump_callback, NULL);
+  base_cand_map.traverse_noresize <void *, ssa_base_cand_dump_callback> (NULL);
   fputs ("\n", dump_file);
 }

@@ -2637,8 +2634,7 @@  execute_strength_reduction (void)
   gcc_obstack_init (&chain_obstack);

   /* Allocate the mapping from base expressions to candidate chains.  */
-  base_cand_map = htab_create (500, base_cand_hash,
-			       base_cand_eq, base_cand_free);
+  base_cand_map.create (500);

   /* Initialize the loop optimizer.  We need to detect flow across
      back edges, and this gives us dominator information as well.  */
@@ -2669,7 +2665,7 @@  execute_strength_reduction (void)
   /* Free resources.  */
   fini_walk_dominator_tree (&walk_data);
   loop_optimizer_finalize ();
-  htab_delete (base_cand_map);
+  base_cand_map.dispose ();
   obstack_free (&chain_obstack, NULL);
   pointer_map_destroy (stmt_cand_map);
   cand_vec.release ();
Index: gcc/gcse.c
===================================================================
--- gcc/gcse.c	(revision 193902)
+++ gcc/gcse.c	(working copy)
@@ -159,7 +159,7 @@  along with GCC; see the file COPYING3.
 #include "intl.h"
 #include "obstack.h"
 #include "tree-pass.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "df.h"
 #include "dbgcnt.h"
 #include "target.h"
@@ -362,8 +362,34 @@  struct ls_expr
 /* Head of the list of load/store memory refs.  */
 static struct ls_expr * pre_ldst_mems = NULL;

+struct pre_ldst_expr_hasher : typed_noop_remove <ls_expr>
+{
+  typedef ls_expr value_type;
+  typedef value_type compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Hashtable helpers.  */
+inline hashval_t
+pre_ldst_expr_hasher::hash (const value_type *x)
+{
+  int do_not_record_p = 0;
+  return
+    hash_rtx (x->pattern, GET_MODE (x->pattern), &do_not_record_p,
NULL, false);
+}
+
+static int expr_equiv_p (const_rtx, const_rtx);
+
+inline bool
+pre_ldst_expr_hasher::equal (const value_type *ptr1,
+			     const compare_type *ptr2)
+{
+  return expr_equiv_p (ptr1->pattern, ptr2->pattern);
+}
+
 /* Hashtable for the load/store memory refs.  */
-static htab_t pre_ldst_table = NULL;
+static hash_table <pre_ldst_expr_hasher> pre_ldst_table;

 /* Bitmap containing one bit for each register in the program.
    Used when performing GCSE to track which registers have been set since
@@ -450,7 +476,6 @@  static int oprs_available_p (const_rtx,
 static void insert_expr_in_table (rtx, enum machine_mode, rtx, int, int, int,
 				  struct hash_table_d *);
 static unsigned int hash_expr (const_rtx, enum machine_mode, int *, int);
-static int expr_equiv_p (const_rtx, const_rtx);
 static void record_last_reg_set_info (rtx, int);
 static void record_last_mem_set_info (rtx);
 static void record_last_set_info (rtx, const_rtx, void *);
@@ -3653,23 +3678,6 @@  one_code_hoisting_pass (void)
     load towards the exit, and we end up with no loads or stores of 'i'
     in the loop.  */

-static hashval_t
-pre_ldst_expr_hash (const void *p)
-{
-  int do_not_record_p = 0;
-  const struct ls_expr *const x = (const struct ls_expr *) p;
-  return
-    hash_rtx (x->pattern, GET_MODE (x->pattern), &do_not_record_p,
NULL, false);
-}
-
-static int
-pre_ldst_expr_eq (const void *p1, const void *p2)
-{
-  const struct ls_expr *const ptr1 = (const struct ls_expr *) p1,
-    *const ptr2 = (const struct ls_expr *) p2;
-  return expr_equiv_p (ptr1->pattern, ptr2->pattern);
-}
-
 /* This will search the ldst list for a matching expression. If it
    doesn't find one, we create one and initialize it.  */

@@ -3679,16 +3687,16 @@  ldst_entry (rtx x)
   int do_not_record_p = 0;
   struct ls_expr * ptr;
   unsigned int hash;
-  void **slot;
+  ls_expr **slot;
   struct ls_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 (pre_ldst_table, &e, hash, INSERT);
+  slot = pre_ldst_table.find_slot_with_hash (&e, hash, INSERT);
   if (*slot)
-    return (struct ls_expr *)*slot;
+    return *slot;

   ptr = XNEW (struct ls_expr);

@@ -3724,9 +3732,8 @@  free_ldst_entry (struct ls_expr * ptr)
 static void
 free_ld_motion_mems (void)
 {
-  if (pre_ldst_table)
-    htab_delete (pre_ldst_table);
-  pre_ldst_table = NULL;
+  if (pre_ldst_table.is_created ())
+    pre_ldst_table.dispose ();

   while (pre_ldst_mems)
     {
@@ -3781,14 +3788,14 @@  static struct ls_expr *
 find_rtx_in_ldst (rtx x)
 {
   struct ls_expr e;
-  void **slot;
-  if (!pre_ldst_table)
+  ls_expr **slot;
+  if (!pre_ldst_table.is_created ())
     return NULL;
   e.pattern = x;
-  slot = htab_find_slot (pre_ldst_table, &e, NO_INSERT);
-  if (!slot || ((struct ls_expr *)*slot)->invalid)
+  slot = pre_ldst_table.find_slot (&e, NO_INSERT);
+  if (!slot || (*slot)->invalid)
     return NULL;
-  return (struct ls_expr *) *slot;
+  return *slot;
 }
 
 /* Load Motion for loads which only kill themselves.  */
@@ -3876,8 +3883,7 @@  compute_ld_motion_mems (void)
   rtx insn;

   pre_ldst_mems = NULL;
-  pre_ldst_table
-    = htab_create (13, pre_ldst_expr_hash, pre_ldst_expr_eq, NULL);
+  pre_ldst_table.create (13);

   FOR_EACH_BB (bb)
     {
@@ -3968,7 +3974,7 @@  trim_ld_motion_mems (void)
       else
 	{
 	  *last = ptr->next;
-	  htab_remove_elt_with_hash (pre_ldst_table, ptr, ptr->hash_index);
+	  pre_ldst_table.remove_elt_with_hash (ptr, ptr->hash_index);
 	  free_ldst_entry (ptr);
 	  ptr = * last;
 	}
Index: gcc/loop-unroll.c
===================================================================
--- gcc/loop-unroll.c	(revision 193902)
+++ gcc/loop-unroll.c	(working copy)
@@ -29,7 +29,7 @@  along with GCC; see the file COPYING3.
 #include "cfgloop.h"
 #include "params.h"
 #include "expr.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "recog.h"
 #include "target.h"
 #include "dumpfile.h"
@@ -102,16 +102,70 @@  struct var_to_expand
                                       var_expansions[REUSE_EXPANSION - 1].  */
 };

+/* Hashtable helper for iv_to_split.  */
+
+struct iv_split_hasher : typed_free_remove <iv_to_split>
+{
+  typedef iv_to_split value_type;
+  typedef iv_to_split compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+
+/* A hash function for information about insns to split.  */
+
+inline hashval_t
+iv_split_hasher::hash (const value_type *ivts)
+{
+  return (hashval_t) INSN_UID (ivts->insn);
+}
+
+/* An equality functions for information about insns to split.  */
+
+inline bool
+iv_split_hasher::equal (const value_type *i1, const compare_type *i2)
+{
+  return i1->insn == i2->insn;
+}
+
+/* Hashtable helper for iv_to_split.  */
+
+struct var_expand_hasher : typed_free_remove <var_to_expand>
+{
+  typedef var_to_expand value_type;
+  typedef var_to_expand compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Return a hash for VES.  */
+
+inline hashval_t
+var_expand_hasher::hash (const value_type *ves)
+{
+  return (hashval_t) INSN_UID (ves->insn);
+}
+
+/* Return true if I1 and I2 refer to the same instruction.  */
+
+inline bool
+var_expand_hasher::equal (const value_type *i1, const compare_type *i2)
+{
+  return i1->insn == i2->insn;
+}
+
 /* Information about optimization applied in
    the unrolled loop.  */

 struct opt_info
 {
-  htab_t insns_to_split;           /* A hashtable of insns to split.  */
+  hash_table <iv_split_hasher> insns_to_split; /* A hashtable of insns to
+						  split.  */
   struct iv_to_split *iv_to_split_head; /* The first iv to split.  */
   struct iv_to_split **iv_to_split_tail; /* Pointer to the tail of
the list.  */
-  htab_t insns_with_var_to_expand; /* A hashtable of insns with accumulators
-                                      to expand.  */
+  hash_table <var_expand_hasher> insns_with_var_to_expand; /* A hashtable of
+					insns with accumulators to expand.  */
   struct var_to_expand *var_to_expand_head; /* The first var to expand.  */
   struct var_to_expand **var_to_expand_tail; /* Pointer to the tail
of the list.  */
   unsigned first_new_block;        /* The first basic block that was
@@ -1534,45 +1588,6 @@  unroll_loop_stupid (struct loop *loop)
 	     nunroll, num_loop_insns (loop));
 }

-/* A hash function for information about insns to split.  */
-
-static hashval_t
-si_info_hash (const void *ivts)
-{
-  return (hashval_t) INSN_UID (((const struct iv_to_split *) ivts)->insn);
-}
-
-/* An equality functions for information about insns to split.  */
-
-static int
-si_info_eq (const void *ivts1, const void *ivts2)
-{
-  const struct iv_to_split *const i1 = (const struct iv_to_split *) ivts1;
-  const struct iv_to_split *const i2 = (const struct iv_to_split *) ivts2;
-
-  return i1->insn == i2->insn;
-}
-
-/* Return a hash for VES, which is really a "var_to_expand *".  */
-
-static hashval_t
-ve_info_hash (const void *ves)
-{
-  return (hashval_t) INSN_UID (((const struct var_to_expand *) ves)->insn);
-}
-
-/* Return true if IVTS1 and IVTS2 (which are really both of type
-   "var_to_expand *") refer to the same instruction.  */
-
-static int
-ve_info_eq (const void *ivts1, const void *ivts2)
-{
-  const struct var_to_expand *const i1 = (const struct var_to_expand *) ivts1;
-  const struct var_to_expand *const i2 = (const struct var_to_expand *) ivts2;
-
-  return i1->insn == i2->insn;
-}
-
 /* Returns true if REG is referenced in one nondebug insn in LOOP.
    Set *DEBUG_USES to the number of debug insns that reference the
    variable.  */
@@ -1856,8 +1871,8 @@  analyze_insns_in_loop (struct loop *loop
   rtx insn;
   struct iv_to_split *ivts = NULL;
   struct var_to_expand *ves = NULL;
-  PTR *slot1;
-  PTR *slot2;
+  iv_to_split **slot1;
+  var_to_expand **slot2;
   vec<edge> edges = get_loop_exit_edges (loop);
   edge exit;
   bool can_apply = false;
@@ -1868,8 +1883,7 @@  analyze_insns_in_loop (struct loop *loop

   if (flag_split_ivs_in_unroller)
     {
-      opt_info->insns_to_split = htab_create (5 * loop->num_nodes,
-					      si_info_hash, si_info_eq, free);
+      opt_info->insns_to_split.create (5 * loop->num_nodes);
       opt_info->iv_to_split_head = NULL;
       opt_info->iv_to_split_tail = &opt_info->iv_to_split_head;
     }
@@ -1890,9 +1904,7 @@  analyze_insns_in_loop (struct loop *loop
   if (flag_variable_expansion_in_unroller
       && can_apply)
     {
-      opt_info->insns_with_var_to_expand = htab_create (5 * loop->num_nodes,
-							ve_info_hash,
-							ve_info_eq, free);
+      opt_info->insns_with_var_to_expand.create (5 * loop->num_nodes);
       opt_info->var_to_expand_head = NULL;
       opt_info->var_to_expand_tail = &opt_info->var_to_expand_head;
     }
@@ -1908,12 +1920,12 @@  analyze_insns_in_loop (struct loop *loop
         if (!INSN_P (insn))
           continue;

-        if (opt_info->insns_to_split)
+        if (opt_info->insns_to_split.is_created ())
           ivts = analyze_iv_to_split_insn (insn);

         if (ivts)
           {
-            slot1 = htab_find_slot (opt_info->insns_to_split, ivts, INSERT);
+            slot1 = opt_info->insns_to_split.find_slot (ivts, INSERT);
 	    gcc_assert (*slot1 == NULL);
             *slot1 = ivts;
 	    *opt_info->iv_to_split_tail = ivts;
@@ -1921,12 +1933,12 @@  analyze_insns_in_loop (struct loop *loop
             continue;
           }

-        if (opt_info->insns_with_var_to_expand)
+        if (opt_info->insns_with_var_to_expand.is_created ())
           ves = analyze_insn_to_expand_var (loop, insn);

         if (ves)
           {
-            slot2 = htab_find_slot
(opt_info->insns_with_var_to_expand, ves, INSERT);
+            slot2 = opt_info->insns_with_var_to_expand.find_slot (ves, INSERT);
 	    gcc_assert (*slot2 == NULL);
             *slot2 = ves;
 	    *opt_info->var_to_expand_tail = ves;
@@ -2278,7 +2290,7 @@  apply_opt_in_copies (struct opt_info *op
   gcc_assert (!unrolling || rewrite_original_loop);

   /* Allocate the basic variables (i0).  */
-  if (opt_info->insns_to_split)
+  if (opt_info->insns_to_split.is_created ())
     for (ivts = opt_info->iv_to_split_head; ivts; ivts = ivts->next)
       allocate_basic_variable (ivts);

@@ -2311,10 +2323,9 @@  apply_opt_in_copies (struct opt_info *op
           ve_templ.insn = orig_insn;

           /* Apply splitting iv optimization.  */
-          if (opt_info->insns_to_split)
+          if (opt_info->insns_to_split.is_created ())
             {
-              ivts = (struct iv_to_split *)
-		htab_find (opt_info->insns_to_split, &ivts_templ);
+              ivts = opt_info->insns_to_split.find (&ivts_templ);

               if (ivts)
                 {
@@ -2327,10 +2338,10 @@  apply_opt_in_copies (struct opt_info *op
                 }
             }
           /* Apply variable expansion optimization.  */
-          if (unrolling && opt_info->insns_with_var_to_expand)
+          if (unrolling && opt_info->insns_with_var_to_expand.is_created ())
             {
               ves = (struct var_to_expand *)
-		htab_find (opt_info->insns_with_var_to_expand, &ve_templ);
+		opt_info->insns_with_var_to_expand.find (&ve_templ);
               if (ves)
                 {
 		  gcc_assert (GET_CODE (PATTERN (insn))
@@ -2347,7 +2358,7 @@  apply_opt_in_copies (struct opt_info *op

   /* Initialize the variable expansions in the loop preheader
      and take care of combining them at the loop exit.  */
-  if (opt_info->insns_with_var_to_expand)
+  if (opt_info->insns_with_var_to_expand.is_created ())
     {
       for (ves = opt_info->var_to_expand_head; ves; ves = ves->next)
 	insert_var_expansion_initialization (ves, opt_info->loop_preheader);
@@ -2376,10 +2387,10 @@  apply_opt_in_copies (struct opt_info *op
  	    continue;

           ivts_templ.insn = orig_insn;
-          if (opt_info->insns_to_split)
+          if (opt_info->insns_to_split.is_created ())
             {
               ivts = (struct iv_to_split *)
-		htab_find (opt_info->insns_to_split, &ivts_templ);
+		opt_info->insns_to_split.find (&ivts_templ);
               if (ivts)
                 {
                   if (!delta)
@@ -2398,15 +2409,15 @@  apply_opt_in_copies (struct opt_info *op
 static void
 free_opt_info (struct opt_info *opt_info)
 {
-  if (opt_info->insns_to_split)
-    htab_delete (opt_info->insns_to_split);
-  if (opt_info->insns_with_var_to_expand)
+  if (opt_info->insns_to_split.is_created ())
+    opt_info->insns_to_split.dispose ();
+  if (opt_info->insns_with_var_to_expand.is_created ())
     {
       struct var_to_expand *ves;

       for (ves = opt_info->var_to_expand_head; ves; ves = ves->next)
 	ves->var_expansions.release ();
-      htab_delete (opt_info->insns_with_var_to_expand);
+      opt_info->insns_with_var_to_expand.dispose ();
     }
   free (opt_info);
 }
Index: gcc/store-motion.c
===================================================================
--- gcc/store-motion.c	(revision 193902)
+++ gcc/store-motion.c	(working copy)
@@ -40,7 +40,7 @@  along with GCC; see the file COPYING3.
 #include "ggc.h"
 #include "intl.h"
 #include "tree-pass.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "df.h"
 #include "dbgcnt.h"

@@ -91,9 +91,6 @@  struct st_expr
 /* 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;

@@ -109,22 +106,32 @@  static int num_stores;
 /* 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 : typed_noop_remove <st_expr>
+{
+  typedef st_expr value_type;
+  typedef st_expr compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+st_expr_hasher::hash (const value_type *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 value_type *ptr1, const compare_type *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.  */

@@ -134,16 +141,16 @@  st_expr_entry (rtx x)
   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);

@@ -177,9 +184,8 @@  free_st_expr_entry (struct st_expr * ptr
 static void
 free_store_motion_mems (void)
 {
-  if (store_motion_mems_table)
-    htab_delete (store_motion_mems_table);
-  store_motion_mems_table = NULL;
+  if (store_motion_mems_table.is_created ())
+    store_motion_mems_table.dispose ();

   while (store_motion_mems)
     {
@@ -646,8 +652,7 @@  compute_store_table (void)
   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.create (13);
   last_set_in = XCNEWVEC (int, max_gcse_regno);
   already_set = XNEWVEC (int, max_gcse_regno);

@@ -709,8 +714,7 @@  compute_store_table (void)
       if (! ptr->avail_stores)
 	{
 	  *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
@@ -1143,8 +1147,7 @@  one_store_motion_pass (void)
   num_stores = compute_store_table ();
   if (num_stores == 0)
     {
-      htab_delete (store_motion_mems_table);
-      store_motion_mems_table = NULL;
+      store_motion_mems_table.dispose ();
       end_alias_analysis ();
       return 0;
     }
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c	(revision 193902)
+++ gcc/cselib.c	(working copy)
@@ -36,7 +36,7 @@  along with GCC; see the file COPYING3.
 #include "emit-rtl.h"
 #include "diagnostic-core.h"
 #include "ggc.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "dumpfile.h"
 #include "cselib.h"
 #include "valtrack.h"
@@ -51,18 +51,18 @@  struct elt_list {
     cselib_val *elt;
 };

+/* See the documentation of cselib_find_slot below.  */
+static enum machine_mode find_slot_memmode;
+
 static bool cselib_record_memory;
 static bool cselib_preserve_constants;
 static bool cselib_any_perm_equivs;
-static int entry_and_rtx_equal_p (const void *, const void *);
-static hashval_t get_value_hash (const void *);
+static inline void promote_debug_loc (struct elt_loc_list *l);
 static struct elt_list *new_elt_list (struct elt_list *, cselib_val *);
 static void new_elt_loc_list (cselib_val *, rtx);
 static void unchain_one_value (cselib_val *);
 static void unchain_one_elt_list (struct elt_list **);
 static void unchain_one_elt_loc_list (struct elt_loc_list **);
-static int discard_useless_locs (void **, void *);
-static int discard_useless_values (void **, void *);
 static void remove_useless_values (void);
 static int rtx_equal_for_cselib_1 (rtx, rtx, enum machine_mode);
 static unsigned int cselib_hash_rtx (rtx, int, enum machine_mode);
@@ -93,8 +93,61 @@  static rtx cselib_expand_value_rtx_1 (rt
      this involves walking the table entries for a given value and comparing
      the locations of the entries with the rtx we are looking up.  */

+struct cselib_hasher : typed_noop_remove <cselib_val>
+{
+  typedef cselib_val value_type;
+  typedef rtx_def compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* The hash function for our hash table.  The value is always computed with
+   cselib_hash_rtx when adding an element; this function just extracts the
+   hash value from a cselib_val structure.  */
+
+inline hashval_t
+cselib_hasher::hash (const value_type *v)
+{
+  return v->hash;
+}
+
+/* The equality test for our hash table.  The first argument V is a table
+   element (i.e. a cselib_val), while the second arg X is an rtx.  We know
+   that all callers of htab_find_slot_with_hash will wrap CONST_INTs into a
+   CONST of an appropriate mode.  */
+
+inline bool
+cselib_hasher::equal (const value_type *v, const compare_type *x_arg)
+{
+  struct elt_loc_list *l;
+  rtx x = CONST_CAST_RTX (x_arg);
+  enum machine_mode mode = GET_MODE (x);
+
+  gcc_assert (!CONST_SCALAR_INT_P (x) && GET_CODE (x) != CONST_FIXED);
+
+  if (mode != GET_MODE (v->val_rtx))
+    return 0;
+
+  /* Unwrap X if necessary.  */
+  if (GET_CODE (x) == CONST
+      && (CONST_SCALAR_INT_P (XEXP (x, 0))
+	  || GET_CODE (XEXP (x, 0)) == CONST_FIXED))
+    x = XEXP (x, 0);
+
+  /* We don't guarantee that distinct rtx's have different hash values,
+     so we need to do a comparison.  */
+  for (l = v->locs; l; l = l->next)
+    if (rtx_equal_for_cselib_1 (l->loc, x, find_slot_memmode))
+      {
+	promote_debug_loc (l);
+	return 1;
+      }
+
+  return 0;
+}
+
 /* A table that enables us to look up elts by their value.  */
-static htab_t cselib_hash_table;
+static hash_table <cselib_hasher> cselib_hash_table;

 /* This is a global so we don't have to pass this through every function.
    It is used in new_elt_loc_list to set SETTING_INSN.  */
@@ -434,13 +487,13 @@  invariant_or_equiv_p (cselib_val *v)
 /* Remove from hash table all VALUEs except constants, function
    invariants and VALUE equivalences.  */

-static int
-preserve_constants_and_equivs (void **x, void *info ATTRIBUTE_UNUSED)
+int
+preserve_constants_and_equivs (cselib_val **x, void *info ATTRIBUTE_UNUSED)
 {
-  cselib_val *v = (cselib_val *)*x;
+  cselib_val *v = *x;

   if (!invariant_or_equiv_p (v))
-    htab_clear_slot (cselib_hash_table, x);
+    cselib_hash_table.clear_slot (x);
   return 1;
 }

@@ -480,10 +533,10 @@  cselib_reset_table (unsigned int num)
     }

   if (cselib_preserve_constants)
-    htab_traverse (cselib_hash_table, preserve_constants_and_equivs, NULL);
+    cselib_hash_table.traverse <void *, preserve_constants_and_equivs> (NULL);
   else
     {
-      htab_empty (cselib_hash_table);
+      cselib_hash_table.empty ();
       gcc_checking_assert (!cselib_any_perm_equivs);
     }

@@ -504,8 +557,10 @@  cselib_get_next_uid (void)
   return next_uid;
 }

+#if 0
 /* See the documentation of cselib_find_slot below.  */
 static enum machine_mode find_slot_memmode;
+#endif

 /* Search for X, whose hashcode is HASH, in CSELIB_HASH_TABLE,
    INSERTing if requested.  When X is part of the address of a MEM,
@@ -513,17 +568,18 @@  static enum machine_mode find_slot_memmo
    table, MEMMODE is held in FIND_SLOT_MEMMODE, so that autoinc RTXs
    in X can be resolved.  */

-static void **
+static cselib_val **
 cselib_find_slot (rtx x, hashval_t hash, enum insert_option insert,
 		  enum machine_mode memmode)
 {
-  void **slot;
+  cselib_val **slot;
   find_slot_memmode = memmode;
-  slot = htab_find_slot_with_hash (cselib_hash_table, x, hash, insert);
+  slot = cselib_hash_table.find_slot_with_hash (x, hash, insert);
   find_slot_memmode = VOIDmode;
   return slot;
 }

+#if 0
 /* The equality test for our hash table.  The first argument ENTRY is a table
    element (i.e. a cselib_val), while the second arg X is an rtx.  We know
    that all callers of htab_find_slot_with_hash will wrap CONST_INTs into a
@@ -570,6 +626,7 @@  get_value_hash (const void *entry)
   const cselib_val *const v = (const cselib_val *) entry;
   return v->hash;
 }
+#endif

 /* Return true if X contains a VALUE rtx.  If ONLY_USELESS is set, we
    only return true for values which point to a cselib_val whose value
@@ -605,10 +662,10 @@  references_value_p (const_rtx x, int onl
    values (i.e. values without any location).  Called through
    htab_traverse.  */

-static int
-discard_useless_locs (void **x, void *info ATTRIBUTE_UNUSED)
+int
+discard_useless_locs (cselib_val **x, void *info ATTRIBUTE_UNUSED)
 {
-  cselib_val *v = (cselib_val *)*x;
+  cselib_val *v = *x;
   struct elt_loc_list **p = &v->locs;
   bool had_locs = v->locs != NULL;
   rtx setting_insn = v->locs ? v->locs->setting_insn : NULL;
@@ -634,10 +691,10 @@  discard_useless_locs (void **x, void *in

 /* If X is a value with no locations, remove it from the hashtable.  */

-static int
-discard_useless_values (void **x, void *info ATTRIBUTE_UNUSED)
+int
+discard_useless_values (cselib_val **x, void *info ATTRIBUTE_UNUSED)
 {
-  cselib_val *v = (cselib_val *)*x;
+  cselib_val *v = *x;

   if (v->locs == 0 && !PRESERVED_VALUE_P (v->val_rtx))
     {
@@ -645,7 +702,7 @@  discard_useless_values (void **x, void *
 	cselib_discard_hook (v);

       CSELIB_VAL_PTR (v->val_rtx) = NULL;
-      htab_clear_slot (cselib_hash_table, x);
+      cselib_hash_table.clear_slot (x);
       unchain_one_value (v);
       n_useless_values--;
     }
@@ -666,7 +723,7 @@  remove_useless_values (void)
   do
     {
       values_became_useless = 0;
-      htab_traverse (cselib_hash_table, discard_useless_locs, 0);
+      cselib_hash_table.traverse <void *, discard_useless_locs> (NULL);
     }
   while (values_became_useless);

@@ -685,7 +742,7 @@  remove_useless_values (void)
   n_debug_values -= n_useless_debug_values;
   n_useless_debug_values = 0;

-  htab_traverse (cselib_hash_table, discard_useless_values, 0);
+  cselib_hash_table.traverse <void *, discard_useless_values> (NULL);

   gcc_assert (!n_useless_values);
 }
@@ -1354,7 +1411,7 @@  cselib_lookup_mem (rtx x, int create)
 {
   enum machine_mode mode = GET_MODE (x);
   enum machine_mode addr_mode;
-  void **slot;
+  cselib_val **slot;
   cselib_val *addr;
   cselib_val *mem_elt;
   struct elt_list *l;
@@ -1960,7 +2017,7 @@  static cselib_val *
 cselib_lookup_1 (rtx x, enum machine_mode mode,
 		 int create, enum machine_mode memmode)
 {
-  void **slot;
+  cselib_val **slot;
   cselib_val *e;
   unsigned int hashval;

@@ -2071,7 +2128,7 @@  cselib_lookup_1 (rtx x, enum machine_mod
   /* We have to fill the slot before calling cselib_subst_to_values:
      the hash table is inconsistent until we do so, and
      cselib_subst_to_values will need to do lookups.  */
-  *slot = (void *) e;
+  *slot = e;
   new_elt_loc_list (e, cselib_subst_to_values (x, memmode));
   return e;
 }
@@ -2687,9 +2744,7 @@  cselib_process_insn (rtx insn)
          quadratic behavior for very large hashtables with very few
 	 useless elements.  */
       && ((unsigned int)n_useless_values
-	  > (cselib_hash_table->n_elements
-	     - cselib_hash_table->n_deleted
-	     - n_debug_values) / 4))
+	  > (cselib_hash_table.elements () - n_debug_values) / 4))
     remove_useless_values ();
 }

@@ -2730,8 +2785,7 @@  cselib_init (int record_what)
     }
   used_regs = XNEWVEC (unsigned int, cselib_nregs);
   n_used_regs = 0;
-  cselib_hash_table = htab_create (31, get_value_hash,
-				   entry_and_rtx_equal_p, NULL);
+  cselib_hash_table.create (31);
   next_uid = 1;
 }

@@ -2750,23 +2804,21 @@  cselib_finish (void)
   free_alloc_pool (cselib_val_pool);
   free_alloc_pool (value_pool);
   cselib_clear_table ();
-  htab_delete (cselib_hash_table);
+  cselib_hash_table.dispose ();
   free (used_regs);
   used_regs = 0;
-  cselib_hash_table = 0;
   n_useless_values = 0;
   n_useless_debug_values = 0;
   n_debug_values = 0;
   next_uid = 0;
 }

-/* Dump the cselib_val *X to FILE *info.  */
+/* Dump the cselib_val *X to FILE *OUT.  */

-static int
-dump_cselib_val (void **x, void *info)
+int
+dump_cselib_val (cselib_val **x, FILE *out)
 {
-  cselib_val *v = (cselib_val *)*x;
-  FILE *out = (FILE *)info;
+  cselib_val *v = *x;
   bool need_lf = true;

   print_inline_rtx (out, v->val_rtx, 0);
@@ -2841,7 +2893,7 @@  void
 dump_cselib_table (FILE *out)
 {
   fprintf (out, "cselib hash table:\n");
-  htab_traverse (cselib_hash_table, dump_cselib_val, out);
+  cselib_hash_table.traverse <FILE *, dump_cselib_val> (out);
   if (first_containing_mem != &dummy_val)
     {
       fputs ("first mem ", out);
Index: gcc/loop-invariant.c
===================================================================
--- gcc/loop-invariant.c	(revision 193902)
+++ gcc/loop-invariant.c	(working copy)
@@ -51,7 +51,7 @@  along with GCC; see the file COPYING3.
 #include "function.h"
 #include "flags.h"
 #include "df.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "except.h"
 #include "params.h"
 #include "regs.h"
@@ -425,27 +425,28 @@  invariant_expr_equal_p (rtx insn1, rtx e
   return true;
 }

-/* Returns hash value for invariant expression entry E.  */
-
-static hashval_t
-hash_invariant_expr (const void *e)
+struct invariant_expr_hasher : typed_free_remove <invariant_expr_entry>
 {
-  const struct invariant_expr_entry *const entry =
-    (const struct invariant_expr_entry *) e;
+  typedef invariant_expr_entry value_type;
+  typedef invariant_expr_entry compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Returns hash value for invariant expression entry ENTRY.  */

+inline hashval_t
+invariant_expr_hasher::hash (const value_type *entry)
+{
   return entry->hash;
 }

-/* Compares invariant expression entries E1 and E2.  */
+/* Compares invariant expression entries ENTRY1 and ENTRY2.  */

-static int
-eq_invariant_expr (const void *e1, const void *e2)
+inline bool
+invariant_expr_hasher::equal (const value_type *entry1,
+			      const compare_type *entry2)
 {
-  const struct invariant_expr_entry *const entry1 =
-    (const struct invariant_expr_entry *) e1;
-  const struct invariant_expr_entry *const entry2 =
-    (const struct invariant_expr_entry *) e2;
-
   if (entry1->mode != entry2->mode)
     return 0;

@@ -453,24 +454,26 @@  eq_invariant_expr (const void *e1, const
 				 entry2->inv->insn, entry2->expr);
 }

+typedef hash_table <invariant_expr_hasher> invariant_htab_type;
+
 /* Checks whether invariant with value EXPR in machine mode MODE is
    recorded in EQ.  If this is the case, return the invariant.  Otherwise
    insert INV to the table for this expression and return INV.  */

 static struct invariant *
-find_or_insert_inv (htab_t eq, rtx expr, enum machine_mode mode,
+find_or_insert_inv (invariant_htab_type eq, rtx expr, enum machine_mode mode,
 		    struct invariant *inv)
 {
   hashval_t hash = hash_invariant_expr_1 (inv->insn, expr);
   struct invariant_expr_entry *entry;
   struct invariant_expr_entry pentry;
-  PTR *slot;
+  invariant_expr_entry **slot;

   pentry.expr = expr;
   pentry.inv = inv;
   pentry.mode = mode;
-  slot = htab_find_slot_with_hash (eq, &pentry, hash, INSERT);
-  entry = (struct invariant_expr_entry *) *slot;
+  slot = eq.find_slot_with_hash (&pentry, hash, INSERT);
+  entry = *slot;

   if (entry)
     return entry->inv;
@@ -489,7 +492,7 @@  find_or_insert_inv (htab_t eq, rtx expr,
    hash table of the invariants.  */

 static void
-find_identical_invariants (htab_t eq, struct invariant *inv)
+find_identical_invariants (invariant_htab_type eq, struct invariant *inv)
 {
   unsigned depno;
   bitmap_iterator bi;
@@ -526,13 +529,13 @@  merge_identical_invariants (void)
 {
   unsigned i;
   struct invariant *inv;
-  htab_t eq = htab_create (invariants.length (),
-			   hash_invariant_expr, eq_invariant_expr, free);
+  invariant_htab_type eq;
+  eq.create (invariants.length ());

   FOR_EACH_VEC_ELT (invariants, i, inv)
     find_identical_invariants (eq, inv);

-  htab_delete (eq);
+  eq.dispose ();
 }

 /* Determines the basic blocks inside LOOP that are always executed and
Index: gcc/loop-iv.c
===================================================================
--- gcc/loop-iv.c	(revision 193902)
+++ gcc/loop-iv.c	(working copy)
@@ -61,7 +61,7 @@  along with GCC; see the file COPYING3.
 #include "intl.h"
 #include "diagnostic-core.h"
 #include "df.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "dumpfile.h"

 /* Possible return values of iv_get_reaching_def.  */
@@ -107,9 +107,35 @@  static struct rtx_iv ** iv_ref_table;

 static struct loop *current_loop;

+/* Hashtable helper.  */
+
+struct biv_entry_hasher : typed_free_remove <biv_entry>
+{
+  typedef biv_entry value_type;
+  typedef rtx_def compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Returns hash value for biv B.  */
+
+inline hashval_t
+biv_entry_hasher::hash (const value_type *b)
+{
+  return b->regno;
+}
+
+/* Compares biv B and register R.  */
+
+inline bool
+biv_entry_hasher::equal (const value_type *b, const compare_type *r)
+{
+  return b->regno == REGNO (r);
+}
+
 /* Bivs of the current loop.  */

-static htab_t bivs;
+static hash_table <biv_entry_hasher> bivs;

 static bool iv_analyze_op (rtx, rtx, struct rtx_iv *);

@@ -244,24 +270,9 @@  clear_iv_info (void)
 	}
     }

-  htab_empty (bivs);
-}
-
-/* Returns hash value for biv B.  */
-
-static hashval_t
-biv_hash (const void *b)
-{
-  return ((const struct biv_entry *) b)->regno;
+  bivs.empty ();
 }

-/* Compares biv B and register R.  */
-
-static int
-biv_eq (const void *b, const void *r)
-{
-  return ((const struct biv_entry *) b)->regno == REGNO ((const_rtx) r);
-}

 /* Prepare the data for an induction variable analysis of a LOOP.  */

@@ -278,7 +289,7 @@  iv_analysis_loop_init (struct loop *loop
   if (clean_slate)
     {
       df_set_flags (DF_EQ_NOTES + DF_DEFER_INSN_RESCAN);
-      bivs = htab_create (10, biv_hash, biv_eq, free);
+      bivs.create (10);
       clean_slate = false;
     }
   else
@@ -838,8 +849,7 @@  record_iv (df_ref def, struct rtx_iv *iv
 static bool
 analyzed_for_bivness_p (rtx def, struct rtx_iv *iv)
 {
-  struct biv_entry *biv =
-    (struct biv_entry *) htab_find_with_hash (bivs, def, REGNO (def));
+  struct biv_entry *biv = bivs.find_with_hash (def, REGNO (def));

   if (!biv)
     return false;
@@ -852,7 +862,7 @@  static void
 record_biv (rtx def, struct rtx_iv *iv)
 {
   struct biv_entry *biv = XNEW (struct biv_entry);
-  void **slot = htab_find_slot_with_hash (bivs, def, REGNO (def), INSERT);
+  biv_entry **slot = bivs.find_slot_with_hash (def, REGNO (def), INSERT);

   biv->regno = REGNO (def);
   biv->iv = *iv;
@@ -1294,11 +1304,10 @@  iv_analysis_done (void)
       clear_iv_info ();
       clean_slate = true;
       df_finish_pass (true);
-      htab_delete (bivs);
+      bivs.dispose ();
       free (iv_ref_table);
       iv_ref_table = NULL;
       iv_ref_table_size = 0;
-      bivs = NULL;
     }
 }

Index: gcc/ira-costs.c
===================================================================
--- gcc/ira-costs.c	(revision 193902)
+++ gcc/ira-costs.c	(working copy)
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "hash-table.h"
 #include "hard-reg-set.h"
 #include "rtl.h"
 #include "expr.h"
@@ -132,35 +133,41 @@  typedef const struct cost_classes *const
 /* Info about cost classes for each pseudo.  */
 static cost_classes_t *regno_cost_classes;

-/* Returns hash value for cost classes info V.  */
-static hashval_t
-cost_classes_hash (const void *v)
+/* Helper for cost_classes hashing.  */
+
+struct cost_classes_hasher
 {
-  const_cost_classes_t hv = (const_cost_classes_t) v;
+  typedef cost_classes value_type;
+  typedef cost_classes compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+  static inline void remove (value_type *);
+};

+/* Returns hash value for cost classes info HV.  */
+inline hashval_t
+cost_classes_hasher::hash (const value_type *hv)
+{
   return iterative_hash (&hv->classes, sizeof (enum reg_class) * hv->num, 0);
 }

-/* Compares cost classes info V1 and V2.  */
-static int
-cost_classes_eq (const void *v1, const void *v2)
+/* Compares cost classes info HV1 and HV2.  */
+inline bool
+cost_classes_hasher::equal (const value_type *hv1, const compare_type *hv2)
 {
-  const_cost_classes_t hv1 = (const_cost_classes_t) v1;
-  const_cost_classes_t hv2 = (const_cost_classes_t) v2;
-
   return hv1->num == hv2->num && memcmp (hv1->classes, hv2->classes,
 					 sizeof (enum reg_class) * hv1->num);
 }

 /* Delete cost classes info V from the hash table.  */
-static void
-cost_classes_del (void *v)
+inline void
+cost_classes_hasher::remove (value_type *v)
 {
   ira_free (v);
 }

 /* Hash table of unique cost classes.  */
-static htab_t cost_classes_htab;
+static hash_table <cost_classes_hasher> cost_classes_htab;

 /* Map allocno class -> cost classes for pseudo of given allocno
    class.  */
@@ -181,8 +188,7 @@  initiate_regno_cost_classes (void)
 	  sizeof (cost_classes_t) * N_REG_CLASSES);
   memset (cost_classes_mode_cache, 0,
 	  sizeof (cost_classes_t) * MAX_MACHINE_MODE);
-  cost_classes_htab
-    = htab_create (200, cost_classes_hash, cost_classes_eq, cost_classes_del);
+  cost_classes_htab.create (200);
 }

 /* Create new cost classes from cost classes FROM and set up members
@@ -230,7 +236,7 @@  setup_regno_cost_classes_by_aclass (int
   cost_classes_t classes_ptr;
   enum reg_class cl;
   int i;
-  PTR *slot;
+  cost_classes **slot;
   HARD_REG_SET temp, temp2;
   bool exclude_p;

@@ -256,7 +262,7 @@  setup_regno_cost_classes_by_aclass (int
 	    }
 	  classes.classes[classes.num++] = cl;
 	}
-      slot = htab_find_slot (cost_classes_htab, &classes, INSERT);
+      slot = cost_classes_htab.find_slot (&classes, INSERT);
       if (*slot == NULL)
 	{
 	  classes_ptr = setup_cost_classes (&classes);
@@ -280,7 +286,7 @@  setup_regno_cost_classes_by_mode (int re
   cost_classes_t classes_ptr;
   enum reg_class cl;
   int i;
-  PTR *slot;
+  cost_classes **slot;
   HARD_REG_SET temp;

   if ((classes_ptr = cost_classes_mode_cache[mode]) == NULL)
@@ -295,7 +301,7 @@  setup_regno_cost_classes_by_mode (int re
 	    continue;
 	  classes.classes[classes.num++] = cl;
 	}
-      slot = htab_find_slot (cost_classes_htab, &classes, INSERT);
+      slot = cost_classes_htab.find_slot (&classes, INSERT);
       if (*slot == NULL)
 	{
 	  classes_ptr = setup_cost_classes (&classes);
@@ -313,7 +319,7 @@  static void
 finish_regno_cost_classes (void)
 {
   ira_free (regno_cost_classes);
-  htab_delete (cost_classes_htab);
+  cost_classes_htab.dispose ();
 }

 
Index: gcc/plugin.c
===================================================================
--- gcc/plugin.c	(revision 193902)
+++ gcc/plugin.c	(working copy)
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "diagnostic-core.h"
 #include "tree.h"
 #include "tree-pass.h"
@@ -50,9 +51,36 @@  static const char *plugin_event_name_ini

 const char **plugin_event_name = plugin_event_name_init;

+/* Event hashtable helpers.  */
+
+struct event_hasher : typed_noop_remove <const char *>
+{
+  typedef const char *value_type;
+  typedef const char *compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Helper function for the event hash table that hashes the entry V.  */
+
+inline hashval_t
+event_hasher::hash (const value_type *v)
+{
+  return htab_hash_string (*v);
+}
+
+/* Helper function for the event hash table that compares the name of an
+   existing entry (S1) with the given string (S2).  */
+
+inline bool
+event_hasher::equal (const value_type *s1, const compare_type *s2)
+{
+  return !strcmp (*s1, *s2);
+}
+
 /* A hash table to map event names to the position of the names in the
    plugin_event_name table.  */
-static htab_t event_tab;
+static hash_table <event_hasher> event_tab;

 /* Keep track of the limit of allocated events and space ready for
    allocating events.  */
@@ -312,41 +340,31 @@  register_plugin_info (const char* name,
   plugin->help = info->help;
 }

-/* Helper function for the event hash table that compares the name of an
-   existing entry (E1) with the given string (S2).  */
-
-static int
-htab_event_eq (const void *e1, const void *s2)
-{
-  const char *s1= *(const char * const *) e1;
-  return !strcmp (s1, (const char *) s2);
-}
-
 /* Look up the event id for NAME.  If the name is not found, return -1
    if INSERT is NO_INSERT.  */

 int
 get_named_event_id (const char *name, enum insert_option insert)
 {
-  void **slot;
+  const char ***slot;

-  if (!event_tab)
+  if (!event_tab.is_created ())
     {
       int i;

-      event_tab = htab_create (150, htab_hash_string, htab_event_eq, NULL);
+      event_tab.create (150);
       for (i = 0; i < event_last; i++)
 	{
-	  slot = htab_find_slot (event_tab, plugin_event_name[i], INSERT);
+	  slot = event_tab.find_slot (&plugin_event_name[i], INSERT);
 	  gcc_assert (*slot == HTAB_EMPTY_ENTRY);
 	  *slot = &plugin_event_name[i];
 	}
     }
-  slot = htab_find_slot (event_tab, name, insert);
+  slot = event_tab.find_slot (&name, insert);
   if (slot == NULL)
     return -1;
   if (*slot != HTAB_EMPTY_ENTRY)
-    return (const char **) *slot - &plugin_event_name[0];
+    return *slot - &plugin_event_name[0];

   if (event_last >= event_horizon)
     {
@@ -368,8 +386,7 @@  get_named_event_id (const char *name, en
 					 plugin_callbacks, event_horizon);
 	}
       /* All the pointers in the hash table will need to be updated.  */
-      htab_delete (event_tab);
-      event_tab = NULL;
+      event_tab.dispose ();
     }
   else
     *slot = &plugin_event_name[event_last];
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 193902)
+++ gcc/Makefile.in	(working copy)
@@ -2255,7 +2255,7 @@  tree-ssa-uninit.o : tree-ssa-uninit.c $(
    $(FLAGS_H) $(HASHTAB_H) pointer-set.h \
    $(GIMPLE_H) $(TREE_INLINE_H) $(GIMPLE_PRETTY_PRINT_H)
 tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
-   $(TREE_H) $(TM_P_H) $(EXPR_H) $(DIAGNOSTIC_H) \
+   $(HASH_TABLE_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(DIAGNOSTIC_H) \
    toplev.h $(FUNCTION_H) $(TM_H) coretypes.h \
    langhooks.h $(TREE_PASS_H) $(BASIC_BLOCK_H) $(BITMAP_H) \
    $(FLAGS_H) $(GGC_H) $(HASHTAB_H) pointer-set.h \
@@ -2318,7 +2318,7 @@  tree-ssa-propagate.o : tree-ssa-propagat
    tree-ssa-propagate.h $(VEC_H) value-prof.h gt-tree-ssa-propagate.h
$(FLAGS_H) \
    $(GIMPLE_H) $(GIMPLE_PRETTY_PRINT_H)
 tree-ssa-dom.o : tree-ssa-dom.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
-   $(TREE_H) $(TM_P_H) $(DIAGNOSTIC_H) \
+   $(HASH_TABLE_H) $(TREE_H) $(TM_P_H) $(DIAGNOSTIC_H) \
    $(FUNCTION_H) $(TM_H) coretypes.h \
    $(BASIC_BLOCK_H) domwalk.h $(TREE_PASS_H) $(FLAGS_H) langhooks.h \
    tree-ssa-propagate.h $(CFGLOOP_H) $(PARAMS_H) \
@@ -2368,7 +2368,7 @@  tree-ssa-sccvn.o : tree-ssa-sccvn.c $(TR
    $(PARAMS_H) $(GIMPLE_PRETTY_PRINT_H) gimple-fold.h
 gimple-ssa-strength-reduction.o : gimple-ssa-strength-reduction.c $(CONFIG_H) \
    $(SYSTEM_H) coretypes.h $(TREE_H) $(GIMPLE_H) $(BASIC_BLOCK_H) \
-   $(TREE_PASS_H) $(CFGLOOP_H) $(TREE_PRETTY_PRINT_H) \
+   $(HASH_TABLE_H) $(TREE_PASS_H) $(CFGLOOP_H) $(TREE_PRETTY_PRINT_H) \
    $(GIMPLE_PRETTY_PRINT_H) alloc-pool.h $(TREE_FLOW_H) domwalk.h \
    pointer-set.h expmed.h
 tree-vrp.o : tree-vrp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
@@ -2376,7 +2376,7 @@  tree-vrp.o : tree-vrp.c $(CONFIG_H) $(SY
    $(BASIC_BLOCK_H) tree-ssa-propagate.h $(FLAGS_H) $(TREE_DUMP_H) \
    $(CFGLOOP_H) $(SCEV_H) intl.h \
    $(GIMPLE_PRETTY_PRINT_H) gimple-fold.h $(OPTABS_H) $(EXPR_H)
-tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H)
$(HASH_TABLE_H) \
    $(TREE_H) $(TM_P_H) $(GGC_H) $(FLAGS_H) $(TARGET_H) \
    $(DIAGNOSTIC_CORE_H) $(FUNCTION_H) $(TM_H) coretypes.h \
    $(TREE_DUMP_H) $(EXCEPT_H) $(CFGLOOP_H) $(TREE_PASS_H) \
@@ -2541,7 +2541,8 @@  tree-chrec.o : tree-chrec.c $(CONFIG_H)
    $(TREE_PRETTY_PRINT_H) $(CFGLOOP_H) $(TREE_FLOW_H) $(SCEV_H) \
    $(PARAMS_H)
 tree-scalar-evolution.o : tree-scalar-evolution.c $(CONFIG_H) $(SYSTEM_H) \
-   coretypes.h dumpfile.h $(GIMPLE_PRETTY_PRINT_H) $(TREE_FLOW_H)
$(CFGLOOP_H) $(SCEV_H) \
+   coretypes.h dumpfile.h $(HASH_TABLE_H) $(GIMPLE_PRETTY_PRINT_H) \
+   $(TREE_FLOW_H) $(CFGLOOP_H) $(SCEV_H) \
    $(PARAMS_H) gt-tree-scalar-evolution.h
 tree-data-ref.o : tree-data-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h
dumpfile.h \
    $(GIMPLE_PRETTY_PRINT_H) $(TREE_FLOW_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) \
@@ -2714,7 +2715,8 @@  passes.o : passes.c $(CONFIG_H) $(SYSTEM
    $(PLUGIN_H) $(IPA_UTILS_H)

 plugin.o : plugin.c $(PLUGIN_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-   $(DIAGNOSTIC_CORE_H) $(TREE_H) $(TREE_PASS_H) intl.h
$(PLUGIN_VERSION_H) $(GGC_H)
+   $(HASH_TABLE_H) $(DIAGNOSTIC_CORE_H) $(TREE_H) $(TREE_PASS_H) \
+   intl.h $(PLUGIN_VERSION_H) $(GGC_H)

 main.o : main.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h
$(DIAGNOSTIC_CORE_H)

@@ -2946,7 +2948,8 @@  coverage.o : coverage.c $(GCOV_IO_H) $(C
    $(FUNCTION_H) $(BASIC_BLOCK_H) toplev.h $(DIAGNOSTIC_CORE_H)
$(GGC_H) langhooks.h $(COVERAGE_H) \
    tree-iterator.h $(CGRAPH_H) gcov-io.c $(TM_P_H) \
    $(DIAGNOSTIC_CORE_H) intl.h gt-coverage.h $(TARGET_H) $(HASH_TABLE_H)
-cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h
$(TM_H) $(RTL_H) \
+cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h \
+   $(HASH_TABLE_H) $(TM_H) $(RTL_H) \
    $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(RECOG_H) \
    $(EMIT_RTL_H) $(DIAGNOSTIC_CORE_H) $(FUNCTION_H) \
    cselib.h gt-cselib.h $(GGC_H) $(TM_P_H) $(PARAMS_H) alloc-pool.h \
@@ -2986,12 +2989,13 @@  cprop.o : cprop.c $(CONFIG_H) $(SYSTEM_H
    intl.h $(OBSTACK_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H) \
    $(DF_H) $(CFGLOOP_H)
 gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
-   $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(GGC_H) \
+   $(HASH_TABLE_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(GGC_H) \
    $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) toplev.h
$(DIAGNOSTIC_CORE_H) \
    $(TM_P_H) $(PARAMS_H) cselib.h $(EXCEPT_H) gt-gcse.h $(TREE_H) \
    intl.h $(OBSTACK_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H) \
    $(DF_H) gcse.h
-store-motion.o : store-motion.c $(CONFIG_H) $(SYSTEM_H) coretypes.h
$(TM_H) $(RTL_H) \
+store-motion.o : store-motion.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+   $(HASH_TABLE_H) $(TM_H) $(RTL_H) \
    $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(GGC_H) \
    $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) toplev.h
$(DIAGNOSTIC_CORE_H) \
    $(TM_P_H) $(EXCEPT_H) $(TREE_H) \
@@ -3134,11 +3138,11 @@  graphds.o : graphds.c graphds.h $(CONFIG
 loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h \
    $(RTL_H) $(BASIC_BLOCK_H) \
    hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) $(TM_H) $(OBSTACK_H) \
-   intl.h $(DIAGNOSTIC_CORE_H) $(DF_H) $(HASHTAB_H)
+   intl.h $(DIAGNOSTIC_CORE_H) $(DF_H) $(HASH_TABLE_H)
 loop-invariant.o : loop-invariant.c $(CONFIG_H) $(SYSTEM_H)
coretypes.h dumpfile.h \
    $(RTL_H) $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) $(RECOG_H) \
    $(TM_H) $(TM_P_H) $(FUNCTION_H) $(FLAGS_H) $(DF_H) $(TARGET_H) \
-   $(OBSTACK_H) $(HASHTAB_H) $(EXCEPT_H) $(PARAMS_H) $(REGS_H) ira.h
+   $(OBSTACK_H) $(HASH_TABLE_H) $(EXCEPT_H) $(PARAMS_H) $(REGS_H) ira.h
 cfgloopmanip.o : cfgloopmanip.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
    $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) \
    coretypes.h $(TM_H) $(OBSTACK_H) $(TREE_FLOW_H)
@@ -3151,8 +3155,7 @@  loop-unswitch.o : loop-unswitch.c $(CONF
    $(EXPR_H) $(TM_H) $(OBSTACK_H)
 loop-unroll.o: loop-unroll.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h \
    $(RTL_H) $(TM_H) $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(PARAMS_H) \
-   $(EXPR_H) $(TM_H) $(HASHTAB_H) $(RECOG_H) \
-   $(OBSTACK_H)
+   $(EXPR_H) $(TM_H) $(HASH_TABLE_H) $(RECOG_H) $(OBSTACK_H)
 dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
$(RTL_H) \
    hard-reg-set.h $(BASIC_BLOCK_H) et-forest.h $(OBSTACK_H)
$(DIAGNOSTIC_CORE_H) \
    $(TIMEVAR_H) graphds.h pointer-set.h $(BITMAP_H)
@@ -3196,8 +3199,8 @@  postreload.o : postreload.c $(CONFIG_H)
 postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
    $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) $(DIAGNOSTIC_CORE_H) \
-   $(TM_P_H) $(EXCEPT_H) $(TREE_H) $(TARGET_H) $(HASHTAB_H) intl.h
$(OBSTACK_H) \
-   $(PARAMS_H) $(TREE_PASS_H) $(DBGCNT_H)
+   $(TM_P_H) $(EXCEPT_H) $(TREE_H) $(TARGET_H) $(HASH_TABLE_H) intl.h \
+   $(OBSTACK_H) $(PARAMS_H) $(TREE_PASS_H) $(DBGCNT_H)
 caller-save.o : caller-save.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h \
    $(TM_H) $(RTL_H) \
    $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H)
$(FUNCTION_H) \
@@ -3230,14 +3233,14 @@  ira-build.o: ira-build.c $(CONFIG_H) $(S
    $(PARAMS_H) $(DF_H) sparseset.h $(IRA_INT_H) reload.h
 ira-costs.o: ira-costs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    hard-reg-set.h $(RTL_H) $(EXPR_H) $(TM_P_H) $(FLAGS_H) $(BASIC_BLOCK_H) \
-   $(REGS_H) addresses.h insn-config.h $(RECOG_H)
$(DIAGNOSTIC_CORE_H) $(TARGET_H) \
-   $(PARAMS_H) $(IRA_INT_H) reload.h
+   $(REGS_H) addresses.h insn-config.h $(RECOG_H) $(DIAGNOSTIC_CORE_H) \
+   $(HASH_TABLE_H) $(TARGET_H) $(PARAMS_H) $(IRA_INT_H) reload.h
 ira-conflicts.o: ira-conflicts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TARGET_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(TREE_H) $(FLAGS_H) \
    insn-config.h $(RECOG_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_CORE_H)
$(TM_P_H) $(PARAMS_H) \
    $(DF_H) sparseset.h addresses.h $(IRA_INT_H)
 ira-color.o: ira-color.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-   $(TARGET_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \
+   $(HASH_TABLE_H) $(TARGET_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \
    $(EXPR_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_CORE_H) $(TM_P_H) reload.h
$(PARAMS_H) \
    $(DF_H) $(IRA_INT_H)
 ira-emit.o: ira-emit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
@@ -3317,7 +3320,7 @@  haifa-sched.o : haifa-sched.c $(CONFIG_H
    $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h
$(FUNCTION_H) \
    $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(EXCEPT_H)
$(TM_P_H) $(TARGET_H) \
    $(PARAMS_H) $(DBGCNT_H) $(CFGLOOP_H) ira.h $(EMIT_RTL_H)
$(COMMON_TARGET_H) \
-   $(HASHTAB_H)
+   $(HASH_TABLE_H)
 sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
    $(FUNCTION_H) $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H)
$(EXCEPT_H) cselib.h \
Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c	(revision 193902)
+++ gcc/tree-cfg.c	(working copy)
@@ -22,6 +22,7 @@  along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "tm.h"
 #include "tree.h"
 #include "tm_p.h"
@@ -88,7 +89,36 @@  struct locus_discrim_map
   location_t locus;
   int discriminator;
 };
-static htab_t discriminator_per_locus;
+
+/* Hashtable helpers.  */
+
+struct locus_descrim_hasher : typed_free_remove <locus_discrim_map>
+{
+  typedef locus_discrim_map value_type;
+  typedef locus_discrim_map compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Trivial hash function for a location_t.  ITEM is a pointer to
+   a hash table entry that maps a location_t to a discriminator.  */
+
+inline hashval_t
+locus_descrim_hasher::hash (const value_type *item)
+{
+  return item->locus;
+}
+
+/* Equality function for the locus-to-discriminator map.  A and B
+   point to the two hash table entries to compare.  */
+
+inline bool
+locus_descrim_hasher::equal (const value_type *a, const compare_type *b)
+{
+  return a->locus == b->locus;
+}
+
+static hash_table <locus_descrim_hasher> discriminator_per_locus;

 /* Basic blocks and flowgraphs.  */
 static void make_blocks (gimple_seq);
@@ -100,8 +130,6 @@  static void make_cond_expr_edges (basic_
 static void make_gimple_switch_edges (basic_block);
 static void make_goto_expr_edges (basic_block);
 static void make_gimple_asm_edges (basic_block);
-static unsigned int locus_map_hash (const void *);
-static int locus_map_eq (const void *, const void *);
 static void assign_discriminator (location_t, basic_block);
 static edge gimple_redirect_edge_and_branch (edge, basic_block);
 static edge gimple_try_redirect_by_replacing_jump (edge, basic_block);
@@ -203,11 +231,10 @@  build_gimple_cfg (gimple_seq seq)
   group_case_labels ();

   /* Create the edges of the flowgraph.  */
-  discriminator_per_locus = htab_create (13, locus_map_hash, locus_map_eq,
-                                         free);
+  discriminator_per_locus.create (13);
   make_edges ();
   cleanup_dead_labels ();
-  htab_delete (discriminator_per_locus);
+  discriminator_per_locus.dispose ();

   /* Debugging dumps.  */

@@ -690,26 +717,6 @@  make_edges (void)
   fold_cond_expr_cond ();
 }

-/* Trivial hash function for a location_t.  ITEM is a pointer to
-   a hash table entry that maps a location_t to a discriminator.  */
-
-static unsigned int
-locus_map_hash (const void *item)
-{
-  return ((const struct locus_discrim_map *) item)->locus;
-}
-
-/* Equality function for the locus-to-discriminator map.  VA and VB
-   point to the two hash table entries to compare.  */
-
-static int
-locus_map_eq (const void *va, const void *vb)
-{
-  const struct locus_discrim_map *a = (const struct locus_discrim_map *) va;
-  const struct locus_discrim_map *b = (const struct locus_discrim_map *) vb;
-  return a->locus == b->locus;
-}
-
 /* Find the next available discriminator value for LOCUS.  The
    discriminator distinguishes among several basic blocks that
    share a common locus, allowing for more accurate sample-based
@@ -723,9 +730,7 @@  next_discriminator_for_locus (location_t

   item.locus = locus;
   item.discriminator = 0;
-  slot = (struct locus_discrim_map **)
-      htab_find_slot_with_hash (discriminator_per_locus, (void *) &item,
-                                (hashval_t) locus, INSERT);
+  slot = discriminator_per_locus.find_slot_with_hash (&item, locus, INSERT);
   gcc_assert (slot);
   if (*slot == HTAB_EMPTY_ENTRY)
     {
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 193902)
+++ gcc/passes.c	(working copy)
@@ -29,6 +29,7 @@  along with GCC; see the file COPYING3.
 #include "coretypes.h"
 #include "tm.h"
 #include "line-map.h"
+#include "hash-table.h"
 #include "input.h"
 #include "tree.h"
 #include "rtl.h"
@@ -582,27 +583,33 @@  struct pass_registry
   struct opt_pass *pass;
 };

+/* Helper for pass_registry hash table.  */
+
+struct pass_registry_hasher : typed_noop_remove <pass_registry>
+{
+  typedef pass_registry value_type;
+  typedef pass_registry compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
 /* Pass registry hash function.  */

-static hashval_t
-passr_hash (const void *p)
+inline hashval_t
+pass_registry_hasher::hash (const value_type *s)
 {
-  const struct pass_registry *const s = (const struct pass_registry *const) p;
   return htab_hash_string (s->unique_name);
 }

 /* Hash equal function  */

-static int
-passr_eq (const void *p1, const void *p2)
+inline bool
+pass_registry_hasher::equal (const value_type *s1, const compare_type *s2)
 {
-  const struct pass_registry *const s1 = (const struct pass_registry
*const) p1;
-  const struct pass_registry *const s2 = (const struct pass_registry
*const) p2;
-
   return !strcmp (s1->unique_name, s2->unique_name);
 }

-static htab_t name_to_pass_map = NULL;
+static hash_table <pass_registry_hasher> name_to_pass_map;