Patchwork [cxx-conversion] Iterator for hash_table, and associated conversions

login
register
mail settings
Submitter Lawrence Crowl
Date Dec. 14, 2012, 4:08 a.m.
Message ID <CAGqM8fbb3AMCTizbZUmef2gnVoVKoKUEm_i9qsn1PtTKHBw2mg@mail.gmail.com>
Download mbox | patch
Permalink /patch/206287/
State New
Headers show

Comments

Lawrence Crowl - Dec. 14, 2012, 4:08 a.m.
Add standard-style iterators to hash_table.
Implement gcc-style FOR_EACH on top of those iterators.

* hash-table.h'hash_table

  Add documentation.
  Add nested class iterator and methods to hash_table.
  Add FOR_EACH_HASH_TABLE_ELEMENT implemented with those iterators.

Convert several uses of htab_t to use hash_table.
Adjust types and calls to match.
These files also use the iterators.
Change uses of FOR_EACH_HTAB_ELEMENT to FOR_EACH_HASH_TABLE_ELEMENT.

* tree-ssa-sccvn.c'vn_tables_s.nary

  Fold vn_nary_op_hash, vn_nary_op_eq into new struct vn_nary_op_hasher.
  Add typedef vn_nary_op_table_type.
  Add typedef vn_nary_op_iterator_type.

* tree-ssa-sccvn.c'vn_tables_s.phis

  Fold vn_phi_hash, free_phi into new struct vn_phi_hasher.
  Add typedef vn_phi_table_type.
  Add typedef vn_phi_iterator_type.

* tree-ssa-sccvn.c'vn_tables_s.references

  Fold vn_reference_hash, vn_reference_op_eq, free_reference
    into new struct vn_reference_hasher.
  Add typedef vn_reference_table_type.
  Add typedef vn_reference_iterator_type.

* tree-ssa-sccvn.c'constant_value_ids

  Fold vn_constant_hash, vn_constant_eq into new struct vn_constant_hasher.

* tree-into-ssa.c'var_infos

  Fold var_info_hash, var_info_eq into new struct var_info_hasher.

* var-tracking.c'emit_note_data_def.vars
* var-tracking.c'shared_hash_def.htab
* var-tracking.c'changed_variables

  Fold variable_htab_hash, variable_htab_eq, variable_htab_free
    into new struct variable_hasher.
  Add typedef variable_table_type.
  Add typedef variable_iterator_type.

* trans-mem.c'tm_log

  Fold tm_log_hash, tm_log_eq, tm_log_free into new struct log_entry_hasher.

* trans-mem.c'tm_memopt_value_numbers

  Fold tm_memop_hash, tm_memop_eq into new struct tm_memop_hasher.

Tested on x86-64.

Okay for branch?
Diego Novillo - Dec. 14, 2012, 4:29 p.m.
On 2012-12-13 23:08 , Lawrence Crowl wrote:

> +  class iterator
> +  {
> +  public:
> +    inline iterator ();
> +    inline iterator (value_type **, value_type **);
> +    inline value_type &operator * ();
> +    void slide ();
> +    inline iterator &operator ++ ();
> +    inline bool operator != (const iterator &) const;
> +  private:
> +    value_type **slot_;
> +    value_type **limit_;
> +  };
> +

This reminds me...  We (OK, *I*) should do the same in vec<>.


> +/* Iterate through the elements of hash_table HTAB,
> +   using hash_table <....>::iterator ITER,
> +   storing each element in RESULT, which is of type TYPE.
> +
> +   This macro has this form for compatibility with the
> +   FOR_EACH_HTAB_ELEMENT currently defined in tree-flow.h.  */
> +
> +#define FOR_EACH_HASH_TABLE_ELEMENT(HTAB, RESULT, TYPE, ITER) \
> +  for ((ITER) = (HTAB).begin (); \
> +       (ITER) != (HTAB).end () ? (RESULT = &*(ITER) , true) : false; \
> +       ++(ITER))
> +

I wonder if we shouldn't just get rid of this style of iteration.  I 
never quite liked it.  I guess it doesn't hurt, though.


The patch is OK.  Thanks.


Diego.

Patch

Index: gcc/tree-into-ssa.c
===================================================================
--- gcc/tree-into-ssa.c	(revision 194487)
+++ gcc/tree-into-ssa.c	(working copy)
@@ -34,7 +34,7 @@  along with GCC; see the file COPYING3.
 #include "tree-flow.h"
 #include "gimple.h"
 #include "tree-inline.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "tree-pass.h"
 #include "cfgloop.h"
 #include "domwalk.h"
@@ -161,9 +161,32 @@  struct var_info_d
 typedef struct var_info_d *var_info_p;


