Patchwork [cxx-conversion] Convert various htab_t tables to hash_table

login
register
mail settings
Submitter Lawrence Crowl
Date Dec. 11, 2012, 10:46 p.m.
Message ID <CAGqM8fYW7d3nXUA6AssLweN9wYE6D8A_YpCeh-S1+1CDqt7Ajw@mail.gmail.com>
Download mbox | patch
Permalink /patch/205328/
State New
Headers show

Comments

Lawrence Crowl - Dec. 11, 2012, 10:46 p.m.
Update various htab_t tables to hash_table.  Each file is independent.
Update dependent calls and types.

* tree-ssa-strlen.c'decl_to_stridxlist_htab

Fold decl_to_stridxlist_hash into new struct stridxlist_hasher.

* tree-ssa-loop-ivopts.c'ivopts_data::inv_expr_tab

Fold htab_inv_expr_hash and htab_inv_expr_eq into new struct
iv_inv_expr_hasher.

* tree-ssa-uncprop.c'equiv

Equiv renamed to val_ssa_equiv because of name ambiguity with local variables.

Fold equiv_hash, equiv_eq and equiv_free into new struct val_ssa_equiv_hasher.

Renamed variables equiv_hash_elt to an_equiv_elt because of name ambiguity
with struct type.  Changed equiv_hash_elt_p to an_equiv_elt_p to match.

* tree-ssa-phiopt.c'seen_ssa_names

Fold name_to_bb_hash and name_to_bb_eq into new struct ssa_names_hasher.

* tree-ssa-structalias.c'pointer_equiv_class_table
* tree-ssa-structalias.c'location_equiv_class_table

Fold equiv_class_label_hash and equiv_class_label_eq into new
struct equiv_class_hasher.

* tree-ssa-structalias.c'shared_bitmap_table

Fold shared_bitmap_hash and shared_bitmap_eq into new struct
shared_bitmap_hasher.

* tree-ssa-live.c'var_map_base_init::tree_to_index

New struct tree_int_map_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.

Okay for branch?
Diego Novillo - Dec. 12, 2012, 2:28 p.m.
On Tue, Dec 11, 2012 at 5:46 PM, Lawrence Crowl <crowl@googlers.com> wrote:
> Update various htab_t tables to hash_table.  Each file is independent.
> Update dependent calls and types.
>
> * tree-ssa-strlen.c'decl_to_stridxlist_htab
>
> Fold decl_to_stridxlist_hash into new struct stridxlist_hasher.
>
> * tree-ssa-loop-ivopts.c'ivopts_data::inv_expr_tab
>
> Fold htab_inv_expr_hash and htab_inv_expr_eq into new struct
> iv_inv_expr_hasher.
>
> * tree-ssa-uncprop.c'equiv
>
> Equiv renamed to val_ssa_equiv because of name ambiguity with local variables.
>
> Fold equiv_hash, equiv_eq and equiv_free into new struct val_ssa_equiv_hasher.
>
> Renamed variables equiv_hash_elt to an_equiv_elt because of name ambiguity
> with struct type.  Changed equiv_hash_elt_p to an_equiv_elt_p to match.
>
> * tree-ssa-phiopt.c'seen_ssa_names
>
> Fold name_to_bb_hash and name_to_bb_eq into new struct ssa_names_hasher.
>
> * tree-ssa-structalias.c'pointer_equiv_class_table
> * tree-ssa-structalias.c'location_equiv_class_table
>
> Fold equiv_class_label_hash and equiv_class_label_eq into new
> struct equiv_class_hasher.
>
> * tree-ssa-structalias.c'shared_bitmap_table
>
> Fold shared_bitmap_hash and shared_bitmap_eq into new struct
> shared_bitmap_hasher.
>
> * tree-ssa-live.c'var_map_base_init::tree_to_index
>
> New struct tree_int_map_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.
>
> Okay for branch?


OK.


Diego.

Patch

Index: gcc/tree-ssa-phiopt.c
===================================================================
--- gcc/tree-ssa-phiopt.c	(revision 194381)
+++ gcc/tree-ssa-phiopt.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 "ggc.h"
 #include "tree.h"
@@ -1239,34 +1240,42 @@  struct name_to_bb
   basic_block bb;
 };

-/* The hash table for remembering what we've seen.  */
-static htab_t seen_ssa_names;
+/* Hashtable helpers.  */

-/* The set of MEM_REFs which can't trap.  */
-static struct pointer_set_t *nontrap_set;
+struct ssa_names_hasher : typed_free_remove <name_to_bb>
+{
+  typedef name_to_bb value_type;
+  typedef name_to_bb compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};

 /* The hash function.  */
