Patchwork Hash table changes from cxx-conversion branch - PART 1

login
register
mail settings
Submitter Lawrence Crowl
Date April 23, 2013, 10:02 p.m.
Message ID <CAGqM8fandnKOyhh3aeRBWiQtOVr0=chjYcq=0NtCQcTjRaNvJw@mail.gmail.com>
Download mbox | patch
Permalink /patch/239021/
State New
Headers show

Comments

Lawrence Crowl - April 23, 2013, 10:02 p.m.
This patch extracts approved portions of the hash_table patches to
the cxx-conversion branch for files not under gcc/config.

Patch committed to trunk.

Update various hash tables from htab_t to hash_table.
Modify types and calls to match.

* tree-ssa-coalesce.c'coalesce_list_d.list from htab_t to hash_table.

Fold coalesce_pair_map_hash and coalesce_pair_map_eq into new
struct coalesce_pair_hasher.

Removed struct coalesce_pair_iterator, as did not meet the hash_table
iterator interface and it provided no significant code reduction.
This leads to a change in the implementation of FOR_EACH_PARTITION_PAIR.

* statistics.c'statistics_hashes

Fold hash_statistics_eq into new struct stats_counter_hasher.

* 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.
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.

* tree-vectorizer.h'_loop_vec_info::peeling_htab

* tree-vectorizer.h

New struct peel_info_hasher.

* tree-vect-loop.c

Update dependent calls and types to match.

* tree-vect-data-refs.c

Fold vect_peeling_hash and vect_peeling_hash_eq into struct peel_info_hasher.

* tree-ssa-reassoc.c'undistribute_ops_list::ctable

Fold oecount_hash and oecount_eq into new struct oecount_hasher.

* tree-ssa-loop-im.c'memory_accesses.refs

Fold memref_hash and memref_eq into new struct mem_ref_hasher.

Tested on x86_64.

Patch

Index: gcc/ChangeLog

2013-04-23  Lawrence Crowl  <crowl@google.com>

	* Makefile.in: Update as needed below.

	* hash-table.h (class hash_table):
	Correct many methods with parameter types compare_type to the correct
	value_type.  (Correct code was unlikely to notice the change.)
	(hash_table::elements_with_deleted) New.
	(class hashtable::iterator): New.
	(hashtable::begin()): New.
	(hashtable::end()): New.
	(FOR_EACH_HASH_TABLE_ELEMENT): New.

	* statistics.c (statistics_hashes):
	Change type to hash_table.  Update dependent calls and types.

	* tree-into-ssa.c (var_infos):
	Change type to hash_table.  Update dependent calls and types.

	* tree-ssa-coalesce.c (struct coalesce_list_d.list):
	Change type to hash_table.  Update dependent calls and types.

	* tree-ssa-loop-im.c (struct mem_ref.refs):
	Change type to hash_table.  Update dependent calls and types.

	* tree-ssa-reassoc.c (undistribute_ops_list::ctable):
	Change type to hash_table.  Update dependent calls and types.

	* tree-ssa-sccvn.c (vn_tables_s::nary):
	Change type to hash_table.  Update dependent calls and types.
	(vn_tables_s::phis): Likewise.
	(vn_tables_s::references): Likewise.

	* tree-ssa-sccvn.h (vn_nary_op_eq): Update parameter and return types.
	(vn_reference_eq): Update parameter and return types.

	* tree-ssa-structalias.c (pointer_equiv_class_table):
	Change type to hash_table.  Update dependent calls and types.
	(location_equiv_class_table): Likewise.

	* tree-vect-data-refs.c: Consequential changes for making
	peeling a hash_table.

	* tree-vect-loop.c (new_loop_vec_info): Dependent hash_table update.
	(destroy_loop_vec_info): Dependent hash_table update.

	* tree-vectorizer.h (peeling_htab):
	Change type to hash_table.  Update dependent calls and types.

Index: gcc/tree-ssa-reassoc.c
===================================================================
--- gcc/tree-ssa-reassoc.c	(revision 198204)
+++ gcc/tree-ssa-reassoc.c	(working copy)
@@ -21,6 +21,7 @@  along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "tm.h"
 #include "tree.h"
 #include "basic-block.h"