+/* VAR_INFOS hashtable helpers.  */
+
+struct var_info_hasher : typed_free_remove <var_info_d>
+{
+  typedef var_info_d value_type;
+  typedef var_info_d compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+var_info_hasher::hash (const value_type *p)
+{
+  return DECL_UID (p->var);
+}
+
+inline bool
+var_info_hasher::equal (const value_type *p1, const compare_type *p2)
+{
+  return p1->var == p2->var;
+}
+
+
 /* Each entry in VAR_INFOS contains an element of type STRUCT
    VAR_INFO_D.  */
-static htab_t var_infos;
+static hash_table <var_info_hasher> var_infos;


 /* Information stored for SSA names.  */
@@ -341,17 +364,17 @@  static inline var_info_p
 get_var_info (tree decl)
 {
   struct var_info_d vi;
-  void **slot;
+  var_info_d **slot;
   vi.var = decl;
-  slot = htab_find_slot_with_hash (var_infos, &vi, DECL_UID (decl), INSERT);
+  slot = var_infos.find_slot_with_hash (&vi, DECL_UID (decl), INSERT);
   if (*slot == NULL)
     {
       var_info_p v = XCNEW (struct var_info_d);
       v->var = decl;
-      *slot = (void *)v;
+      *slot = v;
       return v;
     }
-  return (var_info_p) *slot;
+  return *slot;
 }


@@ -1039,15 +1062,15 @@  insert_phi_nodes_compare_var_infos (cons
 static void
 insert_phi_nodes (bitmap_head *dfs)
 {
-  htab_iterator hi;
+  hash_table <var_info_hasher>::iterator hi;
   unsigned i;
   var_info_p info;
   vec<var_info_p> vars;

   timevar_push (TV_TREE_INSERT_PHI_NODES);

-  vars.create (htab_elements (var_infos));
-  FOR_EACH_HTAB_ELEMENT (var_infos, info, var_info_p, hi)
+  vars.create (var_infos.elements ());
+  FOR_EACH_HASH_TABLE_ELEMENT (var_infos, info, var_info_p, hi)
     if (info->info.need_phi_state != NEED_PHI_STATE_NO)
       vars.quick_push (info);

@@ -1622,12 +1645,12 @@  debug_tree_ssa (void)
 /* Dump statistics for the hash table HTAB.  */

 static void
-htab_statistics (FILE *file, htab_t htab)
+htab_statistics (FILE *file, hash_table <var_info_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 ());
 }


@@ -1636,7 +1659,7 @@  htab_statistics (FILE *file, htab_t htab
 void
 dump_tree_ssa_stats (FILE *file)
 {
-  if (var_infos)
+  if (var_infos.is_created ())
     {
       fprintf (file, "\nHash table statistics:\n");
       fprintf (file, "    var_infos:   ");
@@ -1655,29 +1678,12 @@  debug_tree_ssa_stats (void)
 }


-/* Hashing and equality functions for VAR_INFOS.  */
-
-static hashval_t
-var_info_hash (const void *p)
-{
-  return DECL_UID (((const struct var_info_d *)p)->var);
-}
-
-static int
-var_info_eq (const void *p1, const void *p2)
-{
-  return ((const struct var_info_d *)p1)->var
-	 == ((const struct var_info_d *)p2)->var;
-}
-
-
 /* Callback for htab_traverse to dump the VAR_INFOS hash table.  */

-static int
-debug_var_infos_r (void **slot, void *data)
+int
+debug_var_infos_r (var_info_d **slot, FILE *file)
 {
-  FILE *file = (FILE *) data;
-  struct var_info_d *info = (struct var_info_d *) *slot;
+  struct var_info_d *info = *slot;

   fprintf (file, "VAR: ");
   print_generic_expr (file, info->var, dump_flags);
@@ -1698,8 +1704,8 @@  void
 dump_var_infos (FILE *file)
 {
   fprintf (file, "\n\nDefinition and live-in blocks:\n\n");
-  if (var_infos)
-    htab_traverse (var_infos, debug_var_infos_r, file);
+  if (var_infos.is_created ())
+    var_infos.traverse <FILE *, debug_var_infos_r> (file);
 }


@@ -2200,7 +2206,7 @@  rewrite_blocks (basic_block entry, enum
   if (dump_file && (dump_flags & TDF_STATS))
     {
       dump_dfa_stats (dump_file);
-      if (var_infos)
+      if (var_infos.is_created ())
 	dump_tree_ssa_stats (dump_file);
     }

@@ -2280,9 +2286,8 @@  init_ssa_renamer (void)
   cfun->gimple_df->in_ssa_p = false;

   /* Allocate memory for the DEF_BLOCKS hash table.  */
-  gcc_assert (var_infos == NULL);
-  var_infos = htab_create (vec_safe_length (cfun->local_decls),
-			   var_info_hash, var_info_eq, free);
+  gcc_assert (!var_infos.is_created ());
+  var_infos.create (vec_safe_length (cfun->local_decls));

   bitmap_obstack_initialize (&update_ssa_obstack);
 }
@@ -2293,11 +2298,8 @@  init_ssa_renamer (void)
 static void
 fini_ssa_renamer (void)
 {
-  if (var_infos)
-    {
-      htab_delete (var_infos);
-      var_infos = NULL;
-    }
+  if (var_infos.is_created ())
+    var_infos.dispose ();

   bitmap_obstack_release (&update_ssa_obstack);

@@ -3162,7 +3164,7 @@  update_ssa (unsigned update_flags)
     {
       /* If we rename bare symbols initialize the mapping to
          auxiliar info we need to keep track of.  */
-      var_infos = htab_create (47, var_info_hash, var_info_eq, free);
+      var_infos.create (47);

       /* If we have to rename some symbols from scratch, we need to
 	 start the process at the root of the CFG.  FIXME, it should
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	(revision 194487)
+++ gcc/var-tracking.c	(working copy)
@@ -101,7 +101,7 @@ 
 #include "sbitmap.h"
 #include "alloc-pool.h"
 #include "fibheap.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "regs.h"
 #include "expr.h"
 #include "tree-pass.h"
@@ -197,19 +197,43 @@  typedef struct micro_operation_def
    declaration.  */
 typedef void *decl_or_value;

-/* Structure for passing some other parameters to function
-   emit_note_insn_var_location.  */
-typedef struct emit_note_data_def
+/* Return true if a decl_or_value DV is a DECL or NULL.  */
+static inline bool
+dv_is_decl_p (decl_or_value dv)
 {
-  /* The instruction which the note will be emitted before/after.  */
-  rtx insn;
+  return !dv || (int) TREE_CODE ((tree) dv) != (int) VALUE;
+}

-  /* Where the note will be emitted (before/after insn)?  */
-  enum emit_note_where where;
+/* Return true if a decl_or_value is a VALUE rtl.  */
+static inline bool
+dv_is_value_p (decl_or_value dv)
+{
+  return dv && !dv_is_decl_p (dv);
+}
+
+/* Return the decl in the decl_or_value.  */
+static inline tree
+dv_as_decl (decl_or_value dv)
+{
+  gcc_checking_assert (dv_is_decl_p (dv));
+  return (tree) dv;
+}
+
+/* Return the value in the decl_or_value.  */
+static inline rtx
+dv_as_value (decl_or_value dv)
+{
+  gcc_checking_assert (dv_is_value_p (dv));
+  return (rtx)dv;
+}
+
+/* Return the opaque pointer in the decl_or_value.  */
+static inline void *
+dv_as_opaque (decl_or_value dv)
+{
+  return dv;
+}

-  /* The variables and values active at this point.  */
-  htab_t vars;
-} emit_note_data;

 /* Description of location of a part of a variable.  The content of a physical
    register is described by a chain of these structures.
@@ -230,58 +254,6 @@  typedef struct attrs_def
   HOST_WIDE_INT offset;
 } *attrs;

-/* Structure holding a refcounted hash table.  If refcount > 1,
-   it must be first unshared before modified.  */
-typedef struct shared_hash_def
-{
-  /* Reference count.  */
-  int refcount;
-
-  /* Actual hash table.  */
-  htab_t htab;
-} *shared_hash;
-
-/* Structure holding the IN or OUT set for a basic block.  */
-typedef struct dataflow_set_def
-{
-  /* Adjustment of stack offset.  */
-  HOST_WIDE_INT stack_adjust;
-
-  /* Attributes for registers (lists of attrs).  */
-  attrs regs[FIRST_PSEUDO_REGISTER];
-
-  /* Variable locations.  */
-  shared_hash vars;
-
-  /* Vars that is being traversed.  */
-  shared_hash traversed_vars;
-} dataflow_set;
-
-/* The structure (one for each basic block) containing the information
-   needed for variable tracking.  */
-typedef struct variable_tracking_info_def
-{
-  /* The vector of micro operations.  */
-  vec<micro_operation> mos;
-
-  /* The IN and OUT set for dataflow analysis.  */
-  dataflow_set in;
-  dataflow_set out;
-
-  /* The permanent-in dataflow set for this block.  This is used to
-     hold values for which we had to compute entry values.  ??? This
-     should probably be dynamically allocated, to avoid using more
-     memory in non-debug builds.  */
-  dataflow_set *permp;
-
-  /* Has the block been visited in DFS?  */
-  bool visited;
-
-  /* Has the block been flooded in VTA?  */
-  bool flooded;
-
-} *variable_tracking_info;
-
 /* Structure for chaining the locations.  */
 typedef struct location_chain_def
 {
@@ -455,6 +427,146 @@  typedef const struct variable_def *const
 			      ? &VAR_LOC_1PAUX (var)->deps	  \
 			      : NULL)

+
+
+typedef unsigned int dvuid;
+
+/* Return the uid of DV.  */
+
+static inline dvuid
+dv_uid (decl_or_value dv)
+{
+  if (dv_is_value_p (dv))
+    return CSELIB_VAL_PTR (dv_as_value (dv))->uid;
+  else
+    return DECL_UID (dv_as_decl (dv));
+}
+
+/* Compute the hash from the uid.  */
+
+static inline hashval_t
+dv_uid2hash (dvuid uid)
+{
+  return uid;
+}
+
+/* The hash function for a mask table in a shared_htab chain.  */
+
+static inline hashval_t
+dv_htab_hash (decl_or_value dv)
+{
+  return dv_uid2hash (dv_uid (dv));
+}
+
+static void variable_htab_free (void *);
+
+/* Variable hashtable helpers.  */
+
+struct variable_hasher
+{
+  typedef variable_def value_type;
+  typedef void 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 *);
+};
+
+/* The hash function for variable_htab, computes the hash value
+   from the declaration of variable X.  */
+
+inline hashval_t
+variable_hasher::hash (const value_type *v)
+{
+  return dv_htab_hash (v->dv);
+}
+
+/* Compare the declaration of variable X with declaration Y.  */
+
+inline bool
+variable_hasher::equal (const value_type *v, const compare_type *y)
+{
+  decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
+
+  return (dv_as_opaque (v->dv) == dv_as_opaque (dv));
+}
+
+/* Free the element of VARIABLE_HTAB (its type is struct variable_def).  */
+
+inline void
+variable_hasher::remove (value_type *var)
+{
+  variable_htab_free (var);
+}
+
+typedef hash_table <variable_hasher> variable_table_type;
+typedef variable_table_type::iterator variable_iterator_type;
+
+/* Structure for passing some other parameters to function
+   emit_note_insn_var_location.  */
+typedef struct emit_note_data_def
+{
+  /* The instruction which the note will be emitted before/after.  */
+  rtx insn;
+
+  /* Where the note will be emitted (before/after insn)?  */
+  enum emit_note_where where;
+
+  /* The variables and values active at this point.  */
+  variable_table_type vars;
+} emit_note_data;
+
+/* Structure holding a refcounted hash table.  If refcount > 1,
+   it must be first unshared before modified.  */
+typedef struct shared_hash_def
+{
+  /* Reference count.  */
+  int refcount;
+
+  /* Actual hash table.  */
+  variable_table_type htab;
+} *shared_hash;
+
+/* Structure holding the IN or OUT set for a basic block.  */
+typedef struct dataflow_set_def
+{
+  /* Adjustment of stack offset.  */
+  HOST_WIDE_INT stack_adjust;
+
+  /* Attributes for registers (lists of attrs).  */
+  attrs regs[FIRST_PSEUDO_REGISTER];
+
+  /* Variable locations.  */
+  shared_hash vars;
+
+  /* Vars that is being traversed.  */
+  shared_hash traversed_vars;
+} dataflow_set;
+
+/* The structure (one for each basic block) containing the information
+   needed for variable tracking.  */
+typedef struct variable_tracking_info_def
+{
+  /* The vector of micro operations.  */
+  vec<micro_operation> mos;
+
+  /* The IN and OUT set for dataflow analysis.  */
+  dataflow_set in;
+  dataflow_set out;
+
+  /* The permanent-in dataflow set for this block.  This is used to
+     hold values for which we had to compute entry values.  ??? This
+     should probably be dynamically allocated, to avoid using more
+     memory in non-debug builds.  */
+  dataflow_set *permp;
+
+  /* Has the block been visited in DFS?  */
+  bool visited;
+
+  /* Has the block been flooded in VTA?  */
+  bool flooded;
+
+} *variable_tracking_info;
+
 /* Alloc pool for struct attrs_def.  */
 static alloc_pool attrs_pool;

@@ -474,7 +586,7 @@  static alloc_pool shared_hash_pool;
 static alloc_pool loc_exp_dep_pool;

 /* Changed variables, notes will be emitted for them.  */
-static htab_t changed_variables;
+static variable_table_type changed_variables;

 /* Shall notes be emitted?  */
 static bool emit_notes;
@@ -482,7 +594,7 @@  static bool emit_notes;
 /* Values whose dynamic location lists have gone empty, but whose
    cselib location lists are still usable.  Use this to hold the
    current location, the backlinks, etc, during emit_notes.  */
-static htab_t dropped_values;
+static variable_table_type dropped_values;

 /* Empty shared hashtable.  */
 static shared_hash empty_shared_hash;
@@ -510,9 +622,6 @@  static void stack_adjust_offset_pre_post
 static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
 					       HOST_WIDE_INT *);
 static bool vt_stack_adjustments (void);
-static hashval_t variable_htab_hash (const void *);
-static int variable_htab_eq (const void *, const void *);
-static void variable_htab_free (void *);

 static void init_attrs_list_set (attrs *);
 static void attrs_list_clear (attrs *);
@@ -521,9 +630,9 @@  static void attrs_list_insert (attrs *,
 static void attrs_list_copy (attrs *, attrs);
 static void attrs_list_union (attrs *, attrs);

-static void **unshare_variable (dataflow_set *set, void **slot, variable var,
-				enum var_init_status);
-static void vars_copy (htab_t, htab_t);
+static variable_def **unshare_variable (dataflow_set *set, variable_def **slot,
+					variable var, enum var_init_status);
+static void vars_copy (variable_table_type, variable_table_type);
 static tree var_debug_decl (tree);
 static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
 static void var_reg_delete_and_set (dataflow_set *, rtx, bool,
@@ -540,7 +649,7 @@  static void dataflow_set_clear (dataflow
 static void dataflow_set_copy (dataflow_set *, dataflow_set *);
 static int variable_union_info_cmp_pos (const void *, const void *);
 static void dataflow_set_union (dataflow_set *, dataflow_set *);
-static location_chain find_loc_in_1pdv (rtx, variable, htab_t);
+static location_chain find_loc_in_1pdv (rtx, variable, variable_table_type);
 static bool canon_value_cmp (rtx, rtx);
 static int loc_cmp (rtx, rtx);
 static bool variable_part_different_p (variable_part *, variable_part *);
@@ -559,32 +668,27 @@  static bool compute_bb_dataflow (basic_b
 static bool vt_find_locations (void);

 static void dump_attrs_list (attrs);
-static int dump_var_slot (void **, void *);
 static void dump_var (variable);
-static void dump_vars (htab_t);
+static void dump_vars (variable_table_type);
 static void dump_dataflow_set (dataflow_set *);
 static void dump_dataflow_sets (void);

 static void set_dv_changed (decl_or_value, bool);
 static void variable_was_changed (variable, dataflow_set *);
-static void **set_slot_part (dataflow_set *, rtx, void **,
-			     decl_or_value, HOST_WIDE_INT,
-			     enum var_init_status, rtx);
+static variable_def **set_slot_part (dataflow_set *, rtx, variable_def **,
+				     decl_or_value, HOST_WIDE_INT,
+				     enum var_init_status, rtx);
 static void set_variable_part (dataflow_set *, rtx,
 			       decl_or_value, HOST_WIDE_INT,
 			       enum var_init_status, rtx, enum insert_option);
-static void **clobber_slot_part (dataflow_set *, rtx,
-				 void **, HOST_WIDE_INT, rtx);
+static variable_def **clobber_slot_part (dataflow_set *, rtx,
+					 variable_def **, HOST_WIDE_INT, rtx);
 static void clobber_variable_part (dataflow_set *, rtx,
 				   decl_or_value, HOST_WIDE_INT, rtx);
-static void **delete_slot_part (dataflow_set *, rtx, void **, HOST_WIDE_INT);
+static variable_def **delete_slot_part (dataflow_set *, rtx, variable_def **,
+					HOST_WIDE_INT);
 static void delete_variable_part (dataflow_set *, rtx,
 				  decl_or_value, HOST_WIDE_INT);
-static int emit_note_insn_var_location (void **, void *);
-static void emit_notes_for_changes (rtx, enum emit_note_where, shared_hash);
-static int emit_notes_for_differences_1 (void **, void *);
-static int emit_notes_for_differences_2 (void **, void *);
-static void emit_notes_for_differences (rtx, dataflow_set *, dataflow_set *);
 static void emit_notes_in_bb (basic_block, dataflow_set *);
 static void vt_emit_notes (void);

@@ -1189,36 +1293,6 @@  adjust_insn (basic_block bb, rtx insn)
     }
 }

-/* Return true if a decl_or_value DV is a DECL or NULL.  */
-static inline bool
-dv_is_decl_p (decl_or_value dv)
-{
-  return !dv || (int) TREE_CODE ((tree) dv) != (int) VALUE;
-}
-
-/* Return true if a decl_or_value is a VALUE rtl.  */
-static inline bool
-dv_is_value_p (decl_or_value dv)
-{
-  return dv && !dv_is_decl_p (dv);
-}
-
-/* Return the decl in the decl_or_value.  */
-static inline tree
-dv_as_decl (decl_or_value dv)
-{
-  gcc_checking_assert (dv_is_decl_p (dv));
-  return (tree) dv;
-}
-
-/* Return the value in the decl_or_value.  */
-static inline rtx
-dv_as_value (decl_or_value dv)
-{
-  gcc_checking_assert (dv_is_value_p (dv));
-  return (rtx)dv;
-}
-
 /* Return the DEBUG_EXPR of a DEBUG_EXPR_DECL or the VALUE in DV.  */
 static inline rtx
 dv_as_rtx (decl_or_value dv)
@@ -1234,13 +1308,6 @@  dv_as_rtx (decl_or_value dv)
   return DECL_RTL_KNOWN_SET (decl);
 }

-/* Return the opaque pointer in the decl_or_value.  */
-static inline void *
-dv_as_opaque (decl_or_value dv)
-{
-  return dv;
-}
-
 /* Return nonzero if a decl_or_value must not have more than one
    variable part.  The returned value discriminates among various
    kinds of one-part DVs ccording to enum onepart_enum.  */
@@ -1328,57 +1395,6 @@  debug_dv (decl_or_value dv)
     debug_generic_stmt (dv_as_decl (dv));
 }

-typedef unsigned int dvuid;
-
-/* Return the uid of DV.  */
-
-static inline dvuid
-dv_uid (decl_or_value dv)
-{
-  if (dv_is_value_p (dv))
-    return CSELIB_VAL_PTR (dv_as_value (dv))->uid;
-  else
-    return DECL_UID (dv_as_decl (dv));
-}
-
-/* Compute the hash from the uid.  */
-
-static inline hashval_t
-dv_uid2hash (dvuid uid)
-{
-  return uid;
-}
-
-/* The hash function for a mask table in a shared_htab chain.  */
-
-static inline hashval_t
-dv_htab_hash (decl_or_value dv)
-{
-  return dv_uid2hash (dv_uid (dv));
-}
-
-/* The hash function for variable_htab, computes the hash value
-   from the declaration of variable X.  */
-
-static hashval_t
-variable_htab_hash (const void *x)
-{
-  const_variable const v = (const_variable) x;
-
-  return dv_htab_hash (v->dv);
-}
-
-/* Compare the declaration of variable X with declaration Y.  */
-
-static int
-variable_htab_eq (const void *x, const void *y)
-{
-  const_variable const v = (const_variable) x;
-  decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
-
-  return (dv_as_opaque (v->dv) == dv_as_opaque (dv));
-}
-
 static void loc_exp_dep_clear (variable var);

 /* Free the element of VARIABLE_HTAB (its type is struct variable_def).  */
@@ -1535,7 +1551,7 @@  shared_hash_shared (shared_hash vars)

 /* Return the hash table for VARS.  */

-static inline htab_t
+static inline variable_table_type
 shared_hash_htab (shared_hash vars)
 {
   return vars->htab;
@@ -1559,9 +1575,7 @@  shared_hash_unshare (shared_hash vars)
   shared_hash new_vars = (shared_hash) pool_alloc (shared_hash_pool);
   gcc_assert (vars->refcount > 1);
   new_vars->refcount = 1;
-  new_vars->htab
-    = htab_create (htab_elements (vars->htab) + 3, variable_htab_hash,
-		   variable_htab_eq, variable_htab_free);
+  new_vars->htab.create (vars->htab.elements () + 3);
   vars_copy (new_vars->htab, vars->htab);
   vars->refcount--;
   return new_vars;
@@ -1585,7 +1599,7 @@  shared_hash_destroy (shared_hash vars)
   gcc_checking_assert (vars->refcount > 0);
   if (--vars->refcount == 0)
     {
-      htab_delete (vars->htab);
+      vars->htab.dispose ();
       pool_free (shared_hash_pool, vars);
     }
 }
@@ -1593,16 +1607,16 @@  shared_hash_destroy (shared_hash vars)
 /* Unshare *PVARS if shared and return slot for DV.  If INS is
    INSERT, insert it if not already present.  */

-static inline void **
+static inline variable_def **
 shared_hash_find_slot_unshare_1 (shared_hash *pvars, decl_or_value dv,
 				 hashval_t dvhash, enum insert_option ins)
 {
   if (shared_hash_shared (*pvars))
     *pvars = shared_hash_unshare (*pvars);
-  return htab_find_slot_with_hash (shared_hash_htab (*pvars), dv, dvhash, ins);
+  return shared_hash_htab (*pvars).find_slot_with_hash (dv, dvhash, ins);
 }

-static inline void **
+static inline variable_def **
 shared_hash_find_slot_unshare (shared_hash *pvars, decl_or_value dv,
 			       enum insert_option ins)
 {
@@ -1613,15 +1627,15 @@  shared_hash_find_slot_unshare (shared_ha
    If it is not present, insert it only VARS is not shared, otherwise
    return NULL.  */

-static inline void **
+static inline variable_def **
 shared_hash_find_slot_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
 {
-  return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash,
-				   shared_hash_shared (vars)
-				   ? NO_INSERT : INSERT);
+  return shared_hash_htab (vars).find_slot_with_hash (dv, dvhash,
+						      shared_hash_shared (vars)
+						      ? NO_INSERT : INSERT);
 }

-static inline void **
+static inline variable_def **
 shared_hash_find_slot (shared_hash vars, decl_or_value dv)
 {
   return shared_hash_find_slot_1 (vars, dv, dv_htab_hash (dv));
@@ -1629,15 +1643,14 @@  shared_hash_find_slot (shared_hash vars,

 /* Return slot for DV only if it is already present in the hash table.  */

-static inline void **
+static inline variable_def **
 shared_hash_find_slot_noinsert_1 (shared_hash vars, decl_or_value dv,
 				  hashval_t dvhash)
 {
-  return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash,
-				   NO_INSERT);
+  return shared_hash_htab (vars).find_slot_with_hash (dv, dvhash, NO_INSERT);
 }

-static inline void **
+static inline variable_def **
 shared_hash_find_slot_noinsert (shared_hash vars, decl_or_value dv)
 {
   return shared_hash_find_slot_noinsert_1 (vars, dv, dv_htab_hash (dv));
@@ -1649,7 +1662,7 @@  shared_hash_find_slot_noinsert (shared_h
 static inline variable
 shared_hash_find_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
 {
-  return (variable) htab_find_with_hash (shared_hash_htab (vars), dv, dvhash);
+  return shared_hash_htab (vars).find_with_hash (dv, dvhash);
 }

 static inline variable
@@ -1678,8 +1691,8 @@  static bool dst_can_be_shared;

 /* Return a copy of a variable VAR and insert it to dataflow set SET.  */

-static void **
-unshare_variable (dataflow_set *set, void **slot, variable var,
+static variable_def **
+unshare_variable (dataflow_set *set, variable_def **slot, variable var,
 		  enum var_init_status initialized)
 {
   variable new_var;
@@ -1745,8 +1758,8 @@  unshare_variable (dataflow_set *set, voi
   *slot = new_var;
   if (var->in_changed_variables)
     {
-      void **cslot
-	= htab_find_slot_with_hash (changed_variables, var->dv,
+      variable_def **cslot
+	= changed_variables.find_slot_with_hash (var->dv,
 				    dv_htab_hash (var->dv), NO_INSERT);
       gcc_assert (*cslot == (void *) var);
       var->in_changed_variables = false;
@@ -1760,18 +1773,16 @@  unshare_variable (dataflow_set *set, voi
 /* Copy all variables from hash table SRC to hash table DST.  */

 static void
-vars_copy (htab_t dst, htab_t src)
+vars_copy (variable_table_type dst, variable_table_type src)
 {
-  htab_iterator hi;
+  variable_iterator_type hi;
   variable var;

-  FOR_EACH_HTAB_ELEMENT (src, var, variable, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (src, var, variable, hi)
     {
-      void **dstp;
+      variable_def **dstp;
       var->refcount++;
-      dstp = htab_find_slot_with_hash (dst, var->dv,
-				       dv_htab_hash (var->dv),
-				       INSERT);
+      dstp = dst.find_slot_with_hash (var->dv, dv_htab_hash (var->dv), INSERT);
       *dstp = var;
     }
 }
@@ -2015,8 +2026,7 @@  vt_canonicalize_addr (dataflow_set *set,
 	}

       dv = dv_from_rtx (x);
-      var = (variable) htab_find_with_hash (shared_hash_htab (set->vars),
-					    dv, dv_htab_hash (dv));
+      var = shared_hash_htab (set->vars).find_with_hash (dv,
dv_htab_hash (dv));
       if (!var)
 	break;

@@ -2101,13 +2111,12 @@  struct overlapping_mems
    canonicalized form of COMS->LOC's address, and COMS->LOC must be
    canonicalized itself.  */

-static int
-drop_overlapping_mem_locs (void **slot, void *data)
+int
+drop_overlapping_mem_locs (variable_def **slot, overlapping_mems *coms)
 {
-  struct overlapping_mems *coms = (struct overlapping_mems *)data;
   dataflow_set *set = coms->set;
   rtx mloc = coms->loc, addr = coms->addr;
-  variable var = (variable) *slot;
+  variable var = *slot;

   if (var->onepart == ONEPART_VALUE)
     {
@@ -2127,7 +2136,7 @@  drop_overlapping_mem_locs (void **slot,
 	    return 1;

 	  slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
-	  var = (variable)*slot;
+	  var = *slot;
 	  gcc_assert (var->n_var_parts == 1);
 	}

@@ -2183,8 +2192,8 @@  clobber_overlapping_mems (dataflow_set *
   coms.addr = vt_canonicalize_addr (set, XEXP (loc, 0));

   set->traversed_vars = set->vars;
-  htab_traverse (shared_hash_htab (set->vars),
-		 drop_overlapping_mem_locs, &coms);
+  shared_hash_htab (set->vars)
+    .traverse <overlapping_mems*, drop_overlapping_mem_locs> (&coms);
   set->traversed_vars = NULL;
 }

@@ -2569,7 +2578,7 @@  static int
 variable_union (variable src, dataflow_set *set)
 {
   variable dst;
-  void **dstp;
+  variable_def **dstp;
   int i, j, k;

   dstp = shared_hash_find_slot (set->vars, src->dv);
@@ -2587,7 +2596,7 @@  variable_union (variable src, dataflow_s
       return 1;
     }
   else
-    dst = (variable) *dstp;
+    dst = *dstp;

   gcc_assert (src->n_var_parts);
   gcc_checking_assert (src->onepart == dst->onepart);
@@ -2621,7 +2630,7 @@  variable_union (variable src, dataflow_s
 		{
 		  dstp = unshare_variable (set, dstp, dst,
 					   VAR_INIT_STATUS_INITIALIZED);
-		  dst = (variable)*dstp;
+		  dst = *dstp;
 		  goto restart_onepart_unshared;
 		}

@@ -2674,7 +2683,7 @@  variable_union (variable src, dataflow_s
   if (dst->n_var_parts != k && shared_var_p (dst, set->vars))
     {
       dstp = unshare_variable (set, dstp, dst, VAR_INIT_STATUS_UNKNOWN);
-      dst = (variable)*dstp;
+      dst = *dstp;
     }

   i = src->n_var_parts - 1;
@@ -2949,10 +2958,11 @@  dataflow_set_union (dataflow_set *dst, d
     }
   else
     {
-      htab_iterator hi;
+      variable_iterator_type hi;
       variable var;

-      FOR_EACH_HTAB_ELEMENT (shared_hash_htab (src->vars), var, variable, hi)
+      FOR_EACH_HASH_TABLE_ELEMENT (shared_hash_htab (src->vars),
+				   var, variable, hi)
 	variable_union (var, dst);
     }
 }
@@ -3015,7 +3025,7 @@  dv_changed_p (decl_or_value dv)
    be in star-canonical form.  */

 static location_chain
-find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
+find_loc_in_1pdv (rtx loc, variable var, variable_table_type vars)
 {
   location_chain node;
   enum rtx_code loc_code;
@@ -3072,7 +3082,7 @@  find_loc_in_1pdv (rtx loc, variable var,
       gcc_checking_assert (!node->next);

       dv = dv_from_value (node->loc);
-      rvar = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
+      rvar = vars.find_with_hash (dv, dv_htab_hash (dv));
       return find_loc_in_1pdv (loc, rvar, vars);
     }

@@ -3388,10 +3398,11 @@  loc_cmp (rtx x, rtx y)
 #if ENABLE_CHECKING
 /* Check the order of entries in one-part variables.   */

-static int
-canonicalize_loc_order_check (void **slot, void *data ATTRIBUTE_UNUSED)
+int
+canonicalize_loc_order_check (variable_def **slot,
+			      dataflow_set *data ATTRIBUTE_UNUSED)
 {
-  variable var = (variable) *slot;
+  variable var = *slot;
   location_chain node, next;

 #ifdef ENABLE_RTL_CHECKING
@@ -3423,11 +3434,10 @@  canonicalize_loc_order_check (void **slo
    Ensure less likely values can reach more likely neighbors, making
    the connections bidirectional.  */

-static int
-canonicalize_values_mark (void **slot, void *data)
+int
+canonicalize_values_mark (variable_def **slot, dataflow_set *set)
 {
-  dataflow_set *set = (dataflow_set *)data;
-  variable var = (variable) *slot;
+  variable var = *slot;
   decl_or_value dv = var->dv;
   rtx val;
   location_chain node;
@@ -3447,7 +3457,8 @@  canonicalize_values_mark (void **slot, v
 	else
 	  {
 	    decl_or_value odv = dv_from_value (node->loc);
-	    void **oslot = shared_hash_find_slot_noinsert (set->vars, odv);
+	    variable_def **oslot;
+	    oslot = shared_hash_find_slot_noinsert (set->vars, odv);

 	    set_slot_part (set, val, oslot, odv, 0,
 			   node->init, NULL_RTX);
@@ -3462,16 +3473,15 @@  canonicalize_values_mark (void **slot, v
 /* Remove redundant entries from equivalence lists in onepart
    variables, canonicalizing equivalence sets into star shapes.  */

-static int
-canonicalize_values_star (void **slot, void *data)
+int
+canonicalize_values_star (variable_def **slot, dataflow_set *set)
 {
-  dataflow_set *set = (dataflow_set *)data;
-  variable var = (variable) *slot;
+  variable var = *slot;
   decl_or_value dv = var->dv;
   location_chain node;
   decl_or_value cdv;
   rtx val, cval;
-  void **cslot;
+  variable_def **cslot;
   bool has_value;
   bool has_marks;

@@ -3537,7 +3547,7 @@  canonicalize_values_star (void **slot, v
 		clobber_variable_part (set, NULL, var->dv, 0, NULL);
 		return 1;
 	      }
-	    var = (variable)*slot;
+	    var = *slot;
 	    gcc_assert (dv_is_value_p (var->dv));
 	    if (var->n_var_parts == 0)
 	      return 1;
@@ -3667,7 +3677,7 @@  canonicalize_values_star (void **slot, v
   slot = clobber_slot_part (set, cval, slot, 0, NULL);

   /* Variable may have been unshared.  */
-  var = (variable)*slot;
+  var = *slot;
   gcc_checking_assert (var->n_var_parts &&
var->var_part[0].loc_chain->loc == cval
 		       && var->var_part[0].loc_chain->next == NULL);

@@ -3684,16 +3694,15 @@  canonicalize_values_star (void **slot, v
    have determined or even seen the canonical value of a set when we
    get to a variable that references another member of the set.  */

-static int
-canonicalize_vars_star (void **slot, void *data)
+int
+canonicalize_vars_star (variable_def **slot, dataflow_set *set)
 {
-  dataflow_set *set = (dataflow_set *)data;
-  variable var = (variable) *slot;
+  variable var = *slot;
   decl_or_value dv = var->dv;
   location_chain node;
   rtx cval;
   decl_or_value cdv;
-  void **cslot;
+  variable_def **cslot;
   variable cvar;
   location_chain cnode;

@@ -3715,7 +3724,7 @@  canonicalize_vars_star (void **slot, voi
   cslot = shared_hash_find_slot_noinsert (set->vars, cdv);
   if (!cslot)
     return 1;
-  cvar = (variable)*cslot;
+  cvar = *cslot;
   gcc_assert (cvar->n_var_parts == 1);

   cnode = cvar->var_part[0].loc_chain;
@@ -3747,7 +3756,7 @@  static int
 variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
 {
   dataflow_set *dst = dsm->dst;
-  void **dstslot;
+  variable_def **dstslot;
   variable s2var, dvar = NULL;
   decl_or_value dv = s1var->dv;
   onepart_enum_t onepart = s1var->onepart;
@@ -3787,7 +3796,7 @@  variable_merge_over_cur (variable s1var,
   dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
   if (dstslot)
     {
-      dvar = (variable)*dstslot;
+      dvar = *dstslot;
       gcc_assert (dvar->refcount == 1
 		  && dvar->onepart == onepart
 		  && dvar->n_var_parts == 1);
@@ -3885,8 +3894,8 @@  variable_merge_over_cur (variable s1var,
       nodep = nextp;
     }

-  if (dvar != (variable)*dstslot)
-    dvar = (variable)*dstslot;
+  if (dvar != *dstslot)
+    dvar = *dstslot;
   nodep = &dvar->var_part[0].loc_chain;

   if (val)
@@ -3908,7 +3917,7 @@  variable_merge_over_cur (variable s1var,
       gcc_checking_assert (dstslot
 			   == shared_hash_find_slot_noinsert_1 (dst->vars,
 								dv, dvhash));
-      dvar = (variable)*dstslot;
+      dvar = *dstslot;
     }
   else
     {
@@ -3944,7 +3953,7 @@  variable_merge_over_cur (variable s1var,
 	      if (GET_CODE (node->loc) == VALUE)
 		{
 		  decl_or_value dv = dv_from_value (node->loc);
-		  void **slot = NULL;
+		  variable_def **slot = NULL;

 		  if (shared_hash_shared (dst->vars))
 		    slot = shared_hash_find_slot_noinsert (dst->vars, dv);
@@ -3976,7 +3985,7 @@  variable_merge_over_cur (variable s1var,
 	  gcc_checking_assert (dstslot
 			       == shared_hash_find_slot_noinsert_1 (dst->vars,
 								    dv, dvhash));
-	  dvar = (variable)*dstslot;
+	  dvar = *dstslot;
 	}
     }

@@ -4012,7 +4021,7 @@  variable_merge_over_src (variable s2var,

   if (!s2var->onepart)
     {
-      void **dstp = shared_hash_find_slot (dst->vars, dv);
+      variable_def **dstp = shared_hash_find_slot (dst->vars, dv);
       *dstp = s2var;
       s2var->refcount++;
       return 1;
@@ -4033,19 +4042,17 @@  dataflow_set_merge (dataflow_set *dst, d
   struct dfset_merge dsm;
   int i;
   size_t src1_elems, src2_elems;
-  htab_iterator hi;
+  variable_iterator_type hi;
   variable var;

-  src1_elems = htab_elements (shared_hash_htab (src1->vars));
-  src2_elems = htab_elements (shared_hash_htab (src2->vars));
+  src1_elems = shared_hash_htab (src1->vars).elements ();
+  src2_elems = shared_hash_htab (src2->vars).elements ();
   dataflow_set_init (dst);
   dst->stack_adjust = cur.stack_adjust;
   shared_hash_destroy (dst->vars);
   dst->vars = (shared_hash) pool_alloc (shared_hash_pool);
   dst->vars->refcount = 1;
-  dst->vars->htab
-    = htab_create (MAX (src1_elems, src2_elems), variable_htab_hash,
-		   variable_htab_eq, variable_htab_free);
+  dst->vars->htab.create (MAX (src1_elems, src2_elems));

   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     attrs_list_mpdv_union (&dst->regs[i], src1->regs[i], src2->regs[i]);
@@ -4055,9 +4062,11 @@  dataflow_set_merge (dataflow_set *dst, d
   dsm.cur = src1;
   dsm.src_onepart_cnt = 0;

-  FOR_EACH_HTAB_ELEMENT (shared_hash_htab (dsm.src->vars), var, variable, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (shared_hash_htab (dsm.src->vars),
+			       var, variable, hi)
     variable_merge_over_src (var, &dsm);
-  FOR_EACH_HTAB_ELEMENT (shared_hash_htab (dsm.cur->vars), var, variable, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (shared_hash_htab (dsm.cur->vars),
+			       var, variable, hi)
     variable_merge_over_cur (var, &dsm);

   if (dsm.src_onepart_cnt)
@@ -4127,7 +4136,7 @@  dataflow_set_equiv_regs (dataflow_set *s
 	if (list->offset == 0 && dv_onepart_p (list->dv))
 	  {
 	    rtx cval = canon[(int)GET_MODE (list->loc)];
-	    void **slot;
+	    variable_def **slot;

 	    if (!cval)
 	      continue;
@@ -4198,12 +4207,11 @@  struct dfset_post_merge
 /* Create values for incoming expressions associated with one-part
    variables that don't have value numbers for them.  */

-static int
-variable_post_merge_new_vals (void **slot, void *info)
+int
+variable_post_merge_new_vals (variable_def **slot, dfset_post_merge *dfpm)
 {
-  struct dfset_post_merge *dfpm = (struct dfset_post_merge *)info;
   dataflow_set *set = dfpm->set;
-  variable var = (variable)*slot;
+  variable var = *slot;
   location_chain node;

   if (!var->onepart || !var->n_var_parts)
@@ -4228,7 +4236,7 @@  variable_post_merge_new_vals (void **slo
 		{
 		  slot = unshare_variable (set, slot, var,
 					   VAR_INIT_STATUS_INITIALIZED);
-		  var = (variable)*slot;
+		  var = *slot;
 		  goto restart;
 		}

@@ -4335,12 +4343,11 @@  variable_post_merge_new_vals (void **slo
 /* Reset values in the permanent set that are not associated with the
    chosen expression.  */

-static int
-variable_post_merge_perm_vals (void **pslot, void *info)
+int
+variable_post_merge_perm_vals (variable_def **pslot, dfset_post_merge *dfpm)
 {
-  struct dfset_post_merge *dfpm = (struct dfset_post_merge *)info;
   dataflow_set *set = dfpm->set;
-  variable pvar = (variable)*pslot, var;
+  variable pvar = *pslot, var;
   location_chain pnode;
   decl_or_value dv;
   attrs att;
@@ -4404,13 +4411,15 @@  dataflow_post_merge_adjust (dataflow_set
   dfpm.set = set;
   dfpm.permp = permp;

-  htab_traverse (shared_hash_htab (set->vars), variable_post_merge_new_vals,
-		 &dfpm);
+  shared_hash_htab (set->vars)
+    .traverse <dfset_post_merge*, variable_post_merge_new_vals> (&dfpm);
   if (*permp)
-    htab_traverse (shared_hash_htab ((*permp)->vars),
-		   variable_post_merge_perm_vals, &dfpm);
-  htab_traverse (shared_hash_htab (set->vars), canonicalize_values_star, set);
-  htab_traverse (shared_hash_htab (set->vars), canonicalize_vars_star, set);
+    shared_hash_htab ((*permp)->vars)
+      .traverse <dfset_post_merge*, variable_post_merge_perm_vals> (&dfpm);
+  shared_hash_htab (set->vars)
+    .traverse <dataflow_set *, canonicalize_values_star> (set);
+  shared_hash_htab (set->vars)
+    .traverse <dataflow_set *, canonicalize_vars_star> (set);
 }

 /* Return a node whose loc is a MEM that refers to EXPR in the
@@ -4418,7 +4427,7 @@  dataflow_post_merge_adjust (dataflow_set
    any values recursively mentioned in the location lists.  */

 static location_chain
-find_mem_expr_in_1pdv (tree expr, rtx val, htab_t vars)
+find_mem_expr_in_1pdv (tree expr, rtx val, variable_table_type vars)
 {
   location_chain node;
   decl_or_value dv;
@@ -4432,7 +4441,7 @@  find_mem_expr_in_1pdv (tree expr, rtx va
 	      && !VALUE_RECURSED_INTO (val));

   dv = dv_from_value (val);
-  var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
+  var = vars.find_with_hash (dv, dv_htab_hash (dv));

   if (!var)
     return NULL;
@@ -4489,11 +4498,10 @@  mem_dies_at_call (rtx mem)
    one-part variable, except those whose MEM attributes map back to
    the variable itself, directly or within a VALUE.  */

-static int
-dataflow_set_preserve_mem_locs (void **slot, void *data)
+int
+dataflow_set_preserve_mem_locs (variable_def **slot, dataflow_set *set)
 {
-  dataflow_set *set = (dataflow_set *) data;
-  variable var = (variable) *slot;
+  variable var = *slot;

   if (var->onepart == ONEPART_VDECL || var->onepart == ONEPART_DEXPR)
     {
@@ -4527,7 +4535,7 @@  dataflow_set_preserve_mem_locs (void **s
 	    return 1;

 	  slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
-	  var = (variable)*slot;
+	  var = *slot;
 	  gcc_assert (var->n_var_parts == 1);
 	}

@@ -4599,11 +4607,10 @@  dataflow_set_preserve_mem_locs (void **s
 /* Remove all MEMs from the location list of a hash table entry for a
    value.  */

-static int
-dataflow_set_remove_mem_locs (void **slot, void *data)
+int
+dataflow_set_remove_mem_locs (variable_def **slot, dataflow_set *set)
 {
-  dataflow_set *set = (dataflow_set *) data;
-  variable var = (variable) *slot;
+  variable var = *slot;

   if (var->onepart == ONEPART_VALUE)
     {
@@ -4624,7 +4631,7 @@  dataflow_set_remove_mem_locs (void **slo
 	    return 1;

 	  slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
-	  var = (variable)*slot;
+	  var = *slot;
 	  gcc_assert (var->n_var_parts == 1);
 	}

@@ -4684,11 +4691,11 @@  dataflow_set_clear_at_call (dataflow_set
   if (MAY_HAVE_DEBUG_INSNS)
     {
       set->traversed_vars = set->vars;
-      htab_traverse (shared_hash_htab (set->vars),
-		     dataflow_set_preserve_mem_locs, set);
+      shared_hash_htab (set->vars)
+	.traverse <dataflow_set *, dataflow_set_preserve_mem_locs> (set);
       set->traversed_vars = set->vars;
-      htab_traverse (shared_hash_htab (set->vars),
dataflow_set_remove_mem_locs,
-		     set);
+      shared_hash_htab (set->vars)
+	.traverse <dataflow_set *, dataflow_set_remove_mem_locs> (set);
       set->traversed_vars = NULL;
     }
 }
@@ -4787,21 +4794,21 @@  variable_different_p (variable var1, var
 static bool
 dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
 {
-  htab_iterator hi;
+  variable_iterator_type hi;
   variable var1;

   if (old_set->vars == new_set->vars)
     return false;

-  if (htab_elements (shared_hash_htab (old_set->vars))
-      != htab_elements (shared_hash_htab (new_set->vars)))
+  if (shared_hash_htab (old_set->vars).elements ()
+      != shared_hash_htab (new_set->vars).elements ())
     return true;

-  FOR_EACH_HTAB_ELEMENT (shared_hash_htab (old_set->vars), var1, variable, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (shared_hash_htab (old_set->vars),
+			       var1, variable, hi)
     {
-      htab_t htab = shared_hash_htab (new_set->vars);
-      variable var2 = (variable) htab_find_with_hash (htab, var1->dv,
-						      dv_htab_hash (var1->dv));
+      variable_table_type htab = shared_hash_htab (new_set->vars);
+      variable var2 = htab.find_with_hash (var1->dv, dv_htab_hash (var1->dv));
       if (!var2)
 	{
 	  if (dump_file && (dump_flags & TDF_DETAILS))
@@ -6698,13 +6705,13 @@  compute_bb_dataflow (basic_block bb)
   if (MAY_HAVE_DEBUG_INSNS)
     {
       dataflow_set_equiv_regs (out);
-      htab_traverse (shared_hash_htab (out->vars), canonicalize_values_mark,
-		     out);
-      htab_traverse (shared_hash_htab (out->vars), canonicalize_values_star,
-		     out);
+      shared_hash_htab (out->vars)
+	.traverse <dataflow_set *, canonicalize_values_mark> (out);
+      shared_hash_htab (out->vars)
+	.traverse <dataflow_set *, canonicalize_values_star> (out);
 #if ENABLE_CHECKING
-      htab_traverse (shared_hash_htab (out->vars),
-		     canonicalize_loc_order_check, out);
+      shared_hash_htab (out->vars)
+	.traverse <dataflow_set *, canonicalize_loc_order_check> (out);
 #endif
     }
   changed = dataflow_set_different (&old_out, out);
@@ -6776,12 +6783,10 @@  vt_find_locations (void)
 	      if (VTI (bb)->in.vars)
 		{
 		  htabsz
-		    -= (htab_size (shared_hash_htab (VTI (bb)->in.vars))
-			+ htab_size (shared_hash_htab (VTI (bb)->out.vars)));
-		  oldinsz
-		    = htab_elements (shared_hash_htab (VTI (bb)->in.vars));
-		  oldoutsz
-		    = htab_elements (shared_hash_htab (VTI (bb)->out.vars));
+		    -= shared_hash_htab (VTI (bb)->in.vars).size ()
+			+ shared_hash_htab (VTI (bb)->out.vars).size ();
+		  oldinsz = shared_hash_htab (VTI (bb)->in.vars).elements ();
+		  oldoutsz = shared_hash_htab (VTI (bb)->out.vars).elements ();
 		}
 	      else
 		oldinsz = oldoutsz = 0;
@@ -6819,9 +6824,9 @@  vt_find_locations (void)
 #if ENABLE_CHECKING
 		      /* Merge and merge_adjust should keep entries in
 			 canonical order.  */
-		      htab_traverse (shared_hash_htab (in->vars),
-				     canonicalize_loc_order_check,
-				     in);
+		      shared_hash_htab (in->vars)
+			.traverse <dataflow_set *,
+				   canonicalize_loc_order_check> (in);
 #endif
 		      if (dst_can_be_shared)
 			{
@@ -6841,8 +6846,8 @@  vt_find_locations (void)
 		}

 	      changed = compute_bb_dataflow (bb);
-	      htabsz += (htab_size (shared_hash_htab (VTI (bb)->in.vars))
-			 + htab_size (shared_hash_htab (VTI (bb)->out.vars)));
+	      htabsz += shared_hash_htab (VTI (bb)->in.vars).size ()
+			 + shared_hash_htab (VTI (bb)->out.vars).size ();

 	      if (htabmax && htabsz > htabmax)
 		{
@@ -6889,9 +6894,9 @@  vt_find_locations (void)
 		fprintf (dump_file,
 			 "BB %i: in %i (was %i), out %i (was %i), rem %i + %i, tsz %i\n",
 			 bb->index,
-			 (int)htab_elements (shared_hash_htab (VTI (bb)->in.vars)),
+			 (int)shared_hash_htab (VTI (bb)->in.vars).size (),
 			 oldinsz,
-			 (int)htab_elements (shared_hash_htab (VTI (bb)->out.vars)),
+			 (int)shared_hash_htab (VTI (bb)->out.vars).size (),
 			 oldoutsz,
 			 (int)worklist->nodes, (int)pending->nodes, htabsz);

@@ -6939,10 +6944,10 @@  dump_attrs_list (attrs list)

 /* Print the information about variable *SLOT to dump file.  */

-static int
-dump_var_slot (void **slot, void *data ATTRIBUTE_UNUSED)
+int
+dump_var_tracking_slot (variable_def **slot, void *data ATTRIBUTE_UNUSED)
 {
-  variable var = (variable) *slot;
+  variable var = *slot;

   dump_var (var);

@@ -6998,12 +7003,12 @@  dump_var (variable var)
 /* Print the information about variables from hash table VARS to dump file.  */

 static void
-dump_vars (htab_t vars)
+dump_vars (variable_table_type vars)
 {
-  if (htab_elements (vars) > 0)
+  if (vars.elements () > 0)
     {
       fprintf (dump_file, "Variables:\n");
-      htab_traverse (vars, dump_var_slot, NULL);
+      vars.traverse <void *, dump_var_tracking_slot> (NULL);
     }
 }

@@ -7051,18 +7056,17 @@  dump_dataflow_sets (void)
 static inline variable
 variable_from_dropped (decl_or_value dv, enum insert_option insert)
 {
-  void **slot;
+  variable_def **slot;
   variable empty_var;
   onepart_enum_t onepart;

-  slot = htab_find_slot_with_hash (dropped_values, dv, dv_htab_hash (dv),
-				   insert);
+  slot = dropped_values.find_slot_with_hash (dv, dv_htab_hash (dv), insert);

   if (!slot)
     return NULL;

   if (*slot)
-    return (variable) *slot;
+    return *slot;

   gcc_checking_assert (insert == INSERT);

@@ -7122,18 +7126,16 @@  variable_was_changed (variable var, data

   if (emit_notes)
     {
-      void **slot;
+      variable_def **slot;

       /* Remember this decl or VALUE has been added to changed_variables.  */
       set_dv_changed (var->dv, true);

-      slot = htab_find_slot_with_hash (changed_variables,
-				       var->dv,
-				       hash, INSERT);
+      slot = changed_variables.find_slot_with_hash (var->dv, hash, INSERT);

       if (*slot)
 	{
-	  variable old_var = (variable) *slot;
+	  variable old_var = *slot;
 	  gcc_assert (old_var->in_changed_variables);
 	  old_var->in_changed_variables = false;
 	  if (var != old_var && var->onepart)
@@ -7152,14 +7154,14 @@  variable_was_changed (variable var, data
 	{
 	  onepart_enum_t onepart = var->onepart;
 	  variable empty_var = NULL;
-	  void **dslot = NULL;
+	  variable_def **dslot = NULL;

 	  if (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR)
 	    {
-	      dslot = htab_find_slot_with_hash (dropped_values, var->dv,
+	      dslot = dropped_values.find_slot_with_hash (var->dv,
 						dv_htab_hash (var->dv),
 						INSERT);
-	      empty_var = (variable) *dslot;
+	      empty_var = *dslot;

 	      if (empty_var)
 		{
@@ -7214,7 +7216,7 @@  variable_was_changed (variable var, data
       gcc_assert (set);
       if (var->n_var_parts == 0)
 	{
-	  void **slot;
+	  variable_def **slot;

 	drop_var:
 	  slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
@@ -7223,7 +7225,7 @@  variable_was_changed (variable var, data
 	      if (shared_hash_shared (set->vars))
 		slot = shared_hash_find_slot_unshare (&set->vars, var->dv,
 						      NO_INSERT);
-	      htab_clear_slot (shared_hash_htab (set->vars), slot);
+	      shared_hash_htab (set->vars).clear_slot (slot);
 	    }
 	}
     }
@@ -7273,8 +7275,8 @@  find_variable_location_part (variable va
   return -1;
 }

-static void **
-set_slot_part (dataflow_set *set, rtx loc, void **slot,
+static variable_def **
+set_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
 	       decl_or_value dv, HOST_WIDE_INT offset,
 	       enum var_init_status initialized, rtx set_src)
 {
@@ -7284,7 +7286,7 @@  set_slot_part (dataflow_set *set, rtx lo
   variable var;
   onepart_enum_t onepart;

-  var = (variable) *slot;
+  var = *slot;

   if (var)
     onepart = var->onepart;
@@ -7407,7 +7409,7 @@  set_slot_part (dataflow_set *set, rtx lo
       if (shared_var_p (var, set->vars))
 	{
 	  slot = unshare_variable (set, slot, var, initialized);
-	  var = (variable)*slot;
+	  var = *slot;
 	  for (nextp = &var->var_part[0].loc_chain; c;
 	       nextp = &(*nextp)->next)
 	    c--;
@@ -7446,7 +7448,7 @@  set_slot_part (dataflow_set *set, rtx lo
 	      if (shared_var_p (var, set->vars))
 		{
 		  slot = unshare_variable (set, slot, var, initialized);
-		  var = (variable)*slot;
+		  var = *slot;
 		}
 	    }
 	}
@@ -7458,7 +7460,7 @@  set_slot_part (dataflow_set *set, rtx lo
 	  if (shared_var_p (var, set->vars))
 	    {
 	      slot = unshare_variable (set, slot, var, initialized);
-	      var = (variable)*slot;
+	      var = *slot;
 	    }

 	  /* We track only variables whose size is <= MAX_VAR_PARTS bytes
@@ -7533,7 +7535,7 @@  set_variable_part (dataflow_set *set, rt
 		   enum var_init_status initialized, rtx set_src,
 		   enum insert_option iopt)
 {
-  void **slot;
+  variable_def **slot;

   if (iopt == NO_INSERT)
     slot = shared_hash_find_slot_noinsert (set->vars, dv);
@@ -7551,11 +7553,11 @@  set_variable_part (dataflow_set *set, rt
    The variable part is specified by variable's declaration or value
    DV and offset OFFSET.  */

-static void **
-clobber_slot_part (dataflow_set *set, rtx loc, void **slot,
+static variable_def **
+clobber_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
 		   HOST_WIDE_INT offset, rtx set_src)
 {
-  variable var = (variable) *slot;
+  variable var = *slot;
   int pos = find_variable_location_part (var, offset, NULL);

   if (pos >= 0)
@@ -7614,7 +7616,7 @@  static void
 clobber_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
 		       HOST_WIDE_INT offset, rtx set_src)
 {
-  void **slot;
+  variable_def **slot;

   if (!dv_as_opaque (dv)
       || (!dv_is_value_p (dv) && ! DECL_P (dv_as_decl (dv))))
@@ -7631,11 +7633,11 @@  clobber_variable_part (dataflow_set *set
    variable part is specified by its SET->vars slot SLOT and offset
    OFFSET and the part's location by LOC.  */

-static void **
-delete_slot_part (dataflow_set *set, rtx loc, void **slot,
+static variable_def **
+delete_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
 		  HOST_WIDE_INT offset)
 {
-  variable var = (variable) *slot;
+  variable var = *slot;
   int pos = find_variable_location_part (var, offset, NULL);

   if (pos >= 0)
@@ -7658,7 +7660,7 @@  delete_slot_part (dataflow_set *set, rtx
 		{
 		  slot = unshare_variable (set, slot, var,
 					   VAR_INIT_STATUS_UNKNOWN);
-		  var = (variable)*slot;
+		  var = *slot;
 		  break;
 		}
 	    }
@@ -7722,7 +7724,7 @@  static void
 delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
 		      HOST_WIDE_INT offset)
 {
-  void **slot = shared_hash_find_slot_noinsert (set->vars, dv);
+  variable_def **slot = shared_hash_find_slot_noinsert (set->vars, dv);
   if (!slot)
     return;

@@ -7735,7 +7737,7 @@  delete_variable_part (dataflow_set *set,
 struct expand_loc_callback_data
 {
   /* The variables and values active at this point.  */
-  htab_t vars;
+  variable_table_type vars;

   /* Stack of values and debug_exprs under expansion, and their
      children.  */
@@ -7824,7 +7826,7 @@  loc_exp_dep_clear (variable var)
    back-links in VARS.  */

 static void
-loc_exp_insert_dep (variable var, rtx x, htab_t vars)
+loc_exp_insert_dep (variable var, rtx x, variable_table_type vars)
 {
   decl_or_value dv;
   variable xvar;
@@ -7834,7 +7836,7 @@  loc_exp_insert_dep (variable var, rtx x,

   /* ??? Build a vector of variables parallel to EXPANDING, to avoid
      an additional look up?  */
-  xvar = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
+  xvar = vars.find_with_hash (dv, dv_htab_hash (dv));

   if (!xvar)
     {
@@ -7874,7 +7876,8 @@  loc_exp_insert_dep (variable var, rtx x,
    true if we found any pending-recursion results.  */

 static bool
-loc_exp_dep_set (variable var, rtx result, rtx *value, int count, htab_t vars)
+loc_exp_dep_set (variable var, rtx result, rtx *value, int count,
+		 variable_table_type vars)
 {
   bool pending_recursion = false;

@@ -7903,7 +7906,7 @@  loc_exp_dep_set (variable var, rtx resul
    attempt to compute a current location.  */

 static void
-notify_dependents_of_resolved_value (variable ivar, htab_t vars)
+notify_dependents_of_resolved_value (variable ivar, variable_table_type vars)
 {
   loc_exp_dep *led, *next;

@@ -7941,7 +7944,7 @@  notify_dependents_of_resolved_value (var
 	    continue;
       }

-      var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
+      var = vars.find_with_hash (dv, dv_htab_hash (dv));

       if (!var)
 	var = variable_from_dropped (dv, NO_INSERT);
@@ -8185,7 +8188,7 @@  vt_expand_loc_callback (rtx x, bitmap re
       return NULL;
     }

-  var = (variable) htab_find_with_hash (elcd->vars, dv, dv_htab_hash (dv));
+  var = elcd->vars.find_with_hash (dv, dv_htab_hash (dv));

   if (!var)
     {
@@ -8294,7 +8297,7 @@  resolve_expansions_pending_recursion (ve
    equivalences in VARS, updating their CUR_LOCs in the process.  */

 static rtx
-vt_expand_loc (rtx loc, htab_t vars)
+vt_expand_loc (rtx loc, variable_table_type vars)
 {
   struct expand_loc_callback_data data;
   rtx result;
@@ -8316,7 +8319,7 @@  vt_expand_loc (rtx loc, htab_t vars)
    in VARS, updating their CUR_LOCs in the process.  */

 static rtx
-vt_expand_1pvar (variable var, htab_t vars)
+vt_expand_1pvar (variable var, variable_table_type vars)
 {
   struct expand_loc_callback_data data;
   rtx loc;
@@ -8341,13 +8344,13 @@  vt_expand_1pvar (variable var, htab_t va
    additional parameters: WHERE specifies whether the note shall be emitted
    before or after instruction INSN.  */

-static int
-emit_note_insn_var_location (void **varp, void *data)
+int
+emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
 {
-  variable var = (variable) *varp;
-  rtx insn = ((emit_note_data *)data)->insn;
-  enum emit_note_where where = ((emit_note_data *)data)->where;
-  htab_t vars = ((emit_note_data *)data)->vars;
+  variable var = *varp;
+  rtx insn = data->insn;
+  enum emit_note_where where = data->where;
+  variable_table_type vars = data->vars;
   rtx note, note_vl;
   int i, j, n_var_parts;
   bool complete;
@@ -8585,7 +8588,7 @@  emit_note_insn_var_location (void **varp
   set_dv_changed (var->dv, false);
   gcc_assert (var->in_changed_variables);
   var->in_changed_variables = false;
-  htab_clear_slot (changed_variables, varp);
+  changed_variables.clear_slot (varp);

   /* Continue traversing the hash table.  */
   return 1;
@@ -8594,11 +8597,11 @@  emit_note_insn_var_location (void **varp
 /* While traversing changed_variables, push onto DATA (a stack of RTX
    values) entries that aren't user variables.  */

-static int
-values_to_stack (void **slot, void *data)
+int
+var_track_values_to_stack (variable_def **slot,
+			   vec<rtx, va_stack> *changed_values_stack)
 {
-  vec<rtx, va_stack> *changed_values_stack = (vec<rtx, va_stack> *) data;
-  variable var = (variable) *slot;
+  variable var = *slot;

   if (var->onepart == ONEPART_VALUE)
     changed_values_stack->safe_push (dv_as_value (var->dv));
@@ -8614,14 +8617,14 @@  static void
 remove_value_from_changed_variables (rtx val)
 {
   decl_or_value dv = dv_from_rtx (val);
-  void **slot;
+  variable_def **slot;
   variable var;

-  slot = htab_find_slot_with_hash (changed_variables,
-				   dv, dv_htab_hash (dv), NO_INSERT);
-  var = (variable) *slot;
+  slot = changed_variables.find_slot_with_hash (dv, dv_htab_hash (dv),
+						NO_INSERT);
+  var = *slot;
   var->in_changed_variables = false;
-  htab_clear_slot (changed_variables, slot);
+  changed_variables.clear_slot (slot);
 }

 /* If VAL (a value or debug_expr) has backlinks to variables actively
@@ -8630,23 +8633,22 @@  remove_value_from_changed_variables (rtx
    have dependencies of their own to notify.  */

 static void
-notify_dependents_of_changed_value (rtx val, htab_t htab,
+notify_dependents_of_changed_value (rtx val, variable_table_type htab,
 				    vec<rtx, va_stack> *changed_values_stack)
 {
-  void **slot;
+  variable_def **slot;
   variable var;
   loc_exp_dep *led;
   decl_or_value dv = dv_from_rtx (val);

-  slot = htab_find_slot_with_hash (changed_variables,
-				   dv, dv_htab_hash (dv), NO_INSERT);
+  slot = changed_variables.find_slot_with_hash (dv, dv_htab_hash (dv),
+						NO_INSERT);
   if (!slot)
-    slot = htab_find_slot_with_hash (htab,
-				     dv, dv_htab_hash (dv), NO_INSERT);
+    slot = htab.find_slot_with_hash (dv, dv_htab_hash (dv), NO_INSERT);
   if (!slot)
-    slot = htab_find_slot_with_hash (dropped_values,
-				     dv, dv_htab_hash (dv), NO_INSERT);
-  var = (variable) *slot;
+    slot = dropped_values.find_slot_with_hash (dv, dv_htab_hash (dv),
+					       NO_INSERT);
+  var = *slot;

   while ((led = VAR_LOC_DEP_LST (var)))
     {
@@ -8676,14 +8678,14 @@  notify_dependents_of_changed_value (rtx
 	  break;

 	case ONEPART_VDECL:
-	  ivar = (variable) htab_find_with_hash (htab, ldv, dv_htab_hash (ldv));
+	  ivar = htab.find_with_hash (ldv, dv_htab_hash (ldv));
 	  gcc_checking_assert (!VAR_LOC_DEP_LST (ivar));
 	  variable_was_changed (ivar, NULL);
 	  break;

 	case NOT_ONEPART:
 	  pool_free (loc_exp_dep_pool, led);
-	  ivar = (variable) htab_find_with_hash (htab, ldv, dv_htab_hash (ldv));
+	  ivar = htab.find_with_hash (ldv, dv_htab_hash (ldv));
 	  if (ivar)
 	    {
 	      int i = ivar->n_var_parts;
@@ -8713,7 +8715,7 @@  notify_dependents_of_changed_value (rtx
    CHANGED_VARIABLES.  */

 static void
-process_changed_values (htab_t htab)
+process_changed_values (variable_table_type htab)
 {
   int i, n;
   rtx val;
@@ -8722,7 +8724,9 @@  process_changed_values (htab_t htab)
   vec_stack_alloc (rtx, changed_values_stack, 20);

   /* Move values from changed_variables to changed_values_stack.  */
-  htab_traverse (changed_variables, values_to_stack, &changed_values_stack);
+  changed_variables
+    .traverse <vec<rtx, va_stack>*, var_track_values_to_stack>
+      (&changed_values_stack);

   /* Back-propagate change notifications in values while popping
      them from the stack.  */
@@ -8755,9 +8759,9 @@  emit_notes_for_changes (rtx insn, enum e
 			shared_hash vars)
 {
   emit_note_data data;
-  htab_t htab = shared_hash_htab (vars);
+  variable_table_type htab = shared_hash_htab (vars);

-  if (!htab_elements (changed_variables))
+  if (!changed_variables.elements ())
     return;

   if (MAY_HAVE_DEBUG_INSNS)
@@ -8767,21 +8771,20 @@  emit_notes_for_changes (rtx insn, enum e
   data.where = where;
   data.vars = htab;

-  htab_traverse (changed_variables, emit_note_insn_var_location, &data);
+  changed_variables
+    .traverse <emit_note_data*, emit_note_insn_var_location> (&data);
 }

 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
    same variable in hash table DATA or is not there at all.  */

-static int
-emit_notes_for_differences_1 (void **slot, void *data)
+int
+emit_notes_for_differences_1 (variable_def **slot,
variable_table_type new_vars)
 {
-  htab_t new_vars = (htab_t) data;
   variable old_var, new_var;

-  old_var = (variable) *slot;
-  new_var = (variable) htab_find_with_hash (new_vars, old_var->dv,
-					    dv_htab_hash (old_var->dv));
+  old_var = *slot;
+  new_var = new_vars.find_with_hash (old_var->dv, dv_htab_hash (old_var->dv));

   if (!new_var)
     {
@@ -8847,15 +8850,13 @@  emit_notes_for_differences_1 (void **slo
 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
    table DATA.  */

-static int
-emit_notes_for_differences_2 (void **slot, void *data)
+int
+emit_notes_for_differences_2 (variable_def **slot,
variable_table_type old_vars)
 {
-  htab_t old_vars = (htab_t) data;
   variable old_var, new_var;

-  new_var = (variable) *slot;
-  old_var = (variable) htab_find_with_hash (old_vars, new_var->dv,
-					    dv_htab_hash (new_var->dv));
+  new_var = *slot;
+  old_var = old_vars.find_with_hash (new_var->dv, dv_htab_hash (new_var->dv));
   if (!old_var)
     {
       int i;
@@ -8875,12 +8876,12 @@  static void
 emit_notes_for_differences (rtx insn, dataflow_set *old_set,
 			    dataflow_set *new_set)
 {
-  htab_traverse (shared_hash_htab (old_set->vars),
-		 emit_notes_for_differences_1,
-		 shared_hash_htab (new_set->vars));
-  htab_traverse (shared_hash_htab (new_set->vars),
-		 emit_notes_for_differences_2,
-		 shared_hash_htab (old_set->vars));
+  shared_hash_htab (old_set->vars)
+    .traverse <variable_table_type, emit_notes_for_differences_1>
+      (shared_hash_htab (new_set->vars));
+  shared_hash_htab (new_set->vars)
+    .traverse <variable_table_type, emit_notes_for_differences_2>
+      (shared_hash_htab (old_set->vars));
   emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, new_set->vars);
 }

@@ -9240,7 +9241,7 @@  vt_emit_notes (void)
   basic_block bb;
   dataflow_set cur;

-  gcc_assert (!htab_elements (changed_variables));
+  gcc_assert (!changed_variables.elements ());

   /* Free memory occupied by the out hash tables, as they aren't used
      anymore.  */
@@ -9253,9 +9254,7 @@  vt_emit_notes (void)

   if (MAY_HAVE_DEBUG_INSNS)
     {
-      dropped_values = htab_create (cselib_get_next_uid () * 2,
-				    variable_htab_hash, variable_htab_eq,
-				    variable_htab_free);
+      dropped_values.create (cselib_get_next_uid () * 2);
       loc_exp_dep_pool = create_alloc_pool ("loc_exp_dep pool",
 					    sizeof (loc_exp_dep), 64);
     }
@@ -9276,14 +9275,14 @@  vt_emit_notes (void)
       dataflow_set_clear (&VTI (bb)->in);
     }
 #ifdef ENABLE_CHECKING
-  htab_traverse (shared_hash_htab (cur.vars),
-		 emit_notes_for_differences_1,
-		 shared_hash_htab (empty_shared_hash));
+  shared_hash_htab (cur.vars)
+    .traverse <variable_table_type, emit_notes_for_differences_1>
+      (shared_hash_htab (empty_shared_hash));
 #endif
   dataflow_set_destroy (&cur);

   if (MAY_HAVE_DEBUG_INSNS)
-    htab_delete (dropped_values);
+    dropped_values.dispose ();

   emit_notes = false;
 }
@@ -9616,11 +9615,8 @@  vt_initialize (void)
 					sizeof (struct shared_hash_def), 256);
   empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool);
   empty_shared_hash->refcount = 1;
-  empty_shared_hash->htab
-    = htab_create (1, variable_htab_hash, variable_htab_eq,
-		   variable_htab_free);
-  changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq,
-				   variable_htab_free);
+  empty_shared_hash->htab.create (1);
+  changed_variables.create (10);

   /* Init the IN and OUT sets.  */
   FOR_ALL_BB (bb)
@@ -9971,8 +9967,8 @@  vt_finalize (void)
 	}
     }
   free_aux_for_blocks ();
-  htab_delete (empty_shared_hash->htab);
-  htab_delete (changed_variables);
+  empty_shared_hash->htab.dispose ();
+  changed_variables.dispose ();
   free_alloc_pool (attrs_pool);
   free_alloc_pool (var_pool);
   free_alloc_pool (loc_chain_pool);
Index: gcc/trans-mem.c
===================================================================
--- gcc/trans-mem.c	(revision 194487)
+++ gcc/trans-mem.c	(working copy)
@@ -880,8 +880,62 @@  typedef struct tm_log_entry
   tree save_var;
 } *tm_log_entry_t;

+
+/* Log entry hashtable helpers.  */
+
+struct log_entry_hasher
+{
+  typedef tm_log_entry value_type;
+  typedef tm_log_entry 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 *);
+};
+
+/* Htab support.  Return hash value for a `tm_log_entry'.  */
+inline hashval_t
+log_entry_hasher::hash (const value_type *log)
+{
+  return iterative_hash_expr (log->addr, 0);
+}
+
+/* Htab support.  Return true if two log entries are the same.  */
+inline bool
+log_entry_hasher::equal (const value_type *log1, const compare_type *log2)
+{
+  /* FIXME:
+
+     rth: I suggest that we get rid of the component refs etc.
+     I.e. resolve the reference to base + offset.
+
+     We may need to actually finish a merge with mainline for this,
+     since we'd like to be presented with Richi's MEM_REF_EXPRs more
+     often than not.  But in the meantime your tm_log_entry could save
+     the results of get_inner_reference.
+
+     See: g++.dg/tm/pr46653.C
+  */
+
+  /* Special case plain equality because operand_equal_p() below will
+     return FALSE if the addresses are equal but they have
+     side-effects (e.g. a volatile address).  */
+  if (log1->addr == log2->addr)
+    return true;
+
+  return operand_equal_p (log1->addr, log2->addr, 0);
+}
+
+/* Htab support.  Free one tm_log_entry.  */
+inline void
+log_entry_hasher::remove (value_type *lp)
+{
+  lp->stmts.release ();
+  free (lp);
+}
+
+
 /* The actual log.  */
-static htab_t tm_log;
+static hash_table <log_entry_hasher> tm_log;

 /* Addresses to log with a save/restore sequence.  These should be in
    dominator order.  */
@@ -928,57 +982,11 @@  tm_mem_map_hasher::equal (const value_ty
    of memory (malloc, alloc, etc).  */
 static hash_table <tm_mem_map_hasher> tm_new_mem_hash;

-/* Htab support.  Return hash value for a `tm_log_entry'.  */
-static hashval_t
-tm_log_hash (const void *p)
-{
-  const struct tm_log_entry *log = (const struct tm_log_entry *) p;
-  return iterative_hash_expr (log->addr, 0);
-}
-
-/* Htab support.  Return true if two log entries are the same.  */
-static int
-tm_log_eq (const void *p1, const void *p2)
-{
-  const struct tm_log_entry *log1 = (const struct tm_log_entry *) p1;
-  const struct tm_log_entry *log2 = (const struct tm_log_entry *) p2;
-
-  /* FIXME:
-
-     rth: I suggest that we get rid of the component refs etc.
-     I.e. resolve the reference to base + offset.
-
-     We may need to actually finish a merge with mainline for this,
-     since we'd like to be presented with Richi's MEM_REF_EXPRs more
-     often than not.  But in the meantime your tm_log_entry could save
-     the results of get_inner_reference.
-
-     See: g++.dg/tm/pr46653.C
-  */
-
-  /* Special case plain equality because operand_equal_p() below will
-     return FALSE if the addresses are equal but they have
-     side-effects (e.g. a volatile address).  */
-  if (log1->addr == log2->addr)
-    return true;
-
-  return operand_equal_p (log1->addr, log2->addr, 0);
-}
-
-/* Htab support.  Free one tm_log_entry.  */
-static void
-tm_log_free (void *p)
-{
-  struct tm_log_entry *lp = (struct tm_log_entry *) p;
-  lp->stmts.release ();
-  free (lp);
-}
-
 /* Initialize logging data structures.  */
 static void
 tm_log_init (void)
 {
-  tm_log = htab_create (10, tm_log_hash, tm_log_eq, tm_log_free);
+  tm_log.create (10);
   tm_new_mem_hash.create (5);
   tm_log_save_addresses.create (5);
 }
@@ -987,7 +995,7 @@  tm_log_init (void)
 static void
 tm_log_delete (void)
 {
-  htab_delete (tm_log);
+  tm_log.dispose ();
   tm_new_mem_hash.dispose ();
   tm_log_save_addresses.release ();
 }
@@ -1029,11 +1037,11 @@  transaction_invariant_address_p (const_t
 static void
 tm_log_add (basic_block entry_block, tree addr, gimple stmt)
 {
-  void **slot;
+  tm_log_entry **slot;
   struct tm_log_entry l, *lp;

   l.addr = addr;
-  slot = htab_find_slot (tm_log, &l, INSERT);
+  slot = tm_log.find_slot (&l, INSERT);
   if (!*slot)
     {
       tree type = TREE_TYPE (addr);
@@ -1074,7 +1082,7 @@  tm_log_add (basic_block entry_block, tre
       size_t i;
       gimple oldstmt;

-      lp = (struct tm_log_entry *) *slot;
+      lp = *slot;

       /* If we're generating a save/restore sequence, we don't care
 	 about statements.  */
@@ -1176,10 +1184,10 @@  tm_log_emit_stmt (tree addr, gimple stmt
 static void
 tm_log_emit (void)
 {
-  htab_iterator hi;
+  hash_table <log_entry_hasher>::iterator hi;
   struct tm_log_entry *lp;

-  FOR_EACH_HTAB_ELEMENT (tm_log, lp, tm_log_entry_t, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (tm_log, lp, tm_log_entry_t, hi)
     {
       size_t i;
       gimple stmt;
@@ -1221,7 +1229,7 @@  tm_log_emit_saves (basic_block entry_blo
   for (i = 0; i < tm_log_save_addresses.length (); ++i)
     {
       l.addr = tm_log_save_addresses[i];
-      lp = (struct tm_log_entry *) *htab_find_slot (tm_log, &l, NO_INSERT);
+      lp = *(tm_log.find_slot (&l, NO_INSERT));
       gcc_assert (lp->save_var != NULL);

       /* We only care about variables in the current transaction.  */
@@ -1257,7 +1265,7 @@  tm_log_emit_restores (basic_block entry_
   for (i = tm_log_save_addresses.length () - 1; i >= 0; i--)
     {
       l.addr = tm_log_save_addresses[i];
-      lp = (struct tm_log_entry *) *htab_find_slot (tm_log, &l, NO_INSERT);
+      lp = *(tm_log.find_slot (&l, NO_INSERT));
       gcc_assert (lp->save_var != NULL);

       /* We only care about variables in the current transaction.  */
@@ -3153,6 +3161,35 @@  typedef struct tm_memop
   tree addr;
 } *tm_memop_t;

+/* TM memory operation hashtable helpers.  */
+
+struct tm_memop_hasher : typed_free_remove <tm_memop>
+{
+  typedef tm_memop value_type;
+  typedef tm_memop compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Htab support.  Return a hash value for a `tm_memop'.  */
+inline hashval_t
+tm_memop_hasher::hash (const value_type *mem)
+{
+  tree addr = mem->addr;
+  /* We drill down to the SSA_NAME/DECL for the hash, but equality is
+     actually done with operand_equal_p (see tm_memop_eq).  */
+  if (TREE_CODE (addr) == ADDR_EXPR)
+    addr = TREE_OPERAND (addr, 0);
+  return iterative_hash_expr (addr, 0);
+}
+
+/* Htab support.  Return true if two tm_memop's are the same.  */
+inline bool
+tm_memop_hasher::equal (const value_type *mem1, const compare_type *mem2)
+{
+  return operand_equal_p (mem1->addr, mem2->addr, 0);
+}
+
 /* Sets for solving data flow equations in the memory optimization pass.  */
 struct tm_memopt_bitmaps
 {
@@ -3185,7 +3222,7 @@  static bitmap_obstack tm_memopt_obstack;
 /* Unique counter for TM loads and stores. Loads and stores of the
    same address get the same ID.  */
 static unsigned int tm_memopt_value_id;
-static htab_t tm_memopt_value_numbers;
+static hash_table <tm_memop_hasher> tm_memopt_value_numbers;

 #define STORE_AVAIL_IN(BB) \
   ((struct tm_memopt_bitmaps *) ((BB)->aux))->store_avail_in
@@ -3208,29 +3245,6 @@  static htab_t tm_memopt_value_numbers;
 #define BB_VISITED_P(BB) \
   ((struct tm_memopt_bitmaps *) ((BB)->aux))->visited_p

-/* Htab support.  Return a hash value for a `tm_memop'.  */
-static hashval_t
-tm_memop_hash (const void *p)
-{
-  const struct tm_memop *mem = (const struct tm_memop *) p;
-  tree addr = mem->addr;
-  /* We drill down to the SSA_NAME/DECL for the hash, but equality is
-     actually done with operand_equal_p (see tm_memop_eq).  */
-  if (TREE_CODE (addr) == ADDR_EXPR)
-    addr = TREE_OPERAND (addr, 0);
-  return iterative_hash_expr (addr, 0);
-}
-
-/* Htab support.  Return true if two tm_memop's are the same.  */
-static int
-tm_memop_eq (const void *p1, const void *p2)
-{
-  const struct tm_memop *mem1 = (const struct tm_memop *) p1;
-  const struct tm_memop *mem2 = (const struct tm_memop *) p2;
-
-  return operand_equal_p (mem1->addr, mem2->addr, 0);
-}
-
 /* Given a TM load/store in STMT, return the value number for the address
    it accesses.  */

@@ -3238,13 +3252,13 @@  static unsigned int
 tm_memopt_value_number (gimple stmt, enum insert_option op)
 {
   struct tm_memop tmpmem, *mem;
-  void **slot;
+  tm_memop **slot;

   gcc_assert (is_tm_load (stmt) || is_tm_store (stmt));
   tmpmem.addr = gimple_call_arg (stmt, 0);
-  slot = htab_find_slot (tm_memopt_value_numbers, &tmpmem, op);
+  slot = tm_memopt_value_numbers.find_slot (&tmpmem, op);
   if (*slot)
-    mem = (struct tm_memop *) *slot;
+    mem = *slot;
   else if (op == INSERT)
     {
       mem = XNEW (struct tm_memop);
@@ -3302,11 +3316,11 @@  dump_tm_memopt_set (const char *set_name
   fprintf (dump_file, "TM memopt: %s: [", set_name);
   EXECUTE_IF_SET_IN_BITMAP (bits, 0, i, bi)
     {
-      htab_iterator hi;
-      struct tm_memop *mem;
+      hash_table <tm_memop_hasher>::iterator hi;
+      struct tm_memop *mem = NULL;

       /* Yeah, yeah, yeah.  Whatever.  This is just for debugging.  */
-      FOR_EACH_HTAB_ELEMENT (tm_memopt_value_numbers, mem, tm_memop_t, hi)
+      FOR_EACH_HASH_TABLE_ELEMENT (tm_memopt_value_numbers, mem,
tm_memop_t, hi)
 	if (mem->value_id == i)
 	  break;
       gcc_assert (mem->value_id == i);
@@ -3741,7 +3755,7 @@  execute_tm_memopt (void)
   vec<basic_block> bbs;

   tm_memopt_value_id = 0;
-  tm_memopt_value_numbers = htab_create (10, tm_memop_hash, tm_memop_eq, free);
+  tm_memopt_value_numbers.create (10);

   for (region = all_tm_regions; region; region = region->next)
     {
@@ -3775,10 +3789,10 @@  execute_tm_memopt (void)
       tm_memopt_free_sets (bbs);
       bbs.release ();
       bitmap_obstack_release (&tm_memopt_obstack);
-      htab_empty (tm_memopt_value_numbers);
+      tm_memopt_value_numbers.empty ();
     }

-  htab_delete (tm_memopt_value_numbers);
+  tm_memopt_value_numbers.dispose ();
   return 0;
 }

Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c	(revision 194487)
+++ gcc/tree-ssa-sccvn.c	(working copy)
@@ -30,7 +30,7 @@  along with GCC; see the file COPYING3.
 #include "tree-flow.h"
 #include "gimple.h"
 #include "dumpfile.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "alloc-pool.h"
 #include "flags.h"
 #include "bitmap.h"
@@ -97,19 +97,187 @@  along with GCC; see the file COPYING3.
    structure copies.
 */

+
+/* vn_nary_op hashtable helpers.  */
+
+struct vn_nary_op_hasher : typed_noop_remove <vn_nary_op_s>
+{
+  typedef vn_nary_op_s value_type;
+  typedef vn_nary_op_s compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Return the computed hashcode for nary operation P1.  */
+
+inline hashval_t
+vn_nary_op_hasher::hash (const value_type *vno1)
+{
+  return vno1->hashcode;
+}
+
+/* Compare nary operations P1 and P2 and return true if they are
+   equivalent.  */
+
+inline bool
+vn_nary_op_hasher::equal (const value_type *vno1, const compare_type *vno2)
+{
+  return vn_nary_op_eq (vno1, vno2);
+}
+
+typedef hash_table <vn_nary_op_hasher> vn_nary_op_table_type;
+typedef vn_nary_op_table_type::iterator vn_nary_op_iterator_type;
+
+
+/* vn_phi hashtable helpers.  */
+
+static int
+vn_phi_eq (const_vn_phi_t const vp1, const_vn_phi_t const vp2);
+
+struct vn_phi_hasher
+{
+  typedef vn_phi_s value_type;
+  typedef vn_phi_s 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 *);
+};
+
+/* Return the computed hashcode for phi operation P1.  */
+
+inline hashval_t
+vn_phi_hasher::hash (const value_type *vp1)
+{
+  return vp1->hashcode;
+}
+
+/* Compare two phi entries for equality, ignoring VN_TOP arguments.  */
+
+inline bool
+vn_phi_hasher::equal (const value_type *vp1, const compare_type *vp2)
+{
+  return vn_phi_eq (vp1, vp2);
+}
+
+/* Free a phi operation structure VP.  */
+
+inline void
+vn_phi_hasher::remove (value_type *phi)
+{
+  phi->phiargs.release ();
+}
+
+typedef hash_table <vn_phi_hasher> vn_phi_table_type;
+typedef vn_phi_table_type::iterator vn_phi_iterator_type;
+
+
+/* Compare two reference operands P1 and P2 for equality.  Return true if
+   they are equal, and false otherwise.  */
+
+static int
+vn_reference_op_eq (const void *p1, const void *p2)
+{
+  const_vn_reference_op_t const vro1 = (const_vn_reference_op_t) p1;
+  const_vn_reference_op_t const vro2 = (const_vn_reference_op_t) p2;
+
+  return (vro1->opcode == vro2->opcode
+	  /* We do not care for differences in type qualification.  */
+	  && (vro1->type == vro2->type
+	      || (vro1->type && vro2->type
+		  && types_compatible_p (TYPE_MAIN_VARIANT (vro1->type),
+					 TYPE_MAIN_VARIANT (vro2->type))))
+	  && expressions_equal_p (vro1->op0, vro2->op0)
+	  && expressions_equal_p (vro1->op1, vro2->op1)
+	  && expressions_equal_p (vro1->op2, vro2->op2));
+}
+
+/* Free a reference operation structure VP.  */
+
+static inline void
+free_reference (vn_reference_s *vr)
+{
+  vr->operands.release ();
+}
+
+
+/* vn_reference hashtable helpers.  */
+
+struct vn_reference_hasher
+{
+  typedef vn_reference_s value_type;
+  typedef vn_reference_s 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 *);
+};
+
+/* Return the hashcode for a given reference operation P1.  */
+
+inline hashval_t
+vn_reference_hasher::hash (const value_type *vr1)
+{
+  return vr1->hashcode;
+}
+
+inline bool
+vn_reference_hasher::equal (const value_type *v, const compare_type *c)
+{
+  return vn_reference_eq (v, c);
+}
+
+inline void
+vn_reference_hasher::remove (value_type *v)
+{
+  free_reference (v);
+}
+
+typedef hash_table <vn_reference_hasher> vn_reference_table_type;
+typedef vn_reference_table_type::iterator vn_reference_iterator_type;
+
+
 /* The set of hashtables and alloc_pool's for their items.  */

 typedef struct vn_tables_s
 {
-  htab_t nary;
-  htab_t phis;
-  htab_t references;
+  vn_nary_op_table_type nary;
+  vn_phi_table_type phis;
+  vn_reference_table_type references;
   struct obstack nary_obstack;
   alloc_pool phis_pool;
   alloc_pool references_pool;
 } *vn_tables_t;

-static htab_t constant_to_value_id;
+
+/* vn_constant hashtable helpers.  */
+
+struct vn_constant_hasher : typed_free_remove <vn_constant_s>
+{
+  typedef vn_constant_s value_type;
+  typedef vn_constant_s compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Hash table hash function for vn_constant_t.  */
+
+inline hashval_t
+vn_constant_hasher::hash (const value_type *vc1)
+{
+  return vc1->hashcode;
+}
+
+/* Hash table equality function for vn_constant_t.  */
+
+inline bool
+vn_constant_hasher::equal (const value_type *vc1, const compare_type *vc2)
+{
+  if (vc1->hashcode != vc2->hashcode)
+    return false;
+
+  return vn_constant_eq_with_type (vc1->constant, vc2->constant);
+}
+
+static hash_table <vn_constant_hasher> constant_to_value_id;
 static bitmap constant_value_ids;


@@ -339,62 +507,20 @@  vn_get_stmt_kind (gimple stmt)
     }
 }

-/* Free a phi operation structure VP.  */
-
-static void
-free_phi (void *vp)
-{
-  vn_phi_t phi = (vn_phi_t) vp;
-  phi->phiargs.release ();
-}
-
-/* Free a reference operation structure VP.  */
-
-static void
-free_reference (void *vp)
-{
-  vn_reference_t vr = (vn_reference_t) vp;
-  vr->operands.release ();
-}
-
-/* Hash table equality function for vn_constant_t.  */
-
-static int
-vn_constant_eq (const void *p1, const void *p2)
-{
-  const struct vn_constant_s *vc1 = (const struct vn_constant_s *) p1;
-  const struct vn_constant_s *vc2 = (const struct vn_constant_s *) p2;
-
-  if (vc1->hashcode != vc2->hashcode)
-    return false;
-
-  return vn_constant_eq_with_type (vc1->constant, vc2->constant);
-}
-
-/* Hash table hash function for vn_constant_t.  */
-
-static hashval_t
-vn_constant_hash (const void *p1)
-{
-  const struct vn_constant_s *vc1 = (const struct vn_constant_s *) p1;
-  return vc1->hashcode;
-}
-
 /* Lookup a value id for CONSTANT and return it.  If it does not
    exist returns 0.  */

 unsigned int
 get_constant_value_id (tree constant)
 {
-  void **slot;
+  vn_constant_s **slot;
   struct vn_constant_s vc;

   vc.hashcode = vn_hash_constant_with_type (constant);
   vc.constant = constant;
-  slot = htab_find_slot_with_hash (constant_to_value_id, &vc,
-				   vc.hashcode, NO_INSERT);
+  slot = constant_to_value_id.find_slot_with_hash (&vc, vc.hashcode,
NO_INSERT);
   if (slot)
-    return ((vn_constant_t)*slot)->value_id;
+    return (*slot)->value_id;
   return 0;
 }

@@ -404,22 +530,21 @@  get_constant_value_id (tree constant)
 unsigned int
 get_or_alloc_constant_value_id (tree constant)
 {
-  void **slot;
+  vn_constant_s **slot;
   struct vn_constant_s vc;
   vn_constant_t vcp;

   vc.hashcode = vn_hash_constant_with_type (constant);
   vc.constant = constant;
-  slot = htab_find_slot_with_hash (constant_to_value_id, &vc,
-				   vc.hashcode, INSERT);
+  slot = constant_to_value_id.find_slot_with_hash (&vc, vc.hashcode, INSERT);
   if (*slot)
-    return ((vn_constant_t)*slot)->value_id;
+    return (*slot)->value_id;

   vcp = XNEW (struct vn_constant_s);
   vcp->hashcode = vc.hashcode;
   vcp->constant = constant;
   vcp->value_id = get_next_value_id ();
-  *slot = (void *) vcp;
+  *slot = vcp;
   bitmap_set_bit (constant_value_ids, vcp->value_id);
   return vcp->value_id;
 }
@@ -432,26 +557,6 @@  value_id_constant_p (unsigned int v)
   return bitmap_bit_p (constant_value_ids, v);
 }

-/* Compare two reference operands P1 and P2 for equality.  Return true if
-   they are equal, and false otherwise.  */
-
-static int
-vn_reference_op_eq (const void *p1, const void *p2)
-{
-  const_vn_reference_op_t const vro1 = (const_vn_reference_op_t) p1;
-  const_vn_reference_op_t const vro2 = (const_vn_reference_op_t) p2;
-
-  return (vro1->opcode == vro2->opcode
-	  /* We do not care for differences in type qualification.  */
-	  && (vro1->type == vro2->type
-	      || (vro1->type && vro2->type
-		  && types_compatible_p (TYPE_MAIN_VARIANT (vro1->type),
-					 TYPE_MAIN_VARIANT (vro2->type))))
-	  && expressions_equal_p (vro1->op0, vro2->op0)
-	  && expressions_equal_p (vro1->op1, vro2->op1)
-	  && expressions_equal_p (vro1->op2, vro2->op2));
-}
-
 /* Compute the hash for a reference operand VRO1.  */

 static hashval_t
@@ -467,15 +572,6 @@  vn_reference_op_compute_hash (const vn_r
   return result;
 }

-/* Return the hashcode for a given reference operation P1.  */
-
-static hashval_t
-vn_reference_hash (const void *p1)
-{
-  const_vn_reference_t const vr1 = (const_vn_reference_t) p1;
-  return vr1->hashcode;
-}
-
 /* Compute a hash for the reference operation VR1 and return it.  */

 hashval_t
@@ -525,16 +621,14 @@  vn_reference_compute_hash (const vn_refe
   return result;
 }

-/* Return true if reference operations P1 and P2 are equivalent.  This
+/* Return true if reference operations VR1 and VR2 are equivalent.  This
    means they have the same set of operands and vuses.  */

-int
-vn_reference_eq (const void *p1, const void *p2)
+bool
+vn_reference_eq (const_vn_reference_t const vr1, const_vn_reference_t
const vr2)
 {
   unsigned i, j;

-  const_vn_reference_t const vr1 = (const_vn_reference_t) p1;
-  const_vn_reference_t const vr2 = (const_vn_reference_t) p2;
   if (vr1->hashcode != vr2->hashcode)
     return false;

@@ -1347,15 +1441,13 @@  valueize_shared_reference_ops_from_call
 static tree
 vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult)
 {
-  void **slot;
+  vn_reference_s **slot;
   hashval_t hash;

   hash = vr->hashcode;
-  slot = htab_find_slot_with_hash (current_info->references, vr,
-				   hash, NO_INSERT);
+  slot = current_info->references.find_slot_with_hash (vr, hash, NO_INSERT);
   if (!slot && current_info == optimistic_info)
-    slot = htab_find_slot_with_hash (valid_info->references, vr,
-				     hash, NO_INSERT);
+    slot = valid_info->references.find_slot_with_hash (vr, hash, NO_INSERT);
   if (slot)
     {
       if (vnresult)
@@ -1378,7 +1470,7 @@  vn_reference_lookup_2 (ao_ref *op ATTRIB
 		       unsigned int cnt, void *vr_)
 {
   vn_reference_t vr = (vn_reference_t)vr_;
-  void **slot;
+  vn_reference_s **slot;
   hashval_t hash;

   /* This bounds the stmt walks we perform on reference lookups
@@ -1398,11 +1490,9 @@  vn_reference_lookup_2 (ao_ref *op ATTRIB
     vr->hashcode = vr->hashcode + SSA_NAME_VERSION (vr->vuse);

   hash = vr->hashcode;
-  slot = htab_find_slot_with_hash (current_info->references, vr,
-				   hash, NO_INSERT);
+  slot = current_info->references.find_slot_with_hash (vr, hash, NO_INSERT);
   if (!slot && current_info == optimistic_info)
-    slot = htab_find_slot_with_hash (valid_info->references, vr,
-				     hash, NO_INSERT);
+    slot = valid_info->references.find_slot_with_hash (vr, hash, NO_INSERT);
   if (slot)
     return *slot;

@@ -2005,7 +2095,7 @@  vn_reference_lookup (tree op, tree vuse,
 vn_reference_t
 vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
 {
-  void **slot;
+  vn_reference_s **slot;
   vn_reference_t vr1;

   vr1 = (vn_reference_t) pool_alloc (current_info->references_pool);
@@ -2021,8 +2111,8 @@  vn_reference_insert (tree op, tree resul
   vr1->result = TREE_CODE (result) == SSA_NAME ? SSA_VAL (result) : result;
   vr1->result_vdef = vdef;

-  slot = htab_find_slot_with_hash (current_info->references, vr1,
vr1->hashcode,
-				   INSERT);
+  slot = current_info->references.find_slot_with_hash (vr1, vr1->hashcode,
+						       INSERT);

   /* Because we lookup stores using vuses, and value number failures
      using the vdefs (see visit_reference_op_store for how and why),
@@ -2050,7 +2140,7 @@  vn_reference_insert_pieces (tree vuse, a
 			    tree result, unsigned int value_id)

 {
-  void **slot;
+  vn_reference_s **slot;
   vn_reference_t vr1;

   vr1 = (vn_reference_t) pool_alloc (current_info->references_pool);
@@ -2064,8 +2154,8 @@  vn_reference_insert_pieces (tree vuse, a
     result = SSA_VAL (result);
   vr1->result = result;

-  slot = htab_find_slot_with_hash (current_info->references, vr1,
vr1->hashcode,
-				   INSERT);
+  slot = current_info->references.find_slot_with_hash (vr1, vr1->hashcode,
+						       INSERT);

   /* At this point we should have all the things inserted that we have
      seen before, and we should never try inserting something that
@@ -2106,23 +2196,12 @@  vn_nary_op_compute_hash (const vn_nary_o
   return hash;
 }

-/* Return the computed hashcode for nary operation P1.  */
-
-static hashval_t
-vn_nary_op_hash (const void *p1)
-{
-  const_vn_nary_op_t const vno1 = (const_vn_nary_op_t) p1;
-  return vno1->hashcode;
-}
-
-/* Compare nary operations P1 and P2 and return true if they are
+/* Compare nary operations VNO1 and VNO2 and return true if they are
    equivalent.  */

-int
-vn_nary_op_eq (const void *p1, const void *p2)
+bool
+vn_nary_op_eq (const_vn_nary_op_t const vno1, const_vn_nary_op_t const vno2)
 {
-  const_vn_nary_op_t const vno1 = (const_vn_nary_op_t) p1;
-  const_vn_nary_op_t const vno2 = (const_vn_nary_op_t) p2;
   unsigned i;

   if (vno1->hashcode != vno2->hashcode)
@@ -2239,22 +2318,20 @@  init_vn_nary_op_from_stmt (vn_nary_op_t
 static tree
 vn_nary_op_lookup_1 (vn_nary_op_t vno, vn_nary_op_t *vnresult)
 {
-  void **slot;
+  vn_nary_op_s **slot;

   if (vnresult)
     *vnresult = NULL;

   vno->hashcode = vn_nary_op_compute_hash (vno);
-  slot = htab_find_slot_with_hash (current_info->nary, vno, vno->hashcode,
-				   NO_INSERT);
+  slot = current_info->nary.find_slot_with_hash (vno, vno->hashcode,
NO_INSERT);
   if (!slot && current_info == optimistic_info)
-    slot = htab_find_slot_with_hash (valid_info->nary, vno, vno->hashcode,
-				     NO_INSERT);
+    slot = valid_info->nary.find_slot_with_hash (vno, vno->hashcode,
NO_INSERT);
   if (!slot)
     return NULL_TREE;
   if (vnresult)
-    *vnresult = (vn_nary_op_t)*slot;
-  return ((vn_nary_op_t)*slot)->result;
+    *vnresult = *slot;
+  return (*slot)->result;
 }

 /* Lookup a n-ary operation by its pieces and return the resulting value
@@ -2332,14 +2409,15 @@  alloc_vn_nary_op (unsigned int length, t
    VNO->HASHCODE first.  */

 static vn_nary_op_t
-vn_nary_op_insert_into (vn_nary_op_t vno, htab_t table, bool compute_hash)
+vn_nary_op_insert_into (vn_nary_op_t vno, vn_nary_op_table_type table,
+			bool compute_hash)
 {
-  void **slot;
+  vn_nary_op_s **slot;

   if (compute_hash)
     vno->hashcode = vn_nary_op_compute_hash (vno);

-  slot = htab_find_slot_with_hash (table, vno, vno->hashcode, INSERT);
+  slot = table.find_slot_with_hash (vno, vno->hashcode, INSERT);
   gcc_assert (!*slot);

   *slot = vno;
@@ -2417,23 +2495,11 @@  vn_phi_compute_hash (vn_phi_t vp1)
   return result;
 }

-/* Return the computed hashcode for phi operation P1.  */
-
-static hashval_t
-vn_phi_hash (const void *p1)
-{
-  const_vn_phi_t const vp1 = (const_vn_phi_t) p1;
-  return vp1->hashcode;
-}
-
 /* Compare two phi entries for equality, ignoring VN_TOP arguments.  */

 static int
-vn_phi_eq (const void *p1, const void *p2)
+vn_phi_eq (const_vn_phi_t const vp1, const_vn_phi_t const vp2)
 {
-  const_vn_phi_t const vp1 = (const_vn_phi_t) p1;
-  const_vn_phi_t const vp2 = (const_vn_phi_t) p2;
-
   if (vp1->hashcode != vp2->hashcode)
     return false;

@@ -2472,7 +2538,7 @@  static vec<tree> shared_lookup_phiargs;
 static tree
 vn_phi_lookup (gimple phi)
 {
-  void **slot;
+  vn_phi_s **slot;
   struct vn_phi_s vp1;
   unsigned i;

@@ -2488,14 +2554,12 @@  vn_phi_lookup (gimple phi)
   vp1.phiargs = shared_lookup_phiargs;
   vp1.block = gimple_bb (phi);
   vp1.hashcode = vn_phi_compute_hash (&vp1);
-  slot = htab_find_slot_with_hash (current_info->phis, &vp1, vp1.hashcode,
-				   NO_INSERT);
+  slot = current_info->phis.find_slot_with_hash (&vp1, vp1.hashcode,
NO_INSERT);
   if (!slot && current_info == optimistic_info)
-    slot = htab_find_slot_with_hash (valid_info->phis, &vp1, vp1.hashcode,
-				     NO_INSERT);
+    slot = valid_info->phis.find_slot_with_hash (&vp1, vp1.hashcode,
NO_INSERT);
   if (!slot)
     return NULL_TREE;
-  return ((vn_phi_t)*slot)->result;
+  return (*slot)->result;
 }

 /* Insert PHI into the current hash table with a value number of
@@ -2504,7 +2568,7 @@  vn_phi_lookup (gimple phi)
 static vn_phi_t
 vn_phi_insert (gimple phi, tree result)
 {
-  void **slot;
+  vn_phi_s **slot;
   vn_phi_t vp1 = (vn_phi_t) pool_alloc (current_info->phis_pool);
   unsigned i;
   vec<tree> args = vNULL;
@@ -2522,8 +2586,7 @@  vn_phi_insert (gimple phi, tree result)
   vp1->result = result;
   vp1->hashcode = vn_phi_compute_hash (vp1);

-  slot = htab_find_slot_with_hash (current_info->phis, vp1, vp1->hashcode,
-				   INSERT);
+  slot = current_info->phis.find_slot_with_hash (vp1, vp1->hashcode, INSERT);

   /* Because we iterate over phi operations more than once, it's
      possible the slot might already exist here, hence no assert.*/
@@ -2731,7 +2794,7 @@  visit_reference_op_call (tree lhs, gimpl
     }
   else
     {
-      void **slot;
+      vn_reference_s **slot;
       vn_reference_t vr2;
       if (vdef)
 	changed |= set_ssa_val_to (vdef, vdef);
@@ -2745,8 +2808,8 @@  visit_reference_op_call (tree lhs, gimpl
       vr2->hashcode = vr1.hashcode;
       vr2->result = lhs;
       vr2->result_vdef = vdef;
-      slot = htab_find_slot_with_hash (current_info->references,
-				       vr2, vr2->hashcode, INSERT);
+      slot = current_info->references.find_slot_with_hash (vr2, vr2->hashcode,
+							   INSERT);
       if (*slot)
 	free_reference (*slot);
       *slot = vr2;
@@ -3566,10 +3629,10 @@  static void
 copy_phi (vn_phi_t ophi, vn_tables_t info)
 {
   vn_phi_t phi = (vn_phi_t) pool_alloc (info->phis_pool);
-  void **slot;
+  vn_phi_s **slot;
   memcpy (phi, ophi, sizeof (*phi));
   ophi->phiargs.create (0);
-  slot = htab_find_slot_with_hash (info->phis, phi, phi->hashcode, INSERT);
+  slot = info->phis.find_slot_with_hash (phi, phi->hashcode, INSERT);
   gcc_assert (!*slot);
   *slot = phi;
 }
@@ -3580,12 +3643,11 @@  static void
 copy_reference (vn_reference_t oref, vn_tables_t info)
 {
   vn_reference_t ref;
-  void **slot;
+  vn_reference_s **slot;
   ref = (vn_reference_t) pool_alloc (info->references_pool);
   memcpy (ref, oref, sizeof (*ref));
   oref->operands.create (0);
-  slot = htab_find_slot_with_hash (info->references, ref, ref->hashcode,
-				   INSERT);
+  slot = info->references.find_slot_with_hash (ref, ref->hashcode, INSERT);
   if (*slot)
     free_reference (*slot);
   *slot = ref;
@@ -3600,7 +3662,9 @@  process_scc (vec<tree> scc)
   unsigned int i;
   unsigned int iterations = 0;
   bool changed = true;
-  htab_iterator hi;
+  vn_nary_op_iterator_type hin;
+  vn_phi_iterator_type hip;
+  vn_reference_iterator_type hir;
   vn_nary_op_t nary;
   vn_phi_t phi;
   vn_reference_t ref;
@@ -3637,9 +3701,9 @@  process_scc (vec<tree> scc)
       /* As we are value-numbering optimistically we have to
 	 clear the expression tables and the simplified expressions
 	 in each iteration until we converge.  */
-      htab_empty (optimistic_info->nary);
-      htab_empty (optimistic_info->phis);
-      htab_empty (optimistic_info->references);
+      optimistic_info->nary.empty ();
+      optimistic_info->phis.empty ();
+      optimistic_info->references.empty ();
       obstack_free (&optimistic_info->nary_obstack, NULL);
       gcc_obstack_init (&optimistic_info->nary_obstack);
       empty_alloc_pool (optimistic_info->phis_pool);
@@ -3654,11 +3718,12 @@  process_scc (vec<tree> scc)

   /* Finally, copy the contents of the no longer used optimistic
      table to the valid table.  */
-  FOR_EACH_HTAB_ELEMENT (optimistic_info->nary, nary, vn_nary_op_t, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (optimistic_info->nary, nary, vn_nary_op_t, hin)
     copy_nary (nary, valid_info);
-  FOR_EACH_HTAB_ELEMENT (optimistic_info->phis, phi, vn_phi_t, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (optimistic_info->phis, phi, vn_phi_t, hip)
     copy_phi (phi, valid_info);
-  FOR_EACH_HTAB_ELEMENT (optimistic_info->references, ref, vn_reference_t, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (optimistic_info->references,
+			       ref, vn_reference_t, hir)
     copy_reference (ref, valid_info);

   current_info = valid_info;
@@ -3818,10 +3883,9 @@  continue_walking:
 static void
 allocate_vn_table (vn_tables_t table)
 {
-  table->phis = htab_create (23, vn_phi_hash, vn_phi_eq, free_phi);
-  table->nary = htab_create (23, vn_nary_op_hash, vn_nary_op_eq, NULL);
-  table->references = htab_create (23, vn_reference_hash, vn_reference_eq,
-				   free_reference);
+  table->phis.create (23);
+  table->nary.create (23);
+  table->references.create (23);

   gcc_obstack_init (&table->nary_obstack);
   table->phis_pool = create_alloc_pool ("VN phis",
@@ -3837,9 +3901,9 @@  allocate_vn_table (vn_tables_t table)
 static void
 free_vn_table (vn_tables_t table)
 {
-  htab_delete (table->phis);
-  htab_delete (table->nary);
-  htab_delete (table->references);
+  table->phis.dispose ();
+  table->nary.dispose ();
+  table->references.dispose ();
   obstack_free (&table->nary_obstack, NULL);
   free_alloc_pool (table->phis_pool);
   free_alloc_pool (table->references_pool);
@@ -3854,8 +3918,7 @@  init_scc_vn (void)

   calculate_dominance_info (CDI_DOMINATORS);
   sccstack.create (0);
-  constant_to_value_id = htab_create (23, vn_constant_hash, vn_constant_eq,
-				  free);
+  constant_to_value_id.create (23);

   constant_value_ids = BITMAP_ALLOC (NULL);

@@ -3911,7 +3974,7 @@  free_scc_vn (void)
 {
   size_t i;

-  htab_delete (constant_to_value_id);
+  constant_to_value_id.dispose ();
   BITMAP_FREE (constant_value_ids);
   shared_lookup_phiargs.release ();
   shared_lookup_references.release ();
@@ -3953,7 +4016,9 @@  set_value_id_for_result (tree result, un
 static void
 set_hashtable_value_ids (void)
 {
-  htab_iterator hi;
+  vn_nary_op_iterator_type hin;
+  vn_phi_iterator_type hip;
+  vn_reference_iterator_type hir;
   vn_nary_op_t vno;
   vn_reference_t vr;
   vn_phi_t vp;
@@ -3961,16 +4026,13 @@  set_hashtable_value_ids (void)
   /* Now set the value ids of the things we had put in the hash
      table.  */

-  FOR_EACH_HTAB_ELEMENT (valid_info->nary,
-			 vno, vn_nary_op_t, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (valid_info->nary, vno, vn_nary_op_t, hin)
     set_value_id_for_result (vno->result, &vno->value_id);

-  FOR_EACH_HTAB_ELEMENT (valid_info->phis,
-			 vp, vn_phi_t, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (valid_info->phis, vp, vn_phi_t, hip)
     set_value_id_for_result (vp->result, &vp->value_id);

-  FOR_EACH_HTAB_ELEMENT (valid_info->references,
-			 vr, vn_reference_t, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (valid_info->references, vr, vn_reference_t, hir)
     set_value_id_for_result (vr->result, &vr->value_id);
 }

Index: gcc/tree-ssa-sccvn.h
===================================================================
--- gcc/tree-ssa-sccvn.h	(revision 194487)
+++ gcc/tree-ssa-sccvn.h	(working copy)
@@ -207,10 +207,11 @@  vn_reference_t vn_reference_insert_piece
 					   tree, unsigned int);

 hashval_t vn_nary_op_compute_hash (const vn_nary_op_t);
-int vn_nary_op_eq (const void *, const void *);
+bool vn_nary_op_eq (const_vn_nary_op_t const vno1,
+		    const_vn_nary_op_t const vno2);
 bool vn_nary_may_trap (vn_nary_op_t);
 hashval_t vn_reference_compute_hash (const vn_reference_t);
-int vn_reference_eq (const void *, const void *);
+bool vn_reference_eq (const_vn_reference_t const, const_vn_reference_t const);
 unsigned int get_max_value_id (void);
 unsigned int get_next_value_id (void);
 unsigned int get_constant_value_id (tree);
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 194487)
+++ gcc/Makefile.in	(working copy)
@@ -2269,7 +2269,7 @@  tree-into-ssa.o : tree-into-ssa.c $(TREE
    $(TREE_H) $(TM_P_H) $(DIAGNOSTIC_CORE_H) \
    $(FUNCTION_H) $(TM_H) coretypes.h \
    langhooks.h domwalk.h $(TREE_PASS_H) $(PARAMS_H) $(BASIC_BLOCK_H) \
-   $(BITMAP_H) $(CFGLOOP_H) $(FLAGS_H) $(HASHTAB_H) \
+   $(BITMAP_H) $(CFGLOOP_H) $(FLAGS_H) $(HASH_TABLE_H) \
    $(GIMPLE_H) $(TREE_INLINE_H) $(GIMPLE_PRETTY_PRINT_H)
 tree-ssa-ter.o : tree-ssa-ter.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h dumpfile.h \
@@ -2367,7 +2367,7 @@  tree-ssa-pre.o : tree-ssa-pre.c $(TREE_F
 tree-ssa-sccvn.o : tree-ssa-sccvn.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) \
    $(TM_H) coretypes.h dumpfile.h $(FLAGS_H) $(CFGLOOP_H) \
-   alloc-pool.h $(BASIC_BLOCK_H) $(BITMAP_H) $(HASHTAB_H) $(GIMPLE_H) \
+   alloc-pool.h $(BASIC_BLOCK_H) $(BITMAP_H) $(HASH_TABLE_H) $(GIMPLE_H) \
    $(TREE_INLINE_H) tree-ssa-propagate.h tree-ssa-sccvn.h \
    $(PARAMS_H) $(GIMPLE_PRETTY_PRINT_H) gimple-fold.h
 gimple-ssa-strength-reduction.o : gimple-ssa-strength-reduction.c $(CONFIG_H) \
@@ -3077,7 +3077,7 @@  valtrack.o : valtrack.c $(VALTRACK_H) $(
    coretypes.h $(TM_H) $(FUNCTION_H) $(REGS_H) $(EMIT_RTL_H)
 var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h $(FLAGS_H) \
-   $(BASIC_BLOCK_H) bitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \
+   $(BASIC_BLOCK_H) bitmap.h alloc-pool.h $(FIBHEAP_H) $(HASH_TABLE_H) \
    $(REGS_H) $(EXPR_H) $(TREE_PASS_H) $(TREE_FLOW_H) \
    cselib.h $(TARGET_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) $(DIAGNOSTIC_H) \
    pointer-set.h $(RECOG_H) $(TM_P_H) $(TREE_PRETTY_PRINT_H) $(ALIAS_H)
Index: gcc/hash-table.h
===================================================================
--- gcc/hash-table.h	(revision 194487)
+++ gcc/hash-table.h	(working copy)
@@ -156,6 +156,47 @@  along with GCC; see the file COPYING3.

       hash_table <pointer_hash <whatever_type>> whatever_type_hash_table;

+
+   HASH TABLE ITERATORS
+
+   The hash table provides standard C++ iterators.  For example, consider a
+   hash table of some_info.  We wish to consume each element of the table:
+
+      extern void consume (some_info *);
+
+   We define a convenience typedef and the hash table:
+
+      typedef hash_table <some_info_hasher> info_table_type;
+      info_table_type info_table;
+
+   Then we write the loop in typical C++ style:
+
+      for (info_table_type::iterator iter = info_table.begin ();
+           iter != info_table.end ();
+           ++iter)
+        if ((*iter).status == INFO_READY)
+          consume (&*iter);
+
+   Or with common sub-expression elimination:
+
+      for (info_table_type::iterator iter = info_table.begin ();
+           iter != info_table.end ();
+           ++iter)
+        {
+          some_info &elem = *iter;
+          if (elem.status == INFO_READY)
+            consume (&elem);
+        }
+
+   One can also use a more typical GCC style:
+
+      typedef some_info *some_info_p;
+      some_info *elem_ptr;
+      info_table_type::iterator iter;
+      FOR_EACH_HASH_TABLE_ELEMENT (info_table, elem_ptr, some_info_p, iter)
+        if (elem_ptr->status == INFO_READY)
+          consume (elem_ptr);
+
 */


@@ -369,6 +410,20 @@  public:
   typedef typename Descriptor::value_type value_type;
   typedef typename Descriptor::compare_type compare_type;

+  class iterator
+  {
+  public:
+    inline iterator ();
+    inline iterator (value_type **, value_type **);
+    inline value_type &operator * ();
+    void slide ();
+    inline iterator &operator ++ ();
+    inline bool operator != (const iterator &) const;
+  private:
+    value_type **slot_;
+    value_type **limit_;
+  };
+
 private:
   hash_table_control <value_type> *htab;

@@ -401,6 +456,9 @@  public:
   template <typename Argument,
 	    int (*Callback) (value_type **slot, Argument argument)>
   void traverse (Argument argument);
+
+  iterator begin();
+  iterator end();
 };


@@ -893,4 +951,114 @@  hash_table <Descriptor, Allocator>::trav
   traverse_noresize <Argument, Callback> (argument);
 }

+
+/* Iterator definitions.  */
+
+/* The default constructor produces the end value.  */
+
+template <typename Descriptor,
+	  template <typename Type> class Allocator>
+inline
+hash_table <Descriptor, Allocator>::iterator::iterator ()
+: slot_ (NULL), limit_ (NULL)
+{
+}
+
+/* The parameterized constructor produces the begin value.  */
+
+template <typename Descriptor,
+	  template <typename Type> class Allocator>
+inline
+hash_table <Descriptor, Allocator>::iterator::iterator
+   (value_type **slot, value_type **limit)
+: slot_ (slot), limit_ (limit)
+{
+}
+
+/* Obtain the element.  */
+
+template <typename Descriptor,
+	  template <typename Type> class Allocator>
+inline typename hash_table <Descriptor, Allocator>::value_type &
+hash_table <Descriptor, Allocator>::iterator::operator * ()
+{
+  return **slot_;
+}
+
+/* Slide down the iterator slots until an active entry is found.  */
+
+template <typename Descriptor,
+	  template <typename Type> class Allocator>
+void
+hash_table <Descriptor, Allocator>::iterator::slide ()
+{
+  for ( ; slot_ < limit_; ++slot_ )
+    {
+      value_type *x = *slot_;
+      if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
+        return;
+    }
+  slot_ = NULL;
+  limit_ = NULL;
+}
+
+/* Bump the iterator.  */
+
+template <typename Descriptor,
+	  template <typename Type> class Allocator>
+inline typename hash_table <Descriptor, Allocator>::iterator &
+hash_table <Descriptor, Allocator>::iterator::operator ++ ()
+{
+  ++slot_;
+  slide ();
+  return *this;
+}
+
+/* Compare iterators.  */
+
+template <typename Descriptor,
+	  template <typename Type> class Allocator>
+inline bool
+hash_table <Descriptor, Allocator>::iterator::
+  operator != (const iterator &other) const
+{
+  return slot_ != other.slot_ || limit_ != other.limit_;
+}
+
+/* Hash table iterator producers.  */
+
+/* The beginning of a hash table iteration.  */
+
+template <typename Descriptor,
+	  template <typename Type> class Allocator>
+inline typename hash_table <Descriptor, Allocator>::iterator
+hash_table <Descriptor, Allocator>::begin ()
+{
+  iterator hti (htab->entries, htab->entries + htab->size);
+  hti.slide ();
+  return hti;
+}
+
+/* The end of a hash table iteration.  */
+
+template <typename Descriptor,
+	  template <typename Type> class Allocator>
+inline typename hash_table <Descriptor, Allocator>::iterator
+hash_table <Descriptor, Allocator>::end ()
+{
+  return iterator ();
+}
+
+/* Iterate through the elements of hash_table HTAB,
+   using hash_table <....>::iterator ITER,
+   storing each element in RESULT, which is of type TYPE.
+
+   This macro has this form for compatibility with the
+   FOR_EACH_HTAB_ELEMENT currently defined in tree-flow.h.  */
+
+#define FOR_EACH_HASH_TABLE_ELEMENT(HTAB, RESULT, TYPE, ITER) \
+  for ((ITER) = (HTAB).begin (); \
+       (ITER) != (HTAB).end () ? (RESULT = &*(ITER) , true) : false; \
+       ++(ITER))
+
 #endif /* TYPED_HASHTAB_H */