-static hashval_t
-name_to_bb_hash (const void *p)
+
+inline hashval_t
+ssa_names_hasher::hash (const value_type *n)
 {
-  const struct name_to_bb *n = (const struct name_to_bb *) p;
   return n->ssa_name_ver ^ (((hashval_t) n->store) << 31)
          ^ (n->offset << 6) ^ (n->size << 3);
 }

 /* The equality function of *P1 and *P2.  */
-static int
-name_to_bb_eq (const void *p1, const void *p2)
-{
-  const struct name_to_bb *n1 = (const struct name_to_bb *)p1;
-  const struct name_to_bb *n2 = (const struct name_to_bb *)p2;

+inline bool
+ssa_names_hasher::equal (const value_type *n1, const compare_type *n2)
+{
   return n1->ssa_name_ver == n2->ssa_name_ver
          && n1->store == n2->store
          && n1->offset == n2->offset
          && n1->size == n2->size;
 }

+/* The hash table for remembering what we've seen.  */
+static hash_table <ssa_names_hasher> seen_ssa_names;
+
+/* The set of MEM_REFs which can't trap.  */
+static struct pointer_set_t *nontrap_set;
+
 /* We see the expression EXP in basic block BB.  If it's an interesting
    expression (an MEM_REF through an SSA_NAME) possibly insert the
    expression into the set NONTRAP or the hash table of seen expressions.
@@ -1285,7 +1294,7 @@  add_or_mark_expr (basic_block bb, tree e
     {
       tree name = TREE_OPERAND (exp, 0);
       struct name_to_bb map;
-      void **slot;
+      name_to_bb **slot;
       struct name_to_bb *n2bb;
       basic_block found_bb = 0;

@@ -1297,8 +1306,8 @@  add_or_mark_expr (basic_block bb, tree e
       map.offset = tree_low_cst (TREE_OPERAND (exp, 1), 0);
       map.size = size;

-      slot = htab_find_slot (seen_ssa_names, &map, INSERT);
-      n2bb = (struct name_to_bb *) *slot;
+      slot = seen_ssa_names.find_slot (&map, INSERT);
+      n2bb = *slot;
       if (n2bb)
         found_bb = n2bb->bb;

@@ -1370,8 +1379,7 @@  get_non_trapping (void)
   struct dom_walk_data walk_data;

   nontrap = pointer_set_create ();
-  seen_ssa_names = htab_create (128, name_to_bb_hash, name_to_bb_eq,
-				free);
+  seen_ssa_names.create (128);
   /* We're going to do a dominator walk, so ensure that we have
      dominance information.  */
   calculate_dominance_info (CDI_DOMINATORS);
@@ -1388,7 +1396,7 @@  get_non_trapping (void)
   init_walk_dominator_tree (&walk_data);
   walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
   fini_walk_dominator_tree (&walk_data);
-  htab_delete (seen_ssa_names);
+  seen_ssa_names.dispose ();

   return nontrap;
 }
Index: gcc/tree-ssa-reassoc.c
===================================================================
--- gcc/tree-ssa-reassoc.c	(revision 194381)
+++ gcc/tree-ssa-reassoc.c	(working copy)
@@ -22,6 +22,7 @@  along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "tm.h"
 #include "tree.h"
 #include "basic-block.h"
@@ -944,10 +945,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;
@@ -955,8 +969,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];
@@ -1259,7 +1273,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;

@@ -1307,7 +1321,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;
@@ -1334,7 +1348,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;
@@ -1346,7 +1360,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 194381)
+++ gcc/tree-ssa-loop-im.c	(working copy)
@@ -32,7 +32,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"
@@ -146,6 +146,32 @@  typedef struct mem_ref
 } *mem_ref_p;


+/* 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, obj2, 0);
+}


 /* Description of memory accesses in loops.  */
@@ -153,7 +179,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;
@@ -667,7 +693,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;
@@ -1431,27 +1457,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, (const_tree) obj2, 0);
-}
-
 /* Releases list of memory reference locations ACCS.  */

 static void