@@ -943,10 +944,23 @@  typedef struct oecount_s {
 /* The heap for the oecount hashtable and the sorted list of operands.  */
 static vec<oecount> cvec;

+
+/* Oecount hashtable helpers.  */
+
+struct oecount_hasher : typed_noop_remove <void>
+{
+  /* Note that this hash table stores integers, not pointers.
+     So, observe the casting in the member functions.  */
+  typedef void value_type;
+  typedef void compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
 /* Hash function for oecount.  */

-static hashval_t
-oecount_hash (const void *p)
+inline hashval_t
+oecount_hasher::hash (const value_type *p)
 {
   const oecount *c = &cvec[(size_t)p - 42];
   return htab_hash_pointer (c->op) ^ (hashval_t)c->oecode;
@@ -954,8 +968,8 @@  oecount_hash (const void *p)

 /* Comparison function for oecount.  */

-static int
-oecount_eq (const void *p1, const void *p2)
+inline bool
+oecount_hasher::equal (const value_type *p1, const compare_type *p2)
 {
   const oecount *c1 = &cvec[(size_t)p1 - 42];
   const oecount *c2 = &cvec[(size_t)p2 - 42];
@@ -1257,7 +1271,7 @@  undistribute_ops_list (enum tree_code op
   unsigned nr_candidates, nr_candidates2;
   sbitmap_iterator sbi0;
   vec<operand_entry_t> *subops;
-  htab_t ctable;
+  hash_table <oecount_hasher> ctable;
   bool changed = false;
   int next_oecount_id = 0;

@@ -1305,7 +1319,7 @@  undistribute_ops_list (enum tree_code op

   /* Build linearized sub-operand lists and the counting table.  */
   cvec.create (0);
-  ctable = htab_create (15, oecount_hash, oecount_eq, NULL);
+  ctable.create (15);
   /* ??? Macro arguments cannot have multi-argument template types in
      them.  This typedef is needed to workaround that limitation.  */
   typedef vec<operand_entry_t> vec_operand_entry_t_heap;
@@ -1332,7 +1346,7 @@  undistribute_ops_list (enum tree_code op
 	  c.op = oe1->op;
 	  cvec.safe_push (c);
 	  idx = cvec.length () + 41;
-	  slot = htab_find_slot (ctable, (void *)idx, INSERT);
+	  slot = ctable.find_slot ((void *)idx, INSERT);
 	  if (!*slot)
 	    {
 	      *slot = (void *)idx;
@@ -1344,7 +1358,7 @@  undistribute_ops_list (enum tree_code op
 	    }
 	}
     }
-  htab_delete (ctable);
+  ctable.dispose ();

   /* Sort the counting table.  */
   cvec.qsort (oecount_cmp);
Index: gcc/tree-ssa-loop-im.c
===================================================================
--- gcc/tree-ssa-loop-im.c	(revision 198204)
+++ gcc/tree-ssa-loop-im.c	(working copy)
@@ -31,7 +31,7 @@  along with GCC; see the file COPYING3.
 #include "params.h"
 #include "tree-pass.h"
 #include "flags.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "tree-affine.h"
 #include "pointer-set.h"
 #include "tree-ssa-propagate.h"
@@ -133,6 +133,32 @@  typedef struct mem_ref
    and its subloops.  */
 #define LOOP_DEP_BIT(loopnum, storedp) (2 * (loopnum) + (storedp ? 1 : 0))

+/* Mem_ref hashtable helpers.  */
+
+struct mem_ref_hasher : typed_noop_remove <mem_ref>
+{
+  typedef mem_ref value_type;
+  typedef tree_node compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* A hash function for struct mem_ref object OBJ.  */
+
+inline hashval_t
+mem_ref_hasher::hash (const value_type *mem)
+{
+  return mem->hash;
+}
+
+/* An equality function for struct mem_ref object MEM1 with
+   memory reference OBJ2.  */
+
+inline bool
+mem_ref_hasher::equal (const value_type *mem1, const compare_type *obj2)
+{
+  return operand_equal_p (mem1->mem.ref, (const_tree) obj2, 0);
+}


 /* Description of memory accesses in loops.  */
@@ -140,7 +166,7 @@  typedef struct mem_ref
 static struct
 {
   /* The hash table of memory references accessed in loops.  */
-  htab_t refs;
+  hash_table <mem_ref_hasher> refs;

   /* The list of memory references.  */
   vec<mem_ref_p> refs_list;
@@ -646,7 +672,7 @@  mem_ref_in_stmt (gimple stmt)
   gcc_assert (!store);

   hash = iterative_hash_expr (*mem, 0);
-  ref = (mem_ref_p) htab_find_with_hash (memory_accesses.refs, *mem, hash);
+  ref = memory_accesses.refs.find_with_hash (*mem, hash);

   gcc_assert (ref != NULL);
   return ref;
@@ -1411,27 +1437,6 @@  force_move_till (tree ref, tree *index,
   return true;
 }

-/* A hash function for struct mem_ref object OBJ.  */
-
-static hashval_t
-memref_hash (const void *obj)
-{
-  const struct mem_ref *const mem = (const struct mem_ref *) obj;
-
-  return mem->hash;
-}
-
-/* An equality function for struct mem_ref object OBJ1 with
-   memory reference OBJ2.  */
-
-static int
-memref_eq (const void *obj1, const void *obj2)
-{
-  const struct mem_ref *const mem1 = (const struct mem_ref *) obj1;
-
-  return operand_equal_p (mem1->mem.ref, (const_tree) obj2, 0);
-}
-
 /* A function to free the mem_ref object OBJ.  */

 static void
@@ -1502,7 +1507,7 @@  gather_mem_refs_stmt (struct loop *loop,
 {
   tree *mem = NULL;
   hashval_t hash;
-  PTR *slot;
+  mem_ref **slot;
   mem_ref_p ref;
   bool is_stored;
   unsigned id;
@@ -1526,8 +1531,7 @@  gather_mem_refs_stmt (struct loop *loop,
   else
     {
       hash = iterative_hash_expr (*mem, 0);
-      slot = htab_find_slot_with_hash (memory_accesses.refs,
-				       *mem, hash, INSERT);
+      slot = memory_accesses.refs.find_slot_with_hash (*mem, hash, INSERT);
       if (*slot)
 	{
 	  ref = (mem_ref_p) *slot;
@@ -2553,7 +2557,7 @@  tree_ssa_lim_initialize (void)

   alloc_aux_for_edges (0);

-  memory_accesses.refs = htab_create (100, memref_hash, memref_eq, NULL);
+  memory_accesses.refs.create (100);
   memory_accesses.refs_list.create (100);
   /* Allocate a special, unanalyzable mem-ref with ID zero.  */
   memory_accesses.refs_list.quick_push
@@ -2596,7 +2600,7 @@  tree_ssa_lim_finalize (void)
   bitmap_obstack_release (&lim_bitmap_obstack);
   pointer_map_destroy (lim_aux_data_map);

-  htab_delete (memory_accesses.refs);
+  memory_accesses.refs.dispose ();

   FOR_EACH_VEC_ELT (memory_accesses.refs_list, i, ref)
     memref_free (ref);
Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c	(revision 198204)
+++ gcc/tree-ssa-sccvn.c	(working copy)
@@ -29,7 +29,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"
@@ -96,19 +96,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;


@@ -338,62 +506,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;
 }

@@ -403,22 +529,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;
 }
@@ -431,26 +556,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
@@ -466,15 +571,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
@@ -524,16 +620,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;

@@ -1346,15 +1440,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)
@@ -1377,7 +1469,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
@@ -1397,11 +1489,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;

@@ -2004,7 +2094,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);
@@ -2020,8 +2110,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),
@@ -2049,7 +2139,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);
@@ -2063,8 +2153,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
@@ -2105,23 +2195,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)
@@ -2238,22 +2317,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
@@ -2331,14 +2408,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;
@@ -2414,23 +2492,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;

@@ -2468,7 +2534,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;

@@ -2485,14 +2551,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
@@ -2501,7 +2565,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;
@@ -2520,8 +2584,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.*/
@@ -2724,7 +2787,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);
@@ -2738,8 +2801,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;
@@ -3599,10 +3662,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;
 }
@@ -3613,12 +3676,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;
@@ -3633,7 +3695,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;
@@ -3670,9 +3734,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);
@@ -3687,11 +3751,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;
@@ -3851,10 +3916,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",
@@ -3870,9 +3934,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);
@@ -3887,8 +3951,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);

@@ -3944,7 +4007,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 ();
@@ -3985,7 +4048,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;
@@ -3993,16 +4058,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 198204)
+++ gcc/tree-ssa-sccvn.h	(working copy)
@@ -216,10 +216,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/tree-into-ssa.c
===================================================================
--- gcc/tree-into-ssa.c	(revision 198204)
+++ gcc/tree-into-ssa.c	(working copy)
@@ -33,7 +33,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"
@@ -160,9 +160,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.  */
@@ -340,17 +363,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;
 }


@@ -1044,15 +1067,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);

@@ -1632,12 +1655,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 ());
 }


@@ -1646,7 +1669,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:   ");
@@ -1665,29 +1688,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);
@@ -1708,8 +1714,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);
 }


@@ -2216,7 +2222,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);
     }

@@ -2296,9 +2302,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);
 }
@@ -2309,11 +2314,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);

@@ -3189,7 +3191,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/statistics.c
===================================================================
--- gcc/statistics.c	(revision 198204)
+++ gcc/statistics.c	(working copy)
@@ -24,7 +24,7 @@  along with GCC; see the file COPYING3.
 #include "tree-pass.h"
 #include "tree-dump.h"
 #include "statistics.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "function.h"

 static int statistics_dump_nr;
@@ -42,42 +42,52 @@  typedef struct statistics_counter_s {
   unsigned HOST_WIDE_INT prev_dumped_count;
 } statistics_counter_t;

-/* Array of statistic hashes, indexed by pass id.  */
-static htab_t *statistics_hashes;
-static unsigned nr_statistics_hashes;
+/* Hashtable helpers.  */
+
+struct stats_counter_hasher
+{
+  typedef statistics_counter_t value_type;
+  typedef statistics_counter_t 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 *);
+};

 /* Hash a statistic counter by its string ID.  */

-static hashval_t
-hash_statistics_hash (const void *p)
+inline hashval_t
+stats_counter_hasher::hash (const value_type *c)
 {
-  const statistics_counter_t *const c = (const statistics_counter_t *)p;
   return htab_hash_string (c->id) + c->val;
 }

 /* Compare two statistic counters by their string IDs.  */

-static int
-hash_statistics_eq (const void *p, const void *q)
+inline bool
+stats_counter_hasher::equal (const value_type *c1, const compare_type *c2)
 {
-  const statistics_counter_t *const c1 = (const statistics_counter_t *)p;
-  const statistics_counter_t *const c2 = (const statistics_counter_t *)q;
   return c1->val == c2->val && strcmp (c1->id, c2->id) == 0;
 }

 /* Free a statistics entry.  */

-static void
-hash_statistics_free (void *p)
+inline void
+stats_counter_hasher::remove (value_type *v)
 {
-  free (CONST_CAST(char *, ((statistics_counter_t *)p)->id));
-  free (p);
+  free (CONST_CAST(char *, v->id));
+  free (v);
 }

+typedef hash_table <stats_counter_hasher> stats_counter_table_type;
+
+/* Array of statistic hashes, indexed by pass id.  */
+static stats_counter_table_type *statistics_hashes;
+static unsigned nr_statistics_hashes;
+
 /* Return the current hashtable to be used for recording or printing
    statistics.  */

-static htab_t
+static stats_counter_table_type
 curr_statistics_hash (void)
 {
   unsigned idx;
@@ -86,20 +96,20 @@  curr_statistics_hash (void)
   idx = current_pass->static_pass_number;

   if (idx < nr_statistics_hashes
-      && statistics_hashes[idx] != NULL)
+      && statistics_hashes[idx].is_created ())
     return statistics_hashes[idx];

   if (idx >= nr_statistics_hashes)
     {
-      statistics_hashes = XRESIZEVEC (struct htab *, statistics_hashes, idx+1);
+      statistics_hashes = XRESIZEVEC (stats_counter_table_type,
+				      statistics_hashes, idx+1);
       memset (statistics_hashes + nr_statistics_hashes, 0,
-	      (idx + 1 - nr_statistics_hashes) * sizeof (htab_t));
+	      (idx + 1 - nr_statistics_hashes)
+	      * sizeof (stats_counter_table_type));
       nr_statistics_hashes = idx + 1;
     }

-  statistics_hashes[idx] = htab_create (15, hash_statistics_hash,
-					hash_statistics_eq,
-					hash_statistics_free);
+  statistics_hashes[idx].create (15);

   return statistics_hashes[idx];
 }
@@ -107,10 +117,11 @@  curr_statistics_hash (void)
 /* Helper for statistics_fini_pass.  Print the counter difference
    since the last dump for the pass dump files.  */