@@ -1563,7 +1568,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;
@@ -1589,7 +1594,7 @@  gather_mem_refs_stmt (struct loop *loop,
     }

   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)
     {
@@ -1704,7 +1709,7 @@  analyze_memory_references (void)
   unsigned i;
   bitmap empty;

-  memory_accesses.refs = htab_create (100, memref_hash, memref_eq, NULL);
+  memory_accesses.refs.create (100);
   memory_accesses.refs_list.create (0);
   memory_accesses.refs_in_loop.create (number_of_loops ());
   memory_accesses.all_refs_in_loop.create (number_of_loops ());
@@ -2600,7 +2605,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-structalias.c
===================================================================
--- gcc/tree-ssa-structalias.c	(revision 194381)
+++ gcc/tree-ssa-structalias.c	(working copy)
@@ -33,7 +33,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"
@@ -1879,52 +1879,58 @@  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 it
    contains.  */

 static unsigned int
-equiv_class_lookup (htab_t table, bitmap labels)
+equiv_class_lookup (hash_table <equiv_class_hasher> table, bitmap labels)
 {
-  void **slot;
+  equiv_class_label **slot;
   struct equiv_class_label ecl;

   ecl.labels = labels;
   ecl.hashcode = bitmap_hash (labels);

-  slot = htab_find_slot_with_hash (table, &ecl,
-				   ecl.hashcode, NO_INSERT);
+  slot = table.find_slot_with_hash (&ecl, ecl.hashcode, NO_INSERT);
   if (!slot)
     return 0;
   else
-    return ((equiv_class_label_t) *slot)->equivalence_class;
+    return (*slot)->equivalence_class;
 }


@@ -1932,20 +1938,19 @@  equiv_class_lookup (htab_t table, bitmap
    to TABLE.  */

 static void
-equiv_class_add (htab_t table, unsigned int equivalence_class,
-		 bitmap labels)
+equiv_class_add (hash_table <equiv_class_hasher> table,
+		 unsigned int equivalence_class, bitmap labels)
 {
-  void **slot;
+  equiv_class_label **slot;
   equiv_class_label_t ecl = XNEW (struct equiv_class_label);

   ecl->labels = labels;
   ecl->equivalence_class = equivalence_class;
   ecl->hashcode = bitmap_hash (labels);

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

 /* Perform offline variable substitution.
@@ -2147,10 +2152,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;

@@ -2255,8 +2258,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);
 }

@@ -5760,45 +5763,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;
 }


@@ -5807,16 +5819,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;
 }


@@ -6462,8 +6473,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);
@@ -6716,7 +6726,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/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 194381)
+++ gcc/Makefile.in	(working copy)
@@ -2243,8 +2243,8 @@  tree-ssa-tail-merge.o: tree-ssa-tail-mer
    $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) $(TREE_DUMP_H) $(HASH_TABLE_H) \
    $(GIMPLE_H) $(FUNCTION_H) tree-ssa-sccvn.h \
    $(CGRAPH_H) $(GIMPLE_PRETTY_PRINT_H) $(PARAMS_H)
-tree-ssa-structalias.o: tree-ssa-structalias.c \
-   $(SYSTEM_H) $(CONFIG_H) coretypes.h $(TM_H) $(GGC_H) $(OBSTACK_H)
$(BITMAP_H) \
+tree-ssa-structalias.o: tree-ssa-structalias.c $(SYSTEM_H) $(CONFIG_H) \
+   coretypes.h $(HASH_TABLE_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) \
@@ -2299,7 +2299,7 @@  tree-ssa-ifcombine.o : tree-ssa-ifcombin
    $(TREE_FLOW_H) $(TREE_PASS_H) $(DIAGNOSTIC_H) \
    $(TREE_PRETTY_PRINT_H)
 tree-ssa-phiopt.o : tree-ssa-phiopt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-   $(TM_H) $(GGC_H) $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) \
+   $(HASH_TABLE_H) $(TM_H) $(GGC_H) $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) \
    $(TREE_FLOW_H) $(TREE_PASS_H) langhooks.h $(FLAGS_H) \
    $(DIAGNOSTIC_H) pointer-set.h domwalk.h $(CFGLOOP_H) \
    $(TREE_DATA_REF_H) $(TREE_PRETTY_PRINT_H) $(GIMPLE_PRETTY_PRINT_H) \
@@ -2326,7 +2326,7 @@  tree-ssa-dom.o : tree-ssa-dom.c $(TREE_F
    tree-ssa-propagate.h $(CFGLOOP_H) $(PARAMS_H) \
    $(GIMPLE_PRETTY_PRINT_H)
 tree-ssa-uncprop.o : tree-ssa-uncprop.c $(TREE_FLOW_H) $(CONFIG_H) \
-   $(SYSTEM_H) $(TREE_H) $(TM_P_H) \
+   $(SYSTEM_H) $(HASH_TABLE_H) $(TREE_H) $(TM_P_H) \
    $(DIAGNOSTIC_H) $(FUNCTION_H) $(TM_H) coretypes.h \
    $(BASIC_BLOCK_H) domwalk.h $(TREE_PASS_H) $(FLAGS_H) \
    tree-ssa-propagate.h
@@ -2349,7 +2349,7 @@  domwalk.o : domwalk.c $(CONFIG_H) $(SYST
    $(BASIC_BLOCK_H) domwalk.h sbitmap.h
 tree-ssa-live.o : tree-ssa-live.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h dumpfile.h $(TIMEVAR_H) \
-   $(TREE_SSA_LIVE_H) $(BITMAP_H) debug.h $(FLAGS_H) \
+   $(TREE_SSA_LIVE_H) $(BITMAP_H) debug.h $(FLAGS_H) $(HASH_TABLE_H) \
    $(GIMPLE_PRETTY_PRINT_H) $(GIMPLE_H)
 tree-ssa-copyrename.o : tree-ssa-copyrename.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) $(FUNCTION_H) \
@@ -2469,7 +2469,7 @@  tree-predcom.o: tree-predcom.c $(CONFIG_
 tree-ssa-loop-ivopts.o : tree-ssa-loop-ivopts.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(EXPR_H) \
    $(DIAGNOSTIC_H) $(TM_H) coretypes.h \
-   $(TREE_PASS_H) $(GGC_H) $(RECOG_H) insn-config.h $(HASHTAB_H) $(SCEV_H) \
+   $(TREE_PASS_H) $(GGC_H) $(RECOG_H) insn-config.h $(HASH_TABLE_H) $(SCEV_H) \
    $(CFGLOOP_H) $(PARAMS_H) langhooks.h $(BASIC_BLOCK_H) \
    tree-affine.h pointer-set.h $(TARGET_H) \
    $(GIMPLE_PRETTY_PRINT_H) tree-ssa-propagate.h
@@ -2483,7 +2483,7 @@  tree-ssa-loop-manip.o : tree-ssa-loop-ma
    $(CFGLOOP_H) $(TREE_PASS_H) \
    $(SCEV_H) $(PARAMS_H) $(TREE_INLINE_H) langhooks.h
 tree-ssa-loop-im.o : tree-ssa-loop-im.c $(TREE_FLOW_H) $(CONFIG_H) \
-   $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) domwalk.h \
+   $(SYSTEM_H) $(HASH_TABLE_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) domwalk.h \
    $(PARAMS_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h \
    $(TREE_PASS_H) $(FLAGS_H) $(BASIC_BLOCK_H) \
    pointer-set.h tree-affine.h tree-ssa-propagate.h $(GIMPLE_PRETTY_PRINT_H)
@@ -2500,7 +2500,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) \
@@ -3032,7 +3032,7 @@  tree-ssa-ccp.o : tree-ssa-ccp.c $(TREE_F
    $(DBGCNT_H) $(GIMPLE_PRETTY_PRINT_H) gimple-fold.h
 tree-ssa-strlen.o : tree-ssa-strlen.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TREE_FLOW_H) $(TREE_PASS_H) domwalk.h alloc-pool.h tree-ssa-propagate.h \
-   $(GIMPLE_PRETTY_PRINT_H) $(PARAMS_H) $(EXPR_H)
+   $(GIMPLE_PRETTY_PRINT_H) $(PARAMS_H) $(EXPR_H) $(HASH_TABLE_H)
 tree-sra.o : tree-sra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h alloc-pool.h \
    $(TM_H) $(TREE_H) $(GIMPLE_H) $(CGRAPH_H) $(TREE_FLOW_H) \
    $(IPA_PROP_H) $(DIAGNOSTIC_H) statistics.h \
Index: gcc/tree-ssa-live.c
===================================================================
--- gcc/tree-ssa-live.c	(revision 194381)
+++ gcc/tree-ssa-live.c	(working copy)
@@ -22,6 +22,7 @@  along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "hash-table.h"
 #include "tm.h"
 #include "tree.h"
 #include "gimple-pretty-print.h"
@@ -54,6 +55,29 @@  static void  verify_live_on_entry (tree_
    ssa_name or variable, and vice versa.  */


+/* Hashtable helpers.  */
+
+struct tree_int_map_hasher : typed_noop_remove <tree_int_map>
+{
+  typedef tree_int_map value_type;
+  typedef tree_int_map compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+inline hashval_t
+tree_int_map_hasher::hash (const value_type *v)
+{
+  return tree_map_base_hash (v);
+}
+
+inline bool
+tree_int_map_hasher::equal (const value_type *v, const compare_type *c)
+{
+  return tree_int_map_eq (v, c);
+}
+
+
 /* This routine will initialize the basevar fields of MAP.  */

 static void
@@ -61,12 +85,11 @@  var_map_base_init (var_map map)
 {
   int x, num_part;
   tree var;
-  htab_t tree_to_index;
+  hash_table <tree_int_map_hasher> tree_to_index;
   struct tree_int_map *m, *mapstorage;

   num_part = num_var_partitions (map);
-  tree_to_index = htab_create (num_part, tree_map_base_hash,
-			       tree_int_map_eq, NULL);
+  tree_to_index.create (num_part);
   /* We can have at most num_part entries in the hash tables, so it's
      enough to allocate so many map elements once, saving some malloc
      calls.  */
@@ -92,8 +115,7 @@  var_map_base_init (var_map map)
 	   underlying decl.  */
 	m->base.from = TREE_TYPE (var);
       /* If base variable hasn't been seen, set it up.  */
-      slot = (struct tree_int_map **) htab_find_slot (tree_to_index,
-						      m, INSERT);
+      slot = tree_to_index.find_slot (m, INSERT);
       if (!*slot)
 	{
 	  baseindex = m - mapstorage;
@@ -109,7 +131,7 @@  var_map_base_init (var_map map)
   map->num_basevars = m - mapstorage;

   free (mapstorage);
-  htab_delete (tree_to_index);
+  tree_to_index. dispose ();
 }


Index: gcc/tree-ssa-uncprop.c
===================================================================
--- gcc/tree-ssa-uncprop.c	(revision 194381)
+++ gcc/tree-ssa-uncprop.c	(working copy)
@@ -266,11 +266,6 @@  associate_equivalences_with_edges (void)
    subtree rooted at the block where we record the equivalency.  */
 static vec<tree> equiv_stack;

-/* Global hash table implementing a mapping from invariant values
-   to a list of SSA_NAMEs which have the same value.  We might be
-   able to reuse tree-vn for this code.  */
-static htab_t equiv;
-
 /* Main structure for recording equivalences into our hash table.  */
 struct equiv_hash_elt
 {
@@ -281,53 +276,66 @@  struct equiv_hash_elt
   vec<tree> equivalences;
 };

-static void uncprop_enter_block (struct dom_walk_data *, basic_block);
-static void uncprop_leave_block (struct dom_walk_data *, basic_block);
-static void uncprop_into_successor_phis (basic_block);
+/* Value to ssa name equivalence hashtable helpers.  */

-/* Hashing and equality routines for the hash table.  */
+struct val_ssa_equiv_hasher
+{
+  typedef equiv_hash_elt value_type;
+  typedef equiv_hash_elt compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+  static inline void remove (value_type *);
+};

-static hashval_t
-equiv_hash (const void *p)
+inline hashval_t
+val_ssa_equiv_hasher::hash (const value_type *p)
 {
-  tree const value = ((const struct equiv_hash_elt *)p)->value;
+  tree const value = p->value;
   return iterative_hash_expr (value, 0);
 }

-static int
-equiv_eq (const void *p1, const void *p2)
+inline bool
+val_ssa_equiv_hasher::equal (const value_type *p1, const compare_type *p2)
 {
-  tree value1 = ((const struct equiv_hash_elt *)p1)->value;
-  tree value2 = ((const struct equiv_hash_elt *)p2)->value;
+  tree value1 = p1->value;
+  tree value2 = p2->value;

   return operand_equal_p (value1, value2, 0);
 }

 /* Free an instance of equiv_hash_elt.  */

-static void
-equiv_free (void *p)
+inline void
+val_ssa_equiv_hasher::remove (value_type *elt)
 {
-  struct equiv_hash_elt *elt = (struct equiv_hash_elt *) p;
   elt->equivalences.release ();
   free (elt);
 }

+/* Global hash table implementing a mapping from invariant values
+   to a list of SSA_NAMEs which have the same value.  We might be
+   able to reuse tree-vn for this code.  */
+static hash_table <val_ssa_equiv_hasher> val_ssa_equiv;
+
+static void uncprop_enter_block (struct dom_walk_data *, basic_block);
+static void uncprop_leave_block (struct dom_walk_data *, basic_block);
+static void uncprop_into_successor_phis (basic_block);
+
 /* Remove the most recently recorded equivalency for VALUE.  */

 static void
 remove_equivalence (tree value)
 {
-  struct equiv_hash_elt equiv_hash_elt, *equiv_hash_elt_p;
-  void **slot;
+  struct equiv_hash_elt an_equiv_elt, *an_equiv_elt_p;
+  equiv_hash_elt **slot;

-  equiv_hash_elt.value = value;
-  equiv_hash_elt.equivalences.create (0);
+  an_equiv_elt.value = value;
+  an_equiv_elt.equivalences.create (0);

-  slot = htab_find_slot (equiv, &equiv_hash_elt, NO_INSERT);
+  slot = val_ssa_equiv.find_slot (&an_equiv_elt, NO_INSERT);

-  equiv_hash_elt_p = (struct equiv_hash_elt *) *slot;
-  equiv_hash_elt_p->equivalences.pop ();
+  an_equiv_elt_p = *slot;
+  an_equiv_elt_p->equivalences.pop ();
 }

 /* Record EQUIVALENCE = VALUE into our hash table.  */
@@ -335,23 +343,23 @@  remove_equivalence (tree value)
 static void
 record_equiv (tree value, tree equivalence)
 {
-  struct equiv_hash_elt *equiv_hash_elt;
-  void **slot;
+  equiv_hash_elt *an_equiv_elt_p;
+  equiv_hash_elt **slot;

-  equiv_hash_elt = XNEW (struct equiv_hash_elt);
-  equiv_hash_elt->value = value;
-  equiv_hash_elt->equivalences.create (0);
+  an_equiv_elt_p = XNEW (struct equiv_hash_elt);
+  an_equiv_elt_p->value = value;
+  an_equiv_elt_p->equivalences.create (0);

-  slot = htab_find_slot (equiv, equiv_hash_elt, INSERT);
+  slot = val_ssa_equiv.find_slot (an_equiv_elt_p, INSERT);

   if (*slot == NULL)
-    *slot = (void *) equiv_hash_elt;
+    *slot = an_equiv_elt_p;
   else
-     free (equiv_hash_elt);
+     free (an_equiv_elt_p);

-  equiv_hash_elt = (struct equiv_hash_elt *) *slot;
+  an_equiv_elt_p = *slot;

-  equiv_hash_elt->equivalences.safe_push (equivalence);
+  an_equiv_elt_p->equivalences.safe_push (equivalence);
 }

 /* Main driver for un-cprop.  */
@@ -365,7 +373,7 @@  tree_ssa_uncprop (void)
   associate_equivalences_with_edges ();

   /* Create our global data structures.  */
-  equiv = htab_create (1024, equiv_hash, equiv_eq, equiv_free);
+  val_ssa_equiv.create (1024);
   equiv_stack.create (2);

   /* We're going to do a dominator walk, so ensure that we have
@@ -393,7 +401,7 @@  tree_ssa_uncprop (void)
   /* EQUIV_STACK should already be empty at this point, so we just
      need to empty elements out of the hash table, free EQUIV_STACK,
      and cleanup the AUX field on the edges.  */
-  htab_delete (equiv);
+  val_ssa_equiv.dispose ();
   equiv_stack.release ();
   FOR_EACH_BB (bb)
     {
@@ -464,8 +472,8 @@  uncprop_into_successor_phis (basic_block
 	  gimple phi = gsi_stmt (gsi);
 	  tree arg = PHI_ARG_DEF (phi, e->dest_idx);
 	  tree res = PHI_RESULT (phi);
-	  struct equiv_hash_elt equiv_hash_elt;
-	  void **slot;
+	  equiv_hash_elt an_equiv_elt;
+	  equiv_hash_elt **slot;

 	  /* If the argument is not an invariant, and refers to the same
 	     underlying variable as the PHI result, then there's no
@@ -476,13 +484,13 @@  uncprop_into_successor_phis (basic_block
 	    continue;

 	  /* Lookup this argument's value in the hash table.  */
-	  equiv_hash_elt.value = arg;
-	  equiv_hash_elt.equivalences.create (0);
-	  slot = htab_find_slot (equiv, &equiv_hash_elt, NO_INSERT);
+	  an_equiv_elt.value = arg;
+	  an_equiv_elt.equivalences.create (0);
+	  slot = val_ssa_equiv.find_slot (&an_equiv_elt, NO_INSERT);

 	  if (slot)
 	    {
-	      struct equiv_hash_elt *elt = (struct equiv_hash_elt *) *slot;
+	      struct equiv_hash_elt *elt = *slot;
 	      int j;

 	      /* Walk every equivalence with the same value.  If we find
Index: gcc/tree-ssa-strlen.c
===================================================================
--- gcc/tree-ssa-strlen.c	(revision 194381)
+++ gcc/tree-ssa-strlen.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 "tree-flow.h"
 #include "tree-pass.h"
 #include "domwalk.h"
@@ -111,9 +112,33 @@  struct decl_stridxlist_map
   struct stridxlist list;
 };

+/* stridxlist hashtable helpers.  */
+
+struct stridxlist_hasher : typed_noop_remove <decl_stridxlist_map>
+{
+  typedef decl_stridxlist_map value_type;
+  typedef decl_stridxlist_map compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Hash a from tree in a decl_stridxlist_map.  */
+
+inline hashval_t
+stridxlist_hasher::hash (const value_type *item)
+{
+  return DECL_UID (item->base.from);
+}
+
+inline bool
+stridxlist_hasher::equal (const value_type *v, const compare_type *c)
+{
+  return tree_map_base_eq (&v->base, &c->base);
+}
+
 /* Hash table for mapping decls to a chained list of offset -> idx
    mappings.  */
-static htab_t decl_to_stridxlist_htab;
+static hash_table <stridxlist_hasher> decl_to_stridxlist_htab;

 /* Obstack for struct stridxlist and struct decl_stridxlist_map.  */
 static struct obstack stridx_obstack;
@@ -128,14 +153,6 @@  struct laststmt_struct
   int stridx;
 } laststmt;

-/* Hash a from tree in a decl_stridxlist_map.  */
-
-static unsigned int
-decl_to_stridxlist_hash (const void *item)
-{
-  return DECL_UID (((const struct decl_stridxlist_map *) item)->base.from);
-}
-
 /* Helper function for get_stridx.  */

 static int
@@ -146,7 +163,7 @@  get_addr_stridx (tree exp)
   struct stridxlist *list;
   tree base;

-  if (decl_to_stridxlist_htab == NULL)
+  if (!decl_to_stridxlist_htab.is_created ())
     return 0;

   base = get_addr_base_and_unit_offset (exp, &off);
@@ -154,8 +171,7 @@  get_addr_stridx (tree exp)
     return 0;

   ent.base.from = base;
-  e = (struct decl_stridxlist_map *)
-      htab_find_with_hash (decl_to_stridxlist_htab, &ent, DECL_UID (base));
+  e = decl_to_stridxlist_htab.find_with_hash (&ent, DECL_UID (base));
   if (e == NULL)
     return 0;

@@ -234,7 +250,7 @@  unshare_strinfo_vec (void)
 static int *
 addr_stridxptr (tree exp)
 {
-  void **slot;
+  decl_stridxlist_map **slot;
   struct decl_stridxlist_map ent;
   struct stridxlist *list;
   HOST_WIDE_INT off;
@@ -243,19 +259,18 @@  addr_stridxptr (tree exp)
   if (base == NULL_TREE || !DECL_P (base))
     return NULL;

-  if (decl_to_stridxlist_htab == NULL)
+  if (!decl_to_stridxlist_htab.is_created ())
     {
-      decl_to_stridxlist_htab
-	= htab_create (64, decl_to_stridxlist_hash, tree_map_base_eq, NULL);
+      decl_to_stridxlist_htab.create (64);
       gcc_obstack_init (&stridx_obstack);
     }
   ent.base.from = base;
-  slot = htab_find_slot_with_hash (decl_to_stridxlist_htab, &ent,
-				   DECL_UID (base), INSERT);
+  slot = decl_to_stridxlist_htab.find_slot_with_hash (&ent, DECL_UID (base),
+						      INSERT);
   if (*slot)
     {
       int i;
-      list = &((struct decl_stridxlist_map *)*slot)->list;
+      list = &(*slot)->list;
       for (i = 0; i < 16; i++)
 	{
 	  if (list->offset == off)
@@ -273,7 +288,7 @@  addr_stridxptr (tree exp)
       struct decl_stridxlist_map *e
 	= XOBNEW (&stridx_obstack, struct decl_stridxlist_map);
       e->base.from = base;
-      *slot = (void *) e;
+      *slot = e;
       list = &e->list;
     }
   list->next = NULL;
@@ -1987,11 +2002,10 @@  tree_ssa_strlen (void)

   ssa_ver_to_stridx.release ();
   free_alloc_pool (strinfo_pool);
-  if (decl_to_stridxlist_htab)
+  if (decl_to_stridxlist_htab.is_created ())
     {
       obstack_free (&stridx_obstack, NULL);
-      htab_delete (decl_to_stridxlist_htab);
-      decl_to_stridxlist_htab = NULL;
+      decl_to_stridxlist_htab.dispose ();
     }
   laststmt.stmt = NULL;
   laststmt.len = NULL_TREE;
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c	(revision 194381)
+++ gcc/tree-ssa-loop-ivopts.c	(working copy)
@@ -76,7 +76,7 @@  along with GCC; see the file COPYING3.
 #include "ggc.h"
 #include "insn-config.h"
 #include "pointer-set.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "tree-chrec.h"
 #include "tree-scalar-evolution.h"
 #include "cfgloop.h"
@@ -237,6 +237,33 @@  typedef struct iv_use *iv_use_p;

 typedef struct iv_cand *iv_cand_p;

+/* Hashtable helpers.  */
+
+struct iv_inv_expr_hasher : typed_free_remove <iv_inv_expr_ent>
+{
+  typedef iv_inv_expr_ent value_type;
+  typedef iv_inv_expr_ent compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
+
+/* Hash function for loop invariant expressions.  */
+
+inline hashval_t
+iv_inv_expr_hasher::hash (const value_type *expr)
+{
+  return expr->hash;
+}
+
+/* Hash table equality function for expressions.  */
+
+inline bool
+iv_inv_expr_hasher::equal (const value_type *expr1, const compare_type *expr2)
+{
+  return expr1->hash == expr2->hash
+	 && operand_equal_p (expr1->expr, expr2->expr, 0);
+}
+
 struct ivopts_data
 {
   /* The currently optimized loop.  */
@@ -256,7 +283,7 @@  struct ivopts_data

   /* The hashtable of loop invariant expressions created
      by ivopt.  */
-  htab_t inv_expr_tab;
+  hash_table <iv_inv_expr_hasher> inv_expr_tab;

   /* Loop invariant expression id.  */
   int inv_expr_id;
@@ -815,30 +842,6 @@  niter_for_single_dom_exit (struct ivopts
   return niter_for_exit (data, exit);
 }

-/* Hash table equality function for expressions.  */
-
-static int
-htab_inv_expr_eq (const void *ent1, const void *ent2)
-{
-  const struct iv_inv_expr_ent *expr1 =
-      (const struct iv_inv_expr_ent *)ent1;
-  const struct iv_inv_expr_ent *expr2 =
-      (const struct iv_inv_expr_ent *)ent2;
-
-  return expr1->hash == expr2->hash
-	 && operand_equal_p (expr1->expr, expr2->expr, 0);
-}
-
-/* Hash function for loop invariant expressions.  */
-
-static hashval_t
-htab_inv_expr_hash (const void *ent)
-{
-  const struct iv_inv_expr_ent *expr =
-      (const struct iv_inv_expr_ent *)ent;
-  return expr->hash;
-}
-
 /* Initializes data structures used by the iv optimization pass, stored
    in DATA.  */

@@ -853,8 +856,7 @@  tree_ssa_iv_optimize_init (struct ivopts
   data->niters = NULL;
   data->iv_uses.create (20);
   data->iv_candidates.create (20);
-  data->inv_expr_tab = htab_create (10, htab_inv_expr_hash,
-                                    htab_inv_expr_eq, free);
+  data->inv_expr_tab.create (10);
   data->inv_expr_id = 0;
   decl_rtl_to_reset.create (20);
 }
@@ -3806,8 +3808,7 @@  get_expr_id (struct ivopts_data *data, t

   ent.expr = expr;
   ent.hash = iterative_hash_expr (expr, 0);
-  slot = (struct iv_inv_expr_ent **) htab_find_slot (data->inv_expr_tab,
-                                                     &ent, INSERT);
+  slot = data->inv_expr_tab.find_slot (&ent, INSERT);
   if (*slot)
     return (*slot)->id;

@@ -6631,7 +6632,7 @@  free_loop_data (struct ivopts_data *data

   decl_rtl_to_reset.truncate (0);

-  htab_empty (data->inv_expr_tab);
+  data->inv_expr_tab.empty ();
   data->inv_expr_id = 0;
 }

@@ -6649,7 +6650,7 @@  tree_ssa_iv_optimize_finalize (struct iv
   decl_rtl_to_reset.release ();
   data->iv_uses.release ();
   data->iv_candidates.release ();
-  htab_delete (data->inv_expr_tab);
+  data->inv_expr_tab.dispose ();
 }

 /* Returns true if the loop body BODY includes any function calls.  */