-static int
-statistics_fini_pass_1 (void **slot, void *data ATTRIBUTE_UNUSED)
+int
+statistics_fini_pass_1 (statistics_counter_t **slot,
+			void *data ATTRIBUTE_UNUSED)
 {
-  statistics_counter_t *counter = (statistics_counter_t *)*slot;
+  statistics_counter_t *counter = *slot;
   unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
   if (count == 0)
     return 1;
@@ -127,10 +138,11 @@  statistics_fini_pass_1 (void **slot, voi
 /* Helper for statistics_fini_pass.  Print the counter difference
    since the last dump for the statistics dump.  */

-static int
-statistics_fini_pass_2 (void **slot, void *data ATTRIBUTE_UNUSED)
+int
+statistics_fini_pass_2 (statistics_counter_t **slot,
+			void *data ATTRIBUTE_UNUSED)
 {
-  statistics_counter_t *counter = (statistics_counter_t *)*slot;
+  statistics_counter_t *counter = *slot;
   unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
   if (count == 0)
     return 1;
@@ -157,10 +169,11 @@  statistics_fini_pass_2 (void **slot, voi

 /* Helper for statistics_fini_pass, reset the counters.  */

-static int
-statistics_fini_pass_3 (void **slot, void *data ATTRIBUTE_UNUSED)
+int
+statistics_fini_pass_3 (statistics_counter_t **slot,
+			void *data ATTRIBUTE_UNUSED)
 {
-  statistics_counter_t *counter = (statistics_counter_t *)*slot;
+  statistics_counter_t *counter = *slot;
   counter->prev_dumped_count = counter->count;
   return 1;
 }
@@ -179,26 +192,25 @@  statistics_fini_pass (void)
       fprintf (dump_file, "\n");
       fprintf (dump_file, "Pass statistics:\n");
       fprintf (dump_file, "----------------\n");
-      htab_traverse_noresize (curr_statistics_hash (),
-			      statistics_fini_pass_1, NULL);
+      curr_statistics_hash ()
+	.traverse_noresize <void *, statistics_fini_pass_1> (NULL);
       fprintf (dump_file, "\n");
     }
   if (statistics_dump_file
       && !(statistics_dump_flags & TDF_STATS
 	   || statistics_dump_flags & TDF_DETAILS))
-    htab_traverse_noresize (curr_statistics_hash (),
-			    statistics_fini_pass_2, NULL);
-  htab_traverse_noresize (curr_statistics_hash (),
-			  statistics_fini_pass_3, NULL);
+    curr_statistics_hash ()
+      .traverse_noresize <void *, statistics_fini_pass_2> (NULL);
+  curr_statistics_hash ()
+    .traverse_noresize <void *, statistics_fini_pass_3> (NULL);
 }

 /* Helper for printing summary information.  */

-static int
-statistics_fini_1 (void **slot, void *data)
+int
+statistics_fini_1 (statistics_counter_t **slot, opt_pass *pass)
 {
-  struct opt_pass *pass = (struct opt_pass *)data;
-  statistics_counter_t *counter = (statistics_counter_t *)*slot;
+  statistics_counter_t *counter = *slot;
   if (counter->count == 0)
     return 1;
   if (counter->histogram_p)
@@ -230,10 +242,11 @@  statistics_fini (void)
     {
       unsigned i;
       for (i = 0; i < nr_statistics_hashes; ++i)
-	if (statistics_hashes[i] != NULL
+	if (statistics_hashes[i].is_created ()
 	    && get_pass_for_id (i) != NULL)
-	  htab_traverse_noresize (statistics_hashes[i],
-				  statistics_fini_1, get_pass_for_id (i));
+	  statistics_hashes[i]
+	    .traverse_noresize <opt_pass *, statistics_fini_1>
+	    (get_pass_for_id (i));
     }

   dump_end (statistics_dump_nr, statistics_dump_file);
@@ -261,14 +274,14 @@  statistics_init (void)
    and HISTOGRAM_P.  */

 static statistics_counter_t *
-lookup_or_add_counter (htab_t hash, const char *id, int val,
+lookup_or_add_counter (stats_counter_table_type hash, const char *id, int val,
 		       bool histogram_p)
 {
   statistics_counter_t **counter;
   statistics_counter_t c;
   c.id = id;
   c.val = val;
-  counter = (statistics_counter_t **) htab_find_slot (hash, &c, INSERT);
+  counter = hash.find_slot (&c, INSERT);
   if (!*counter)
     {
       *counter = XNEW (struct statistics_counter_s);
Index: gcc/tree-ssa-coalesce.c
===================================================================
--- gcc/tree-ssa-coalesce.c	(revision 198204)
+++ gcc/tree-ssa-coalesce.c	(working copy)
@@ -49,6 +49,41 @@  typedef struct coalesce_pair
 } * coalesce_pair_p;
 typedef const struct coalesce_pair *const_coalesce_pair_p;

+/* Coalesce pair hashtable helpers.  */
+
+struct coalesce_pair_hasher : typed_noop_remove <coalesce_pair>
+{
+  typedef coalesce_pair value_type;
+  typedef coalesce_pair compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Hash function for coalesce list.  Calculate hash for PAIR.   */
+
+inline hashval_t
+coalesce_pair_hasher::hash (const value_type *pair)
+{
+  hashval_t a = (hashval_t)(pair->first_element);
+  hashval_t b = (hashval_t)(pair->second_element);
+
+  return b * (b - 1) / 2 + a;
+}
+
+/* Equality function for coalesce list hash table.  Compare PAIR1 and PAIR2,
+   returning TRUE if the two pairs are equivalent.  */
+
+inline bool
+coalesce_pair_hasher::equal (const value_type *p1, const compare_type *p2)
+{
+  return (p1->first_element == p2->first_element
+	  && p1->second_element == p2->second_element);
+}
+
+typedef hash_table <coalesce_pair_hasher> coalesce_table_type;
+typedef coalesce_table_type::iterator coalesce_iterator_type;
+
+
 typedef struct cost_one_pair_d
 {
   int first_element;
@@ -60,7 +95,7 @@  typedef struct cost_one_pair_d

 typedef struct coalesce_list_d
 {
-  htab_t list;			/* Hash table.  */
+  coalesce_table_type list;	/* Hash table.  */
   coalesce_pair_p *sorted;	/* List when sorted.  */
   int num_sorted;		/* Number in the sorted list.  */
   cost_one_pair_p cost_one_list;/* Single use coalesces with cost 1.  */
@@ -185,34 +220,6 @@  pop_best_coalesce (coalesce_list_p cl, i
 }


-#define COALESCE_HASH_FN(R1, R2) ((R2) * ((R2) - 1) / 2 + (R1))
-
-/* Hash function for coalesce list.  Calculate hash for PAIR.   */
-
-static unsigned int
-coalesce_pair_map_hash (const void *pair)
-{
-  hashval_t a = (hashval_t)(((const_coalesce_pair_p)pair)->first_element);
-  hashval_t b = (hashval_t)(((const_coalesce_pair_p)pair)->second_element);
-
-  return COALESCE_HASH_FN (a,b);
-}
-
-
-/* Equality function for coalesce list hash table.  Compare PAIR1 and PAIR2,
-   returning TRUE if the two pairs are equivalent.  */
-
-static int
-coalesce_pair_map_eq (const void *pair1, const void *pair2)
-{
-  const_coalesce_pair_p const p1 = (const_coalesce_pair_p) pair1;
-  const_coalesce_pair_p const p2 = (const_coalesce_pair_p) pair2;
-
-  return (p1->first_element == p2->first_element
-	  && p1->second_element == p2->second_element);
-}
-
-
 /* Create a new empty coalesce list object and return it.  */

 static inline coalesce_list_p
@@ -225,8 +232,7 @@  create_coalesce_list (void)
     size = 40;

   list = (coalesce_list_p) xmalloc (sizeof (struct coalesce_list_d));
-  list->list = htab_create (size, coalesce_pair_map_hash,
-  			    coalesce_pair_map_eq, NULL);
+  list->list.create (size);
   list->sorted = NULL;
   list->num_sorted = 0;
   list->cost_one_list = NULL;
@@ -240,7 +246,7 @@  static inline void
 delete_coalesce_list (coalesce_list_p cl)
 {
   gcc_assert (cl->cost_one_list == NULL);
-  htab_delete (cl->list);
+  cl->list.dispose ();
   free (cl->sorted);
   gcc_assert (cl->num_sorted == 0);
   free (cl);
@@ -255,7 +261,7 @@  static coalesce_pair_p
 find_coalesce_pair (coalesce_list_p cl, int p1, int p2, bool create)
 {
   struct coalesce_pair p;
-  void **slot;
+  coalesce_pair **slot;
   unsigned int hash;

   /* Normalize so that p1 is the smaller value.  */
@@ -270,9 +276,8 @@  find_coalesce_pair (coalesce_list_p cl,
       p.second_element = p2;
     }

-  hash = coalesce_pair_map_hash (&p);
-  slot = htab_find_slot_with_hash (cl->list, &p, hash,
-				   create ? INSERT : NO_INSERT);
+  hash = coalesce_pair_hasher::hash (&p);
+  slot = cl->list.find_slot_with_hash (&p, hash, create ? INSERT : NO_INSERT);
   if (!slot)
     return NULL;

@@ -283,7 +288,7 @@  find_coalesce_pair (coalesce_list_p cl,
       pair->first_element = p.first_element;
       pair->second_element = p.second_element;
       pair->cost = 0;
-      *slot = (void *)pair;
+      *slot = pair;
     }

   return (struct coalesce_pair *) *slot;
@@ -355,56 +360,14 @@  compare_pairs (const void *p1, const voi
 static inline int
 num_coalesce_pairs (coalesce_list_p cl)
 {
-  return htab_elements (cl->list);
-}
-
-
-/* Iterator over hash table pairs.  */
-typedef struct
-{
-  htab_iterator hti;
-} coalesce_pair_iterator;
-
-
-/* Return first partition pair from list CL, initializing iterator ITER.  */
-
-static inline coalesce_pair_p
-first_coalesce_pair (coalesce_list_p cl, coalesce_pair_iterator *iter)
-{
-  coalesce_pair_p pair;
-
-  pair = (coalesce_pair_p) first_htab_element (&(iter->hti), cl->list);
-  return pair;
-}
-
-
-/* Return TRUE if there are no more partitions in for ITER to process.  */
-
-static inline bool
-end_coalesce_pair_p (coalesce_pair_iterator *iter)
-{
-  return end_htab_p (&(iter->hti));
-}
-
-
-/* Return the next partition pair to be visited by ITER.  */
-
-static inline coalesce_pair_p
-next_coalesce_pair (coalesce_pair_iterator *iter)
-{
-  coalesce_pair_p pair;
-
-  pair = (coalesce_pair_p) next_htab_element (&(iter->hti));
-  return pair;
+  return cl->list.elements ();
 }


 /* Iterate over CL using ITER, returning values in PAIR.  */

 #define FOR_EACH_PARTITION_PAIR(PAIR, ITER, CL)		\
-  for ((PAIR) = first_coalesce_pair ((CL), &(ITER));	\
-       !end_coalesce_pair_p (&(ITER));			\
-       (PAIR) = next_coalesce_pair (&(ITER)))
+  FOR_EACH_HASH_TABLE_ELEMENT ((CL)->list, (PAIR), coalesce_pair_p, (ITER))


 /* Prepare CL for removal of preferred pairs.  When finished they are sorted
@@ -415,7 +378,7 @@  sort_coalesce_list (coalesce_list_p cl)
 {
   unsigned x, num;
   coalesce_pair_p p;
-  coalesce_pair_iterator ppi;
+  coalesce_iterator_type ppi;

   gcc_assert (cl->sorted == NULL);

@@ -461,7 +424,8 @@  static void
 dump_coalesce_list (FILE *f, coalesce_list_p cl)
 {
   coalesce_pair_p node;
-  coalesce_pair_iterator ppi;
+  coalesce_iterator_type ppi;
+
   int x;
   tree var;

Index: gcc/tree-vect-loop.c
===================================================================
--- gcc/tree-vect-loop.c	(revision 198204)
+++ gcc/tree-vect-loop.c	(working copy)
@@ -879,7 +879,6 @@  new_loop_vec_info (struct loop *loop)
   LOOP_VINFO_REDUCTION_CHAINS (res).create (10);
   LOOP_VINFO_SLP_INSTANCES (res).create (10);
   LOOP_VINFO_SLP_UNROLLING_FACTOR (res) = 1;
-  LOOP_VINFO_PEELING_HTAB (res) = NULL;
   LOOP_VINFO_TARGET_COST_DATA (res) = init_cost (loop);
   LOOP_VINFO_PEELING_FOR_GAPS (res) = false;
   LOOP_VINFO_OPERANDS_SWAPPED (res) = false;
@@ -960,8 +959,8 @@  destroy_loop_vec_info (loop_vec_info loo
   LOOP_VINFO_REDUCTIONS (loop_vinfo).release ();
   LOOP_VINFO_REDUCTION_CHAINS (loop_vinfo).release ();

-  if (LOOP_VINFO_PEELING_HTAB (loop_vinfo))
-    htab_delete (LOOP_VINFO_PEELING_HTAB (loop_vinfo));
+  if (LOOP_VINFO_PEELING_HTAB (loop_vinfo).is_created ())
+    LOOP_VINFO_PEELING_HTAB (loop_vinfo).dispose ();

   destroy_cost_data (LOOP_VINFO_TARGET_COST_DATA (loop_vinfo));

Index: gcc/tree-ssa-structalias.c
===================================================================
--- gcc/tree-ssa-structalias.c	(revision 198204)
+++ gcc/tree-ssa-structalias.c	(working copy)
@@ -32,7 +32,7 @@ 
 #include "tree-inline.h"
 #include "diagnostic-core.h"
 #include "gimple.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "function.h"
 #include "cgraph.h"
 #include "tree-pass.h"
@@ -1862,48 +1862,54 @@  typedef struct equiv_class_label
 } *equiv_class_label_t;
 typedef const struct equiv_class_label *const_equiv_class_label_t;

-/* A hashtable for mapping a bitmap of labels->pointer equivalence
-   classes.  */
-static htab_t pointer_equiv_class_table;
+/* Equiv_class_label hashtable helpers.  */

-/* A hashtable for mapping a bitmap of labels->location equivalence
-   classes.  */
-static htab_t location_equiv_class_table;
+struct equiv_class_hasher : typed_free_remove <equiv_class_label>
+{
+  typedef equiv_class_label value_type;
+  typedef equiv_class_label compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};

 /* Hash function for a equiv_class_label_t */

-static hashval_t
-equiv_class_label_hash (const void *p)
+inline hashval_t
+equiv_class_hasher::hash (const value_type *ecl)
 {
-  const_equiv_class_label_t const ecl = (const_equiv_class_label_t) p;
   return ecl->hashcode;
 }

 /* Equality function for two equiv_class_label_t's.  */

-static int
-equiv_class_label_eq (const void *p1, const void *p2)
+inline bool
+equiv_class_hasher::equal (const value_type *eql1, const compare_type *eql2)
 {
-  const_equiv_class_label_t const eql1 = (const_equiv_class_label_t) p1;
-  const_equiv_class_label_t const eql2 = (const_equiv_class_label_t) p2;
   return (eql1->hashcode == eql2->hashcode
 	  && bitmap_equal_p (eql1->labels, eql2->labels));
 }

+/* A hashtable for mapping a bitmap of labels->pointer equivalence
+   classes.  */
+static hash_table <equiv_class_hasher> pointer_equiv_class_table;
+
+/* A hashtable for mapping a bitmap of labels->location equivalence
+   classes.  */
+static hash_table <equiv_class_hasher> location_equiv_class_table;
+
 /* Lookup a equivalence class in TABLE by the bitmap of LABELS with
    hash HAS it contains.  Sets *REF_LABELS to the bitmap LABELS
    is equivalent to.  */

 static equiv_class_label *
-equiv_class_lookup_or_add (htab_t table, bitmap labels)
+equiv_class_lookup_or_add (hash_table <equiv_class_hasher> table,
bitmap labels)
 {
   equiv_class_label **slot;
   equiv_class_label ecl;

   ecl.labels = labels;
   ecl.hashcode = bitmap_hash (labels);
-  slot = (equiv_class_label **) htab_find_slot_with_hash (table, &ecl,
-							  ecl.hashcode, INSERT);
+  slot = table.find_slot_with_hash (&ecl, ecl.hashcode, INSERT);
   if (!*slot)
     {
       *slot = XNEW (struct equiv_class_label);
@@ -2222,10 +2228,8 @@  perform_var_substitution (constraint_gra
   struct scc_info *si = init_scc_info (size);

   bitmap_obstack_initialize (&iteration_obstack);
-  pointer_equiv_class_table = htab_create (511, equiv_class_label_hash,
-					   equiv_class_label_eq, free);
-  location_equiv_class_table = htab_create (511, equiv_class_label_hash,
-					    equiv_class_label_eq, free);
+  pointer_equiv_class_table.create (511);
+  location_equiv_class_table.create (511);
   pointer_equiv_class = 1;
   location_equiv_class = 1;

@@ -2358,8 +2362,8 @@  free_var_substitution_info (struct scc_i
   free (graph->points_to);
   free (graph->eq_rep);
   sbitmap_free (graph->direct_nodes);
-  htab_delete (pointer_equiv_class_table);
-  htab_delete (location_equiv_class_table);
+  pointer_equiv_class_table.dispose ();
+  location_equiv_class_table.dispose ();
   bitmap_obstack_release (&iteration_obstack);
 }

@@ -5900,45 +5904,54 @@  typedef struct shared_bitmap_info
 } *shared_bitmap_info_t;
 typedef const struct shared_bitmap_info *const_shared_bitmap_info_t;

-static htab_t shared_bitmap_table;
+/* Shared_bitmap hashtable helpers.  */
+
+struct shared_bitmap_hasher : typed_free_remove <shared_bitmap_info>
+{
+  typedef shared_bitmap_info value_type;
+  typedef shared_bitmap_info compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};

 /* Hash function for a shared_bitmap_info_t */

-static hashval_t
-shared_bitmap_hash (const void *p)
+inline hashval_t
+shared_bitmap_hasher::hash (const value_type *bi)
 {
-  const_shared_bitmap_info_t const bi = (const_shared_bitmap_info_t) p;
   return bi->hashcode;
 }

 /* Equality function for two shared_bitmap_info_t's. */

-static int
-shared_bitmap_eq (const void *p1, const void *p2)
+inline bool
+shared_bitmap_hasher::equal (const value_type *sbi1, const compare_type *sbi2)
 {
-  const_shared_bitmap_info_t const sbi1 = (const_shared_bitmap_info_t) p1;
-  const_shared_bitmap_info_t const sbi2 = (const_shared_bitmap_info_t) p2;
   return bitmap_equal_p (sbi1->pt_vars, sbi2->pt_vars);
 }

+/* Shared_bitmap hashtable.  */
+
+static hash_table <shared_bitmap_hasher> shared_bitmap_table;
+
 /* Lookup a bitmap in the shared bitmap hashtable, and return an already
    existing instance if there is one, NULL otherwise.  */

 static bitmap
 shared_bitmap_lookup (bitmap pt_vars)
 {
-  void **slot;
+  shared_bitmap_info **slot;
   struct shared_bitmap_info sbi;

   sbi.pt_vars = pt_vars;
   sbi.hashcode = bitmap_hash (pt_vars);

-  slot = htab_find_slot_with_hash (shared_bitmap_table, &sbi,
-				   sbi.hashcode, NO_INSERT);
+  slot = shared_bitmap_table.find_slot_with_hash (&sbi, sbi.hashcode,
+						  NO_INSERT);
   if (!slot)
     return NULL;
   else
-    return ((shared_bitmap_info_t) *slot)->pt_vars;
+    return (*slot)->pt_vars;
 }


@@ -5947,16 +5960,15 @@  shared_bitmap_lookup (bitmap pt_vars)
 static void
 shared_bitmap_add (bitmap pt_vars)
 {
-  void **slot;
+  shared_bitmap_info **slot;
   shared_bitmap_info_t sbi = XNEW (struct shared_bitmap_info);

   sbi->pt_vars = pt_vars;
   sbi->hashcode = bitmap_hash (pt_vars);

-  slot = htab_find_slot_with_hash (shared_bitmap_table, sbi,
-				   sbi->hashcode, INSERT);
+  slot = shared_bitmap_table.find_slot_with_hash (sbi, sbi->hashcode, INSERT);
   gcc_assert (!*slot);
-  *slot = (void *) sbi;
+  *slot = sbi;
 }


@@ -6612,8 +6624,7 @@  init_alias_vars (void)
   call_stmt_vars = pointer_map_create ();

   memset (&stats, 0, sizeof (stats));
-  shared_bitmap_table = htab_create (511, shared_bitmap_hash,
-				     shared_bitmap_eq, free);
+  shared_bitmap_table.create (511);
   init_base_vars ();

   gcc_obstack_init (&fake_var_decl_obstack);
@@ -6869,7 +6880,7 @@  delete_points_to_sets (void)
 {
   unsigned int i;

-  htab_delete (shared_bitmap_table);
+  shared_bitmap_table.dispose ();
   if (dump_file && (dump_flags & TDF_STATS))
     fprintf (dump_file, "Points to sets created:%d\n",
 	     stats.points_to_sets_created);
Index: gcc/tree-vect-data-refs.c
===================================================================
--- gcc/tree-vect-data-refs.c	(revision 198204)
+++ gcc/tree-vect-data-refs.c	(working copy)
@@ -1062,27 +1062,6 @@  vect_get_data_access_cost (struct data_r
 }


-static hashval_t
-vect_peeling_hash (const void *elem)
-{
-  const struct _vect_peel_info *peel_info;
-
-  peel_info = (const struct _vect_peel_info *) elem;
-  return (hashval_t) peel_info->npeel;
-}
-
-
-static int
-vect_peeling_hash_eq (const void *elem1, const void *elem2)
-{
-  const struct _vect_peel_info *a, *b;
-
-  a = (const struct _vect_peel_info *) elem1;
-  b = (const struct _vect_peel_info *) elem2;
-  return (a->npeel == b->npeel);
-}
-
-
 /* Insert DR into peeling hash table with NPEEL as key.  */

 static void
@@ -1090,12 +1069,11 @@  vect_peeling_hash_insert (loop_vec_info
                           int npeel)
 {
   struct _vect_peel_info elem, *slot;
-  void **new_slot;
+  _vect_peel_info **new_slot;
   bool supportable_dr_alignment = vect_supportable_dr_alignment (dr, true);

   elem.npeel = npeel;
-  slot = (vect_peel_info) htab_find (LOOP_VINFO_PEELING_HTAB (loop_vinfo),
-                                     &elem);
+  slot = LOOP_VINFO_PEELING_HTAB (loop_vinfo).find (&elem);
   if (slot)
     slot->count++;
   else
@@ -1104,8 +1082,7 @@  vect_peeling_hash_insert (loop_vec_info
       slot->npeel = npeel;
       slot->dr = dr;
       slot->count = 1;
-      new_slot = htab_find_slot (LOOP_VINFO_PEELING_HTAB (loop_vinfo), slot,
-                                 INSERT);
+      new_slot = LOOP_VINFO_PEELING_HTAB (loop_vinfo).find_slot (slot, INSERT);
       *new_slot = slot;
     }

@@ -1117,11 +1094,11 @@  vect_peeling_hash_insert (loop_vec_info
 /* Traverse peeling hash table to find peeling option that aligns maximum
    number of data accesses.  */

-static int
-vect_peeling_hash_get_most_frequent (void **slot, void *data)
+int
+vect_peeling_hash_get_most_frequent (_vect_peel_info **slot,
+				     _vect_peel_extended_info *max)
 {
-  vect_peel_info elem = (vect_peel_info) *slot;
-  vect_peel_extended_info max = (vect_peel_extended_info) data;
+  vect_peel_info elem = *slot;

   if (elem->count > max->peel_info.count
       || (elem->count == max->peel_info.count
@@ -1139,11 +1116,11 @@  vect_peeling_hash_get_most_frequent (voi
 /* Traverse peeling hash table and calculate cost for each peeling option.
    Find the one with the lowest cost.  */

-static int
-vect_peeling_hash_get_lowest_cost (void **slot, void *data)
+int
+vect_peeling_hash_get_lowest_cost (_vect_peel_info **slot,
+				   _vect_peel_extended_info *min)
 {
-  vect_peel_info elem = (vect_peel_info) *slot;
-  vect_peel_extended_info min = (vect_peel_extended_info) data;
+  vect_peel_info elem = *slot;
   int save_misalignment, dummy;
   unsigned int inside_cost = 0, outside_cost = 0, i;
   gimple stmt = DR_STMT (elem->dr);
@@ -1223,14 +1200,16 @@  vect_peeling_hash_choose_best_peeling (l
      {
        res.inside_cost = INT_MAX;
        res.outside_cost = INT_MAX;
-       htab_traverse (LOOP_VINFO_PEELING_HTAB (loop_vinfo),
-                      vect_peeling_hash_get_lowest_cost, &res);
+       LOOP_VINFO_PEELING_HTAB (loop_vinfo)
+           .traverse <_vect_peel_extended_info *,
+                      vect_peeling_hash_get_lowest_cost> (&res);
      }
    else
      {
        res.peel_info.count = 0;
-       htab_traverse (LOOP_VINFO_PEELING_HTAB (loop_vinfo),
-                      vect_peeling_hash_get_most_frequent, &res);
+       LOOP_VINFO_PEELING_HTAB (loop_vinfo)
+           .traverse <_vect_peel_extended_info *,
+                      vect_peeling_hash_get_most_frequent> (&res);
      }

    *npeel = res.peel_info.npeel;
@@ -1423,10 +1402,8 @@  vect_enhance_data_refs_alignment (loop_v
 						    size_zero_node) < 0;

               /* Save info about DR in the hash table.  */
-              if (!LOOP_VINFO_PEELING_HTAB (loop_vinfo))
-                LOOP_VINFO_PEELING_HTAB (loop_vinfo) =
-                           htab_create (1, vect_peeling_hash,
-                                        vect_peeling_hash_eq, free);
+              if (!LOOP_VINFO_PEELING_HTAB (loop_vinfo).is_created ())
+                LOOP_VINFO_PEELING_HTAB (loop_vinfo).create (1);

               vectype = STMT_VINFO_VECTYPE (stmt_info);
               nelements = TYPE_VECTOR_SUBPARTS (vectype);
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 198204)
+++ gcc/Makefile.in	(working copy)
@@ -966,7 +966,8 @@  GIMPLE_STREAMER_H = gimple-streamer.h $(
 TREE_STREAMER_H = tree-streamer.h $(TREE_H) $(LTO_STREAMER_H) \
 		  $(STREAMER_HOOKS_H)
 STREAMER_HOOKS_H = streamer-hooks.h $(TREE_H)
-TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H) $(TARGET_H)
+TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H) $(TARGET_H) \
+	$(HASH_TABLE_H)
 IPA_PROP_H = ipa-prop.h $(TREE_H) $(VEC_H) $(CGRAPH_H) $(GIMPLE_H) alloc-pool.h
 IPA_INLINE_H = ipa-inline.h $(IPA_PROP_H)
 GSTAB_H = gstab.h stab.def
@@ -2255,7 +2256,7 @@  tree-ssa-structalias.o: tree-ssa-structa
    $(SYSTEM_H) $(CONFIG_H) coretypes.h $(TM_H) $(GGC_H) $(OBSTACK_H)
$(BITMAP_H) \
    $(FLAGS_H) $(TM_P_H) $(BASIC_BLOCK_H) \
    $(DIAGNOSTIC_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) \
-   $(GIMPLE_H) $(HASHTAB_H) $(FUNCTION_H) $(CGRAPH_H) \
+   $(GIMPLE_H) $(HASH_TABLE_H) $(FUNCTION_H) $(CGRAPH_H) \
    $(TREE_PASS_H) alloc-pool.h $(SPLAY_TREE_H) $(PARAMS_H) \
    $(CGRAPH_H) $(ALIAS_H) pointer-set.h
 tree-ssa-uninit.o : tree-ssa-uninit.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
@@ -2275,7 +2276,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) \
@@ -2374,7 +2375,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) \
@@ -2509,7 +2510,7 @@  tree-ssa-alias.o : tree-ssa-alias.c $(TR
    pointer-set.h alloc-pool.h \
    $(TREE_PRETTY_PRINT_H)
 tree-ssa-reassoc.o : tree-ssa-reassoc.c $(TREE_FLOW_H) $(CONFIG_H) \
-   $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) \
+   $(SYSTEM_H) $(HASH_TABLE_H) $(TREE_H) $(DIAGNOSTIC_H) \
    $(TM_H) coretypes.h $(TREE_PASS_H) $(FLAGS_H) \
    tree-iterator.h $(BASIC_BLOCK_H) $(GIMPLE_H) $(TREE_INLINE_H) \
    $(VEC_H) langhooks.h alloc-pool.h pointer-set.h $(CFGLOOP_H) \
@@ -2765,7 +2766,7 @@  function.o : function.c $(CONFIG_H) $(SY
    $(TREE_PASS_H) $(DF_H) $(PARAMS_H) bb-reorder.h \
    $(COMMON_TARGET_H)
 statistics.o : statistics.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-   $(TREE_PASS_H) $(TREE_DUMP_H) $(HASHTAB_H) statistics.h $(FUNCTION_H)
+   $(TREE_PASS_H) $(TREE_DUMP_H) $(HASH_TABLE_H) statistics.h $(FUNCTION_H)
 stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) $(TM_H) \
    $(RTL_H) \
    $(TREE_H) $(FLAGS_H) $(FUNCTION_H) insn-config.h hard-reg-set.h $(EXPR_H) \
Index: gcc/hash-table.h
===================================================================
--- gcc/hash-table.h	(revision 198204)
+++ gcc/hash-table.h	(working copy)
@@ -155,6 +155,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);
+
 */


@@ -368,6 +409,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;

@@ -379,19 +434,19 @@  public:
   void create (size_t initial_slots);
   bool is_created ();
   void dispose ();
-  value_type *find (const compare_type *comparable);
+  value_type *find (const value_type *value);
   value_type *find_with_hash (const compare_type *comparable, hashval_t hash);
-  value_type **find_slot (const compare_type *comparable,
-			  enum insert_option insert);
+  value_type **find_slot (const value_type *value, enum insert_option insert);
   value_type **find_slot_with_hash (const compare_type *comparable,
 				    hashval_t hash, enum insert_option insert);
   void empty ();
   void clear_slot (value_type **slot);
-  void remove_elt (const compare_type *comparable);
+  void remove_elt (const value_type *value);
   void remove_elt_with_hash (const compare_type *comparable, hashval_t hash);
-  size_t size();
-  size_t elements();
-  double collisions();
+  size_t size ();
+  size_t elements ();
+  size_t elements_with_deleted ();
+  double collisions ();

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


@@ -430,9 +488,9 @@  hash_table <Descriptor, Allocator>::is_c
 template <typename Descriptor,
 	  template <typename Type> class Allocator>
 inline typename Descriptor::value_type *
-hash_table <Descriptor, Allocator>::find (const compare_type *comparable)
+hash_table <Descriptor, Allocator>::find (const value_type *value)
 {
-  return find_with_hash (comparable, Descriptor::hash (comparable));
+  return find_with_hash (value, Descriptor::hash (value));
 }


@@ -442,9 +500,9 @@  template <typename Descriptor,
 	  template <typename Type> class Allocator>
 inline typename Descriptor::value_type **
 hash_table <Descriptor, Allocator>
-::find_slot (const compare_type *comparable, enum insert_option insert)
+::find_slot (const value_type *value, enum insert_option insert)
 {
-  return find_slot_with_hash (comparable, Descriptor::hash
(comparable), insert);
+  return find_slot_with_hash (value, Descriptor::hash (value), insert);
 }


@@ -453,9 +511,9 @@  hash_table <Descriptor, Allocator>
 template <typename Descriptor,
 	  template <typename Type> class Allocator>
 inline void
-hash_table <Descriptor, Allocator>::remove_elt (const compare_type *comparable)
+hash_table <Descriptor, Allocator>::remove_elt (const value_type *value)
 {
-  remove_elt_with_hash (comparable, Descriptor::hash (comparable));
+  remove_elt_with_hash (value, Descriptor::hash (value));
 }


@@ -475,12 +533,23 @@  hash_table <Descriptor, Allocator>::size
 template <typename Descriptor,
 	  template <typename Type> class Allocator>
 inline size_t
-hash_table <Descriptor, Allocator>::elements()
+hash_table <Descriptor, Allocator>::elements ()
 {
   return htab->n_elements - htab->n_deleted;
 }


+/* Return the current number of elements in this hash table. */
+
+template <typename Descriptor,
+	  template <typename Type> class Allocator>
+inline size_t
+hash_table <Descriptor, Allocator>::elements_with_deleted ()
+{
+  return htab->n_elements;
+}
+
+
   /* Return the fraction of fixed collisions during all work with given
      hash table. */

@@ -881,4 +950,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 */
Index: gcc/tree-vectorizer.h
===================================================================
--- gcc/tree-vectorizer.h	(revision 198204)
+++ gcc/tree-vectorizer.h	(working copy)
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.

 #include "tree-data-ref.h"
 #include "target.h"
+#include "hash-table.h"

 typedef source_location LOC;
 #define UNKNOWN_LOC UNKNOWN_LOCATION
@@ -189,6 +190,30 @@  typedef struct _vect_peel_extended_info
   stmt_vector_for_cost body_cost_vec;
 } *vect_peel_extended_info;

+
+/* Peeling hashtable helpers.  */
+
+struct peel_info_hasher : typed_free_remove <_vect_peel_info>
+{
+  typedef _vect_peel_info value_type;
+  typedef _vect_peel_info compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+peel_info_hasher::hash (const value_type *peel_info)
+{
+  return (hashval_t) peel_info->npeel;
+}
+
+inline bool
+peel_info_hasher::equal (const value_type *a, const compare_type *b)
+{
+  return (a->npeel == b->npeel);
+}
+
+
 /*-----------------------------------------------------------------*/
 /* Info on vectorized loops.                                       */
 /*-----------------------------------------------------------------*/
@@ -273,7 +298,7 @@  typedef struct _loop_vec_info {
   vec<gimple> reduction_chains;

   /* Hash table used to choose the best peeling option.  */
-  htab_t peeling_htab;
+  hash_table <peel_info_hasher> peeling_htab;

   /* Cost data used by the target cost model.  */
   void *target_cost_data;