diff mbox

add hash_set

Message ID 1406638216-31397-1-git-send-email-tsaunders@mozilla.com
State New
Headers show

Commit Message

Trevor Saunders July 29, 2014, 12:50 p.m. UTC
From: Trevor Saunders <tsaunders@mozilla.com>

Hi,

this adds a hash_set wrapper around hash_table, and then replaces usage of pointer_set with it.

bootstrapped +regtested on x86_64-unknown-linux-gnu, ok?

Trev

ada/

	* gcc-interface/trans.c: Use hash_set instead of pointer_set.

c-family/

	* c-gimplify.c: Use hash_set instead of pointer_set.

c/

	* c-decl.c: Use hash_set instead of pointer_set.

cp/

	* class.c, cp-gimplify.c, cp-tree.h, decl.c, decl2.c, error.c,
	method.c, name-lookup.c, pt.c, semantics.c, tree.c: Use hash_set
	instead of pointer_set.

fortran/

	* openmp.c, trans-decl.c: Use hash_set instead of pointer_set.

gcc/

	* hash-set.h: new File.
	* cfgexpand.c, cfgloop.c, cgraph.c, cgraphbuild.c, cgraphunit.c,
	cprop.c, cse.c, gimple-walk.c, gimple-walk.h, gimplify.c, godump.c,
	ipa-devirt.c, ipa-pure-const.c, ipa-visibility.c, ipa.c, lto-cgraph.c,
	lto-streamer-out.c, stmt.c, tree-cfg.c, tree-core.h, tree-eh.c,
	tree-inline.c, tree-inline.h, tree-nested.c, tree-pretty-print.c,
	tree-ssa-loop-niter.c, tree-ssa-phiopt.c, tree-ssa-threadedge.c,
	tree-ssa-uninit.c, tree.c, tree.h, value-prof.c, varasm.c,
	varpool.c: Use hash_set instead of pointer_set.

lto/

	* lto-partition.c, lto-partition.h: Use hash_set instead of
	pointer_set.

Comments

Richard Biener July 30, 2014, 10:25 a.m. UTC | #1
On Tue, Jul 29, 2014 at 2:50 PM,  <tsaunders@mozilla.com> wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
> this adds a hash_set wrapper around hash_table, and then replaces usage of pointer_set with it.
>
> bootstrapped +regtested on x86_64-unknown-linux-gnu, ok?

Ok.

Thanks,
Richard.

> Trev
>
> ada/
>
>         * gcc-interface/trans.c: Use hash_set instead of pointer_set.
>
> c-family/
>
>         * c-gimplify.c: Use hash_set instead of pointer_set.
>
> c/
>
>         * c-decl.c: Use hash_set instead of pointer_set.
>
> cp/
>
>         * class.c, cp-gimplify.c, cp-tree.h, decl.c, decl2.c, error.c,
>         method.c, name-lookup.c, pt.c, semantics.c, tree.c: Use hash_set
>         instead of pointer_set.
>
> fortran/
>
>         * openmp.c, trans-decl.c: Use hash_set instead of pointer_set.
>
> gcc/
>
>         * hash-set.h: new File.
>         * cfgexpand.c, cfgloop.c, cgraph.c, cgraphbuild.c, cgraphunit.c,
>         cprop.c, cse.c, gimple-walk.c, gimple-walk.h, gimplify.c, godump.c,
>         ipa-devirt.c, ipa-pure-const.c, ipa-visibility.c, ipa.c, lto-cgraph.c,
>         lto-streamer-out.c, stmt.c, tree-cfg.c, tree-core.h, tree-eh.c,
>         tree-inline.c, tree-inline.h, tree-nested.c, tree-pretty-print.c,
>         tree-ssa-loop-niter.c, tree-ssa-phiopt.c, tree-ssa-threadedge.c,
>         tree-ssa-uninit.c, tree.c, tree.h, value-prof.c, varasm.c,
>         varpool.c: Use hash_set instead of pointer_set.
>
> lto/
>
>         * lto-partition.c, lto-partition.h: Use hash_set instead of
>         pointer_set.
> diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
> index f42ac7f..6961838 100644
> --- a/gcc/ada/gcc-interface/trans.c
> +++ b/gcc/ada/gcc-interface/trans.c
> @@ -36,7 +36,7 @@
>  #include "output.h"
>  #include "libfuncs.h"  /* For set_stack_check_libfunc.  */
>  #include "tree-iterator.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "gimple-expr.h"
>  #include "gimplify.h"
>  #include "bitmap.h"
> @@ -3054,7 +3054,7 @@ struct nrv_data
>    bitmap nrv;
>    tree result;
>    Node_Id gnat_ret;
> -  struct pointer_set_t *visited;
> +  hash_set<tree> *visited;
>  };
>
>  /* Return true if T is a Named Return Value.  */
> @@ -3188,7 +3188,7 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
>    /* Avoid walking into the same tree more than once.  Unfortunately, we
>       can't just use walk_tree_without_duplicates because it would only
>       call us for the first occurrence of NRVs in the function body.  */
> -  if (pointer_set_insert (dp->visited, *tp))
> +  if (dp->visited->add (*tp))
>      *walk_subtrees = 0;
>
>    return NULL_TREE;
> @@ -3328,7 +3328,7 @@ finalize_nrv_unc_r (tree *tp, int *walk_subtrees, void *data)
>    /* Avoid walking into the same tree more than once.  Unfortunately, we
>       can't just use walk_tree_without_duplicates because it would only
>       call us for the first occurrence of NRVs in the function body.  */
> -  if (pointer_set_insert (dp->visited, *tp))
> +  if (dp->visited->add (*tp))
>      *walk_subtrees = 0;
>
>    return NULL_TREE;
> @@ -3376,13 +3376,13 @@ finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret
>    data.nrv = nrv;
>    data.result = DECL_RESULT (fndecl);
>    data.gnat_ret = gnat_ret;
> -  data.visited = pointer_set_create ();
> +  data.visited = new hash_set<tree>;
>    if (TYPE_RETURN_UNCONSTRAINED_P (TREE_TYPE (fndecl)))
>      func = finalize_nrv_unc_r;
>    else
>      func = finalize_nrv_r;
>    walk_tree (&DECL_SAVED_TREE (fndecl), func, &data, NULL);
> -  pointer_set_destroy (data.visited);
> +  delete data.visited;
>  }
>
>  /* Return true if RET_VAL can be used as a Named Return Value for the
> diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
> index 2b5ce5b..4898217 100644
> --- a/gcc/c-family/c-gimplify.c
> +++ b/gcc/c-family/c-gimplify.c
> @@ -74,7 +74,7 @@ along with GCC; see the file COPYING3.  If not see
>  static tree
>  ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
>  {
> -  struct pointer_set_t *pset = (struct pointer_set_t *) data;
> +  hash_set<tree> *pset = (hash_set<tree> *) data;
>
>    /* Since walk_tree doesn't call the callback function on the decls
>       in BIND_EXPR_VARS, we have to walk them manually.  */
> @@ -116,10 +116,9 @@ c_genericize (tree fndecl)
>
>    if (flag_sanitize & SANITIZE_BOUNDS)
>      {
> -      struct pointer_set_t *pset = pointer_set_create ();
> -      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, pset,
> -                pset);
> -      pointer_set_destroy (pset);
> +      hash_set<tree> pset;
> +      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
> +                &pset);
>      }
>
>    /* Dump the C-specific tree IR.  */
> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> index 2a4b439..050ddff 100644
> --- a/gcc/c/c-decl.c
> +++ b/gcc/c/c-decl.c
> @@ -59,7 +59,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "cgraph.h"
>  #include "hash-table.h"
>  #include "langhooks-def.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "plugin.h"
>  #include "c-family/c-ada-spec.h"
>  #include "cilk.h"
> @@ -7221,17 +7221,17 @@ warn_cxx_compat_finish_struct (tree fieldlist)
>    if (!struct_parse_info->typedefs_seen.is_empty ()
>        && fieldlist != NULL_TREE)
>      {
> -      /* Use a pointer_set using the name of the typedef.  We can use
> -        a pointer_set because identifiers are interned.  */
> -      struct pointer_set_t *tset = pointer_set_create ();
> +      /* Use a hash_set<tree> using the name of the typedef.  We can use
> +        a hash_set<tree> because identifiers are interned.  */
> +      hash_set<tree> tset;
>
>        FOR_EACH_VEC_ELT (struct_parse_info->typedefs_seen, ix, x)
> -       pointer_set_insert (tset, DECL_NAME (x));
> +       tset.add (DECL_NAME (x));
>
>        for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
>         {
>           if (DECL_NAME (x) != NULL_TREE
> -             && pointer_set_contains (tset, DECL_NAME (x)))
> +             && tset.contains (DECL_NAME (x)))
>             {
>               warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
>                           ("using %qD as both field and typedef name is "
> @@ -7241,8 +7241,6 @@ warn_cxx_compat_finish_struct (tree fieldlist)
>                  the typedef name is used.  */
>             }
>         }
> -
> -      pointer_set_destroy (tset);
>      }
>
>    /* For each field which has a binding and which was not defined in
> @@ -8189,7 +8187,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>    struct c_binding *b;
>    tree parm, decl, last;
>    tree parmids = arg_info->parms;
> -  struct pointer_set_t *seen_args = pointer_set_create ();
> +  hash_set<tree> seen_args;
>
>    if (!in_system_header_at (input_location))
>      warning_at (DECL_SOURCE_LOCATION (fndecl),
> @@ -8220,7 +8218,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>                       "%qD declared as a non-parameter", decl);
>           /* If the declaration is already marked, we have a duplicate
>              name.  Complain and ignore the duplicate.  */
> -         else if (pointer_set_contains (seen_args, decl))
> +         else if (seen_args.contains (decl))
>             {
>               error_at (DECL_SOURCE_LOCATION (decl),
>                         "multiple parameters named %qD", decl);
> @@ -8269,7 +8267,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>         }
>
>        TREE_PURPOSE (parm) = decl;
> -      pointer_set_insert (seen_args, decl);
> +      seen_args.add (decl);
>      }
>
>    /* Now examine the parms chain for incomplete declarations
> @@ -8289,7 +8287,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>           TREE_TYPE (parm) = error_mark_node;
>         }
>
> -      if (!pointer_set_contains (seen_args, parm))
> +      if (!seen_args.contains (parm))
>         {
>           error_at (DECL_SOURCE_LOCATION (parm),
>                     "declaration for parameter %qD but no such parameter",
> @@ -8324,8 +8322,6 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>        DECL_CHAIN (last) = 0;
>      }
>
> -  pointer_set_destroy (seen_args);
> -
>    /* If there was a previous prototype,
>       set the DECL_ARG_TYPE of each argument according to
>       the type previously specified, and report any mismatches.  */
> diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
> index 2f0ae71..b20be10 100644
> --- a/gcc/cfgexpand.c
> +++ b/gcc/cfgexpand.c
> @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "expr.h"
>  #include "langhooks.h"
>  #include "bitmap.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
> @@ -594,7 +595,7 @@ stack_var_cmp (const void *a, const void *b)
>  static void
>  add_partitioned_vars_to_ptset (struct pt_solution *pt,
>                                struct pointer_map_t *decls_to_partitions,
> -                              struct pointer_set_t *visited, bitmap temp)
> +                              hash_set<bitmap> *visited, bitmap temp)
>  {
>    bitmap_iterator bi;
>    unsigned i;
> @@ -604,7 +605,7 @@ add_partitioned_vars_to_ptset (struct pt_solution *pt,
>        || pt->vars == NULL
>        /* The pointed-to vars bitmap is shared, it is enough to
>          visit it once.  */
> -      || pointer_set_insert (visited, pt->vars))
> +      || visited->add (pt->vars))
>      return;
>
>    bitmap_clear (temp);
> @@ -684,7 +685,7 @@ update_alias_info_with_stack_vars (void)
>    if (decls_to_partitions)
>      {
>        unsigned i;
> -      struct pointer_set_t *visited = pointer_set_create ();
> +      hash_set<bitmap> visited;
>        bitmap temp = BITMAP_ALLOC (&stack_var_bitmap_obstack);
>
>        for (i = 1; i < num_ssa_names; i++)
> @@ -696,13 +697,12 @@ update_alias_info_with_stack_vars (void)
>               && POINTER_TYPE_P (TREE_TYPE (name))
>               && ((pi = SSA_NAME_PTR_INFO (name)) != NULL))
>             add_partitioned_vars_to_ptset (&pi->pt, decls_to_partitions,
> -                                          visited, temp);
> +                                          &visited, temp);
>         }
>
>        add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped,
> -                                    decls_to_partitions, visited, temp);
> +                                    decls_to_partitions, &visited, temp);
>
> -      pointer_set_destroy (visited);
>        pointer_map_destroy (decls_to_partitions);
>        BITMAP_FREE (temp);
>      }
> diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
> index 73f79ef..8f7e265 100644
> --- a/gcc/cfgloop.c
> +++ b/gcc/cfgloop.c
> @@ -28,7 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "diagnostic-core.h"
>  #include "flags.h"
>  #include "tree.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
>  #include "gimple-expr.h"
> @@ -650,11 +650,11 @@ find_subloop_latch_edge (struct loop *loop)
>  /* Callback for make_forwarder_block.  Returns true if the edge E is marked
>     in the set MFB_REIS_SET.  */
>
> -static struct pointer_set_t *mfb_reis_set;
> +static hash_set<edge> *mfb_reis_set;
>  static bool
>  mfb_redirect_edges_in_set (edge e)
>  {
> -  return pointer_set_contains (mfb_reis_set, e);
> +  return mfb_reis_set->contains (e);
>  }
>
>  /* Creates a subloop of LOOP with latch edge LATCH.  */
> @@ -666,15 +666,15 @@ form_subloop (struct loop *loop, edge latch)
>    edge e, new_entry;
>    struct loop *new_loop;
>
> -  mfb_reis_set = pointer_set_create ();
> +  mfb_reis_set = new hash_set<edge>;
>    FOR_EACH_EDGE (e, ei, loop->header->preds)
>      {
>        if (e != latch)
> -       pointer_set_insert (mfb_reis_set, e);
> +       mfb_reis_set->add (e);
>      }
>    new_entry = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
>                                     NULL);
> -  pointer_set_destroy (mfb_reis_set);
> +  delete mfb_reis_set;
>
>    loop->header = new_entry->src;
>
> @@ -705,12 +705,12 @@ merge_latch_edges (struct loop *loop)
>        if (dump_file)
>         fprintf (dump_file, "Merged latch edges of loop %d\n", loop->num);
>
> -      mfb_reis_set = pointer_set_create ();
> +      mfb_reis_set = new hash_set<edge>;
>        FOR_EACH_VEC_ELT (latches, i, e)
> -       pointer_set_insert (mfb_reis_set, e);
> +       mfb_reis_set->add (e);
>        latch = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
>                                     NULL);
> -      pointer_set_destroy (mfb_reis_set);
> +      delete mfb_reis_set;
>
>        loop->header = latch->dest;
>        loop->latch = latch->src;
> diff --git a/gcc/cgraph.c b/gcc/cgraph.c
> index a5d0749..7c72399 100644
> --- a/gcc/cgraph.c
> +++ b/gcc/cgraph.c
> @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-inline.h"
>  #include "langhooks.h"
>  #include "hashtab.h"
> +#include "hash-set.h"
>  #include "toplev.h"
>  #include "flags.h"
>  #include "debug.h"
> @@ -2871,7 +2872,7 @@ cgraph_node::verify_node (void)
>      {
>        if (this_cfun->cfg)
>         {
> -         pointer_set_t *stmts = pointer_set_create ();
> +         hash_set<gimple> stmts;
>           int i;
>           struct ipa_ref *ref = NULL;
>
> @@ -2881,13 +2882,13 @@ cgraph_node::verify_node (void)
>             {
>               for (gsi = gsi_start_phis (this_block);
>                    !gsi_end_p (gsi); gsi_next (&gsi))
> -               pointer_set_insert (stmts, gsi_stmt (gsi));
> +               stmts.add (gsi_stmt (gsi));
>               for (gsi = gsi_start_bb (this_block);
>                    !gsi_end_p (gsi);
>                    gsi_next (&gsi))
>                 {
>                   gimple stmt = gsi_stmt (gsi);
> -                 pointer_set_insert (stmts, stmt);
> +                 stmts.add (stmt);
>                   if (is_gimple_call (stmt))
>                     {
>                       struct cgraph_edge *e = get_edge (stmt);
> @@ -2931,13 +2932,12 @@ cgraph_node::verify_node (void)
>                 }
>               }
>             for (i = 0; iterate_reference (i, ref); i++)
> -             if (ref->stmt && !pointer_set_contains (stmts, ref->stmt))
> +             if (ref->stmt && !stmts.contains (ref->stmt))
>                 {
>                   error ("reference to dead statement");
>                   cgraph_debug_gimple_stmt (this_cfun, ref->stmt);
>                   error_found = true;
>                 }
> -           pointer_set_destroy (stmts);
>         }
>        else
>         /* No CFG available?!  */
> diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
> index 91811d7..a04958f 100644
> --- a/gcc/cgraphbuild.c
> +++ b/gcc/cgraphbuild.c
> @@ -322,7 +322,6 @@ pass_build_cgraph_edges::execute (function *fun)
>  {
>    basic_block bb;
>    struct cgraph_node *node = cgraph_node::get (current_function_decl);
> -  struct pointer_set_t *visited_nodes = pointer_set_create ();
>    gimple_stmt_iterator gsi;
>    tree decl;
>    unsigned ix;
> @@ -386,7 +385,6 @@ pass_build_cgraph_edges::execute (function *fun)
>        varpool_node::finalize_decl (decl);
>    record_eh_tables (node, fun);
>
> -  pointer_set_destroy (visited_nodes);
>    return 0;
>  }
>
> @@ -405,15 +403,14 @@ make_pass_build_cgraph_edges (gcc::context *ctxt)
>  void
>  record_references_in_initializer (tree decl, bool only_vars)
>  {
> -  struct pointer_set_t *visited_nodes = pointer_set_create ();
>    varpool_node *node = varpool_node::get_create (decl);
> +  hash_set<tree> visited_nodes;
>    struct record_reference_ctx ctx = {false, NULL};
>
>    ctx.varpool_node = node;
>    ctx.only_vars = only_vars;
>    walk_tree (&DECL_INITIAL (decl), record_reference,
> -             &ctx, visited_nodes);
> -  pointer_set_destroy (visited_nodes);
> +             &ctx, &visited_nodes);
>  }
>
>  /* Rebuild cgraph edges for current function node.  This needs to be run after
> diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> index 3080b9a..220b953 100644
> --- a/gcc/cgraphunit.c
> +++ b/gcc/cgraphunit.c
> @@ -845,7 +845,7 @@ varpool_node::finalize_decl (tree decl)
>     avoid udplicate work.  */
>
>  static void
> -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
>                                struct cgraph_edge *edge)
>  {
>    unsigned int i;
> @@ -855,8 +855,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
>      = possible_polymorphic_call_targets
>         (edge, &final, &cache_token);
>
> -  if (!pointer_set_insert (reachable_call_targets,
> -                          cache_token))
> +  if (!reachable_call_targets->add (cache_token))
>      {
>        if (cgraph_dump_file)
>         dump_possible_polymorphic_call_targets
> @@ -936,7 +935,7 @@ analyze_functions (void)
>    struct cgraph_node *first_handled = first_analyzed;
>    static varpool_node *first_analyzed_var;
>    varpool_node *first_handled_var = first_analyzed_var;
> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> +  hash_set<void *> reachable_call_targets;
>
>    symtab_node *node;
>    symtab_node *next;
> @@ -1035,7 +1034,7 @@ analyze_functions (void)
>                     {
>                       next = edge->next_callee;
>                       if (edge->indirect_info->polymorphic)
> -                       walk_polymorphic_call_targets (reachable_call_targets,
> +                       walk_polymorphic_call_targets (&reachable_call_targets,
>                                                        edge);
>                     }
>                 }
> @@ -1123,7 +1122,6 @@ analyze_functions (void)
>        symtab_node::dump_table (cgraph_dump_file);
>      }
>    bitmap_obstack_release (NULL);
> -  pointer_set_destroy (reachable_call_targets);
>    ggc_collect ();
>    /* Initialize assembler name hash, in particular we want to trigger C++
>       mangling and same body alias creation before we free DECL_ARGUMENTS
> diff --git a/gcc/cp/class.c b/gcc/cp/class.c
> index 0f611e1..d9b34f7 100644
> --- a/gcc/cp/class.c
> +++ b/gcc/cp/class.c
> @@ -5359,15 +5359,15 @@ finalize_literal_type_property (tree t)
>  void
>  explain_non_literal_class (tree t)
>  {
> -  static struct pointer_set_t *diagnosed;
> +  static hash_set<tree> *diagnosed;
>
>    if (!CLASS_TYPE_P (t))
>      return;
>    t = TYPE_MAIN_VARIANT (t);
>
>    if (diagnosed == NULL)
> -    diagnosed = pointer_set_create ();
> -  if (pointer_set_insert (diagnosed, t) != 0)
> +    diagnosed = new hash_set<tree>;
> +  if (diagnosed->add (t))
>      /* Already explained.  */
>      return;
>
> diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
> index a35177b..3cfcbc6 100644
> --- a/gcc/cp/cp-gimplify.c
> +++ b/gcc/cp/cp-gimplify.c
> @@ -871,7 +871,7 @@ omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
>
>  struct cp_genericize_data
>  {
> -  struct pointer_set_t *p_set;
> +  hash_set<tree> *p_set;
>    vec<tree> bind_expr_stack;
>    struct cp_genericize_omp_taskreg *omp_ctx;
>  };
> @@ -884,7 +884,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
>  {
>    tree stmt = *stmt_p;
>    struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
> -  struct pointer_set_t *p_set = wtd->p_set;
> +  hash_set<tree> *p_set = wtd->p_set;
>
>    /* If in an OpenMP context, note var uses.  */
>    if (__builtin_expect (wtd->omp_ctx != NULL, 0)
> @@ -924,7 +924,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
>      }
>
>    /* Other than invisiref parms, don't walk the same tree twice.  */
> -  if (pointer_set_contains (p_set, stmt))
> +  if (p_set->contains (stmt))
>      {
>        *walk_subtrees = 0;
>        return NULL_TREE;
> @@ -1199,7 +1199,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
>        return NULL;
>      }
>
> -  pointer_set_insert (p_set, *stmt_p);
> +  p_set->add (*stmt_p);
>
>    return NULL;
>  }
> @@ -1211,11 +1211,11 @@ cp_genericize_tree (tree* t_p)
>  {
>    struct cp_genericize_data wtd;
>
> -  wtd.p_set = pointer_set_create ();
> +  wtd.p_set = new hash_set<tree>;
>    wtd.bind_expr_stack.create (0);
>    wtd.omp_ctx = NULL;
>    cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
> -  pointer_set_destroy (wtd.p_set);
> +  delete wtd.p_set;
>    wtd.bind_expr_stack.release ();
>  }
>
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 0c0d804..622de9c 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -6028,7 +6028,7 @@ extern void verify_stmt_tree                      (tree);
>  extern linkage_kind decl_linkage               (tree);
>  extern duration_kind decl_storage_duration     (tree);
>  extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
> -                             void*, struct pointer_set_t*);
> +                             void*, hash_set<tree> *);
>  #define cp_walk_tree(tp,func,data,pset) \
>         walk_tree_1 (tp, func, data, pset, cp_walk_subtrees)
>  #define cp_walk_tree_without_duplicates(tp,func,data) \
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index aafb917..f70684f 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -8198,7 +8198,7 @@ check_static_variable_definition (tree decl, tree type)
>  static tree
>  stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
>  {
> -  struct pointer_set_t *pset = (struct pointer_set_t *)data;
> +  hash_set<tree> *pset = (hash_set<tree> *)data;
>    tree expr = *expr_p;
>    if (TREE_CODE (expr) == SAVE_EXPR)
>      {
> @@ -8218,10 +8218,9 @@ stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
>  static void
>  stabilize_vla_size (tree size)
>  {
> -  struct pointer_set_t *pset = pointer_set_create ();
> +  hash_set<tree> pset;
>    /* Break out any function calls into temporary variables.  */
> -  cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
> -  pointer_set_destroy (pset);
> +  cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
>  }
>
>  /* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
> diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
> index 8fa3145..d79665e 100644
> --- a/gcc/cp/decl2.c
> +++ b/gcc/cp/decl2.c
> @@ -3938,11 +3938,11 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
>     supported, collect and return all the functions for which we should
>     emit a hidden alias.  */
>
> -static struct pointer_set_t *
> +static hash_set<tree> *
>  collect_candidates_for_java_method_aliases (void)
>  {
>    struct cgraph_node *node;
> -  struct pointer_set_t *candidates = NULL;
> +  hash_set<tree> *candidates = NULL;
>
>  #ifndef HAVE_GAS_HIDDEN
>    return candidates;
> @@ -3957,8 +3957,8 @@ collect_candidates_for_java_method_aliases (void)
>           && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
>         {
>           if (candidates == NULL)
> -           candidates = pointer_set_create ();
> -         pointer_set_insert (candidates, fndecl);
> +           candidates = new hash_set<tree>;
> +         candidates->add (fndecl);
>         }
>      }
>
> @@ -3973,7 +3973,7 @@ collect_candidates_for_java_method_aliases (void)
>     by collect_candidates_for_java_method_aliases.  */
>
>  static void
> -build_java_method_aliases (struct pointer_set_t *candidates)
> +build_java_method_aliases (hash_set<tree> *candidates)
>  {
>    struct cgraph_node *node;
>
> @@ -3986,7 +3986,7 @@ build_java_method_aliases (struct pointer_set_t *candidates)
>        tree fndecl = node->decl;
>
>        if (TREE_ASM_WRITTEN (fndecl)
> -         && pointer_set_contains (candidates, fndecl))
> +         && candidates->contains (fndecl))
>         {
>           /* Mangle the name in a predictable way; we need to reference
>              this from a java compiled object file.  */
> @@ -4296,7 +4296,7 @@ cp_write_global_declarations (void)
>    unsigned ssdf_count = 0;
>    int retries = 0;
>    tree decl;
> -  struct pointer_set_t *candidates;
> +  hash_set<tree> *candidates;
>
>    locus = input_location;
>    at_eof = 1;
> @@ -4713,7 +4713,7 @@ cp_write_global_declarations (void)
>    if (candidates)
>      {
>        build_java_method_aliases (candidates);
> -      pointer_set_destroy (candidates);
> +      delete candidates;
>      }
>
>    finish_repo ();
> diff --git a/gcc/cp/error.c b/gcc/cp/error.c
> index fa3bdc4..c8987ee 100644
> --- a/gcc/cp/error.c
> +++ b/gcc/cp/error.c
> @@ -1325,7 +1325,7 @@ dump_template_decl (cxx_pretty_printer *pp, tree t, int flags)
>
>  struct find_typenames_t
>  {
> -  struct pointer_set_t *p_set;
> +  hash_set<tree> *p_set;
>    vec<tree, va_gc> *typenames;
>  };
>
> @@ -1351,7 +1351,7 @@ find_typenames_r (tree *tp, int *walk_subtrees, void *data)
>        return NULL_TREE;
>      }
>
> -  if (mv && (mv == *tp || !pointer_set_insert (d->p_set, mv)))
> +  if (mv && (mv == *tp || !d->p_set->add (mv)))
>      vec_safe_push (d->typenames, mv);
>
>    /* Search into class template arguments, which cp_walk_subtrees
> @@ -1367,11 +1367,11 @@ static vec<tree, va_gc> *
>  find_typenames (tree t)
>  {
>    struct find_typenames_t ft;
> -  ft.p_set = pointer_set_create ();
> +  ft.p_set = new hash_set<tree>;
>    ft.typenames = NULL;
>    cp_walk_tree (&TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
>                 find_typenames_r, &ft, ft.p_set);
> -  pointer_set_destroy (ft.p_set);
> +  delete ft.p_set;
>    return ft.typenames;
>  }
>
> diff --git a/gcc/cp/method.c b/gcc/cp/method.c
> index e5fa0c1..65c5621 100644
> --- a/gcc/cp/method.c
> +++ b/gcc/cp/method.c
> @@ -1480,7 +1480,7 @@ maybe_explain_implicit_delete (tree decl)
>    if (DECL_DEFAULTED_FN (decl))
>      {
>        /* Not marked GTY; it doesn't need to be GC'd or written to PCH.  */
> -      static struct pointer_set_t *explained;
> +      static hash_set<tree> *explained;
>
>        special_function_kind sfk;
>        location_t loc;
> @@ -1488,8 +1488,8 @@ maybe_explain_implicit_delete (tree decl)
>        tree ctype;
>
>        if (!explained)
> -       explained = pointer_set_create ();
> -      if (pointer_set_insert (explained, decl))
> +       explained = new hash_set<tree>;
> +      if (explained->add (decl))
>         return true;
>
>        sfk = special_function_p (decl);
> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> index 75b46ac..6e779a6 100644
> --- a/gcc/cp/name-lookup.c
> +++ b/gcc/cp/name-lookup.c
> @@ -35,7 +35,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "debug.h"
>  #include "c-family/c-pragma.h"
>  #include "params.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>
>  /* The bindings for a particular name in a particular scope.  */
>
> @@ -5152,7 +5152,7 @@ struct arg_lookup
>    vec<tree, va_gc> *namespaces;
>    vec<tree, va_gc> *classes;
>    tree functions;
> -  struct pointer_set_t *fn_set;
> +  hash_set<tree> *fn_set;
>  };
>
>  static bool arg_assoc (struct arg_lookup*, tree);
> @@ -5175,7 +5175,7 @@ add_function (struct arg_lookup *k, tree fn)
>    if (!is_overloaded_fn (fn))
>      /* All names except those of (possibly overloaded) functions and
>         function templates are ignored.  */;
> -  else if (k->fn_set && pointer_set_insert (k->fn_set, fn))
> +  else if (k->fn_set && k->fn_set->add (fn))
>      /* It's already in the list.  */;
>    else if (!k->functions)
>      k->functions = fn;
> @@ -5639,9 +5639,9 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
>        /* We shouldn't be here if lookup found something other than
>          namespace-scope functions.  */
>        gcc_assert (DECL_NAMESPACE_SCOPE_P (OVL_CURRENT (fns)));
> -      k.fn_set = pointer_set_create ();
> +      k.fn_set = new hash_set<tree>;
>        for (ovl = fns; ovl; ovl = OVL_NEXT (ovl))
> -       pointer_set_insert (k.fn_set, OVL_CURRENT (ovl));
> +       k.fn_set->add (OVL_CURRENT (ovl));
>      }
>    else
>      k.fn_set = NULL;
> @@ -5661,8 +5661,7 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
>
>    release_tree_vector (k.classes);
>    release_tree_vector (k.namespaces);
> -  if (k.fn_set)
> -    pointer_set_destroy (k.fn_set);
> +  delete k.fn_set;
>
>    return fns;
>  }
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index b32cf6c..9b156f5 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -147,7 +147,7 @@ static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
>  static tree convert_template_argument (tree, tree, tree,
>                                        tsubst_flags_t, int, tree);
>  static int for_each_template_parm (tree, tree_fn_t, void*,
> -                                  struct pointer_set_t*, bool);
> +                                  hash_set<tree> *, bool);
>  static tree expand_template_argument_pack (tree);
>  static tree build_template_parm_index (int, int, int, tree, tree);
>  static bool inline_needs_template_parms (tree, bool);
> @@ -3080,7 +3080,7 @@ struct find_parameter_pack_data
>    tree* parameter_packs;
>
>    /* Set of AST nodes that have been visited by the traversal.  */
> -  struct pointer_set_t *visited;
> +  hash_set<tree> *visited;
>  };
>
>  /* Identifies all of the argument packs that occur in a template
> @@ -3243,9 +3243,9 @@ uses_parameter_packs (tree t)
>    tree parameter_packs = NULL_TREE;
>    struct find_parameter_pack_data ppd;
>    ppd.parameter_packs = &parameter_packs;
> -  ppd.visited = pointer_set_create ();
> +  ppd.visited = new hash_set<tree>;
>    cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
> -  pointer_set_destroy (ppd.visited);
> +  delete ppd.visited;
>    return parameter_packs != NULL_TREE;
>  }
>
> @@ -3292,7 +3292,7 @@ make_pack_expansion (tree arg)
>
>        /* Determine which parameter packs will be used by the base
>           class expansion.  */
> -      ppd.visited = pointer_set_create ();
> +      ppd.visited = new hash_set<tree>;
>        ppd.parameter_packs = &parameter_packs;
>        cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
>                      &ppd, ppd.visited);
> @@ -3300,7 +3300,7 @@ make_pack_expansion (tree arg)
>        if (parameter_packs == NULL_TREE)
>          {
>            error ("base initializer expansion %<%T%> contains no parameter packs", arg);
> -          pointer_set_destroy (ppd.visited);
> +          delete ppd.visited;
>            return error_mark_node;
>          }
>
> @@ -3317,7 +3317,7 @@ make_pack_expansion (tree arg)
>              }
>          }
>
> -      pointer_set_destroy (ppd.visited);
> +      delete ppd.visited;
>
>        /* Create the pack expansion type for the base type.  */
>        purpose = cxx_make_type (TYPE_PACK_EXPANSION);
> @@ -3352,9 +3352,9 @@ make_pack_expansion (tree arg)
>
>    /* Determine which parameter packs will be expanded.  */
>    ppd.parameter_packs = &parameter_packs;
> -  ppd.visited = pointer_set_create ();
> +  ppd.visited = new hash_set<tree>;
>    cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
> -  pointer_set_destroy (ppd.visited);
> +  delete ppd.visited;
>
>    /* Make sure we found some parameter packs.  */
>    if (parameter_packs == NULL_TREE)
> @@ -3399,9 +3399,9 @@ check_for_bare_parameter_packs (tree t)
>      t = TREE_TYPE (t);
>
>    ppd.parameter_packs = &parameter_packs;
> -  ppd.visited = pointer_set_create ();
> +  ppd.visited = new hash_set<tree>;
>    cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
> -  pointer_set_destroy (ppd.visited);
> +  delete ppd.visited;
>
>    if (parameter_packs)
>      {
> @@ -4381,11 +4381,11 @@ fixed_parameter_pack_p (tree parm)
>    tree parameter_packs = NULL_TREE;
>    struct find_parameter_pack_data ppd;
>    ppd.parameter_packs = &parameter_packs;
> -  ppd.visited = pointer_set_create ();
> +  ppd.visited = new hash_set<tree>;
>
>    fixed_parameter_pack_p_1 (parm, &ppd);
>
> -  pointer_set_destroy (ppd.visited);
> +  delete ppd.visited;
>    return parameter_packs;
>  }
>
> @@ -7907,7 +7907,7 @@ struct pair_fn_data
>    /* True when we should also visit template parameters that occur in
>       non-deduced contexts.  */
>    bool include_nondeduced_p;
> -  struct pointer_set_t *visited;
> +  hash_set<tree> *visited;
>  };
>
>  /* Called from for_each_template_parm via walk_tree.  */
> @@ -8107,7 +8107,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
>
>  static int
>  for_each_template_parm (tree t, tree_fn_t fn, void* data,
> -                       struct pointer_set_t *visited,
> +                       hash_set<tree> *visited,
>                         bool include_nondeduced_p)
>  {
>    struct pair_fn_data pfd;
> @@ -8126,7 +8126,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
>    if (visited)
>      pfd.visited = visited;
>    else
> -    pfd.visited = pointer_set_create ();
> +    pfd.visited = new hash_set<tree>;
>    result = cp_walk_tree (&t,
>                          for_each_template_parm_r,
>                          &pfd,
> @@ -8135,7 +8135,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
>    /* Clean up.  */
>    if (!visited)
>      {
> -      pointer_set_destroy (pfd.visited);
> +      delete pfd.visited;
>        pfd.visited = 0;
>      }
>
> diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
> index c87764d..735284e 100644
> --- a/gcc/cp/semantics.c
> +++ b/gcc/cp/semantics.c
> @@ -8031,7 +8031,7 @@ register_constexpr_fundef (tree fun, tree body)
>  void
>  explain_invalid_constexpr_fn (tree fun)
>  {
> -  static struct pointer_set_t *diagnosed;
> +  static hash_set<tree> *diagnosed;
>    tree body;
>    location_t save_loc;
>    /* Only diagnose defaulted functions or instantiations.  */
> @@ -8039,8 +8039,8 @@ explain_invalid_constexpr_fn (tree fun)
>        && !is_instantiation_of_constexpr (fun))
>      return;
>    if (diagnosed == NULL)
> -    diagnosed = pointer_set_create ();
> -  if (pointer_set_insert (diagnosed, fun) != 0)
> +    diagnosed = new hash_set<tree>;
> +  if (diagnosed->add (fun))
>      /* Already explained.  */
>      return;
>
> diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
> index f6c5693..697a02b 100644
> --- a/gcc/cp/tree.c
> +++ b/gcc/cp/tree.c
> @@ -3485,7 +3485,7 @@ cxx_type_hash_eq (const_tree typea, const_tree typeb)
>
>  tree
>  cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
> -                 void *data, struct pointer_set_t *pset)
> +                 void *data, hash_set<tree> *pset)
>  {
>    enum tree_code code = TREE_CODE (*tp);
>    tree result;
> diff --git a/gcc/cprop.c b/gcc/cprop.c
> index 6291c91..4234afa 100644
> --- a/gcc/cprop.c
> +++ b/gcc/cprop.c
> @@ -167,7 +167,7 @@ reg_available_p (const_rtx x, const_rtx insn ATTRIBUTE_UNUSED)
>     ??? May need to make things more elaborate.  Later, as necessary.  */
>
>  static unsigned int
> -hash_set (int regno, int hash_table_size)
> +hash_mod (int regno, int hash_table_size)
>  {
>    return (unsigned) regno % hash_table_size;
>  }
> @@ -187,7 +187,7 @@ insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table,
>    struct expr *cur_expr, *last_expr = NULL;
>    struct occr *cur_occr;
>
> -  hash = hash_set (REGNO (dest), table->size);
> +  hash = hash_mod (REGNO (dest), table->size);
>
>    for (cur_expr = table->table[hash]; cur_expr;
>         cur_expr = cur_expr->next_same_hash)
> @@ -483,7 +483,7 @@ compute_hash_table (struct hash_table_d *table)
>  static struct expr *
>  lookup_set (unsigned int regno, struct hash_table_d *table)
>  {
> -  unsigned int hash = hash_set (regno, table->size);
> +  unsigned int hash = hash_mod (regno, table->size);
>    struct expr *expr;
>
>    expr = table->table[hash];
> diff --git a/gcc/cse.c b/gcc/cse.c
> index 34f9364..dd9a076 100644
> --- a/gcc/cse.c
> +++ b/gcc/cse.c
> @@ -41,7 +41,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-pass.h"
>  #include "df.h"
>  #include "dbgcnt.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>
>  /* The basic idea of common subexpression elimination is to go
>     through the code, keeping a record of expressions that would
> @@ -2906,7 +2906,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>                       enum machine_mode *pmode1, enum machine_mode *pmode2)
>  {
>    rtx arg1, arg2;
> -  struct pointer_set_t *visited = NULL;
> +  hash_set<rtx> *visited = NULL;
>    /* Set nonzero when we find something of interest.  */
>    rtx x = NULL;
>
> @@ -2923,8 +2923,8 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>        if (x)
>         {
>           if (!visited)
> -           visited = pointer_set_create ();
> -         pointer_set_insert (visited, x);
> +           visited = new hash_set<rtx>;
> +         visited->add (x);
>           x = 0;
>         }
>
> @@ -3005,7 +3005,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>             continue;
>
>           /* If it's a comparison we've used before, skip it.  */
> -         if (visited && pointer_set_contains (visited, p->exp))
> +         if (visited && visited->contains (p->exp))
>             continue;
>
>           if (GET_CODE (p->exp) == COMPARE
> @@ -3087,7 +3087,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>    *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0);
>
>    if (visited)
> -    pointer_set_destroy (visited);
> +    delete visited;
>    return code;
>  }
>
> diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
> index 68ba70f..410efb1 100644
> --- a/gcc/fortran/openmp.c
> +++ b/gcc/fortran/openmp.c
> @@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "arith.h"
>  #include "match.h"
>  #include "parse.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>
>  /* Match an end of OpenMP directive.  End of OpenMP directive is optional
>     whitespace, followed by '\n' or comment '!'.  */
> @@ -3013,8 +3013,8 @@ resolve_omp_atomic (gfc_code *code)
>  struct omp_context
>  {
>    gfc_code *code;
> -  struct pointer_set_t *sharing_clauses;
> -  struct pointer_set_t *private_iterators;
> +  hash_set<gfc_symbol *> *sharing_clauses;
> +  hash_set<gfc_symbol *> *private_iterators;
>    struct omp_context *previous;
>  } *omp_current_ctx;
>  static gfc_code *omp_current_do_code;
> @@ -3057,8 +3057,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
>    int list;
>
>    ctx.code = code;
> -  ctx.sharing_clauses = pointer_set_create ();
> -  ctx.private_iterators = pointer_set_create ();
> +  ctx.sharing_clauses = new hash_set<gfc_symbol *>;
> +  ctx.private_iterators = new hash_set<gfc_symbol *>;
>    ctx.previous = omp_current_ctx;
>    omp_current_ctx = &ctx;
>
> @@ -3072,7 +3072,7 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
>        case OMP_LIST_REDUCTION:
>        case OMP_LIST_LINEAR:
>         for (n = omp_clauses->lists[list]; n; n = n->next)
> -         pointer_set_insert (ctx.sharing_clauses, n->sym);
> +         ctx.sharing_clauses->add (n->sym);
>         break;
>        default:
>         break;
> @@ -3097,8 +3097,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
>      }
>
>    omp_current_ctx = ctx.previous;
> -  pointer_set_destroy (ctx.sharing_clauses);
> -  pointer_set_destroy (ctx.private_iterators);
> +  delete ctx.sharing_clauses;
> +  delete ctx.private_iterators;
>  }
>
>
> @@ -3154,10 +3154,10 @@ gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym)
>    if (omp_current_ctx == NULL)
>      return;
>
> -  if (pointer_set_contains (omp_current_ctx->sharing_clauses, sym))
> +  if (omp_current_ctx->sharing_clauses->contains (sym))
>      return;
>
> -  if (! pointer_set_insert (omp_current_ctx->private_iterators, sym))
> +  if (! omp_current_ctx->private_iterators->add (sym))
>      {
>        gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
>        gfc_omp_namelist *p;
> diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
> index 8b56151..babe48f 100644
> --- a/gcc/fortran/trans-decl.c
> +++ b/gcc/fortran/trans-decl.c
> @@ -40,7 +40,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "cgraph.h"
>  #include "debug.h"
>  #include "gfortran.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "constructor.h"
>  #include "trans.h"
>  #include "trans-types.h"
> @@ -63,7 +63,7 @@ static GTY(()) tree parent_fake_result_decl;
>  static GTY(()) tree saved_function_decls;
>  static GTY(()) tree saved_parent_function_decls;
>
> -static struct pointer_set_t *nonlocal_dummy_decl_pset;
> +static hash_set<tree> *nonlocal_dummy_decl_pset;
>  static GTY(()) tree nonlocal_dummy_decls;
>
>  /* Holds the variable DECLs that are locals.  */
> @@ -1094,9 +1094,9 @@ gfc_nonlocal_dummy_array_decl (gfc_symbol *sym)
>    tree decl, dummy;
>
>    if (! nonlocal_dummy_decl_pset)
> -    nonlocal_dummy_decl_pset = pointer_set_create ();
> +    nonlocal_dummy_decl_pset = new hash_set<tree>;
>
> -  if (pointer_set_insert (nonlocal_dummy_decl_pset, sym->backend_decl))
> +  if (nonlocal_dummy_decl_pset->add (sym->backend_decl))
>      return;
>
>    dummy = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl);
> @@ -5861,7 +5861,7 @@ gfc_generate_function_code (gfc_namespace * ns)
>      {
>        BLOCK_VARS (DECL_INITIAL (fndecl))
>         = chainon (BLOCK_VARS (DECL_INITIAL (fndecl)), nonlocal_dummy_decls);
> -      pointer_set_destroy (nonlocal_dummy_decl_pset);
> +      delete nonlocal_dummy_decl_pset;
>        nonlocal_dummy_decls = NULL;
>        nonlocal_dummy_decl_pset = NULL;
>      }
> diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
> index b6f0495..f4f6757 100644
> --- a/gcc/gimple-walk.c
> +++ b/gcc/gimple-walk.c
> @@ -180,7 +180,7 @@ tree
>  walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
>                 struct walk_stmt_info *wi)
>  {
> -  struct pointer_set_t *pset = (wi) ? wi->pset : NULL;
> +  hash_set<tree> *pset = (wi) ? wi->pset : NULL;
>    unsigned i;
>    tree ret = NULL_TREE;
>
> diff --git a/gcc/gimple-walk.h b/gcc/gimple-walk.h
> index 555eb18..5b75fdc 100644
> --- a/gcc/gimple-walk.h
> +++ b/gcc/gimple-walk.h
> @@ -36,7 +36,7 @@ struct walk_stmt_info
>    /* Pointer map used to mark visited tree nodes when calling
>       walk_tree on each operand.  If set to NULL, duplicate tree nodes
>       will be visited more than once.  */
> -  struct pointer_set_t *pset;
> +  hash_set<tree> *pset;
>
>    /* Operand returned by the callbacks.  This is set when calling
>       walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> index 4ab36d0..c0ae7cc 100644
> --- a/gcc/gimplify.c
> +++ b/gcc/gimplify.c
> @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "coretypes.h"
>  #include "tree.h"
>  #include "expr.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "hash-table.h"
>  #include "basic-block.h"
> @@ -134,7 +135,7 @@ struct gimplify_omp_ctx
>  {
>    struct gimplify_omp_ctx *outer_context;
>    splay_tree variables;
> -  struct pointer_set_t *privatized_types;
> +  hash_set<tree> *privatized_types;
>    location_t location;
>    enum omp_clause_default_kind default_kind;
>    enum omp_region_type region_type;
> @@ -352,7 +353,7 @@ new_omp_context (enum omp_region_type region_type)
>    c = XCNEW (struct gimplify_omp_ctx);
>    c->outer_context = gimplify_omp_ctxp;
>    c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
> -  c->privatized_types = pointer_set_create ();
> +  c->privatized_types = new hash_set<tree>;
>    c->location = input_location;
>    c->region_type = region_type;
>    if ((region_type & ORT_TASK) == 0)
> @@ -369,7 +370,7 @@ static void
>  delete_omp_context (struct gimplify_omp_ctx *c)
>  {
>    splay_tree_delete (c->variables);
> -  pointer_set_destroy (c->privatized_types);
> +  delete c->privatized_types;
>    XDELETE (c);
>  }
>
> @@ -744,7 +745,7 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
>       copy their subtrees if we can make sure to do it only once.  */
>    if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
>      {
> -      if (data && !pointer_set_insert ((struct pointer_set_t *)data, t))
> +      if (data && !((hash_set<tree> *)data)->add (t))
>         ;
>        else
>         *walk_subtrees = 0;
> @@ -829,15 +830,14 @@ unshare_body (tree fndecl)
>    struct cgraph_node *cgn = cgraph_node::get (fndecl);
>    /* If the language requires deep unsharing, we need a pointer set to make
>       sure we don't repeatedly unshare subtrees of unshareable nodes.  */
> -  struct pointer_set_t *visited
> -    = lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
> +  hash_set<tree> *visited
> +    = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
>
>    copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
>    copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
>    copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
>
> -  if (visited)
> -    pointer_set_destroy (visited);
> +  delete visited;
>
>    if (cgn)
>      for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
> @@ -1733,7 +1733,7 @@ gimplify_conversion (tree *expr_p)
>  }
>
>  /* Nonlocal VLAs seen in the current function.  */
> -static struct pointer_set_t *nonlocal_vlas;
> +static hash_set<tree> *nonlocal_vlas;
>
>  /* The VAR_DECLs created for nonlocal VLAs for debug info purposes.  */
>  static tree nonlocal_vla_vars;
> @@ -1784,7 +1784,7 @@ gimplify_var_or_parm_decl (tree *expr_p)
>                  && (ctx->region_type == ORT_WORKSHARE
>                      || ctx->region_type == ORT_SIMD))
>             ctx = ctx->outer_context;
> -         if (!ctx && !pointer_set_insert (nonlocal_vlas, decl))
> +         if (!ctx && !nonlocal_vlas->add (decl))
>             {
>               tree copy = copy_node (decl);
>
> @@ -5463,7 +5463,7 @@ omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
>      return;
>    type = TYPE_MAIN_VARIANT (type);
>
> -  if (pointer_set_insert (ctx->privatized_types, type))
> +  if (ctx->privatized_types->add (type))
>      return;
>
>    switch (TREE_CODE (type))
> @@ -8766,7 +8766,7 @@ gimplify_body (tree fndecl, bool do_parms)
>
>    cgn = cgraph_node::get (fndecl);
>    if (cgn && cgn->origin)
> -    nonlocal_vlas = pointer_set_create ();
> +    nonlocal_vlas = new hash_set<tree>;
>
>    /* Make sure input_location isn't set to something weird.  */
>    input_location = DECL_SOURCE_LOCATION (fndecl);
> @@ -8830,7 +8830,7 @@ gimplify_body (tree fndecl, bool do_parms)
>                          nonlocal_vla_vars);
>           nonlocal_vla_vars = NULL_TREE;
>         }
> -      pointer_set_destroy (nonlocal_vlas);
> +      delete nonlocal_vlas;
>        nonlocal_vlas = NULL;
>      }
>
> diff --git a/gcc/godump.c b/gcc/godump.c
> index 2afd7f1..7566f4d 100644
> --- a/gcc/godump.c
> +++ b/gcc/godump.c
> @@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "diagnostic-core.h"
>  #include "tree.h"
>  #include "ggc.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "obstack.h"
>  #include "debug.h"
>  #include "wide-int-print.h"
> @@ -525,11 +525,11 @@ go_type_decl (tree decl, int local)
>  struct godump_container
>  {
>    /* DECLs that we have already seen.  */
> -  struct pointer_set_t *decls_seen;
> +  hash_set<tree> decls_seen;
>
>    /* Types which may potentially have to be defined as dummy
>       types.  */
> -  struct pointer_set_t *pot_dummy_types;
> +  hash_set<const char *> pot_dummy_types;
>
>    /* Go keywords.  */
>    htab_t keyword_hash;
> @@ -569,8 +569,8 @@ go_format_type (struct godump_container *container, tree type,
>    ob = &container->type_obstack;
>
>    if (TYPE_NAME (type) != NULL_TREE
> -      && (pointer_set_contains (container->decls_seen, type)
> -         || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
> +      && (container->decls_seen.contains (type)
> +         || container->decls_seen.contains (TYPE_NAME (type)))
>        && (AGGREGATE_TYPE_P (type)
>           || POINTER_TYPE_P (type)
>           || TREE_CODE (type) == FUNCTION_TYPE))
> @@ -590,7 +590,7 @@ go_format_type (struct godump_container *container, tree type,
>        return ret;
>      }
>
> -  pointer_set_insert (container->decls_seen, type);
> +  container->decls_seen.add (type);
>
>    switch (TREE_CODE (type))
>      {
> @@ -697,8 +697,7 @@ go_format_type (struct godump_container *container, tree type,
>              definition.  So this struct or union is a potential dummy
>              type.  */
>           if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
> -           pointer_set_insert (container->pot_dummy_types,
> -                               IDENTIFIER_POINTER (name));
> +           container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
>
>           return ret;
>          }
> @@ -948,10 +947,10 @@ go_output_typedef (struct godump_container *container, tree decl)
>       separately.  */
>    if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
>        && TYPE_SIZE (TREE_TYPE (decl)) != 0
> -      && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
> +      && !container->decls_seen.contains (TREE_TYPE (decl))
>        && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
> -         || !pointer_set_contains (container->decls_seen,
> -                                   TYPE_CANONICAL (TREE_TYPE (decl)))))
> +         || !container->decls_seen.contains
> +                                   (TYPE_CANONICAL (TREE_TYPE (decl)))))
>      {
>        tree element;
>
> @@ -988,10 +987,9 @@ go_output_typedef (struct godump_container *container, tree decl)
>           mhval->value = xstrdup (buf);
>           *slot = mhval;
>         }
> -      pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
> +      container->decls_seen.add (TREE_TYPE (decl));
>        if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
> -       pointer_set_insert (container->decls_seen,
> -                           TYPE_CANONICAL (TREE_TYPE (decl)));
> +       container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
>      }
>
>    if (DECL_NAME (decl) != NULL_TREE)
> @@ -1027,7 +1025,7 @@ go_output_typedef (struct godump_container *container, tree decl)
>                      size);
>         }
>
> -      pointer_set_insert (container->decls_seen, decl);
> +      container->decls_seen.add (decl);
>      }
>    else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
>      {
> @@ -1072,11 +1070,11 @@ go_output_var (struct godump_container *container, tree decl)
>  {
>    bool is_valid;
>
> -  if (pointer_set_contains (container->decls_seen, decl)
> -      || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
> +  if (container->decls_seen.contains (decl)
> +      || container->decls_seen.contains (DECL_NAME (decl)))
>      return;
> -  pointer_set_insert (container->decls_seen, decl);
> -  pointer_set_insert (container->decls_seen, DECL_NAME (decl));
> +  container->decls_seen.add (decl);
> +  container->decls_seen.add (DECL_NAME (decl));
>
>    is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
>    if (is_valid
> @@ -1103,11 +1101,10 @@ go_output_var (struct godump_container *container, tree decl)
>      {
>        tree type_name = TYPE_NAME (TREE_TYPE (decl));
>        if (TREE_CODE (type_name) == IDENTIFIER_NODE)
> -       pointer_set_insert (container->pot_dummy_types,
> -                           IDENTIFIER_POINTER (type_name));
> +       container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
>        else if (TREE_CODE (type_name) == TYPE_DECL)
> -       pointer_set_insert (container->pot_dummy_types,
> -                           IDENTIFIER_POINTER (DECL_NAME (type_name)));
> +       container->pot_dummy_types.add
> +                           (IDENTIFIER_POINTER (DECL_NAME (type_name)));
>      }
>  }
>
> @@ -1147,10 +1144,10 @@ keyword_hash_init (struct godump_container *container)
>
>  /* Traversing the pot_dummy_types and seeing which types are present
>     in the global types hash table and creating dummy definitions if
> -   not found.  This function is invoked by pointer_set_traverse.  */
> +   not found.  This function is invoked by hash_set::traverse.  */
>
> -static bool
> -find_dummy_types (const void *ptr, void *adata)
> +bool
> +find_dummy_types (const char *const &ptr, godump_container *adata)
>  {
>    struct godump_container *data = (struct godump_container *) adata;
>    const char *type = (const char *) ptr;
> @@ -1175,8 +1172,6 @@ go_finish (const char *filename)
>
>    real_debug_hooks->finish (filename);
>
> -  container.decls_seen = pointer_set_create ();
> -  container.pot_dummy_types = pointer_set_create ();
>    container.type_hash = htab_create (100, htab_hash_string,
>                                       string_hash_eq, NULL);
>    container.invalid_hash = htab_create (10, htab_hash_string,
> @@ -1211,11 +1206,9 @@ go_finish (const char *filename)
>    htab_traverse_noresize (macro_hash, go_print_macro, NULL);
>
>    /* To emit dummy definitions.  */
> -  pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
> -                        (void *) &container);
> +  container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
> +                        (&container);
>
> -  pointer_set_destroy (container.decls_seen);
> -  pointer_set_destroy (container.pot_dummy_types);
>    htab_delete (container.type_hash);
>    htab_delete (container.invalid_hash);
>    htab_delete (container.keyword_hash);
> diff --git a/gcc/hash-set.h b/gcc/hash-set.h
> new file mode 100644
> index 0000000..47bae9e
> --- /dev/null
> +++ b/gcc/hash-set.h
> @@ -0,0 +1,173 @@
> +/* A type-safe hash set.
> +   Copyright (C) 2014 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +
> +#ifndef hash_set_h
> +#define hash_set_h
> +
> +#include "hash-table.h"
> +
> +/* implement default behavior for traits when types allow it.  */
> +
> +struct default_hashset_traits
> +{
> +  /* Hashes the passed in key.  */
> +
> +  template<typename T>
> +  static hashval_t
> +  hash (T *p)
> +    {
> +      return uintptr_t(p) >> 3;
> +    }
> +
> +  template<typename T> static hashval_t hash(const T &v) { return v; }
> +
> +  /* Return true if the two keys passed as arguments are equal.  */
> +
> +  template<typename T>
> +  static bool
> +  equal (const T &a, const T &b)
> +    {
> +      return a == b;
> +    }
> +
> +  /* Called to dispose of the key before marking the entry as deleted.  */
> +
> +  template<typename T> static void remove (T &v) { v.~T (); }
> +
> +  /* Mark the passed in entry as being deleted.  */
> +
> +  template<typename T>
> +  static void
> +  mark_deleted (T *&e)
> +    {
> +      e = reinterpret_cast<void *> (1);
> +    }
> +
> +  /* Mark the passed in entry as being empty.  */
> +
> +  template<typename T>
> +  static void
> +  mark_empty (T *&e)
> +    {
> +      e = NULL;
> +    }
> +
> +  /* Return true if the passed in entry is marked as deleted.  */
> +
> +  template<typename T>
> +  static bool
> +  is_deleted (T *e)
> +    {
> +      return e == reinterpret_cast<void *> (1);
> +    }
> +
> +  /* Return true if the passed in entry is marked as empty.  */
> +
> +  template<typename T> static bool is_empty (T *e) { return e == NULL; }
> +};
> +
> +template<typename Key, typename Traits = default_hashset_traits>
> +class hash_set
> +{
> +  struct hash_entry
> +  {
> +    Key m_key;
> +
> +    typedef hash_entry value_type;
> +    typedef Key compare_type;
> +    typedef int store_values_directly;
> +
> +    static hashval_t hash (const hash_entry &e)
> +      {
> +               return Traits::hash (e.m_key);
> +      }
> +
> +    static bool equal (const hash_entry &a, const Key &b)
> +               {
> +         return Traits::equal (a.m_key, b);
> +               }
> +
> +    static void remove (hash_entry &e) { Traits::remove (e.m_key); }
> +
> +    static void
> +    mark_deleted (hash_entry &e)
> +      {
> +               Traits::mark_deleted (e.m_key);
> +      }
> +
> +    static bool is_deleted (const hash_entry &e)
> +      {
> +               return Traits::is_deleted (e.m_key);
> +      }
> +
> +    static void
> +    mark_empty (hash_entry &e)
> +      {
> +       Traits::mark_empty (e.m_key);
> +      }
> +
> +    static bool
> +    is_empty (const hash_entry &e)
> +      {
> +       return Traits::is_empty (e.m_key);
> +      }
> +  };
> +
> +public:
> +  explicit hash_set (size_t n = 13) : m_table (n) {}
> +
> +  /* If key k isn't already in the map add it to the map, and
> +     return false.  Otherwise return true.  */
> +
> +  bool add (const Key &k)
> +    {
> +      hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
> +                                                  INSERT);
> +      bool existed = !hash_entry::is_empty (*e);
> +      if (!existed)
> +       e->m_key = k;
> +
> +      return existed;
> +    }
> +
> +  /* if the passed in key is in the map return its value otherwise NULL.  */
> +
> +  bool contains (const Key &k)
> +    {
> +      hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
> +      return !Traits::is_empty (e.m_key);
> +    }
> +
> +  /* Call the call back on each pair of key and value with the passed in
> +     arg.  */
> +
> +  template<typename Arg, bool (*f)(const Key &, Arg)>
> +  void traverse (Arg a) const
> +    {
> +      for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
> +          iter != m_table.end (); ++iter)
> +       f ((*iter).m_key, a);
> +    }
> +
> +private:
> +  hash_table<hash_entry> m_table;
> +};
> +
> +#endif
> diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
> index 127d58d..70a70a7 100644
> --- a/gcc/ipa-devirt.c
> +++ b/gcc/ipa-devirt.c
> @@ -115,7 +115,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "cgraph.h"
>  #include "expr.h"
>  #include "tree-pass.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "target.h"
>  #include "hash-table.h"
>  #include "inchash.h"
> @@ -134,7 +134,8 @@ along with GCC; see the file COPYING3.  If not see
>  #include "stor-layout.h"
>  #include "intl.h"
>
> -static bool odr_types_equivalent_p (tree, tree, bool, bool *, pointer_set_t *);
> +static bool odr_types_equivalent_p (tree, tree, bool, bool *,
> +                                   hash_set<tree> *);
>
>  static bool odr_violation_reported = false;
>
> @@ -144,7 +145,7 @@ const ipa_polymorphic_call_context ipa_dummy_polymorphic_call_context
>     = {0, NULL, false, true};
>
>  /* Pointer set of all call targets appearing in the cache.  */
> -static pointer_set_t *cached_polymorphic_call_targets;
> +static hash_set<cgraph_node *> *cached_polymorphic_call_targets;
>
>  /* The node of type inheritance graph.  For each type unique in
>     One Defintion Rule (ODR) sense, we produce one node linking all
> @@ -163,7 +164,7 @@ struct GTY(()) odr_type_d
>    /* All equivalent types, if more than one.  */
>    vec<tree, va_gc> *types;
>    /* Set of all equivalent types, if NON-NULL.  */
> -  pointer_set_t * GTY((skip)) types_set;
> +  hash_set<tree> * GTY((skip)) types_set;
>
>    /* Unique ID indexing the type in odr_types array.  */
>    int id;
> @@ -409,7 +410,7 @@ odr_hasher::remove (value_type *v)
>    v->bases.release ();
>    v->derived_types.release ();
>    if (v->types_set)
> -    pointer_set_destroy (v->types_set);
> +    delete v->types_set;
>    ggc_free (v);
>  }
>
> @@ -439,7 +440,7 @@ set_type_binfo (tree type, tree binfo)
>  /* Compare T2 and T2 based on name or structure.  */
>
>  static bool
> -odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
> +odr_subtypes_equivalent_p (tree t1, tree t2, hash_set<tree> *visited)
>  {
>    bool an1, an2;
>
> @@ -473,7 +474,7 @@ odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
>        /* This should really be a pair hash, but for the moment we do not need
>          100% reliability and it would be better to compare all ODR types so
>          recursion here is needed only for component types.  */
> -      if (pointer_set_insert (visited, t1))
> +      if (visited->add (t1))
>         return true;
>        return odr_types_equivalent_p (t1, t2, false, NULL, visited);
>      }
> @@ -562,7 +563,7 @@ warn_types_mismatch (tree t1, tree t2)
>     gimple_canonical_types_compatible_p.  */
>
>  static bool
> -odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, pointer_set_t *visited)
> +odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, hash_set<tree> *visited)
>  {
>    /* Check first for the obvious case of pointer identity.  */
>    if (t1 == t2)
> @@ -938,7 +939,7 @@ add_type_duplicate (odr_type val, tree type)
>  {
>    bool build_bases = false;
>    if (!val->types_set)
> -    val->types_set = pointer_set_create ();
> +    val->types_set = new hash_set<tree>;
>
>    /* Always prefer complete type to be the leader.  */
>    if (!COMPLETE_TYPE_P (val->type)
> @@ -952,20 +953,20 @@ add_type_duplicate (odr_type val, tree type)
>      }
>
>    /* See if this duplicate is new.  */
> -  if (!pointer_set_insert (val->types_set, type))
> +  if (!val->types_set->add (type))
>      {
>        bool merge = true;
>        bool base_mismatch = false;
>        unsigned int i,j;
>        bool warned = false;
> -      pointer_set_t *visited = pointer_set_create ();
> +      hash_set<tree> visited;
>
>        gcc_assert (in_lto_p);
>        vec_safe_push (val->types, type);
>
>        /* First we compare memory layout.  */
>        if (!odr_types_equivalent_p (val->type, type, !flag_ltrans && !val->odr_violated,
> -                                  &warned, visited))
> +                                  &warned, &visited))
>         {
>           merge = false;
>           odr_violation_reported = true;
> @@ -980,7 +981,6 @@ add_type_duplicate (odr_type val, tree type)
>               putc ('\n',cgraph_dump_file);
>             }
>         }
> -      pointer_set_destroy (visited);
>
>        /* Next sanity check that bases are the same.  If not, we will end
>          up producing wrong answers.  */
> @@ -1356,7 +1356,7 @@ referenced_from_vtable_p (struct cgraph_node *node)
>
>  static void
>  maybe_record_node (vec <cgraph_node *> &nodes,
> -                  tree target, pointer_set_t *inserted,
> +                  tree target, hash_set<tree> *inserted,
>                    bool can_refer,
>                    bool *completep)
>  {
> @@ -1422,10 +1422,9 @@ maybe_record_node (vec <cgraph_node *> &nodes,
>      {
>        gcc_assert (!target_node->global.inlined_to);
>        gcc_assert (target_node->real_symbol_p ());
> -      if (!pointer_set_insert (inserted, target_node->decl))
> +      if (!inserted->add (target))
>         {
> -         pointer_set_insert (cached_polymorphic_call_targets,
> -                             target_node);
> +         cached_polymorphic_call_targets->add (target_node);
>           nodes.safe_push (target_node);
>         }
>      }
> @@ -1465,8 +1464,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
>                           HOST_WIDE_INT otr_token,
>                           tree outer_type,
>                           HOST_WIDE_INT offset,
> -                         pointer_set_t *inserted,
> -                         pointer_set_t *matched_vtables,
> +                         hash_set<tree> *inserted,
> +                         hash_set<tree> *matched_vtables,
>                           bool anonymous,
>                           bool *completep)
>  {
> @@ -1519,8 +1518,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
>         }
>        gcc_assert (inner_binfo);
>        if (bases_to_consider
> -         ? !pointer_set_contains (matched_vtables, BINFO_VTABLE (inner_binfo))
> -         : !pointer_set_insert (matched_vtables, BINFO_VTABLE (inner_binfo)))
> +         ? !matched_vtables->contains (BINFO_VTABLE (inner_binfo))
> +         : !matched_vtables->add (BINFO_VTABLE (inner_binfo)))
>         {
>           bool can_refer;
>           tree target = gimple_get_virt_method_for_binfo (otr_token,
> @@ -1559,8 +1558,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
>
>  static void
>  possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes,
> -                                    pointer_set_t *inserted,
> -                                    pointer_set_t *matched_vtables,
> +                                    hash_set<tree> *inserted,
> +                                    hash_set<tree> *matched_vtables,
>                                      tree otr_type,
>                                      odr_type type,
>                                      HOST_WIDE_INT otr_token,
> @@ -1684,7 +1683,7 @@ free_polymorphic_call_targets_hash ()
>      {
>        delete polymorphic_call_target_hash;
>        polymorphic_call_target_hash = NULL;
> -      pointer_set_destroy (cached_polymorphic_call_targets);
> +      delete cached_polymorphic_call_targets;
>        cached_polymorphic_call_targets = NULL;
>      }
>  }
> @@ -1695,7 +1694,7 @@ static void
>  devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
>  {
>    if (cached_polymorphic_call_targets
> -      && pointer_set_contains (cached_polymorphic_call_targets, n))
> +      && cached_polymorphic_call_targets->contains (n))
>      free_polymorphic_call_targets_hash ();
>  }
>
> @@ -2277,8 +2276,8 @@ record_targets_from_bases (tree otr_type,
>                            tree outer_type,
>                            HOST_WIDE_INT offset,
>                            vec <cgraph_node *> &nodes,
> -                          pointer_set_t *inserted,
> -                          pointer_set_t *matched_vtables,
> +                          hash_set<tree> *inserted,
> +                          hash_set<tree> *matched_vtables,
>                            bool *completep)
>  {
>    while (true)
> @@ -2319,7 +2318,7 @@ record_targets_from_bases (tree otr_type,
>           return;
>         }
>        gcc_assert (base_binfo);
> -      if (!pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo)))
> +      if (!matched_vtables->add (BINFO_VTABLE (base_binfo)))
>         {
>           bool can_refer;
>           tree target = gimple_get_virt_method_for_binfo (otr_token,
> @@ -2327,7 +2326,7 @@ record_targets_from_bases (tree otr_type,
>                                                           &can_refer);
>           if (!target || ! DECL_CXX_DESTRUCTOR_P (target))
>             maybe_record_node (nodes, target, inserted, can_refer, completep);
> -         pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo));
> +         matched_vtables->add (BINFO_VTABLE (base_binfo));
>         }
>      }
>  }
> @@ -2377,8 +2376,6 @@ possible_polymorphic_call_targets (tree otr_type,
>                                    int *nonconstruction_targetsp)
>  {
>    static struct cgraph_node_hook_list *node_removal_hook_holder;
> -  pointer_set_t *inserted;
> -  pointer_set_t *matched_vtables;
>    vec <cgraph_node *> nodes = vNULL;
>    vec <tree> bases_to_consider = vNULL;
>    odr_type type, outer_type;
> @@ -2457,7 +2454,7 @@ possible_polymorphic_call_targets (tree otr_type,
>    /* Initialize query cache.  */
>    if (!cached_polymorphic_call_targets)
>      {
> -      cached_polymorphic_call_targets = pointer_set_create ();
> +      cached_polymorphic_call_targets = new hash_set<cgraph_node *>;
>        polymorphic_call_target_hash
>                 = new polymorphic_call_target_hash_type (23);
>        if (!node_removal_hook_holder)
> @@ -2496,8 +2493,8 @@ possible_polymorphic_call_targets (tree otr_type,
>    (*slot)->otr_token = otr_token;
>    (*slot)->context = context;
>
> -  inserted = pointer_set_create ();
> -  matched_vtables = pointer_set_create ();
> +  hash_set<tree> inserted;
> +  hash_set<tree> matched_vtables;
>
>    /* First see virtual method of type itself.  */
>    binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type),
> @@ -2526,7 +2523,7 @@ possible_polymorphic_call_targets (tree otr_type,
>
>    /* If OUTER_TYPE is abstract, we know we are not seeing its instance.  */
>    if (type_possibly_instantiated_p (outer_type->type))
> -    maybe_record_node (nodes, target, inserted, can_refer, &complete);
> +    maybe_record_node (nodes, target, &inserted, can_refer, &complete);
>    else
>      {
>        skipped = true;
> @@ -2534,7 +2531,7 @@ possible_polymorphic_call_targets (tree otr_type,
>      }
>
>    if (binfo)
> -    pointer_set_insert (matched_vtables, BINFO_VTABLE (binfo));
> +    matched_vtables.add (BINFO_VTABLE (binfo));
>
>    /* Next walk recursively all derived types.  */
>    if (context.maybe_derived_type)
> @@ -2544,8 +2541,8 @@ possible_polymorphic_call_targets (tree otr_type,
>        if (!type->all_derivations_known)
>         complete = false;
>        for (i = 0; i < outer_type->derived_types.length(); i++)
> -       possible_polymorphic_call_targets_1 (nodes, inserted,
> -                                            matched_vtables,
> +       possible_polymorphic_call_targets_1 (nodes, &inserted,
> +                                            &matched_vtables,
>                                              otr_type,
>                                              outer_type->derived_types[i],
>                                              otr_token, outer_type->type,
> @@ -2571,12 +2568,12 @@ possible_polymorphic_call_targets (tree otr_type,
>               || (context.maybe_derived_type
>                   && !type_all_derivations_known_p (outer_type->type))))
>         record_targets_from_bases (otr_type, otr_token, outer_type->type,
> -                                  context.offset, nodes, inserted,
> -                                  matched_vtables, &complete);
> +                                  context.offset, nodes, &inserted,
> +                                  &matched_vtables, &complete);
>        if (skipped)
> -        maybe_record_node (nodes, target, inserted, can_refer, &complete);
> +        maybe_record_node (nodes, target, &inserted, can_refer, &complete);
>        for (i = 0; i < bases_to_consider.length(); i++)
> -        maybe_record_node (nodes, bases_to_consider[i], inserted, can_refer, &complete);
> +        maybe_record_node (nodes, bases_to_consider[i], &inserted, can_refer, &complete);
>      }
>    bases_to_consider.release();
>
> @@ -2587,8 +2584,6 @@ possible_polymorphic_call_targets (tree otr_type,
>    if (nonconstruction_targetsp)
>      *nonconstruction_targetsp = (*slot)->nonconstruction_targets;
>
> -  pointer_set_destroy (inserted);
> -  pointer_set_destroy (matched_vtables);
>    timevar_pop (TV_IPA_VIRTUAL_CALL);
>    return nodes;
>  }
> @@ -2744,7 +2739,7 @@ static unsigned int
>  ipa_devirt (void)
>  {
>    struct cgraph_node *n;
> -  struct pointer_set_t *bad_call_targets = pointer_set_create ();
> +  hash_set<void *> bad_call_targets;
>    struct cgraph_edge *e;
>
>    int npolymorphic = 0, nspeculated = 0, nconverted = 0, ncold = 0;
> @@ -2792,8 +2787,7 @@ ipa_devirt (void)
>                 if (!dump_file)
>                   continue;
>               }
> -           if (pointer_set_contains (bad_call_targets,
> -                                     cache_token))
> +           if (bad_call_targets.contains (cache_token))
>               {
>                 if (dump_file)
>                   fprintf (dump_file, "Target list is known to be useless\n\n");
> @@ -2818,7 +2812,7 @@ ipa_devirt (void)
>                 }
>             if (!likely_target)
>               {
> -               pointer_set_insert (bad_call_targets, cache_token);
> +               bad_call_targets.add (cache_token);
>                 continue;
>               }
>             /* This is reached only when dumping; check if we agree or disagree
> @@ -2905,7 +2899,6 @@ ipa_devirt (void)
>        if (update)
>         inline_update_overall_summary (n);
>      }
> -  pointer_set_destroy (bad_call_targets);
>
>    if (dump_file)
>      fprintf (dump_file,
> diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
> index 2c281be..b964502 100644
> --- a/gcc/ipa-pure-const.c
> +++ b/gcc/ipa-pure-const.c
> @@ -65,8 +65,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-scalar-evolution.h"
>  #include "intl.h"
>  #include "opts.h"
> -
> -static struct pointer_set_t *visited_nodes;
> +#include "hash-set.h"
>
>  /* Lattice values for const and pure functions.  Everything starts out
>     being const, then may drop to pure and then neither depending on
> @@ -133,13 +132,13 @@ function_always_visible_to_compiler_p (tree decl)
>
>  /* Emit suggestion about attribute ATTRIB_NAME for DECL.  KNOWN_FINITE
>     is true if the function is known to be finite.  The diagnostic is
> -   controlled by OPTION.  WARNED_ABOUT is a pointer_set unique for
> +   controlled by OPTION.  WARNED_ABOUT is a hash_set<tree> unique for
>     OPTION, this function may initialize it and it is always returned
>     by the function.  */
>
> -static struct pointer_set_t *
> +static hash_set<tree> *
>  suggest_attribute (int option, tree decl, bool known_finite,
> -                  struct pointer_set_t *warned_about,
> +                  hash_set<tree> *warned_about,
>                    const char * attrib_name)
>  {
>    if (!option_enabled (option, &global_options))
> @@ -149,10 +148,10 @@ suggest_attribute (int option, tree decl, bool known_finite,
>      return warned_about;
>
>    if (!warned_about)
> -    warned_about = pointer_set_create ();
> -  if (pointer_set_contains (warned_about, decl))
> +    warned_about = new hash_set<tree>;
> +  if (warned_about->contains (decl))
>      return warned_about;
> -  pointer_set_insert (warned_about, decl);
> +  warned_about->add (decl);
>    warning_at (DECL_SOURCE_LOCATION (decl),
>               option,
>               known_finite
> @@ -168,7 +167,7 @@ suggest_attribute (int option, tree decl, bool known_finite,
>  static void
>  warn_function_pure (tree decl, bool known_finite)
>  {
> -  static struct pointer_set_t *warned_about;
> +  static hash_set<tree> *warned_about;
>
>    warned_about
>      = suggest_attribute (OPT_Wsuggest_attribute_pure, decl,
> @@ -181,7 +180,7 @@ warn_function_pure (tree decl, bool known_finite)
>  static void
>  warn_function_const (tree decl, bool known_finite)
>  {
> -  static struct pointer_set_t *warned_about;
> +  static hash_set<tree> *warned_about;
>    warned_about
>      = suggest_attribute (OPT_Wsuggest_attribute_const, decl,
>                          known_finite, warned_about, "const");
> @@ -190,7 +189,7 @@ warn_function_const (tree decl, bool known_finite)
>  static void
>  warn_function_noreturn (tree decl)
>  {
> -  static struct pointer_set_t *warned_about;
> +  static hash_set<tree> *warned_about;
>    if (!lang_hooks.missing_noreturn_ok_p (decl)
>        && targetm.warn_func_return (decl))
>      warned_about
> @@ -846,11 +845,8 @@ add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
>       static declarations.  We do not need to scan them more than once
>       since all we would be interested in are the addressof
>       operations.  */
> -  visited_nodes = pointer_set_create ();
>    if (node->get_availability () > AVAIL_INTERPOSABLE)
>      set_function_state (node, analyze_function (node, true));
> -  pointer_set_destroy (visited_nodes);
> -  visited_nodes = NULL;
>  }
>
>  /* Called when new clone is inserted to callgraph late.  */
> @@ -912,12 +908,6 @@ pure_const_generate_summary (void)
>
>    register_hooks ();
>
> -  /* There are some shared nodes, in particular the initializers on
> -     static declarations.  We do not need to scan them more than once
> -     since all we would be interested in are the addressof
> -     operations.  */
> -  visited_nodes = pointer_set_create ();
> -
>    /* Process all of the functions.
>
>       We process AVAIL_INTERPOSABLE functions.  We can not use the results
> @@ -927,9 +917,6 @@ pure_const_generate_summary (void)
>    FOR_EACH_DEFINED_FUNCTION (node)
>      if (node->get_availability () >= AVAIL_INTERPOSABLE)
>        set_function_state (node, analyze_function (node, true));
> -
> -  pointer_set_destroy (visited_nodes);
> -  visited_nodes = NULL;
>  }
>
>
> diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
> index 4720ee9..bca2bc7 100644
> --- a/gcc/ipa-visibility.c
> +++ b/gcc/ipa-visibility.c
> @@ -687,12 +687,11 @@ function_and_variable_visibility (bool whole_program)
>               }
>           if (found)
>             {
> -             struct pointer_set_t *visited_nodes = pointer_set_create ();
> +             hash_set<tree> visited_nodes;
>
>               vnode->get_constructor ();
>               walk_tree (&DECL_INITIAL (vnode->decl),
> -                        update_vtable_references, NULL, visited_nodes);
> -             pointer_set_destroy (visited_nodes);
> +                        update_vtable_references, NULL, &visited_nodes);
>               vnode->remove_all_references ();
>               record_references_in_initializer (vnode->decl, false);
>             }
> diff --git a/gcc/ipa.c b/gcc/ipa.c
> index 8198b17..1081e89 100644
> --- a/gcc/ipa.c
> +++ b/gcc/ipa.c
> @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "cgraph.h"
>  #include "tree-pass.h"
>  #include "hash-map.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "gimple-expr.h"
>  #include "gimplify.h"
>  #include "flags.h"
> @@ -84,14 +84,14 @@ update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined
>
>  static void
>  enqueue_node (symtab_node *node, symtab_node **first,
> -             struct pointer_set_t *reachable)
> +             hash_set<symtab_node *> *reachable)
>  {
>    /* Node is still in queue; do nothing.  */
>    if (node->aux && node->aux != (void *) 2)
>      return;
>    /* Node was already processed as unreachable, re-enqueue
>       only if it became reachable now.  */
> -  if (node->aux == (void *)2 && !pointer_set_contains (reachable, node))
> +  if (node->aux == (void *)2 && !reachable->contains (node))
>      return;
>    node->aux = *first;
>    *first = node;
> @@ -103,7 +103,7 @@ static void
>  process_references (symtab_node *snode,
>                     symtab_node **first,
>                     bool before_inlining_p,
> -                   struct pointer_set_t *reachable)
> +                   hash_set<symtab_node *> *reachable)
>  {
>    int i;
>    struct ipa_ref *ref = NULL;
> @@ -124,7 +124,7 @@ process_references (symtab_node *snode,
>                       && flag_wpa
>                       && ctor_for_folding (node->decl)
>                          != error_mark_node))))
> -       pointer_set_insert (reachable, node);
> +       reachable->add (node);
>        enqueue_node (node, first, reachable);
>      }
>  }
> @@ -138,10 +138,11 @@ process_references (symtab_node *snode,
>     possible.  */
>
>  static void
> -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
>                                struct cgraph_edge *edge,
>                                symtab_node **first,
> -                              pointer_set_t *reachable, bool before_inlining_p)
> +                              hash_set<symtab_node *> *reachable,
> +                              bool before_inlining_p)
>  {
>    unsigned int i;
>    void *cache_token;
> @@ -150,8 +151,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
>      = possible_polymorphic_call_targets
>         (edge, &final, &cache_token);
>
> -  if (!pointer_set_insert (reachable_call_targets,
> -                          cache_token))
> +  if (!reachable_call_targets->add (cache_token))
>      {
>        for (i = 0; i < targets.length (); i++)
>         {
> @@ -172,7 +172,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
>                    && (cgraph_state < CGRAPH_STATE_IPA_SSA
>                        || !lookup_attribute ("always_inline",
>                                              DECL_ATTRIBUTES (n->decl)))))
> -            pointer_set_insert (reachable, n);
> +            reachable->add (n);
>
>           /* Even after inlining we want to keep the possible targets in the
>              boundary, so late passes can still produce direct call even if
> @@ -276,9 +276,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>    struct cgraph_node *node, *next;
>    varpool_node *vnode, *vnext;
>    bool changed = false;
> -  struct pointer_set_t *reachable = pointer_set_create ();
> -  struct pointer_set_t *body_needed_for_clonning = pointer_set_create ();
> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> +  hash_set<symtab_node *> reachable;
> +  hash_set<tree> body_needed_for_clonning;
> +  hash_set<void *> reachable_call_targets;
>
>    timevar_push (TV_IPA_UNREACHABLE);
>    if (optimize && flag_devirtualize)
> @@ -304,8 +304,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>           && !node->can_remove_if_no_direct_calls_and_refs_p ())
>         {
>           gcc_assert (!node->global.inlined_to);
> -         pointer_set_insert (reachable, node);
> -         enqueue_node (node, &first, reachable);
> +         reachable.add (node);
> +         enqueue_node (node, &first, &reachable);
>         }
>        else
>         gcc_assert (!node->aux);
> @@ -316,14 +316,14 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>      if (!vnode->can_remove_if_no_refs_p()
>         && !vnode->in_other_partition)
>        {
> -       pointer_set_insert (reachable, vnode);
> -       enqueue_node (vnode, &first, reachable);
> +       reachable.add (vnode);
> +       enqueue_node (vnode, &first, &reachable);
>        }
>
>    /* Perform reachability analysis.  */
>    while (first != (symtab_node *) (void *) 1)
>      {
> -      bool in_boundary_p = !pointer_set_contains (reachable, first);
> +      bool in_boundary_p = !reachable.contains (first);
>        symtab_node *node = first;
>
>        first = (symtab_node *)first->aux;
> @@ -340,7 +340,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>               struct cgraph_node *origin_node
>               = cgraph_node::get_create (DECL_ABSTRACT_ORIGIN (node->decl));
>               origin_node->used_as_abstract_origin = true;
> -             enqueue_node (origin_node, &first, reachable);
> +             enqueue_node (origin_node, &first, &reachable);
>             }
>           /* If any symbol in a comdat group is reachable, force
>              all externally visible symbols in the same comdat
> @@ -353,11 +353,11 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>                    next != node;
>                    next = next->same_comdat_group)
>                 if (!next->comdat_local_p ()
> -                   && !pointer_set_insert (reachable, next))
> -                 enqueue_node (next, &first, reachable);
> +                   && !reachable.add (next))
> +                 enqueue_node (next, &first, &reachable);
>             }
>           /* Mark references as reachable.  */
> -         process_references (node, &first, before_inlining_p, reachable);
> +         process_references (node, &first, before_inlining_p, &reachable);
>         }
>
>        if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
> @@ -375,8 +375,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>                     {
>                       next = e->next_callee;
>                       if (e->indirect_info->polymorphic)
> -                       walk_polymorphic_call_targets (reachable_call_targets,
> -                                                      e, &first, reachable,
> +                       walk_polymorphic_call_targets (&reachable_call_targets,
> +                                                      e, &first, &reachable,
>                                                        before_inlining_p);
>                     }
>                 }
> @@ -394,17 +394,16 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>                       if (DECL_EXTERNAL (e->callee->decl)
>                           && e->callee->alias
>                           && before_inlining_p)
> -                       pointer_set_insert (reachable,
> -                                           e->callee->function_symbol ());
> -                     pointer_set_insert (reachable, e->callee);
> +                       reachable.add (e->callee->function_symbol ());
> +                     reachable.add (e->callee);
>                     }
> -                 enqueue_node (e->callee, &first, reachable);
> +                 enqueue_node (e->callee, &first, &reachable);
>                 }
>
>               /* When inline clone exists, mark body to be preserved so when removing
>                  offline copy of the function we don't kill it.  */
>               if (cnode->global.inlined_to)
> -               pointer_set_insert (body_needed_for_clonning, cnode->decl);
> +               body_needed_for_clonning.add (cnode->decl);
>
>               /* For non-inline clones, force their origins to the boundary and ensure
>                  that body is not removed.  */
> @@ -414,8 +413,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>                   cnode = cnode->clone_of;
>                   if (noninline)
>                     {
> -                     pointer_set_insert (body_needed_for_clonning, cnode->decl);
> -                     enqueue_node (cnode, &first, reachable);
> +                     body_needed_for_clonning.add (cnode->decl);
> +                     enqueue_node (cnode, &first, &reachable);
>                     }
>                 }
>
> @@ -429,8 +428,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>                    next;
>                    next = next->simdclone->next_clone)
>                 if (in_boundary_p
> -                   || !pointer_set_insert (reachable, next))
> -                 enqueue_node (next, &first, reachable);
> +                   || !reachable.add (next))
> +                 enqueue_node (next, &first, &reachable);
>             }
>         }
>        /* When we see constructor of external variable, keep referred nodes in the
> @@ -444,7 +443,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>         {
>           struct ipa_ref *ref = NULL;
>           for (int i = 0; node->iterate_reference (i, ref); i++)
> -           enqueue_node (ref->referred, &first, reachable);
> +           enqueue_node (ref->referred, &first, &reachable);
>         }
>      }
>
> @@ -462,9 +461,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>           changed = true;
>         }
>        /* If node is unreachable, remove its body.  */
> -      else if (!pointer_set_contains (reachable, node))
> +      else if (!reachable.contains (node))
>          {
> -         if (!pointer_set_contains (body_needed_for_clonning, node->decl))
> +         if (!body_needed_for_clonning.contains (node->decl))
>             node->release_body ();
>           else if (!node->clone_of)
>             gcc_assert (in_lto_p || DECL_RESULT (node->decl));
> @@ -530,7 +529,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>           vnode->remove ();
>           changed = true;
>         }
> -      else if (!pointer_set_contains (reachable, vnode))
> +      else if (!reachable.contains (vnode))
>          {
>           tree init;
>           if (vnode->definition)
> @@ -557,10 +556,6 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>         vnode->aux = NULL;
>      }
>
> -  pointer_set_destroy (reachable);
> -  pointer_set_destroy (body_needed_for_clonning);
> -  pointer_set_destroy (reachable_call_targets);
> -
>    /* Now update address_taken flags and try to promote functions to be local.  */
>    if (file)
>      fprintf (file, "\nClearing address taken flags:");
> diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
> index b1fcf67..42b0790 100644
> --- a/gcc/lto-cgraph.c
> +++ b/gcc/lto-cgraph.c
> @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "params.h"
>  #include "input.h"
>  #include "hashtab.h"
> +#include "hash-set.h"
>  #include "langhooks.h"
>  #include "bitmap.h"
>  #include "function.h"
> @@ -819,7 +820,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
>    int i;
>    lto_symtab_encoder_t encoder;
>    lto_symtab_encoder_iterator lsei;
> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> +  hash_set<void *> reachable_call_targets;
>
>    encoder = lto_symtab_encoder_new (false);
>
> @@ -902,8 +903,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
>               vec <cgraph_node *>targets
>                 = possible_polymorphic_call_targets
>                     (edge, &final, &cache_token);
> -             if (!pointer_set_insert (reachable_call_targets,
> -                                      cache_token))
> +             if (!reachable_call_targets.add (cache_token))
>                 {
>                   for (i = 0; i < targets.length (); i++)
>                     {
> @@ -923,7 +923,6 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
>             }
>      }
>    lto_symtab_encoder_delete (in_encoder);
> -  pointer_set_destroy (reachable_call_targets);
>    return encoder;
>  }
>
> diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
> index 271fbd5..3fd9147 100644
> --- a/gcc/lto-streamer-out.c
> +++ b/gcc/lto-streamer-out.c
> @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "params.h"
>  #include "input.h"
>  #include "hashtab.h"
> +#include "hash-set.h"
>  #include "basic-block.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
> @@ -2433,7 +2434,7 @@ lto_out_decl_state_written_size (struct lto_out_decl_state *state)
>  static void
>  write_symbol (struct streamer_tree_cache_d *cache,
>               struct lto_output_stream *stream,
> -             tree t, struct pointer_set_t *seen, bool alias)
> +             tree t, hash_set<const char *> *seen, bool alias)
>  {
>    const char *name;
>    enum gcc_plugin_symbol_kind kind;
> @@ -2461,9 +2462,8 @@ write_symbol (struct streamer_tree_cache_d *cache,
>       same name manipulations that ASM_OUTPUT_LABELREF does. */
>    name = IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name) (name));
>
> -  if (pointer_set_contains (seen, name))
> +  if (seen->add (name))
>      return;
> -  pointer_set_insert (seen, name);
>
>    streamer_tree_cache_lookup (cache, t, &slot_num);
>    gcc_assert (slot_num != (unsigned)-1);
> @@ -2588,7 +2588,6 @@ produce_symtab (struct output_block *ob)
>  {
>    struct streamer_tree_cache_d *cache = ob->writer_cache;
>    char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
> -  struct pointer_set_t *seen;
>    struct lto_output_stream stream;
>    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
>    lto_symtab_encoder_iterator lsei;
> @@ -2596,7 +2595,7 @@ produce_symtab (struct output_block *ob)
>    lto_begin_section (section_name, false);
>    free (section_name);
>
> -  seen = pointer_set_create ();
> +  hash_set<const char *> seen;
>    memset (&stream, 0, sizeof (stream));
>
>    /* Write the symbol table.
> @@ -2609,7 +2608,7 @@ produce_symtab (struct output_block *ob)
>
>        if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
>         continue;
> -      write_symbol (cache, &stream, node->decl, seen, false);
> +      write_symbol (cache, &stream, node->decl, &seen, false);
>      }
>    for (lsei = lsei_start (encoder);
>         !lsei_end_p (lsei); lsei_next (&lsei))
> @@ -2618,11 +2617,10 @@ produce_symtab (struct output_block *ob)
>
>        if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
>         continue;
> -      write_symbol (cache, &stream, node->decl, seen, false);
> +      write_symbol (cache, &stream, node->decl, &seen, false);
>      }
>
>    lto_write_stream (&stream);
> -  pointer_set_destroy (seen);
>
>    lto_end_section ();
>  }
> diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
> index cb08a88..a5bcf92 100644
> --- a/gcc/lto/lto-partition.c
> +++ b/gcc/lto/lto-partition.c
> @@ -66,7 +66,7 @@ free_ltrans_partitions (void)
>    for (idx = 0; ltrans_partitions.iterate (idx, &part); idx++)
>      {
>        if (part->initializers_visited)
> -       pointer_set_destroy (part->initializers_visited);
> +       delete part->initializers_visited;
>        /* Symtab encoder is freed after streaming.  */
>        free (part);
>      }
> @@ -101,8 +101,8 @@ add_references_to_partition (ltrans_partition part, symtab_node *node)
>              && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
>        {
>         if (!part->initializers_visited)
> -         part->initializers_visited = pointer_set_create ();
> -       if (!pointer_set_insert (part->initializers_visited, ref->referred))
> +         part->initializers_visited = new hash_set<symtab_node *>;
> +       if (!part->initializers_visited->add (ref->referred))
>           add_references_to_partition (part, ref->referred);
>        }
>  }
> @@ -250,7 +250,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes)
>
>        /* After UNDO we no longer know what was visited.  */
>        if (partition->initializers_visited)
> -       pointer_set_destroy (partition->initializers_visited);
> +       delete partition->initializers_visited;
>        partition->initializers_visited = NULL;
>
>        if (!node->alias && (cnode = dyn_cast <cgraph_node *> (node)))
> diff --git a/gcc/lto/lto-partition.h b/gcc/lto/lto-partition.h
> index 8db61b3..50ec2fa 100644
> --- a/gcc/lto/lto-partition.h
> +++ b/gcc/lto/lto-partition.h
> @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
>  along with GCC; see the file COPYING3.  If not see
>  <http://www.gnu.org/licenses/>.  */
>
> +#include "hash-set.h"
>
>  /* Structure describing ltrans partitions.  */
>
> @@ -25,7 +26,7 @@ struct ltrans_partition_def
>    lto_symtab_encoder_t encoder;
>    const char * name;
>    int insns;
> -  pointer_set_t *initializers_visited;
> +  hash_set<symtab_node *> *initializers_visited;
>  };
>
>  typedef struct ltrans_partition_def *ltrans_partition;
> diff --git a/gcc/stmt.c b/gcc/stmt.c
> index 0aae085..55ec279 100644
> --- a/gcc/stmt.c
> +++ b/gcc/stmt.c
> @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "predict.h"
>  #include "optabs.h"
>  #include "target.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "basic-block.h"
>  #include "tree-ssa-alias.h"
> @@ -1183,7 +1184,7 @@ expand_case (gimple stmt)
>       how to expand this switch().  */
>    uniq = 0;
>    count = 0;
> -  struct pointer_set_t *seen_labels = pointer_set_create ();
> +  hash_set<tree> seen_labels;
>    compute_cases_per_edge (stmt);
>
>    for (i = ncases - 1; i >= 1; --i)
> @@ -1203,7 +1204,7 @@ expand_case (gimple stmt)
>
>        /* If we have not seen this label yet, then increase the
>          number of unique case node targets seen.  */
> -      if (!pointer_set_insert (seen_labels, lab))
> +      if (!seen_labels.add (lab))
>         uniq++;
>
>        /* The bounds on the case range, LOW and HIGH, have to be converted
> @@ -1231,7 +1232,6 @@ expand_case (gimple stmt)
>            case_edge->probability / (intptr_t)(case_edge->aux),
>            case_node_pool);
>      }
> -  pointer_set_destroy (seen_labels);
>    reset_out_edges_aux (bb);
>
>    /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> index 6fee8a4..e034762 100644
> --- a/gcc/tree-cfg.c
> +++ b/gcc/tree-cfg.c
> @@ -4691,7 +4691,7 @@ tree_node_can_be_shared (tree t)
>  static tree
>  verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
>  {
> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> +  hash_set<void *> *visited = (hash_set<void *> *) data;
>
>    if (tree_node_can_be_shared (*tp))
>      {
> @@ -4699,7 +4699,7 @@ verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
>        return NULL;
>      }
>
> -  if (pointer_set_insert (visited, *tp))
> +  if (visited->add (*tp))
>      return *tp;
>
>    return NULL;
> @@ -4719,9 +4719,9 @@ static int
>  verify_eh_throw_stmt_node (void **slot, void *data)
>  {
>    struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> +  hash_set<void *> *visited = (hash_set<void *> *) data;
>
> -  if (!pointer_set_contains (visited, node->stmt))
> +  if (!visited->contains (node->stmt))
>      {
>        error ("dead STMT in EH table");
>        debug_gimple_stmt (node->stmt);
> @@ -4733,11 +4733,11 @@ verify_eh_throw_stmt_node (void **slot, void *data)
>  /* Verify if the location LOCs block is in BLOCKS.  */
>
>  static bool
> -verify_location (pointer_set_t *blocks, location_t loc)
> +verify_location (hash_set<tree> *blocks, location_t loc)
>  {
>    tree block = LOCATION_BLOCK (loc);
>    if (block != NULL_TREE
> -      && !pointer_set_contains (blocks, block))
> +      && !blocks->contains (block))
>      {
>        error ("location references block not in block tree");
>        return true;
> @@ -4770,7 +4770,7 @@ verify_expr_no_block (tree *tp, int *walk_subtrees, void *)
>  static tree
>  verify_expr_location_1 (tree *tp, int *walk_subtrees, void *data)
>  {
> -  struct pointer_set_t *blocks = (struct pointer_set_t *) data;
> +  hash_set<tree> *blocks = (hash_set<tree> *) data;
>
>    if (TREE_CODE (*tp) == VAR_DECL
>        && DECL_HAS_DEBUG_EXPR_P (*tp))
> @@ -4816,12 +4816,12 @@ verify_expr_location (tree *tp, int *walk_subtrees, void *data)
>  /* Insert all subblocks of BLOCK into BLOCKS and recurse.  */
>
>  static void
> -collect_subblocks (pointer_set_t *blocks, tree block)
> +collect_subblocks (hash_set<tree> *blocks, tree block)
>  {
>    tree t;
>    for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
>      {
> -      pointer_set_insert (blocks, t);
> +      blocks->add (t);
>        collect_subblocks (blocks, t);
>      }
>  }
> @@ -4833,18 +4833,17 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>  {
>    basic_block bb;
>    bool err = false;
> -  struct pointer_set_t *visited, *visited_stmts, *blocks;
>
>    timevar_push (TV_TREE_STMT_VERIFY);
> -  visited = pointer_set_create ();
> -  visited_stmts = pointer_set_create ();
> +  hash_set<void *> visited;
> +  hash_set<gimple> visited_stmts;
>
>    /* Collect all BLOCKs referenced by the BLOCK tree of FN.  */
> -  blocks = pointer_set_create ();
> +  hash_set<tree> blocks;
>    if (DECL_INITIAL (fn->decl))
>      {
> -      pointer_set_insert (blocks, DECL_INITIAL (fn->decl));
> -      collect_subblocks (blocks, DECL_INITIAL (fn->decl));
> +      blocks.add (DECL_INITIAL (fn->decl));
> +      collect_subblocks (&blocks, DECL_INITIAL (fn->decl));
>      }
>
>    FOR_EACH_BB_FN (bb, fn)
> @@ -4857,7 +4856,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>           bool err2 = false;
>           unsigned i;
>
> -         pointer_set_insert (visited_stmts, phi);
> +         visited_stmts.add (phi);
>
>           if (gimple_bb (phi) != bb)
>             {
> @@ -4878,7 +4877,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>             {
>               tree arg = gimple_phi_arg_def (phi, i);
>               tree addr = walk_tree (&arg, verify_node_sharing_1,
> -                                    visited, NULL);
> +                                    &visited, NULL);
>               if (addr)
>                 {
>                   error ("incorrect sharing of tree nodes");
> @@ -4892,13 +4891,13 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>                   error ("virtual PHI with argument locations");
>                   err2 = true;
>                 }
> -             addr = walk_tree (&arg, verify_expr_location_1, blocks, NULL);
> +             addr = walk_tree (&arg, verify_expr_location_1, &blocks, NULL);
>               if (addr)
>                 {
>                   debug_generic_expr (addr);
>                   err2 = true;
>                 }
> -             err2 |= verify_location (blocks, loc);
> +             err2 |= verify_location (&blocks, loc);
>             }
>
>           if (err2)
> @@ -4914,7 +4913,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>           tree addr;
>           int lp_nr;
>
> -         pointer_set_insert (visited_stmts, stmt);
> +         visited_stmts.add (stmt);
>
>           if (gimple_bb (stmt) != bb)
>             {
> @@ -4923,10 +4922,10 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>             }
>
>           err2 |= verify_gimple_stmt (stmt);
> -         err2 |= verify_location (blocks, gimple_location (stmt));
> +         err2 |= verify_location (&blocks, gimple_location (stmt));
>
>           memset (&wi, 0, sizeof (wi));
> -         wi.info = (void *) visited;
> +         wi.info = (void *) &visited;
>           addr = walk_gimple_op (stmt, verify_node_sharing, &wi);
>           if (addr)
>             {
> @@ -4936,7 +4935,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>             }
>
>           memset (&wi, 0, sizeof (wi));
> -         wi.info = (void *) blocks;
> +         wi.info = (void *) &blocks;
>           addr = walk_gimple_op (stmt, verify_expr_location, &wi);
>           if (addr)
>             {
> @@ -4992,14 +4991,11 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>    if (get_eh_throw_stmt_table (cfun))
>      htab_traverse (get_eh_throw_stmt_table (cfun),
>                    verify_eh_throw_stmt_node,
> -                  visited_stmts);
> +                  &visited_stmts);
>
>    if (err || eh_error_found)
>      internal_error ("verify_gimple failed");
>
> -  pointer_set_destroy (visited);
> -  pointer_set_destroy (visited_stmts);
> -  pointer_set_destroy (blocks);
>    verify_histograms ();
>    timevar_pop (TV_TREE_STMT_VERIFY);
>  }
> diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> index 34c48fa..9d462d1 100644
> --- a/gcc/tree-core.h
> +++ b/gcc/tree-core.h
> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>  #define GCC_TREE_CORE_H
>
>  #include "hashtab.h"
> +#include "hash-set.h"
>  #include "machmode.h"
>  #include "input.h"
>  #include "statistics.h"
> @@ -45,7 +46,6 @@ struct fixed_value;
>  struct ptr_info_def;
>  struct range_info_def;
>  struct die_struct;
> -struct pointer_set_t;
>
>
>  /*---------------------------------------------------------------------------
> @@ -692,7 +692,7 @@ typedef tree (*walk_tree_fn) (tree *, int *, void *);
>
>  /* The type of a callback function that represents a custom walk_tree.  */
>  typedef tree (*walk_tree_lh) (tree *, int *, tree (*) (tree *, int *, void *),
> -                             void *, struct pointer_set_t*);
> +                             void *, hash_set<tree> *);
>
>
>  /*---------------------------------------------------------------------------
> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> index df9a6fc..38842e8 100644
> --- a/gcc/tree-eh.c
> +++ b/gcc/tree-eh.c
> @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "flags.h"
>  #include "function.h"
>  #include "except.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "basic-block.h"
>  #include "tree-ssa-alias.h"
> @@ -3578,7 +3579,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>         eh_catch c;
>         edge_iterator ei;
>         edge e;
> -       struct pointer_set_t *seen_values = pointer_set_create ();
> +       hash_set<tree> seen_values;
>
>         /* Collect the labels for a switch.  Zero the post_landing_pad
>            field becase we'll no longer have anything keeping these labels
> @@ -3605,12 +3606,12 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>                    attached to the handler anymore, we remove
>                    the corresponding edge and then we delete unreachable
>                    blocks at the end of this pass.  */
> -               if (! pointer_set_contains (seen_values, TREE_VALUE (flt_node)))
> +               if (! seen_values.contains (TREE_VALUE (flt_node)))
>                   {
>                     tree t = build_case_label (TREE_VALUE (flt_node),
>                                                NULL, lab);
>                     labels.safe_push (t);
> -                   pointer_set_insert (seen_values, TREE_VALUE (flt_node));
> +                   seen_values.add (TREE_VALUE (flt_node));
>                     have_label = true;
>                   }
>
> @@ -3662,7 +3663,6 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>             x = gimple_build_switch (filter, default_label, labels);
>             gsi_insert_before (&gsi, x, GSI_SAME_STMT);
>           }
> -       pointer_set_destroy (seen_values);
>        }
>        break;
>
> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> index 33705b7..6af4912 100644
> --- a/gcc/tree-inline.c
> +++ b/gcc/tree-inline.c
> @@ -1788,7 +1788,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
>              expensive, copy_body can be told to watch for nontrivial
>              changes.  */
>           if (id->statements_to_fold)
> -           pointer_set_insert (id->statements_to_fold, stmt);
> +           id->statements_to_fold->add (stmt);
>
>           /* We're duplicating a CALL_EXPR.  Find any corresponding
>              callgraph edges and update or duplicate them.  */
> @@ -3507,7 +3507,6 @@ inline_forbidden_p (tree fndecl)
>  {
>    struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
>    struct walk_stmt_info wi;
> -  struct pointer_set_t *visited_nodes;
>    basic_block bb;
>    bool forbidden_p = false;
>
> @@ -3518,10 +3517,10 @@ inline_forbidden_p (tree fndecl)
>
>    /* Next, walk the statements of the function looking for
>       constraucts we can't handle, or are non-optimal for inlining.  */
> -  visited_nodes = pointer_set_create ();
> +  hash_set<tree> visited_nodes;
>    memset (&wi, 0, sizeof (wi));
>    wi.info = (void *) fndecl;
> -  wi.pset = visited_nodes;
> +  wi.pset = &visited_nodes;
>
>    FOR_EACH_BB_FN (bb, fun)
>      {
> @@ -3533,7 +3532,6 @@ inline_forbidden_p (tree fndecl)
>         break;
>      }
>
> -  pointer_set_destroy (visited_nodes);
>    return forbidden_p;
>  }
>
> @@ -4531,7 +4529,7 @@ gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
>     in the STATEMENTS pointer set.  */
>
>  static void
> -fold_marked_statements (int first, struct pointer_set_t *statements)
> +fold_marked_statements (int first, hash_set<gimple> *statements)
>  {
>    for (; first < n_basic_blocks_for_fn (cfun); first++)
>      if (BASIC_BLOCK_FOR_FN (cfun, first))
> @@ -4541,7 +4539,7 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
>         for (gsi = gsi_start_bb (BASIC_BLOCK_FOR_FN (cfun, first));
>              !gsi_end_p (gsi);
>              gsi_next (&gsi))
> -         if (pointer_set_contains (statements, gsi_stmt (gsi)))
> +         if (statements->contains (gsi_stmt (gsi)))
>             {
>               gimple old_stmt = gsi_stmt (gsi);
>               tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
> @@ -4642,7 +4640,7 @@ optimize_inline_calls (tree fn)
>    id.transform_return_to_modify = true;
>    id.transform_parameter = true;
>    id.transform_lang_insert_block = NULL;
> -  id.statements_to_fold = pointer_set_create ();
> +  id.statements_to_fold = new hash_set<gimple>;
>
>    push_gimplify_context ();
>
> @@ -4678,7 +4676,7 @@ optimize_inline_calls (tree fn)
>
>    /* Fold queued statements.  */
>    fold_marked_statements (last, id.statements_to_fold);
> -  pointer_set_destroy (id.statements_to_fold);
> +  delete id.statements_to_fold;
>
>    gcc_assert (!id.debug_stmts.exists ());
>
> @@ -4920,7 +4918,6 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
>  {
>    copy_body_data id;
>    struct walk_stmt_info wi;
> -  struct pointer_set_t *visited;
>    gimple_seq copy;
>
>    /* There's nothing to do for NULL_TREE.  */
> @@ -4943,11 +4940,10 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
>
>    /* Walk the tree once to find local labels.  */
>    memset (&wi, 0, sizeof (wi));
> -  visited = pointer_set_create ();
> +  hash_set<tree> visited;
>    wi.info = &id;
> -  wi.pset = visited;
> +  wi.pset = &visited;
>    walk_gimple_seq (seq, mark_local_labels_stmt, NULL, &wi);
> -  pointer_set_destroy (visited);
>
>    copy = gimple_seq_copy (seq);
>
> @@ -5370,7 +5366,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
>    memset (&id, 0, sizeof (id));
>
>    /* Generate a new name for the new version. */
> -  id.statements_to_fold = pointer_set_create ();
> +  id.statements_to_fold = new hash_set<gimple>;
>
>    id.decl_map = pointer_map_create ();
>    id.debug_map = NULL;
> @@ -5541,7 +5537,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
>    free_dominance_info (CDI_POST_DOMINATORS);
>
>    fold_marked_statements (0, id.statements_to_fold);
> -  pointer_set_destroy (id.statements_to_fold);
> +  delete id.statements_to_fold;
>    fold_cond_expr_cond ();
>    delete_unreachable_blocks_update_callgraph (&id);
>    if (id.dst_node->definition)
> diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
> index 2a5daaf..c13e6c7 100644
> --- a/gcc/tree-inline.h
> +++ b/gcc/tree-inline.h
> @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
>  #ifndef GCC_TREE_INLINE_H
>  #define GCC_TREE_INLINE_H
>
> +#include "hash-set.h"
> +
>  struct cgraph_edge;
>
>  /* Indicate the desired behavior wrt call graph edges.  We can either
> @@ -114,7 +116,7 @@ struct copy_body_data
>    void (*transform_lang_insert_block) (tree);
>
>    /* Statements that might be possibly folded.  */
> -  struct pointer_set_t *statements_to_fold;
> +  hash_set<gimple> *statements_to_fold;
>
>    /* Entry basic block to currently copied body.  */
>    basic_block entry_bb;
> diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
> index 185d87c..45c5cf7 100644
> --- a/gcc/tree-nested.c
> +++ b/gcc/tree-nested.c
> @@ -95,7 +95,7 @@ struct nesting_info
>
>    struct pointer_map_t *field_map;
>    struct pointer_map_t *var_map;
> -  struct pointer_set_t *mem_refs;
> +  hash_set<tree *> *mem_refs;
>    bitmap suppress_expansion;
>
>    tree context;
> @@ -732,7 +732,7 @@ create_nesting_tree (struct cgraph_node *cgn)
>    struct nesting_info *info = XCNEW (struct nesting_info);
>    info->field_map = pointer_map_create ();
>    info->var_map = pointer_map_create ();
> -  info->mem_refs = pointer_set_create ();
> +  info->mem_refs = new hash_set<tree *>;
>    info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
>    info->context = cgn->decl;
>
> @@ -1651,7 +1651,7 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
>          fold here, as the chain record type is not yet finalized.  */
>        if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
>           && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
> -       pointer_set_insert (info->mem_refs, tp);
> +       info->mem_refs->add (tp);
>        wi->val_only = save_val_only;
>        break;
>
> @@ -2655,8 +2655,8 @@ remap_vla_decls (tree block, struct nesting_info *root)
>  }
>
>  /* Fold the MEM_REF *E.  */
> -static bool
> -fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED)
> +bool
> +fold_mem_refs (tree *const &e, void *data ATTRIBUTE_UNUSED)
>  {
>    tree *ref_p = CONST_CAST2 (tree *, const tree *, (const tree *)e);
>    *ref_p = fold (*ref_p);
> @@ -2878,7 +2878,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
>      }
>
>    /* Fold the rewritten MEM_REF trees.  */
> -  pointer_set_traverse (root->mem_refs, fold_mem_refs, NULL);
> +  root->mem_refs->traverse<void *, fold_mem_refs> (NULL);
>
>    /* Dump the translated tree function.  */
>    if (dump_file)
> @@ -2933,7 +2933,7 @@ free_nesting_tree (struct nesting_info *root)
>        next = iter_nestinfo_next (node);
>        pointer_map_destroy (node->var_map);
>        pointer_map_destroy (node->field_map);
> -      pointer_set_destroy (node->mem_refs);
> +      delete node->mem_refs;
>        free (node);
>        node = next;
>      }
> diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
> index ca6e014..aee0331 100644
> --- a/gcc/tree-pretty-print.c
> +++ b/gcc/tree-pretty-print.c
> @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "expr.h"
>  #include "tree-pretty-print.h"
>  #include "hashtab.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "gimple-expr.h"
>  #include "cgraph.h"
>  #include "langhooks.h"
> @@ -103,14 +103,14 @@ debug_generic_stmt (tree t)
>  DEBUG_FUNCTION void
>  debug_tree_chain (tree t)
>  {
> -  struct pointer_set_t *seen = pointer_set_create ();
> +  hash_set<tree> seen;
>
>    while (t)
>      {
>        print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
>        fprintf (stderr, " ");
>        t = TREE_CHAIN (t);
> -      if (pointer_set_insert (seen, t))
> +      if (seen.add (t))
>         {
>           fprintf (stderr, "... [cycled back to ");
>           print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
> @@ -119,8 +119,6 @@ debug_tree_chain (tree t)
>         }
>      }
>    fprintf (stderr, "\n");
> -
> -  pointer_set_destroy (seen);
>  }
>
>  /* Prints declaration DECL to the FILE with details specified by FLAGS.  */
> diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
> index 36d68a8..83c1b19 100644
> --- a/gcc/tree-ssa-loop-niter.c
> +++ b/gcc/tree-ssa-loop-niter.c
> @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "basic-block.h"
>  #include "gimple-pretty-print.h"
>  #include "intl.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
> @@ -3281,7 +3282,7 @@ discover_iteration_bound_by_body_walk (struct loop *loop)
>  static void
>  maybe_lower_iteration_bound (struct loop *loop)
>  {
> -  pointer_set_t *not_executed_last_iteration = NULL;
> +  hash_set<gimple> *not_executed_last_iteration = NULL;
>    struct nb_iter_bound *elt;
>    bool found_exit = false;
>    vec<basic_block> queue = vNULL;
> @@ -3300,8 +3301,8 @@ maybe_lower_iteration_bound (struct loop *loop)
>           && wi::ltu_p (elt->bound, loop->nb_iterations_upper_bound))
>         {
>           if (!not_executed_last_iteration)
> -           not_executed_last_iteration = pointer_set_create ();
> -         pointer_set_insert (not_executed_last_iteration, elt->stmt);
> +           not_executed_last_iteration = new hash_set<gimple>;
> +         not_executed_last_iteration->add (elt->stmt);
>         }
>      }
>    if (!not_executed_last_iteration)
> @@ -3327,7 +3328,7 @@ maybe_lower_iteration_bound (struct loop *loop)
>        for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>         {
>           gimple stmt = gsi_stmt (gsi);
> -         if (pointer_set_contains (not_executed_last_iteration, stmt))
> +         if (not_executed_last_iteration->contains (stmt))
>             {
>               stmt_found = true;
>               break;
> @@ -3376,7 +3377,7 @@ maybe_lower_iteration_bound (struct loop *loop)
>      }
>    BITMAP_FREE (visited);
>    queue.release ();
> -  pointer_set_destroy (not_executed_last_iteration);
> +  delete not_executed_last_iteration;
>  }
>
>  /* Records estimates on numbers of iterations of LOOP.  If USE_UNDEFINED_P
> diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
> index 052d760..3185d9a 100644
> --- a/gcc/tree-ssa-phiopt.c
> +++ b/gcc/tree-ssa-phiopt.c
> @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "flags.h"
>  #include "tm_p.h"
>  #include "basic-block.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
> @@ -72,9 +73,9 @@ static bool abs_replacement (basic_block, basic_block,
>  static bool neg_replacement (basic_block, basic_block,
>                              edge, edge, gimple, tree, tree);
>  static bool cond_store_replacement (basic_block, basic_block, edge, edge,
> -                                   struct pointer_set_t *);
> +                                   hash_set<tree> *);
>  static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
> -static struct pointer_set_t * get_non_trapping (void);
> +static hash_set<tree> * get_non_trapping ();
>  static void replace_phi_edge_with_variable (basic_block, edge, gimple, tree);
>  static void hoist_adjacent_loads (basic_block, basic_block,
>                                   basic_block, basic_block);
> @@ -176,7 +177,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
>    basic_block *bb_order;
>    unsigned n, i;
>    bool cfgchanged = false;
> -  struct pointer_set_t *nontrap = 0;
> +  hash_set<tree> *nontrap = 0;
>
>    if (do_store_elim)
>      /* Calculate the set of non-trapping memory accesses.  */
> @@ -363,7 +364,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
>    free (bb_order);
>
>    if (do_store_elim)
> -    pointer_set_destroy (nontrap);
> +    delete nontrap;
>    /* If the CFG has changed, we should cleanup the CFG.  */
>    if (cfgchanged && do_store_elim)
>      {
> @@ -1469,7 +1470,7 @@ ssa_names_hasher::equal (const value_type *n1, const compare_type *n2)
>  class nontrapping_dom_walker : public dom_walker
>  {
>  public:
> -  nontrapping_dom_walker (cdi_direction direction, pointer_set_t *ps)
> +  nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps)
>      : dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {}
>
>    virtual void before_dom_children (basic_block);
> @@ -1484,7 +1485,7 @@ private:
>       the RHS.  */
>    void add_or_mark_expr (basic_block, tree, bool);
>
> -  pointer_set_t *m_nontrapping;
> +  hash_set<tree> *m_nontrapping;
>
>    /* The hash table for remembering what we've seen.  */
>    hash_table<ssa_names_hasher> m_seen_ssa_names;
> @@ -1572,7 +1573,7 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
>          then we can't trap.  */
>        if (found_bb && (((size_t)found_bb->aux) & 1) == 1)
>         {
> -         pointer_set_insert (m_nontrapping, exp);
> +         m_nontrapping->add (exp);
>         }
>        else
>          {
> @@ -1601,11 +1602,11 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
>     It will do a dominator walk over the whole function, and it will
>     make use of the bb->aux pointers.  It returns a set of trees
>     (the MEM_REFs itself) which can't trap.  */
> -static struct pointer_set_t *
> +static hash_set<tree> *
>  get_non_trapping (void)
>  {
>    nt_call_phase = 0;
> -  pointer_set_t *nontrap = pointer_set_create ();
> +  hash_set<tree> *nontrap = new hash_set<tree>;
>    /* We're going to do a dominator walk, so ensure that we have
>       dominance information.  */
>    calculate_dominance_info (CDI_DOMINATORS);
> @@ -1634,7 +1635,7 @@ get_non_trapping (void)
>
>  static bool
>  cond_store_replacement (basic_block middle_bb, basic_block join_bb,
> -                       edge e0, edge e1, struct pointer_set_t *nontrap)
> +                       edge e0, edge e1, hash_set<tree> *nontrap)
>  {
>    gimple assign = last_and_only_stmt (middle_bb);
>    tree lhs, rhs, name, name2;
> @@ -1659,7 +1660,7 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb,
>    /* Prove that we can move the store down.  We could also check
>       TREE_THIS_NOTRAP here, but in that case we also could move stores,
>       whose value is not available readily, which we want to avoid.  */
> -  if (!pointer_set_contains (nontrap, lhs))
> +  if (!nontrap->contains (lhs))
>      return false;
>
>    /* Now we've checked the constraints, so do the transformation:
> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
> index 9807b42..3dee5ba 100644
> --- a/gcc/tree-ssa-threadedge.c
> +++ b/gcc/tree-ssa-threadedge.c
> @@ -30,7 +30,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "function.h"
>  #include "timevar.h"
>  #include "dumpfile.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
>  #include "gimple-expr.h"
> @@ -693,13 +693,13 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>      }
>
>    auto_vec<tree, alloc_count> fewvars;
> -  pointer_set_t *vars = NULL;
> +  hash_set<tree> *vars = NULL;
>
>    /* If we're already starting with 3/4 of alloc_count, go for a
> -     pointer_set, otherwise start with an unordered stack-allocated
> +     hash_set, otherwise start with an unordered stack-allocated
>       VEC.  */
>    if (i * 4 > alloc_count * 3)
> -    vars = pointer_set_create ();
> +    vars = new hash_set<tree>;
>
>    /* Now go through the initial debug stmts in DEST again, this time
>       actually inserting in VARS or FEWVARS.  Don't bother checking for
> @@ -720,7 +720,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>         gcc_unreachable ();
>
>        if (vars)
> -       pointer_set_insert (vars, var);
> +       vars->add (var);
>        else
>         fewvars.quick_push (var);
>      }
> @@ -754,7 +754,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>              or somesuch.  Adding `&& bb == src' to the condition
>              below will preserve all potentially relevant debug
>              notes.  */
> -         if (vars && pointer_set_insert (vars, var))
> +         if (vars && vars->add (var))
>             continue;
>           else if (!vars)
>             {
> @@ -769,11 +769,11 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>                 fewvars.quick_push (var);
>               else
>                 {
> -                 vars = pointer_set_create ();
> +                 vars = new hash_set<tree>;
>                   for (i = 0; i < alloc_count; i++)
> -                   pointer_set_insert (vars, fewvars[i]);
> +                   vars->add (fewvars[i]);
>                   fewvars.release ();
> -                 pointer_set_insert (vars, var);
> +                 vars->add (var);
>                 }
>             }
>
> @@ -786,7 +786,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>    while (bb != src && single_pred_p (bb));
>
>    if (vars)
> -    pointer_set_destroy (vars);
> +    delete vars;
>    else if (fewvars.exists ())
>      fewvars.release ();
>  }
> diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
> index 64259fb..f2578b7 100644
> --- a/gcc/tree-ssa-uninit.c
> +++ b/gcc/tree-ssa-uninit.c
> @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "function.h"
>  #include "gimple-pretty-print.h"
>  #include "bitmap.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
> @@ -60,7 +61,7 @@ along with GCC; see the file COPYING3.  If not see
>  /* Pointer set of potentially undefined ssa names, i.e.,
>     ssa names that are defined by phi with operands that
>     are not defined or potentially undefined.  */
> -static pointer_set_t *possibly_undefined_names = 0;
> +static hash_set<tree> *possibly_undefined_names = 0;
>
>  /* Bit mask handling macros.  */
>  #define MASK_SET_BIT(mask, pos) mask |= (1 << pos)
> @@ -89,7 +90,7 @@ has_undefined_value_p (tree t)
>  {
>    return (ssa_undefined_value_p (t)
>            || (possibly_undefined_names
> -              && pointer_set_contains (possibly_undefined_names, t)));
> +              && possibly_undefined_names->contains (t)));
>  }
>
>
> @@ -648,13 +649,13 @@ find_predicates (pred_chain_union *preds,
>  static void
>  collect_phi_def_edges (gimple phi, basic_block cd_root,
>                         vec<edge> *edges,
> -                       pointer_set_t *visited_phis)
> +                       hash_set<gimple> *visited_phis)
>  {
>    size_t i, n;
>    edge opnd_edge;
>    tree opnd;
>
> -  if (pointer_set_insert (visited_phis, phi))
> +  if (visited_phis->add (phi))
>      return;
>
>    n = gimple_phi_num_args (phi);
> @@ -707,7 +708,6 @@ find_def_preds (pred_chain_union *preds, gimple phi)
>    vec<edge> def_edges = vNULL;
>    bool has_valid_pred = false;
>    basic_block phi_bb, cd_root = 0;
> -  pointer_set_t *visited_phis;
>
>    phi_bb = gimple_bb (phi);
>    /* First find the closest dominating bb to be
> @@ -716,9 +716,8 @@ find_def_preds (pred_chain_union *preds, gimple phi)
>    if (!cd_root)
>      return false;
>
> -  visited_phis = pointer_set_create ();
> -  collect_phi_def_edges (phi, cd_root, &def_edges, visited_phis);
> -  pointer_set_destroy (visited_phis);
> +  hash_set<gimple> visited_phis;
> +  collect_phi_def_edges (phi, cd_root, &def_edges, &visited_phis);
>
>    n = def_edges.length ();
>    if (n == 0)
> @@ -941,7 +940,7 @@ is_use_properly_guarded (gimple use_stmt,
>                           basic_block use_bb,
>                           gimple phi,
>                           unsigned uninit_opnds,
> -                         pointer_set_t *visited_phis);
> +                         hash_set<gimple> *visited_phis);
>
>  /* Returns true if all uninitialized opnds are pruned. Returns false
>     otherwise. PHI is the phi node with uninitialized operands,
> @@ -983,7 +982,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
>                                               gimple flag_def,
>                                               tree boundary_cst,
>                                               enum tree_code cmp_code,
> -                                             pointer_set_t *visited_phis,
> +                                             hash_set<gimple> *visited_phis,
>                                               bitmap *visited_flag_phis)
>  {
>    unsigned i;
> @@ -1153,7 +1152,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
>  static bool
>  use_pred_not_overlap_with_undef_path_pred (pred_chain_union preds,
>                                            gimple phi, unsigned uninit_opnds,
> -                                          pointer_set_t *visited_phis)
> +                                          hash_set<gimple> *visited_phis)
>  {
>    unsigned int i, n;
>    gimple flag_def = 0;
> @@ -1818,11 +1817,11 @@ push_pred (pred_chain_union *norm_preds, pred_info pred)
>
>  inline static void
>  push_to_worklist (tree op, vec<pred_info, va_heap, vl_ptr> *work_list,
> -                  pointer_set_t *mark_set)
> +                  hash_set<tree> *mark_set)
>  {
> -  if (pointer_set_contains (mark_set, op))
> +  if (mark_set->contains (op))
>      return;
> -  pointer_set_insert (mark_set, op);
> +  mark_set->add (op);
>
>    pred_info arg_pred;
>    arg_pred.pred_lhs = op;
> @@ -1907,7 +1906,7 @@ normalize_one_pred_1 (pred_chain_union *norm_preds,
>                        pred_info pred,
>                        enum tree_code and_or_code,
>                        vec<pred_info, va_heap, vl_ptr> *work_list,
> -                     pointer_set_t *mark_set)
> +                     hash_set<tree> *mark_set)
>  {
>    if (!is_neq_zero_form_p (pred))
>      {
> @@ -1987,7 +1986,6 @@ normalize_one_pred (pred_chain_union *norm_preds,
>                      pred_info pred)
>  {
>    vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
> -  pointer_set_t *mark_set = NULL;
>    enum tree_code and_or_code = ERROR_MARK;
>    pred_chain norm_chain = vNULL;
>
> @@ -2015,19 +2013,18 @@ normalize_one_pred (pred_chain_union *norm_preds,
>      }
>
>    work_list.safe_push (pred);
> -  mark_set = pointer_set_create ();
> +  hash_set<tree> mark_set;
>
>    while (!work_list.is_empty ())
>      {
>        pred_info a_pred = work_list.pop ();
>        normalize_one_pred_1 (norm_preds, &norm_chain, a_pred,
> -                            and_or_code, &work_list, mark_set);
> +                            and_or_code, &work_list, &mark_set);
>      }
>    if (and_or_code == BIT_AND_EXPR)
>      norm_preds->safe_push (norm_chain);
>
>    work_list.release ();
> -  pointer_set_destroy (mark_set);
>  }
>
>  static void
> @@ -2035,26 +2032,25 @@ normalize_one_pred_chain (pred_chain_union *norm_preds,
>                            pred_chain one_chain)
>  {
>    vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
> -  pointer_set_t *mark_set = pointer_set_create ();
> +  hash_set<tree> mark_set;
>    pred_chain norm_chain = vNULL;
>    size_t i;
>
>    for (i = 0; i < one_chain.length (); i++)
>      {
>        work_list.safe_push (one_chain[i]);
> -      pointer_set_insert (mark_set, one_chain[i].pred_lhs);
> +      mark_set.add (one_chain[i].pred_lhs);
>      }
>
>    while (!work_list.is_empty ())
>      {
>        pred_info a_pred = work_list.pop ();
>        normalize_one_pred_1 (0, &norm_chain, a_pred,
> -                            BIT_AND_EXPR, &work_list, mark_set);
> +                            BIT_AND_EXPR, &work_list, &mark_set);
>      }
>
>    norm_preds->safe_push (norm_chain);
>    work_list.release ();
> -  pointer_set_destroy (mark_set);
>  }
>
>  /* Normalize predicate chains PREDS and returns the normalized one.  */
> @@ -2112,7 +2108,7 @@ is_use_properly_guarded (gimple use_stmt,
>                           basic_block use_bb,
>                           gimple phi,
>                           unsigned uninit_opnds,
> -                         pointer_set_t *visited_phis)
> +                         hash_set<gimple> *visited_phis)
>  {
>    basic_block phi_bb;
>    pred_chain_union preds = vNULL;
> @@ -2120,7 +2116,7 @@ is_use_properly_guarded (gimple use_stmt,
>    bool has_valid_preds = false;
>    bool is_properly_guarded = false;
>
> -  if (pointer_set_insert (visited_phis, phi))
> +  if (visited_phis->add (phi))
>      return false;
>
>    phi_bb = gimple_bb (phi);
> @@ -2181,7 +2177,7 @@ is_use_properly_guarded (gimple use_stmt,
>  static gimple
>  find_uninit_use (gimple phi, unsigned uninit_opnds,
>                   vec<gimple> *worklist,
> -                pointer_set_t *added_to_worklist)
> +                hash_set<gimple> *added_to_worklist)
>  {
>    tree phi_result;
>    use_operand_p use_p;
> @@ -2192,28 +2188,22 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>
>    FOR_EACH_IMM_USE_FAST (use_p, iter, phi_result)
>      {
> -      pointer_set_t *visited_phis;
>        basic_block use_bb;
>
>        use_stmt = USE_STMT (use_p);
>        if (is_gimple_debug (use_stmt))
>         continue;
>
> -      visited_phis = pointer_set_create ();
> -
>        if (gimple_code (use_stmt) == GIMPLE_PHI)
>         use_bb = gimple_phi_arg_edge (use_stmt,
>                                       PHI_ARG_INDEX_FROM_USE (use_p))->src;
>        else
>         use_bb = gimple_bb (use_stmt);
>
> +      hash_set<gimple> visited_phis;
>        if (is_use_properly_guarded (use_stmt, use_bb, phi, uninit_opnds,
> -                                   visited_phis))
> -        {
> -          pointer_set_destroy (visited_phis);
> -          continue;
> -        }
> -      pointer_set_destroy (visited_phis);
> +                                   &visited_phis))
> +       continue;
>
>        if (dump_file && (dump_flags & TDF_DETAILS))
>          {
> @@ -2226,7 +2216,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>
>        /* Found a phi use that is not guarded,
>           add the phi to the worklist.  */
> -      if (!pointer_set_insert (added_to_worklist, use_stmt))
> +      if (!added_to_worklist->add (use_stmt))
>          {
>            if (dump_file && (dump_flags & TDF_DETAILS))
>              {
> @@ -2235,7 +2225,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>              }
>
>            worklist->safe_push (use_stmt);
> -          pointer_set_insert (possibly_undefined_names, phi_result);
> +          possibly_undefined_names->add (phi_result);
>          }
>      }
>
> @@ -2252,7 +2242,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>
>  static void
>  warn_uninitialized_phi (gimple phi, vec<gimple> *worklist,
> -                        pointer_set_t *added_to_worklist)
> +                        hash_set<gimple> *added_to_worklist)
>  {
>    unsigned uninit_opnds;
>    gimple uninit_use_stmt = 0;
> @@ -2339,7 +2329,6 @@ pass_late_warn_uninitialized::execute (function *fun)
>    basic_block bb;
>    gimple_stmt_iterator gsi;
>    vec<gimple> worklist = vNULL;
> -  pointer_set_t *added_to_worklist;
>
>    calculate_dominance_info (CDI_DOMINATORS);
>    calculate_dominance_info (CDI_POST_DOMINATORS);
> @@ -2350,8 +2339,8 @@ pass_late_warn_uninitialized::execute (function *fun)
>
>    timevar_push (TV_TREE_UNINIT);
>
> -  possibly_undefined_names = pointer_set_create ();
> -  added_to_worklist = pointer_set_create ();
> +  possibly_undefined_names = new hash_set<tree>;
> +  hash_set<gimple> added_to_worklist;
>
>    /* Initialize worklist  */
>    FOR_EACH_BB_FN (bb, fun)
> @@ -2373,7 +2362,7 @@ pass_late_warn_uninitialized::execute (function *fun)
>                 && uninit_undefined_value_p (op))
>               {
>                 worklist.safe_push (phi);
> -               pointer_set_insert (added_to_worklist, phi);
> +               added_to_worklist.add (phi);
>                 if (dump_file && (dump_flags & TDF_DETAILS))
>                   {
>                     fprintf (dump_file, "[WORKLIST]: add to initial list: ");
> @@ -2388,12 +2377,11 @@ pass_late_warn_uninitialized::execute (function *fun)
>      {
>        gimple cur_phi = 0;
>        cur_phi = worklist.pop ();
> -      warn_uninitialized_phi (cur_phi, &worklist, added_to_worklist);
> +      warn_uninitialized_phi (cur_phi, &worklist, &added_to_worklist);
>      }
>
>    worklist.release ();
> -  pointer_set_destroy (added_to_worklist);
> -  pointer_set_destroy (possibly_undefined_names);
> +  delete possibly_undefined_names;
>    possibly_undefined_names = NULL;
>    free_dominance_info (CDI_POST_DOMINATORS);
>    timevar_pop (TV_TREE_UNINIT);
> diff --git a/gcc/tree.c b/gcc/tree.c
> index 6669a84..de1c9b6 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -5143,7 +5143,7 @@ struct free_lang_data_d
>    vec<tree> worklist;
>
>    /* Set of traversed objects.  Used to avoid duplicate visits.  */
> -  struct pointer_set_t *pset;
> +  hash_set<tree> *pset;
>
>    /* Array of symbols to process with free_lang_data_in_decl.  */
>    vec<tree> decls;
> @@ -5208,7 +5208,7 @@ add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
>  static inline void
>  fld_worklist_push (tree t, struct free_lang_data_d *fld)
>  {
> -  if (t && !is_lang_specific (t) && !pointer_set_contains (fld->pset, t))
> +  if (t && !is_lang_specific (t) && !fld->pset->contains (t))
>      fld->worklist.safe_push ((t));
>  }
>
> @@ -5374,7 +5374,7 @@ find_decls_types (tree t, struct free_lang_data_d *fld)
>  {
>    while (1)
>      {
> -      if (!pointer_set_contains (fld->pset, t))
> +      if (!fld->pset->contains (t))
>         walk_tree (&t, find_decls_types_r, fld, fld->pset);
>        if (fld->worklist.is_empty ())
>         break;
> @@ -5584,7 +5584,7 @@ free_lang_data_in_cgraph (void)
>    alias_pair *p;
>
>    /* Initialize sets and arrays to store referenced decls and types.  */
> -  fld.pset = pointer_set_create ();
> +  fld.pset = new hash_set<tree>;
>    fld.worklist.create (0);
>    fld.decls.create (100);
>    fld.types.create (100);
> @@ -5614,7 +5614,7 @@ free_lang_data_in_cgraph (void)
>    FOR_EACH_VEC_ELT (fld.types, i, t)
>      free_lang_data_in_type (t);
>
> -  pointer_set_destroy (fld.pset);
> +  delete fld.pset;
>    fld.worklist.release ();
>    fld.decls.release ();
>    fld.types.release ();
> @@ -10819,7 +10819,7 @@ num_ending_zeros (const_tree x)
>
>  static tree
>  walk_type_fields (tree type, walk_tree_fn func, void *data,
> -                 struct pointer_set_t *pset, walk_tree_lh lh)
> +                 hash_set<tree> *pset, walk_tree_lh lh)
>  {
>    tree result = NULL_TREE;
>
> @@ -10901,7 +10901,7 @@ walk_type_fields (tree type, walk_tree_fn func, void *data,
>
>  tree
>  walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
> -            struct pointer_set_t *pset, walk_tree_lh lh)
> +            hash_set<tree> *pset, walk_tree_lh lh)
>  {
>    enum tree_code code;
>    int walk_subtrees;
> @@ -10922,7 +10922,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
>
>    /* Don't walk the same tree twice, if the user has requested
>       that we avoid doing so.  */
> -  if (pset && pointer_set_insert (pset, *tp))
> +  if (pset && pset->add (*tp))
>      return NULL_TREE;
>
>    /* Call the function.  */
> @@ -11237,11 +11237,9 @@ walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data,
>                                 walk_tree_lh lh)
>  {
>    tree result;
> -  struct pointer_set_t *pset;
>
> -  pset = pointer_set_create ();
> -  result = walk_tree_1 (tp, func, data, pset, lh);
> -  pointer_set_destroy (pset);
> +  hash_set<tree> pset;
> +  result = walk_tree_1 (tp, func, data, &pset, lh);
>    return result;
>  }
>
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 2bb6d1f..c9f978a 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>  #define GCC_TREE_H
>
>  #include "tree-core.h"
> +#include "hash-set.h"
>  #include "wide-int.h"
>  #include "inchash.h"
>
> @@ -4328,7 +4329,7 @@ extern void using_eh_for_cleanups (void);
>  extern bool using_eh_for_cleanups_p (void);
>  extern const char *get_tree_code_name (enum tree_code);
>  extern void set_call_expr_flags (tree, int);
> -extern tree walk_tree_1 (tree*, walk_tree_fn, void*, struct pointer_set_t*,
> +extern tree walk_tree_1 (tree*, walk_tree_fn, void*, hash_set<tree>*,
>                          walk_tree_lh);
>  extern tree walk_tree_without_duplicates_1 (tree*, walk_tree_fn, void*,
>                                             walk_tree_lh);
> diff --git a/gcc/value-prof.c b/gcc/value-prof.c
> index 3e51539..ffdee65 100644
> --- a/gcc/value-prof.c
> +++ b/gcc/value-prof.c
> @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "data-streamer.h"
>  #include "builtins.h"
>  #include "tree-nested.h"
> +#include "hash-set.h"
>
>  /* In this file value profile based optimizations are placed.  Currently the
>     following optimizations are implemented (for more detailed descriptions
> @@ -515,10 +516,10 @@ static bool error_found = false;
>  static int
>  visit_hist (void **slot, void *data)
>  {
> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> +  hash_set<histogram_value> *visited = (hash_set<histogram_value> *) data;
>    histogram_value hist = *(histogram_value *) slot;
>
> -  if (!pointer_set_contains (visited, hist)
> +  if (!visited->contains (hist)
>        && hist->type != HIST_TYPE_TIME_PROFILE)
>      {
>        error ("dead histogram");
> @@ -538,10 +539,9 @@ verify_histograms (void)
>    basic_block bb;
>    gimple_stmt_iterator gsi;
>    histogram_value hist;
> -  struct pointer_set_t *visited_hists;
>
>    error_found = false;
> -  visited_hists = pointer_set_create ();
> +  hash_set<histogram_value> visited_hists;
>    FOR_EACH_BB_FN (bb, cfun)
>      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>        {
> @@ -558,12 +558,11 @@ verify_histograms (void)
>                 dump_histogram_value (stderr, hist);
>                 error_found = true;
>               }
> -            pointer_set_insert (visited_hists, hist);
> +            visited_hists.add (hist);
>           }
>        }
>    if (VALUE_HISTOGRAMS (cfun))
> -    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, visited_hists);
> -  pointer_set_destroy (visited_hists);
> +    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, &visited_hists);
>    if (error_found)
>      internal_error ("verify_histograms failed");
>  }
> diff --git a/gcc/varasm.c b/gcc/varasm.c
> index 819ec26..9d8602b 100644
> --- a/gcc/varasm.c
> +++ b/gcc/varasm.c
> @@ -51,7 +51,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "common/common-target.h"
>  #include "targhooks.h"
>  #include "cgraph.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "asan.h"
>  #include "basic-block.h"
>
> @@ -2249,7 +2249,7 @@ static bool pending_assemble_externals_processed;
>
>  /* Avoid O(external_decls**2) lookups in the pending_assemble_externals
>     TREE_LIST in assemble_external.  */
> -static struct pointer_set_t *pending_assemble_externals_set;
> +static hash_set<tree> *pending_assemble_externals_set;
>
>  /* True if DECL is a function decl for which no out-of-line copy exists.
>     It is assumed that DECL's assembler name has been set.  */
> @@ -2303,7 +2303,7 @@ process_pending_assemble_externals (void)
>
>    pending_assemble_externals = 0;
>    pending_assemble_externals_processed = true;
> -  pointer_set_destroy (pending_assemble_externals_set);
> +  delete pending_assemble_externals_set;
>  #endif
>  }
>
> @@ -2361,7 +2361,7 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
>        return;
>      }
>
> -  if (! pointer_set_insert (pending_assemble_externals_set, decl))
> +  if (! pending_assemble_externals_set->add (decl))
>      pending_assemble_externals = tree_cons (NULL, decl,
>                                             pending_assemble_externals);
>  #endif
> @@ -5991,7 +5991,7 @@ init_varasm_once (void)
>      readonly_data_section = text_section;
>
>  #ifdef ASM_OUTPUT_EXTERNAL
> -  pending_assemble_externals_set = pointer_set_create ();
> +  pending_assemble_externals_set = new hash_set<tree>;
>  #endif
>  }
>
> diff --git a/gcc/varpool.c b/gcc/varpool.c
> index 74117e2..558767f 100644
> --- a/gcc/varpool.c
> +++ b/gcc/varpool.c
> @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-ssa-alias.h"
>  #include "gimple.h"
>  #include "lto-streamer.h"
> +#include "hash-set.h"
>
>  const char * const tls_model_names[]={"none", "tls-emulated", "tls-real",
>                                       "tls-global-dynamic", "tls-local-dynamic",
> @@ -576,7 +577,7 @@ varpool_remove_unreferenced_decls (void)
>    varpool_node *first = (varpool_node *)(void *)1;
>    int i;
>    struct ipa_ref *ref = NULL;
> -  struct pointer_set_t *referenced = pointer_set_create ();
> +  hash_set<varpool_node *> referenced;
>
>    if (seen_error ())
>      return;
> @@ -623,7 +624,7 @@ varpool_remove_unreferenced_decls (void)
>               && vnode->analyzed)
>             enqueue_node (vnode, &first);
>           else
> -           pointer_set_insert (referenced, node);
> +           referenced.add (node);
>         }
>      }
>    if (cgraph_dump_file)
> @@ -635,13 +636,13 @@ varpool_remove_unreferenced_decls (void)
>         {
>            if (cgraph_dump_file)
>             fprintf (cgraph_dump_file, " %s", node->asm_name ());
> -         if (pointer_set_contains (referenced, node))
> +         if (referenced.contains (node))
>             node->remove_initializer ();
>           else
>             node->remove ();
>         }
>      }
> -  pointer_set_destroy (referenced);
> +
>    if (cgraph_dump_file)
>      fprintf (cgraph_dump_file, "\n");
>  }
> --
> 2.0.1
>
Trevor Saunders Aug. 2, 2014, 11:24 a.m. UTC | #2
On Wed, Jul 30, 2014 at 12:25:41PM +0200, Richard Biener wrote:
> On Tue, Jul 29, 2014 at 2:50 PM,  <tsaunders@mozilla.com> wrote:
> > From: Trevor Saunders <tsaunders@mozilla.com>
> >
> > Hi,
> >
> > this adds a hash_set wrapper around hash_table, and then replaces usage of pointer_set with it.
> >
> > bootstrapped +regtested on x86_64-unknown-linux-gnu, ok?
> 
> Ok.

committed as r213516, thanks for the review!

Trev

> 
> Thanks,
> Richard.
> 
> > Trev
> >
> > ada/
> >
> >         * gcc-interface/trans.c: Use hash_set instead of pointer_set.
> >
> > c-family/
> >
> >         * c-gimplify.c: Use hash_set instead of pointer_set.
> >
> > c/
> >
> >         * c-decl.c: Use hash_set instead of pointer_set.
> >
> > cp/
> >
> >         * class.c, cp-gimplify.c, cp-tree.h, decl.c, decl2.c, error.c,
> >         method.c, name-lookup.c, pt.c, semantics.c, tree.c: Use hash_set
> >         instead of pointer_set.
> >
> > fortran/
> >
> >         * openmp.c, trans-decl.c: Use hash_set instead of pointer_set.
> >
> > gcc/
> >
> >         * hash-set.h: new File.
> >         * cfgexpand.c, cfgloop.c, cgraph.c, cgraphbuild.c, cgraphunit.c,
> >         cprop.c, cse.c, gimple-walk.c, gimple-walk.h, gimplify.c, godump.c,
> >         ipa-devirt.c, ipa-pure-const.c, ipa-visibility.c, ipa.c, lto-cgraph.c,
> >         lto-streamer-out.c, stmt.c, tree-cfg.c, tree-core.h, tree-eh.c,
> >         tree-inline.c, tree-inline.h, tree-nested.c, tree-pretty-print.c,
> >         tree-ssa-loop-niter.c, tree-ssa-phiopt.c, tree-ssa-threadedge.c,
> >         tree-ssa-uninit.c, tree.c, tree.h, value-prof.c, varasm.c,
> >         varpool.c: Use hash_set instead of pointer_set.
> >
> > lto/
> >
> >         * lto-partition.c, lto-partition.h: Use hash_set instead of
> >         pointer_set.
> > diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
> > index f42ac7f..6961838 100644
> > --- a/gcc/ada/gcc-interface/trans.c
> > +++ b/gcc/ada/gcc-interface/trans.c
> > @@ -36,7 +36,7 @@
> >  #include "output.h"
> >  #include "libfuncs.h"  /* For set_stack_check_libfunc.  */
> >  #include "tree-iterator.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "gimple-expr.h"
> >  #include "gimplify.h"
> >  #include "bitmap.h"
> > @@ -3054,7 +3054,7 @@ struct nrv_data
> >    bitmap nrv;
> >    tree result;
> >    Node_Id gnat_ret;
> > -  struct pointer_set_t *visited;
> > +  hash_set<tree> *visited;
> >  };
> >
> >  /* Return true if T is a Named Return Value.  */
> > @@ -3188,7 +3188,7 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
> >    /* Avoid walking into the same tree more than once.  Unfortunately, we
> >       can't just use walk_tree_without_duplicates because it would only
> >       call us for the first occurrence of NRVs in the function body.  */
> > -  if (pointer_set_insert (dp->visited, *tp))
> > +  if (dp->visited->add (*tp))
> >      *walk_subtrees = 0;
> >
> >    return NULL_TREE;
> > @@ -3328,7 +3328,7 @@ finalize_nrv_unc_r (tree *tp, int *walk_subtrees, void *data)
> >    /* Avoid walking into the same tree more than once.  Unfortunately, we
> >       can't just use walk_tree_without_duplicates because it would only
> >       call us for the first occurrence of NRVs in the function body.  */
> > -  if (pointer_set_insert (dp->visited, *tp))
> > +  if (dp->visited->add (*tp))
> >      *walk_subtrees = 0;
> >
> >    return NULL_TREE;
> > @@ -3376,13 +3376,13 @@ finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret
> >    data.nrv = nrv;
> >    data.result = DECL_RESULT (fndecl);
> >    data.gnat_ret = gnat_ret;
> > -  data.visited = pointer_set_create ();
> > +  data.visited = new hash_set<tree>;
> >    if (TYPE_RETURN_UNCONSTRAINED_P (TREE_TYPE (fndecl)))
> >      func = finalize_nrv_unc_r;
> >    else
> >      func = finalize_nrv_r;
> >    walk_tree (&DECL_SAVED_TREE (fndecl), func, &data, NULL);
> > -  pointer_set_destroy (data.visited);
> > +  delete data.visited;
> >  }
> >
> >  /* Return true if RET_VAL can be used as a Named Return Value for the
> > diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
> > index 2b5ce5b..4898217 100644
> > --- a/gcc/c-family/c-gimplify.c
> > +++ b/gcc/c-family/c-gimplify.c
> > @@ -74,7 +74,7 @@ along with GCC; see the file COPYING3.  If not see
> >  static tree
> >  ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
> >  {
> > -  struct pointer_set_t *pset = (struct pointer_set_t *) data;
> > +  hash_set<tree> *pset = (hash_set<tree> *) data;
> >
> >    /* Since walk_tree doesn't call the callback function on the decls
> >       in BIND_EXPR_VARS, we have to walk them manually.  */
> > @@ -116,10 +116,9 @@ c_genericize (tree fndecl)
> >
> >    if (flag_sanitize & SANITIZE_BOUNDS)
> >      {
> > -      struct pointer_set_t *pset = pointer_set_create ();
> > -      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, pset,
> > -                pset);
> > -      pointer_set_destroy (pset);
> > +      hash_set<tree> pset;
> > +      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
> > +                &pset);
> >      }
> >
> >    /* Dump the C-specific tree IR.  */
> > diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> > index 2a4b439..050ddff 100644
> > --- a/gcc/c/c-decl.c
> > +++ b/gcc/c/c-decl.c
> > @@ -59,7 +59,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "cgraph.h"
> >  #include "hash-table.h"
> >  #include "langhooks-def.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "plugin.h"
> >  #include "c-family/c-ada-spec.h"
> >  #include "cilk.h"
> > @@ -7221,17 +7221,17 @@ warn_cxx_compat_finish_struct (tree fieldlist)
> >    if (!struct_parse_info->typedefs_seen.is_empty ()
> >        && fieldlist != NULL_TREE)
> >      {
> > -      /* Use a pointer_set using the name of the typedef.  We can use
> > -        a pointer_set because identifiers are interned.  */
> > -      struct pointer_set_t *tset = pointer_set_create ();
> > +      /* Use a hash_set<tree> using the name of the typedef.  We can use
> > +        a hash_set<tree> because identifiers are interned.  */
> > +      hash_set<tree> tset;
> >
> >        FOR_EACH_VEC_ELT (struct_parse_info->typedefs_seen, ix, x)
> > -       pointer_set_insert (tset, DECL_NAME (x));
> > +       tset.add (DECL_NAME (x));
> >
> >        for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
> >         {
> >           if (DECL_NAME (x) != NULL_TREE
> > -             && pointer_set_contains (tset, DECL_NAME (x)))
> > +             && tset.contains (DECL_NAME (x)))
> >             {
> >               warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
> >                           ("using %qD as both field and typedef name is "
> > @@ -7241,8 +7241,6 @@ warn_cxx_compat_finish_struct (tree fieldlist)
> >                  the typedef name is used.  */
> >             }
> >         }
> > -
> > -      pointer_set_destroy (tset);
> >      }
> >
> >    /* For each field which has a binding and which was not defined in
> > @@ -8189,7 +8187,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >    struct c_binding *b;
> >    tree parm, decl, last;
> >    tree parmids = arg_info->parms;
> > -  struct pointer_set_t *seen_args = pointer_set_create ();
> > +  hash_set<tree> seen_args;
> >
> >    if (!in_system_header_at (input_location))
> >      warning_at (DECL_SOURCE_LOCATION (fndecl),
> > @@ -8220,7 +8218,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >                       "%qD declared as a non-parameter", decl);
> >           /* If the declaration is already marked, we have a duplicate
> >              name.  Complain and ignore the duplicate.  */
> > -         else if (pointer_set_contains (seen_args, decl))
> > +         else if (seen_args.contains (decl))
> >             {
> >               error_at (DECL_SOURCE_LOCATION (decl),
> >                         "multiple parameters named %qD", decl);
> > @@ -8269,7 +8267,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >         }
> >
> >        TREE_PURPOSE (parm) = decl;
> > -      pointer_set_insert (seen_args, decl);
> > +      seen_args.add (decl);
> >      }
> >
> >    /* Now examine the parms chain for incomplete declarations
> > @@ -8289,7 +8287,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >           TREE_TYPE (parm) = error_mark_node;
> >         }
> >
> > -      if (!pointer_set_contains (seen_args, parm))
> > +      if (!seen_args.contains (parm))
> >         {
> >           error_at (DECL_SOURCE_LOCATION (parm),
> >                     "declaration for parameter %qD but no such parameter",
> > @@ -8324,8 +8322,6 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >        DECL_CHAIN (last) = 0;
> >      }
> >
> > -  pointer_set_destroy (seen_args);
> > -
> >    /* If there was a previous prototype,
> >       set the DECL_ARG_TYPE of each argument according to
> >       the type previously specified, and report any mismatches.  */
> > diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
> > index 2f0ae71..b20be10 100644
> > --- a/gcc/cfgexpand.c
> > +++ b/gcc/cfgexpand.c
> > @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "expr.h"
> >  #include "langhooks.h"
> >  #include "bitmap.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> > @@ -594,7 +595,7 @@ stack_var_cmp (const void *a, const void *b)
> >  static void
> >  add_partitioned_vars_to_ptset (struct pt_solution *pt,
> >                                struct pointer_map_t *decls_to_partitions,
> > -                              struct pointer_set_t *visited, bitmap temp)
> > +                              hash_set<bitmap> *visited, bitmap temp)
> >  {
> >    bitmap_iterator bi;
> >    unsigned i;
> > @@ -604,7 +605,7 @@ add_partitioned_vars_to_ptset (struct pt_solution *pt,
> >        || pt->vars == NULL
> >        /* The pointed-to vars bitmap is shared, it is enough to
> >          visit it once.  */
> > -      || pointer_set_insert (visited, pt->vars))
> > +      || visited->add (pt->vars))
> >      return;
> >
> >    bitmap_clear (temp);
> > @@ -684,7 +685,7 @@ update_alias_info_with_stack_vars (void)
> >    if (decls_to_partitions)
> >      {
> >        unsigned i;
> > -      struct pointer_set_t *visited = pointer_set_create ();
> > +      hash_set<bitmap> visited;
> >        bitmap temp = BITMAP_ALLOC (&stack_var_bitmap_obstack);
> >
> >        for (i = 1; i < num_ssa_names; i++)
> > @@ -696,13 +697,12 @@ update_alias_info_with_stack_vars (void)
> >               && POINTER_TYPE_P (TREE_TYPE (name))
> >               && ((pi = SSA_NAME_PTR_INFO (name)) != NULL))
> >             add_partitioned_vars_to_ptset (&pi->pt, decls_to_partitions,
> > -                                          visited, temp);
> > +                                          &visited, temp);
> >         }
> >
> >        add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped,
> > -                                    decls_to_partitions, visited, temp);
> > +                                    decls_to_partitions, &visited, temp);
> >
> > -      pointer_set_destroy (visited);
> >        pointer_map_destroy (decls_to_partitions);
> >        BITMAP_FREE (temp);
> >      }
> > diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
> > index 73f79ef..8f7e265 100644
> > --- a/gcc/cfgloop.c
> > +++ b/gcc/cfgloop.c
> > @@ -28,7 +28,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "diagnostic-core.h"
> >  #include "flags.h"
> >  #include "tree.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> >  #include "gimple-expr.h"
> > @@ -650,11 +650,11 @@ find_subloop_latch_edge (struct loop *loop)
> >  /* Callback for make_forwarder_block.  Returns true if the edge E is marked
> >     in the set MFB_REIS_SET.  */
> >
> > -static struct pointer_set_t *mfb_reis_set;
> > +static hash_set<edge> *mfb_reis_set;
> >  static bool
> >  mfb_redirect_edges_in_set (edge e)
> >  {
> > -  return pointer_set_contains (mfb_reis_set, e);
> > +  return mfb_reis_set->contains (e);
> >  }
> >
> >  /* Creates a subloop of LOOP with latch edge LATCH.  */
> > @@ -666,15 +666,15 @@ form_subloop (struct loop *loop, edge latch)
> >    edge e, new_entry;
> >    struct loop *new_loop;
> >
> > -  mfb_reis_set = pointer_set_create ();
> > +  mfb_reis_set = new hash_set<edge>;
> >    FOR_EACH_EDGE (e, ei, loop->header->preds)
> >      {
> >        if (e != latch)
> > -       pointer_set_insert (mfb_reis_set, e);
> > +       mfb_reis_set->add (e);
> >      }
> >    new_entry = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
> >                                     NULL);
> > -  pointer_set_destroy (mfb_reis_set);
> > +  delete mfb_reis_set;
> >
> >    loop->header = new_entry->src;
> >
> > @@ -705,12 +705,12 @@ merge_latch_edges (struct loop *loop)
> >        if (dump_file)
> >         fprintf (dump_file, "Merged latch edges of loop %d\n", loop->num);
> >
> > -      mfb_reis_set = pointer_set_create ();
> > +      mfb_reis_set = new hash_set<edge>;
> >        FOR_EACH_VEC_ELT (latches, i, e)
> > -       pointer_set_insert (mfb_reis_set, e);
> > +       mfb_reis_set->add (e);
> >        latch = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
> >                                     NULL);
> > -      pointer_set_destroy (mfb_reis_set);
> > +      delete mfb_reis_set;
> >
> >        loop->header = latch->dest;
> >        loop->latch = latch->src;
> > diff --git a/gcc/cgraph.c b/gcc/cgraph.c
> > index a5d0749..7c72399 100644
> > --- a/gcc/cgraph.c
> > +++ b/gcc/cgraph.c
> > @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "tree-inline.h"
> >  #include "langhooks.h"
> >  #include "hashtab.h"
> > +#include "hash-set.h"
> >  #include "toplev.h"
> >  #include "flags.h"
> >  #include "debug.h"
> > @@ -2871,7 +2872,7 @@ cgraph_node::verify_node (void)
> >      {
> >        if (this_cfun->cfg)
> >         {
> > -         pointer_set_t *stmts = pointer_set_create ();
> > +         hash_set<gimple> stmts;
> >           int i;
> >           struct ipa_ref *ref = NULL;
> >
> > @@ -2881,13 +2882,13 @@ cgraph_node::verify_node (void)
> >             {
> >               for (gsi = gsi_start_phis (this_block);
> >                    !gsi_end_p (gsi); gsi_next (&gsi))
> > -               pointer_set_insert (stmts, gsi_stmt (gsi));
> > +               stmts.add (gsi_stmt (gsi));
> >               for (gsi = gsi_start_bb (this_block);
> >                    !gsi_end_p (gsi);
> >                    gsi_next (&gsi))
> >                 {
> >                   gimple stmt = gsi_stmt (gsi);
> > -                 pointer_set_insert (stmts, stmt);
> > +                 stmts.add (stmt);
> >                   if (is_gimple_call (stmt))
> >                     {
> >                       struct cgraph_edge *e = get_edge (stmt);
> > @@ -2931,13 +2932,12 @@ cgraph_node::verify_node (void)
> >                 }
> >               }
> >             for (i = 0; iterate_reference (i, ref); i++)
> > -             if (ref->stmt && !pointer_set_contains (stmts, ref->stmt))
> > +             if (ref->stmt && !stmts.contains (ref->stmt))
> >                 {
> >                   error ("reference to dead statement");
> >                   cgraph_debug_gimple_stmt (this_cfun, ref->stmt);
> >                   error_found = true;
> >                 }
> > -           pointer_set_destroy (stmts);
> >         }
> >        else
> >         /* No CFG available?!  */
> > diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
> > index 91811d7..a04958f 100644
> > --- a/gcc/cgraphbuild.c
> > +++ b/gcc/cgraphbuild.c
> > @@ -322,7 +322,6 @@ pass_build_cgraph_edges::execute (function *fun)
> >  {
> >    basic_block bb;
> >    struct cgraph_node *node = cgraph_node::get (current_function_decl);
> > -  struct pointer_set_t *visited_nodes = pointer_set_create ();
> >    gimple_stmt_iterator gsi;
> >    tree decl;
> >    unsigned ix;
> > @@ -386,7 +385,6 @@ pass_build_cgraph_edges::execute (function *fun)
> >        varpool_node::finalize_decl (decl);
> >    record_eh_tables (node, fun);
> >
> > -  pointer_set_destroy (visited_nodes);
> >    return 0;
> >  }
> >
> > @@ -405,15 +403,14 @@ make_pass_build_cgraph_edges (gcc::context *ctxt)
> >  void
> >  record_references_in_initializer (tree decl, bool only_vars)
> >  {
> > -  struct pointer_set_t *visited_nodes = pointer_set_create ();
> >    varpool_node *node = varpool_node::get_create (decl);
> > +  hash_set<tree> visited_nodes;
> >    struct record_reference_ctx ctx = {false, NULL};
> >
> >    ctx.varpool_node = node;
> >    ctx.only_vars = only_vars;
> >    walk_tree (&DECL_INITIAL (decl), record_reference,
> > -             &ctx, visited_nodes);
> > -  pointer_set_destroy (visited_nodes);
> > +             &ctx, &visited_nodes);
> >  }
> >
> >  /* Rebuild cgraph edges for current function node.  This needs to be run after
> > diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> > index 3080b9a..220b953 100644
> > --- a/gcc/cgraphunit.c
> > +++ b/gcc/cgraphunit.c
> > @@ -845,7 +845,7 @@ varpool_node::finalize_decl (tree decl)
> >     avoid udplicate work.  */
> >
> >  static void
> > -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> > +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
> >                                struct cgraph_edge *edge)
> >  {
> >    unsigned int i;
> > @@ -855,8 +855,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> >      = possible_polymorphic_call_targets
> >         (edge, &final, &cache_token);
> >
> > -  if (!pointer_set_insert (reachable_call_targets,
> > -                          cache_token))
> > +  if (!reachable_call_targets->add (cache_token))
> >      {
> >        if (cgraph_dump_file)
> >         dump_possible_polymorphic_call_targets
> > @@ -936,7 +935,7 @@ analyze_functions (void)
> >    struct cgraph_node *first_handled = first_analyzed;
> >    static varpool_node *first_analyzed_var;
> >    varpool_node *first_handled_var = first_analyzed_var;
> > -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> > +  hash_set<void *> reachable_call_targets;
> >
> >    symtab_node *node;
> >    symtab_node *next;
> > @@ -1035,7 +1034,7 @@ analyze_functions (void)
> >                     {
> >                       next = edge->next_callee;
> >                       if (edge->indirect_info->polymorphic)
> > -                       walk_polymorphic_call_targets (reachable_call_targets,
> > +                       walk_polymorphic_call_targets (&reachable_call_targets,
> >                                                        edge);
> >                     }
> >                 }
> > @@ -1123,7 +1122,6 @@ analyze_functions (void)
> >        symtab_node::dump_table (cgraph_dump_file);
> >      }
> >    bitmap_obstack_release (NULL);
> > -  pointer_set_destroy (reachable_call_targets);
> >    ggc_collect ();
> >    /* Initialize assembler name hash, in particular we want to trigger C++
> >       mangling and same body alias creation before we free DECL_ARGUMENTS
> > diff --git a/gcc/cp/class.c b/gcc/cp/class.c
> > index 0f611e1..d9b34f7 100644
> > --- a/gcc/cp/class.c
> > +++ b/gcc/cp/class.c
> > @@ -5359,15 +5359,15 @@ finalize_literal_type_property (tree t)
> >  void
> >  explain_non_literal_class (tree t)
> >  {
> > -  static struct pointer_set_t *diagnosed;
> > +  static hash_set<tree> *diagnosed;
> >
> >    if (!CLASS_TYPE_P (t))
> >      return;
> >    t = TYPE_MAIN_VARIANT (t);
> >
> >    if (diagnosed == NULL)
> > -    diagnosed = pointer_set_create ();
> > -  if (pointer_set_insert (diagnosed, t) != 0)
> > +    diagnosed = new hash_set<tree>;
> > +  if (diagnosed->add (t))
> >      /* Already explained.  */
> >      return;
> >
> > diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
> > index a35177b..3cfcbc6 100644
> > --- a/gcc/cp/cp-gimplify.c
> > +++ b/gcc/cp/cp-gimplify.c
> > @@ -871,7 +871,7 @@ omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
> >
> >  struct cp_genericize_data
> >  {
> > -  struct pointer_set_t *p_set;
> > +  hash_set<tree> *p_set;
> >    vec<tree> bind_expr_stack;
> >    struct cp_genericize_omp_taskreg *omp_ctx;
> >  };
> > @@ -884,7 +884,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
> >  {
> >    tree stmt = *stmt_p;
> >    struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
> > -  struct pointer_set_t *p_set = wtd->p_set;
> > +  hash_set<tree> *p_set = wtd->p_set;
> >
> >    /* If in an OpenMP context, note var uses.  */
> >    if (__builtin_expect (wtd->omp_ctx != NULL, 0)
> > @@ -924,7 +924,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
> >      }
> >
> >    /* Other than invisiref parms, don't walk the same tree twice.  */
> > -  if (pointer_set_contains (p_set, stmt))
> > +  if (p_set->contains (stmt))
> >      {
> >        *walk_subtrees = 0;
> >        return NULL_TREE;
> > @@ -1199,7 +1199,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
> >        return NULL;
> >      }
> >
> > -  pointer_set_insert (p_set, *stmt_p);
> > +  p_set->add (*stmt_p);
> >
> >    return NULL;
> >  }
> > @@ -1211,11 +1211,11 @@ cp_genericize_tree (tree* t_p)
> >  {
> >    struct cp_genericize_data wtd;
> >
> > -  wtd.p_set = pointer_set_create ();
> > +  wtd.p_set = new hash_set<tree>;
> >    wtd.bind_expr_stack.create (0);
> >    wtd.omp_ctx = NULL;
> >    cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
> > -  pointer_set_destroy (wtd.p_set);
> > +  delete wtd.p_set;
> >    wtd.bind_expr_stack.release ();
> >  }
> >
> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> > index 0c0d804..622de9c 100644
> > --- a/gcc/cp/cp-tree.h
> > +++ b/gcc/cp/cp-tree.h
> > @@ -6028,7 +6028,7 @@ extern void verify_stmt_tree                      (tree);
> >  extern linkage_kind decl_linkage               (tree);
> >  extern duration_kind decl_storage_duration     (tree);
> >  extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
> > -                             void*, struct pointer_set_t*);
> > +                             void*, hash_set<tree> *);
> >  #define cp_walk_tree(tp,func,data,pset) \
> >         walk_tree_1 (tp, func, data, pset, cp_walk_subtrees)
> >  #define cp_walk_tree_without_duplicates(tp,func,data) \
> > diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> > index aafb917..f70684f 100644
> > --- a/gcc/cp/decl.c
> > +++ b/gcc/cp/decl.c
> > @@ -8198,7 +8198,7 @@ check_static_variable_definition (tree decl, tree type)
> >  static tree
> >  stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
> >  {
> > -  struct pointer_set_t *pset = (struct pointer_set_t *)data;
> > +  hash_set<tree> *pset = (hash_set<tree> *)data;
> >    tree expr = *expr_p;
> >    if (TREE_CODE (expr) == SAVE_EXPR)
> >      {
> > @@ -8218,10 +8218,9 @@ stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
> >  static void
> >  stabilize_vla_size (tree size)
> >  {
> > -  struct pointer_set_t *pset = pointer_set_create ();
> > +  hash_set<tree> pset;
> >    /* Break out any function calls into temporary variables.  */
> > -  cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
> > -  pointer_set_destroy (pset);
> > +  cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
> >  }
> >
> >  /* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
> > diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
> > index 8fa3145..d79665e 100644
> > --- a/gcc/cp/decl2.c
> > +++ b/gcc/cp/decl2.c
> > @@ -3938,11 +3938,11 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
> >     supported, collect and return all the functions for which we should
> >     emit a hidden alias.  */
> >
> > -static struct pointer_set_t *
> > +static hash_set<tree> *
> >  collect_candidates_for_java_method_aliases (void)
> >  {
> >    struct cgraph_node *node;
> > -  struct pointer_set_t *candidates = NULL;
> > +  hash_set<tree> *candidates = NULL;
> >
> >  #ifndef HAVE_GAS_HIDDEN
> >    return candidates;
> > @@ -3957,8 +3957,8 @@ collect_candidates_for_java_method_aliases (void)
> >           && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
> >         {
> >           if (candidates == NULL)
> > -           candidates = pointer_set_create ();
> > -         pointer_set_insert (candidates, fndecl);
> > +           candidates = new hash_set<tree>;
> > +         candidates->add (fndecl);
> >         }
> >      }
> >
> > @@ -3973,7 +3973,7 @@ collect_candidates_for_java_method_aliases (void)
> >     by collect_candidates_for_java_method_aliases.  */
> >
> >  static void
> > -build_java_method_aliases (struct pointer_set_t *candidates)
> > +build_java_method_aliases (hash_set<tree> *candidates)
> >  {
> >    struct cgraph_node *node;
> >
> > @@ -3986,7 +3986,7 @@ build_java_method_aliases (struct pointer_set_t *candidates)
> >        tree fndecl = node->decl;
> >
> >        if (TREE_ASM_WRITTEN (fndecl)
> > -         && pointer_set_contains (candidates, fndecl))
> > +         && candidates->contains (fndecl))
> >         {
> >           /* Mangle the name in a predictable way; we need to reference
> >              this from a java compiled object file.  */
> > @@ -4296,7 +4296,7 @@ cp_write_global_declarations (void)
> >    unsigned ssdf_count = 0;
> >    int retries = 0;
> >    tree decl;
> > -  struct pointer_set_t *candidates;
> > +  hash_set<tree> *candidates;
> >
> >    locus = input_location;
> >    at_eof = 1;
> > @@ -4713,7 +4713,7 @@ cp_write_global_declarations (void)
> >    if (candidates)
> >      {
> >        build_java_method_aliases (candidates);
> > -      pointer_set_destroy (candidates);
> > +      delete candidates;
> >      }
> >
> >    finish_repo ();
> > diff --git a/gcc/cp/error.c b/gcc/cp/error.c
> > index fa3bdc4..c8987ee 100644
> > --- a/gcc/cp/error.c
> > +++ b/gcc/cp/error.c
> > @@ -1325,7 +1325,7 @@ dump_template_decl (cxx_pretty_printer *pp, tree t, int flags)
> >
> >  struct find_typenames_t
> >  {
> > -  struct pointer_set_t *p_set;
> > +  hash_set<tree> *p_set;
> >    vec<tree, va_gc> *typenames;
> >  };
> >
> > @@ -1351,7 +1351,7 @@ find_typenames_r (tree *tp, int *walk_subtrees, void *data)
> >        return NULL_TREE;
> >      }
> >
> > -  if (mv && (mv == *tp || !pointer_set_insert (d->p_set, mv)))
> > +  if (mv && (mv == *tp || !d->p_set->add (mv)))
> >      vec_safe_push (d->typenames, mv);
> >
> >    /* Search into class template arguments, which cp_walk_subtrees
> > @@ -1367,11 +1367,11 @@ static vec<tree, va_gc> *
> >  find_typenames (tree t)
> >  {
> >    struct find_typenames_t ft;
> > -  ft.p_set = pointer_set_create ();
> > +  ft.p_set = new hash_set<tree>;
> >    ft.typenames = NULL;
> >    cp_walk_tree (&TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
> >                 find_typenames_r, &ft, ft.p_set);
> > -  pointer_set_destroy (ft.p_set);
> > +  delete ft.p_set;
> >    return ft.typenames;
> >  }
> >
> > diff --git a/gcc/cp/method.c b/gcc/cp/method.c
> > index e5fa0c1..65c5621 100644
> > --- a/gcc/cp/method.c
> > +++ b/gcc/cp/method.c
> > @@ -1480,7 +1480,7 @@ maybe_explain_implicit_delete (tree decl)
> >    if (DECL_DEFAULTED_FN (decl))
> >      {
> >        /* Not marked GTY; it doesn't need to be GC'd or written to PCH.  */
> > -      static struct pointer_set_t *explained;
> > +      static hash_set<tree> *explained;
> >
> >        special_function_kind sfk;
> >        location_t loc;
> > @@ -1488,8 +1488,8 @@ maybe_explain_implicit_delete (tree decl)
> >        tree ctype;
> >
> >        if (!explained)
> > -       explained = pointer_set_create ();
> > -      if (pointer_set_insert (explained, decl))
> > +       explained = new hash_set<tree>;
> > +      if (explained->add (decl))
> >         return true;
> >
> >        sfk = special_function_p (decl);
> > diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> > index 75b46ac..6e779a6 100644
> > --- a/gcc/cp/name-lookup.c
> > +++ b/gcc/cp/name-lookup.c
> > @@ -35,7 +35,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "debug.h"
> >  #include "c-family/c-pragma.h"
> >  #include "params.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >
> >  /* The bindings for a particular name in a particular scope.  */
> >
> > @@ -5152,7 +5152,7 @@ struct arg_lookup
> >    vec<tree, va_gc> *namespaces;
> >    vec<tree, va_gc> *classes;
> >    tree functions;
> > -  struct pointer_set_t *fn_set;
> > +  hash_set<tree> *fn_set;
> >  };
> >
> >  static bool arg_assoc (struct arg_lookup*, tree);
> > @@ -5175,7 +5175,7 @@ add_function (struct arg_lookup *k, tree fn)
> >    if (!is_overloaded_fn (fn))
> >      /* All names except those of (possibly overloaded) functions and
> >         function templates are ignored.  */;
> > -  else if (k->fn_set && pointer_set_insert (k->fn_set, fn))
> > +  else if (k->fn_set && k->fn_set->add (fn))
> >      /* It's already in the list.  */;
> >    else if (!k->functions)
> >      k->functions = fn;
> > @@ -5639,9 +5639,9 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
> >        /* We shouldn't be here if lookup found something other than
> >          namespace-scope functions.  */
> >        gcc_assert (DECL_NAMESPACE_SCOPE_P (OVL_CURRENT (fns)));
> > -      k.fn_set = pointer_set_create ();
> > +      k.fn_set = new hash_set<tree>;
> >        for (ovl = fns; ovl; ovl = OVL_NEXT (ovl))
> > -       pointer_set_insert (k.fn_set, OVL_CURRENT (ovl));
> > +       k.fn_set->add (OVL_CURRENT (ovl));
> >      }
> >    else
> >      k.fn_set = NULL;
> > @@ -5661,8 +5661,7 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
> >
> >    release_tree_vector (k.classes);
> >    release_tree_vector (k.namespaces);
> > -  if (k.fn_set)
> > -    pointer_set_destroy (k.fn_set);
> > +  delete k.fn_set;
> >
> >    return fns;
> >  }
> > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> > index b32cf6c..9b156f5 100644
> > --- a/gcc/cp/pt.c
> > +++ b/gcc/cp/pt.c
> > @@ -147,7 +147,7 @@ static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
> >  static tree convert_template_argument (tree, tree, tree,
> >                                        tsubst_flags_t, int, tree);
> >  static int for_each_template_parm (tree, tree_fn_t, void*,
> > -                                  struct pointer_set_t*, bool);
> > +                                  hash_set<tree> *, bool);
> >  static tree expand_template_argument_pack (tree);
> >  static tree build_template_parm_index (int, int, int, tree, tree);
> >  static bool inline_needs_template_parms (tree, bool);
> > @@ -3080,7 +3080,7 @@ struct find_parameter_pack_data
> >    tree* parameter_packs;
> >
> >    /* Set of AST nodes that have been visited by the traversal.  */
> > -  struct pointer_set_t *visited;
> > +  hash_set<tree> *visited;
> >  };
> >
> >  /* Identifies all of the argument packs that occur in a template
> > @@ -3243,9 +3243,9 @@ uses_parameter_packs (tree t)
> >    tree parameter_packs = NULL_TREE;
> >    struct find_parameter_pack_data ppd;
> >    ppd.parameter_packs = &parameter_packs;
> > -  ppd.visited = pointer_set_create ();
> > +  ppd.visited = new hash_set<tree>;
> >    cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
> > -  pointer_set_destroy (ppd.visited);
> > +  delete ppd.visited;
> >    return parameter_packs != NULL_TREE;
> >  }
> >
> > @@ -3292,7 +3292,7 @@ make_pack_expansion (tree arg)
> >
> >        /* Determine which parameter packs will be used by the base
> >           class expansion.  */
> > -      ppd.visited = pointer_set_create ();
> > +      ppd.visited = new hash_set<tree>;
> >        ppd.parameter_packs = &parameter_packs;
> >        cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
> >                      &ppd, ppd.visited);
> > @@ -3300,7 +3300,7 @@ make_pack_expansion (tree arg)
> >        if (parameter_packs == NULL_TREE)
> >          {
> >            error ("base initializer expansion %<%T%> contains no parameter packs", arg);
> > -          pointer_set_destroy (ppd.visited);
> > +          delete ppd.visited;
> >            return error_mark_node;
> >          }
> >
> > @@ -3317,7 +3317,7 @@ make_pack_expansion (tree arg)
> >              }
> >          }
> >
> > -      pointer_set_destroy (ppd.visited);
> > +      delete ppd.visited;
> >
> >        /* Create the pack expansion type for the base type.  */
> >        purpose = cxx_make_type (TYPE_PACK_EXPANSION);
> > @@ -3352,9 +3352,9 @@ make_pack_expansion (tree arg)
> >
> >    /* Determine which parameter packs will be expanded.  */
> >    ppd.parameter_packs = &parameter_packs;
> > -  ppd.visited = pointer_set_create ();
> > +  ppd.visited = new hash_set<tree>;
> >    cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
> > -  pointer_set_destroy (ppd.visited);
> > +  delete ppd.visited;
> >
> >    /* Make sure we found some parameter packs.  */
> >    if (parameter_packs == NULL_TREE)
> > @@ -3399,9 +3399,9 @@ check_for_bare_parameter_packs (tree t)
> >      t = TREE_TYPE (t);
> >
> >    ppd.parameter_packs = &parameter_packs;
> > -  ppd.visited = pointer_set_create ();
> > +  ppd.visited = new hash_set<tree>;
> >    cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
> > -  pointer_set_destroy (ppd.visited);
> > +  delete ppd.visited;
> >
> >    if (parameter_packs)
> >      {
> > @@ -4381,11 +4381,11 @@ fixed_parameter_pack_p (tree parm)
> >    tree parameter_packs = NULL_TREE;
> >    struct find_parameter_pack_data ppd;
> >    ppd.parameter_packs = &parameter_packs;
> > -  ppd.visited = pointer_set_create ();
> > +  ppd.visited = new hash_set<tree>;
> >
> >    fixed_parameter_pack_p_1 (parm, &ppd);
> >
> > -  pointer_set_destroy (ppd.visited);
> > +  delete ppd.visited;
> >    return parameter_packs;
> >  }
> >
> > @@ -7907,7 +7907,7 @@ struct pair_fn_data
> >    /* True when we should also visit template parameters that occur in
> >       non-deduced contexts.  */
> >    bool include_nondeduced_p;
> > -  struct pointer_set_t *visited;
> > +  hash_set<tree> *visited;
> >  };
> >
> >  /* Called from for_each_template_parm via walk_tree.  */
> > @@ -8107,7 +8107,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
> >
> >  static int
> >  for_each_template_parm (tree t, tree_fn_t fn, void* data,
> > -                       struct pointer_set_t *visited,
> > +                       hash_set<tree> *visited,
> >                         bool include_nondeduced_p)
> >  {
> >    struct pair_fn_data pfd;
> > @@ -8126,7 +8126,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
> >    if (visited)
> >      pfd.visited = visited;
> >    else
> > -    pfd.visited = pointer_set_create ();
> > +    pfd.visited = new hash_set<tree>;
> >    result = cp_walk_tree (&t,
> >                          for_each_template_parm_r,
> >                          &pfd,
> > @@ -8135,7 +8135,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
> >    /* Clean up.  */
> >    if (!visited)
> >      {
> > -      pointer_set_destroy (pfd.visited);
> > +      delete pfd.visited;
> >        pfd.visited = 0;
> >      }
> >
> > diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
> > index c87764d..735284e 100644
> > --- a/gcc/cp/semantics.c
> > +++ b/gcc/cp/semantics.c
> > @@ -8031,7 +8031,7 @@ register_constexpr_fundef (tree fun, tree body)
> >  void
> >  explain_invalid_constexpr_fn (tree fun)
> >  {
> > -  static struct pointer_set_t *diagnosed;
> > +  static hash_set<tree> *diagnosed;
> >    tree body;
> >    location_t save_loc;
> >    /* Only diagnose defaulted functions or instantiations.  */
> > @@ -8039,8 +8039,8 @@ explain_invalid_constexpr_fn (tree fun)
> >        && !is_instantiation_of_constexpr (fun))
> >      return;
> >    if (diagnosed == NULL)
> > -    diagnosed = pointer_set_create ();
> > -  if (pointer_set_insert (diagnosed, fun) != 0)
> > +    diagnosed = new hash_set<tree>;
> > +  if (diagnosed->add (fun))
> >      /* Already explained.  */
> >      return;
> >
> > diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
> > index f6c5693..697a02b 100644
> > --- a/gcc/cp/tree.c
> > +++ b/gcc/cp/tree.c
> > @@ -3485,7 +3485,7 @@ cxx_type_hash_eq (const_tree typea, const_tree typeb)
> >
> >  tree
> >  cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
> > -                 void *data, struct pointer_set_t *pset)
> > +                 void *data, hash_set<tree> *pset)
> >  {
> >    enum tree_code code = TREE_CODE (*tp);
> >    tree result;
> > diff --git a/gcc/cprop.c b/gcc/cprop.c
> > index 6291c91..4234afa 100644
> > --- a/gcc/cprop.c
> > +++ b/gcc/cprop.c
> > @@ -167,7 +167,7 @@ reg_available_p (const_rtx x, const_rtx insn ATTRIBUTE_UNUSED)
> >     ??? May need to make things more elaborate.  Later, as necessary.  */
> >
> >  static unsigned int
> > -hash_set (int regno, int hash_table_size)
> > +hash_mod (int regno, int hash_table_size)
> >  {
> >    return (unsigned) regno % hash_table_size;
> >  }
> > @@ -187,7 +187,7 @@ insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table,
> >    struct expr *cur_expr, *last_expr = NULL;
> >    struct occr *cur_occr;
> >
> > -  hash = hash_set (REGNO (dest), table->size);
> > +  hash = hash_mod (REGNO (dest), table->size);
> >
> >    for (cur_expr = table->table[hash]; cur_expr;
> >         cur_expr = cur_expr->next_same_hash)
> > @@ -483,7 +483,7 @@ compute_hash_table (struct hash_table_d *table)
> >  static struct expr *
> >  lookup_set (unsigned int regno, struct hash_table_d *table)
> >  {
> > -  unsigned int hash = hash_set (regno, table->size);
> > +  unsigned int hash = hash_mod (regno, table->size);
> >    struct expr *expr;
> >
> >    expr = table->table[hash];
> > diff --git a/gcc/cse.c b/gcc/cse.c
> > index 34f9364..dd9a076 100644
> > --- a/gcc/cse.c
> > +++ b/gcc/cse.c
> > @@ -41,7 +41,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "tree-pass.h"
> >  #include "df.h"
> >  #include "dbgcnt.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >
> >  /* The basic idea of common subexpression elimination is to go
> >     through the code, keeping a record of expressions that would
> > @@ -2906,7 +2906,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >                       enum machine_mode *pmode1, enum machine_mode *pmode2)
> >  {
> >    rtx arg1, arg2;
> > -  struct pointer_set_t *visited = NULL;
> > +  hash_set<rtx> *visited = NULL;
> >    /* Set nonzero when we find something of interest.  */
> >    rtx x = NULL;
> >
> > @@ -2923,8 +2923,8 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >        if (x)
> >         {
> >           if (!visited)
> > -           visited = pointer_set_create ();
> > -         pointer_set_insert (visited, x);
> > +           visited = new hash_set<rtx>;
> > +         visited->add (x);
> >           x = 0;
> >         }
> >
> > @@ -3005,7 +3005,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >             continue;
> >
> >           /* If it's a comparison we've used before, skip it.  */
> > -         if (visited && pointer_set_contains (visited, p->exp))
> > +         if (visited && visited->contains (p->exp))
> >             continue;
> >
> >           if (GET_CODE (p->exp) == COMPARE
> > @@ -3087,7 +3087,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >    *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0);
> >
> >    if (visited)
> > -    pointer_set_destroy (visited);
> > +    delete visited;
> >    return code;
> >  }
> >
> > diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
> > index 68ba70f..410efb1 100644
> > --- a/gcc/fortran/openmp.c
> > +++ b/gcc/fortran/openmp.c
> > @@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "arith.h"
> >  #include "match.h"
> >  #include "parse.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >
> >  /* Match an end of OpenMP directive.  End of OpenMP directive is optional
> >     whitespace, followed by '\n' or comment '!'.  */
> > @@ -3013,8 +3013,8 @@ resolve_omp_atomic (gfc_code *code)
> >  struct omp_context
> >  {
> >    gfc_code *code;
> > -  struct pointer_set_t *sharing_clauses;
> > -  struct pointer_set_t *private_iterators;
> > +  hash_set<gfc_symbol *> *sharing_clauses;
> > +  hash_set<gfc_symbol *> *private_iterators;
> >    struct omp_context *previous;
> >  } *omp_current_ctx;
> >  static gfc_code *omp_current_do_code;
> > @@ -3057,8 +3057,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
> >    int list;
> >
> >    ctx.code = code;
> > -  ctx.sharing_clauses = pointer_set_create ();
> > -  ctx.private_iterators = pointer_set_create ();
> > +  ctx.sharing_clauses = new hash_set<gfc_symbol *>;
> > +  ctx.private_iterators = new hash_set<gfc_symbol *>;
> >    ctx.previous = omp_current_ctx;
> >    omp_current_ctx = &ctx;
> >
> > @@ -3072,7 +3072,7 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
> >        case OMP_LIST_REDUCTION:
> >        case OMP_LIST_LINEAR:
> >         for (n = omp_clauses->lists[list]; n; n = n->next)
> > -         pointer_set_insert (ctx.sharing_clauses, n->sym);
> > +         ctx.sharing_clauses->add (n->sym);
> >         break;
> >        default:
> >         break;
> > @@ -3097,8 +3097,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
> >      }
> >
> >    omp_current_ctx = ctx.previous;
> > -  pointer_set_destroy (ctx.sharing_clauses);
> > -  pointer_set_destroy (ctx.private_iterators);
> > +  delete ctx.sharing_clauses;
> > +  delete ctx.private_iterators;
> >  }
> >
> >
> > @@ -3154,10 +3154,10 @@ gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym)
> >    if (omp_current_ctx == NULL)
> >      return;
> >
> > -  if (pointer_set_contains (omp_current_ctx->sharing_clauses, sym))
> > +  if (omp_current_ctx->sharing_clauses->contains (sym))
> >      return;
> >
> > -  if (! pointer_set_insert (omp_current_ctx->private_iterators, sym))
> > +  if (! omp_current_ctx->private_iterators->add (sym))
> >      {
> >        gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
> >        gfc_omp_namelist *p;
> > diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
> > index 8b56151..babe48f 100644
> > --- a/gcc/fortran/trans-decl.c
> > +++ b/gcc/fortran/trans-decl.c
> > @@ -40,7 +40,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "cgraph.h"
> >  #include "debug.h"
> >  #include "gfortran.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "constructor.h"
> >  #include "trans.h"
> >  #include "trans-types.h"
> > @@ -63,7 +63,7 @@ static GTY(()) tree parent_fake_result_decl;
> >  static GTY(()) tree saved_function_decls;
> >  static GTY(()) tree saved_parent_function_decls;
> >
> > -static struct pointer_set_t *nonlocal_dummy_decl_pset;
> > +static hash_set<tree> *nonlocal_dummy_decl_pset;
> >  static GTY(()) tree nonlocal_dummy_decls;
> >
> >  /* Holds the variable DECLs that are locals.  */
> > @@ -1094,9 +1094,9 @@ gfc_nonlocal_dummy_array_decl (gfc_symbol *sym)
> >    tree decl, dummy;
> >
> >    if (! nonlocal_dummy_decl_pset)
> > -    nonlocal_dummy_decl_pset = pointer_set_create ();
> > +    nonlocal_dummy_decl_pset = new hash_set<tree>;
> >
> > -  if (pointer_set_insert (nonlocal_dummy_decl_pset, sym->backend_decl))
> > +  if (nonlocal_dummy_decl_pset->add (sym->backend_decl))
> >      return;
> >
> >    dummy = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl);
> > @@ -5861,7 +5861,7 @@ gfc_generate_function_code (gfc_namespace * ns)
> >      {
> >        BLOCK_VARS (DECL_INITIAL (fndecl))
> >         = chainon (BLOCK_VARS (DECL_INITIAL (fndecl)), nonlocal_dummy_decls);
> > -      pointer_set_destroy (nonlocal_dummy_decl_pset);
> > +      delete nonlocal_dummy_decl_pset;
> >        nonlocal_dummy_decls = NULL;
> >        nonlocal_dummy_decl_pset = NULL;
> >      }
> > diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
> > index b6f0495..f4f6757 100644
> > --- a/gcc/gimple-walk.c
> > +++ b/gcc/gimple-walk.c
> > @@ -180,7 +180,7 @@ tree
> >  walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
> >                 struct walk_stmt_info *wi)
> >  {
> > -  struct pointer_set_t *pset = (wi) ? wi->pset : NULL;
> > +  hash_set<tree> *pset = (wi) ? wi->pset : NULL;
> >    unsigned i;
> >    tree ret = NULL_TREE;
> >
> > diff --git a/gcc/gimple-walk.h b/gcc/gimple-walk.h
> > index 555eb18..5b75fdc 100644
> > --- a/gcc/gimple-walk.h
> > +++ b/gcc/gimple-walk.h
> > @@ -36,7 +36,7 @@ struct walk_stmt_info
> >    /* Pointer map used to mark visited tree nodes when calling
> >       walk_tree on each operand.  If set to NULL, duplicate tree nodes
> >       will be visited more than once.  */
> > -  struct pointer_set_t *pset;
> > +  hash_set<tree> *pset;
> >
> >    /* Operand returned by the callbacks.  This is set when calling
> >       walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
> > diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> > index 4ab36d0..c0ae7cc 100644
> > --- a/gcc/gimplify.c
> > +++ b/gcc/gimplify.c
> > @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "coretypes.h"
> >  #include "tree.h"
> >  #include "expr.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "hash-table.h"
> >  #include "basic-block.h"
> > @@ -134,7 +135,7 @@ struct gimplify_omp_ctx
> >  {
> >    struct gimplify_omp_ctx *outer_context;
> >    splay_tree variables;
> > -  struct pointer_set_t *privatized_types;
> > +  hash_set<tree> *privatized_types;
> >    location_t location;
> >    enum omp_clause_default_kind default_kind;
> >    enum omp_region_type region_type;
> > @@ -352,7 +353,7 @@ new_omp_context (enum omp_region_type region_type)
> >    c = XCNEW (struct gimplify_omp_ctx);
> >    c->outer_context = gimplify_omp_ctxp;
> >    c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
> > -  c->privatized_types = pointer_set_create ();
> > +  c->privatized_types = new hash_set<tree>;
> >    c->location = input_location;
> >    c->region_type = region_type;
> >    if ((region_type & ORT_TASK) == 0)
> > @@ -369,7 +370,7 @@ static void
> >  delete_omp_context (struct gimplify_omp_ctx *c)
> >  {
> >    splay_tree_delete (c->variables);
> > -  pointer_set_destroy (c->privatized_types);
> > +  delete c->privatized_types;
> >    XDELETE (c);
> >  }
> >
> > @@ -744,7 +745,7 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
> >       copy their subtrees if we can make sure to do it only once.  */
> >    if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
> >      {
> > -      if (data && !pointer_set_insert ((struct pointer_set_t *)data, t))
> > +      if (data && !((hash_set<tree> *)data)->add (t))
> >         ;
> >        else
> >         *walk_subtrees = 0;
> > @@ -829,15 +830,14 @@ unshare_body (tree fndecl)
> >    struct cgraph_node *cgn = cgraph_node::get (fndecl);
> >    /* If the language requires deep unsharing, we need a pointer set to make
> >       sure we don't repeatedly unshare subtrees of unshareable nodes.  */
> > -  struct pointer_set_t *visited
> > -    = lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
> > +  hash_set<tree> *visited
> > +    = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
> >
> >    copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
> >    copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
> >    copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
> >
> > -  if (visited)
> > -    pointer_set_destroy (visited);
> > +  delete visited;
> >
> >    if (cgn)
> >      for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
> > @@ -1733,7 +1733,7 @@ gimplify_conversion (tree *expr_p)
> >  }
> >
> >  /* Nonlocal VLAs seen in the current function.  */
> > -static struct pointer_set_t *nonlocal_vlas;
> > +static hash_set<tree> *nonlocal_vlas;
> >
> >  /* The VAR_DECLs created for nonlocal VLAs for debug info purposes.  */
> >  static tree nonlocal_vla_vars;
> > @@ -1784,7 +1784,7 @@ gimplify_var_or_parm_decl (tree *expr_p)
> >                  && (ctx->region_type == ORT_WORKSHARE
> >                      || ctx->region_type == ORT_SIMD))
> >             ctx = ctx->outer_context;
> > -         if (!ctx && !pointer_set_insert (nonlocal_vlas, decl))
> > +         if (!ctx && !nonlocal_vlas->add (decl))
> >             {
> >               tree copy = copy_node (decl);
> >
> > @@ -5463,7 +5463,7 @@ omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
> >      return;
> >    type = TYPE_MAIN_VARIANT (type);
> >
> > -  if (pointer_set_insert (ctx->privatized_types, type))
> > +  if (ctx->privatized_types->add (type))
> >      return;
> >
> >    switch (TREE_CODE (type))
> > @@ -8766,7 +8766,7 @@ gimplify_body (tree fndecl, bool do_parms)
> >
> >    cgn = cgraph_node::get (fndecl);
> >    if (cgn && cgn->origin)
> > -    nonlocal_vlas = pointer_set_create ();
> > +    nonlocal_vlas = new hash_set<tree>;
> >
> >    /* Make sure input_location isn't set to something weird.  */
> >    input_location = DECL_SOURCE_LOCATION (fndecl);
> > @@ -8830,7 +8830,7 @@ gimplify_body (tree fndecl, bool do_parms)
> >                          nonlocal_vla_vars);
> >           nonlocal_vla_vars = NULL_TREE;
> >         }
> > -      pointer_set_destroy (nonlocal_vlas);
> > +      delete nonlocal_vlas;
> >        nonlocal_vlas = NULL;
> >      }
> >
> > diff --git a/gcc/godump.c b/gcc/godump.c
> > index 2afd7f1..7566f4d 100644
> > --- a/gcc/godump.c
> > +++ b/gcc/godump.c
> > @@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "diagnostic-core.h"
> >  #include "tree.h"
> >  #include "ggc.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "obstack.h"
> >  #include "debug.h"
> >  #include "wide-int-print.h"
> > @@ -525,11 +525,11 @@ go_type_decl (tree decl, int local)
> >  struct godump_container
> >  {
> >    /* DECLs that we have already seen.  */
> > -  struct pointer_set_t *decls_seen;
> > +  hash_set<tree> decls_seen;
> >
> >    /* Types which may potentially have to be defined as dummy
> >       types.  */
> > -  struct pointer_set_t *pot_dummy_types;
> > +  hash_set<const char *> pot_dummy_types;
> >
> >    /* Go keywords.  */
> >    htab_t keyword_hash;
> > @@ -569,8 +569,8 @@ go_format_type (struct godump_container *container, tree type,
> >    ob = &container->type_obstack;
> >
> >    if (TYPE_NAME (type) != NULL_TREE
> > -      && (pointer_set_contains (container->decls_seen, type)
> > -         || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
> > +      && (container->decls_seen.contains (type)
> > +         || container->decls_seen.contains (TYPE_NAME (type)))
> >        && (AGGREGATE_TYPE_P (type)
> >           || POINTER_TYPE_P (type)
> >           || TREE_CODE (type) == FUNCTION_TYPE))
> > @@ -590,7 +590,7 @@ go_format_type (struct godump_container *container, tree type,
> >        return ret;
> >      }
> >
> > -  pointer_set_insert (container->decls_seen, type);
> > +  container->decls_seen.add (type);
> >
> >    switch (TREE_CODE (type))
> >      {
> > @@ -697,8 +697,7 @@ go_format_type (struct godump_container *container, tree type,
> >              definition.  So this struct or union is a potential dummy
> >              type.  */
> >           if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
> > -           pointer_set_insert (container->pot_dummy_types,
> > -                               IDENTIFIER_POINTER (name));
> > +           container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
> >
> >           return ret;
> >          }
> > @@ -948,10 +947,10 @@ go_output_typedef (struct godump_container *container, tree decl)
> >       separately.  */
> >    if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
> >        && TYPE_SIZE (TREE_TYPE (decl)) != 0
> > -      && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
> > +      && !container->decls_seen.contains (TREE_TYPE (decl))
> >        && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
> > -         || !pointer_set_contains (container->decls_seen,
> > -                                   TYPE_CANONICAL (TREE_TYPE (decl)))))
> > +         || !container->decls_seen.contains
> > +                                   (TYPE_CANONICAL (TREE_TYPE (decl)))))
> >      {
> >        tree element;
> >
> > @@ -988,10 +987,9 @@ go_output_typedef (struct godump_container *container, tree decl)
> >           mhval->value = xstrdup (buf);
> >           *slot = mhval;
> >         }
> > -      pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
> > +      container->decls_seen.add (TREE_TYPE (decl));
> >        if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
> > -       pointer_set_insert (container->decls_seen,
> > -                           TYPE_CANONICAL (TREE_TYPE (decl)));
> > +       container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
> >      }
> >
> >    if (DECL_NAME (decl) != NULL_TREE)
> > @@ -1027,7 +1025,7 @@ go_output_typedef (struct godump_container *container, tree decl)
> >                      size);
> >         }
> >
> > -      pointer_set_insert (container->decls_seen, decl);
> > +      container->decls_seen.add (decl);
> >      }
> >    else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
> >      {
> > @@ -1072,11 +1070,11 @@ go_output_var (struct godump_container *container, tree decl)
> >  {
> >    bool is_valid;
> >
> > -  if (pointer_set_contains (container->decls_seen, decl)
> > -      || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
> > +  if (container->decls_seen.contains (decl)
> > +      || container->decls_seen.contains (DECL_NAME (decl)))
> >      return;
> > -  pointer_set_insert (container->decls_seen, decl);
> > -  pointer_set_insert (container->decls_seen, DECL_NAME (decl));
> > +  container->decls_seen.add (decl);
> > +  container->decls_seen.add (DECL_NAME (decl));
> >
> >    is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
> >    if (is_valid
> > @@ -1103,11 +1101,10 @@ go_output_var (struct godump_container *container, tree decl)
> >      {
> >        tree type_name = TYPE_NAME (TREE_TYPE (decl));
> >        if (TREE_CODE (type_name) == IDENTIFIER_NODE)
> > -       pointer_set_insert (container->pot_dummy_types,
> > -                           IDENTIFIER_POINTER (type_name));
> > +       container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
> >        else if (TREE_CODE (type_name) == TYPE_DECL)
> > -       pointer_set_insert (container->pot_dummy_types,
> > -                           IDENTIFIER_POINTER (DECL_NAME (type_name)));
> > +       container->pot_dummy_types.add
> > +                           (IDENTIFIER_POINTER (DECL_NAME (type_name)));
> >      }
> >  }
> >
> > @@ -1147,10 +1144,10 @@ keyword_hash_init (struct godump_container *container)
> >
> >  /* Traversing the pot_dummy_types and seeing which types are present
> >     in the global types hash table and creating dummy definitions if
> > -   not found.  This function is invoked by pointer_set_traverse.  */
> > +   not found.  This function is invoked by hash_set::traverse.  */
> >
> > -static bool
> > -find_dummy_types (const void *ptr, void *adata)
> > +bool
> > +find_dummy_types (const char *const &ptr, godump_container *adata)
> >  {
> >    struct godump_container *data = (struct godump_container *) adata;
> >    const char *type = (const char *) ptr;
> > @@ -1175,8 +1172,6 @@ go_finish (const char *filename)
> >
> >    real_debug_hooks->finish (filename);
> >
> > -  container.decls_seen = pointer_set_create ();
> > -  container.pot_dummy_types = pointer_set_create ();
> >    container.type_hash = htab_create (100, htab_hash_string,
> >                                       string_hash_eq, NULL);
> >    container.invalid_hash = htab_create (10, htab_hash_string,
> > @@ -1211,11 +1206,9 @@ go_finish (const char *filename)
> >    htab_traverse_noresize (macro_hash, go_print_macro, NULL);
> >
> >    /* To emit dummy definitions.  */
> > -  pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
> > -                        (void *) &container);
> > +  container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
> > +                        (&container);
> >
> > -  pointer_set_destroy (container.decls_seen);
> > -  pointer_set_destroy (container.pot_dummy_types);
> >    htab_delete (container.type_hash);
> >    htab_delete (container.invalid_hash);
> >    htab_delete (container.keyword_hash);
> > diff --git a/gcc/hash-set.h b/gcc/hash-set.h
> > new file mode 100644
> > index 0000000..47bae9e
> > --- /dev/null
> > +++ b/gcc/hash-set.h
> > @@ -0,0 +1,173 @@
> > +/* A type-safe hash set.
> > +   Copyright (C) 2014 Free Software Foundation, Inc.
> > +
> > +This file is part of GCC.
> > +
> > +GCC is free software; you can redistribute it and/or modify it under
> > +the terms of the GNU General Public License as published by the Free
> > +Software Foundation; either version 3, or (at your option) any later
> > +version.
> > +
> > +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> > +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> > +for more details.
> > +
> > +You should have received a copy of the GNU General Public License
> > +along with GCC; see the file COPYING3.  If not see
> > +<http://www.gnu.org/licenses/>.  */
> > +
> > +
> > +#ifndef hash_set_h
> > +#define hash_set_h
> > +
> > +#include "hash-table.h"
> > +
> > +/* implement default behavior for traits when types allow it.  */
> > +
> > +struct default_hashset_traits
> > +{
> > +  /* Hashes the passed in key.  */
> > +
> > +  template<typename T>
> > +  static hashval_t
> > +  hash (T *p)
> > +    {
> > +      return uintptr_t(p) >> 3;
> > +    }
> > +
> > +  template<typename T> static hashval_t hash(const T &v) { return v; }
> > +
> > +  /* Return true if the two keys passed as arguments are equal.  */
> > +
> > +  template<typename T>
> > +  static bool
> > +  equal (const T &a, const T &b)
> > +    {
> > +      return a == b;
> > +    }
> > +
> > +  /* Called to dispose of the key before marking the entry as deleted.  */
> > +
> > +  template<typename T> static void remove (T &v) { v.~T (); }
> > +
> > +  /* Mark the passed in entry as being deleted.  */
> > +
> > +  template<typename T>
> > +  static void
> > +  mark_deleted (T *&e)
> > +    {
> > +      e = reinterpret_cast<void *> (1);
> > +    }
> > +
> > +  /* Mark the passed in entry as being empty.  */
> > +
> > +  template<typename T>
> > +  static void
> > +  mark_empty (T *&e)
> > +    {
> > +      e = NULL;
> > +    }
> > +
> > +  /* Return true if the passed in entry is marked as deleted.  */
> > +
> > +  template<typename T>
> > +  static bool
> > +  is_deleted (T *e)
> > +    {
> > +      return e == reinterpret_cast<void *> (1);
> > +    }
> > +
> > +  /* Return true if the passed in entry is marked as empty.  */
> > +
> > +  template<typename T> static bool is_empty (T *e) { return e == NULL; }
> > +};
> > +
> > +template<typename Key, typename Traits = default_hashset_traits>
> > +class hash_set
> > +{
> > +  struct hash_entry
> > +  {
> > +    Key m_key;
> > +
> > +    typedef hash_entry value_type;
> > +    typedef Key compare_type;
> > +    typedef int store_values_directly;
> > +
> > +    static hashval_t hash (const hash_entry &e)
> > +      {
> > +               return Traits::hash (e.m_key);
> > +      }
> > +
> > +    static bool equal (const hash_entry &a, const Key &b)
> > +               {
> > +         return Traits::equal (a.m_key, b);
> > +               }
> > +
> > +    static void remove (hash_entry &e) { Traits::remove (e.m_key); }
> > +
> > +    static void
> > +    mark_deleted (hash_entry &e)
> > +      {
> > +               Traits::mark_deleted (e.m_key);
> > +      }
> > +
> > +    static bool is_deleted (const hash_entry &e)
> > +      {
> > +               return Traits::is_deleted (e.m_key);
> > +      }
> > +
> > +    static void
> > +    mark_empty (hash_entry &e)
> > +      {
> > +       Traits::mark_empty (e.m_key);
> > +      }
> > +
> > +    static bool
> > +    is_empty (const hash_entry &e)
> > +      {
> > +       return Traits::is_empty (e.m_key);
> > +      }
> > +  };
> > +
> > +public:
> > +  explicit hash_set (size_t n = 13) : m_table (n) {}
> > +
> > +  /* If key k isn't already in the map add it to the map, and
> > +     return false.  Otherwise return true.  */
> > +
> > +  bool add (const Key &k)
> > +    {
> > +      hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
> > +                                                  INSERT);
> > +      bool existed = !hash_entry::is_empty (*e);
> > +      if (!existed)
> > +       e->m_key = k;
> > +
> > +      return existed;
> > +    }
> > +
> > +  /* if the passed in key is in the map return its value otherwise NULL.  */
> > +
> > +  bool contains (const Key &k)
> > +    {
> > +      hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
> > +      return !Traits::is_empty (e.m_key);
> > +    }
> > +
> > +  /* Call the call back on each pair of key and value with the passed in
> > +     arg.  */
> > +
> > +  template<typename Arg, bool (*f)(const Key &, Arg)>
> > +  void traverse (Arg a) const
> > +    {
> > +      for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
> > +          iter != m_table.end (); ++iter)
> > +       f ((*iter).m_key, a);
> > +    }
> > +
> > +private:
> > +  hash_table<hash_entry> m_table;
> > +};
> > +
> > +#endif
> > diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
> > index 127d58d..70a70a7 100644
> > --- a/gcc/ipa-devirt.c
> > +++ b/gcc/ipa-devirt.c
> > @@ -115,7 +115,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "cgraph.h"
> >  #include "expr.h"
> >  #include "tree-pass.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "target.h"
> >  #include "hash-table.h"
> >  #include "inchash.h"
> > @@ -134,7 +134,8 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "stor-layout.h"
> >  #include "intl.h"
> >
> > -static bool odr_types_equivalent_p (tree, tree, bool, bool *, pointer_set_t *);
> > +static bool odr_types_equivalent_p (tree, tree, bool, bool *,
> > +                                   hash_set<tree> *);
> >
> >  static bool odr_violation_reported = false;
> >
> > @@ -144,7 +145,7 @@ const ipa_polymorphic_call_context ipa_dummy_polymorphic_call_context
> >     = {0, NULL, false, true};
> >
> >  /* Pointer set of all call targets appearing in the cache.  */
> > -static pointer_set_t *cached_polymorphic_call_targets;
> > +static hash_set<cgraph_node *> *cached_polymorphic_call_targets;
> >
> >  /* The node of type inheritance graph.  For each type unique in
> >     One Defintion Rule (ODR) sense, we produce one node linking all
> > @@ -163,7 +164,7 @@ struct GTY(()) odr_type_d
> >    /* All equivalent types, if more than one.  */
> >    vec<tree, va_gc> *types;
> >    /* Set of all equivalent types, if NON-NULL.  */
> > -  pointer_set_t * GTY((skip)) types_set;
> > +  hash_set<tree> * GTY((skip)) types_set;
> >
> >    /* Unique ID indexing the type in odr_types array.  */
> >    int id;
> > @@ -409,7 +410,7 @@ odr_hasher::remove (value_type *v)
> >    v->bases.release ();
> >    v->derived_types.release ();
> >    if (v->types_set)
> > -    pointer_set_destroy (v->types_set);
> > +    delete v->types_set;
> >    ggc_free (v);
> >  }
> >
> > @@ -439,7 +440,7 @@ set_type_binfo (tree type, tree binfo)
> >  /* Compare T2 and T2 based on name or structure.  */
> >
> >  static bool
> > -odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
> > +odr_subtypes_equivalent_p (tree t1, tree t2, hash_set<tree> *visited)
> >  {
> >    bool an1, an2;
> >
> > @@ -473,7 +474,7 @@ odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
> >        /* This should really be a pair hash, but for the moment we do not need
> >          100% reliability and it would be better to compare all ODR types so
> >          recursion here is needed only for component types.  */
> > -      if (pointer_set_insert (visited, t1))
> > +      if (visited->add (t1))
> >         return true;
> >        return odr_types_equivalent_p (t1, t2, false, NULL, visited);
> >      }
> > @@ -562,7 +563,7 @@ warn_types_mismatch (tree t1, tree t2)
> >     gimple_canonical_types_compatible_p.  */
> >
> >  static bool
> > -odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, pointer_set_t *visited)
> > +odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, hash_set<tree> *visited)
> >  {
> >    /* Check first for the obvious case of pointer identity.  */
> >    if (t1 == t2)
> > @@ -938,7 +939,7 @@ add_type_duplicate (odr_type val, tree type)
> >  {
> >    bool build_bases = false;
> >    if (!val->types_set)
> > -    val->types_set = pointer_set_create ();
> > +    val->types_set = new hash_set<tree>;
> >
> >    /* Always prefer complete type to be the leader.  */
> >    if (!COMPLETE_TYPE_P (val->type)
> > @@ -952,20 +953,20 @@ add_type_duplicate (odr_type val, tree type)
> >      }
> >
> >    /* See if this duplicate is new.  */
> > -  if (!pointer_set_insert (val->types_set, type))
> > +  if (!val->types_set->add (type))
> >      {
> >        bool merge = true;
> >        bool base_mismatch = false;
> >        unsigned int i,j;
> >        bool warned = false;
> > -      pointer_set_t *visited = pointer_set_create ();
> > +      hash_set<tree> visited;
> >
> >        gcc_assert (in_lto_p);
> >        vec_safe_push (val->types, type);
> >
> >        /* First we compare memory layout.  */
> >        if (!odr_types_equivalent_p (val->type, type, !flag_ltrans && !val->odr_violated,
> > -                                  &warned, visited))
> > +                                  &warned, &visited))
> >         {
> >           merge = false;
> >           odr_violation_reported = true;
> > @@ -980,7 +981,6 @@ add_type_duplicate (odr_type val, tree type)
> >               putc ('\n',cgraph_dump_file);
> >             }
> >         }
> > -      pointer_set_destroy (visited);
> >
> >        /* Next sanity check that bases are the same.  If not, we will end
> >          up producing wrong answers.  */
> > @@ -1356,7 +1356,7 @@ referenced_from_vtable_p (struct cgraph_node *node)
> >
> >  static void
> >  maybe_record_node (vec <cgraph_node *> &nodes,
> > -                  tree target, pointer_set_t *inserted,
> > +                  tree target, hash_set<tree> *inserted,
> >                    bool can_refer,
> >                    bool *completep)
> >  {
> > @@ -1422,10 +1422,9 @@ maybe_record_node (vec <cgraph_node *> &nodes,
> >      {
> >        gcc_assert (!target_node->global.inlined_to);
> >        gcc_assert (target_node->real_symbol_p ());
> > -      if (!pointer_set_insert (inserted, target_node->decl))
> > +      if (!inserted->add (target))
> >         {
> > -         pointer_set_insert (cached_polymorphic_call_targets,
> > -                             target_node);
> > +         cached_polymorphic_call_targets->add (target_node);
> >           nodes.safe_push (target_node);
> >         }
> >      }
> > @@ -1465,8 +1464,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
> >                           HOST_WIDE_INT otr_token,
> >                           tree outer_type,
> >                           HOST_WIDE_INT offset,
> > -                         pointer_set_t *inserted,
> > -                         pointer_set_t *matched_vtables,
> > +                         hash_set<tree> *inserted,
> > +                         hash_set<tree> *matched_vtables,
> >                           bool anonymous,
> >                           bool *completep)
> >  {
> > @@ -1519,8 +1518,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
> >         }
> >        gcc_assert (inner_binfo);
> >        if (bases_to_consider
> > -         ? !pointer_set_contains (matched_vtables, BINFO_VTABLE (inner_binfo))
> > -         : !pointer_set_insert (matched_vtables, BINFO_VTABLE (inner_binfo)))
> > +         ? !matched_vtables->contains (BINFO_VTABLE (inner_binfo))
> > +         : !matched_vtables->add (BINFO_VTABLE (inner_binfo)))
> >         {
> >           bool can_refer;
> >           tree target = gimple_get_virt_method_for_binfo (otr_token,
> > @@ -1559,8 +1558,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
> >
> >  static void
> >  possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes,
> > -                                    pointer_set_t *inserted,
> > -                                    pointer_set_t *matched_vtables,
> > +                                    hash_set<tree> *inserted,
> > +                                    hash_set<tree> *matched_vtables,
> >                                      tree otr_type,
> >                                      odr_type type,
> >                                      HOST_WIDE_INT otr_token,
> > @@ -1684,7 +1683,7 @@ free_polymorphic_call_targets_hash ()
> >      {
> >        delete polymorphic_call_target_hash;
> >        polymorphic_call_target_hash = NULL;
> > -      pointer_set_destroy (cached_polymorphic_call_targets);
> > +      delete cached_polymorphic_call_targets;
> >        cached_polymorphic_call_targets = NULL;
> >      }
> >  }
> > @@ -1695,7 +1694,7 @@ static void
> >  devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
> >  {
> >    if (cached_polymorphic_call_targets
> > -      && pointer_set_contains (cached_polymorphic_call_targets, n))
> > +      && cached_polymorphic_call_targets->contains (n))
> >      free_polymorphic_call_targets_hash ();
> >  }
> >
> > @@ -2277,8 +2276,8 @@ record_targets_from_bases (tree otr_type,
> >                            tree outer_type,
> >                            HOST_WIDE_INT offset,
> >                            vec <cgraph_node *> &nodes,
> > -                          pointer_set_t *inserted,
> > -                          pointer_set_t *matched_vtables,
> > +                          hash_set<tree> *inserted,
> > +                          hash_set<tree> *matched_vtables,
> >                            bool *completep)
> >  {
> >    while (true)
> > @@ -2319,7 +2318,7 @@ record_targets_from_bases (tree otr_type,
> >           return;
> >         }
> >        gcc_assert (base_binfo);
> > -      if (!pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo)))
> > +      if (!matched_vtables->add (BINFO_VTABLE (base_binfo)))
> >         {
> >           bool can_refer;
> >           tree target = gimple_get_virt_method_for_binfo (otr_token,
> > @@ -2327,7 +2326,7 @@ record_targets_from_bases (tree otr_type,
> >                                                           &can_refer);
> >           if (!target || ! DECL_CXX_DESTRUCTOR_P (target))
> >             maybe_record_node (nodes, target, inserted, can_refer, completep);
> > -         pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo));
> > +         matched_vtables->add (BINFO_VTABLE (base_binfo));
> >         }
> >      }
> >  }
> > @@ -2377,8 +2376,6 @@ possible_polymorphic_call_targets (tree otr_type,
> >                                    int *nonconstruction_targetsp)
> >  {
> >    static struct cgraph_node_hook_list *node_removal_hook_holder;
> > -  pointer_set_t *inserted;
> > -  pointer_set_t *matched_vtables;
> >    vec <cgraph_node *> nodes = vNULL;
> >    vec <tree> bases_to_consider = vNULL;
> >    odr_type type, outer_type;
> > @@ -2457,7 +2454,7 @@ possible_polymorphic_call_targets (tree otr_type,
> >    /* Initialize query cache.  */
> >    if (!cached_polymorphic_call_targets)
> >      {
> > -      cached_polymorphic_call_targets = pointer_set_create ();
> > +      cached_polymorphic_call_targets = new hash_set<cgraph_node *>;
> >        polymorphic_call_target_hash
> >                 = new polymorphic_call_target_hash_type (23);
> >        if (!node_removal_hook_holder)
> > @@ -2496,8 +2493,8 @@ possible_polymorphic_call_targets (tree otr_type,
> >    (*slot)->otr_token = otr_token;
> >    (*slot)->context = context;
> >
> > -  inserted = pointer_set_create ();
> > -  matched_vtables = pointer_set_create ();
> > +  hash_set<tree> inserted;
> > +  hash_set<tree> matched_vtables;
> >
> >    /* First see virtual method of type itself.  */
> >    binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type),
> > @@ -2526,7 +2523,7 @@ possible_polymorphic_call_targets (tree otr_type,
> >
> >    /* If OUTER_TYPE is abstract, we know we are not seeing its instance.  */
> >    if (type_possibly_instantiated_p (outer_type->type))
> > -    maybe_record_node (nodes, target, inserted, can_refer, &complete);
> > +    maybe_record_node (nodes, target, &inserted, can_refer, &complete);
> >    else
> >      {
> >        skipped = true;
> > @@ -2534,7 +2531,7 @@ possible_polymorphic_call_targets (tree otr_type,
> >      }
> >
> >    if (binfo)
> > -    pointer_set_insert (matched_vtables, BINFO_VTABLE (binfo));
> > +    matched_vtables.add (BINFO_VTABLE (binfo));
> >
> >    /* Next walk recursively all derived types.  */
> >    if (context.maybe_derived_type)
> > @@ -2544,8 +2541,8 @@ possible_polymorphic_call_targets (tree otr_type,
> >        if (!type->all_derivations_known)
> >         complete = false;
> >        for (i = 0; i < outer_type->derived_types.length(); i++)
> > -       possible_polymorphic_call_targets_1 (nodes, inserted,
> > -                                            matched_vtables,
> > +       possible_polymorphic_call_targets_1 (nodes, &inserted,
> > +                                            &matched_vtables,
> >                                              otr_type,
> >                                              outer_type->derived_types[i],
> >                                              otr_token, outer_type->type,
> > @@ -2571,12 +2568,12 @@ possible_polymorphic_call_targets (tree otr_type,
> >               || (context.maybe_derived_type
> >                   && !type_all_derivations_known_p (outer_type->type))))
> >         record_targets_from_bases (otr_type, otr_token, outer_type->type,
> > -                                  context.offset, nodes, inserted,
> > -                                  matched_vtables, &complete);
> > +                                  context.offset, nodes, &inserted,
> > +                                  &matched_vtables, &complete);
> >        if (skipped)
> > -        maybe_record_node (nodes, target, inserted, can_refer, &complete);
> > +        maybe_record_node (nodes, target, &inserted, can_refer, &complete);
> >        for (i = 0; i < bases_to_consider.length(); i++)
> > -        maybe_record_node (nodes, bases_to_consider[i], inserted, can_refer, &complete);
> > +        maybe_record_node (nodes, bases_to_consider[i], &inserted, can_refer, &complete);
> >      }
> >    bases_to_consider.release();
> >
> > @@ -2587,8 +2584,6 @@ possible_polymorphic_call_targets (tree otr_type,
> >    if (nonconstruction_targetsp)
> >      *nonconstruction_targetsp = (*slot)->nonconstruction_targets;
> >
> > -  pointer_set_destroy (inserted);
> > -  pointer_set_destroy (matched_vtables);
> >    timevar_pop (TV_IPA_VIRTUAL_CALL);
> >    return nodes;
> >  }
> > @@ -2744,7 +2739,7 @@ static unsigned int
> >  ipa_devirt (void)
> >  {
> >    struct cgraph_node *n;
> > -  struct pointer_set_t *bad_call_targets = pointer_set_create ();
> > +  hash_set<void *> bad_call_targets;
> >    struct cgraph_edge *e;
> >
> >    int npolymorphic = 0, nspeculated = 0, nconverted = 0, ncold = 0;
> > @@ -2792,8 +2787,7 @@ ipa_devirt (void)
> >                 if (!dump_file)
> >                   continue;
> >               }
> > -           if (pointer_set_contains (bad_call_targets,
> > -                                     cache_token))
> > +           if (bad_call_targets.contains (cache_token))
> >               {
> >                 if (dump_file)
> >                   fprintf (dump_file, "Target list is known to be useless\n\n");
> > @@ -2818,7 +2812,7 @@ ipa_devirt (void)
> >                 }
> >             if (!likely_target)
> >               {
> > -               pointer_set_insert (bad_call_targets, cache_token);
> > +               bad_call_targets.add (cache_token);
> >                 continue;
> >               }
> >             /* This is reached only when dumping; check if we agree or disagree
> > @@ -2905,7 +2899,6 @@ ipa_devirt (void)
> >        if (update)
> >         inline_update_overall_summary (n);
> >      }
> > -  pointer_set_destroy (bad_call_targets);
> >
> >    if (dump_file)
> >      fprintf (dump_file,
> > diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
> > index 2c281be..b964502 100644
> > --- a/gcc/ipa-pure-const.c
> > +++ b/gcc/ipa-pure-const.c
> > @@ -65,8 +65,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "tree-scalar-evolution.h"
> >  #include "intl.h"
> >  #include "opts.h"
> > -
> > -static struct pointer_set_t *visited_nodes;
> > +#include "hash-set.h"
> >
> >  /* Lattice values for const and pure functions.  Everything starts out
> >     being const, then may drop to pure and then neither depending on
> > @@ -133,13 +132,13 @@ function_always_visible_to_compiler_p (tree decl)
> >
> >  /* Emit suggestion about attribute ATTRIB_NAME for DECL.  KNOWN_FINITE
> >     is true if the function is known to be finite.  The diagnostic is
> > -   controlled by OPTION.  WARNED_ABOUT is a pointer_set unique for
> > +   controlled by OPTION.  WARNED_ABOUT is a hash_set<tree> unique for
> >     OPTION, this function may initialize it and it is always returned
> >     by the function.  */
> >
> > -static struct pointer_set_t *
> > +static hash_set<tree> *
> >  suggest_attribute (int option, tree decl, bool known_finite,
> > -                  struct pointer_set_t *warned_about,
> > +                  hash_set<tree> *warned_about,
> >                    const char * attrib_name)
> >  {
> >    if (!option_enabled (option, &global_options))
> > @@ -149,10 +148,10 @@ suggest_attribute (int option, tree decl, bool known_finite,
> >      return warned_about;
> >
> >    if (!warned_about)
> > -    warned_about = pointer_set_create ();
> > -  if (pointer_set_contains (warned_about, decl))
> > +    warned_about = new hash_set<tree>;
> > +  if (warned_about->contains (decl))
> >      return warned_about;
> > -  pointer_set_insert (warned_about, decl);
> > +  warned_about->add (decl);
> >    warning_at (DECL_SOURCE_LOCATION (decl),
> >               option,
> >               known_finite
> > @@ -168,7 +167,7 @@ suggest_attribute (int option, tree decl, bool known_finite,
> >  static void
> >  warn_function_pure (tree decl, bool known_finite)
> >  {
> > -  static struct pointer_set_t *warned_about;
> > +  static hash_set<tree> *warned_about;
> >
> >    warned_about
> >      = suggest_attribute (OPT_Wsuggest_attribute_pure, decl,
> > @@ -181,7 +180,7 @@ warn_function_pure (tree decl, bool known_finite)
> >  static void
> >  warn_function_const (tree decl, bool known_finite)
> >  {
> > -  static struct pointer_set_t *warned_about;
> > +  static hash_set<tree> *warned_about;
> >    warned_about
> >      = suggest_attribute (OPT_Wsuggest_attribute_const, decl,
> >                          known_finite, warned_about, "const");
> > @@ -190,7 +189,7 @@ warn_function_const (tree decl, bool known_finite)
> >  static void
> >  warn_function_noreturn (tree decl)
> >  {
> > -  static struct pointer_set_t *warned_about;
> > +  static hash_set<tree> *warned_about;
> >    if (!lang_hooks.missing_noreturn_ok_p (decl)
> >        && targetm.warn_func_return (decl))
> >      warned_about
> > @@ -846,11 +845,8 @@ add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
> >       static declarations.  We do not need to scan them more than once
> >       since all we would be interested in are the addressof
> >       operations.  */
> > -  visited_nodes = pointer_set_create ();
> >    if (node->get_availability () > AVAIL_INTERPOSABLE)
> >      set_function_state (node, analyze_function (node, true));
> > -  pointer_set_destroy (visited_nodes);
> > -  visited_nodes = NULL;
> >  }
> >
> >  /* Called when new clone is inserted to callgraph late.  */
> > @@ -912,12 +908,6 @@ pure_const_generate_summary (void)
> >
> >    register_hooks ();
> >
> > -  /* There are some shared nodes, in particular the initializers on
> > -     static declarations.  We do not need to scan them more than once
> > -     since all we would be interested in are the addressof
> > -     operations.  */
> > -  visited_nodes = pointer_set_create ();
> > -
> >    /* Process all of the functions.
> >
> >       We process AVAIL_INTERPOSABLE functions.  We can not use the results
> > @@ -927,9 +917,6 @@ pure_const_generate_summary (void)
> >    FOR_EACH_DEFINED_FUNCTION (node)
> >      if (node->get_availability () >= AVAIL_INTERPOSABLE)
> >        set_function_state (node, analyze_function (node, true));
> > -
> > -  pointer_set_destroy (visited_nodes);
> > -  visited_nodes = NULL;
> >  }
> >
> >
> > diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
> > index 4720ee9..bca2bc7 100644
> > --- a/gcc/ipa-visibility.c
> > +++ b/gcc/ipa-visibility.c
> > @@ -687,12 +687,11 @@ function_and_variable_visibility (bool whole_program)
> >               }
> >           if (found)
> >             {
> > -             struct pointer_set_t *visited_nodes = pointer_set_create ();
> > +             hash_set<tree> visited_nodes;
> >
> >               vnode->get_constructor ();
> >               walk_tree (&DECL_INITIAL (vnode->decl),
> > -                        update_vtable_references, NULL, visited_nodes);
> > -             pointer_set_destroy (visited_nodes);
> > +                        update_vtable_references, NULL, &visited_nodes);
> >               vnode->remove_all_references ();
> >               record_references_in_initializer (vnode->decl, false);
> >             }
> > diff --git a/gcc/ipa.c b/gcc/ipa.c
> > index 8198b17..1081e89 100644
> > --- a/gcc/ipa.c
> > +++ b/gcc/ipa.c
> > @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "cgraph.h"
> >  #include "tree-pass.h"
> >  #include "hash-map.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "gimple-expr.h"
> >  #include "gimplify.h"
> >  #include "flags.h"
> > @@ -84,14 +84,14 @@ update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined
> >
> >  static void
> >  enqueue_node (symtab_node *node, symtab_node **first,
> > -             struct pointer_set_t *reachable)
> > +             hash_set<symtab_node *> *reachable)
> >  {
> >    /* Node is still in queue; do nothing.  */
> >    if (node->aux && node->aux != (void *) 2)
> >      return;
> >    /* Node was already processed as unreachable, re-enqueue
> >       only if it became reachable now.  */
> > -  if (node->aux == (void *)2 && !pointer_set_contains (reachable, node))
> > +  if (node->aux == (void *)2 && !reachable->contains (node))
> >      return;
> >    node->aux = *first;
> >    *first = node;
> > @@ -103,7 +103,7 @@ static void
> >  process_references (symtab_node *snode,
> >                     symtab_node **first,
> >                     bool before_inlining_p,
> > -                   struct pointer_set_t *reachable)
> > +                   hash_set<symtab_node *> *reachable)
> >  {
> >    int i;
> >    struct ipa_ref *ref = NULL;
> > @@ -124,7 +124,7 @@ process_references (symtab_node *snode,
> >                       && flag_wpa
> >                       && ctor_for_folding (node->decl)
> >                          != error_mark_node))))
> > -       pointer_set_insert (reachable, node);
> > +       reachable->add (node);
> >        enqueue_node (node, first, reachable);
> >      }
> >  }
> > @@ -138,10 +138,11 @@ process_references (symtab_node *snode,
> >     possible.  */
> >
> >  static void
> > -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> > +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
> >                                struct cgraph_edge *edge,
> >                                symtab_node **first,
> > -                              pointer_set_t *reachable, bool before_inlining_p)
> > +                              hash_set<symtab_node *> *reachable,
> > +                              bool before_inlining_p)
> >  {
> >    unsigned int i;
> >    void *cache_token;
> > @@ -150,8 +151,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> >      = possible_polymorphic_call_targets
> >         (edge, &final, &cache_token);
> >
> > -  if (!pointer_set_insert (reachable_call_targets,
> > -                          cache_token))
> > +  if (!reachable_call_targets->add (cache_token))
> >      {
> >        for (i = 0; i < targets.length (); i++)
> >         {
> > @@ -172,7 +172,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> >                    && (cgraph_state < CGRAPH_STATE_IPA_SSA
> >                        || !lookup_attribute ("always_inline",
> >                                              DECL_ATTRIBUTES (n->decl)))))
> > -            pointer_set_insert (reachable, n);
> > +            reachable->add (n);
> >
> >           /* Even after inlining we want to keep the possible targets in the
> >              boundary, so late passes can still produce direct call even if
> > @@ -276,9 +276,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >    struct cgraph_node *node, *next;
> >    varpool_node *vnode, *vnext;
> >    bool changed = false;
> > -  struct pointer_set_t *reachable = pointer_set_create ();
> > -  struct pointer_set_t *body_needed_for_clonning = pointer_set_create ();
> > -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> > +  hash_set<symtab_node *> reachable;
> > +  hash_set<tree> body_needed_for_clonning;
> > +  hash_set<void *> reachable_call_targets;
> >
> >    timevar_push (TV_IPA_UNREACHABLE);
> >    if (optimize && flag_devirtualize)
> > @@ -304,8 +304,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >           && !node->can_remove_if_no_direct_calls_and_refs_p ())
> >         {
> >           gcc_assert (!node->global.inlined_to);
> > -         pointer_set_insert (reachable, node);
> > -         enqueue_node (node, &first, reachable);
> > +         reachable.add (node);
> > +         enqueue_node (node, &first, &reachable);
> >         }
> >        else
> >         gcc_assert (!node->aux);
> > @@ -316,14 +316,14 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >      if (!vnode->can_remove_if_no_refs_p()
> >         && !vnode->in_other_partition)
> >        {
> > -       pointer_set_insert (reachable, vnode);
> > -       enqueue_node (vnode, &first, reachable);
> > +       reachable.add (vnode);
> > +       enqueue_node (vnode, &first, &reachable);
> >        }
> >
> >    /* Perform reachability analysis.  */
> >    while (first != (symtab_node *) (void *) 1)
> >      {
> > -      bool in_boundary_p = !pointer_set_contains (reachable, first);
> > +      bool in_boundary_p = !reachable.contains (first);
> >        symtab_node *node = first;
> >
> >        first = (symtab_node *)first->aux;
> > @@ -340,7 +340,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >               struct cgraph_node *origin_node
> >               = cgraph_node::get_create (DECL_ABSTRACT_ORIGIN (node->decl));
> >               origin_node->used_as_abstract_origin = true;
> > -             enqueue_node (origin_node, &first, reachable);
> > +             enqueue_node (origin_node, &first, &reachable);
> >             }
> >           /* If any symbol in a comdat group is reachable, force
> >              all externally visible symbols in the same comdat
> > @@ -353,11 +353,11 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >                    next != node;
> >                    next = next->same_comdat_group)
> >                 if (!next->comdat_local_p ()
> > -                   && !pointer_set_insert (reachable, next))
> > -                 enqueue_node (next, &first, reachable);
> > +                   && !reachable.add (next))
> > +                 enqueue_node (next, &first, &reachable);
> >             }
> >           /* Mark references as reachable.  */
> > -         process_references (node, &first, before_inlining_p, reachable);
> > +         process_references (node, &first, before_inlining_p, &reachable);
> >         }
> >
> >        if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
> > @@ -375,8 +375,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >                     {
> >                       next = e->next_callee;
> >                       if (e->indirect_info->polymorphic)
> > -                       walk_polymorphic_call_targets (reachable_call_targets,
> > -                                                      e, &first, reachable,
> > +                       walk_polymorphic_call_targets (&reachable_call_targets,
> > +                                                      e, &first, &reachable,
> >                                                        before_inlining_p);
> >                     }
> >                 }
> > @@ -394,17 +394,16 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >                       if (DECL_EXTERNAL (e->callee->decl)
> >                           && e->callee->alias
> >                           && before_inlining_p)
> > -                       pointer_set_insert (reachable,
> > -                                           e->callee->function_symbol ());
> > -                     pointer_set_insert (reachable, e->callee);
> > +                       reachable.add (e->callee->function_symbol ());
> > +                     reachable.add (e->callee);
> >                     }
> > -                 enqueue_node (e->callee, &first, reachable);
> > +                 enqueue_node (e->callee, &first, &reachable);
> >                 }
> >
> >               /* When inline clone exists, mark body to be preserved so when removing
> >                  offline copy of the function we don't kill it.  */
> >               if (cnode->global.inlined_to)
> > -               pointer_set_insert (body_needed_for_clonning, cnode->decl);
> > +               body_needed_for_clonning.add (cnode->decl);
> >
> >               /* For non-inline clones, force their origins to the boundary and ensure
> >                  that body is not removed.  */
> > @@ -414,8 +413,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >                   cnode = cnode->clone_of;
> >                   if (noninline)
> >                     {
> > -                     pointer_set_insert (body_needed_for_clonning, cnode->decl);
> > -                     enqueue_node (cnode, &first, reachable);
> > +                     body_needed_for_clonning.add (cnode->decl);
> > +                     enqueue_node (cnode, &first, &reachable);
> >                     }
> >                 }
> >
> > @@ -429,8 +428,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >                    next;
> >                    next = next->simdclone->next_clone)
> >                 if (in_boundary_p
> > -                   || !pointer_set_insert (reachable, next))
> > -                 enqueue_node (next, &first, reachable);
> > +                   || !reachable.add (next))
> > +                 enqueue_node (next, &first, &reachable);
> >             }
> >         }
> >        /* When we see constructor of external variable, keep referred nodes in the
> > @@ -444,7 +443,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >         {
> >           struct ipa_ref *ref = NULL;
> >           for (int i = 0; node->iterate_reference (i, ref); i++)
> > -           enqueue_node (ref->referred, &first, reachable);
> > +           enqueue_node (ref->referred, &first, &reachable);
> >         }
> >      }
> >
> > @@ -462,9 +461,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >           changed = true;
> >         }
> >        /* If node is unreachable, remove its body.  */
> > -      else if (!pointer_set_contains (reachable, node))
> > +      else if (!reachable.contains (node))
> >          {
> > -         if (!pointer_set_contains (body_needed_for_clonning, node->decl))
> > +         if (!body_needed_for_clonning.contains (node->decl))
> >             node->release_body ();
> >           else if (!node->clone_of)
> >             gcc_assert (in_lto_p || DECL_RESULT (node->decl));
> > @@ -530,7 +529,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >           vnode->remove ();
> >           changed = true;
> >         }
> > -      else if (!pointer_set_contains (reachable, vnode))
> > +      else if (!reachable.contains (vnode))
> >          {
> >           tree init;
> >           if (vnode->definition)
> > @@ -557,10 +556,6 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >         vnode->aux = NULL;
> >      }
> >
> > -  pointer_set_destroy (reachable);
> > -  pointer_set_destroy (body_needed_for_clonning);
> > -  pointer_set_destroy (reachable_call_targets);
> > -
> >    /* Now update address_taken flags and try to promote functions to be local.  */
> >    if (file)
> >      fprintf (file, "\nClearing address taken flags:");
> > diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
> > index b1fcf67..42b0790 100644
> > --- a/gcc/lto-cgraph.c
> > +++ b/gcc/lto-cgraph.c
> > @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "params.h"
> >  #include "input.h"
> >  #include "hashtab.h"
> > +#include "hash-set.h"
> >  #include "langhooks.h"
> >  #include "bitmap.h"
> >  #include "function.h"
> > @@ -819,7 +820,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
> >    int i;
> >    lto_symtab_encoder_t encoder;
> >    lto_symtab_encoder_iterator lsei;
> > -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> > +  hash_set<void *> reachable_call_targets;
> >
> >    encoder = lto_symtab_encoder_new (false);
> >
> > @@ -902,8 +903,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
> >               vec <cgraph_node *>targets
> >                 = possible_polymorphic_call_targets
> >                     (edge, &final, &cache_token);
> > -             if (!pointer_set_insert (reachable_call_targets,
> > -                                      cache_token))
> > +             if (!reachable_call_targets.add (cache_token))
> >                 {
> >                   for (i = 0; i < targets.length (); i++)
> >                     {
> > @@ -923,7 +923,6 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
> >             }
> >      }
> >    lto_symtab_encoder_delete (in_encoder);
> > -  pointer_set_destroy (reachable_call_targets);
> >    return encoder;
> >  }
> >
> > diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
> > index 271fbd5..3fd9147 100644
> > --- a/gcc/lto-streamer-out.c
> > +++ b/gcc/lto-streamer-out.c
> > @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "params.h"
> >  #include "input.h"
> >  #include "hashtab.h"
> > +#include "hash-set.h"
> >  #include "basic-block.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> > @@ -2433,7 +2434,7 @@ lto_out_decl_state_written_size (struct lto_out_decl_state *state)
> >  static void
> >  write_symbol (struct streamer_tree_cache_d *cache,
> >               struct lto_output_stream *stream,
> > -             tree t, struct pointer_set_t *seen, bool alias)
> > +             tree t, hash_set<const char *> *seen, bool alias)
> >  {
> >    const char *name;
> >    enum gcc_plugin_symbol_kind kind;
> > @@ -2461,9 +2462,8 @@ write_symbol (struct streamer_tree_cache_d *cache,
> >       same name manipulations that ASM_OUTPUT_LABELREF does. */
> >    name = IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name) (name));
> >
> > -  if (pointer_set_contains (seen, name))
> > +  if (seen->add (name))
> >      return;
> > -  pointer_set_insert (seen, name);
> >
> >    streamer_tree_cache_lookup (cache, t, &slot_num);
> >    gcc_assert (slot_num != (unsigned)-1);
> > @@ -2588,7 +2588,6 @@ produce_symtab (struct output_block *ob)
> >  {
> >    struct streamer_tree_cache_d *cache = ob->writer_cache;
> >    char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
> > -  struct pointer_set_t *seen;
> >    struct lto_output_stream stream;
> >    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
> >    lto_symtab_encoder_iterator lsei;
> > @@ -2596,7 +2595,7 @@ produce_symtab (struct output_block *ob)
> >    lto_begin_section (section_name, false);
> >    free (section_name);
> >
> > -  seen = pointer_set_create ();
> > +  hash_set<const char *> seen;
> >    memset (&stream, 0, sizeof (stream));
> >
> >    /* Write the symbol table.
> > @@ -2609,7 +2608,7 @@ produce_symtab (struct output_block *ob)
> >
> >        if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
> >         continue;
> > -      write_symbol (cache, &stream, node->decl, seen, false);
> > +      write_symbol (cache, &stream, node->decl, &seen, false);
> >      }
> >    for (lsei = lsei_start (encoder);
> >         !lsei_end_p (lsei); lsei_next (&lsei))
> > @@ -2618,11 +2617,10 @@ produce_symtab (struct output_block *ob)
> >
> >        if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
> >         continue;
> > -      write_symbol (cache, &stream, node->decl, seen, false);
> > +      write_symbol (cache, &stream, node->decl, &seen, false);
> >      }
> >
> >    lto_write_stream (&stream);
> > -  pointer_set_destroy (seen);
> >
> >    lto_end_section ();
> >  }
> > diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
> > index cb08a88..a5bcf92 100644
> > --- a/gcc/lto/lto-partition.c
> > +++ b/gcc/lto/lto-partition.c
> > @@ -66,7 +66,7 @@ free_ltrans_partitions (void)
> >    for (idx = 0; ltrans_partitions.iterate (idx, &part); idx++)
> >      {
> >        if (part->initializers_visited)
> > -       pointer_set_destroy (part->initializers_visited);
> > +       delete part->initializers_visited;
> >        /* Symtab encoder is freed after streaming.  */
> >        free (part);
> >      }
> > @@ -101,8 +101,8 @@ add_references_to_partition (ltrans_partition part, symtab_node *node)
> >              && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
> >        {
> >         if (!part->initializers_visited)
> > -         part->initializers_visited = pointer_set_create ();
> > -       if (!pointer_set_insert (part->initializers_visited, ref->referred))
> > +         part->initializers_visited = new hash_set<symtab_node *>;
> > +       if (!part->initializers_visited->add (ref->referred))
> >           add_references_to_partition (part, ref->referred);
> >        }
> >  }
> > @@ -250,7 +250,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes)
> >
> >        /* After UNDO we no longer know what was visited.  */
> >        if (partition->initializers_visited)
> > -       pointer_set_destroy (partition->initializers_visited);
> > +       delete partition->initializers_visited;
> >        partition->initializers_visited = NULL;
> >
> >        if (!node->alias && (cnode = dyn_cast <cgraph_node *> (node)))
> > diff --git a/gcc/lto/lto-partition.h b/gcc/lto/lto-partition.h
> > index 8db61b3..50ec2fa 100644
> > --- a/gcc/lto/lto-partition.h
> > +++ b/gcc/lto/lto-partition.h
> > @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
> >  along with GCC; see the file COPYING3.  If not see
> >  <http://www.gnu.org/licenses/>.  */
> >
> > +#include "hash-set.h"
> >
> >  /* Structure describing ltrans partitions.  */
> >
> > @@ -25,7 +26,7 @@ struct ltrans_partition_def
> >    lto_symtab_encoder_t encoder;
> >    const char * name;
> >    int insns;
> > -  pointer_set_t *initializers_visited;
> > +  hash_set<symtab_node *> *initializers_visited;
> >  };
> >
> >  typedef struct ltrans_partition_def *ltrans_partition;
> > diff --git a/gcc/stmt.c b/gcc/stmt.c
> > index 0aae085..55ec279 100644
> > --- a/gcc/stmt.c
> > +++ b/gcc/stmt.c
> > @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "predict.h"
> >  #include "optabs.h"
> >  #include "target.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "basic-block.h"
> >  #include "tree-ssa-alias.h"
> > @@ -1183,7 +1184,7 @@ expand_case (gimple stmt)
> >       how to expand this switch().  */
> >    uniq = 0;
> >    count = 0;
> > -  struct pointer_set_t *seen_labels = pointer_set_create ();
> > +  hash_set<tree> seen_labels;
> >    compute_cases_per_edge (stmt);
> >
> >    for (i = ncases - 1; i >= 1; --i)
> > @@ -1203,7 +1204,7 @@ expand_case (gimple stmt)
> >
> >        /* If we have not seen this label yet, then increase the
> >          number of unique case node targets seen.  */
> > -      if (!pointer_set_insert (seen_labels, lab))
> > +      if (!seen_labels.add (lab))
> >         uniq++;
> >
> >        /* The bounds on the case range, LOW and HIGH, have to be converted
> > @@ -1231,7 +1232,6 @@ expand_case (gimple stmt)
> >            case_edge->probability / (intptr_t)(case_edge->aux),
> >            case_node_pool);
> >      }
> > -  pointer_set_destroy (seen_labels);
> >    reset_out_edges_aux (bb);
> >
> >    /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
> > diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> > index 6fee8a4..e034762 100644
> > --- a/gcc/tree-cfg.c
> > +++ b/gcc/tree-cfg.c
> > @@ -4691,7 +4691,7 @@ tree_node_can_be_shared (tree t)
> >  static tree
> >  verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
> >  {
> > -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> > +  hash_set<void *> *visited = (hash_set<void *> *) data;
> >
> >    if (tree_node_can_be_shared (*tp))
> >      {
> > @@ -4699,7 +4699,7 @@ verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
> >        return NULL;
> >      }
> >
> > -  if (pointer_set_insert (visited, *tp))
> > +  if (visited->add (*tp))
> >      return *tp;
> >
> >    return NULL;
> > @@ -4719,9 +4719,9 @@ static int
> >  verify_eh_throw_stmt_node (void **slot, void *data)
> >  {
> >    struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
> > -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> > +  hash_set<void *> *visited = (hash_set<void *> *) data;
> >
> > -  if (!pointer_set_contains (visited, node->stmt))
> > +  if (!visited->contains (node->stmt))
> >      {
> >        error ("dead STMT in EH table");
> >        debug_gimple_stmt (node->stmt);
> > @@ -4733,11 +4733,11 @@ verify_eh_throw_stmt_node (void **slot, void *data)
> >  /* Verify if the location LOCs block is in BLOCKS.  */
> >
> >  static bool
> > -verify_location (pointer_set_t *blocks, location_t loc)
> > +verify_location (hash_set<tree> *blocks, location_t loc)
> >  {
> >    tree block = LOCATION_BLOCK (loc);
> >    if (block != NULL_TREE
> > -      && !pointer_set_contains (blocks, block))
> > +      && !blocks->contains (block))
> >      {
> >        error ("location references block not in block tree");
> >        return true;
> > @@ -4770,7 +4770,7 @@ verify_expr_no_block (tree *tp, int *walk_subtrees, void *)
> >  static tree
> >  verify_expr_location_1 (tree *tp, int *walk_subtrees, void *data)
> >  {
> > -  struct pointer_set_t *blocks = (struct pointer_set_t *) data;
> > +  hash_set<tree> *blocks = (hash_set<tree> *) data;
> >
> >    if (TREE_CODE (*tp) == VAR_DECL
> >        && DECL_HAS_DEBUG_EXPR_P (*tp))
> > @@ -4816,12 +4816,12 @@ verify_expr_location (tree *tp, int *walk_subtrees, void *data)
> >  /* Insert all subblocks of BLOCK into BLOCKS and recurse.  */
> >
> >  static void
> > -collect_subblocks (pointer_set_t *blocks, tree block)
> > +collect_subblocks (hash_set<tree> *blocks, tree block)
> >  {
> >    tree t;
> >    for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
> >      {
> > -      pointer_set_insert (blocks, t);
> > +      blocks->add (t);
> >        collect_subblocks (blocks, t);
> >      }
> >  }
> > @@ -4833,18 +4833,17 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >  {
> >    basic_block bb;
> >    bool err = false;
> > -  struct pointer_set_t *visited, *visited_stmts, *blocks;
> >
> >    timevar_push (TV_TREE_STMT_VERIFY);
> > -  visited = pointer_set_create ();
> > -  visited_stmts = pointer_set_create ();
> > +  hash_set<void *> visited;
> > +  hash_set<gimple> visited_stmts;
> >
> >    /* Collect all BLOCKs referenced by the BLOCK tree of FN.  */
> > -  blocks = pointer_set_create ();
> > +  hash_set<tree> blocks;
> >    if (DECL_INITIAL (fn->decl))
> >      {
> > -      pointer_set_insert (blocks, DECL_INITIAL (fn->decl));
> > -      collect_subblocks (blocks, DECL_INITIAL (fn->decl));
> > +      blocks.add (DECL_INITIAL (fn->decl));
> > +      collect_subblocks (&blocks, DECL_INITIAL (fn->decl));
> >      }
> >
> >    FOR_EACH_BB_FN (bb, fn)
> > @@ -4857,7 +4856,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >           bool err2 = false;
> >           unsigned i;
> >
> > -         pointer_set_insert (visited_stmts, phi);
> > +         visited_stmts.add (phi);
> >
> >           if (gimple_bb (phi) != bb)
> >             {
> > @@ -4878,7 +4877,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >             {
> >               tree arg = gimple_phi_arg_def (phi, i);
> >               tree addr = walk_tree (&arg, verify_node_sharing_1,
> > -                                    visited, NULL);
> > +                                    &visited, NULL);
> >               if (addr)
> >                 {
> >                   error ("incorrect sharing of tree nodes");
> > @@ -4892,13 +4891,13 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >                   error ("virtual PHI with argument locations");
> >                   err2 = true;
> >                 }
> > -             addr = walk_tree (&arg, verify_expr_location_1, blocks, NULL);
> > +             addr = walk_tree (&arg, verify_expr_location_1, &blocks, NULL);
> >               if (addr)
> >                 {
> >                   debug_generic_expr (addr);
> >                   err2 = true;
> >                 }
> > -             err2 |= verify_location (blocks, loc);
> > +             err2 |= verify_location (&blocks, loc);
> >             }
> >
> >           if (err2)
> > @@ -4914,7 +4913,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >           tree addr;
> >           int lp_nr;
> >
> > -         pointer_set_insert (visited_stmts, stmt);
> > +         visited_stmts.add (stmt);
> >
> >           if (gimple_bb (stmt) != bb)
> >             {
> > @@ -4923,10 +4922,10 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >             }
> >
> >           err2 |= verify_gimple_stmt (stmt);
> > -         err2 |= verify_location (blocks, gimple_location (stmt));
> > +         err2 |= verify_location (&blocks, gimple_location (stmt));
> >
> >           memset (&wi, 0, sizeof (wi));
> > -         wi.info = (void *) visited;
> > +         wi.info = (void *) &visited;
> >           addr = walk_gimple_op (stmt, verify_node_sharing, &wi);
> >           if (addr)
> >             {
> > @@ -4936,7 +4935,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >             }
> >
> >           memset (&wi, 0, sizeof (wi));
> > -         wi.info = (void *) blocks;
> > +         wi.info = (void *) &blocks;
> >           addr = walk_gimple_op (stmt, verify_expr_location, &wi);
> >           if (addr)
> >             {
> > @@ -4992,14 +4991,11 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >    if (get_eh_throw_stmt_table (cfun))
> >      htab_traverse (get_eh_throw_stmt_table (cfun),
> >                    verify_eh_throw_stmt_node,
> > -                  visited_stmts);
> > +                  &visited_stmts);
> >
> >    if (err || eh_error_found)
> >      internal_error ("verify_gimple failed");
> >
> > -  pointer_set_destroy (visited);
> > -  pointer_set_destroy (visited_stmts);
> > -  pointer_set_destroy (blocks);
> >    verify_histograms ();
> >    timevar_pop (TV_TREE_STMT_VERIFY);
> >  }
> > diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> > index 34c48fa..9d462d1 100644
> > --- a/gcc/tree-core.h
> > +++ b/gcc/tree-core.h
> > @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #define GCC_TREE_CORE_H
> >
> >  #include "hashtab.h"
> > +#include "hash-set.h"
> >  #include "machmode.h"
> >  #include "input.h"
> >  #include "statistics.h"
> > @@ -45,7 +46,6 @@ struct fixed_value;
> >  struct ptr_info_def;
> >  struct range_info_def;
> >  struct die_struct;
> > -struct pointer_set_t;
> >
> >
> >  /*---------------------------------------------------------------------------
> > @@ -692,7 +692,7 @@ typedef tree (*walk_tree_fn) (tree *, int *, void *);
> >
> >  /* The type of a callback function that represents a custom walk_tree.  */
> >  typedef tree (*walk_tree_lh) (tree *, int *, tree (*) (tree *, int *, void *),
> > -                             void *, struct pointer_set_t*);
> > +                             void *, hash_set<tree> *);
> >
> >
> >  /*---------------------------------------------------------------------------
> > diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> > index df9a6fc..38842e8 100644
> > --- a/gcc/tree-eh.c
> > +++ b/gcc/tree-eh.c
> > @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "flags.h"
> >  #include "function.h"
> >  #include "except.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "basic-block.h"
> >  #include "tree-ssa-alias.h"
> > @@ -3578,7 +3579,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
> >         eh_catch c;
> >         edge_iterator ei;
> >         edge e;
> > -       struct pointer_set_t *seen_values = pointer_set_create ();
> > +       hash_set<tree> seen_values;
> >
> >         /* Collect the labels for a switch.  Zero the post_landing_pad
> >            field becase we'll no longer have anything keeping these labels
> > @@ -3605,12 +3606,12 @@ lower_eh_dispatch (basic_block src, gimple stmt)
> >                    attached to the handler anymore, we remove
> >                    the corresponding edge and then we delete unreachable
> >                    blocks at the end of this pass.  */
> > -               if (! pointer_set_contains (seen_values, TREE_VALUE (flt_node)))
> > +               if (! seen_values.contains (TREE_VALUE (flt_node)))
> >                   {
> >                     tree t = build_case_label (TREE_VALUE (flt_node),
> >                                                NULL, lab);
> >                     labels.safe_push (t);
> > -                   pointer_set_insert (seen_values, TREE_VALUE (flt_node));
> > +                   seen_values.add (TREE_VALUE (flt_node));
> >                     have_label = true;
> >                   }
> >
> > @@ -3662,7 +3663,6 @@ lower_eh_dispatch (basic_block src, gimple stmt)
> >             x = gimple_build_switch (filter, default_label, labels);
> >             gsi_insert_before (&gsi, x, GSI_SAME_STMT);
> >           }
> > -       pointer_set_destroy (seen_values);
> >        }
> >        break;
> >
> > diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> > index 33705b7..6af4912 100644
> > --- a/gcc/tree-inline.c
> > +++ b/gcc/tree-inline.c
> > @@ -1788,7 +1788,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
> >              expensive, copy_body can be told to watch for nontrivial
> >              changes.  */
> >           if (id->statements_to_fold)
> > -           pointer_set_insert (id->statements_to_fold, stmt);
> > +           id->statements_to_fold->add (stmt);
> >
> >           /* We're duplicating a CALL_EXPR.  Find any corresponding
> >              callgraph edges and update or duplicate them.  */
> > @@ -3507,7 +3507,6 @@ inline_forbidden_p (tree fndecl)
> >  {
> >    struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
> >    struct walk_stmt_info wi;
> > -  struct pointer_set_t *visited_nodes;
> >    basic_block bb;
> >    bool forbidden_p = false;
> >
> > @@ -3518,10 +3517,10 @@ inline_forbidden_p (tree fndecl)
> >
> >    /* Next, walk the statements of the function looking for
> >       constraucts we can't handle, or are non-optimal for inlining.  */
> > -  visited_nodes = pointer_set_create ();
> > +  hash_set<tree> visited_nodes;
> >    memset (&wi, 0, sizeof (wi));
> >    wi.info = (void *) fndecl;
> > -  wi.pset = visited_nodes;
> > +  wi.pset = &visited_nodes;
> >
> >    FOR_EACH_BB_FN (bb, fun)
> >      {
> > @@ -3533,7 +3532,6 @@ inline_forbidden_p (tree fndecl)
> >         break;
> >      }
> >
> > -  pointer_set_destroy (visited_nodes);
> >    return forbidden_p;
> >  }
> >
> > @@ -4531,7 +4529,7 @@ gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
> >     in the STATEMENTS pointer set.  */
> >
> >  static void
> > -fold_marked_statements (int first, struct pointer_set_t *statements)
> > +fold_marked_statements (int first, hash_set<gimple> *statements)
> >  {
> >    for (; first < n_basic_blocks_for_fn (cfun); first++)
> >      if (BASIC_BLOCK_FOR_FN (cfun, first))
> > @@ -4541,7 +4539,7 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
> >         for (gsi = gsi_start_bb (BASIC_BLOCK_FOR_FN (cfun, first));
> >              !gsi_end_p (gsi);
> >              gsi_next (&gsi))
> > -         if (pointer_set_contains (statements, gsi_stmt (gsi)))
> > +         if (statements->contains (gsi_stmt (gsi)))
> >             {
> >               gimple old_stmt = gsi_stmt (gsi);
> >               tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
> > @@ -4642,7 +4640,7 @@ optimize_inline_calls (tree fn)
> >    id.transform_return_to_modify = true;
> >    id.transform_parameter = true;
> >    id.transform_lang_insert_block = NULL;
> > -  id.statements_to_fold = pointer_set_create ();
> > +  id.statements_to_fold = new hash_set<gimple>;
> >
> >    push_gimplify_context ();
> >
> > @@ -4678,7 +4676,7 @@ optimize_inline_calls (tree fn)
> >
> >    /* Fold queued statements.  */
> >    fold_marked_statements (last, id.statements_to_fold);
> > -  pointer_set_destroy (id.statements_to_fold);
> > +  delete id.statements_to_fold;
> >
> >    gcc_assert (!id.debug_stmts.exists ());
> >
> > @@ -4920,7 +4918,6 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
> >  {
> >    copy_body_data id;
> >    struct walk_stmt_info wi;
> > -  struct pointer_set_t *visited;
> >    gimple_seq copy;
> >
> >    /* There's nothing to do for NULL_TREE.  */
> > @@ -4943,11 +4940,10 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
> >
> >    /* Walk the tree once to find local labels.  */
> >    memset (&wi, 0, sizeof (wi));
> > -  visited = pointer_set_create ();
> > +  hash_set<tree> visited;
> >    wi.info = &id;
> > -  wi.pset = visited;
> > +  wi.pset = &visited;
> >    walk_gimple_seq (seq, mark_local_labels_stmt, NULL, &wi);
> > -  pointer_set_destroy (visited);
> >
> >    copy = gimple_seq_copy (seq);
> >
> > @@ -5370,7 +5366,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
> >    memset (&id, 0, sizeof (id));
> >
> >    /* Generate a new name for the new version. */
> > -  id.statements_to_fold = pointer_set_create ();
> > +  id.statements_to_fold = new hash_set<gimple>;
> >
> >    id.decl_map = pointer_map_create ();
> >    id.debug_map = NULL;
> > @@ -5541,7 +5537,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
> >    free_dominance_info (CDI_POST_DOMINATORS);
> >
> >    fold_marked_statements (0, id.statements_to_fold);
> > -  pointer_set_destroy (id.statements_to_fold);
> > +  delete id.statements_to_fold;
> >    fold_cond_expr_cond ();
> >    delete_unreachable_blocks_update_callgraph (&id);
> >    if (id.dst_node->definition)
> > diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
> > index 2a5daaf..c13e6c7 100644
> > --- a/gcc/tree-inline.h
> > +++ b/gcc/tree-inline.h
> > @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
> >  #ifndef GCC_TREE_INLINE_H
> >  #define GCC_TREE_INLINE_H
> >
> > +#include "hash-set.h"
> > +
> >  struct cgraph_edge;
> >
> >  /* Indicate the desired behavior wrt call graph edges.  We can either
> > @@ -114,7 +116,7 @@ struct copy_body_data
> >    void (*transform_lang_insert_block) (tree);
> >
> >    /* Statements that might be possibly folded.  */
> > -  struct pointer_set_t *statements_to_fold;
> > +  hash_set<gimple> *statements_to_fold;
> >
> >    /* Entry basic block to currently copied body.  */
> >    basic_block entry_bb;
> > diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
> > index 185d87c..45c5cf7 100644
> > --- a/gcc/tree-nested.c
> > +++ b/gcc/tree-nested.c
> > @@ -95,7 +95,7 @@ struct nesting_info
> >
> >    struct pointer_map_t *field_map;
> >    struct pointer_map_t *var_map;
> > -  struct pointer_set_t *mem_refs;
> > +  hash_set<tree *> *mem_refs;
> >    bitmap suppress_expansion;
> >
> >    tree context;
> > @@ -732,7 +732,7 @@ create_nesting_tree (struct cgraph_node *cgn)
> >    struct nesting_info *info = XCNEW (struct nesting_info);
> >    info->field_map = pointer_map_create ();
> >    info->var_map = pointer_map_create ();
> > -  info->mem_refs = pointer_set_create ();
> > +  info->mem_refs = new hash_set<tree *>;
> >    info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
> >    info->context = cgn->decl;
> >
> > @@ -1651,7 +1651,7 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
> >          fold here, as the chain record type is not yet finalized.  */
> >        if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
> >           && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
> > -       pointer_set_insert (info->mem_refs, tp);
> > +       info->mem_refs->add (tp);
> >        wi->val_only = save_val_only;
> >        break;
> >
> > @@ -2655,8 +2655,8 @@ remap_vla_decls (tree block, struct nesting_info *root)
> >  }
> >
> >  /* Fold the MEM_REF *E.  */
> > -static bool
> > -fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED)
> > +bool
> > +fold_mem_refs (tree *const &e, void *data ATTRIBUTE_UNUSED)
> >  {
> >    tree *ref_p = CONST_CAST2 (tree *, const tree *, (const tree *)e);
> >    *ref_p = fold (*ref_p);
> > @@ -2878,7 +2878,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
> >      }
> >
> >    /* Fold the rewritten MEM_REF trees.  */
> > -  pointer_set_traverse (root->mem_refs, fold_mem_refs, NULL);
> > +  root->mem_refs->traverse<void *, fold_mem_refs> (NULL);
> >
> >    /* Dump the translated tree function.  */
> >    if (dump_file)
> > @@ -2933,7 +2933,7 @@ free_nesting_tree (struct nesting_info *root)
> >        next = iter_nestinfo_next (node);
> >        pointer_map_destroy (node->var_map);
> >        pointer_map_destroy (node->field_map);
> > -      pointer_set_destroy (node->mem_refs);
> > +      delete node->mem_refs;
> >        free (node);
> >        node = next;
> >      }
> > diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
> > index ca6e014..aee0331 100644
> > --- a/gcc/tree-pretty-print.c
> > +++ b/gcc/tree-pretty-print.c
> > @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "expr.h"
> >  #include "tree-pretty-print.h"
> >  #include "hashtab.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "gimple-expr.h"
> >  #include "cgraph.h"
> >  #include "langhooks.h"
> > @@ -103,14 +103,14 @@ debug_generic_stmt (tree t)
> >  DEBUG_FUNCTION void
> >  debug_tree_chain (tree t)
> >  {
> > -  struct pointer_set_t *seen = pointer_set_create ();
> > +  hash_set<tree> seen;
> >
> >    while (t)
> >      {
> >        print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
> >        fprintf (stderr, " ");
> >        t = TREE_CHAIN (t);
> > -      if (pointer_set_insert (seen, t))
> > +      if (seen.add (t))
> >         {
> >           fprintf (stderr, "... [cycled back to ");
> >           print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
> > @@ -119,8 +119,6 @@ debug_tree_chain (tree t)
> >         }
> >      }
> >    fprintf (stderr, "\n");
> > -
> > -  pointer_set_destroy (seen);
> >  }
> >
> >  /* Prints declaration DECL to the FILE with details specified by FLAGS.  */
> > diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
> > index 36d68a8..83c1b19 100644
> > --- a/gcc/tree-ssa-loop-niter.c
> > +++ b/gcc/tree-ssa-loop-niter.c
> > @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "basic-block.h"
> >  #include "gimple-pretty-print.h"
> >  #include "intl.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> > @@ -3281,7 +3282,7 @@ discover_iteration_bound_by_body_walk (struct loop *loop)
> >  static void
> >  maybe_lower_iteration_bound (struct loop *loop)
> >  {
> > -  pointer_set_t *not_executed_last_iteration = NULL;
> > +  hash_set<gimple> *not_executed_last_iteration = NULL;
> >    struct nb_iter_bound *elt;
> >    bool found_exit = false;
> >    vec<basic_block> queue = vNULL;
> > @@ -3300,8 +3301,8 @@ maybe_lower_iteration_bound (struct loop *loop)
> >           && wi::ltu_p (elt->bound, loop->nb_iterations_upper_bound))
> >         {
> >           if (!not_executed_last_iteration)
> > -           not_executed_last_iteration = pointer_set_create ();
> > -         pointer_set_insert (not_executed_last_iteration, elt->stmt);
> > +           not_executed_last_iteration = new hash_set<gimple>;
> > +         not_executed_last_iteration->add (elt->stmt);
> >         }
> >      }
> >    if (!not_executed_last_iteration)
> > @@ -3327,7 +3328,7 @@ maybe_lower_iteration_bound (struct loop *loop)
> >        for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> >         {
> >           gimple stmt = gsi_stmt (gsi);
> > -         if (pointer_set_contains (not_executed_last_iteration, stmt))
> > +         if (not_executed_last_iteration->contains (stmt))
> >             {
> >               stmt_found = true;
> >               break;
> > @@ -3376,7 +3377,7 @@ maybe_lower_iteration_bound (struct loop *loop)
> >      }
> >    BITMAP_FREE (visited);
> >    queue.release ();
> > -  pointer_set_destroy (not_executed_last_iteration);
> > +  delete not_executed_last_iteration;
> >  }
> >
> >  /* Records estimates on numbers of iterations of LOOP.  If USE_UNDEFINED_P
> > diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
> > index 052d760..3185d9a 100644
> > --- a/gcc/tree-ssa-phiopt.c
> > +++ b/gcc/tree-ssa-phiopt.c
> > @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "flags.h"
> >  #include "tm_p.h"
> >  #include "basic-block.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> > @@ -72,9 +73,9 @@ static bool abs_replacement (basic_block, basic_block,
> >  static bool neg_replacement (basic_block, basic_block,
> >                              edge, edge, gimple, tree, tree);
> >  static bool cond_store_replacement (basic_block, basic_block, edge, edge,
> > -                                   struct pointer_set_t *);
> > +                                   hash_set<tree> *);
> >  static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
> > -static struct pointer_set_t * get_non_trapping (void);
> > +static hash_set<tree> * get_non_trapping ();
> >  static void replace_phi_edge_with_variable (basic_block, edge, gimple, tree);
> >  static void hoist_adjacent_loads (basic_block, basic_block,
> >                                   basic_block, basic_block);
> > @@ -176,7 +177,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
> >    basic_block *bb_order;
> >    unsigned n, i;
> >    bool cfgchanged = false;
> > -  struct pointer_set_t *nontrap = 0;
> > +  hash_set<tree> *nontrap = 0;
> >
> >    if (do_store_elim)
> >      /* Calculate the set of non-trapping memory accesses.  */
> > @@ -363,7 +364,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
> >    free (bb_order);
> >
> >    if (do_store_elim)
> > -    pointer_set_destroy (nontrap);
> > +    delete nontrap;
> >    /* If the CFG has changed, we should cleanup the CFG.  */
> >    if (cfgchanged && do_store_elim)
> >      {
> > @@ -1469,7 +1470,7 @@ ssa_names_hasher::equal (const value_type *n1, const compare_type *n2)
> >  class nontrapping_dom_walker : public dom_walker
> >  {
> >  public:
> > -  nontrapping_dom_walker (cdi_direction direction, pointer_set_t *ps)
> > +  nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps)
> >      : dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {}
> >
> >    virtual void before_dom_children (basic_block);
> > @@ -1484,7 +1485,7 @@ private:
> >       the RHS.  */
> >    void add_or_mark_expr (basic_block, tree, bool);
> >
> > -  pointer_set_t *m_nontrapping;
> > +  hash_set<tree> *m_nontrapping;
> >
> >    /* The hash table for remembering what we've seen.  */
> >    hash_table<ssa_names_hasher> m_seen_ssa_names;
> > @@ -1572,7 +1573,7 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
> >          then we can't trap.  */
> >        if (found_bb && (((size_t)found_bb->aux) & 1) == 1)
> >         {
> > -         pointer_set_insert (m_nontrapping, exp);
> > +         m_nontrapping->add (exp);
> >         }
> >        else
> >          {
> > @@ -1601,11 +1602,11 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
> >     It will do a dominator walk over the whole function, and it will
> >     make use of the bb->aux pointers.  It returns a set of trees
> >     (the MEM_REFs itself) which can't trap.  */
> > -static struct pointer_set_t *
> > +static hash_set<tree> *
> >  get_non_trapping (void)
> >  {
> >    nt_call_phase = 0;
> > -  pointer_set_t *nontrap = pointer_set_create ();
> > +  hash_set<tree> *nontrap = new hash_set<tree>;
> >    /* We're going to do a dominator walk, so ensure that we have
> >       dominance information.  */
> >    calculate_dominance_info (CDI_DOMINATORS);
> > @@ -1634,7 +1635,7 @@ get_non_trapping (void)
> >
> >  static bool
> >  cond_store_replacement (basic_block middle_bb, basic_block join_bb,
> > -                       edge e0, edge e1, struct pointer_set_t *nontrap)
> > +                       edge e0, edge e1, hash_set<tree> *nontrap)
> >  {
> >    gimple assign = last_and_only_stmt (middle_bb);
> >    tree lhs, rhs, name, name2;
> > @@ -1659,7 +1660,7 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb,
> >    /* Prove that we can move the store down.  We could also check
> >       TREE_THIS_NOTRAP here, but in that case we also could move stores,
> >       whose value is not available readily, which we want to avoid.  */
> > -  if (!pointer_set_contains (nontrap, lhs))
> > +  if (!nontrap->contains (lhs))
> >      return false;
> >
> >    /* Now we've checked the constraints, so do the transformation:
> > diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
> > index 9807b42..3dee5ba 100644
> > --- a/gcc/tree-ssa-threadedge.c
> > +++ b/gcc/tree-ssa-threadedge.c
> > @@ -30,7 +30,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "function.h"
> >  #include "timevar.h"
> >  #include "dumpfile.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> >  #include "gimple-expr.h"
> > @@ -693,13 +693,13 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >      }
> >
> >    auto_vec<tree, alloc_count> fewvars;
> > -  pointer_set_t *vars = NULL;
> > +  hash_set<tree> *vars = NULL;
> >
> >    /* If we're already starting with 3/4 of alloc_count, go for a
> > -     pointer_set, otherwise start with an unordered stack-allocated
> > +     hash_set, otherwise start with an unordered stack-allocated
> >       VEC.  */
> >    if (i * 4 > alloc_count * 3)
> > -    vars = pointer_set_create ();
> > +    vars = new hash_set<tree>;
> >
> >    /* Now go through the initial debug stmts in DEST again, this time
> >       actually inserting in VARS or FEWVARS.  Don't bother checking for
> > @@ -720,7 +720,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >         gcc_unreachable ();
> >
> >        if (vars)
> > -       pointer_set_insert (vars, var);
> > +       vars->add (var);
> >        else
> >         fewvars.quick_push (var);
> >      }
> > @@ -754,7 +754,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >              or somesuch.  Adding `&& bb == src' to the condition
> >              below will preserve all potentially relevant debug
> >              notes.  */
> > -         if (vars && pointer_set_insert (vars, var))
> > +         if (vars && vars->add (var))
> >             continue;
> >           else if (!vars)
> >             {
> > @@ -769,11 +769,11 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >                 fewvars.quick_push (var);
> >               else
> >                 {
> > -                 vars = pointer_set_create ();
> > +                 vars = new hash_set<tree>;
> >                   for (i = 0; i < alloc_count; i++)
> > -                   pointer_set_insert (vars, fewvars[i]);
> > +                   vars->add (fewvars[i]);
> >                   fewvars.release ();
> > -                 pointer_set_insert (vars, var);
> > +                 vars->add (var);
> >                 }
> >             }
> >
> > @@ -786,7 +786,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >    while (bb != src && single_pred_p (bb));
> >
> >    if (vars)
> > -    pointer_set_destroy (vars);
> > +    delete vars;
> >    else if (fewvars.exists ())
> >      fewvars.release ();
> >  }
> > diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
> > index 64259fb..f2578b7 100644
> > --- a/gcc/tree-ssa-uninit.c
> > +++ b/gcc/tree-ssa-uninit.c
> > @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "function.h"
> >  #include "gimple-pretty-print.h"
> >  #include "bitmap.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> > @@ -60,7 +61,7 @@ along with GCC; see the file COPYING3.  If not see
> >  /* Pointer set of potentially undefined ssa names, i.e.,
> >     ssa names that are defined by phi with operands that
> >     are not defined or potentially undefined.  */
> > -static pointer_set_t *possibly_undefined_names = 0;
> > +static hash_set<tree> *possibly_undefined_names = 0;
> >
> >  /* Bit mask handling macros.  */
> >  #define MASK_SET_BIT(mask, pos) mask |= (1 << pos)
> > @@ -89,7 +90,7 @@ has_undefined_value_p (tree t)
> >  {
> >    return (ssa_undefined_value_p (t)
> >            || (possibly_undefined_names
> > -              && pointer_set_contains (possibly_undefined_names, t)));
> > +              && possibly_undefined_names->contains (t)));
> >  }
> >
> >
> > @@ -648,13 +649,13 @@ find_predicates (pred_chain_union *preds,
> >  static void
> >  collect_phi_def_edges (gimple phi, basic_block cd_root,
> >                         vec<edge> *edges,
> > -                       pointer_set_t *visited_phis)
> > +                       hash_set<gimple> *visited_phis)
> >  {
> >    size_t i, n;
> >    edge opnd_edge;
> >    tree opnd;
> >
> > -  if (pointer_set_insert (visited_phis, phi))
> > +  if (visited_phis->add (phi))
> >      return;
> >
> >    n = gimple_phi_num_args (phi);
> > @@ -707,7 +708,6 @@ find_def_preds (pred_chain_union *preds, gimple phi)
> >    vec<edge> def_edges = vNULL;
> >    bool has_valid_pred = false;
> >    basic_block phi_bb, cd_root = 0;
> > -  pointer_set_t *visited_phis;
> >
> >    phi_bb = gimple_bb (phi);
> >    /* First find the closest dominating bb to be
> > @@ -716,9 +716,8 @@ find_def_preds (pred_chain_union *preds, gimple phi)
> >    if (!cd_root)
> >      return false;
> >
> > -  visited_phis = pointer_set_create ();
> > -  collect_phi_def_edges (phi, cd_root, &def_edges, visited_phis);
> > -  pointer_set_destroy (visited_phis);
> > +  hash_set<gimple> visited_phis;
> > +  collect_phi_def_edges (phi, cd_root, &def_edges, &visited_phis);
> >
> >    n = def_edges.length ();
> >    if (n == 0)
> > @@ -941,7 +940,7 @@ is_use_properly_guarded (gimple use_stmt,
> >                           basic_block use_bb,
> >                           gimple phi,
> >                           unsigned uninit_opnds,
> > -                         pointer_set_t *visited_phis);
> > +                         hash_set<gimple> *visited_phis);
> >
> >  /* Returns true if all uninitialized opnds are pruned. Returns false
> >     otherwise. PHI is the phi node with uninitialized operands,
> > @@ -983,7 +982,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
> >                                               gimple flag_def,
> >                                               tree boundary_cst,
> >                                               enum tree_code cmp_code,
> > -                                             pointer_set_t *visited_phis,
> > +                                             hash_set<gimple> *visited_phis,
> >                                               bitmap *visited_flag_phis)
> >  {
> >    unsigned i;
> > @@ -1153,7 +1152,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
> >  static bool
> >  use_pred_not_overlap_with_undef_path_pred (pred_chain_union preds,
> >                                            gimple phi, unsigned uninit_opnds,
> > -                                          pointer_set_t *visited_phis)
> > +                                          hash_set<gimple> *visited_phis)
> >  {
> >    unsigned int i, n;
> >    gimple flag_def = 0;
> > @@ -1818,11 +1817,11 @@ push_pred (pred_chain_union *norm_preds, pred_info pred)
> >
> >  inline static void
> >  push_to_worklist (tree op, vec<pred_info, va_heap, vl_ptr> *work_list,
> > -                  pointer_set_t *mark_set)
> > +                  hash_set<tree> *mark_set)
> >  {
> > -  if (pointer_set_contains (mark_set, op))
> > +  if (mark_set->contains (op))
> >      return;
> > -  pointer_set_insert (mark_set, op);
> > +  mark_set->add (op);
> >
> >    pred_info arg_pred;
> >    arg_pred.pred_lhs = op;
> > @@ -1907,7 +1906,7 @@ normalize_one_pred_1 (pred_chain_union *norm_preds,
> >                        pred_info pred,
> >                        enum tree_code and_or_code,
> >                        vec<pred_info, va_heap, vl_ptr> *work_list,
> > -                     pointer_set_t *mark_set)
> > +                     hash_set<tree> *mark_set)
> >  {
> >    if (!is_neq_zero_form_p (pred))
> >      {
> > @@ -1987,7 +1986,6 @@ normalize_one_pred (pred_chain_union *norm_preds,
> >                      pred_info pred)
> >  {
> >    vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
> > -  pointer_set_t *mark_set = NULL;
> >    enum tree_code and_or_code = ERROR_MARK;
> >    pred_chain norm_chain = vNULL;
> >
> > @@ -2015,19 +2013,18 @@ normalize_one_pred (pred_chain_union *norm_preds,
> >      }
> >
> >    work_list.safe_push (pred);
> > -  mark_set = pointer_set_create ();
> > +  hash_set<tree> mark_set;
> >
> >    while (!work_list.is_empty ())
> >      {
> >        pred_info a_pred = work_list.pop ();
> >        normalize_one_pred_1 (norm_preds, &norm_chain, a_pred,
> > -                            and_or_code, &work_list, mark_set);
> > +                            and_or_code, &work_list, &mark_set);
> >      }
> >    if (and_or_code == BIT_AND_EXPR)
> >      norm_preds->safe_push (norm_chain);
> >
> >    work_list.release ();
> > -  pointer_set_destroy (mark_set);
> >  }
> >
> >  static void
> > @@ -2035,26 +2032,25 @@ normalize_one_pred_chain (pred_chain_union *norm_preds,
> >                            pred_chain one_chain)
> >  {
> >    vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
> > -  pointer_set_t *mark_set = pointer_set_create ();
> > +  hash_set<tree> mark_set;
> >    pred_chain norm_chain = vNULL;
> >    size_t i;
> >
> >    for (i = 0; i < one_chain.length (); i++)
> >      {
> >        work_list.safe_push (one_chain[i]);
> > -      pointer_set_insert (mark_set, one_chain[i].pred_lhs);
> > +      mark_set.add (one_chain[i].pred_lhs);
> >      }
> >
> >    while (!work_list.is_empty ())
> >      {
> >        pred_info a_pred = work_list.pop ();
> >        normalize_one_pred_1 (0, &norm_chain, a_pred,
> > -                            BIT_AND_EXPR, &work_list, mark_set);
> > +                            BIT_AND_EXPR, &work_list, &mark_set);
> >      }
> >
> >    norm_preds->safe_push (norm_chain);
> >    work_list.release ();
> > -  pointer_set_destroy (mark_set);
> >  }
> >
> >  /* Normalize predicate chains PREDS and returns the normalized one.  */
> > @@ -2112,7 +2108,7 @@ is_use_properly_guarded (gimple use_stmt,
> >                           basic_block use_bb,
> >                           gimple phi,
> >                           unsigned uninit_opnds,
> > -                         pointer_set_t *visited_phis)
> > +                         hash_set<gimple> *visited_phis)
> >  {
> >    basic_block phi_bb;
> >    pred_chain_union preds = vNULL;
> > @@ -2120,7 +2116,7 @@ is_use_properly_guarded (gimple use_stmt,
> >    bool has_valid_preds = false;
> >    bool is_properly_guarded = false;
> >
> > -  if (pointer_set_insert (visited_phis, phi))
> > +  if (visited_phis->add (phi))
> >      return false;
> >
> >    phi_bb = gimple_bb (phi);
> > @@ -2181,7 +2177,7 @@ is_use_properly_guarded (gimple use_stmt,
> >  static gimple
> >  find_uninit_use (gimple phi, unsigned uninit_opnds,
> >                   vec<gimple> *worklist,
> > -                pointer_set_t *added_to_worklist)
> > +                hash_set<gimple> *added_to_worklist)
> >  {
> >    tree phi_result;
> >    use_operand_p use_p;
> > @@ -2192,28 +2188,22 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >
> >    FOR_EACH_IMM_USE_FAST (use_p, iter, phi_result)
> >      {
> > -      pointer_set_t *visited_phis;
> >        basic_block use_bb;
> >
> >        use_stmt = USE_STMT (use_p);
> >        if (is_gimple_debug (use_stmt))
> >         continue;
> >
> > -      visited_phis = pointer_set_create ();
> > -
> >        if (gimple_code (use_stmt) == GIMPLE_PHI)
> >         use_bb = gimple_phi_arg_edge (use_stmt,
> >                                       PHI_ARG_INDEX_FROM_USE (use_p))->src;
> >        else
> >         use_bb = gimple_bb (use_stmt);
> >
> > +      hash_set<gimple> visited_phis;
> >        if (is_use_properly_guarded (use_stmt, use_bb, phi, uninit_opnds,
> > -                                   visited_phis))
> > -        {
> > -          pointer_set_destroy (visited_phis);
> > -          continue;
> > -        }
> > -      pointer_set_destroy (visited_phis);
> > +                                   &visited_phis))
> > +       continue;
> >
> >        if (dump_file && (dump_flags & TDF_DETAILS))
> >          {
> > @@ -2226,7 +2216,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >
> >        /* Found a phi use that is not guarded,
> >           add the phi to the worklist.  */
> > -      if (!pointer_set_insert (added_to_worklist, use_stmt))
> > +      if (!added_to_worklist->add (use_stmt))
> >          {
> >            if (dump_file && (dump_flags & TDF_DETAILS))
> >              {
> > @@ -2235,7 +2225,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >              }
> >
> >            worklist->safe_push (use_stmt);
> > -          pointer_set_insert (possibly_undefined_names, phi_result);
> > +          possibly_undefined_names->add (phi_result);
> >          }
> >      }
> >
> > @@ -2252,7 +2242,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >
> >  static void
> >  warn_uninitialized_phi (gimple phi, vec<gimple> *worklist,
> > -                        pointer_set_t *added_to_worklist)
> > +                        hash_set<gimple> *added_to_worklist)
> >  {
> >    unsigned uninit_opnds;
> >    gimple uninit_use_stmt = 0;
> > @@ -2339,7 +2329,6 @@ pass_late_warn_uninitialized::execute (function *fun)
> >    basic_block bb;
> >    gimple_stmt_iterator gsi;
> >    vec<gimple> worklist = vNULL;
> > -  pointer_set_t *added_to_worklist;
> >
> >    calculate_dominance_info (CDI_DOMINATORS);
> >    calculate_dominance_info (CDI_POST_DOMINATORS);
> > @@ -2350,8 +2339,8 @@ pass_late_warn_uninitialized::execute (function *fun)
> >
> >    timevar_push (TV_TREE_UNINIT);
> >
> > -  possibly_undefined_names = pointer_set_create ();
> > -  added_to_worklist = pointer_set_create ();
> > +  possibly_undefined_names = new hash_set<tree>;
> > +  hash_set<gimple> added_to_worklist;
> >
> >    /* Initialize worklist  */
> >    FOR_EACH_BB_FN (bb, fun)
> > @@ -2373,7 +2362,7 @@ pass_late_warn_uninitialized::execute (function *fun)
> >                 && uninit_undefined_value_p (op))
> >               {
> >                 worklist.safe_push (phi);
> > -               pointer_set_insert (added_to_worklist, phi);
> > +               added_to_worklist.add (phi);
> >                 if (dump_file && (dump_flags & TDF_DETAILS))
> >                   {
> >                     fprintf (dump_file, "[WORKLIST]: add to initial list: ");
> > @@ -2388,12 +2377,11 @@ pass_late_warn_uninitialized::execute (function *fun)
> >      {
> >        gimple cur_phi = 0;
> >        cur_phi = worklist.pop ();
> > -      warn_uninitialized_phi (cur_phi, &worklist, added_to_worklist);
> > +      warn_uninitialized_phi (cur_phi, &worklist, &added_to_worklist);
> >      }
> >
> >    worklist.release ();
> > -  pointer_set_destroy (added_to_worklist);
> > -  pointer_set_destroy (possibly_undefined_names);
> > +  delete possibly_undefined_names;
> >    possibly_undefined_names = NULL;
> >    free_dominance_info (CDI_POST_DOMINATORS);
> >    timevar_pop (TV_TREE_UNINIT);
> > diff --git a/gcc/tree.c b/gcc/tree.c
> > index 6669a84..de1c9b6 100644
> > --- a/gcc/tree.c
> > +++ b/gcc/tree.c
> > @@ -5143,7 +5143,7 @@ struct free_lang_data_d
> >    vec<tree> worklist;
> >
> >    /* Set of traversed objects.  Used to avoid duplicate visits.  */
> > -  struct pointer_set_t *pset;
> > +  hash_set<tree> *pset;
> >
> >    /* Array of symbols to process with free_lang_data_in_decl.  */
> >    vec<tree> decls;
> > @@ -5208,7 +5208,7 @@ add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
> >  static inline void
> >  fld_worklist_push (tree t, struct free_lang_data_d *fld)
> >  {
> > -  if (t && !is_lang_specific (t) && !pointer_set_contains (fld->pset, t))
> > +  if (t && !is_lang_specific (t) && !fld->pset->contains (t))
> >      fld->worklist.safe_push ((t));
> >  }
> >
> > @@ -5374,7 +5374,7 @@ find_decls_types (tree t, struct free_lang_data_d *fld)
> >  {
> >    while (1)
> >      {
> > -      if (!pointer_set_contains (fld->pset, t))
> > +      if (!fld->pset->contains (t))
> >         walk_tree (&t, find_decls_types_r, fld, fld->pset);
> >        if (fld->worklist.is_empty ())
> >         break;
> > @@ -5584,7 +5584,7 @@ free_lang_data_in_cgraph (void)
> >    alias_pair *p;
> >
> >    /* Initialize sets and arrays to store referenced decls and types.  */
> > -  fld.pset = pointer_set_create ();
> > +  fld.pset = new hash_set<tree>;
> >    fld.worklist.create (0);
> >    fld.decls.create (100);
> >    fld.types.create (100);
> > @@ -5614,7 +5614,7 @@ free_lang_data_in_cgraph (void)
> >    FOR_EACH_VEC_ELT (fld.types, i, t)
> >      free_lang_data_in_type (t);
> >
> > -  pointer_set_destroy (fld.pset);
> > +  delete fld.pset;
> >    fld.worklist.release ();
> >    fld.decls.release ();
> >    fld.types.release ();
> > @@ -10819,7 +10819,7 @@ num_ending_zeros (const_tree x)
> >
> >  static tree
> >  walk_type_fields (tree type, walk_tree_fn func, void *data,
> > -                 struct pointer_set_t *pset, walk_tree_lh lh)
> > +                 hash_set<tree> *pset, walk_tree_lh lh)
> >  {
> >    tree result = NULL_TREE;
> >
> > @@ -10901,7 +10901,7 @@ walk_type_fields (tree type, walk_tree_fn func, void *data,
> >
> >  tree
> >  walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
> > -            struct pointer_set_t *pset, walk_tree_lh lh)
> > +            hash_set<tree> *pset, walk_tree_lh lh)
> >  {
> >    enum tree_code code;
> >    int walk_subtrees;
> > @@ -10922,7 +10922,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
> >
> >    /* Don't walk the same tree twice, if the user has requested
> >       that we avoid doing so.  */
> > -  if (pset && pointer_set_insert (pset, *tp))
> > +  if (pset && pset->add (*tp))
> >      return NULL_TREE;
> >
> >    /* Call the function.  */
> > @@ -11237,11 +11237,9 @@ walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data,
> >                                 walk_tree_lh lh)
> >  {
> >    tree result;
> > -  struct pointer_set_t *pset;
> >
> > -  pset = pointer_set_create ();
> > -  result = walk_tree_1 (tp, func, data, pset, lh);
> > -  pointer_set_destroy (pset);
> > +  hash_set<tree> pset;
> > +  result = walk_tree_1 (tp, func, data, &pset, lh);
> >    return result;
> >  }
> >
> > diff --git a/gcc/tree.h b/gcc/tree.h
> > index 2bb6d1f..c9f978a 100644
> > --- a/gcc/tree.h
> > +++ b/gcc/tree.h
> > @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #define GCC_TREE_H
> >
> >  #include "tree-core.h"
> > +#include "hash-set.h"
> >  #include "wide-int.h"
> >  #include "inchash.h"
> >
> > @@ -4328,7 +4329,7 @@ extern void using_eh_for_cleanups (void);
> >  extern bool using_eh_for_cleanups_p (void);
> >  extern const char *get_tree_code_name (enum tree_code);
> >  extern void set_call_expr_flags (tree, int);
> > -extern tree walk_tree_1 (tree*, walk_tree_fn, void*, struct pointer_set_t*,
> > +extern tree walk_tree_1 (tree*, walk_tree_fn, void*, hash_set<tree>*,
> >                          walk_tree_lh);
> >  extern tree walk_tree_without_duplicates_1 (tree*, walk_tree_fn, void*,
> >                                             walk_tree_lh);
> > diff --git a/gcc/value-prof.c b/gcc/value-prof.c
> > index 3e51539..ffdee65 100644
> > --- a/gcc/value-prof.c
> > +++ b/gcc/value-prof.c
> > @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "data-streamer.h"
> >  #include "builtins.h"
> >  #include "tree-nested.h"
> > +#include "hash-set.h"
> >
> >  /* In this file value profile based optimizations are placed.  Currently the
> >     following optimizations are implemented (for more detailed descriptions
> > @@ -515,10 +516,10 @@ static bool error_found = false;
> >  static int
> >  visit_hist (void **slot, void *data)
> >  {
> > -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> > +  hash_set<histogram_value> *visited = (hash_set<histogram_value> *) data;
> >    histogram_value hist = *(histogram_value *) slot;
> >
> > -  if (!pointer_set_contains (visited, hist)
> > +  if (!visited->contains (hist)
> >        && hist->type != HIST_TYPE_TIME_PROFILE)
> >      {
> >        error ("dead histogram");
> > @@ -538,10 +539,9 @@ verify_histograms (void)
> >    basic_block bb;
> >    gimple_stmt_iterator gsi;
> >    histogram_value hist;
> > -  struct pointer_set_t *visited_hists;
> >
> >    error_found = false;
> > -  visited_hists = pointer_set_create ();
> > +  hash_set<histogram_value> visited_hists;
> >    FOR_EACH_BB_FN (bb, cfun)
> >      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> >        {
> > @@ -558,12 +558,11 @@ verify_histograms (void)
> >                 dump_histogram_value (stderr, hist);
> >                 error_found = true;
> >               }
> > -            pointer_set_insert (visited_hists, hist);
> > +            visited_hists.add (hist);
> >           }
> >        }
> >    if (VALUE_HISTOGRAMS (cfun))
> > -    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, visited_hists);
> > -  pointer_set_destroy (visited_hists);
> > +    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, &visited_hists);
> >    if (error_found)
> >      internal_error ("verify_histograms failed");
> >  }
> > diff --git a/gcc/varasm.c b/gcc/varasm.c
> > index 819ec26..9d8602b 100644
> > --- a/gcc/varasm.c
> > +++ b/gcc/varasm.c
> > @@ -51,7 +51,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "common/common-target.h"
> >  #include "targhooks.h"
> >  #include "cgraph.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "asan.h"
> >  #include "basic-block.h"
> >
> > @@ -2249,7 +2249,7 @@ static bool pending_assemble_externals_processed;
> >
> >  /* Avoid O(external_decls**2) lookups in the pending_assemble_externals
> >     TREE_LIST in assemble_external.  */
> > -static struct pointer_set_t *pending_assemble_externals_set;
> > +static hash_set<tree> *pending_assemble_externals_set;
> >
> >  /* True if DECL is a function decl for which no out-of-line copy exists.
> >     It is assumed that DECL's assembler name has been set.  */
> > @@ -2303,7 +2303,7 @@ process_pending_assemble_externals (void)
> >
> >    pending_assemble_externals = 0;
> >    pending_assemble_externals_processed = true;
> > -  pointer_set_destroy (pending_assemble_externals_set);
> > +  delete pending_assemble_externals_set;
> >  #endif
> >  }
> >
> > @@ -2361,7 +2361,7 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
> >        return;
> >      }
> >
> > -  if (! pointer_set_insert (pending_assemble_externals_set, decl))
> > +  if (! pending_assemble_externals_set->add (decl))
> >      pending_assemble_externals = tree_cons (NULL, decl,
> >                                             pending_assemble_externals);
> >  #endif
> > @@ -5991,7 +5991,7 @@ init_varasm_once (void)
> >      readonly_data_section = text_section;
> >
> >  #ifdef ASM_OUTPUT_EXTERNAL
> > -  pending_assemble_externals_set = pointer_set_create ();
> > +  pending_assemble_externals_set = new hash_set<tree>;
> >  #endif
> >  }
> >
> > diff --git a/gcc/varpool.c b/gcc/varpool.c
> > index 74117e2..558767f 100644
> > --- a/gcc/varpool.c
> > +++ b/gcc/varpool.c
> > @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "tree-ssa-alias.h"
> >  #include "gimple.h"
> >  #include "lto-streamer.h"
> > +#include "hash-set.h"
> >
> >  const char * const tls_model_names[]={"none", "tls-emulated", "tls-real",
> >                                       "tls-global-dynamic", "tls-local-dynamic",
> > @@ -576,7 +577,7 @@ varpool_remove_unreferenced_decls (void)
> >    varpool_node *first = (varpool_node *)(void *)1;
> >    int i;
> >    struct ipa_ref *ref = NULL;
> > -  struct pointer_set_t *referenced = pointer_set_create ();
> > +  hash_set<varpool_node *> referenced;
> >
> >    if (seen_error ())
> >      return;
> > @@ -623,7 +624,7 @@ varpool_remove_unreferenced_decls (void)
> >               && vnode->analyzed)
> >             enqueue_node (vnode, &first);
> >           else
> > -           pointer_set_insert (referenced, node);
> > +           referenced.add (node);
> >         }
> >      }
> >    if (cgraph_dump_file)
> > @@ -635,13 +636,13 @@ varpool_remove_unreferenced_decls (void)
> >         {
> >            if (cgraph_dump_file)
> >             fprintf (cgraph_dump_file, " %s", node->asm_name ());
> > -         if (pointer_set_contains (referenced, node))
> > +         if (referenced.contains (node))
> >             node->remove_initializer ();
> >           else
> >             node->remove ();
> >         }
> >      }
> > -  pointer_set_destroy (referenced);
> > +
> >    if (cgraph_dump_file)
> >      fprintf (cgraph_dump_file, "\n");
> >  }
> > --
> > 2.0.1
> >
Andrew Pinski Aug. 2, 2014, 10:44 p.m. UTC | #3
On Tue, Jul 29, 2014 at 5:50 AM,  <tsaunders@mozilla.com> wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
> this adds a hash_set wrapper around hash_table, and then replaces usage of pointer_set with it.
>
> bootstrapped +regtested on x86_64-unknown-linux-gnu, ok?
>
> Trev
>
> ada/
>
>         * gcc-interface/trans.c: Use hash_set instead of pointer_set.
>
> c-family/
>
>         * c-gimplify.c: Use hash_set instead of pointer_set.
>
> c/
>
>         * c-decl.c: Use hash_set instead of pointer_set.
>
> cp/
>
>         * class.c, cp-gimplify.c, cp-tree.h, decl.c, decl2.c, error.c,
>         method.c, name-lookup.c, pt.c, semantics.c, tree.c: Use hash_set
>         instead of pointer_set.
>
> fortran/
>
>         * openmp.c, trans-decl.c: Use hash_set instead of pointer_set.
>
> gcc/
>
>         * hash-set.h: new File.
>         * cfgexpand.c, cfgloop.c, cgraph.c, cgraphbuild.c, cgraphunit.c,
>         cprop.c, cse.c, gimple-walk.c, gimple-walk.h, gimplify.c, godump.c,
>         ipa-devirt.c, ipa-pure-const.c, ipa-visibility.c, ipa.c, lto-cgraph.c,
>         lto-streamer-out.c, stmt.c, tree-cfg.c, tree-core.h, tree-eh.c,
>         tree-inline.c, tree-inline.h, tree-nested.c, tree-pretty-print.c,
>         tree-ssa-loop-niter.c, tree-ssa-phiopt.c, tree-ssa-threadedge.c,
>         tree-ssa-uninit.c, tree.c, tree.h, value-prof.c, varasm.c,
>         varpool.c: Use hash_set instead of pointer_set.


This changelog is less than useful and really does not follow the
GCC/GNU coding style.  Please expand and place all functions which are
changed in it.  I use ChangeLog entries when merging in code to see
which of the merged code I need to pick up.

Thanks,
Andrew Pinski



>
> lto/
>
>         * lto-partition.c, lto-partition.h: Use hash_set instead of
>         pointer_set.
> diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
> index f42ac7f..6961838 100644
> --- a/gcc/ada/gcc-interface/trans.c
> +++ b/gcc/ada/gcc-interface/trans.c
> @@ -36,7 +36,7 @@
>  #include "output.h"
>  #include "libfuncs.h"  /* For set_stack_check_libfunc.  */
>  #include "tree-iterator.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "gimple-expr.h"
>  #include "gimplify.h"
>  #include "bitmap.h"
> @@ -3054,7 +3054,7 @@ struct nrv_data
>    bitmap nrv;
>    tree result;
>    Node_Id gnat_ret;
> -  struct pointer_set_t *visited;
> +  hash_set<tree> *visited;
>  };
>
>  /* Return true if T is a Named Return Value.  */
> @@ -3188,7 +3188,7 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
>    /* Avoid walking into the same tree more than once.  Unfortunately, we
>       can't just use walk_tree_without_duplicates because it would only
>       call us for the first occurrence of NRVs in the function body.  */
> -  if (pointer_set_insert (dp->visited, *tp))
> +  if (dp->visited->add (*tp))
>      *walk_subtrees = 0;
>
>    return NULL_TREE;
> @@ -3328,7 +3328,7 @@ finalize_nrv_unc_r (tree *tp, int *walk_subtrees, void *data)
>    /* Avoid walking into the same tree more than once.  Unfortunately, we
>       can't just use walk_tree_without_duplicates because it would only
>       call us for the first occurrence of NRVs in the function body.  */
> -  if (pointer_set_insert (dp->visited, *tp))
> +  if (dp->visited->add (*tp))
>      *walk_subtrees = 0;
>
>    return NULL_TREE;
> @@ -3376,13 +3376,13 @@ finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret
>    data.nrv = nrv;
>    data.result = DECL_RESULT (fndecl);
>    data.gnat_ret = gnat_ret;
> -  data.visited = pointer_set_create ();
> +  data.visited = new hash_set<tree>;
>    if (TYPE_RETURN_UNCONSTRAINED_P (TREE_TYPE (fndecl)))
>      func = finalize_nrv_unc_r;
>    else
>      func = finalize_nrv_r;
>    walk_tree (&DECL_SAVED_TREE (fndecl), func, &data, NULL);
> -  pointer_set_destroy (data.visited);
> +  delete data.visited;
>  }
>
>  /* Return true if RET_VAL can be used as a Named Return Value for the
> diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
> index 2b5ce5b..4898217 100644
> --- a/gcc/c-family/c-gimplify.c
> +++ b/gcc/c-family/c-gimplify.c
> @@ -74,7 +74,7 @@ along with GCC; see the file COPYING3.  If not see
>  static tree
>  ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
>  {
> -  struct pointer_set_t *pset = (struct pointer_set_t *) data;
> +  hash_set<tree> *pset = (hash_set<tree> *) data;
>
>    /* Since walk_tree doesn't call the callback function on the decls
>       in BIND_EXPR_VARS, we have to walk them manually.  */
> @@ -116,10 +116,9 @@ c_genericize (tree fndecl)
>
>    if (flag_sanitize & SANITIZE_BOUNDS)
>      {
> -      struct pointer_set_t *pset = pointer_set_create ();
> -      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, pset,
> -                pset);
> -      pointer_set_destroy (pset);
> +      hash_set<tree> pset;
> +      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
> +                &pset);
>      }
>
>    /* Dump the C-specific tree IR.  */
> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> index 2a4b439..050ddff 100644
> --- a/gcc/c/c-decl.c
> +++ b/gcc/c/c-decl.c
> @@ -59,7 +59,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "cgraph.h"
>  #include "hash-table.h"
>  #include "langhooks-def.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "plugin.h"
>  #include "c-family/c-ada-spec.h"
>  #include "cilk.h"
> @@ -7221,17 +7221,17 @@ warn_cxx_compat_finish_struct (tree fieldlist)
>    if (!struct_parse_info->typedefs_seen.is_empty ()
>        && fieldlist != NULL_TREE)
>      {
> -      /* Use a pointer_set using the name of the typedef.  We can use
> -        a pointer_set because identifiers are interned.  */
> -      struct pointer_set_t *tset = pointer_set_create ();
> +      /* Use a hash_set<tree> using the name of the typedef.  We can use
> +        a hash_set<tree> because identifiers are interned.  */
> +      hash_set<tree> tset;
>
>        FOR_EACH_VEC_ELT (struct_parse_info->typedefs_seen, ix, x)
> -       pointer_set_insert (tset, DECL_NAME (x));
> +       tset.add (DECL_NAME (x));
>
>        for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
>         {
>           if (DECL_NAME (x) != NULL_TREE
> -             && pointer_set_contains (tset, DECL_NAME (x)))
> +             && tset.contains (DECL_NAME (x)))
>             {
>               warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
>                           ("using %qD as both field and typedef name is "
> @@ -7241,8 +7241,6 @@ warn_cxx_compat_finish_struct (tree fieldlist)
>                  the typedef name is used.  */
>             }
>         }
> -
> -      pointer_set_destroy (tset);
>      }
>
>    /* For each field which has a binding and which was not defined in
> @@ -8189,7 +8187,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>    struct c_binding *b;
>    tree parm, decl, last;
>    tree parmids = arg_info->parms;
> -  struct pointer_set_t *seen_args = pointer_set_create ();
> +  hash_set<tree> seen_args;
>
>    if (!in_system_header_at (input_location))
>      warning_at (DECL_SOURCE_LOCATION (fndecl),
> @@ -8220,7 +8218,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>                       "%qD declared as a non-parameter", decl);
>           /* If the declaration is already marked, we have a duplicate
>              name.  Complain and ignore the duplicate.  */
> -         else if (pointer_set_contains (seen_args, decl))
> +         else if (seen_args.contains (decl))
>             {
>               error_at (DECL_SOURCE_LOCATION (decl),
>                         "multiple parameters named %qD", decl);
> @@ -8269,7 +8267,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>         }
>
>        TREE_PURPOSE (parm) = decl;
> -      pointer_set_insert (seen_args, decl);
> +      seen_args.add (decl);
>      }
>
>    /* Now examine the parms chain for incomplete declarations
> @@ -8289,7 +8287,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>           TREE_TYPE (parm) = error_mark_node;
>         }
>
> -      if (!pointer_set_contains (seen_args, parm))
> +      if (!seen_args.contains (parm))
>         {
>           error_at (DECL_SOURCE_LOCATION (parm),
>                     "declaration for parameter %qD but no such parameter",
> @@ -8324,8 +8322,6 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>        DECL_CHAIN (last) = 0;
>      }
>
> -  pointer_set_destroy (seen_args);
> -
>    /* If there was a previous prototype,
>       set the DECL_ARG_TYPE of each argument according to
>       the type previously specified, and report any mismatches.  */
> diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
> index 2f0ae71..b20be10 100644
> --- a/gcc/cfgexpand.c
> +++ b/gcc/cfgexpand.c
> @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "expr.h"
>  #include "langhooks.h"
>  #include "bitmap.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
> @@ -594,7 +595,7 @@ stack_var_cmp (const void *a, const void *b)
>  static void
>  add_partitioned_vars_to_ptset (struct pt_solution *pt,
>                                struct pointer_map_t *decls_to_partitions,
> -                              struct pointer_set_t *visited, bitmap temp)
> +                              hash_set<bitmap> *visited, bitmap temp)
>  {
>    bitmap_iterator bi;
>    unsigned i;
> @@ -604,7 +605,7 @@ add_partitioned_vars_to_ptset (struct pt_solution *pt,
>        || pt->vars == NULL
>        /* The pointed-to vars bitmap is shared, it is enough to
>          visit it once.  */
> -      || pointer_set_insert (visited, pt->vars))
> +      || visited->add (pt->vars))
>      return;
>
>    bitmap_clear (temp);
> @@ -684,7 +685,7 @@ update_alias_info_with_stack_vars (void)
>    if (decls_to_partitions)
>      {
>        unsigned i;
> -      struct pointer_set_t *visited = pointer_set_create ();
> +      hash_set<bitmap> visited;
>        bitmap temp = BITMAP_ALLOC (&stack_var_bitmap_obstack);
>
>        for (i = 1; i < num_ssa_names; i++)
> @@ -696,13 +697,12 @@ update_alias_info_with_stack_vars (void)
>               && POINTER_TYPE_P (TREE_TYPE (name))
>               && ((pi = SSA_NAME_PTR_INFO (name)) != NULL))
>             add_partitioned_vars_to_ptset (&pi->pt, decls_to_partitions,
> -                                          visited, temp);
> +                                          &visited, temp);
>         }
>
>        add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped,
> -                                    decls_to_partitions, visited, temp);
> +                                    decls_to_partitions, &visited, temp);
>
> -      pointer_set_destroy (visited);
>        pointer_map_destroy (decls_to_partitions);
>        BITMAP_FREE (temp);
>      }
> diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
> index 73f79ef..8f7e265 100644
> --- a/gcc/cfgloop.c
> +++ b/gcc/cfgloop.c
> @@ -28,7 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "diagnostic-core.h"
>  #include "flags.h"
>  #include "tree.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
>  #include "gimple-expr.h"
> @@ -650,11 +650,11 @@ find_subloop_latch_edge (struct loop *loop)
>  /* Callback for make_forwarder_block.  Returns true if the edge E is marked
>     in the set MFB_REIS_SET.  */
>
> -static struct pointer_set_t *mfb_reis_set;
> +static hash_set<edge> *mfb_reis_set;
>  static bool
>  mfb_redirect_edges_in_set (edge e)
>  {
> -  return pointer_set_contains (mfb_reis_set, e);
> +  return mfb_reis_set->contains (e);
>  }
>
>  /* Creates a subloop of LOOP with latch edge LATCH.  */
> @@ -666,15 +666,15 @@ form_subloop (struct loop *loop, edge latch)
>    edge e, new_entry;
>    struct loop *new_loop;
>
> -  mfb_reis_set = pointer_set_create ();
> +  mfb_reis_set = new hash_set<edge>;
>    FOR_EACH_EDGE (e, ei, loop->header->preds)
>      {
>        if (e != latch)
> -       pointer_set_insert (mfb_reis_set, e);
> +       mfb_reis_set->add (e);
>      }
>    new_entry = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
>                                     NULL);
> -  pointer_set_destroy (mfb_reis_set);
> +  delete mfb_reis_set;
>
>    loop->header = new_entry->src;
>
> @@ -705,12 +705,12 @@ merge_latch_edges (struct loop *loop)
>        if (dump_file)
>         fprintf (dump_file, "Merged latch edges of loop %d\n", loop->num);
>
> -      mfb_reis_set = pointer_set_create ();
> +      mfb_reis_set = new hash_set<edge>;
>        FOR_EACH_VEC_ELT (latches, i, e)
> -       pointer_set_insert (mfb_reis_set, e);
> +       mfb_reis_set->add (e);
>        latch = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
>                                     NULL);
> -      pointer_set_destroy (mfb_reis_set);
> +      delete mfb_reis_set;
>
>        loop->header = latch->dest;
>        loop->latch = latch->src;
> diff --git a/gcc/cgraph.c b/gcc/cgraph.c
> index a5d0749..7c72399 100644
> --- a/gcc/cgraph.c
> +++ b/gcc/cgraph.c
> @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-inline.h"
>  #include "langhooks.h"
>  #include "hashtab.h"
> +#include "hash-set.h"
>  #include "toplev.h"
>  #include "flags.h"
>  #include "debug.h"
> @@ -2871,7 +2872,7 @@ cgraph_node::verify_node (void)
>      {
>        if (this_cfun->cfg)
>         {
> -         pointer_set_t *stmts = pointer_set_create ();
> +         hash_set<gimple> stmts;
>           int i;
>           struct ipa_ref *ref = NULL;
>
> @@ -2881,13 +2882,13 @@ cgraph_node::verify_node (void)
>             {
>               for (gsi = gsi_start_phis (this_block);
>                    !gsi_end_p (gsi); gsi_next (&gsi))
> -               pointer_set_insert (stmts, gsi_stmt (gsi));
> +               stmts.add (gsi_stmt (gsi));
>               for (gsi = gsi_start_bb (this_block);
>                    !gsi_end_p (gsi);
>                    gsi_next (&gsi))
>                 {
>                   gimple stmt = gsi_stmt (gsi);
> -                 pointer_set_insert (stmts, stmt);
> +                 stmts.add (stmt);
>                   if (is_gimple_call (stmt))
>                     {
>                       struct cgraph_edge *e = get_edge (stmt);
> @@ -2931,13 +2932,12 @@ cgraph_node::verify_node (void)
>                 }
>               }
>             for (i = 0; iterate_reference (i, ref); i++)
> -             if (ref->stmt && !pointer_set_contains (stmts, ref->stmt))
> +             if (ref->stmt && !stmts.contains (ref->stmt))
>                 {
>                   error ("reference to dead statement");
>                   cgraph_debug_gimple_stmt (this_cfun, ref->stmt);
>                   error_found = true;
>                 }
> -           pointer_set_destroy (stmts);
>         }
>        else
>         /* No CFG available?!  */
> diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
> index 91811d7..a04958f 100644
> --- a/gcc/cgraphbuild.c
> +++ b/gcc/cgraphbuild.c
> @@ -322,7 +322,6 @@ pass_build_cgraph_edges::execute (function *fun)
>  {
>    basic_block bb;
>    struct cgraph_node *node = cgraph_node::get (current_function_decl);
> -  struct pointer_set_t *visited_nodes = pointer_set_create ();
>    gimple_stmt_iterator gsi;
>    tree decl;
>    unsigned ix;
> @@ -386,7 +385,6 @@ pass_build_cgraph_edges::execute (function *fun)
>        varpool_node::finalize_decl (decl);
>    record_eh_tables (node, fun);
>
> -  pointer_set_destroy (visited_nodes);
>    return 0;
>  }
>
> @@ -405,15 +403,14 @@ make_pass_build_cgraph_edges (gcc::context *ctxt)
>  void
>  record_references_in_initializer (tree decl, bool only_vars)
>  {
> -  struct pointer_set_t *visited_nodes = pointer_set_create ();
>    varpool_node *node = varpool_node::get_create (decl);
> +  hash_set<tree> visited_nodes;
>    struct record_reference_ctx ctx = {false, NULL};
>
>    ctx.varpool_node = node;
>    ctx.only_vars = only_vars;
>    walk_tree (&DECL_INITIAL (decl), record_reference,
> -             &ctx, visited_nodes);
> -  pointer_set_destroy (visited_nodes);
> +             &ctx, &visited_nodes);
>  }
>
>  /* Rebuild cgraph edges for current function node.  This needs to be run after
> diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> index 3080b9a..220b953 100644
> --- a/gcc/cgraphunit.c
> +++ b/gcc/cgraphunit.c
> @@ -845,7 +845,7 @@ varpool_node::finalize_decl (tree decl)
>     avoid udplicate work.  */
>
>  static void
> -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
>                                struct cgraph_edge *edge)
>  {
>    unsigned int i;
> @@ -855,8 +855,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
>      = possible_polymorphic_call_targets
>         (edge, &final, &cache_token);
>
> -  if (!pointer_set_insert (reachable_call_targets,
> -                          cache_token))
> +  if (!reachable_call_targets->add (cache_token))
>      {
>        if (cgraph_dump_file)
>         dump_possible_polymorphic_call_targets
> @@ -936,7 +935,7 @@ analyze_functions (void)
>    struct cgraph_node *first_handled = first_analyzed;
>    static varpool_node *first_analyzed_var;
>    varpool_node *first_handled_var = first_analyzed_var;
> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> +  hash_set<void *> reachable_call_targets;
>
>    symtab_node *node;
>    symtab_node *next;
> @@ -1035,7 +1034,7 @@ analyze_functions (void)
>                     {
>                       next = edge->next_callee;
>                       if (edge->indirect_info->polymorphic)
> -                       walk_polymorphic_call_targets (reachable_call_targets,
> +                       walk_polymorphic_call_targets (&reachable_call_targets,
>                                                        edge);
>                     }
>                 }
> @@ -1123,7 +1122,6 @@ analyze_functions (void)
>        symtab_node::dump_table (cgraph_dump_file);
>      }
>    bitmap_obstack_release (NULL);
> -  pointer_set_destroy (reachable_call_targets);
>    ggc_collect ();
>    /* Initialize assembler name hash, in particular we want to trigger C++
>       mangling and same body alias creation before we free DECL_ARGUMENTS
> diff --git a/gcc/cp/class.c b/gcc/cp/class.c
> index 0f611e1..d9b34f7 100644
> --- a/gcc/cp/class.c
> +++ b/gcc/cp/class.c
> @@ -5359,15 +5359,15 @@ finalize_literal_type_property (tree t)
>  void
>  explain_non_literal_class (tree t)
>  {
> -  static struct pointer_set_t *diagnosed;
> +  static hash_set<tree> *diagnosed;
>
>    if (!CLASS_TYPE_P (t))
>      return;
>    t = TYPE_MAIN_VARIANT (t);
>
>    if (diagnosed == NULL)
> -    diagnosed = pointer_set_create ();
> -  if (pointer_set_insert (diagnosed, t) != 0)
> +    diagnosed = new hash_set<tree>;
> +  if (diagnosed->add (t))
>      /* Already explained.  */
>      return;
>
> diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
> index a35177b..3cfcbc6 100644
> --- a/gcc/cp/cp-gimplify.c
> +++ b/gcc/cp/cp-gimplify.c
> @@ -871,7 +871,7 @@ omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
>
>  struct cp_genericize_data
>  {
> -  struct pointer_set_t *p_set;
> +  hash_set<tree> *p_set;
>    vec<tree> bind_expr_stack;
>    struct cp_genericize_omp_taskreg *omp_ctx;
>  };
> @@ -884,7 +884,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
>  {
>    tree stmt = *stmt_p;
>    struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
> -  struct pointer_set_t *p_set = wtd->p_set;
> +  hash_set<tree> *p_set = wtd->p_set;
>
>    /* If in an OpenMP context, note var uses.  */
>    if (__builtin_expect (wtd->omp_ctx != NULL, 0)
> @@ -924,7 +924,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
>      }
>
>    /* Other than invisiref parms, don't walk the same tree twice.  */
> -  if (pointer_set_contains (p_set, stmt))
> +  if (p_set->contains (stmt))
>      {
>        *walk_subtrees = 0;
>        return NULL_TREE;
> @@ -1199,7 +1199,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
>        return NULL;
>      }
>
> -  pointer_set_insert (p_set, *stmt_p);
> +  p_set->add (*stmt_p);
>
>    return NULL;
>  }
> @@ -1211,11 +1211,11 @@ cp_genericize_tree (tree* t_p)
>  {
>    struct cp_genericize_data wtd;
>
> -  wtd.p_set = pointer_set_create ();
> +  wtd.p_set = new hash_set<tree>;
>    wtd.bind_expr_stack.create (0);
>    wtd.omp_ctx = NULL;
>    cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
> -  pointer_set_destroy (wtd.p_set);
> +  delete wtd.p_set;
>    wtd.bind_expr_stack.release ();
>  }
>
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 0c0d804..622de9c 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -6028,7 +6028,7 @@ extern void verify_stmt_tree                      (tree);
>  extern linkage_kind decl_linkage               (tree);
>  extern duration_kind decl_storage_duration     (tree);
>  extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
> -                             void*, struct pointer_set_t*);
> +                             void*, hash_set<tree> *);
>  #define cp_walk_tree(tp,func,data,pset) \
>         walk_tree_1 (tp, func, data, pset, cp_walk_subtrees)
>  #define cp_walk_tree_without_duplicates(tp,func,data) \
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index aafb917..f70684f 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -8198,7 +8198,7 @@ check_static_variable_definition (tree decl, tree type)
>  static tree
>  stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
>  {
> -  struct pointer_set_t *pset = (struct pointer_set_t *)data;
> +  hash_set<tree> *pset = (hash_set<tree> *)data;
>    tree expr = *expr_p;
>    if (TREE_CODE (expr) == SAVE_EXPR)
>      {
> @@ -8218,10 +8218,9 @@ stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
>  static void
>  stabilize_vla_size (tree size)
>  {
> -  struct pointer_set_t *pset = pointer_set_create ();
> +  hash_set<tree> pset;
>    /* Break out any function calls into temporary variables.  */
> -  cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
> -  pointer_set_destroy (pset);
> +  cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
>  }
>
>  /* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
> diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
> index 8fa3145..d79665e 100644
> --- a/gcc/cp/decl2.c
> +++ b/gcc/cp/decl2.c
> @@ -3938,11 +3938,11 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
>     supported, collect and return all the functions for which we should
>     emit a hidden alias.  */
>
> -static struct pointer_set_t *
> +static hash_set<tree> *
>  collect_candidates_for_java_method_aliases (void)
>  {
>    struct cgraph_node *node;
> -  struct pointer_set_t *candidates = NULL;
> +  hash_set<tree> *candidates = NULL;
>
>  #ifndef HAVE_GAS_HIDDEN
>    return candidates;
> @@ -3957,8 +3957,8 @@ collect_candidates_for_java_method_aliases (void)
>           && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
>         {
>           if (candidates == NULL)
> -           candidates = pointer_set_create ();
> -         pointer_set_insert (candidates, fndecl);
> +           candidates = new hash_set<tree>;
> +         candidates->add (fndecl);
>         }
>      }
>
> @@ -3973,7 +3973,7 @@ collect_candidates_for_java_method_aliases (void)
>     by collect_candidates_for_java_method_aliases.  */
>
>  static void
> -build_java_method_aliases (struct pointer_set_t *candidates)
> +build_java_method_aliases (hash_set<tree> *candidates)
>  {
>    struct cgraph_node *node;
>
> @@ -3986,7 +3986,7 @@ build_java_method_aliases (struct pointer_set_t *candidates)
>        tree fndecl = node->decl;
>
>        if (TREE_ASM_WRITTEN (fndecl)
> -         && pointer_set_contains (candidates, fndecl))
> +         && candidates->contains (fndecl))
>         {
>           /* Mangle the name in a predictable way; we need to reference
>              this from a java compiled object file.  */
> @@ -4296,7 +4296,7 @@ cp_write_global_declarations (void)
>    unsigned ssdf_count = 0;
>    int retries = 0;
>    tree decl;
> -  struct pointer_set_t *candidates;
> +  hash_set<tree> *candidates;
>
>    locus = input_location;
>    at_eof = 1;
> @@ -4713,7 +4713,7 @@ cp_write_global_declarations (void)
>    if (candidates)
>      {
>        build_java_method_aliases (candidates);
> -      pointer_set_destroy (candidates);
> +      delete candidates;
>      }
>
>    finish_repo ();
> diff --git a/gcc/cp/error.c b/gcc/cp/error.c
> index fa3bdc4..c8987ee 100644
> --- a/gcc/cp/error.c
> +++ b/gcc/cp/error.c
> @@ -1325,7 +1325,7 @@ dump_template_decl (cxx_pretty_printer *pp, tree t, int flags)
>
>  struct find_typenames_t
>  {
> -  struct pointer_set_t *p_set;
> +  hash_set<tree> *p_set;
>    vec<tree, va_gc> *typenames;
>  };
>
> @@ -1351,7 +1351,7 @@ find_typenames_r (tree *tp, int *walk_subtrees, void *data)
>        return NULL_TREE;
>      }
>
> -  if (mv && (mv == *tp || !pointer_set_insert (d->p_set, mv)))
> +  if (mv && (mv == *tp || !d->p_set->add (mv)))
>      vec_safe_push (d->typenames, mv);
>
>    /* Search into class template arguments, which cp_walk_subtrees
> @@ -1367,11 +1367,11 @@ static vec<tree, va_gc> *
>  find_typenames (tree t)
>  {
>    struct find_typenames_t ft;
> -  ft.p_set = pointer_set_create ();
> +  ft.p_set = new hash_set<tree>;
>    ft.typenames = NULL;
>    cp_walk_tree (&TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
>                 find_typenames_r, &ft, ft.p_set);
> -  pointer_set_destroy (ft.p_set);
> +  delete ft.p_set;
>    return ft.typenames;
>  }
>
> diff --git a/gcc/cp/method.c b/gcc/cp/method.c
> index e5fa0c1..65c5621 100644
> --- a/gcc/cp/method.c
> +++ b/gcc/cp/method.c
> @@ -1480,7 +1480,7 @@ maybe_explain_implicit_delete (tree decl)
>    if (DECL_DEFAULTED_FN (decl))
>      {
>        /* Not marked GTY; it doesn't need to be GC'd or written to PCH.  */
> -      static struct pointer_set_t *explained;
> +      static hash_set<tree> *explained;
>
>        special_function_kind sfk;
>        location_t loc;
> @@ -1488,8 +1488,8 @@ maybe_explain_implicit_delete (tree decl)
>        tree ctype;
>
>        if (!explained)
> -       explained = pointer_set_create ();
> -      if (pointer_set_insert (explained, decl))
> +       explained = new hash_set<tree>;
> +      if (explained->add (decl))
>         return true;
>
>        sfk = special_function_p (decl);
> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> index 75b46ac..6e779a6 100644
> --- a/gcc/cp/name-lookup.c
> +++ b/gcc/cp/name-lookup.c
> @@ -35,7 +35,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "debug.h"
>  #include "c-family/c-pragma.h"
>  #include "params.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>
>  /* The bindings for a particular name in a particular scope.  */
>
> @@ -5152,7 +5152,7 @@ struct arg_lookup
>    vec<tree, va_gc> *namespaces;
>    vec<tree, va_gc> *classes;
>    tree functions;
> -  struct pointer_set_t *fn_set;
> +  hash_set<tree> *fn_set;
>  };
>
>  static bool arg_assoc (struct arg_lookup*, tree);
> @@ -5175,7 +5175,7 @@ add_function (struct arg_lookup *k, tree fn)
>    if (!is_overloaded_fn (fn))
>      /* All names except those of (possibly overloaded) functions and
>         function templates are ignored.  */;
> -  else if (k->fn_set && pointer_set_insert (k->fn_set, fn))
> +  else if (k->fn_set && k->fn_set->add (fn))
>      /* It's already in the list.  */;
>    else if (!k->functions)
>      k->functions = fn;
> @@ -5639,9 +5639,9 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
>        /* We shouldn't be here if lookup found something other than
>          namespace-scope functions.  */
>        gcc_assert (DECL_NAMESPACE_SCOPE_P (OVL_CURRENT (fns)));
> -      k.fn_set = pointer_set_create ();
> +      k.fn_set = new hash_set<tree>;
>        for (ovl = fns; ovl; ovl = OVL_NEXT (ovl))
> -       pointer_set_insert (k.fn_set, OVL_CURRENT (ovl));
> +       k.fn_set->add (OVL_CURRENT (ovl));
>      }
>    else
>      k.fn_set = NULL;
> @@ -5661,8 +5661,7 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
>
>    release_tree_vector (k.classes);
>    release_tree_vector (k.namespaces);
> -  if (k.fn_set)
> -    pointer_set_destroy (k.fn_set);
> +  delete k.fn_set;
>
>    return fns;
>  }
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index b32cf6c..9b156f5 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -147,7 +147,7 @@ static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
>  static tree convert_template_argument (tree, tree, tree,
>                                        tsubst_flags_t, int, tree);
>  static int for_each_template_parm (tree, tree_fn_t, void*,
> -                                  struct pointer_set_t*, bool);
> +                                  hash_set<tree> *, bool);
>  static tree expand_template_argument_pack (tree);
>  static tree build_template_parm_index (int, int, int, tree, tree);
>  static bool inline_needs_template_parms (tree, bool);
> @@ -3080,7 +3080,7 @@ struct find_parameter_pack_data
>    tree* parameter_packs;
>
>    /* Set of AST nodes that have been visited by the traversal.  */
> -  struct pointer_set_t *visited;
> +  hash_set<tree> *visited;
>  };
>
>  /* Identifies all of the argument packs that occur in a template
> @@ -3243,9 +3243,9 @@ uses_parameter_packs (tree t)
>    tree parameter_packs = NULL_TREE;
>    struct find_parameter_pack_data ppd;
>    ppd.parameter_packs = &parameter_packs;
> -  ppd.visited = pointer_set_create ();
> +  ppd.visited = new hash_set<tree>;
>    cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
> -  pointer_set_destroy (ppd.visited);
> +  delete ppd.visited;
>    return parameter_packs != NULL_TREE;
>  }
>
> @@ -3292,7 +3292,7 @@ make_pack_expansion (tree arg)
>
>        /* Determine which parameter packs will be used by the base
>           class expansion.  */
> -      ppd.visited = pointer_set_create ();
> +      ppd.visited = new hash_set<tree>;
>        ppd.parameter_packs = &parameter_packs;
>        cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
>                      &ppd, ppd.visited);
> @@ -3300,7 +3300,7 @@ make_pack_expansion (tree arg)
>        if (parameter_packs == NULL_TREE)
>          {
>            error ("base initializer expansion %<%T%> contains no parameter packs", arg);
> -          pointer_set_destroy (ppd.visited);
> +          delete ppd.visited;
>            return error_mark_node;
>          }
>
> @@ -3317,7 +3317,7 @@ make_pack_expansion (tree arg)
>              }
>          }
>
> -      pointer_set_destroy (ppd.visited);
> +      delete ppd.visited;
>
>        /* Create the pack expansion type for the base type.  */
>        purpose = cxx_make_type (TYPE_PACK_EXPANSION);
> @@ -3352,9 +3352,9 @@ make_pack_expansion (tree arg)
>
>    /* Determine which parameter packs will be expanded.  */
>    ppd.parameter_packs = &parameter_packs;
> -  ppd.visited = pointer_set_create ();
> +  ppd.visited = new hash_set<tree>;
>    cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
> -  pointer_set_destroy (ppd.visited);
> +  delete ppd.visited;
>
>    /* Make sure we found some parameter packs.  */
>    if (parameter_packs == NULL_TREE)
> @@ -3399,9 +3399,9 @@ check_for_bare_parameter_packs (tree t)
>      t = TREE_TYPE (t);
>
>    ppd.parameter_packs = &parameter_packs;
> -  ppd.visited = pointer_set_create ();
> +  ppd.visited = new hash_set<tree>;
>    cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
> -  pointer_set_destroy (ppd.visited);
> +  delete ppd.visited;
>
>    if (parameter_packs)
>      {
> @@ -4381,11 +4381,11 @@ fixed_parameter_pack_p (tree parm)
>    tree parameter_packs = NULL_TREE;
>    struct find_parameter_pack_data ppd;
>    ppd.parameter_packs = &parameter_packs;
> -  ppd.visited = pointer_set_create ();
> +  ppd.visited = new hash_set<tree>;
>
>    fixed_parameter_pack_p_1 (parm, &ppd);
>
> -  pointer_set_destroy (ppd.visited);
> +  delete ppd.visited;
>    return parameter_packs;
>  }
>
> @@ -7907,7 +7907,7 @@ struct pair_fn_data
>    /* True when we should also visit template parameters that occur in
>       non-deduced contexts.  */
>    bool include_nondeduced_p;
> -  struct pointer_set_t *visited;
> +  hash_set<tree> *visited;
>  };
>
>  /* Called from for_each_template_parm via walk_tree.  */
> @@ -8107,7 +8107,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
>
>  static int
>  for_each_template_parm (tree t, tree_fn_t fn, void* data,
> -                       struct pointer_set_t *visited,
> +                       hash_set<tree> *visited,
>                         bool include_nondeduced_p)
>  {
>    struct pair_fn_data pfd;
> @@ -8126,7 +8126,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
>    if (visited)
>      pfd.visited = visited;
>    else
> -    pfd.visited = pointer_set_create ();
> +    pfd.visited = new hash_set<tree>;
>    result = cp_walk_tree (&t,
>                          for_each_template_parm_r,
>                          &pfd,
> @@ -8135,7 +8135,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
>    /* Clean up.  */
>    if (!visited)
>      {
> -      pointer_set_destroy (pfd.visited);
> +      delete pfd.visited;
>        pfd.visited = 0;
>      }
>
> diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
> index c87764d..735284e 100644
> --- a/gcc/cp/semantics.c
> +++ b/gcc/cp/semantics.c
> @@ -8031,7 +8031,7 @@ register_constexpr_fundef (tree fun, tree body)
>  void
>  explain_invalid_constexpr_fn (tree fun)
>  {
> -  static struct pointer_set_t *diagnosed;
> +  static hash_set<tree> *diagnosed;
>    tree body;
>    location_t save_loc;
>    /* Only diagnose defaulted functions or instantiations.  */
> @@ -8039,8 +8039,8 @@ explain_invalid_constexpr_fn (tree fun)
>        && !is_instantiation_of_constexpr (fun))
>      return;
>    if (diagnosed == NULL)
> -    diagnosed = pointer_set_create ();
> -  if (pointer_set_insert (diagnosed, fun) != 0)
> +    diagnosed = new hash_set<tree>;
> +  if (diagnosed->add (fun))
>      /* Already explained.  */
>      return;
>
> diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
> index f6c5693..697a02b 100644
> --- a/gcc/cp/tree.c
> +++ b/gcc/cp/tree.c
> @@ -3485,7 +3485,7 @@ cxx_type_hash_eq (const_tree typea, const_tree typeb)
>
>  tree
>  cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
> -                 void *data, struct pointer_set_t *pset)
> +                 void *data, hash_set<tree> *pset)
>  {
>    enum tree_code code = TREE_CODE (*tp);
>    tree result;
> diff --git a/gcc/cprop.c b/gcc/cprop.c
> index 6291c91..4234afa 100644
> --- a/gcc/cprop.c
> +++ b/gcc/cprop.c
> @@ -167,7 +167,7 @@ reg_available_p (const_rtx x, const_rtx insn ATTRIBUTE_UNUSED)
>     ??? May need to make things more elaborate.  Later, as necessary.  */
>
>  static unsigned int
> -hash_set (int regno, int hash_table_size)
> +hash_mod (int regno, int hash_table_size)
>  {
>    return (unsigned) regno % hash_table_size;
>  }
> @@ -187,7 +187,7 @@ insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table,
>    struct expr *cur_expr, *last_expr = NULL;
>    struct occr *cur_occr;
>
> -  hash = hash_set (REGNO (dest), table->size);
> +  hash = hash_mod (REGNO (dest), table->size);
>
>    for (cur_expr = table->table[hash]; cur_expr;
>         cur_expr = cur_expr->next_same_hash)
> @@ -483,7 +483,7 @@ compute_hash_table (struct hash_table_d *table)
>  static struct expr *
>  lookup_set (unsigned int regno, struct hash_table_d *table)
>  {
> -  unsigned int hash = hash_set (regno, table->size);
> +  unsigned int hash = hash_mod (regno, table->size);
>    struct expr *expr;
>
>    expr = table->table[hash];
> diff --git a/gcc/cse.c b/gcc/cse.c
> index 34f9364..dd9a076 100644
> --- a/gcc/cse.c
> +++ b/gcc/cse.c
> @@ -41,7 +41,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-pass.h"
>  #include "df.h"
>  #include "dbgcnt.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>
>  /* The basic idea of common subexpression elimination is to go
>     through the code, keeping a record of expressions that would
> @@ -2906,7 +2906,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>                       enum machine_mode *pmode1, enum machine_mode *pmode2)
>  {
>    rtx arg1, arg2;
> -  struct pointer_set_t *visited = NULL;
> +  hash_set<rtx> *visited = NULL;
>    /* Set nonzero when we find something of interest.  */
>    rtx x = NULL;
>
> @@ -2923,8 +2923,8 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>        if (x)
>         {
>           if (!visited)
> -           visited = pointer_set_create ();
> -         pointer_set_insert (visited, x);
> +           visited = new hash_set<rtx>;
> +         visited->add (x);
>           x = 0;
>         }
>
> @@ -3005,7 +3005,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>             continue;
>
>           /* If it's a comparison we've used before, skip it.  */
> -         if (visited && pointer_set_contains (visited, p->exp))
> +         if (visited && visited->contains (p->exp))
>             continue;
>
>           if (GET_CODE (p->exp) == COMPARE
> @@ -3087,7 +3087,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>    *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0);
>
>    if (visited)
> -    pointer_set_destroy (visited);
> +    delete visited;
>    return code;
>  }
>
> diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
> index 68ba70f..410efb1 100644
> --- a/gcc/fortran/openmp.c
> +++ b/gcc/fortran/openmp.c
> @@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "arith.h"
>  #include "match.h"
>  #include "parse.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>
>  /* Match an end of OpenMP directive.  End of OpenMP directive is optional
>     whitespace, followed by '\n' or comment '!'.  */
> @@ -3013,8 +3013,8 @@ resolve_omp_atomic (gfc_code *code)
>  struct omp_context
>  {
>    gfc_code *code;
> -  struct pointer_set_t *sharing_clauses;
> -  struct pointer_set_t *private_iterators;
> +  hash_set<gfc_symbol *> *sharing_clauses;
> +  hash_set<gfc_symbol *> *private_iterators;
>    struct omp_context *previous;
>  } *omp_current_ctx;
>  static gfc_code *omp_current_do_code;
> @@ -3057,8 +3057,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
>    int list;
>
>    ctx.code = code;
> -  ctx.sharing_clauses = pointer_set_create ();
> -  ctx.private_iterators = pointer_set_create ();
> +  ctx.sharing_clauses = new hash_set<gfc_symbol *>;
> +  ctx.private_iterators = new hash_set<gfc_symbol *>;
>    ctx.previous = omp_current_ctx;
>    omp_current_ctx = &ctx;
>
> @@ -3072,7 +3072,7 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
>        case OMP_LIST_REDUCTION:
>        case OMP_LIST_LINEAR:
>         for (n = omp_clauses->lists[list]; n; n = n->next)
> -         pointer_set_insert (ctx.sharing_clauses, n->sym);
> +         ctx.sharing_clauses->add (n->sym);
>         break;
>        default:
>         break;
> @@ -3097,8 +3097,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
>      }
>
>    omp_current_ctx = ctx.previous;
> -  pointer_set_destroy (ctx.sharing_clauses);
> -  pointer_set_destroy (ctx.private_iterators);
> +  delete ctx.sharing_clauses;
> +  delete ctx.private_iterators;
>  }
>
>
> @@ -3154,10 +3154,10 @@ gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym)
>    if (omp_current_ctx == NULL)
>      return;
>
> -  if (pointer_set_contains (omp_current_ctx->sharing_clauses, sym))
> +  if (omp_current_ctx->sharing_clauses->contains (sym))
>      return;
>
> -  if (! pointer_set_insert (omp_current_ctx->private_iterators, sym))
> +  if (! omp_current_ctx->private_iterators->add (sym))
>      {
>        gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
>        gfc_omp_namelist *p;
> diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
> index 8b56151..babe48f 100644
> --- a/gcc/fortran/trans-decl.c
> +++ b/gcc/fortran/trans-decl.c
> @@ -40,7 +40,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "cgraph.h"
>  #include "debug.h"
>  #include "gfortran.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "constructor.h"
>  #include "trans.h"
>  #include "trans-types.h"
> @@ -63,7 +63,7 @@ static GTY(()) tree parent_fake_result_decl;
>  static GTY(()) tree saved_function_decls;
>  static GTY(()) tree saved_parent_function_decls;
>
> -static struct pointer_set_t *nonlocal_dummy_decl_pset;
> +static hash_set<tree> *nonlocal_dummy_decl_pset;
>  static GTY(()) tree nonlocal_dummy_decls;
>
>  /* Holds the variable DECLs that are locals.  */
> @@ -1094,9 +1094,9 @@ gfc_nonlocal_dummy_array_decl (gfc_symbol *sym)
>    tree decl, dummy;
>
>    if (! nonlocal_dummy_decl_pset)
> -    nonlocal_dummy_decl_pset = pointer_set_create ();
> +    nonlocal_dummy_decl_pset = new hash_set<tree>;
>
> -  if (pointer_set_insert (nonlocal_dummy_decl_pset, sym->backend_decl))
> +  if (nonlocal_dummy_decl_pset->add (sym->backend_decl))
>      return;
>
>    dummy = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl);
> @@ -5861,7 +5861,7 @@ gfc_generate_function_code (gfc_namespace * ns)
>      {
>        BLOCK_VARS (DECL_INITIAL (fndecl))
>         = chainon (BLOCK_VARS (DECL_INITIAL (fndecl)), nonlocal_dummy_decls);
> -      pointer_set_destroy (nonlocal_dummy_decl_pset);
> +      delete nonlocal_dummy_decl_pset;
>        nonlocal_dummy_decls = NULL;
>        nonlocal_dummy_decl_pset = NULL;
>      }
> diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
> index b6f0495..f4f6757 100644
> --- a/gcc/gimple-walk.c
> +++ b/gcc/gimple-walk.c
> @@ -180,7 +180,7 @@ tree
>  walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
>                 struct walk_stmt_info *wi)
>  {
> -  struct pointer_set_t *pset = (wi) ? wi->pset : NULL;
> +  hash_set<tree> *pset = (wi) ? wi->pset : NULL;
>    unsigned i;
>    tree ret = NULL_TREE;
>
> diff --git a/gcc/gimple-walk.h b/gcc/gimple-walk.h
> index 555eb18..5b75fdc 100644
> --- a/gcc/gimple-walk.h
> +++ b/gcc/gimple-walk.h
> @@ -36,7 +36,7 @@ struct walk_stmt_info
>    /* Pointer map used to mark visited tree nodes when calling
>       walk_tree on each operand.  If set to NULL, duplicate tree nodes
>       will be visited more than once.  */
> -  struct pointer_set_t *pset;
> +  hash_set<tree> *pset;
>
>    /* Operand returned by the callbacks.  This is set when calling
>       walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> index 4ab36d0..c0ae7cc 100644
> --- a/gcc/gimplify.c
> +++ b/gcc/gimplify.c
> @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "coretypes.h"
>  #include "tree.h"
>  #include "expr.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "hash-table.h"
>  #include "basic-block.h"
> @@ -134,7 +135,7 @@ struct gimplify_omp_ctx
>  {
>    struct gimplify_omp_ctx *outer_context;
>    splay_tree variables;
> -  struct pointer_set_t *privatized_types;
> +  hash_set<tree> *privatized_types;
>    location_t location;
>    enum omp_clause_default_kind default_kind;
>    enum omp_region_type region_type;
> @@ -352,7 +353,7 @@ new_omp_context (enum omp_region_type region_type)
>    c = XCNEW (struct gimplify_omp_ctx);
>    c->outer_context = gimplify_omp_ctxp;
>    c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
> -  c->privatized_types = pointer_set_create ();
> +  c->privatized_types = new hash_set<tree>;
>    c->location = input_location;
>    c->region_type = region_type;
>    if ((region_type & ORT_TASK) == 0)
> @@ -369,7 +370,7 @@ static void
>  delete_omp_context (struct gimplify_omp_ctx *c)
>  {
>    splay_tree_delete (c->variables);
> -  pointer_set_destroy (c->privatized_types);
> +  delete c->privatized_types;
>    XDELETE (c);
>  }
>
> @@ -744,7 +745,7 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
>       copy their subtrees if we can make sure to do it only once.  */
>    if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
>      {
> -      if (data && !pointer_set_insert ((struct pointer_set_t *)data, t))
> +      if (data && !((hash_set<tree> *)data)->add (t))
>         ;
>        else
>         *walk_subtrees = 0;
> @@ -829,15 +830,14 @@ unshare_body (tree fndecl)
>    struct cgraph_node *cgn = cgraph_node::get (fndecl);
>    /* If the language requires deep unsharing, we need a pointer set to make
>       sure we don't repeatedly unshare subtrees of unshareable nodes.  */
> -  struct pointer_set_t *visited
> -    = lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
> +  hash_set<tree> *visited
> +    = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
>
>    copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
>    copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
>    copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
>
> -  if (visited)
> -    pointer_set_destroy (visited);
> +  delete visited;
>
>    if (cgn)
>      for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
> @@ -1733,7 +1733,7 @@ gimplify_conversion (tree *expr_p)
>  }
>
>  /* Nonlocal VLAs seen in the current function.  */
> -static struct pointer_set_t *nonlocal_vlas;
> +static hash_set<tree> *nonlocal_vlas;
>
>  /* The VAR_DECLs created for nonlocal VLAs for debug info purposes.  */
>  static tree nonlocal_vla_vars;
> @@ -1784,7 +1784,7 @@ gimplify_var_or_parm_decl (tree *expr_p)
>                  && (ctx->region_type == ORT_WORKSHARE
>                      || ctx->region_type == ORT_SIMD))
>             ctx = ctx->outer_context;
> -         if (!ctx && !pointer_set_insert (nonlocal_vlas, decl))
> +         if (!ctx && !nonlocal_vlas->add (decl))
>             {
>               tree copy = copy_node (decl);
>
> @@ -5463,7 +5463,7 @@ omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
>      return;
>    type = TYPE_MAIN_VARIANT (type);
>
> -  if (pointer_set_insert (ctx->privatized_types, type))
> +  if (ctx->privatized_types->add (type))
>      return;
>
>    switch (TREE_CODE (type))
> @@ -8766,7 +8766,7 @@ gimplify_body (tree fndecl, bool do_parms)
>
>    cgn = cgraph_node::get (fndecl);
>    if (cgn && cgn->origin)
> -    nonlocal_vlas = pointer_set_create ();
> +    nonlocal_vlas = new hash_set<tree>;
>
>    /* Make sure input_location isn't set to something weird.  */
>    input_location = DECL_SOURCE_LOCATION (fndecl);
> @@ -8830,7 +8830,7 @@ gimplify_body (tree fndecl, bool do_parms)
>                          nonlocal_vla_vars);
>           nonlocal_vla_vars = NULL_TREE;
>         }
> -      pointer_set_destroy (nonlocal_vlas);
> +      delete nonlocal_vlas;
>        nonlocal_vlas = NULL;
>      }
>
> diff --git a/gcc/godump.c b/gcc/godump.c
> index 2afd7f1..7566f4d 100644
> --- a/gcc/godump.c
> +++ b/gcc/godump.c
> @@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "diagnostic-core.h"
>  #include "tree.h"
>  #include "ggc.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "obstack.h"
>  #include "debug.h"
>  #include "wide-int-print.h"
> @@ -525,11 +525,11 @@ go_type_decl (tree decl, int local)
>  struct godump_container
>  {
>    /* DECLs that we have already seen.  */
> -  struct pointer_set_t *decls_seen;
> +  hash_set<tree> decls_seen;
>
>    /* Types which may potentially have to be defined as dummy
>       types.  */
> -  struct pointer_set_t *pot_dummy_types;
> +  hash_set<const char *> pot_dummy_types;
>
>    /* Go keywords.  */
>    htab_t keyword_hash;
> @@ -569,8 +569,8 @@ go_format_type (struct godump_container *container, tree type,
>    ob = &container->type_obstack;
>
>    if (TYPE_NAME (type) != NULL_TREE
> -      && (pointer_set_contains (container->decls_seen, type)
> -         || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
> +      && (container->decls_seen.contains (type)
> +         || container->decls_seen.contains (TYPE_NAME (type)))
>        && (AGGREGATE_TYPE_P (type)
>           || POINTER_TYPE_P (type)
>           || TREE_CODE (type) == FUNCTION_TYPE))
> @@ -590,7 +590,7 @@ go_format_type (struct godump_container *container, tree type,
>        return ret;
>      }
>
> -  pointer_set_insert (container->decls_seen, type);
> +  container->decls_seen.add (type);
>
>    switch (TREE_CODE (type))
>      {
> @@ -697,8 +697,7 @@ go_format_type (struct godump_container *container, tree type,
>              definition.  So this struct or union is a potential dummy
>              type.  */
>           if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
> -           pointer_set_insert (container->pot_dummy_types,
> -                               IDENTIFIER_POINTER (name));
> +           container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
>
>           return ret;
>          }
> @@ -948,10 +947,10 @@ go_output_typedef (struct godump_container *container, tree decl)
>       separately.  */
>    if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
>        && TYPE_SIZE (TREE_TYPE (decl)) != 0
> -      && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
> +      && !container->decls_seen.contains (TREE_TYPE (decl))
>        && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
> -         || !pointer_set_contains (container->decls_seen,
> -                                   TYPE_CANONICAL (TREE_TYPE (decl)))))
> +         || !container->decls_seen.contains
> +                                   (TYPE_CANONICAL (TREE_TYPE (decl)))))
>      {
>        tree element;
>
> @@ -988,10 +987,9 @@ go_output_typedef (struct godump_container *container, tree decl)
>           mhval->value = xstrdup (buf);
>           *slot = mhval;
>         }
> -      pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
> +      container->decls_seen.add (TREE_TYPE (decl));
>        if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
> -       pointer_set_insert (container->decls_seen,
> -                           TYPE_CANONICAL (TREE_TYPE (decl)));
> +       container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
>      }
>
>    if (DECL_NAME (decl) != NULL_TREE)
> @@ -1027,7 +1025,7 @@ go_output_typedef (struct godump_container *container, tree decl)
>                      size);
>         }
>
> -      pointer_set_insert (container->decls_seen, decl);
> +      container->decls_seen.add (decl);
>      }
>    else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
>      {
> @@ -1072,11 +1070,11 @@ go_output_var (struct godump_container *container, tree decl)
>  {
>    bool is_valid;
>
> -  if (pointer_set_contains (container->decls_seen, decl)
> -      || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
> +  if (container->decls_seen.contains (decl)
> +      || container->decls_seen.contains (DECL_NAME (decl)))
>      return;
> -  pointer_set_insert (container->decls_seen, decl);
> -  pointer_set_insert (container->decls_seen, DECL_NAME (decl));
> +  container->decls_seen.add (decl);
> +  container->decls_seen.add (DECL_NAME (decl));
>
>    is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
>    if (is_valid
> @@ -1103,11 +1101,10 @@ go_output_var (struct godump_container *container, tree decl)
>      {
>        tree type_name = TYPE_NAME (TREE_TYPE (decl));
>        if (TREE_CODE (type_name) == IDENTIFIER_NODE)
> -       pointer_set_insert (container->pot_dummy_types,
> -                           IDENTIFIER_POINTER (type_name));
> +       container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
>        else if (TREE_CODE (type_name) == TYPE_DECL)
> -       pointer_set_insert (container->pot_dummy_types,
> -                           IDENTIFIER_POINTER (DECL_NAME (type_name)));
> +       container->pot_dummy_types.add
> +                           (IDENTIFIER_POINTER (DECL_NAME (type_name)));
>      }
>  }
>
> @@ -1147,10 +1144,10 @@ keyword_hash_init (struct godump_container *container)
>
>  /* Traversing the pot_dummy_types and seeing which types are present
>     in the global types hash table and creating dummy definitions if
> -   not found.  This function is invoked by pointer_set_traverse.  */
> +   not found.  This function is invoked by hash_set::traverse.  */
>
> -static bool
> -find_dummy_types (const void *ptr, void *adata)
> +bool
> +find_dummy_types (const char *const &ptr, godump_container *adata)
>  {
>    struct godump_container *data = (struct godump_container *) adata;
>    const char *type = (const char *) ptr;
> @@ -1175,8 +1172,6 @@ go_finish (const char *filename)
>
>    real_debug_hooks->finish (filename);
>
> -  container.decls_seen = pointer_set_create ();
> -  container.pot_dummy_types = pointer_set_create ();
>    container.type_hash = htab_create (100, htab_hash_string,
>                                       string_hash_eq, NULL);
>    container.invalid_hash = htab_create (10, htab_hash_string,
> @@ -1211,11 +1206,9 @@ go_finish (const char *filename)
>    htab_traverse_noresize (macro_hash, go_print_macro, NULL);
>
>    /* To emit dummy definitions.  */
> -  pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
> -                        (void *) &container);
> +  container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
> +                        (&container);
>
> -  pointer_set_destroy (container.decls_seen);
> -  pointer_set_destroy (container.pot_dummy_types);
>    htab_delete (container.type_hash);
>    htab_delete (container.invalid_hash);
>    htab_delete (container.keyword_hash);
> diff --git a/gcc/hash-set.h b/gcc/hash-set.h
> new file mode 100644
> index 0000000..47bae9e
> --- /dev/null
> +++ b/gcc/hash-set.h
> @@ -0,0 +1,173 @@
> +/* A type-safe hash set.
> +   Copyright (C) 2014 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +
> +#ifndef hash_set_h
> +#define hash_set_h
> +
> +#include "hash-table.h"
> +
> +/* implement default behavior for traits when types allow it.  */
> +
> +struct default_hashset_traits
> +{
> +  /* Hashes the passed in key.  */
> +
> +  template<typename T>
> +  static hashval_t
> +  hash (T *p)
> +    {
> +      return uintptr_t(p) >> 3;
> +    }
> +
> +  template<typename T> static hashval_t hash(const T &v) { return v; }
> +
> +  /* Return true if the two keys passed as arguments are equal.  */
> +
> +  template<typename T>
> +  static bool
> +  equal (const T &a, const T &b)
> +    {
> +      return a == b;
> +    }
> +
> +  /* Called to dispose of the key before marking the entry as deleted.  */
> +
> +  template<typename T> static void remove (T &v) { v.~T (); }
> +
> +  /* Mark the passed in entry as being deleted.  */
> +
> +  template<typename T>
> +  static void
> +  mark_deleted (T *&e)
> +    {
> +      e = reinterpret_cast<void *> (1);
> +    }
> +
> +  /* Mark the passed in entry as being empty.  */
> +
> +  template<typename T>
> +  static void
> +  mark_empty (T *&e)
> +    {
> +      e = NULL;
> +    }
> +
> +  /* Return true if the passed in entry is marked as deleted.  */
> +
> +  template<typename T>
> +  static bool
> +  is_deleted (T *e)
> +    {
> +      return e == reinterpret_cast<void *> (1);
> +    }
> +
> +  /* Return true if the passed in entry is marked as empty.  */
> +
> +  template<typename T> static bool is_empty (T *e) { return e == NULL; }
> +};
> +
> +template<typename Key, typename Traits = default_hashset_traits>
> +class hash_set
> +{
> +  struct hash_entry
> +  {
> +    Key m_key;
> +
> +    typedef hash_entry value_type;
> +    typedef Key compare_type;
> +    typedef int store_values_directly;
> +
> +    static hashval_t hash (const hash_entry &e)
> +      {
> +               return Traits::hash (e.m_key);
> +      }
> +
> +    static bool equal (const hash_entry &a, const Key &b)
> +               {
> +         return Traits::equal (a.m_key, b);
> +               }
> +
> +    static void remove (hash_entry &e) { Traits::remove (e.m_key); }
> +
> +    static void
> +    mark_deleted (hash_entry &e)
> +      {
> +               Traits::mark_deleted (e.m_key);
> +      }
> +
> +    static bool is_deleted (const hash_entry &e)
> +      {
> +               return Traits::is_deleted (e.m_key);
> +      }
> +
> +    static void
> +    mark_empty (hash_entry &e)
> +      {
> +       Traits::mark_empty (e.m_key);
> +      }
> +
> +    static bool
> +    is_empty (const hash_entry &e)
> +      {
> +       return Traits::is_empty (e.m_key);
> +      }
> +  };
> +
> +public:
> +  explicit hash_set (size_t n = 13) : m_table (n) {}
> +
> +  /* If key k isn't already in the map add it to the map, and
> +     return false.  Otherwise return true.  */
> +
> +  bool add (const Key &k)
> +    {
> +      hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
> +                                                  INSERT);
> +      bool existed = !hash_entry::is_empty (*e);
> +      if (!existed)
> +       e->m_key = k;
> +
> +      return existed;
> +    }
> +
> +  /* if the passed in key is in the map return its value otherwise NULL.  */
> +
> +  bool contains (const Key &k)
> +    {
> +      hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
> +      return !Traits::is_empty (e.m_key);
> +    }
> +
> +  /* Call the call back on each pair of key and value with the passed in
> +     arg.  */
> +
> +  template<typename Arg, bool (*f)(const Key &, Arg)>
> +  void traverse (Arg a) const
> +    {
> +      for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
> +          iter != m_table.end (); ++iter)
> +       f ((*iter).m_key, a);
> +    }
> +
> +private:
> +  hash_table<hash_entry> m_table;
> +};
> +
> +#endif
> diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
> index 127d58d..70a70a7 100644
> --- a/gcc/ipa-devirt.c
> +++ b/gcc/ipa-devirt.c
> @@ -115,7 +115,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "cgraph.h"
>  #include "expr.h"
>  #include "tree-pass.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "target.h"
>  #include "hash-table.h"
>  #include "inchash.h"
> @@ -134,7 +134,8 @@ along with GCC; see the file COPYING3.  If not see
>  #include "stor-layout.h"
>  #include "intl.h"
>
> -static bool odr_types_equivalent_p (tree, tree, bool, bool *, pointer_set_t *);
> +static bool odr_types_equivalent_p (tree, tree, bool, bool *,
> +                                   hash_set<tree> *);
>
>  static bool odr_violation_reported = false;
>
> @@ -144,7 +145,7 @@ const ipa_polymorphic_call_context ipa_dummy_polymorphic_call_context
>     = {0, NULL, false, true};
>
>  /* Pointer set of all call targets appearing in the cache.  */
> -static pointer_set_t *cached_polymorphic_call_targets;
> +static hash_set<cgraph_node *> *cached_polymorphic_call_targets;
>
>  /* The node of type inheritance graph.  For each type unique in
>     One Defintion Rule (ODR) sense, we produce one node linking all
> @@ -163,7 +164,7 @@ struct GTY(()) odr_type_d
>    /* All equivalent types, if more than one.  */
>    vec<tree, va_gc> *types;
>    /* Set of all equivalent types, if NON-NULL.  */
> -  pointer_set_t * GTY((skip)) types_set;
> +  hash_set<tree> * GTY((skip)) types_set;
>
>    /* Unique ID indexing the type in odr_types array.  */
>    int id;
> @@ -409,7 +410,7 @@ odr_hasher::remove (value_type *v)
>    v->bases.release ();
>    v->derived_types.release ();
>    if (v->types_set)
> -    pointer_set_destroy (v->types_set);
> +    delete v->types_set;
>    ggc_free (v);
>  }
>
> @@ -439,7 +440,7 @@ set_type_binfo (tree type, tree binfo)
>  /* Compare T2 and T2 based on name or structure.  */
>
>  static bool
> -odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
> +odr_subtypes_equivalent_p (tree t1, tree t2, hash_set<tree> *visited)
>  {
>    bool an1, an2;
>
> @@ -473,7 +474,7 @@ odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
>        /* This should really be a pair hash, but for the moment we do not need
>          100% reliability and it would be better to compare all ODR types so
>          recursion here is needed only for component types.  */
> -      if (pointer_set_insert (visited, t1))
> +      if (visited->add (t1))
>         return true;
>        return odr_types_equivalent_p (t1, t2, false, NULL, visited);
>      }
> @@ -562,7 +563,7 @@ warn_types_mismatch (tree t1, tree t2)
>     gimple_canonical_types_compatible_p.  */
>
>  static bool
> -odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, pointer_set_t *visited)
> +odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, hash_set<tree> *visited)
>  {
>    /* Check first for the obvious case of pointer identity.  */
>    if (t1 == t2)
> @@ -938,7 +939,7 @@ add_type_duplicate (odr_type val, tree type)
>  {
>    bool build_bases = false;
>    if (!val->types_set)
> -    val->types_set = pointer_set_create ();
> +    val->types_set = new hash_set<tree>;
>
>    /* Always prefer complete type to be the leader.  */
>    if (!COMPLETE_TYPE_P (val->type)
> @@ -952,20 +953,20 @@ add_type_duplicate (odr_type val, tree type)
>      }
>
>    /* See if this duplicate is new.  */
> -  if (!pointer_set_insert (val->types_set, type))
> +  if (!val->types_set->add (type))
>      {
>        bool merge = true;
>        bool base_mismatch = false;
>        unsigned int i,j;
>        bool warned = false;
> -      pointer_set_t *visited = pointer_set_create ();
> +      hash_set<tree> visited;
>
>        gcc_assert (in_lto_p);
>        vec_safe_push (val->types, type);
>
>        /* First we compare memory layout.  */
>        if (!odr_types_equivalent_p (val->type, type, !flag_ltrans && !val->odr_violated,
> -                                  &warned, visited))
> +                                  &warned, &visited))
>         {
>           merge = false;
>           odr_violation_reported = true;
> @@ -980,7 +981,6 @@ add_type_duplicate (odr_type val, tree type)
>               putc ('\n',cgraph_dump_file);
>             }
>         }
> -      pointer_set_destroy (visited);
>
>        /* Next sanity check that bases are the same.  If not, we will end
>          up producing wrong answers.  */
> @@ -1356,7 +1356,7 @@ referenced_from_vtable_p (struct cgraph_node *node)
>
>  static void
>  maybe_record_node (vec <cgraph_node *> &nodes,
> -                  tree target, pointer_set_t *inserted,
> +                  tree target, hash_set<tree> *inserted,
>                    bool can_refer,
>                    bool *completep)
>  {
> @@ -1422,10 +1422,9 @@ maybe_record_node (vec <cgraph_node *> &nodes,
>      {
>        gcc_assert (!target_node->global.inlined_to);
>        gcc_assert (target_node->real_symbol_p ());
> -      if (!pointer_set_insert (inserted, target_node->decl))
> +      if (!inserted->add (target))
>         {
> -         pointer_set_insert (cached_polymorphic_call_targets,
> -                             target_node);
> +         cached_polymorphic_call_targets->add (target_node);
>           nodes.safe_push (target_node);
>         }
>      }
> @@ -1465,8 +1464,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
>                           HOST_WIDE_INT otr_token,
>                           tree outer_type,
>                           HOST_WIDE_INT offset,
> -                         pointer_set_t *inserted,
> -                         pointer_set_t *matched_vtables,
> +                         hash_set<tree> *inserted,
> +                         hash_set<tree> *matched_vtables,
>                           bool anonymous,
>                           bool *completep)
>  {
> @@ -1519,8 +1518,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
>         }
>        gcc_assert (inner_binfo);
>        if (bases_to_consider
> -         ? !pointer_set_contains (matched_vtables, BINFO_VTABLE (inner_binfo))
> -         : !pointer_set_insert (matched_vtables, BINFO_VTABLE (inner_binfo)))
> +         ? !matched_vtables->contains (BINFO_VTABLE (inner_binfo))
> +         : !matched_vtables->add (BINFO_VTABLE (inner_binfo)))
>         {
>           bool can_refer;
>           tree target = gimple_get_virt_method_for_binfo (otr_token,
> @@ -1559,8 +1558,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
>
>  static void
>  possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes,
> -                                    pointer_set_t *inserted,
> -                                    pointer_set_t *matched_vtables,
> +                                    hash_set<tree> *inserted,
> +                                    hash_set<tree> *matched_vtables,
>                                      tree otr_type,
>                                      odr_type type,
>                                      HOST_WIDE_INT otr_token,
> @@ -1684,7 +1683,7 @@ free_polymorphic_call_targets_hash ()
>      {
>        delete polymorphic_call_target_hash;
>        polymorphic_call_target_hash = NULL;
> -      pointer_set_destroy (cached_polymorphic_call_targets);
> +      delete cached_polymorphic_call_targets;
>        cached_polymorphic_call_targets = NULL;
>      }
>  }
> @@ -1695,7 +1694,7 @@ static void
>  devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
>  {
>    if (cached_polymorphic_call_targets
> -      && pointer_set_contains (cached_polymorphic_call_targets, n))
> +      && cached_polymorphic_call_targets->contains (n))
>      free_polymorphic_call_targets_hash ();
>  }
>
> @@ -2277,8 +2276,8 @@ record_targets_from_bases (tree otr_type,
>                            tree outer_type,
>                            HOST_WIDE_INT offset,
>                            vec <cgraph_node *> &nodes,
> -                          pointer_set_t *inserted,
> -                          pointer_set_t *matched_vtables,
> +                          hash_set<tree> *inserted,
> +                          hash_set<tree> *matched_vtables,
>                            bool *completep)
>  {
>    while (true)
> @@ -2319,7 +2318,7 @@ record_targets_from_bases (tree otr_type,
>           return;
>         }
>        gcc_assert (base_binfo);
> -      if (!pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo)))
> +      if (!matched_vtables->add (BINFO_VTABLE (base_binfo)))
>         {
>           bool can_refer;
>           tree target = gimple_get_virt_method_for_binfo (otr_token,
> @@ -2327,7 +2326,7 @@ record_targets_from_bases (tree otr_type,
>                                                           &can_refer);
>           if (!target || ! DECL_CXX_DESTRUCTOR_P (target))
>             maybe_record_node (nodes, target, inserted, can_refer, completep);
> -         pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo));
> +         matched_vtables->add (BINFO_VTABLE (base_binfo));
>         }
>      }
>  }
> @@ -2377,8 +2376,6 @@ possible_polymorphic_call_targets (tree otr_type,
>                                    int *nonconstruction_targetsp)
>  {
>    static struct cgraph_node_hook_list *node_removal_hook_holder;
> -  pointer_set_t *inserted;
> -  pointer_set_t *matched_vtables;
>    vec <cgraph_node *> nodes = vNULL;
>    vec <tree> bases_to_consider = vNULL;
>    odr_type type, outer_type;
> @@ -2457,7 +2454,7 @@ possible_polymorphic_call_targets (tree otr_type,
>    /* Initialize query cache.  */
>    if (!cached_polymorphic_call_targets)
>      {
> -      cached_polymorphic_call_targets = pointer_set_create ();
> +      cached_polymorphic_call_targets = new hash_set<cgraph_node *>;
>        polymorphic_call_target_hash
>                 = new polymorphic_call_target_hash_type (23);
>        if (!node_removal_hook_holder)
> @@ -2496,8 +2493,8 @@ possible_polymorphic_call_targets (tree otr_type,
>    (*slot)->otr_token = otr_token;
>    (*slot)->context = context;
>
> -  inserted = pointer_set_create ();
> -  matched_vtables = pointer_set_create ();
> +  hash_set<tree> inserted;
> +  hash_set<tree> matched_vtables;
>
>    /* First see virtual method of type itself.  */
>    binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type),
> @@ -2526,7 +2523,7 @@ possible_polymorphic_call_targets (tree otr_type,
>
>    /* If OUTER_TYPE is abstract, we know we are not seeing its instance.  */
>    if (type_possibly_instantiated_p (outer_type->type))
> -    maybe_record_node (nodes, target, inserted, can_refer, &complete);
> +    maybe_record_node (nodes, target, &inserted, can_refer, &complete);
>    else
>      {
>        skipped = true;
> @@ -2534,7 +2531,7 @@ possible_polymorphic_call_targets (tree otr_type,
>      }
>
>    if (binfo)
> -    pointer_set_insert (matched_vtables, BINFO_VTABLE (binfo));
> +    matched_vtables.add (BINFO_VTABLE (binfo));
>
>    /* Next walk recursively all derived types.  */
>    if (context.maybe_derived_type)
> @@ -2544,8 +2541,8 @@ possible_polymorphic_call_targets (tree otr_type,
>        if (!type->all_derivations_known)
>         complete = false;
>        for (i = 0; i < outer_type->derived_types.length(); i++)
> -       possible_polymorphic_call_targets_1 (nodes, inserted,
> -                                            matched_vtables,
> +       possible_polymorphic_call_targets_1 (nodes, &inserted,
> +                                            &matched_vtables,
>                                              otr_type,
>                                              outer_type->derived_types[i],
>                                              otr_token, outer_type->type,
> @@ -2571,12 +2568,12 @@ possible_polymorphic_call_targets (tree otr_type,
>               || (context.maybe_derived_type
>                   && !type_all_derivations_known_p (outer_type->type))))
>         record_targets_from_bases (otr_type, otr_token, outer_type->type,
> -                                  context.offset, nodes, inserted,
> -                                  matched_vtables, &complete);
> +                                  context.offset, nodes, &inserted,
> +                                  &matched_vtables, &complete);
>        if (skipped)
> -        maybe_record_node (nodes, target, inserted, can_refer, &complete);
> +        maybe_record_node (nodes, target, &inserted, can_refer, &complete);
>        for (i = 0; i < bases_to_consider.length(); i++)
> -        maybe_record_node (nodes, bases_to_consider[i], inserted, can_refer, &complete);
> +        maybe_record_node (nodes, bases_to_consider[i], &inserted, can_refer, &complete);
>      }
>    bases_to_consider.release();
>
> @@ -2587,8 +2584,6 @@ possible_polymorphic_call_targets (tree otr_type,
>    if (nonconstruction_targetsp)
>      *nonconstruction_targetsp = (*slot)->nonconstruction_targets;
>
> -  pointer_set_destroy (inserted);
> -  pointer_set_destroy (matched_vtables);
>    timevar_pop (TV_IPA_VIRTUAL_CALL);
>    return nodes;
>  }
> @@ -2744,7 +2739,7 @@ static unsigned int
>  ipa_devirt (void)
>  {
>    struct cgraph_node *n;
> -  struct pointer_set_t *bad_call_targets = pointer_set_create ();
> +  hash_set<void *> bad_call_targets;
>    struct cgraph_edge *e;
>
>    int npolymorphic = 0, nspeculated = 0, nconverted = 0, ncold = 0;
> @@ -2792,8 +2787,7 @@ ipa_devirt (void)
>                 if (!dump_file)
>                   continue;
>               }
> -           if (pointer_set_contains (bad_call_targets,
> -                                     cache_token))
> +           if (bad_call_targets.contains (cache_token))
>               {
>                 if (dump_file)
>                   fprintf (dump_file, "Target list is known to be useless\n\n");
> @@ -2818,7 +2812,7 @@ ipa_devirt (void)
>                 }
>             if (!likely_target)
>               {
> -               pointer_set_insert (bad_call_targets, cache_token);
> +               bad_call_targets.add (cache_token);
>                 continue;
>               }
>             /* This is reached only when dumping; check if we agree or disagree
> @@ -2905,7 +2899,6 @@ ipa_devirt (void)
>        if (update)
>         inline_update_overall_summary (n);
>      }
> -  pointer_set_destroy (bad_call_targets);
>
>    if (dump_file)
>      fprintf (dump_file,
> diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
> index 2c281be..b964502 100644
> --- a/gcc/ipa-pure-const.c
> +++ b/gcc/ipa-pure-const.c
> @@ -65,8 +65,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-scalar-evolution.h"
>  #include "intl.h"
>  #include "opts.h"
> -
> -static struct pointer_set_t *visited_nodes;
> +#include "hash-set.h"
>
>  /* Lattice values for const and pure functions.  Everything starts out
>     being const, then may drop to pure and then neither depending on
> @@ -133,13 +132,13 @@ function_always_visible_to_compiler_p (tree decl)
>
>  /* Emit suggestion about attribute ATTRIB_NAME for DECL.  KNOWN_FINITE
>     is true if the function is known to be finite.  The diagnostic is
> -   controlled by OPTION.  WARNED_ABOUT is a pointer_set unique for
> +   controlled by OPTION.  WARNED_ABOUT is a hash_set<tree> unique for
>     OPTION, this function may initialize it and it is always returned
>     by the function.  */
>
> -static struct pointer_set_t *
> +static hash_set<tree> *
>  suggest_attribute (int option, tree decl, bool known_finite,
> -                  struct pointer_set_t *warned_about,
> +                  hash_set<tree> *warned_about,
>                    const char * attrib_name)
>  {
>    if (!option_enabled (option, &global_options))
> @@ -149,10 +148,10 @@ suggest_attribute (int option, tree decl, bool known_finite,
>      return warned_about;
>
>    if (!warned_about)
> -    warned_about = pointer_set_create ();
> -  if (pointer_set_contains (warned_about, decl))
> +    warned_about = new hash_set<tree>;
> +  if (warned_about->contains (decl))
>      return warned_about;
> -  pointer_set_insert (warned_about, decl);
> +  warned_about->add (decl);
>    warning_at (DECL_SOURCE_LOCATION (decl),
>               option,
>               known_finite
> @@ -168,7 +167,7 @@ suggest_attribute (int option, tree decl, bool known_finite,
>  static void
>  warn_function_pure (tree decl, bool known_finite)
>  {
> -  static struct pointer_set_t *warned_about;
> +  static hash_set<tree> *warned_about;
>
>    warned_about
>      = suggest_attribute (OPT_Wsuggest_attribute_pure, decl,
> @@ -181,7 +180,7 @@ warn_function_pure (tree decl, bool known_finite)
>  static void
>  warn_function_const (tree decl, bool known_finite)
>  {
> -  static struct pointer_set_t *warned_about;
> +  static hash_set<tree> *warned_about;
>    warned_about
>      = suggest_attribute (OPT_Wsuggest_attribute_const, decl,
>                          known_finite, warned_about, "const");
> @@ -190,7 +189,7 @@ warn_function_const (tree decl, bool known_finite)
>  static void
>  warn_function_noreturn (tree decl)
>  {
> -  static struct pointer_set_t *warned_about;
> +  static hash_set<tree> *warned_about;
>    if (!lang_hooks.missing_noreturn_ok_p (decl)
>        && targetm.warn_func_return (decl))
>      warned_about
> @@ -846,11 +845,8 @@ add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
>       static declarations.  We do not need to scan them more than once
>       since all we would be interested in are the addressof
>       operations.  */
> -  visited_nodes = pointer_set_create ();
>    if (node->get_availability () > AVAIL_INTERPOSABLE)
>      set_function_state (node, analyze_function (node, true));
> -  pointer_set_destroy (visited_nodes);
> -  visited_nodes = NULL;
>  }
>
>  /* Called when new clone is inserted to callgraph late.  */
> @@ -912,12 +908,6 @@ pure_const_generate_summary (void)
>
>    register_hooks ();
>
> -  /* There are some shared nodes, in particular the initializers on
> -     static declarations.  We do not need to scan them more than once
> -     since all we would be interested in are the addressof
> -     operations.  */
> -  visited_nodes = pointer_set_create ();
> -
>    /* Process all of the functions.
>
>       We process AVAIL_INTERPOSABLE functions.  We can not use the results
> @@ -927,9 +917,6 @@ pure_const_generate_summary (void)
>    FOR_EACH_DEFINED_FUNCTION (node)
>      if (node->get_availability () >= AVAIL_INTERPOSABLE)
>        set_function_state (node, analyze_function (node, true));
> -
> -  pointer_set_destroy (visited_nodes);
> -  visited_nodes = NULL;
>  }
>
>
> diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
> index 4720ee9..bca2bc7 100644
> --- a/gcc/ipa-visibility.c
> +++ b/gcc/ipa-visibility.c
> @@ -687,12 +687,11 @@ function_and_variable_visibility (bool whole_program)
>               }
>           if (found)
>             {
> -             struct pointer_set_t *visited_nodes = pointer_set_create ();
> +             hash_set<tree> visited_nodes;
>
>               vnode->get_constructor ();
>               walk_tree (&DECL_INITIAL (vnode->decl),
> -                        update_vtable_references, NULL, visited_nodes);
> -             pointer_set_destroy (visited_nodes);
> +                        update_vtable_references, NULL, &visited_nodes);
>               vnode->remove_all_references ();
>               record_references_in_initializer (vnode->decl, false);
>             }
> diff --git a/gcc/ipa.c b/gcc/ipa.c
> index 8198b17..1081e89 100644
> --- a/gcc/ipa.c
> +++ b/gcc/ipa.c
> @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "cgraph.h"
>  #include "tree-pass.h"
>  #include "hash-map.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "gimple-expr.h"
>  #include "gimplify.h"
>  #include "flags.h"
> @@ -84,14 +84,14 @@ update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined
>
>  static void
>  enqueue_node (symtab_node *node, symtab_node **first,
> -             struct pointer_set_t *reachable)
> +             hash_set<symtab_node *> *reachable)
>  {
>    /* Node is still in queue; do nothing.  */
>    if (node->aux && node->aux != (void *) 2)
>      return;
>    /* Node was already processed as unreachable, re-enqueue
>       only if it became reachable now.  */
> -  if (node->aux == (void *)2 && !pointer_set_contains (reachable, node))
> +  if (node->aux == (void *)2 && !reachable->contains (node))
>      return;
>    node->aux = *first;
>    *first = node;
> @@ -103,7 +103,7 @@ static void
>  process_references (symtab_node *snode,
>                     symtab_node **first,
>                     bool before_inlining_p,
> -                   struct pointer_set_t *reachable)
> +                   hash_set<symtab_node *> *reachable)
>  {
>    int i;
>    struct ipa_ref *ref = NULL;
> @@ -124,7 +124,7 @@ process_references (symtab_node *snode,
>                       && flag_wpa
>                       && ctor_for_folding (node->decl)
>                          != error_mark_node))))
> -       pointer_set_insert (reachable, node);
> +       reachable->add (node);
>        enqueue_node (node, first, reachable);
>      }
>  }
> @@ -138,10 +138,11 @@ process_references (symtab_node *snode,
>     possible.  */
>
>  static void
> -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
>                                struct cgraph_edge *edge,
>                                symtab_node **first,
> -                              pointer_set_t *reachable, bool before_inlining_p)
> +                              hash_set<symtab_node *> *reachable,
> +                              bool before_inlining_p)
>  {
>    unsigned int i;
>    void *cache_token;
> @@ -150,8 +151,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
>      = possible_polymorphic_call_targets
>         (edge, &final, &cache_token);
>
> -  if (!pointer_set_insert (reachable_call_targets,
> -                          cache_token))
> +  if (!reachable_call_targets->add (cache_token))
>      {
>        for (i = 0; i < targets.length (); i++)
>         {
> @@ -172,7 +172,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
>                    && (cgraph_state < CGRAPH_STATE_IPA_SSA
>                        || !lookup_attribute ("always_inline",
>                                              DECL_ATTRIBUTES (n->decl)))))
> -            pointer_set_insert (reachable, n);
> +            reachable->add (n);
>
>           /* Even after inlining we want to keep the possible targets in the
>              boundary, so late passes can still produce direct call even if
> @@ -276,9 +276,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>    struct cgraph_node *node, *next;
>    varpool_node *vnode, *vnext;
>    bool changed = false;
> -  struct pointer_set_t *reachable = pointer_set_create ();
> -  struct pointer_set_t *body_needed_for_clonning = pointer_set_create ();
> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> +  hash_set<symtab_node *> reachable;
> +  hash_set<tree> body_needed_for_clonning;
> +  hash_set<void *> reachable_call_targets;
>
>    timevar_push (TV_IPA_UNREACHABLE);
>    if (optimize && flag_devirtualize)
> @@ -304,8 +304,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>           && !node->can_remove_if_no_direct_calls_and_refs_p ())
>         {
>           gcc_assert (!node->global.inlined_to);
> -         pointer_set_insert (reachable, node);
> -         enqueue_node (node, &first, reachable);
> +         reachable.add (node);
> +         enqueue_node (node, &first, &reachable);
>         }
>        else
>         gcc_assert (!node->aux);
> @@ -316,14 +316,14 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>      if (!vnode->can_remove_if_no_refs_p()
>         && !vnode->in_other_partition)
>        {
> -       pointer_set_insert (reachable, vnode);
> -       enqueue_node (vnode, &first, reachable);
> +       reachable.add (vnode);
> +       enqueue_node (vnode, &first, &reachable);
>        }
>
>    /* Perform reachability analysis.  */
>    while (first != (symtab_node *) (void *) 1)
>      {
> -      bool in_boundary_p = !pointer_set_contains (reachable, first);
> +      bool in_boundary_p = !reachable.contains (first);
>        symtab_node *node = first;
>
>        first = (symtab_node *)first->aux;
> @@ -340,7 +340,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>               struct cgraph_node *origin_node
>               = cgraph_node::get_create (DECL_ABSTRACT_ORIGIN (node->decl));
>               origin_node->used_as_abstract_origin = true;
> -             enqueue_node (origin_node, &first, reachable);
> +             enqueue_node (origin_node, &first, &reachable);
>             }
>           /* If any symbol in a comdat group is reachable, force
>              all externally visible symbols in the same comdat
> @@ -353,11 +353,11 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>                    next != node;
>                    next = next->same_comdat_group)
>                 if (!next->comdat_local_p ()
> -                   && !pointer_set_insert (reachable, next))
> -                 enqueue_node (next, &first, reachable);
> +                   && !reachable.add (next))
> +                 enqueue_node (next, &first, &reachable);
>             }
>           /* Mark references as reachable.  */
> -         process_references (node, &first, before_inlining_p, reachable);
> +         process_references (node, &first, before_inlining_p, &reachable);
>         }
>
>        if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
> @@ -375,8 +375,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>                     {
>                       next = e->next_callee;
>                       if (e->indirect_info->polymorphic)
> -                       walk_polymorphic_call_targets (reachable_call_targets,
> -                                                      e, &first, reachable,
> +                       walk_polymorphic_call_targets (&reachable_call_targets,
> +                                                      e, &first, &reachable,
>                                                        before_inlining_p);
>                     }
>                 }
> @@ -394,17 +394,16 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>                       if (DECL_EXTERNAL (e->callee->decl)
>                           && e->callee->alias
>                           && before_inlining_p)
> -                       pointer_set_insert (reachable,
> -                                           e->callee->function_symbol ());
> -                     pointer_set_insert (reachable, e->callee);
> +                       reachable.add (e->callee->function_symbol ());
> +                     reachable.add (e->callee);
>                     }
> -                 enqueue_node (e->callee, &first, reachable);
> +                 enqueue_node (e->callee, &first, &reachable);
>                 }
>
>               /* When inline clone exists, mark body to be preserved so when removing
>                  offline copy of the function we don't kill it.  */
>               if (cnode->global.inlined_to)
> -               pointer_set_insert (body_needed_for_clonning, cnode->decl);
> +               body_needed_for_clonning.add (cnode->decl);
>
>               /* For non-inline clones, force their origins to the boundary and ensure
>                  that body is not removed.  */
> @@ -414,8 +413,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>                   cnode = cnode->clone_of;
>                   if (noninline)
>                     {
> -                     pointer_set_insert (body_needed_for_clonning, cnode->decl);
> -                     enqueue_node (cnode, &first, reachable);
> +                     body_needed_for_clonning.add (cnode->decl);
> +                     enqueue_node (cnode, &first, &reachable);
>                     }
>                 }
>
> @@ -429,8 +428,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>                    next;
>                    next = next->simdclone->next_clone)
>                 if (in_boundary_p
> -                   || !pointer_set_insert (reachable, next))
> -                 enqueue_node (next, &first, reachable);
> +                   || !reachable.add (next))
> +                 enqueue_node (next, &first, &reachable);
>             }
>         }
>        /* When we see constructor of external variable, keep referred nodes in the
> @@ -444,7 +443,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>         {
>           struct ipa_ref *ref = NULL;
>           for (int i = 0; node->iterate_reference (i, ref); i++)
> -           enqueue_node (ref->referred, &first, reachable);
> +           enqueue_node (ref->referred, &first, &reachable);
>         }
>      }
>
> @@ -462,9 +461,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>           changed = true;
>         }
>        /* If node is unreachable, remove its body.  */
> -      else if (!pointer_set_contains (reachable, node))
> +      else if (!reachable.contains (node))
>          {
> -         if (!pointer_set_contains (body_needed_for_clonning, node->decl))
> +         if (!body_needed_for_clonning.contains (node->decl))
>             node->release_body ();
>           else if (!node->clone_of)
>             gcc_assert (in_lto_p || DECL_RESULT (node->decl));
> @@ -530,7 +529,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>           vnode->remove ();
>           changed = true;
>         }
> -      else if (!pointer_set_contains (reachable, vnode))
> +      else if (!reachable.contains (vnode))
>          {
>           tree init;
>           if (vnode->definition)
> @@ -557,10 +556,6 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>         vnode->aux = NULL;
>      }
>
> -  pointer_set_destroy (reachable);
> -  pointer_set_destroy (body_needed_for_clonning);
> -  pointer_set_destroy (reachable_call_targets);
> -
>    /* Now update address_taken flags and try to promote functions to be local.  */
>    if (file)
>      fprintf (file, "\nClearing address taken flags:");
> diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
> index b1fcf67..42b0790 100644
> --- a/gcc/lto-cgraph.c
> +++ b/gcc/lto-cgraph.c
> @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "params.h"
>  #include "input.h"
>  #include "hashtab.h"
> +#include "hash-set.h"
>  #include "langhooks.h"
>  #include "bitmap.h"
>  #include "function.h"
> @@ -819,7 +820,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
>    int i;
>    lto_symtab_encoder_t encoder;
>    lto_symtab_encoder_iterator lsei;
> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> +  hash_set<void *> reachable_call_targets;
>
>    encoder = lto_symtab_encoder_new (false);
>
> @@ -902,8 +903,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
>               vec <cgraph_node *>targets
>                 = possible_polymorphic_call_targets
>                     (edge, &final, &cache_token);
> -             if (!pointer_set_insert (reachable_call_targets,
> -                                      cache_token))
> +             if (!reachable_call_targets.add (cache_token))
>                 {
>                   for (i = 0; i < targets.length (); i++)
>                     {
> @@ -923,7 +923,6 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
>             }
>      }
>    lto_symtab_encoder_delete (in_encoder);
> -  pointer_set_destroy (reachable_call_targets);
>    return encoder;
>  }
>
> diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
> index 271fbd5..3fd9147 100644
> --- a/gcc/lto-streamer-out.c
> +++ b/gcc/lto-streamer-out.c
> @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "params.h"
>  #include "input.h"
>  #include "hashtab.h"
> +#include "hash-set.h"
>  #include "basic-block.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
> @@ -2433,7 +2434,7 @@ lto_out_decl_state_written_size (struct lto_out_decl_state *state)
>  static void
>  write_symbol (struct streamer_tree_cache_d *cache,
>               struct lto_output_stream *stream,
> -             tree t, struct pointer_set_t *seen, bool alias)
> +             tree t, hash_set<const char *> *seen, bool alias)
>  {
>    const char *name;
>    enum gcc_plugin_symbol_kind kind;
> @@ -2461,9 +2462,8 @@ write_symbol (struct streamer_tree_cache_d *cache,
>       same name manipulations that ASM_OUTPUT_LABELREF does. */
>    name = IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name) (name));
>
> -  if (pointer_set_contains (seen, name))
> +  if (seen->add (name))
>      return;
> -  pointer_set_insert (seen, name);
>
>    streamer_tree_cache_lookup (cache, t, &slot_num);
>    gcc_assert (slot_num != (unsigned)-1);
> @@ -2588,7 +2588,6 @@ produce_symtab (struct output_block *ob)
>  {
>    struct streamer_tree_cache_d *cache = ob->writer_cache;
>    char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
> -  struct pointer_set_t *seen;
>    struct lto_output_stream stream;
>    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
>    lto_symtab_encoder_iterator lsei;
> @@ -2596,7 +2595,7 @@ produce_symtab (struct output_block *ob)
>    lto_begin_section (section_name, false);
>    free (section_name);
>
> -  seen = pointer_set_create ();
> +  hash_set<const char *> seen;
>    memset (&stream, 0, sizeof (stream));
>
>    /* Write the symbol table.
> @@ -2609,7 +2608,7 @@ produce_symtab (struct output_block *ob)
>
>        if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
>         continue;
> -      write_symbol (cache, &stream, node->decl, seen, false);
> +      write_symbol (cache, &stream, node->decl, &seen, false);
>      }
>    for (lsei = lsei_start (encoder);
>         !lsei_end_p (lsei); lsei_next (&lsei))
> @@ -2618,11 +2617,10 @@ produce_symtab (struct output_block *ob)
>
>        if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
>         continue;
> -      write_symbol (cache, &stream, node->decl, seen, false);
> +      write_symbol (cache, &stream, node->decl, &seen, false);
>      }
>
>    lto_write_stream (&stream);
> -  pointer_set_destroy (seen);
>
>    lto_end_section ();
>  }
> diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
> index cb08a88..a5bcf92 100644
> --- a/gcc/lto/lto-partition.c
> +++ b/gcc/lto/lto-partition.c
> @@ -66,7 +66,7 @@ free_ltrans_partitions (void)
>    for (idx = 0; ltrans_partitions.iterate (idx, &part); idx++)
>      {
>        if (part->initializers_visited)
> -       pointer_set_destroy (part->initializers_visited);
> +       delete part->initializers_visited;
>        /* Symtab encoder is freed after streaming.  */
>        free (part);
>      }
> @@ -101,8 +101,8 @@ add_references_to_partition (ltrans_partition part, symtab_node *node)
>              && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
>        {
>         if (!part->initializers_visited)
> -         part->initializers_visited = pointer_set_create ();
> -       if (!pointer_set_insert (part->initializers_visited, ref->referred))
> +         part->initializers_visited = new hash_set<symtab_node *>;
> +       if (!part->initializers_visited->add (ref->referred))
>           add_references_to_partition (part, ref->referred);
>        }
>  }
> @@ -250,7 +250,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes)
>
>        /* After UNDO we no longer know what was visited.  */
>        if (partition->initializers_visited)
> -       pointer_set_destroy (partition->initializers_visited);
> +       delete partition->initializers_visited;
>        partition->initializers_visited = NULL;
>
>        if (!node->alias && (cnode = dyn_cast <cgraph_node *> (node)))
> diff --git a/gcc/lto/lto-partition.h b/gcc/lto/lto-partition.h
> index 8db61b3..50ec2fa 100644
> --- a/gcc/lto/lto-partition.h
> +++ b/gcc/lto/lto-partition.h
> @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
>  along with GCC; see the file COPYING3.  If not see
>  <http://www.gnu.org/licenses/>.  */
>
> +#include "hash-set.h"
>
>  /* Structure describing ltrans partitions.  */
>
> @@ -25,7 +26,7 @@ struct ltrans_partition_def
>    lto_symtab_encoder_t encoder;
>    const char * name;
>    int insns;
> -  pointer_set_t *initializers_visited;
> +  hash_set<symtab_node *> *initializers_visited;
>  };
>
>  typedef struct ltrans_partition_def *ltrans_partition;
> diff --git a/gcc/stmt.c b/gcc/stmt.c
> index 0aae085..55ec279 100644
> --- a/gcc/stmt.c
> +++ b/gcc/stmt.c
> @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "predict.h"
>  #include "optabs.h"
>  #include "target.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "basic-block.h"
>  #include "tree-ssa-alias.h"
> @@ -1183,7 +1184,7 @@ expand_case (gimple stmt)
>       how to expand this switch().  */
>    uniq = 0;
>    count = 0;
> -  struct pointer_set_t *seen_labels = pointer_set_create ();
> +  hash_set<tree> seen_labels;
>    compute_cases_per_edge (stmt);
>
>    for (i = ncases - 1; i >= 1; --i)
> @@ -1203,7 +1204,7 @@ expand_case (gimple stmt)
>
>        /* If we have not seen this label yet, then increase the
>          number of unique case node targets seen.  */
> -      if (!pointer_set_insert (seen_labels, lab))
> +      if (!seen_labels.add (lab))
>         uniq++;
>
>        /* The bounds on the case range, LOW and HIGH, have to be converted
> @@ -1231,7 +1232,6 @@ expand_case (gimple stmt)
>            case_edge->probability / (intptr_t)(case_edge->aux),
>            case_node_pool);
>      }
> -  pointer_set_destroy (seen_labels);
>    reset_out_edges_aux (bb);
>
>    /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> index 6fee8a4..e034762 100644
> --- a/gcc/tree-cfg.c
> +++ b/gcc/tree-cfg.c
> @@ -4691,7 +4691,7 @@ tree_node_can_be_shared (tree t)
>  static tree
>  verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
>  {
> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> +  hash_set<void *> *visited = (hash_set<void *> *) data;
>
>    if (tree_node_can_be_shared (*tp))
>      {
> @@ -4699,7 +4699,7 @@ verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
>        return NULL;
>      }
>
> -  if (pointer_set_insert (visited, *tp))
> +  if (visited->add (*tp))
>      return *tp;
>
>    return NULL;
> @@ -4719,9 +4719,9 @@ static int
>  verify_eh_throw_stmt_node (void **slot, void *data)
>  {
>    struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> +  hash_set<void *> *visited = (hash_set<void *> *) data;
>
> -  if (!pointer_set_contains (visited, node->stmt))
> +  if (!visited->contains (node->stmt))
>      {
>        error ("dead STMT in EH table");
>        debug_gimple_stmt (node->stmt);
> @@ -4733,11 +4733,11 @@ verify_eh_throw_stmt_node (void **slot, void *data)
>  /* Verify if the location LOCs block is in BLOCKS.  */
>
>  static bool
> -verify_location (pointer_set_t *blocks, location_t loc)
> +verify_location (hash_set<tree> *blocks, location_t loc)
>  {
>    tree block = LOCATION_BLOCK (loc);
>    if (block != NULL_TREE
> -      && !pointer_set_contains (blocks, block))
> +      && !blocks->contains (block))
>      {
>        error ("location references block not in block tree");
>        return true;
> @@ -4770,7 +4770,7 @@ verify_expr_no_block (tree *tp, int *walk_subtrees, void *)
>  static tree
>  verify_expr_location_1 (tree *tp, int *walk_subtrees, void *data)
>  {
> -  struct pointer_set_t *blocks = (struct pointer_set_t *) data;
> +  hash_set<tree> *blocks = (hash_set<tree> *) data;
>
>    if (TREE_CODE (*tp) == VAR_DECL
>        && DECL_HAS_DEBUG_EXPR_P (*tp))
> @@ -4816,12 +4816,12 @@ verify_expr_location (tree *tp, int *walk_subtrees, void *data)
>  /* Insert all subblocks of BLOCK into BLOCKS and recurse.  */
>
>  static void
> -collect_subblocks (pointer_set_t *blocks, tree block)
> +collect_subblocks (hash_set<tree> *blocks, tree block)
>  {
>    tree t;
>    for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
>      {
> -      pointer_set_insert (blocks, t);
> +      blocks->add (t);
>        collect_subblocks (blocks, t);
>      }
>  }
> @@ -4833,18 +4833,17 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>  {
>    basic_block bb;
>    bool err = false;
> -  struct pointer_set_t *visited, *visited_stmts, *blocks;
>
>    timevar_push (TV_TREE_STMT_VERIFY);
> -  visited = pointer_set_create ();
> -  visited_stmts = pointer_set_create ();
> +  hash_set<void *> visited;
> +  hash_set<gimple> visited_stmts;
>
>    /* Collect all BLOCKs referenced by the BLOCK tree of FN.  */
> -  blocks = pointer_set_create ();
> +  hash_set<tree> blocks;
>    if (DECL_INITIAL (fn->decl))
>      {
> -      pointer_set_insert (blocks, DECL_INITIAL (fn->decl));
> -      collect_subblocks (blocks, DECL_INITIAL (fn->decl));
> +      blocks.add (DECL_INITIAL (fn->decl));
> +      collect_subblocks (&blocks, DECL_INITIAL (fn->decl));
>      }
>
>    FOR_EACH_BB_FN (bb, fn)
> @@ -4857,7 +4856,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>           bool err2 = false;
>           unsigned i;
>
> -         pointer_set_insert (visited_stmts, phi);
> +         visited_stmts.add (phi);
>
>           if (gimple_bb (phi) != bb)
>             {
> @@ -4878,7 +4877,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>             {
>               tree arg = gimple_phi_arg_def (phi, i);
>               tree addr = walk_tree (&arg, verify_node_sharing_1,
> -                                    visited, NULL);
> +                                    &visited, NULL);
>               if (addr)
>                 {
>                   error ("incorrect sharing of tree nodes");
> @@ -4892,13 +4891,13 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>                   error ("virtual PHI with argument locations");
>                   err2 = true;
>                 }
> -             addr = walk_tree (&arg, verify_expr_location_1, blocks, NULL);
> +             addr = walk_tree (&arg, verify_expr_location_1, &blocks, NULL);
>               if (addr)
>                 {
>                   debug_generic_expr (addr);
>                   err2 = true;
>                 }
> -             err2 |= verify_location (blocks, loc);
> +             err2 |= verify_location (&blocks, loc);
>             }
>
>           if (err2)
> @@ -4914,7 +4913,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>           tree addr;
>           int lp_nr;
>
> -         pointer_set_insert (visited_stmts, stmt);
> +         visited_stmts.add (stmt);
>
>           if (gimple_bb (stmt) != bb)
>             {
> @@ -4923,10 +4922,10 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>             }
>
>           err2 |= verify_gimple_stmt (stmt);
> -         err2 |= verify_location (blocks, gimple_location (stmt));
> +         err2 |= verify_location (&blocks, gimple_location (stmt));
>
>           memset (&wi, 0, sizeof (wi));
> -         wi.info = (void *) visited;
> +         wi.info = (void *) &visited;
>           addr = walk_gimple_op (stmt, verify_node_sharing, &wi);
>           if (addr)
>             {
> @@ -4936,7 +4935,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>             }
>
>           memset (&wi, 0, sizeof (wi));
> -         wi.info = (void *) blocks;
> +         wi.info = (void *) &blocks;
>           addr = walk_gimple_op (stmt, verify_expr_location, &wi);
>           if (addr)
>             {
> @@ -4992,14 +4991,11 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>    if (get_eh_throw_stmt_table (cfun))
>      htab_traverse (get_eh_throw_stmt_table (cfun),
>                    verify_eh_throw_stmt_node,
> -                  visited_stmts);
> +                  &visited_stmts);
>
>    if (err || eh_error_found)
>      internal_error ("verify_gimple failed");
>
> -  pointer_set_destroy (visited);
> -  pointer_set_destroy (visited_stmts);
> -  pointer_set_destroy (blocks);
>    verify_histograms ();
>    timevar_pop (TV_TREE_STMT_VERIFY);
>  }
> diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> index 34c48fa..9d462d1 100644
> --- a/gcc/tree-core.h
> +++ b/gcc/tree-core.h
> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>  #define GCC_TREE_CORE_H
>
>  #include "hashtab.h"
> +#include "hash-set.h"
>  #include "machmode.h"
>  #include "input.h"
>  #include "statistics.h"
> @@ -45,7 +46,6 @@ struct fixed_value;
>  struct ptr_info_def;
>  struct range_info_def;
>  struct die_struct;
> -struct pointer_set_t;
>
>
>  /*---------------------------------------------------------------------------
> @@ -692,7 +692,7 @@ typedef tree (*walk_tree_fn) (tree *, int *, void *);
>
>  /* The type of a callback function that represents a custom walk_tree.  */
>  typedef tree (*walk_tree_lh) (tree *, int *, tree (*) (tree *, int *, void *),
> -                             void *, struct pointer_set_t*);
> +                             void *, hash_set<tree> *);
>
>
>  /*---------------------------------------------------------------------------
> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> index df9a6fc..38842e8 100644
> --- a/gcc/tree-eh.c
> +++ b/gcc/tree-eh.c
> @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "flags.h"
>  #include "function.h"
>  #include "except.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "basic-block.h"
>  #include "tree-ssa-alias.h"
> @@ -3578,7 +3579,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>         eh_catch c;
>         edge_iterator ei;
>         edge e;
> -       struct pointer_set_t *seen_values = pointer_set_create ();
> +       hash_set<tree> seen_values;
>
>         /* Collect the labels for a switch.  Zero the post_landing_pad
>            field becase we'll no longer have anything keeping these labels
> @@ -3605,12 +3606,12 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>                    attached to the handler anymore, we remove
>                    the corresponding edge and then we delete unreachable
>                    blocks at the end of this pass.  */
> -               if (! pointer_set_contains (seen_values, TREE_VALUE (flt_node)))
> +               if (! seen_values.contains (TREE_VALUE (flt_node)))
>                   {
>                     tree t = build_case_label (TREE_VALUE (flt_node),
>                                                NULL, lab);
>                     labels.safe_push (t);
> -                   pointer_set_insert (seen_values, TREE_VALUE (flt_node));
> +                   seen_values.add (TREE_VALUE (flt_node));
>                     have_label = true;
>                   }
>
> @@ -3662,7 +3663,6 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>             x = gimple_build_switch (filter, default_label, labels);
>             gsi_insert_before (&gsi, x, GSI_SAME_STMT);
>           }
> -       pointer_set_destroy (seen_values);
>        }
>        break;
>
> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> index 33705b7..6af4912 100644
> --- a/gcc/tree-inline.c
> +++ b/gcc/tree-inline.c
> @@ -1788,7 +1788,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
>              expensive, copy_body can be told to watch for nontrivial
>              changes.  */
>           if (id->statements_to_fold)
> -           pointer_set_insert (id->statements_to_fold, stmt);
> +           id->statements_to_fold->add (stmt);
>
>           /* We're duplicating a CALL_EXPR.  Find any corresponding
>              callgraph edges and update or duplicate them.  */
> @@ -3507,7 +3507,6 @@ inline_forbidden_p (tree fndecl)
>  {
>    struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
>    struct walk_stmt_info wi;
> -  struct pointer_set_t *visited_nodes;
>    basic_block bb;
>    bool forbidden_p = false;
>
> @@ -3518,10 +3517,10 @@ inline_forbidden_p (tree fndecl)
>
>    /* Next, walk the statements of the function looking for
>       constraucts we can't handle, or are non-optimal for inlining.  */
> -  visited_nodes = pointer_set_create ();
> +  hash_set<tree> visited_nodes;
>    memset (&wi, 0, sizeof (wi));
>    wi.info = (void *) fndecl;
> -  wi.pset = visited_nodes;
> +  wi.pset = &visited_nodes;
>
>    FOR_EACH_BB_FN (bb, fun)
>      {
> @@ -3533,7 +3532,6 @@ inline_forbidden_p (tree fndecl)
>         break;
>      }
>
> -  pointer_set_destroy (visited_nodes);
>    return forbidden_p;
>  }
>
> @@ -4531,7 +4529,7 @@ gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
>     in the STATEMENTS pointer set.  */
>
>  static void
> -fold_marked_statements (int first, struct pointer_set_t *statements)
> +fold_marked_statements (int first, hash_set<gimple> *statements)
>  {
>    for (; first < n_basic_blocks_for_fn (cfun); first++)
>      if (BASIC_BLOCK_FOR_FN (cfun, first))
> @@ -4541,7 +4539,7 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
>         for (gsi = gsi_start_bb (BASIC_BLOCK_FOR_FN (cfun, first));
>              !gsi_end_p (gsi);
>              gsi_next (&gsi))
> -         if (pointer_set_contains (statements, gsi_stmt (gsi)))
> +         if (statements->contains (gsi_stmt (gsi)))
>             {
>               gimple old_stmt = gsi_stmt (gsi);
>               tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
> @@ -4642,7 +4640,7 @@ optimize_inline_calls (tree fn)
>    id.transform_return_to_modify = true;
>    id.transform_parameter = true;
>    id.transform_lang_insert_block = NULL;
> -  id.statements_to_fold = pointer_set_create ();
> +  id.statements_to_fold = new hash_set<gimple>;
>
>    push_gimplify_context ();
>
> @@ -4678,7 +4676,7 @@ optimize_inline_calls (tree fn)
>
>    /* Fold queued statements.  */
>    fold_marked_statements (last, id.statements_to_fold);
> -  pointer_set_destroy (id.statements_to_fold);
> +  delete id.statements_to_fold;
>
>    gcc_assert (!id.debug_stmts.exists ());
>
> @@ -4920,7 +4918,6 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
>  {
>    copy_body_data id;
>    struct walk_stmt_info wi;
> -  struct pointer_set_t *visited;
>    gimple_seq copy;
>
>    /* There's nothing to do for NULL_TREE.  */
> @@ -4943,11 +4940,10 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
>
>    /* Walk the tree once to find local labels.  */
>    memset (&wi, 0, sizeof (wi));
> -  visited = pointer_set_create ();
> +  hash_set<tree> visited;
>    wi.info = &id;
> -  wi.pset = visited;
> +  wi.pset = &visited;
>    walk_gimple_seq (seq, mark_local_labels_stmt, NULL, &wi);
> -  pointer_set_destroy (visited);
>
>    copy = gimple_seq_copy (seq);
>
> @@ -5370,7 +5366,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
>    memset (&id, 0, sizeof (id));
>
>    /* Generate a new name for the new version. */
> -  id.statements_to_fold = pointer_set_create ();
> +  id.statements_to_fold = new hash_set<gimple>;
>
>    id.decl_map = pointer_map_create ();
>    id.debug_map = NULL;
> @@ -5541,7 +5537,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
>    free_dominance_info (CDI_POST_DOMINATORS);
>
>    fold_marked_statements (0, id.statements_to_fold);
> -  pointer_set_destroy (id.statements_to_fold);
> +  delete id.statements_to_fold;
>    fold_cond_expr_cond ();
>    delete_unreachable_blocks_update_callgraph (&id);
>    if (id.dst_node->definition)
> diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
> index 2a5daaf..c13e6c7 100644
> --- a/gcc/tree-inline.h
> +++ b/gcc/tree-inline.h
> @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
>  #ifndef GCC_TREE_INLINE_H
>  #define GCC_TREE_INLINE_H
>
> +#include "hash-set.h"
> +
>  struct cgraph_edge;
>
>  /* Indicate the desired behavior wrt call graph edges.  We can either
> @@ -114,7 +116,7 @@ struct copy_body_data
>    void (*transform_lang_insert_block) (tree);
>
>    /* Statements that might be possibly folded.  */
> -  struct pointer_set_t *statements_to_fold;
> +  hash_set<gimple> *statements_to_fold;
>
>    /* Entry basic block to currently copied body.  */
>    basic_block entry_bb;
> diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
> index 185d87c..45c5cf7 100644
> --- a/gcc/tree-nested.c
> +++ b/gcc/tree-nested.c
> @@ -95,7 +95,7 @@ struct nesting_info
>
>    struct pointer_map_t *field_map;
>    struct pointer_map_t *var_map;
> -  struct pointer_set_t *mem_refs;
> +  hash_set<tree *> *mem_refs;
>    bitmap suppress_expansion;
>
>    tree context;
> @@ -732,7 +732,7 @@ create_nesting_tree (struct cgraph_node *cgn)
>    struct nesting_info *info = XCNEW (struct nesting_info);
>    info->field_map = pointer_map_create ();
>    info->var_map = pointer_map_create ();
> -  info->mem_refs = pointer_set_create ();
> +  info->mem_refs = new hash_set<tree *>;
>    info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
>    info->context = cgn->decl;
>
> @@ -1651,7 +1651,7 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
>          fold here, as the chain record type is not yet finalized.  */
>        if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
>           && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
> -       pointer_set_insert (info->mem_refs, tp);
> +       info->mem_refs->add (tp);
>        wi->val_only = save_val_only;
>        break;
>
> @@ -2655,8 +2655,8 @@ remap_vla_decls (tree block, struct nesting_info *root)
>  }
>
>  /* Fold the MEM_REF *E.  */
> -static bool
> -fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED)
> +bool
> +fold_mem_refs (tree *const &e, void *data ATTRIBUTE_UNUSED)
>  {
>    tree *ref_p = CONST_CAST2 (tree *, const tree *, (const tree *)e);
>    *ref_p = fold (*ref_p);
> @@ -2878,7 +2878,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
>      }
>
>    /* Fold the rewritten MEM_REF trees.  */
> -  pointer_set_traverse (root->mem_refs, fold_mem_refs, NULL);
> +  root->mem_refs->traverse<void *, fold_mem_refs> (NULL);
>
>    /* Dump the translated tree function.  */
>    if (dump_file)
> @@ -2933,7 +2933,7 @@ free_nesting_tree (struct nesting_info *root)
>        next = iter_nestinfo_next (node);
>        pointer_map_destroy (node->var_map);
>        pointer_map_destroy (node->field_map);
> -      pointer_set_destroy (node->mem_refs);
> +      delete node->mem_refs;
>        free (node);
>        node = next;
>      }
> diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
> index ca6e014..aee0331 100644
> --- a/gcc/tree-pretty-print.c
> +++ b/gcc/tree-pretty-print.c
> @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "expr.h"
>  #include "tree-pretty-print.h"
>  #include "hashtab.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "gimple-expr.h"
>  #include "cgraph.h"
>  #include "langhooks.h"
> @@ -103,14 +103,14 @@ debug_generic_stmt (tree t)
>  DEBUG_FUNCTION void
>  debug_tree_chain (tree t)
>  {
> -  struct pointer_set_t *seen = pointer_set_create ();
> +  hash_set<tree> seen;
>
>    while (t)
>      {
>        print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
>        fprintf (stderr, " ");
>        t = TREE_CHAIN (t);
> -      if (pointer_set_insert (seen, t))
> +      if (seen.add (t))
>         {
>           fprintf (stderr, "... [cycled back to ");
>           print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
> @@ -119,8 +119,6 @@ debug_tree_chain (tree t)
>         }
>      }
>    fprintf (stderr, "\n");
> -
> -  pointer_set_destroy (seen);
>  }
>
>  /* Prints declaration DECL to the FILE with details specified by FLAGS.  */
> diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
> index 36d68a8..83c1b19 100644
> --- a/gcc/tree-ssa-loop-niter.c
> +++ b/gcc/tree-ssa-loop-niter.c
> @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "basic-block.h"
>  #include "gimple-pretty-print.h"
>  #include "intl.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
> @@ -3281,7 +3282,7 @@ discover_iteration_bound_by_body_walk (struct loop *loop)
>  static void
>  maybe_lower_iteration_bound (struct loop *loop)
>  {
> -  pointer_set_t *not_executed_last_iteration = NULL;
> +  hash_set<gimple> *not_executed_last_iteration = NULL;
>    struct nb_iter_bound *elt;
>    bool found_exit = false;
>    vec<basic_block> queue = vNULL;
> @@ -3300,8 +3301,8 @@ maybe_lower_iteration_bound (struct loop *loop)
>           && wi::ltu_p (elt->bound, loop->nb_iterations_upper_bound))
>         {
>           if (!not_executed_last_iteration)
> -           not_executed_last_iteration = pointer_set_create ();
> -         pointer_set_insert (not_executed_last_iteration, elt->stmt);
> +           not_executed_last_iteration = new hash_set<gimple>;
> +         not_executed_last_iteration->add (elt->stmt);
>         }
>      }
>    if (!not_executed_last_iteration)
> @@ -3327,7 +3328,7 @@ maybe_lower_iteration_bound (struct loop *loop)
>        for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>         {
>           gimple stmt = gsi_stmt (gsi);
> -         if (pointer_set_contains (not_executed_last_iteration, stmt))
> +         if (not_executed_last_iteration->contains (stmt))
>             {
>               stmt_found = true;
>               break;
> @@ -3376,7 +3377,7 @@ maybe_lower_iteration_bound (struct loop *loop)
>      }
>    BITMAP_FREE (visited);
>    queue.release ();
> -  pointer_set_destroy (not_executed_last_iteration);
> +  delete not_executed_last_iteration;
>  }
>
>  /* Records estimates on numbers of iterations of LOOP.  If USE_UNDEFINED_P
> diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
> index 052d760..3185d9a 100644
> --- a/gcc/tree-ssa-phiopt.c
> +++ b/gcc/tree-ssa-phiopt.c
> @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "flags.h"
>  #include "tm_p.h"
>  #include "basic-block.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
> @@ -72,9 +73,9 @@ static bool abs_replacement (basic_block, basic_block,
>  static bool neg_replacement (basic_block, basic_block,
>                              edge, edge, gimple, tree, tree);
>  static bool cond_store_replacement (basic_block, basic_block, edge, edge,
> -                                   struct pointer_set_t *);
> +                                   hash_set<tree> *);
>  static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
> -static struct pointer_set_t * get_non_trapping (void);
> +static hash_set<tree> * get_non_trapping ();
>  static void replace_phi_edge_with_variable (basic_block, edge, gimple, tree);
>  static void hoist_adjacent_loads (basic_block, basic_block,
>                                   basic_block, basic_block);
> @@ -176,7 +177,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
>    basic_block *bb_order;
>    unsigned n, i;
>    bool cfgchanged = false;
> -  struct pointer_set_t *nontrap = 0;
> +  hash_set<tree> *nontrap = 0;
>
>    if (do_store_elim)
>      /* Calculate the set of non-trapping memory accesses.  */
> @@ -363,7 +364,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
>    free (bb_order);
>
>    if (do_store_elim)
> -    pointer_set_destroy (nontrap);
> +    delete nontrap;
>    /* If the CFG has changed, we should cleanup the CFG.  */
>    if (cfgchanged && do_store_elim)
>      {
> @@ -1469,7 +1470,7 @@ ssa_names_hasher::equal (const value_type *n1, const compare_type *n2)
>  class nontrapping_dom_walker : public dom_walker
>  {
>  public:
> -  nontrapping_dom_walker (cdi_direction direction, pointer_set_t *ps)
> +  nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps)
>      : dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {}
>
>    virtual void before_dom_children (basic_block);
> @@ -1484,7 +1485,7 @@ private:
>       the RHS.  */
>    void add_or_mark_expr (basic_block, tree, bool);
>
> -  pointer_set_t *m_nontrapping;
> +  hash_set<tree> *m_nontrapping;
>
>    /* The hash table for remembering what we've seen.  */
>    hash_table<ssa_names_hasher> m_seen_ssa_names;
> @@ -1572,7 +1573,7 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
>          then we can't trap.  */
>        if (found_bb && (((size_t)found_bb->aux) & 1) == 1)
>         {
> -         pointer_set_insert (m_nontrapping, exp);
> +         m_nontrapping->add (exp);
>         }
>        else
>          {
> @@ -1601,11 +1602,11 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
>     It will do a dominator walk over the whole function, and it will
>     make use of the bb->aux pointers.  It returns a set of trees
>     (the MEM_REFs itself) which can't trap.  */
> -static struct pointer_set_t *
> +static hash_set<tree> *
>  get_non_trapping (void)
>  {
>    nt_call_phase = 0;
> -  pointer_set_t *nontrap = pointer_set_create ();
> +  hash_set<tree> *nontrap = new hash_set<tree>;
>    /* We're going to do a dominator walk, so ensure that we have
>       dominance information.  */
>    calculate_dominance_info (CDI_DOMINATORS);
> @@ -1634,7 +1635,7 @@ get_non_trapping (void)
>
>  static bool
>  cond_store_replacement (basic_block middle_bb, basic_block join_bb,
> -                       edge e0, edge e1, struct pointer_set_t *nontrap)
> +                       edge e0, edge e1, hash_set<tree> *nontrap)
>  {
>    gimple assign = last_and_only_stmt (middle_bb);
>    tree lhs, rhs, name, name2;
> @@ -1659,7 +1660,7 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb,
>    /* Prove that we can move the store down.  We could also check
>       TREE_THIS_NOTRAP here, but in that case we also could move stores,
>       whose value is not available readily, which we want to avoid.  */
> -  if (!pointer_set_contains (nontrap, lhs))
> +  if (!nontrap->contains (lhs))
>      return false;
>
>    /* Now we've checked the constraints, so do the transformation:
> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
> index 9807b42..3dee5ba 100644
> --- a/gcc/tree-ssa-threadedge.c
> +++ b/gcc/tree-ssa-threadedge.c
> @@ -30,7 +30,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "function.h"
>  #include "timevar.h"
>  #include "dumpfile.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
>  #include "gimple-expr.h"
> @@ -693,13 +693,13 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>      }
>
>    auto_vec<tree, alloc_count> fewvars;
> -  pointer_set_t *vars = NULL;
> +  hash_set<tree> *vars = NULL;
>
>    /* If we're already starting with 3/4 of alloc_count, go for a
> -     pointer_set, otherwise start with an unordered stack-allocated
> +     hash_set, otherwise start with an unordered stack-allocated
>       VEC.  */
>    if (i * 4 > alloc_count * 3)
> -    vars = pointer_set_create ();
> +    vars = new hash_set<tree>;
>
>    /* Now go through the initial debug stmts in DEST again, this time
>       actually inserting in VARS or FEWVARS.  Don't bother checking for
> @@ -720,7 +720,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>         gcc_unreachable ();
>
>        if (vars)
> -       pointer_set_insert (vars, var);
> +       vars->add (var);
>        else
>         fewvars.quick_push (var);
>      }
> @@ -754,7 +754,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>              or somesuch.  Adding `&& bb == src' to the condition
>              below will preserve all potentially relevant debug
>              notes.  */
> -         if (vars && pointer_set_insert (vars, var))
> +         if (vars && vars->add (var))
>             continue;
>           else if (!vars)
>             {
> @@ -769,11 +769,11 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>                 fewvars.quick_push (var);
>               else
>                 {
> -                 vars = pointer_set_create ();
> +                 vars = new hash_set<tree>;
>                   for (i = 0; i < alloc_count; i++)
> -                   pointer_set_insert (vars, fewvars[i]);
> +                   vars->add (fewvars[i]);
>                   fewvars.release ();
> -                 pointer_set_insert (vars, var);
> +                 vars->add (var);
>                 }
>             }
>
> @@ -786,7 +786,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>    while (bb != src && single_pred_p (bb));
>
>    if (vars)
> -    pointer_set_destroy (vars);
> +    delete vars;
>    else if (fewvars.exists ())
>      fewvars.release ();
>  }
> diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
> index 64259fb..f2578b7 100644
> --- a/gcc/tree-ssa-uninit.c
> +++ b/gcc/tree-ssa-uninit.c
> @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "function.h"
>  #include "gimple-pretty-print.h"
>  #include "bitmap.h"
> +#include "hash-set.h"
>  #include "pointer-set.h"
>  #include "tree-ssa-alias.h"
>  #include "internal-fn.h"
> @@ -60,7 +61,7 @@ along with GCC; see the file COPYING3.  If not see
>  /* Pointer set of potentially undefined ssa names, i.e.,
>     ssa names that are defined by phi with operands that
>     are not defined or potentially undefined.  */
> -static pointer_set_t *possibly_undefined_names = 0;
> +static hash_set<tree> *possibly_undefined_names = 0;
>
>  /* Bit mask handling macros.  */
>  #define MASK_SET_BIT(mask, pos) mask |= (1 << pos)
> @@ -89,7 +90,7 @@ has_undefined_value_p (tree t)
>  {
>    return (ssa_undefined_value_p (t)
>            || (possibly_undefined_names
> -              && pointer_set_contains (possibly_undefined_names, t)));
> +              && possibly_undefined_names->contains (t)));
>  }
>
>
> @@ -648,13 +649,13 @@ find_predicates (pred_chain_union *preds,
>  static void
>  collect_phi_def_edges (gimple phi, basic_block cd_root,
>                         vec<edge> *edges,
> -                       pointer_set_t *visited_phis)
> +                       hash_set<gimple> *visited_phis)
>  {
>    size_t i, n;
>    edge opnd_edge;
>    tree opnd;
>
> -  if (pointer_set_insert (visited_phis, phi))
> +  if (visited_phis->add (phi))
>      return;
>
>    n = gimple_phi_num_args (phi);
> @@ -707,7 +708,6 @@ find_def_preds (pred_chain_union *preds, gimple phi)
>    vec<edge> def_edges = vNULL;
>    bool has_valid_pred = false;
>    basic_block phi_bb, cd_root = 0;
> -  pointer_set_t *visited_phis;
>
>    phi_bb = gimple_bb (phi);
>    /* First find the closest dominating bb to be
> @@ -716,9 +716,8 @@ find_def_preds (pred_chain_union *preds, gimple phi)
>    if (!cd_root)
>      return false;
>
> -  visited_phis = pointer_set_create ();
> -  collect_phi_def_edges (phi, cd_root, &def_edges, visited_phis);
> -  pointer_set_destroy (visited_phis);
> +  hash_set<gimple> visited_phis;
> +  collect_phi_def_edges (phi, cd_root, &def_edges, &visited_phis);
>
>    n = def_edges.length ();
>    if (n == 0)
> @@ -941,7 +940,7 @@ is_use_properly_guarded (gimple use_stmt,
>                           basic_block use_bb,
>                           gimple phi,
>                           unsigned uninit_opnds,
> -                         pointer_set_t *visited_phis);
> +                         hash_set<gimple> *visited_phis);
>
>  /* Returns true if all uninitialized opnds are pruned. Returns false
>     otherwise. PHI is the phi node with uninitialized operands,
> @@ -983,7 +982,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
>                                               gimple flag_def,
>                                               tree boundary_cst,
>                                               enum tree_code cmp_code,
> -                                             pointer_set_t *visited_phis,
> +                                             hash_set<gimple> *visited_phis,
>                                               bitmap *visited_flag_phis)
>  {
>    unsigned i;
> @@ -1153,7 +1152,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
>  static bool
>  use_pred_not_overlap_with_undef_path_pred (pred_chain_union preds,
>                                            gimple phi, unsigned uninit_opnds,
> -                                          pointer_set_t *visited_phis)
> +                                          hash_set<gimple> *visited_phis)
>  {
>    unsigned int i, n;
>    gimple flag_def = 0;
> @@ -1818,11 +1817,11 @@ push_pred (pred_chain_union *norm_preds, pred_info pred)
>
>  inline static void
>  push_to_worklist (tree op, vec<pred_info, va_heap, vl_ptr> *work_list,
> -                  pointer_set_t *mark_set)
> +                  hash_set<tree> *mark_set)
>  {
> -  if (pointer_set_contains (mark_set, op))
> +  if (mark_set->contains (op))
>      return;
> -  pointer_set_insert (mark_set, op);
> +  mark_set->add (op);
>
>    pred_info arg_pred;
>    arg_pred.pred_lhs = op;
> @@ -1907,7 +1906,7 @@ normalize_one_pred_1 (pred_chain_union *norm_preds,
>                        pred_info pred,
>                        enum tree_code and_or_code,
>                        vec<pred_info, va_heap, vl_ptr> *work_list,
> -                     pointer_set_t *mark_set)
> +                     hash_set<tree> *mark_set)
>  {
>    if (!is_neq_zero_form_p (pred))
>      {
> @@ -1987,7 +1986,6 @@ normalize_one_pred (pred_chain_union *norm_preds,
>                      pred_info pred)
>  {
>    vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
> -  pointer_set_t *mark_set = NULL;
>    enum tree_code and_or_code = ERROR_MARK;
>    pred_chain norm_chain = vNULL;
>
> @@ -2015,19 +2013,18 @@ normalize_one_pred (pred_chain_union *norm_preds,
>      }
>
>    work_list.safe_push (pred);
> -  mark_set = pointer_set_create ();
> +  hash_set<tree> mark_set;
>
>    while (!work_list.is_empty ())
>      {
>        pred_info a_pred = work_list.pop ();
>        normalize_one_pred_1 (norm_preds, &norm_chain, a_pred,
> -                            and_or_code, &work_list, mark_set);
> +                            and_or_code, &work_list, &mark_set);
>      }
>    if (and_or_code == BIT_AND_EXPR)
>      norm_preds->safe_push (norm_chain);
>
>    work_list.release ();
> -  pointer_set_destroy (mark_set);
>  }
>
>  static void
> @@ -2035,26 +2032,25 @@ normalize_one_pred_chain (pred_chain_union *norm_preds,
>                            pred_chain one_chain)
>  {
>    vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
> -  pointer_set_t *mark_set = pointer_set_create ();
> +  hash_set<tree> mark_set;
>    pred_chain norm_chain = vNULL;
>    size_t i;
>
>    for (i = 0; i < one_chain.length (); i++)
>      {
>        work_list.safe_push (one_chain[i]);
> -      pointer_set_insert (mark_set, one_chain[i].pred_lhs);
> +      mark_set.add (one_chain[i].pred_lhs);
>      }
>
>    while (!work_list.is_empty ())
>      {
>        pred_info a_pred = work_list.pop ();
>        normalize_one_pred_1 (0, &norm_chain, a_pred,
> -                            BIT_AND_EXPR, &work_list, mark_set);
> +                            BIT_AND_EXPR, &work_list, &mark_set);
>      }
>
>    norm_preds->safe_push (norm_chain);
>    work_list.release ();
> -  pointer_set_destroy (mark_set);
>  }
>
>  /* Normalize predicate chains PREDS and returns the normalized one.  */
> @@ -2112,7 +2108,7 @@ is_use_properly_guarded (gimple use_stmt,
>                           basic_block use_bb,
>                           gimple phi,
>                           unsigned uninit_opnds,
> -                         pointer_set_t *visited_phis)
> +                         hash_set<gimple> *visited_phis)
>  {
>    basic_block phi_bb;
>    pred_chain_union preds = vNULL;
> @@ -2120,7 +2116,7 @@ is_use_properly_guarded (gimple use_stmt,
>    bool has_valid_preds = false;
>    bool is_properly_guarded = false;
>
> -  if (pointer_set_insert (visited_phis, phi))
> +  if (visited_phis->add (phi))
>      return false;
>
>    phi_bb = gimple_bb (phi);
> @@ -2181,7 +2177,7 @@ is_use_properly_guarded (gimple use_stmt,
>  static gimple
>  find_uninit_use (gimple phi, unsigned uninit_opnds,
>                   vec<gimple> *worklist,
> -                pointer_set_t *added_to_worklist)
> +                hash_set<gimple> *added_to_worklist)
>  {
>    tree phi_result;
>    use_operand_p use_p;
> @@ -2192,28 +2188,22 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>
>    FOR_EACH_IMM_USE_FAST (use_p, iter, phi_result)
>      {
> -      pointer_set_t *visited_phis;
>        basic_block use_bb;
>
>        use_stmt = USE_STMT (use_p);
>        if (is_gimple_debug (use_stmt))
>         continue;
>
> -      visited_phis = pointer_set_create ();
> -
>        if (gimple_code (use_stmt) == GIMPLE_PHI)
>         use_bb = gimple_phi_arg_edge (use_stmt,
>                                       PHI_ARG_INDEX_FROM_USE (use_p))->src;
>        else
>         use_bb = gimple_bb (use_stmt);
>
> +      hash_set<gimple> visited_phis;
>        if (is_use_properly_guarded (use_stmt, use_bb, phi, uninit_opnds,
> -                                   visited_phis))
> -        {
> -          pointer_set_destroy (visited_phis);
> -          continue;
> -        }
> -      pointer_set_destroy (visited_phis);
> +                                   &visited_phis))
> +       continue;
>
>        if (dump_file && (dump_flags & TDF_DETAILS))
>          {
> @@ -2226,7 +2216,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>
>        /* Found a phi use that is not guarded,
>           add the phi to the worklist.  */
> -      if (!pointer_set_insert (added_to_worklist, use_stmt))
> +      if (!added_to_worklist->add (use_stmt))
>          {
>            if (dump_file && (dump_flags & TDF_DETAILS))
>              {
> @@ -2235,7 +2225,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>              }
>
>            worklist->safe_push (use_stmt);
> -          pointer_set_insert (possibly_undefined_names, phi_result);
> +          possibly_undefined_names->add (phi_result);
>          }
>      }
>
> @@ -2252,7 +2242,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>
>  static void
>  warn_uninitialized_phi (gimple phi, vec<gimple> *worklist,
> -                        pointer_set_t *added_to_worklist)
> +                        hash_set<gimple> *added_to_worklist)
>  {
>    unsigned uninit_opnds;
>    gimple uninit_use_stmt = 0;
> @@ -2339,7 +2329,6 @@ pass_late_warn_uninitialized::execute (function *fun)
>    basic_block bb;
>    gimple_stmt_iterator gsi;
>    vec<gimple> worklist = vNULL;
> -  pointer_set_t *added_to_worklist;
>
>    calculate_dominance_info (CDI_DOMINATORS);
>    calculate_dominance_info (CDI_POST_DOMINATORS);
> @@ -2350,8 +2339,8 @@ pass_late_warn_uninitialized::execute (function *fun)
>
>    timevar_push (TV_TREE_UNINIT);
>
> -  possibly_undefined_names = pointer_set_create ();
> -  added_to_worklist = pointer_set_create ();
> +  possibly_undefined_names = new hash_set<tree>;
> +  hash_set<gimple> added_to_worklist;
>
>    /* Initialize worklist  */
>    FOR_EACH_BB_FN (bb, fun)
> @@ -2373,7 +2362,7 @@ pass_late_warn_uninitialized::execute (function *fun)
>                 && uninit_undefined_value_p (op))
>               {
>                 worklist.safe_push (phi);
> -               pointer_set_insert (added_to_worklist, phi);
> +               added_to_worklist.add (phi);
>                 if (dump_file && (dump_flags & TDF_DETAILS))
>                   {
>                     fprintf (dump_file, "[WORKLIST]: add to initial list: ");
> @@ -2388,12 +2377,11 @@ pass_late_warn_uninitialized::execute (function *fun)
>      {
>        gimple cur_phi = 0;
>        cur_phi = worklist.pop ();
> -      warn_uninitialized_phi (cur_phi, &worklist, added_to_worklist);
> +      warn_uninitialized_phi (cur_phi, &worklist, &added_to_worklist);
>      }
>
>    worklist.release ();
> -  pointer_set_destroy (added_to_worklist);
> -  pointer_set_destroy (possibly_undefined_names);
> +  delete possibly_undefined_names;
>    possibly_undefined_names = NULL;
>    free_dominance_info (CDI_POST_DOMINATORS);
>    timevar_pop (TV_TREE_UNINIT);
> diff --git a/gcc/tree.c b/gcc/tree.c
> index 6669a84..de1c9b6 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -5143,7 +5143,7 @@ struct free_lang_data_d
>    vec<tree> worklist;
>
>    /* Set of traversed objects.  Used to avoid duplicate visits.  */
> -  struct pointer_set_t *pset;
> +  hash_set<tree> *pset;
>
>    /* Array of symbols to process with free_lang_data_in_decl.  */
>    vec<tree> decls;
> @@ -5208,7 +5208,7 @@ add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
>  static inline void
>  fld_worklist_push (tree t, struct free_lang_data_d *fld)
>  {
> -  if (t && !is_lang_specific (t) && !pointer_set_contains (fld->pset, t))
> +  if (t && !is_lang_specific (t) && !fld->pset->contains (t))
>      fld->worklist.safe_push ((t));
>  }
>
> @@ -5374,7 +5374,7 @@ find_decls_types (tree t, struct free_lang_data_d *fld)
>  {
>    while (1)
>      {
> -      if (!pointer_set_contains (fld->pset, t))
> +      if (!fld->pset->contains (t))
>         walk_tree (&t, find_decls_types_r, fld, fld->pset);
>        if (fld->worklist.is_empty ())
>         break;
> @@ -5584,7 +5584,7 @@ free_lang_data_in_cgraph (void)
>    alias_pair *p;
>
>    /* Initialize sets and arrays to store referenced decls and types.  */
> -  fld.pset = pointer_set_create ();
> +  fld.pset = new hash_set<tree>;
>    fld.worklist.create (0);
>    fld.decls.create (100);
>    fld.types.create (100);
> @@ -5614,7 +5614,7 @@ free_lang_data_in_cgraph (void)
>    FOR_EACH_VEC_ELT (fld.types, i, t)
>      free_lang_data_in_type (t);
>
> -  pointer_set_destroy (fld.pset);
> +  delete fld.pset;
>    fld.worklist.release ();
>    fld.decls.release ();
>    fld.types.release ();
> @@ -10819,7 +10819,7 @@ num_ending_zeros (const_tree x)
>
>  static tree
>  walk_type_fields (tree type, walk_tree_fn func, void *data,
> -                 struct pointer_set_t *pset, walk_tree_lh lh)
> +                 hash_set<tree> *pset, walk_tree_lh lh)
>  {
>    tree result = NULL_TREE;
>
> @@ -10901,7 +10901,7 @@ walk_type_fields (tree type, walk_tree_fn func, void *data,
>
>  tree
>  walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
> -            struct pointer_set_t *pset, walk_tree_lh lh)
> +            hash_set<tree> *pset, walk_tree_lh lh)
>  {
>    enum tree_code code;
>    int walk_subtrees;
> @@ -10922,7 +10922,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
>
>    /* Don't walk the same tree twice, if the user has requested
>       that we avoid doing so.  */
> -  if (pset && pointer_set_insert (pset, *tp))
> +  if (pset && pset->add (*tp))
>      return NULL_TREE;
>
>    /* Call the function.  */
> @@ -11237,11 +11237,9 @@ walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data,
>                                 walk_tree_lh lh)
>  {
>    tree result;
> -  struct pointer_set_t *pset;
>
> -  pset = pointer_set_create ();
> -  result = walk_tree_1 (tp, func, data, pset, lh);
> -  pointer_set_destroy (pset);
> +  hash_set<tree> pset;
> +  result = walk_tree_1 (tp, func, data, &pset, lh);
>    return result;
>  }
>
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 2bb6d1f..c9f978a 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>  #define GCC_TREE_H
>
>  #include "tree-core.h"
> +#include "hash-set.h"
>  #include "wide-int.h"
>  #include "inchash.h"
>
> @@ -4328,7 +4329,7 @@ extern void using_eh_for_cleanups (void);
>  extern bool using_eh_for_cleanups_p (void);
>  extern const char *get_tree_code_name (enum tree_code);
>  extern void set_call_expr_flags (tree, int);
> -extern tree walk_tree_1 (tree*, walk_tree_fn, void*, struct pointer_set_t*,
> +extern tree walk_tree_1 (tree*, walk_tree_fn, void*, hash_set<tree>*,
>                          walk_tree_lh);
>  extern tree walk_tree_without_duplicates_1 (tree*, walk_tree_fn, void*,
>                                             walk_tree_lh);
> diff --git a/gcc/value-prof.c b/gcc/value-prof.c
> index 3e51539..ffdee65 100644
> --- a/gcc/value-prof.c
> +++ b/gcc/value-prof.c
> @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "data-streamer.h"
>  #include "builtins.h"
>  #include "tree-nested.h"
> +#include "hash-set.h"
>
>  /* In this file value profile based optimizations are placed.  Currently the
>     following optimizations are implemented (for more detailed descriptions
> @@ -515,10 +516,10 @@ static bool error_found = false;
>  static int
>  visit_hist (void **slot, void *data)
>  {
> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> +  hash_set<histogram_value> *visited = (hash_set<histogram_value> *) data;
>    histogram_value hist = *(histogram_value *) slot;
>
> -  if (!pointer_set_contains (visited, hist)
> +  if (!visited->contains (hist)
>        && hist->type != HIST_TYPE_TIME_PROFILE)
>      {
>        error ("dead histogram");
> @@ -538,10 +539,9 @@ verify_histograms (void)
>    basic_block bb;
>    gimple_stmt_iterator gsi;
>    histogram_value hist;
> -  struct pointer_set_t *visited_hists;
>
>    error_found = false;
> -  visited_hists = pointer_set_create ();
> +  hash_set<histogram_value> visited_hists;
>    FOR_EACH_BB_FN (bb, cfun)
>      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>        {
> @@ -558,12 +558,11 @@ verify_histograms (void)
>                 dump_histogram_value (stderr, hist);
>                 error_found = true;
>               }
> -            pointer_set_insert (visited_hists, hist);
> +            visited_hists.add (hist);
>           }
>        }
>    if (VALUE_HISTOGRAMS (cfun))
> -    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, visited_hists);
> -  pointer_set_destroy (visited_hists);
> +    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, &visited_hists);
>    if (error_found)
>      internal_error ("verify_histograms failed");
>  }
> diff --git a/gcc/varasm.c b/gcc/varasm.c
> index 819ec26..9d8602b 100644
> --- a/gcc/varasm.c
> +++ b/gcc/varasm.c
> @@ -51,7 +51,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "common/common-target.h"
>  #include "targhooks.h"
>  #include "cgraph.h"
> -#include "pointer-set.h"
> +#include "hash-set.h"
>  #include "asan.h"
>  #include "basic-block.h"
>
> @@ -2249,7 +2249,7 @@ static bool pending_assemble_externals_processed;
>
>  /* Avoid O(external_decls**2) lookups in the pending_assemble_externals
>     TREE_LIST in assemble_external.  */
> -static struct pointer_set_t *pending_assemble_externals_set;
> +static hash_set<tree> *pending_assemble_externals_set;
>
>  /* True if DECL is a function decl for which no out-of-line copy exists.
>     It is assumed that DECL's assembler name has been set.  */
> @@ -2303,7 +2303,7 @@ process_pending_assemble_externals (void)
>
>    pending_assemble_externals = 0;
>    pending_assemble_externals_processed = true;
> -  pointer_set_destroy (pending_assemble_externals_set);
> +  delete pending_assemble_externals_set;
>  #endif
>  }
>
> @@ -2361,7 +2361,7 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
>        return;
>      }
>
> -  if (! pointer_set_insert (pending_assemble_externals_set, decl))
> +  if (! pending_assemble_externals_set->add (decl))
>      pending_assemble_externals = tree_cons (NULL, decl,
>                                             pending_assemble_externals);
>  #endif
> @@ -5991,7 +5991,7 @@ init_varasm_once (void)
>      readonly_data_section = text_section;
>
>  #ifdef ASM_OUTPUT_EXTERNAL
> -  pending_assemble_externals_set = pointer_set_create ();
> +  pending_assemble_externals_set = new hash_set<tree>;
>  #endif
>  }
>
> diff --git a/gcc/varpool.c b/gcc/varpool.c
> index 74117e2..558767f 100644
> --- a/gcc/varpool.c
> +++ b/gcc/varpool.c
> @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-ssa-alias.h"
>  #include "gimple.h"
>  #include "lto-streamer.h"
> +#include "hash-set.h"
>
>  const char * const tls_model_names[]={"none", "tls-emulated", "tls-real",
>                                       "tls-global-dynamic", "tls-local-dynamic",
> @@ -576,7 +577,7 @@ varpool_remove_unreferenced_decls (void)
>    varpool_node *first = (varpool_node *)(void *)1;
>    int i;
>    struct ipa_ref *ref = NULL;
> -  struct pointer_set_t *referenced = pointer_set_create ();
> +  hash_set<varpool_node *> referenced;
>
>    if (seen_error ())
>      return;
> @@ -623,7 +624,7 @@ varpool_remove_unreferenced_decls (void)
>               && vnode->analyzed)
>             enqueue_node (vnode, &first);
>           else
> -           pointer_set_insert (referenced, node);
> +           referenced.add (node);
>         }
>      }
>    if (cgraph_dump_file)
> @@ -635,13 +636,13 @@ varpool_remove_unreferenced_decls (void)
>         {
>            if (cgraph_dump_file)
>             fprintf (cgraph_dump_file, " %s", node->asm_name ());
> -         if (pointer_set_contains (referenced, node))
> +         if (referenced.contains (node))
>             node->remove_initializer ();
>           else
>             node->remove ();
>         }
>      }
> -  pointer_set_destroy (referenced);
> +
>    if (cgraph_dump_file)
>      fprintf (cgraph_dump_file, "\n");
>  }
> --
> 2.0.1
>
Trevor Saunders Aug. 4, 2014, 5:15 p.m. UTC | #4
On Sat, Aug 02, 2014 at 03:44:17PM -0700, Andrew Pinski wrote:
> On Tue, Jul 29, 2014 at 5:50 AM,  <tsaunders@mozilla.com> wrote:
> > From: Trevor Saunders <tsaunders@mozilla.com>
> >
> > Hi,
> >
> > this adds a hash_set wrapper around hash_table, and then replaces usage of pointer_set with it.
> >
> > bootstrapped +regtested on x86_64-unknown-linux-gnu, ok?
> >
> > Trev
> >
> > ada/
> >
> >         * gcc-interface/trans.c: Use hash_set instead of pointer_set.
> >
> > c-family/
> >
> >         * c-gimplify.c: Use hash_set instead of pointer_set.
> >
> > c/
> >
> >         * c-decl.c: Use hash_set instead of pointer_set.
> >
> > cp/
> >
> >         * class.c, cp-gimplify.c, cp-tree.h, decl.c, decl2.c, error.c,
> >         method.c, name-lookup.c, pt.c, semantics.c, tree.c: Use hash_set
> >         instead of pointer_set.
> >
> > fortran/
> >
> >         * openmp.c, trans-decl.c: Use hash_set instead of pointer_set.
> >
> > gcc/
> >
> >         * hash-set.h: new File.
> >         * cfgexpand.c, cfgloop.c, cgraph.c, cgraphbuild.c, cgraphunit.c,
> >         cprop.c, cse.c, gimple-walk.c, gimple-walk.h, gimplify.c, godump.c,
> >         ipa-devirt.c, ipa-pure-const.c, ipa-visibility.c, ipa.c, lto-cgraph.c,
> >         lto-streamer-out.c, stmt.c, tree-cfg.c, tree-core.h, tree-eh.c,
> >         tree-inline.c, tree-inline.h, tree-nested.c, tree-pretty-print.c,
> >         tree-ssa-loop-niter.c, tree-ssa-phiopt.c, tree-ssa-threadedge.c,
> >         tree-ssa-uninit.c, tree.c, tree.h, value-prof.c, varasm.c,
> >         varpool.c: Use hash_set instead of pointer_set.
> 
> 
> This changelog is less than useful and really does not follow the
> GCC/GNU coding style.  Please expand and place all functions which are

I'm pretty sure its written somewhere that format is ok, and there's
precedent for it.  Note the update all callers rule could also be used
to just write

	(pointer_map_create): Rename to
	(hash_set::hash_set): and update all callers.

now I agree its useless, but that's just the nature of something
that just summarizes the diff.  it'd be no more useful if it
included the headers for diff -p with some regexs to get rid of
the line markers.

> changed in it.  I use ChangeLog entries when merging in code to see
> which of the merged code I need to pick up.

just use a merge tool that isn't total garbage and let it handle
everything but actual conflicts? or failing that just use diff -p that's
going to be just about as accurate as what humans can reasonably be expected
to produce.

Trev

> 
> Thanks,
> Andrew Pinski
> 
> 
> 
> >
> > lto/
> >
> >         * lto-partition.c, lto-partition.h: Use hash_set instead of
> >         pointer_set.
> > diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
> > index f42ac7f..6961838 100644
> > --- a/gcc/ada/gcc-interface/trans.c
> > +++ b/gcc/ada/gcc-interface/trans.c
> > @@ -36,7 +36,7 @@
> >  #include "output.h"
> >  #include "libfuncs.h"  /* For set_stack_check_libfunc.  */
> >  #include "tree-iterator.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "gimple-expr.h"
> >  #include "gimplify.h"
> >  #include "bitmap.h"
> > @@ -3054,7 +3054,7 @@ struct nrv_data
> >    bitmap nrv;
> >    tree result;
> >    Node_Id gnat_ret;
> > -  struct pointer_set_t *visited;
> > +  hash_set<tree> *visited;
> >  };
> >
> >  /* Return true if T is a Named Return Value.  */
> > @@ -3188,7 +3188,7 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
> >    /* Avoid walking into the same tree more than once.  Unfortunately, we
> >       can't just use walk_tree_without_duplicates because it would only
> >       call us for the first occurrence of NRVs in the function body.  */
> > -  if (pointer_set_insert (dp->visited, *tp))
> > +  if (dp->visited->add (*tp))
> >      *walk_subtrees = 0;
> >
> >    return NULL_TREE;
> > @@ -3328,7 +3328,7 @@ finalize_nrv_unc_r (tree *tp, int *walk_subtrees, void *data)
> >    /* Avoid walking into the same tree more than once.  Unfortunately, we
> >       can't just use walk_tree_without_duplicates because it would only
> >       call us for the first occurrence of NRVs in the function body.  */
> > -  if (pointer_set_insert (dp->visited, *tp))
> > +  if (dp->visited->add (*tp))
> >      *walk_subtrees = 0;
> >
> >    return NULL_TREE;
> > @@ -3376,13 +3376,13 @@ finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret
> >    data.nrv = nrv;
> >    data.result = DECL_RESULT (fndecl);
> >    data.gnat_ret = gnat_ret;
> > -  data.visited = pointer_set_create ();
> > +  data.visited = new hash_set<tree>;
> >    if (TYPE_RETURN_UNCONSTRAINED_P (TREE_TYPE (fndecl)))
> >      func = finalize_nrv_unc_r;
> >    else
> >      func = finalize_nrv_r;
> >    walk_tree (&DECL_SAVED_TREE (fndecl), func, &data, NULL);
> > -  pointer_set_destroy (data.visited);
> > +  delete data.visited;
> >  }
> >
> >  /* Return true if RET_VAL can be used as a Named Return Value for the
> > diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
> > index 2b5ce5b..4898217 100644
> > --- a/gcc/c-family/c-gimplify.c
> > +++ b/gcc/c-family/c-gimplify.c
> > @@ -74,7 +74,7 @@ along with GCC; see the file COPYING3.  If not see
> >  static tree
> >  ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
> >  {
> > -  struct pointer_set_t *pset = (struct pointer_set_t *) data;
> > +  hash_set<tree> *pset = (hash_set<tree> *) data;
> >
> >    /* Since walk_tree doesn't call the callback function on the decls
> >       in BIND_EXPR_VARS, we have to walk them manually.  */
> > @@ -116,10 +116,9 @@ c_genericize (tree fndecl)
> >
> >    if (flag_sanitize & SANITIZE_BOUNDS)
> >      {
> > -      struct pointer_set_t *pset = pointer_set_create ();
> > -      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, pset,
> > -                pset);
> > -      pointer_set_destroy (pset);
> > +      hash_set<tree> pset;
> > +      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
> > +                &pset);
> >      }
> >
> >    /* Dump the C-specific tree IR.  */
> > diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> > index 2a4b439..050ddff 100644
> > --- a/gcc/c/c-decl.c
> > +++ b/gcc/c/c-decl.c
> > @@ -59,7 +59,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "cgraph.h"
> >  #include "hash-table.h"
> >  #include "langhooks-def.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "plugin.h"
> >  #include "c-family/c-ada-spec.h"
> >  #include "cilk.h"
> > @@ -7221,17 +7221,17 @@ warn_cxx_compat_finish_struct (tree fieldlist)
> >    if (!struct_parse_info->typedefs_seen.is_empty ()
> >        && fieldlist != NULL_TREE)
> >      {
> > -      /* Use a pointer_set using the name of the typedef.  We can use
> > -        a pointer_set because identifiers are interned.  */
> > -      struct pointer_set_t *tset = pointer_set_create ();
> > +      /* Use a hash_set<tree> using the name of the typedef.  We can use
> > +        a hash_set<tree> because identifiers are interned.  */
> > +      hash_set<tree> tset;
> >
> >        FOR_EACH_VEC_ELT (struct_parse_info->typedefs_seen, ix, x)
> > -       pointer_set_insert (tset, DECL_NAME (x));
> > +       tset.add (DECL_NAME (x));
> >
> >        for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
> >         {
> >           if (DECL_NAME (x) != NULL_TREE
> > -             && pointer_set_contains (tset, DECL_NAME (x)))
> > +             && tset.contains (DECL_NAME (x)))
> >             {
> >               warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
> >                           ("using %qD as both field and typedef name is "
> > @@ -7241,8 +7241,6 @@ warn_cxx_compat_finish_struct (tree fieldlist)
> >                  the typedef name is used.  */
> >             }
> >         }
> > -
> > -      pointer_set_destroy (tset);
> >      }
> >
> >    /* For each field which has a binding and which was not defined in
> > @@ -8189,7 +8187,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >    struct c_binding *b;
> >    tree parm, decl, last;
> >    tree parmids = arg_info->parms;
> > -  struct pointer_set_t *seen_args = pointer_set_create ();
> > +  hash_set<tree> seen_args;
> >
> >    if (!in_system_header_at (input_location))
> >      warning_at (DECL_SOURCE_LOCATION (fndecl),
> > @@ -8220,7 +8218,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >                       "%qD declared as a non-parameter", decl);
> >           /* If the declaration is already marked, we have a duplicate
> >              name.  Complain and ignore the duplicate.  */
> > -         else if (pointer_set_contains (seen_args, decl))
> > +         else if (seen_args.contains (decl))
> >             {
> >               error_at (DECL_SOURCE_LOCATION (decl),
> >                         "multiple parameters named %qD", decl);
> > @@ -8269,7 +8267,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >         }
> >
> >        TREE_PURPOSE (parm) = decl;
> > -      pointer_set_insert (seen_args, decl);
> > +      seen_args.add (decl);
> >      }
> >
> >    /* Now examine the parms chain for incomplete declarations
> > @@ -8289,7 +8287,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >           TREE_TYPE (parm) = error_mark_node;
> >         }
> >
> > -      if (!pointer_set_contains (seen_args, parm))
> > +      if (!seen_args.contains (parm))
> >         {
> >           error_at (DECL_SOURCE_LOCATION (parm),
> >                     "declaration for parameter %qD but no such parameter",
> > @@ -8324,8 +8322,6 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >        DECL_CHAIN (last) = 0;
> >      }
> >
> > -  pointer_set_destroy (seen_args);
> > -
> >    /* If there was a previous prototype,
> >       set the DECL_ARG_TYPE of each argument according to
> >       the type previously specified, and report any mismatches.  */
> > diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
> > index 2f0ae71..b20be10 100644
> > --- a/gcc/cfgexpand.c
> > +++ b/gcc/cfgexpand.c
> > @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "expr.h"
> >  #include "langhooks.h"
> >  #include "bitmap.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> > @@ -594,7 +595,7 @@ stack_var_cmp (const void *a, const void *b)
> >  static void
> >  add_partitioned_vars_to_ptset (struct pt_solution *pt,
> >                                struct pointer_map_t *decls_to_partitions,
> > -                              struct pointer_set_t *visited, bitmap temp)
> > +                              hash_set<bitmap> *visited, bitmap temp)
> >  {
> >    bitmap_iterator bi;
> >    unsigned i;
> > @@ -604,7 +605,7 @@ add_partitioned_vars_to_ptset (struct pt_solution *pt,
> >        || pt->vars == NULL
> >        /* The pointed-to vars bitmap is shared, it is enough to
> >          visit it once.  */
> > -      || pointer_set_insert (visited, pt->vars))
> > +      || visited->add (pt->vars))
> >      return;
> >
> >    bitmap_clear (temp);
> > @@ -684,7 +685,7 @@ update_alias_info_with_stack_vars (void)
> >    if (decls_to_partitions)
> >      {
> >        unsigned i;
> > -      struct pointer_set_t *visited = pointer_set_create ();
> > +      hash_set<bitmap> visited;
> >        bitmap temp = BITMAP_ALLOC (&stack_var_bitmap_obstack);
> >
> >        for (i = 1; i < num_ssa_names; i++)
> > @@ -696,13 +697,12 @@ update_alias_info_with_stack_vars (void)
> >               && POINTER_TYPE_P (TREE_TYPE (name))
> >               && ((pi = SSA_NAME_PTR_INFO (name)) != NULL))
> >             add_partitioned_vars_to_ptset (&pi->pt, decls_to_partitions,
> > -                                          visited, temp);
> > +                                          &visited, temp);
> >         }
> >
> >        add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped,
> > -                                    decls_to_partitions, visited, temp);
> > +                                    decls_to_partitions, &visited, temp);
> >
> > -      pointer_set_destroy (visited);
> >        pointer_map_destroy (decls_to_partitions);
> >        BITMAP_FREE (temp);
> >      }
> > diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
> > index 73f79ef..8f7e265 100644
> > --- a/gcc/cfgloop.c
> > +++ b/gcc/cfgloop.c
> > @@ -28,7 +28,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "diagnostic-core.h"
> >  #include "flags.h"
> >  #include "tree.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> >  #include "gimple-expr.h"
> > @@ -650,11 +650,11 @@ find_subloop_latch_edge (struct loop *loop)
> >  /* Callback for make_forwarder_block.  Returns true if the edge E is marked
> >     in the set MFB_REIS_SET.  */
> >
> > -static struct pointer_set_t *mfb_reis_set;
> > +static hash_set<edge> *mfb_reis_set;
> >  static bool
> >  mfb_redirect_edges_in_set (edge e)
> >  {
> > -  return pointer_set_contains (mfb_reis_set, e);
> > +  return mfb_reis_set->contains (e);
> >  }
> >
> >  /* Creates a subloop of LOOP with latch edge LATCH.  */
> > @@ -666,15 +666,15 @@ form_subloop (struct loop *loop, edge latch)
> >    edge e, new_entry;
> >    struct loop *new_loop;
> >
> > -  mfb_reis_set = pointer_set_create ();
> > +  mfb_reis_set = new hash_set<edge>;
> >    FOR_EACH_EDGE (e, ei, loop->header->preds)
> >      {
> >        if (e != latch)
> > -       pointer_set_insert (mfb_reis_set, e);
> > +       mfb_reis_set->add (e);
> >      }
> >    new_entry = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
> >                                     NULL);
> > -  pointer_set_destroy (mfb_reis_set);
> > +  delete mfb_reis_set;
> >
> >    loop->header = new_entry->src;
> >
> > @@ -705,12 +705,12 @@ merge_latch_edges (struct loop *loop)
> >        if (dump_file)
> >         fprintf (dump_file, "Merged latch edges of loop %d\n", loop->num);
> >
> > -      mfb_reis_set = pointer_set_create ();
> > +      mfb_reis_set = new hash_set<edge>;
> >        FOR_EACH_VEC_ELT (latches, i, e)
> > -       pointer_set_insert (mfb_reis_set, e);
> > +       mfb_reis_set->add (e);
> >        latch = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
> >                                     NULL);
> > -      pointer_set_destroy (mfb_reis_set);
> > +      delete mfb_reis_set;
> >
> >        loop->header = latch->dest;
> >        loop->latch = latch->src;
> > diff --git a/gcc/cgraph.c b/gcc/cgraph.c
> > index a5d0749..7c72399 100644
> > --- a/gcc/cgraph.c
> > +++ b/gcc/cgraph.c
> > @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "tree-inline.h"
> >  #include "langhooks.h"
> >  #include "hashtab.h"
> > +#include "hash-set.h"
> >  #include "toplev.h"
> >  #include "flags.h"
> >  #include "debug.h"
> > @@ -2871,7 +2872,7 @@ cgraph_node::verify_node (void)
> >      {
> >        if (this_cfun->cfg)
> >         {
> > -         pointer_set_t *stmts = pointer_set_create ();
> > +         hash_set<gimple> stmts;
> >           int i;
> >           struct ipa_ref *ref = NULL;
> >
> > @@ -2881,13 +2882,13 @@ cgraph_node::verify_node (void)
> >             {
> >               for (gsi = gsi_start_phis (this_block);
> >                    !gsi_end_p (gsi); gsi_next (&gsi))
> > -               pointer_set_insert (stmts, gsi_stmt (gsi));
> > +               stmts.add (gsi_stmt (gsi));
> >               for (gsi = gsi_start_bb (this_block);
> >                    !gsi_end_p (gsi);
> >                    gsi_next (&gsi))
> >                 {
> >                   gimple stmt = gsi_stmt (gsi);
> > -                 pointer_set_insert (stmts, stmt);
> > +                 stmts.add (stmt);
> >                   if (is_gimple_call (stmt))
> >                     {
> >                       struct cgraph_edge *e = get_edge (stmt);
> > @@ -2931,13 +2932,12 @@ cgraph_node::verify_node (void)
> >                 }
> >               }
> >             for (i = 0; iterate_reference (i, ref); i++)
> > -             if (ref->stmt && !pointer_set_contains (stmts, ref->stmt))
> > +             if (ref->stmt && !stmts.contains (ref->stmt))
> >                 {
> >                   error ("reference to dead statement");
> >                   cgraph_debug_gimple_stmt (this_cfun, ref->stmt);
> >                   error_found = true;
> >                 }
> > -           pointer_set_destroy (stmts);
> >         }
> >        else
> >         /* No CFG available?!  */
> > diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
> > index 91811d7..a04958f 100644
> > --- a/gcc/cgraphbuild.c
> > +++ b/gcc/cgraphbuild.c
> > @@ -322,7 +322,6 @@ pass_build_cgraph_edges::execute (function *fun)
> >  {
> >    basic_block bb;
> >    struct cgraph_node *node = cgraph_node::get (current_function_decl);
> > -  struct pointer_set_t *visited_nodes = pointer_set_create ();
> >    gimple_stmt_iterator gsi;
> >    tree decl;
> >    unsigned ix;
> > @@ -386,7 +385,6 @@ pass_build_cgraph_edges::execute (function *fun)
> >        varpool_node::finalize_decl (decl);
> >    record_eh_tables (node, fun);
> >
> > -  pointer_set_destroy (visited_nodes);
> >    return 0;
> >  }
> >
> > @@ -405,15 +403,14 @@ make_pass_build_cgraph_edges (gcc::context *ctxt)
> >  void
> >  record_references_in_initializer (tree decl, bool only_vars)
> >  {
> > -  struct pointer_set_t *visited_nodes = pointer_set_create ();
> >    varpool_node *node = varpool_node::get_create (decl);
> > +  hash_set<tree> visited_nodes;
> >    struct record_reference_ctx ctx = {false, NULL};
> >
> >    ctx.varpool_node = node;
> >    ctx.only_vars = only_vars;
> >    walk_tree (&DECL_INITIAL (decl), record_reference,
> > -             &ctx, visited_nodes);
> > -  pointer_set_destroy (visited_nodes);
> > +             &ctx, &visited_nodes);
> >  }
> >
> >  /* Rebuild cgraph edges for current function node.  This needs to be run after
> > diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> > index 3080b9a..220b953 100644
> > --- a/gcc/cgraphunit.c
> > +++ b/gcc/cgraphunit.c
> > @@ -845,7 +845,7 @@ varpool_node::finalize_decl (tree decl)
> >     avoid udplicate work.  */
> >
> >  static void
> > -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> > +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
> >                                struct cgraph_edge *edge)
> >  {
> >    unsigned int i;
> > @@ -855,8 +855,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> >      = possible_polymorphic_call_targets
> >         (edge, &final, &cache_token);
> >
> > -  if (!pointer_set_insert (reachable_call_targets,
> > -                          cache_token))
> > +  if (!reachable_call_targets->add (cache_token))
> >      {
> >        if (cgraph_dump_file)
> >         dump_possible_polymorphic_call_targets
> > @@ -936,7 +935,7 @@ analyze_functions (void)
> >    struct cgraph_node *first_handled = first_analyzed;
> >    static varpool_node *first_analyzed_var;
> >    varpool_node *first_handled_var = first_analyzed_var;
> > -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> > +  hash_set<void *> reachable_call_targets;
> >
> >    symtab_node *node;
> >    symtab_node *next;
> > @@ -1035,7 +1034,7 @@ analyze_functions (void)
> >                     {
> >                       next = edge->next_callee;
> >                       if (edge->indirect_info->polymorphic)
> > -                       walk_polymorphic_call_targets (reachable_call_targets,
> > +                       walk_polymorphic_call_targets (&reachable_call_targets,
> >                                                        edge);
> >                     }
> >                 }
> > @@ -1123,7 +1122,6 @@ analyze_functions (void)
> >        symtab_node::dump_table (cgraph_dump_file);
> >      }
> >    bitmap_obstack_release (NULL);
> > -  pointer_set_destroy (reachable_call_targets);
> >    ggc_collect ();
> >    /* Initialize assembler name hash, in particular we want to trigger C++
> >       mangling and same body alias creation before we free DECL_ARGUMENTS
> > diff --git a/gcc/cp/class.c b/gcc/cp/class.c
> > index 0f611e1..d9b34f7 100644
> > --- a/gcc/cp/class.c
> > +++ b/gcc/cp/class.c
> > @@ -5359,15 +5359,15 @@ finalize_literal_type_property (tree t)
> >  void
> >  explain_non_literal_class (tree t)
> >  {
> > -  static struct pointer_set_t *diagnosed;
> > +  static hash_set<tree> *diagnosed;
> >
> >    if (!CLASS_TYPE_P (t))
> >      return;
> >    t = TYPE_MAIN_VARIANT (t);
> >
> >    if (diagnosed == NULL)
> > -    diagnosed = pointer_set_create ();
> > -  if (pointer_set_insert (diagnosed, t) != 0)
> > +    diagnosed = new hash_set<tree>;
> > +  if (diagnosed->add (t))
> >      /* Already explained.  */
> >      return;
> >
> > diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
> > index a35177b..3cfcbc6 100644
> > --- a/gcc/cp/cp-gimplify.c
> > +++ b/gcc/cp/cp-gimplify.c
> > @@ -871,7 +871,7 @@ omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
> >
> >  struct cp_genericize_data
> >  {
> > -  struct pointer_set_t *p_set;
> > +  hash_set<tree> *p_set;
> >    vec<tree> bind_expr_stack;
> >    struct cp_genericize_omp_taskreg *omp_ctx;
> >  };
> > @@ -884,7 +884,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
> >  {
> >    tree stmt = *stmt_p;
> >    struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
> > -  struct pointer_set_t *p_set = wtd->p_set;
> > +  hash_set<tree> *p_set = wtd->p_set;
> >
> >    /* If in an OpenMP context, note var uses.  */
> >    if (__builtin_expect (wtd->omp_ctx != NULL, 0)
> > @@ -924,7 +924,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
> >      }
> >
> >    /* Other than invisiref parms, don't walk the same tree twice.  */
> > -  if (pointer_set_contains (p_set, stmt))
> > +  if (p_set->contains (stmt))
> >      {
> >        *walk_subtrees = 0;
> >        return NULL_TREE;
> > @@ -1199,7 +1199,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
> >        return NULL;
> >      }
> >
> > -  pointer_set_insert (p_set, *stmt_p);
> > +  p_set->add (*stmt_p);
> >
> >    return NULL;
> >  }
> > @@ -1211,11 +1211,11 @@ cp_genericize_tree (tree* t_p)
> >  {
> >    struct cp_genericize_data wtd;
> >
> > -  wtd.p_set = pointer_set_create ();
> > +  wtd.p_set = new hash_set<tree>;
> >    wtd.bind_expr_stack.create (0);
> >    wtd.omp_ctx = NULL;
> >    cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
> > -  pointer_set_destroy (wtd.p_set);
> > +  delete wtd.p_set;
> >    wtd.bind_expr_stack.release ();
> >  }
> >
> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> > index 0c0d804..622de9c 100644
> > --- a/gcc/cp/cp-tree.h
> > +++ b/gcc/cp/cp-tree.h
> > @@ -6028,7 +6028,7 @@ extern void verify_stmt_tree                      (tree);
> >  extern linkage_kind decl_linkage               (tree);
> >  extern duration_kind decl_storage_duration     (tree);
> >  extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
> > -                             void*, struct pointer_set_t*);
> > +                             void*, hash_set<tree> *);
> >  #define cp_walk_tree(tp,func,data,pset) \
> >         walk_tree_1 (tp, func, data, pset, cp_walk_subtrees)
> >  #define cp_walk_tree_without_duplicates(tp,func,data) \
> > diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> > index aafb917..f70684f 100644
> > --- a/gcc/cp/decl.c
> > +++ b/gcc/cp/decl.c
> > @@ -8198,7 +8198,7 @@ check_static_variable_definition (tree decl, tree type)
> >  static tree
> >  stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
> >  {
> > -  struct pointer_set_t *pset = (struct pointer_set_t *)data;
> > +  hash_set<tree> *pset = (hash_set<tree> *)data;
> >    tree expr = *expr_p;
> >    if (TREE_CODE (expr) == SAVE_EXPR)
> >      {
> > @@ -8218,10 +8218,9 @@ stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
> >  static void
> >  stabilize_vla_size (tree size)
> >  {
> > -  struct pointer_set_t *pset = pointer_set_create ();
> > +  hash_set<tree> pset;
> >    /* Break out any function calls into temporary variables.  */
> > -  cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
> > -  pointer_set_destroy (pset);
> > +  cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
> >  }
> >
> >  /* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
> > diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
> > index 8fa3145..d79665e 100644
> > --- a/gcc/cp/decl2.c
> > +++ b/gcc/cp/decl2.c
> > @@ -3938,11 +3938,11 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
> >     supported, collect and return all the functions for which we should
> >     emit a hidden alias.  */
> >
> > -static struct pointer_set_t *
> > +static hash_set<tree> *
> >  collect_candidates_for_java_method_aliases (void)
> >  {
> >    struct cgraph_node *node;
> > -  struct pointer_set_t *candidates = NULL;
> > +  hash_set<tree> *candidates = NULL;
> >
> >  #ifndef HAVE_GAS_HIDDEN
> >    return candidates;
> > @@ -3957,8 +3957,8 @@ collect_candidates_for_java_method_aliases (void)
> >           && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
> >         {
> >           if (candidates == NULL)
> > -           candidates = pointer_set_create ();
> > -         pointer_set_insert (candidates, fndecl);
> > +           candidates = new hash_set<tree>;
> > +         candidates->add (fndecl);
> >         }
> >      }
> >
> > @@ -3973,7 +3973,7 @@ collect_candidates_for_java_method_aliases (void)
> >     by collect_candidates_for_java_method_aliases.  */
> >
> >  static void
> > -build_java_method_aliases (struct pointer_set_t *candidates)
> > +build_java_method_aliases (hash_set<tree> *candidates)
> >  {
> >    struct cgraph_node *node;
> >
> > @@ -3986,7 +3986,7 @@ build_java_method_aliases (struct pointer_set_t *candidates)
> >        tree fndecl = node->decl;
> >
> >        if (TREE_ASM_WRITTEN (fndecl)
> > -         && pointer_set_contains (candidates, fndecl))
> > +         && candidates->contains (fndecl))
> >         {
> >           /* Mangle the name in a predictable way; we need to reference
> >              this from a java compiled object file.  */
> > @@ -4296,7 +4296,7 @@ cp_write_global_declarations (void)
> >    unsigned ssdf_count = 0;
> >    int retries = 0;
> >    tree decl;
> > -  struct pointer_set_t *candidates;
> > +  hash_set<tree> *candidates;
> >
> >    locus = input_location;
> >    at_eof = 1;
> > @@ -4713,7 +4713,7 @@ cp_write_global_declarations (void)
> >    if (candidates)
> >      {
> >        build_java_method_aliases (candidates);
> > -      pointer_set_destroy (candidates);
> > +      delete candidates;
> >      }
> >
> >    finish_repo ();
> > diff --git a/gcc/cp/error.c b/gcc/cp/error.c
> > index fa3bdc4..c8987ee 100644
> > --- a/gcc/cp/error.c
> > +++ b/gcc/cp/error.c
> > @@ -1325,7 +1325,7 @@ dump_template_decl (cxx_pretty_printer *pp, tree t, int flags)
> >
> >  struct find_typenames_t
> >  {
> > -  struct pointer_set_t *p_set;
> > +  hash_set<tree> *p_set;
> >    vec<tree, va_gc> *typenames;
> >  };
> >
> > @@ -1351,7 +1351,7 @@ find_typenames_r (tree *tp, int *walk_subtrees, void *data)
> >        return NULL_TREE;
> >      }
> >
> > -  if (mv && (mv == *tp || !pointer_set_insert (d->p_set, mv)))
> > +  if (mv && (mv == *tp || !d->p_set->add (mv)))
> >      vec_safe_push (d->typenames, mv);
> >
> >    /* Search into class template arguments, which cp_walk_subtrees
> > @@ -1367,11 +1367,11 @@ static vec<tree, va_gc> *
> >  find_typenames (tree t)
> >  {
> >    struct find_typenames_t ft;
> > -  ft.p_set = pointer_set_create ();
> > +  ft.p_set = new hash_set<tree>;
> >    ft.typenames = NULL;
> >    cp_walk_tree (&TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
> >                 find_typenames_r, &ft, ft.p_set);
> > -  pointer_set_destroy (ft.p_set);
> > +  delete ft.p_set;
> >    return ft.typenames;
> >  }
> >
> > diff --git a/gcc/cp/method.c b/gcc/cp/method.c
> > index e5fa0c1..65c5621 100644
> > --- a/gcc/cp/method.c
> > +++ b/gcc/cp/method.c
> > @@ -1480,7 +1480,7 @@ maybe_explain_implicit_delete (tree decl)
> >    if (DECL_DEFAULTED_FN (decl))
> >      {
> >        /* Not marked GTY; it doesn't need to be GC'd or written to PCH.  */
> > -      static struct pointer_set_t *explained;
> > +      static hash_set<tree> *explained;
> >
> >        special_function_kind sfk;
> >        location_t loc;
> > @@ -1488,8 +1488,8 @@ maybe_explain_implicit_delete (tree decl)
> >        tree ctype;
> >
> >        if (!explained)
> > -       explained = pointer_set_create ();
> > -      if (pointer_set_insert (explained, decl))
> > +       explained = new hash_set<tree>;
> > +      if (explained->add (decl))
> >         return true;
> >
> >        sfk = special_function_p (decl);
> > diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> > index 75b46ac..6e779a6 100644
> > --- a/gcc/cp/name-lookup.c
> > +++ b/gcc/cp/name-lookup.c
> > @@ -35,7 +35,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "debug.h"
> >  #include "c-family/c-pragma.h"
> >  #include "params.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >
> >  /* The bindings for a particular name in a particular scope.  */
> >
> > @@ -5152,7 +5152,7 @@ struct arg_lookup
> >    vec<tree, va_gc> *namespaces;
> >    vec<tree, va_gc> *classes;
> >    tree functions;
> > -  struct pointer_set_t *fn_set;
> > +  hash_set<tree> *fn_set;
> >  };
> >
> >  static bool arg_assoc (struct arg_lookup*, tree);
> > @@ -5175,7 +5175,7 @@ add_function (struct arg_lookup *k, tree fn)
> >    if (!is_overloaded_fn (fn))
> >      /* All names except those of (possibly overloaded) functions and
> >         function templates are ignored.  */;
> > -  else if (k->fn_set && pointer_set_insert (k->fn_set, fn))
> > +  else if (k->fn_set && k->fn_set->add (fn))
> >      /* It's already in the list.  */;
> >    else if (!k->functions)
> >      k->functions = fn;
> > @@ -5639,9 +5639,9 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
> >        /* We shouldn't be here if lookup found something other than
> >          namespace-scope functions.  */
> >        gcc_assert (DECL_NAMESPACE_SCOPE_P (OVL_CURRENT (fns)));
> > -      k.fn_set = pointer_set_create ();
> > +      k.fn_set = new hash_set<tree>;
> >        for (ovl = fns; ovl; ovl = OVL_NEXT (ovl))
> > -       pointer_set_insert (k.fn_set, OVL_CURRENT (ovl));
> > +       k.fn_set->add (OVL_CURRENT (ovl));
> >      }
> >    else
> >      k.fn_set = NULL;
> > @@ -5661,8 +5661,7 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
> >
> >    release_tree_vector (k.classes);
> >    release_tree_vector (k.namespaces);
> > -  if (k.fn_set)
> > -    pointer_set_destroy (k.fn_set);
> > +  delete k.fn_set;
> >
> >    return fns;
> >  }
> > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> > index b32cf6c..9b156f5 100644
> > --- a/gcc/cp/pt.c
> > +++ b/gcc/cp/pt.c
> > @@ -147,7 +147,7 @@ static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
> >  static tree convert_template_argument (tree, tree, tree,
> >                                        tsubst_flags_t, int, tree);
> >  static int for_each_template_parm (tree, tree_fn_t, void*,
> > -                                  struct pointer_set_t*, bool);
> > +                                  hash_set<tree> *, bool);
> >  static tree expand_template_argument_pack (tree);
> >  static tree build_template_parm_index (int, int, int, tree, tree);
> >  static bool inline_needs_template_parms (tree, bool);
> > @@ -3080,7 +3080,7 @@ struct find_parameter_pack_data
> >    tree* parameter_packs;
> >
> >    /* Set of AST nodes that have been visited by the traversal.  */
> > -  struct pointer_set_t *visited;
> > +  hash_set<tree> *visited;
> >  };
> >
> >  /* Identifies all of the argument packs that occur in a template
> > @@ -3243,9 +3243,9 @@ uses_parameter_packs (tree t)
> >    tree parameter_packs = NULL_TREE;
> >    struct find_parameter_pack_data ppd;
> >    ppd.parameter_packs = &parameter_packs;
> > -  ppd.visited = pointer_set_create ();
> > +  ppd.visited = new hash_set<tree>;
> >    cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
> > -  pointer_set_destroy (ppd.visited);
> > +  delete ppd.visited;
> >    return parameter_packs != NULL_TREE;
> >  }
> >
> > @@ -3292,7 +3292,7 @@ make_pack_expansion (tree arg)
> >
> >        /* Determine which parameter packs will be used by the base
> >           class expansion.  */
> > -      ppd.visited = pointer_set_create ();
> > +      ppd.visited = new hash_set<tree>;
> >        ppd.parameter_packs = &parameter_packs;
> >        cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
> >                      &ppd, ppd.visited);
> > @@ -3300,7 +3300,7 @@ make_pack_expansion (tree arg)
> >        if (parameter_packs == NULL_TREE)
> >          {
> >            error ("base initializer expansion %<%T%> contains no parameter packs", arg);
> > -          pointer_set_destroy (ppd.visited);
> > +          delete ppd.visited;
> >            return error_mark_node;
> >          }
> >
> > @@ -3317,7 +3317,7 @@ make_pack_expansion (tree arg)
> >              }
> >          }
> >
> > -      pointer_set_destroy (ppd.visited);
> > +      delete ppd.visited;
> >
> >        /* Create the pack expansion type for the base type.  */
> >        purpose = cxx_make_type (TYPE_PACK_EXPANSION);
> > @@ -3352,9 +3352,9 @@ make_pack_expansion (tree arg)
> >
> >    /* Determine which parameter packs will be expanded.  */
> >    ppd.parameter_packs = &parameter_packs;
> > -  ppd.visited = pointer_set_create ();
> > +  ppd.visited = new hash_set<tree>;
> >    cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
> > -  pointer_set_destroy (ppd.visited);
> > +  delete ppd.visited;
> >
> >    /* Make sure we found some parameter packs.  */
> >    if (parameter_packs == NULL_TREE)
> > @@ -3399,9 +3399,9 @@ check_for_bare_parameter_packs (tree t)
> >      t = TREE_TYPE (t);
> >
> >    ppd.parameter_packs = &parameter_packs;
> > -  ppd.visited = pointer_set_create ();
> > +  ppd.visited = new hash_set<tree>;
> >    cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
> > -  pointer_set_destroy (ppd.visited);
> > +  delete ppd.visited;
> >
> >    if (parameter_packs)
> >      {
> > @@ -4381,11 +4381,11 @@ fixed_parameter_pack_p (tree parm)
> >    tree parameter_packs = NULL_TREE;
> >    struct find_parameter_pack_data ppd;
> >    ppd.parameter_packs = &parameter_packs;
> > -  ppd.visited = pointer_set_create ();
> > +  ppd.visited = new hash_set<tree>;
> >
> >    fixed_parameter_pack_p_1 (parm, &ppd);
> >
> > -  pointer_set_destroy (ppd.visited);
> > +  delete ppd.visited;
> >    return parameter_packs;
> >  }
> >
> > @@ -7907,7 +7907,7 @@ struct pair_fn_data
> >    /* True when we should also visit template parameters that occur in
> >       non-deduced contexts.  */
> >    bool include_nondeduced_p;
> > -  struct pointer_set_t *visited;
> > +  hash_set<tree> *visited;
> >  };
> >
> >  /* Called from for_each_template_parm via walk_tree.  */
> > @@ -8107,7 +8107,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
> >
> >  static int
> >  for_each_template_parm (tree t, tree_fn_t fn, void* data,
> > -                       struct pointer_set_t *visited,
> > +                       hash_set<tree> *visited,
> >                         bool include_nondeduced_p)
> >  {
> >    struct pair_fn_data pfd;
> > @@ -8126,7 +8126,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
> >    if (visited)
> >      pfd.visited = visited;
> >    else
> > -    pfd.visited = pointer_set_create ();
> > +    pfd.visited = new hash_set<tree>;
> >    result = cp_walk_tree (&t,
> >                          for_each_template_parm_r,
> >                          &pfd,
> > @@ -8135,7 +8135,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
> >    /* Clean up.  */
> >    if (!visited)
> >      {
> > -      pointer_set_destroy (pfd.visited);
> > +      delete pfd.visited;
> >        pfd.visited = 0;
> >      }
> >
> > diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
> > index c87764d..735284e 100644
> > --- a/gcc/cp/semantics.c
> > +++ b/gcc/cp/semantics.c
> > @@ -8031,7 +8031,7 @@ register_constexpr_fundef (tree fun, tree body)
> >  void
> >  explain_invalid_constexpr_fn (tree fun)
> >  {
> > -  static struct pointer_set_t *diagnosed;
> > +  static hash_set<tree> *diagnosed;
> >    tree body;
> >    location_t save_loc;
> >    /* Only diagnose defaulted functions or instantiations.  */
> > @@ -8039,8 +8039,8 @@ explain_invalid_constexpr_fn (tree fun)
> >        && !is_instantiation_of_constexpr (fun))
> >      return;
> >    if (diagnosed == NULL)
> > -    diagnosed = pointer_set_create ();
> > -  if (pointer_set_insert (diagnosed, fun) != 0)
> > +    diagnosed = new hash_set<tree>;
> > +  if (diagnosed->add (fun))
> >      /* Already explained.  */
> >      return;
> >
> > diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
> > index f6c5693..697a02b 100644
> > --- a/gcc/cp/tree.c
> > +++ b/gcc/cp/tree.c
> > @@ -3485,7 +3485,7 @@ cxx_type_hash_eq (const_tree typea, const_tree typeb)
> >
> >  tree
> >  cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
> > -                 void *data, struct pointer_set_t *pset)
> > +                 void *data, hash_set<tree> *pset)
> >  {
> >    enum tree_code code = TREE_CODE (*tp);
> >    tree result;
> > diff --git a/gcc/cprop.c b/gcc/cprop.c
> > index 6291c91..4234afa 100644
> > --- a/gcc/cprop.c
> > +++ b/gcc/cprop.c
> > @@ -167,7 +167,7 @@ reg_available_p (const_rtx x, const_rtx insn ATTRIBUTE_UNUSED)
> >     ??? May need to make things more elaborate.  Later, as necessary.  */
> >
> >  static unsigned int
> > -hash_set (int regno, int hash_table_size)
> > +hash_mod (int regno, int hash_table_size)
> >  {
> >    return (unsigned) regno % hash_table_size;
> >  }
> > @@ -187,7 +187,7 @@ insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table,
> >    struct expr *cur_expr, *last_expr = NULL;
> >    struct occr *cur_occr;
> >
> > -  hash = hash_set (REGNO (dest), table->size);
> > +  hash = hash_mod (REGNO (dest), table->size);
> >
> >    for (cur_expr = table->table[hash]; cur_expr;
> >         cur_expr = cur_expr->next_same_hash)
> > @@ -483,7 +483,7 @@ compute_hash_table (struct hash_table_d *table)
> >  static struct expr *
> >  lookup_set (unsigned int regno, struct hash_table_d *table)
> >  {
> > -  unsigned int hash = hash_set (regno, table->size);
> > +  unsigned int hash = hash_mod (regno, table->size);
> >    struct expr *expr;
> >
> >    expr = table->table[hash];
> > diff --git a/gcc/cse.c b/gcc/cse.c
> > index 34f9364..dd9a076 100644
> > --- a/gcc/cse.c
> > +++ b/gcc/cse.c
> > @@ -41,7 +41,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "tree-pass.h"
> >  #include "df.h"
> >  #include "dbgcnt.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >
> >  /* The basic idea of common subexpression elimination is to go
> >     through the code, keeping a record of expressions that would
> > @@ -2906,7 +2906,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >                       enum machine_mode *pmode1, enum machine_mode *pmode2)
> >  {
> >    rtx arg1, arg2;
> > -  struct pointer_set_t *visited = NULL;
> > +  hash_set<rtx> *visited = NULL;
> >    /* Set nonzero when we find something of interest.  */
> >    rtx x = NULL;
> >
> > @@ -2923,8 +2923,8 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >        if (x)
> >         {
> >           if (!visited)
> > -           visited = pointer_set_create ();
> > -         pointer_set_insert (visited, x);
> > +           visited = new hash_set<rtx>;
> > +         visited->add (x);
> >           x = 0;
> >         }
> >
> > @@ -3005,7 +3005,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >             continue;
> >
> >           /* If it's a comparison we've used before, skip it.  */
> > -         if (visited && pointer_set_contains (visited, p->exp))
> > +         if (visited && visited->contains (p->exp))
> >             continue;
> >
> >           if (GET_CODE (p->exp) == COMPARE
> > @@ -3087,7 +3087,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >    *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0);
> >
> >    if (visited)
> > -    pointer_set_destroy (visited);
> > +    delete visited;
> >    return code;
> >  }
> >
> > diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
> > index 68ba70f..410efb1 100644
> > --- a/gcc/fortran/openmp.c
> > +++ b/gcc/fortran/openmp.c
> > @@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "arith.h"
> >  #include "match.h"
> >  #include "parse.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >
> >  /* Match an end of OpenMP directive.  End of OpenMP directive is optional
> >     whitespace, followed by '\n' or comment '!'.  */
> > @@ -3013,8 +3013,8 @@ resolve_omp_atomic (gfc_code *code)
> >  struct omp_context
> >  {
> >    gfc_code *code;
> > -  struct pointer_set_t *sharing_clauses;
> > -  struct pointer_set_t *private_iterators;
> > +  hash_set<gfc_symbol *> *sharing_clauses;
> > +  hash_set<gfc_symbol *> *private_iterators;
> >    struct omp_context *previous;
> >  } *omp_current_ctx;
> >  static gfc_code *omp_current_do_code;
> > @@ -3057,8 +3057,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
> >    int list;
> >
> >    ctx.code = code;
> > -  ctx.sharing_clauses = pointer_set_create ();
> > -  ctx.private_iterators = pointer_set_create ();
> > +  ctx.sharing_clauses = new hash_set<gfc_symbol *>;
> > +  ctx.private_iterators = new hash_set<gfc_symbol *>;
> >    ctx.previous = omp_current_ctx;
> >    omp_current_ctx = &ctx;
> >
> > @@ -3072,7 +3072,7 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
> >        case OMP_LIST_REDUCTION:
> >        case OMP_LIST_LINEAR:
> >         for (n = omp_clauses->lists[list]; n; n = n->next)
> > -         pointer_set_insert (ctx.sharing_clauses, n->sym);
> > +         ctx.sharing_clauses->add (n->sym);
> >         break;
> >        default:
> >         break;
> > @@ -3097,8 +3097,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
> >      }
> >
> >    omp_current_ctx = ctx.previous;
> > -  pointer_set_destroy (ctx.sharing_clauses);
> > -  pointer_set_destroy (ctx.private_iterators);
> > +  delete ctx.sharing_clauses;
> > +  delete ctx.private_iterators;
> >  }
> >
> >
> > @@ -3154,10 +3154,10 @@ gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym)
> >    if (omp_current_ctx == NULL)
> >      return;
> >
> > -  if (pointer_set_contains (omp_current_ctx->sharing_clauses, sym))
> > +  if (omp_current_ctx->sharing_clauses->contains (sym))
> >      return;
> >
> > -  if (! pointer_set_insert (omp_current_ctx->private_iterators, sym))
> > +  if (! omp_current_ctx->private_iterators->add (sym))
> >      {
> >        gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
> >        gfc_omp_namelist *p;
> > diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
> > index 8b56151..babe48f 100644
> > --- a/gcc/fortran/trans-decl.c
> > +++ b/gcc/fortran/trans-decl.c
> > @@ -40,7 +40,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "cgraph.h"
> >  #include "debug.h"
> >  #include "gfortran.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "constructor.h"
> >  #include "trans.h"
> >  #include "trans-types.h"
> > @@ -63,7 +63,7 @@ static GTY(()) tree parent_fake_result_decl;
> >  static GTY(()) tree saved_function_decls;
> >  static GTY(()) tree saved_parent_function_decls;
> >
> > -static struct pointer_set_t *nonlocal_dummy_decl_pset;
> > +static hash_set<tree> *nonlocal_dummy_decl_pset;
> >  static GTY(()) tree nonlocal_dummy_decls;
> >
> >  /* Holds the variable DECLs that are locals.  */
> > @@ -1094,9 +1094,9 @@ gfc_nonlocal_dummy_array_decl (gfc_symbol *sym)
> >    tree decl, dummy;
> >
> >    if (! nonlocal_dummy_decl_pset)
> > -    nonlocal_dummy_decl_pset = pointer_set_create ();
> > +    nonlocal_dummy_decl_pset = new hash_set<tree>;
> >
> > -  if (pointer_set_insert (nonlocal_dummy_decl_pset, sym->backend_decl))
> > +  if (nonlocal_dummy_decl_pset->add (sym->backend_decl))
> >      return;
> >
> >    dummy = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl);
> > @@ -5861,7 +5861,7 @@ gfc_generate_function_code (gfc_namespace * ns)
> >      {
> >        BLOCK_VARS (DECL_INITIAL (fndecl))
> >         = chainon (BLOCK_VARS (DECL_INITIAL (fndecl)), nonlocal_dummy_decls);
> > -      pointer_set_destroy (nonlocal_dummy_decl_pset);
> > +      delete nonlocal_dummy_decl_pset;
> >        nonlocal_dummy_decls = NULL;
> >        nonlocal_dummy_decl_pset = NULL;
> >      }
> > diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
> > index b6f0495..f4f6757 100644
> > --- a/gcc/gimple-walk.c
> > +++ b/gcc/gimple-walk.c
> > @@ -180,7 +180,7 @@ tree
> >  walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
> >                 struct walk_stmt_info *wi)
> >  {
> > -  struct pointer_set_t *pset = (wi) ? wi->pset : NULL;
> > +  hash_set<tree> *pset = (wi) ? wi->pset : NULL;
> >    unsigned i;
> >    tree ret = NULL_TREE;
> >
> > diff --git a/gcc/gimple-walk.h b/gcc/gimple-walk.h
> > index 555eb18..5b75fdc 100644
> > --- a/gcc/gimple-walk.h
> > +++ b/gcc/gimple-walk.h
> > @@ -36,7 +36,7 @@ struct walk_stmt_info
> >    /* Pointer map used to mark visited tree nodes when calling
> >       walk_tree on each operand.  If set to NULL, duplicate tree nodes
> >       will be visited more than once.  */
> > -  struct pointer_set_t *pset;
> > +  hash_set<tree> *pset;
> >
> >    /* Operand returned by the callbacks.  This is set when calling
> >       walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
> > diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> > index 4ab36d0..c0ae7cc 100644
> > --- a/gcc/gimplify.c
> > +++ b/gcc/gimplify.c
> > @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "coretypes.h"
> >  #include "tree.h"
> >  #include "expr.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "hash-table.h"
> >  #include "basic-block.h"
> > @@ -134,7 +135,7 @@ struct gimplify_omp_ctx
> >  {
> >    struct gimplify_omp_ctx *outer_context;
> >    splay_tree variables;
> > -  struct pointer_set_t *privatized_types;
> > +  hash_set<tree> *privatized_types;
> >    location_t location;
> >    enum omp_clause_default_kind default_kind;
> >    enum omp_region_type region_type;
> > @@ -352,7 +353,7 @@ new_omp_context (enum omp_region_type region_type)
> >    c = XCNEW (struct gimplify_omp_ctx);
> >    c->outer_context = gimplify_omp_ctxp;
> >    c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
> > -  c->privatized_types = pointer_set_create ();
> > +  c->privatized_types = new hash_set<tree>;
> >    c->location = input_location;
> >    c->region_type = region_type;
> >    if ((region_type & ORT_TASK) == 0)
> > @@ -369,7 +370,7 @@ static void
> >  delete_omp_context (struct gimplify_omp_ctx *c)
> >  {
> >    splay_tree_delete (c->variables);
> > -  pointer_set_destroy (c->privatized_types);
> > +  delete c->privatized_types;
> >    XDELETE (c);
> >  }
> >
> > @@ -744,7 +745,7 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
> >       copy their subtrees if we can make sure to do it only once.  */
> >    if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
> >      {
> > -      if (data && !pointer_set_insert ((struct pointer_set_t *)data, t))
> > +      if (data && !((hash_set<tree> *)data)->add (t))
> >         ;
> >        else
> >         *walk_subtrees = 0;
> > @@ -829,15 +830,14 @@ unshare_body (tree fndecl)
> >    struct cgraph_node *cgn = cgraph_node::get (fndecl);
> >    /* If the language requires deep unsharing, we need a pointer set to make
> >       sure we don't repeatedly unshare subtrees of unshareable nodes.  */
> > -  struct pointer_set_t *visited
> > -    = lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
> > +  hash_set<tree> *visited
> > +    = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
> >
> >    copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
> >    copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
> >    copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
> >
> > -  if (visited)
> > -    pointer_set_destroy (visited);
> > +  delete visited;
> >
> >    if (cgn)
> >      for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
> > @@ -1733,7 +1733,7 @@ gimplify_conversion (tree *expr_p)
> >  }
> >
> >  /* Nonlocal VLAs seen in the current function.  */
> > -static struct pointer_set_t *nonlocal_vlas;
> > +static hash_set<tree> *nonlocal_vlas;
> >
> >  /* The VAR_DECLs created for nonlocal VLAs for debug info purposes.  */
> >  static tree nonlocal_vla_vars;
> > @@ -1784,7 +1784,7 @@ gimplify_var_or_parm_decl (tree *expr_p)
> >                  && (ctx->region_type == ORT_WORKSHARE
> >                      || ctx->region_type == ORT_SIMD))
> >             ctx = ctx->outer_context;
> > -         if (!ctx && !pointer_set_insert (nonlocal_vlas, decl))
> > +         if (!ctx && !nonlocal_vlas->add (decl))
> >             {
> >               tree copy = copy_node (decl);
> >
> > @@ -5463,7 +5463,7 @@ omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
> >      return;
> >    type = TYPE_MAIN_VARIANT (type);
> >
> > -  if (pointer_set_insert (ctx->privatized_types, type))
> > +  if (ctx->privatized_types->add (type))
> >      return;
> >
> >    switch (TREE_CODE (type))
> > @@ -8766,7 +8766,7 @@ gimplify_body (tree fndecl, bool do_parms)
> >
> >    cgn = cgraph_node::get (fndecl);
> >    if (cgn && cgn->origin)
> > -    nonlocal_vlas = pointer_set_create ();
> > +    nonlocal_vlas = new hash_set<tree>;
> >
> >    /* Make sure input_location isn't set to something weird.  */
> >    input_location = DECL_SOURCE_LOCATION (fndecl);
> > @@ -8830,7 +8830,7 @@ gimplify_body (tree fndecl, bool do_parms)
> >                          nonlocal_vla_vars);
> >           nonlocal_vla_vars = NULL_TREE;
> >         }
> > -      pointer_set_destroy (nonlocal_vlas);
> > +      delete nonlocal_vlas;
> >        nonlocal_vlas = NULL;
> >      }
> >
> > diff --git a/gcc/godump.c b/gcc/godump.c
> > index 2afd7f1..7566f4d 100644
> > --- a/gcc/godump.c
> > +++ b/gcc/godump.c
> > @@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "diagnostic-core.h"
> >  #include "tree.h"
> >  #include "ggc.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "obstack.h"
> >  #include "debug.h"
> >  #include "wide-int-print.h"
> > @@ -525,11 +525,11 @@ go_type_decl (tree decl, int local)
> >  struct godump_container
> >  {
> >    /* DECLs that we have already seen.  */
> > -  struct pointer_set_t *decls_seen;
> > +  hash_set<tree> decls_seen;
> >
> >    /* Types which may potentially have to be defined as dummy
> >       types.  */
> > -  struct pointer_set_t *pot_dummy_types;
> > +  hash_set<const char *> pot_dummy_types;
> >
> >    /* Go keywords.  */
> >    htab_t keyword_hash;
> > @@ -569,8 +569,8 @@ go_format_type (struct godump_container *container, tree type,
> >    ob = &container->type_obstack;
> >
> >    if (TYPE_NAME (type) != NULL_TREE
> > -      && (pointer_set_contains (container->decls_seen, type)
> > -         || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
> > +      && (container->decls_seen.contains (type)
> > +         || container->decls_seen.contains (TYPE_NAME (type)))
> >        && (AGGREGATE_TYPE_P (type)
> >           || POINTER_TYPE_P (type)
> >           || TREE_CODE (type) == FUNCTION_TYPE))
> > @@ -590,7 +590,7 @@ go_format_type (struct godump_container *container, tree type,
> >        return ret;
> >      }
> >
> > -  pointer_set_insert (container->decls_seen, type);
> > +  container->decls_seen.add (type);
> >
> >    switch (TREE_CODE (type))
> >      {
> > @@ -697,8 +697,7 @@ go_format_type (struct godump_container *container, tree type,
> >              definition.  So this struct or union is a potential dummy
> >              type.  */
> >           if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
> > -           pointer_set_insert (container->pot_dummy_types,
> > -                               IDENTIFIER_POINTER (name));
> > +           container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
> >
> >           return ret;
> >          }
> > @@ -948,10 +947,10 @@ go_output_typedef (struct godump_container *container, tree decl)
> >       separately.  */
> >    if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
> >        && TYPE_SIZE (TREE_TYPE (decl)) != 0
> > -      && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
> > +      && !container->decls_seen.contains (TREE_TYPE (decl))
> >        && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
> > -         || !pointer_set_contains (container->decls_seen,
> > -                                   TYPE_CANONICAL (TREE_TYPE (decl)))))
> > +         || !container->decls_seen.contains
> > +                                   (TYPE_CANONICAL (TREE_TYPE (decl)))))
> >      {
> >        tree element;
> >
> > @@ -988,10 +987,9 @@ go_output_typedef (struct godump_container *container, tree decl)
> >           mhval->value = xstrdup (buf);
> >           *slot = mhval;
> >         }
> > -      pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
> > +      container->decls_seen.add (TREE_TYPE (decl));
> >        if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
> > -       pointer_set_insert (container->decls_seen,
> > -                           TYPE_CANONICAL (TREE_TYPE (decl)));
> > +       container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
> >      }
> >
> >    if (DECL_NAME (decl) != NULL_TREE)
> > @@ -1027,7 +1025,7 @@ go_output_typedef (struct godump_container *container, tree decl)
> >                      size);
> >         }
> >
> > -      pointer_set_insert (container->decls_seen, decl);
> > +      container->decls_seen.add (decl);
> >      }
> >    else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
> >      {
> > @@ -1072,11 +1070,11 @@ go_output_var (struct godump_container *container, tree decl)
> >  {
> >    bool is_valid;
> >
> > -  if (pointer_set_contains (container->decls_seen, decl)
> > -      || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
> > +  if (container->decls_seen.contains (decl)
> > +      || container->decls_seen.contains (DECL_NAME (decl)))
> >      return;
> > -  pointer_set_insert (container->decls_seen, decl);
> > -  pointer_set_insert (container->decls_seen, DECL_NAME (decl));
> > +  container->decls_seen.add (decl);
> > +  container->decls_seen.add (DECL_NAME (decl));
> >
> >    is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
> >    if (is_valid
> > @@ -1103,11 +1101,10 @@ go_output_var (struct godump_container *container, tree decl)
> >      {
> >        tree type_name = TYPE_NAME (TREE_TYPE (decl));
> >        if (TREE_CODE (type_name) == IDENTIFIER_NODE)
> > -       pointer_set_insert (container->pot_dummy_types,
> > -                           IDENTIFIER_POINTER (type_name));
> > +       container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
> >        else if (TREE_CODE (type_name) == TYPE_DECL)
> > -       pointer_set_insert (container->pot_dummy_types,
> > -                           IDENTIFIER_POINTER (DECL_NAME (type_name)));
> > +       container->pot_dummy_types.add
> > +                           (IDENTIFIER_POINTER (DECL_NAME (type_name)));
> >      }
> >  }
> >
> > @@ -1147,10 +1144,10 @@ keyword_hash_init (struct godump_container *container)
> >
> >  /* Traversing the pot_dummy_types and seeing which types are present
> >     in the global types hash table and creating dummy definitions if
> > -   not found.  This function is invoked by pointer_set_traverse.  */
> > +   not found.  This function is invoked by hash_set::traverse.  */
> >
> > -static bool
> > -find_dummy_types (const void *ptr, void *adata)
> > +bool
> > +find_dummy_types (const char *const &ptr, godump_container *adata)
> >  {
> >    struct godump_container *data = (struct godump_container *) adata;
> >    const char *type = (const char *) ptr;
> > @@ -1175,8 +1172,6 @@ go_finish (const char *filename)
> >
> >    real_debug_hooks->finish (filename);
> >
> > -  container.decls_seen = pointer_set_create ();
> > -  container.pot_dummy_types = pointer_set_create ();
> >    container.type_hash = htab_create (100, htab_hash_string,
> >                                       string_hash_eq, NULL);
> >    container.invalid_hash = htab_create (10, htab_hash_string,
> > @@ -1211,11 +1206,9 @@ go_finish (const char *filename)
> >    htab_traverse_noresize (macro_hash, go_print_macro, NULL);
> >
> >    /* To emit dummy definitions.  */
> > -  pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
> > -                        (void *) &container);
> > +  container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
> > +                        (&container);
> >
> > -  pointer_set_destroy (container.decls_seen);
> > -  pointer_set_destroy (container.pot_dummy_types);
> >    htab_delete (container.type_hash);
> >    htab_delete (container.invalid_hash);
> >    htab_delete (container.keyword_hash);
> > diff --git a/gcc/hash-set.h b/gcc/hash-set.h
> > new file mode 100644
> > index 0000000..47bae9e
> > --- /dev/null
> > +++ b/gcc/hash-set.h
> > @@ -0,0 +1,173 @@
> > +/* A type-safe hash set.
> > +   Copyright (C) 2014 Free Software Foundation, Inc.
> > +
> > +This file is part of GCC.
> > +
> > +GCC is free software; you can redistribute it and/or modify it under
> > +the terms of the GNU General Public License as published by the Free
> > +Software Foundation; either version 3, or (at your option) any later
> > +version.
> > +
> > +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> > +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> > +for more details.
> > +
> > +You should have received a copy of the GNU General Public License
> > +along with GCC; see the file COPYING3.  If not see
> > +<http://www.gnu.org/licenses/>.  */
> > +
> > +
> > +#ifndef hash_set_h
> > +#define hash_set_h
> > +
> > +#include "hash-table.h"
> > +
> > +/* implement default behavior for traits when types allow it.  */
> > +
> > +struct default_hashset_traits
> > +{
> > +  /* Hashes the passed in key.  */
> > +
> > +  template<typename T>
> > +  static hashval_t
> > +  hash (T *p)
> > +    {
> > +      return uintptr_t(p) >> 3;
> > +    }
> > +
> > +  template<typename T> static hashval_t hash(const T &v) { return v; }
> > +
> > +  /* Return true if the two keys passed as arguments are equal.  */
> > +
> > +  template<typename T>
> > +  static bool
> > +  equal (const T &a, const T &b)
> > +    {
> > +      return a == b;
> > +    }
> > +
> > +  /* Called to dispose of the key before marking the entry as deleted.  */
> > +
> > +  template<typename T> static void remove (T &v) { v.~T (); }
> > +
> > +  /* Mark the passed in entry as being deleted.  */
> > +
> > +  template<typename T>
> > +  static void
> > +  mark_deleted (T *&e)
> > +    {
> > +      e = reinterpret_cast<void *> (1);
> > +    }
> > +
> > +  /* Mark the passed in entry as being empty.  */
> > +
> > +  template<typename T>
> > +  static void
> > +  mark_empty (T *&e)
> > +    {
> > +      e = NULL;
> > +    }
> > +
> > +  /* Return true if the passed in entry is marked as deleted.  */
> > +
> > +  template<typename T>
> > +  static bool
> > +  is_deleted (T *e)
> > +    {
> > +      return e == reinterpret_cast<void *> (1);
> > +    }
> > +
> > +  /* Return true if the passed in entry is marked as empty.  */
> > +
> > +  template<typename T> static bool is_empty (T *e) { return e == NULL; }
> > +};
> > +
> > +template<typename Key, typename Traits = default_hashset_traits>
> > +class hash_set
> > +{
> > +  struct hash_entry
> > +  {
> > +    Key m_key;
> > +
> > +    typedef hash_entry value_type;
> > +    typedef Key compare_type;
> > +    typedef int store_values_directly;
> > +
> > +    static hashval_t hash (const hash_entry &e)
> > +      {
> > +               return Traits::hash (e.m_key);
> > +      }
> > +
> > +    static bool equal (const hash_entry &a, const Key &b)
> > +               {
> > +         return Traits::equal (a.m_key, b);
> > +               }
> > +
> > +    static void remove (hash_entry &e) { Traits::remove (e.m_key); }
> > +
> > +    static void
> > +    mark_deleted (hash_entry &e)
> > +      {
> > +               Traits::mark_deleted (e.m_key);
> > +      }
> > +
> > +    static bool is_deleted (const hash_entry &e)
> > +      {
> > +               return Traits::is_deleted (e.m_key);
> > +      }
> > +
> > +    static void
> > +    mark_empty (hash_entry &e)
> > +      {
> > +       Traits::mark_empty (e.m_key);
> > +      }
> > +
> > +    static bool
> > +    is_empty (const hash_entry &e)
> > +      {
> > +       return Traits::is_empty (e.m_key);
> > +      }
> > +  };
> > +
> > +public:
> > +  explicit hash_set (size_t n = 13) : m_table (n) {}
> > +
> > +  /* If key k isn't already in the map add it to the map, and
> > +     return false.  Otherwise return true.  */
> > +
> > +  bool add (const Key &k)
> > +    {
> > +      hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
> > +                                                  INSERT);
> > +      bool existed = !hash_entry::is_empty (*e);
> > +      if (!existed)
> > +       e->m_key = k;
> > +
> > +      return existed;
> > +    }
> > +
> > +  /* if the passed in key is in the map return its value otherwise NULL.  */
> > +
> > +  bool contains (const Key &k)
> > +    {
> > +      hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
> > +      return !Traits::is_empty (e.m_key);
> > +    }
> > +
> > +  /* Call the call back on each pair of key and value with the passed in
> > +     arg.  */
> > +
> > +  template<typename Arg, bool (*f)(const Key &, Arg)>
> > +  void traverse (Arg a) const
> > +    {
> > +      for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
> > +          iter != m_table.end (); ++iter)
> > +       f ((*iter).m_key, a);
> > +    }
> > +
> > +private:
> > +  hash_table<hash_entry> m_table;
> > +};
> > +
> > +#endif
> > diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
> > index 127d58d..70a70a7 100644
> > --- a/gcc/ipa-devirt.c
> > +++ b/gcc/ipa-devirt.c
> > @@ -115,7 +115,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "cgraph.h"
> >  #include "expr.h"
> >  #include "tree-pass.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "target.h"
> >  #include "hash-table.h"
> >  #include "inchash.h"
> > @@ -134,7 +134,8 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "stor-layout.h"
> >  #include "intl.h"
> >
> > -static bool odr_types_equivalent_p (tree, tree, bool, bool *, pointer_set_t *);
> > +static bool odr_types_equivalent_p (tree, tree, bool, bool *,
> > +                                   hash_set<tree> *);
> >
> >  static bool odr_violation_reported = false;
> >
> > @@ -144,7 +145,7 @@ const ipa_polymorphic_call_context ipa_dummy_polymorphic_call_context
> >     = {0, NULL, false, true};
> >
> >  /* Pointer set of all call targets appearing in the cache.  */
> > -static pointer_set_t *cached_polymorphic_call_targets;
> > +static hash_set<cgraph_node *> *cached_polymorphic_call_targets;
> >
> >  /* The node of type inheritance graph.  For each type unique in
> >     One Defintion Rule (ODR) sense, we produce one node linking all
> > @@ -163,7 +164,7 @@ struct GTY(()) odr_type_d
> >    /* All equivalent types, if more than one.  */
> >    vec<tree, va_gc> *types;
> >    /* Set of all equivalent types, if NON-NULL.  */
> > -  pointer_set_t * GTY((skip)) types_set;
> > +  hash_set<tree> * GTY((skip)) types_set;
> >
> >    /* Unique ID indexing the type in odr_types array.  */
> >    int id;
> > @@ -409,7 +410,7 @@ odr_hasher::remove (value_type *v)
> >    v->bases.release ();
> >    v->derived_types.release ();
> >    if (v->types_set)
> > -    pointer_set_destroy (v->types_set);
> > +    delete v->types_set;
> >    ggc_free (v);
> >  }
> >
> > @@ -439,7 +440,7 @@ set_type_binfo (tree type, tree binfo)
> >  /* Compare T2 and T2 based on name or structure.  */
> >
> >  static bool
> > -odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
> > +odr_subtypes_equivalent_p (tree t1, tree t2, hash_set<tree> *visited)
> >  {
> >    bool an1, an2;
> >
> > @@ -473,7 +474,7 @@ odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
> >        /* This should really be a pair hash, but for the moment we do not need
> >          100% reliability and it would be better to compare all ODR types so
> >          recursion here is needed only for component types.  */
> > -      if (pointer_set_insert (visited, t1))
> > +      if (visited->add (t1))
> >         return true;
> >        return odr_types_equivalent_p (t1, t2, false, NULL, visited);
> >      }
> > @@ -562,7 +563,7 @@ warn_types_mismatch (tree t1, tree t2)
> >     gimple_canonical_types_compatible_p.  */
> >
> >  static bool
> > -odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, pointer_set_t *visited)
> > +odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, hash_set<tree> *visited)
> >  {
> >    /* Check first for the obvious case of pointer identity.  */
> >    if (t1 == t2)
> > @@ -938,7 +939,7 @@ add_type_duplicate (odr_type val, tree type)
> >  {
> >    bool build_bases = false;
> >    if (!val->types_set)
> > -    val->types_set = pointer_set_create ();
> > +    val->types_set = new hash_set<tree>;
> >
> >    /* Always prefer complete type to be the leader.  */
> >    if (!COMPLETE_TYPE_P (val->type)
> > @@ -952,20 +953,20 @@ add_type_duplicate (odr_type val, tree type)
> >      }
> >
> >    /* See if this duplicate is new.  */
> > -  if (!pointer_set_insert (val->types_set, type))
> > +  if (!val->types_set->add (type))
> >      {
> >        bool merge = true;
> >        bool base_mismatch = false;
> >        unsigned int i,j;
> >        bool warned = false;
> > -      pointer_set_t *visited = pointer_set_create ();
> > +      hash_set<tree> visited;
> >
> >        gcc_assert (in_lto_p);
> >        vec_safe_push (val->types, type);
> >
> >        /* First we compare memory layout.  */
> >        if (!odr_types_equivalent_p (val->type, type, !flag_ltrans && !val->odr_violated,
> > -                                  &warned, visited))
> > +                                  &warned, &visited))
> >         {
> >           merge = false;
> >           odr_violation_reported = true;
> > @@ -980,7 +981,6 @@ add_type_duplicate (odr_type val, tree type)
> >               putc ('\n',cgraph_dump_file);
> >             }
> >         }
> > -      pointer_set_destroy (visited);
> >
> >        /* Next sanity check that bases are the same.  If not, we will end
> >          up producing wrong answers.  */
> > @@ -1356,7 +1356,7 @@ referenced_from_vtable_p (struct cgraph_node *node)
> >
> >  static void
> >  maybe_record_node (vec <cgraph_node *> &nodes,
> > -                  tree target, pointer_set_t *inserted,
> > +                  tree target, hash_set<tree> *inserted,
> >                    bool can_refer,
> >                    bool *completep)
> >  {
> > @@ -1422,10 +1422,9 @@ maybe_record_node (vec <cgraph_node *> &nodes,
> >      {
> >        gcc_assert (!target_node->global.inlined_to);
> >        gcc_assert (target_node->real_symbol_p ());
> > -      if (!pointer_set_insert (inserted, target_node->decl))
> > +      if (!inserted->add (target))
> >         {
> > -         pointer_set_insert (cached_polymorphic_call_targets,
> > -                             target_node);
> > +         cached_polymorphic_call_targets->add (target_node);
> >           nodes.safe_push (target_node);
> >         }
> >      }
> > @@ -1465,8 +1464,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
> >                           HOST_WIDE_INT otr_token,
> >                           tree outer_type,
> >                           HOST_WIDE_INT offset,
> > -                         pointer_set_t *inserted,
> > -                         pointer_set_t *matched_vtables,
> > +                         hash_set<tree> *inserted,
> > +                         hash_set<tree> *matched_vtables,
> >                           bool anonymous,
> >                           bool *completep)
> >  {
> > @@ -1519,8 +1518,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
> >         }
> >        gcc_assert (inner_binfo);
> >        if (bases_to_consider
> > -         ? !pointer_set_contains (matched_vtables, BINFO_VTABLE (inner_binfo))
> > -         : !pointer_set_insert (matched_vtables, BINFO_VTABLE (inner_binfo)))
> > +         ? !matched_vtables->contains (BINFO_VTABLE (inner_binfo))
> > +         : !matched_vtables->add (BINFO_VTABLE (inner_binfo)))
> >         {
> >           bool can_refer;
> >           tree target = gimple_get_virt_method_for_binfo (otr_token,
> > @@ -1559,8 +1558,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
> >
> >  static void
> >  possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes,
> > -                                    pointer_set_t *inserted,
> > -                                    pointer_set_t *matched_vtables,
> > +                                    hash_set<tree> *inserted,
> > +                                    hash_set<tree> *matched_vtables,
> >                                      tree otr_type,
> >                                      odr_type type,
> >                                      HOST_WIDE_INT otr_token,
> > @@ -1684,7 +1683,7 @@ free_polymorphic_call_targets_hash ()
> >      {
> >        delete polymorphic_call_target_hash;
> >        polymorphic_call_target_hash = NULL;
> > -      pointer_set_destroy (cached_polymorphic_call_targets);
> > +      delete cached_polymorphic_call_targets;
> >        cached_polymorphic_call_targets = NULL;
> >      }
> >  }
> > @@ -1695,7 +1694,7 @@ static void
> >  devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
> >  {
> >    if (cached_polymorphic_call_targets
> > -      && pointer_set_contains (cached_polymorphic_call_targets, n))
> > +      && cached_polymorphic_call_targets->contains (n))
> >      free_polymorphic_call_targets_hash ();
> >  }
> >
> > @@ -2277,8 +2276,8 @@ record_targets_from_bases (tree otr_type,
> >                            tree outer_type,
> >                            HOST_WIDE_INT offset,
> >                            vec <cgraph_node *> &nodes,
> > -                          pointer_set_t *inserted,
> > -                          pointer_set_t *matched_vtables,
> > +                          hash_set<tree> *inserted,
> > +                          hash_set<tree> *matched_vtables,
> >                            bool *completep)
> >  {
> >    while (true)
> > @@ -2319,7 +2318,7 @@ record_targets_from_bases (tree otr_type,
> >           return;
> >         }
> >        gcc_assert (base_binfo);
> > -      if (!pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo)))
> > +      if (!matched_vtables->add (BINFO_VTABLE (base_binfo)))
> >         {
> >           bool can_refer;
> >           tree target = gimple_get_virt_method_for_binfo (otr_token,
> > @@ -2327,7 +2326,7 @@ record_targets_from_bases (tree otr_type,
> >                                                           &can_refer);
> >           if (!target || ! DECL_CXX_DESTRUCTOR_P (target))
> >             maybe_record_node (nodes, target, inserted, can_refer, completep);
> > -         pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo));
> > +         matched_vtables->add (BINFO_VTABLE (base_binfo));
> >         }
> >      }
> >  }
> > @@ -2377,8 +2376,6 @@ possible_polymorphic_call_targets (tree otr_type,
> >                                    int *nonconstruction_targetsp)
> >  {
> >    static struct cgraph_node_hook_list *node_removal_hook_holder;
> > -  pointer_set_t *inserted;
> > -  pointer_set_t *matched_vtables;
> >    vec <cgraph_node *> nodes = vNULL;
> >    vec <tree> bases_to_consider = vNULL;
> >    odr_type type, outer_type;
> > @@ -2457,7 +2454,7 @@ possible_polymorphic_call_targets (tree otr_type,
> >    /* Initialize query cache.  */
> >    if (!cached_polymorphic_call_targets)
> >      {
> > -      cached_polymorphic_call_targets = pointer_set_create ();
> > +      cached_polymorphic_call_targets = new hash_set<cgraph_node *>;
> >        polymorphic_call_target_hash
> >                 = new polymorphic_call_target_hash_type (23);
> >        if (!node_removal_hook_holder)
> > @@ -2496,8 +2493,8 @@ possible_polymorphic_call_targets (tree otr_type,
> >    (*slot)->otr_token = otr_token;
> >    (*slot)->context = context;
> >
> > -  inserted = pointer_set_create ();
> > -  matched_vtables = pointer_set_create ();
> > +  hash_set<tree> inserted;
> > +  hash_set<tree> matched_vtables;
> >
> >    /* First see virtual method of type itself.  */
> >    binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type),
> > @@ -2526,7 +2523,7 @@ possible_polymorphic_call_targets (tree otr_type,
> >
> >    /* If OUTER_TYPE is abstract, we know we are not seeing its instance.  */
> >    if (type_possibly_instantiated_p (outer_type->type))
> > -    maybe_record_node (nodes, target, inserted, can_refer, &complete);
> > +    maybe_record_node (nodes, target, &inserted, can_refer, &complete);
> >    else
> >      {
> >        skipped = true;
> > @@ -2534,7 +2531,7 @@ possible_polymorphic_call_targets (tree otr_type,
> >      }
> >
> >    if (binfo)
> > -    pointer_set_insert (matched_vtables, BINFO_VTABLE (binfo));
> > +    matched_vtables.add (BINFO_VTABLE (binfo));
> >
> >    /* Next walk recursively all derived types.  */
> >    if (context.maybe_derived_type)
> > @@ -2544,8 +2541,8 @@ possible_polymorphic_call_targets (tree otr_type,
> >        if (!type->all_derivations_known)
> >         complete = false;
> >        for (i = 0; i < outer_type->derived_types.length(); i++)
> > -       possible_polymorphic_call_targets_1 (nodes, inserted,
> > -                                            matched_vtables,
> > +       possible_polymorphic_call_targets_1 (nodes, &inserted,
> > +                                            &matched_vtables,
> >                                              otr_type,
> >                                              outer_type->derived_types[i],
> >                                              otr_token, outer_type->type,
> > @@ -2571,12 +2568,12 @@ possible_polymorphic_call_targets (tree otr_type,
> >               || (context.maybe_derived_type
> >                   && !type_all_derivations_known_p (outer_type->type))))
> >         record_targets_from_bases (otr_type, otr_token, outer_type->type,
> > -                                  context.offset, nodes, inserted,
> > -                                  matched_vtables, &complete);
> > +                                  context.offset, nodes, &inserted,
> > +                                  &matched_vtables, &complete);
> >        if (skipped)
> > -        maybe_record_node (nodes, target, inserted, can_refer, &complete);
> > +        maybe_record_node (nodes, target, &inserted, can_refer, &complete);
> >        for (i = 0; i < bases_to_consider.length(); i++)
> > -        maybe_record_node (nodes, bases_to_consider[i], inserted, can_refer, &complete);
> > +        maybe_record_node (nodes, bases_to_consider[i], &inserted, can_refer, &complete);
> >      }
> >    bases_to_consider.release();
> >
> > @@ -2587,8 +2584,6 @@ possible_polymorphic_call_targets (tree otr_type,
> >    if (nonconstruction_targetsp)
> >      *nonconstruction_targetsp = (*slot)->nonconstruction_targets;
> >
> > -  pointer_set_destroy (inserted);
> > -  pointer_set_destroy (matched_vtables);
> >    timevar_pop (TV_IPA_VIRTUAL_CALL);
> >    return nodes;
> >  }
> > @@ -2744,7 +2739,7 @@ static unsigned int
> >  ipa_devirt (void)
> >  {
> >    struct cgraph_node *n;
> > -  struct pointer_set_t *bad_call_targets = pointer_set_create ();
> > +  hash_set<void *> bad_call_targets;
> >    struct cgraph_edge *e;
> >
> >    int npolymorphic = 0, nspeculated = 0, nconverted = 0, ncold = 0;
> > @@ -2792,8 +2787,7 @@ ipa_devirt (void)
> >                 if (!dump_file)
> >                   continue;
> >               }
> > -           if (pointer_set_contains (bad_call_targets,
> > -                                     cache_token))
> > +           if (bad_call_targets.contains (cache_token))
> >               {
> >                 if (dump_file)
> >                   fprintf (dump_file, "Target list is known to be useless\n\n");
> > @@ -2818,7 +2812,7 @@ ipa_devirt (void)
> >                 }
> >             if (!likely_target)
> >               {
> > -               pointer_set_insert (bad_call_targets, cache_token);
> > +               bad_call_targets.add (cache_token);
> >                 continue;
> >               }
> >             /* This is reached only when dumping; check if we agree or disagree
> > @@ -2905,7 +2899,6 @@ ipa_devirt (void)
> >        if (update)
> >         inline_update_overall_summary (n);
> >      }
> > -  pointer_set_destroy (bad_call_targets);
> >
> >    if (dump_file)
> >      fprintf (dump_file,
> > diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
> > index 2c281be..b964502 100644
> > --- a/gcc/ipa-pure-const.c
> > +++ b/gcc/ipa-pure-const.c
> > @@ -65,8 +65,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "tree-scalar-evolution.h"
> >  #include "intl.h"
> >  #include "opts.h"
> > -
> > -static struct pointer_set_t *visited_nodes;
> > +#include "hash-set.h"
> >
> >  /* Lattice values for const and pure functions.  Everything starts out
> >     being const, then may drop to pure and then neither depending on
> > @@ -133,13 +132,13 @@ function_always_visible_to_compiler_p (tree decl)
> >
> >  /* Emit suggestion about attribute ATTRIB_NAME for DECL.  KNOWN_FINITE
> >     is true if the function is known to be finite.  The diagnostic is
> > -   controlled by OPTION.  WARNED_ABOUT is a pointer_set unique for
> > +   controlled by OPTION.  WARNED_ABOUT is a hash_set<tree> unique for
> >     OPTION, this function may initialize it and it is always returned
> >     by the function.  */
> >
> > -static struct pointer_set_t *
> > +static hash_set<tree> *
> >  suggest_attribute (int option, tree decl, bool known_finite,
> > -                  struct pointer_set_t *warned_about,
> > +                  hash_set<tree> *warned_about,
> >                    const char * attrib_name)
> >  {
> >    if (!option_enabled (option, &global_options))
> > @@ -149,10 +148,10 @@ suggest_attribute (int option, tree decl, bool known_finite,
> >      return warned_about;
> >
> >    if (!warned_about)
> > -    warned_about = pointer_set_create ();
> > -  if (pointer_set_contains (warned_about, decl))
> > +    warned_about = new hash_set<tree>;
> > +  if (warned_about->contains (decl))
> >      return warned_about;
> > -  pointer_set_insert (warned_about, decl);
> > +  warned_about->add (decl);
> >    warning_at (DECL_SOURCE_LOCATION (decl),
> >               option,
> >               known_finite
> > @@ -168,7 +167,7 @@ suggest_attribute (int option, tree decl, bool known_finite,
> >  static void
> >  warn_function_pure (tree decl, bool known_finite)
> >  {
> > -  static struct pointer_set_t *warned_about;
> > +  static hash_set<tree> *warned_about;
> >
> >    warned_about
> >      = suggest_attribute (OPT_Wsuggest_attribute_pure, decl,
> > @@ -181,7 +180,7 @@ warn_function_pure (tree decl, bool known_finite)
> >  static void
> >  warn_function_const (tree decl, bool known_finite)
> >  {
> > -  static struct pointer_set_t *warned_about;
> > +  static hash_set<tree> *warned_about;
> >    warned_about
> >      = suggest_attribute (OPT_Wsuggest_attribute_const, decl,
> >                          known_finite, warned_about, "const");
> > @@ -190,7 +189,7 @@ warn_function_const (tree decl, bool known_finite)
> >  static void
> >  warn_function_noreturn (tree decl)
> >  {
> > -  static struct pointer_set_t *warned_about;
> > +  static hash_set<tree> *warned_about;
> >    if (!lang_hooks.missing_noreturn_ok_p (decl)
> >        && targetm.warn_func_return (decl))
> >      warned_about
> > @@ -846,11 +845,8 @@ add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
> >       static declarations.  We do not need to scan them more than once
> >       since all we would be interested in are the addressof
> >       operations.  */
> > -  visited_nodes = pointer_set_create ();
> >    if (node->get_availability () > AVAIL_INTERPOSABLE)
> >      set_function_state (node, analyze_function (node, true));
> > -  pointer_set_destroy (visited_nodes);
> > -  visited_nodes = NULL;
> >  }
> >
> >  /* Called when new clone is inserted to callgraph late.  */
> > @@ -912,12 +908,6 @@ pure_const_generate_summary (void)
> >
> >    register_hooks ();
> >
> > -  /* There are some shared nodes, in particular the initializers on
> > -     static declarations.  We do not need to scan them more than once
> > -     since all we would be interested in are the addressof
> > -     operations.  */
> > -  visited_nodes = pointer_set_create ();
> > -
> >    /* Process all of the functions.
> >
> >       We process AVAIL_INTERPOSABLE functions.  We can not use the results
> > @@ -927,9 +917,6 @@ pure_const_generate_summary (void)
> >    FOR_EACH_DEFINED_FUNCTION (node)
> >      if (node->get_availability () >= AVAIL_INTERPOSABLE)
> >        set_function_state (node, analyze_function (node, true));
> > -
> > -  pointer_set_destroy (visited_nodes);
> > -  visited_nodes = NULL;
> >  }
> >
> >
> > diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
> > index 4720ee9..bca2bc7 100644
> > --- a/gcc/ipa-visibility.c
> > +++ b/gcc/ipa-visibility.c
> > @@ -687,12 +687,11 @@ function_and_variable_visibility (bool whole_program)
> >               }
> >           if (found)
> >             {
> > -             struct pointer_set_t *visited_nodes = pointer_set_create ();
> > +             hash_set<tree> visited_nodes;
> >
> >               vnode->get_constructor ();
> >               walk_tree (&DECL_INITIAL (vnode->decl),
> > -                        update_vtable_references, NULL, visited_nodes);
> > -             pointer_set_destroy (visited_nodes);
> > +                        update_vtable_references, NULL, &visited_nodes);
> >               vnode->remove_all_references ();
> >               record_references_in_initializer (vnode->decl, false);
> >             }
> > diff --git a/gcc/ipa.c b/gcc/ipa.c
> > index 8198b17..1081e89 100644
> > --- a/gcc/ipa.c
> > +++ b/gcc/ipa.c
> > @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "cgraph.h"
> >  #include "tree-pass.h"
> >  #include "hash-map.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "gimple-expr.h"
> >  #include "gimplify.h"
> >  #include "flags.h"
> > @@ -84,14 +84,14 @@ update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined
> >
> >  static void
> >  enqueue_node (symtab_node *node, symtab_node **first,
> > -             struct pointer_set_t *reachable)
> > +             hash_set<symtab_node *> *reachable)
> >  {
> >    /* Node is still in queue; do nothing.  */
> >    if (node->aux && node->aux != (void *) 2)
> >      return;
> >    /* Node was already processed as unreachable, re-enqueue
> >       only if it became reachable now.  */
> > -  if (node->aux == (void *)2 && !pointer_set_contains (reachable, node))
> > +  if (node->aux == (void *)2 && !reachable->contains (node))
> >      return;
> >    node->aux = *first;
> >    *first = node;
> > @@ -103,7 +103,7 @@ static void
> >  process_references (symtab_node *snode,
> >                     symtab_node **first,
> >                     bool before_inlining_p,
> > -                   struct pointer_set_t *reachable)
> > +                   hash_set<symtab_node *> *reachable)
> >  {
> >    int i;
> >    struct ipa_ref *ref = NULL;
> > @@ -124,7 +124,7 @@ process_references (symtab_node *snode,
> >                       && flag_wpa
> >                       && ctor_for_folding (node->decl)
> >                          != error_mark_node))))
> > -       pointer_set_insert (reachable, node);
> > +       reachable->add (node);
> >        enqueue_node (node, first, reachable);
> >      }
> >  }
> > @@ -138,10 +138,11 @@ process_references (symtab_node *snode,
> >     possible.  */
> >
> >  static void
> > -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> > +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
> >                                struct cgraph_edge *edge,
> >                                symtab_node **first,
> > -                              pointer_set_t *reachable, bool before_inlining_p)
> > +                              hash_set<symtab_node *> *reachable,
> > +                              bool before_inlining_p)
> >  {
> >    unsigned int i;
> >    void *cache_token;
> > @@ -150,8 +151,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> >      = possible_polymorphic_call_targets
> >         (edge, &final, &cache_token);
> >
> > -  if (!pointer_set_insert (reachable_call_targets,
> > -                          cache_token))
> > +  if (!reachable_call_targets->add (cache_token))
> >      {
> >        for (i = 0; i < targets.length (); i++)
> >         {
> > @@ -172,7 +172,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> >                    && (cgraph_state < CGRAPH_STATE_IPA_SSA
> >                        || !lookup_attribute ("always_inline",
> >                                              DECL_ATTRIBUTES (n->decl)))))
> > -            pointer_set_insert (reachable, n);
> > +            reachable->add (n);
> >
> >           /* Even after inlining we want to keep the possible targets in the
> >              boundary, so late passes can still produce direct call even if
> > @@ -276,9 +276,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >    struct cgraph_node *node, *next;
> >    varpool_node *vnode, *vnext;
> >    bool changed = false;
> > -  struct pointer_set_t *reachable = pointer_set_create ();
> > -  struct pointer_set_t *body_needed_for_clonning = pointer_set_create ();
> > -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> > +  hash_set<symtab_node *> reachable;
> > +  hash_set<tree> body_needed_for_clonning;
> > +  hash_set<void *> reachable_call_targets;
> >
> >    timevar_push (TV_IPA_UNREACHABLE);
> >    if (optimize && flag_devirtualize)
> > @@ -304,8 +304,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >           && !node->can_remove_if_no_direct_calls_and_refs_p ())
> >         {
> >           gcc_assert (!node->global.inlined_to);
> > -         pointer_set_insert (reachable, node);
> > -         enqueue_node (node, &first, reachable);
> > +         reachable.add (node);
> > +         enqueue_node (node, &first, &reachable);
> >         }
> >        else
> >         gcc_assert (!node->aux);
> > @@ -316,14 +316,14 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >      if (!vnode->can_remove_if_no_refs_p()
> >         && !vnode->in_other_partition)
> >        {
> > -       pointer_set_insert (reachable, vnode);
> > -       enqueue_node (vnode, &first, reachable);
> > +       reachable.add (vnode);
> > +       enqueue_node (vnode, &first, &reachable);
> >        }
> >
> >    /* Perform reachability analysis.  */
> >    while (first != (symtab_node *) (void *) 1)
> >      {
> > -      bool in_boundary_p = !pointer_set_contains (reachable, first);
> > +      bool in_boundary_p = !reachable.contains (first);
> >        symtab_node *node = first;
> >
> >        first = (symtab_node *)first->aux;
> > @@ -340,7 +340,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >               struct cgraph_node *origin_node
> >               = cgraph_node::get_create (DECL_ABSTRACT_ORIGIN (node->decl));
> >               origin_node->used_as_abstract_origin = true;
> > -             enqueue_node (origin_node, &first, reachable);
> > +             enqueue_node (origin_node, &first, &reachable);
> >             }
> >           /* If any symbol in a comdat group is reachable, force
> >              all externally visible symbols in the same comdat
> > @@ -353,11 +353,11 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >                    next != node;
> >                    next = next->same_comdat_group)
> >                 if (!next->comdat_local_p ()
> > -                   && !pointer_set_insert (reachable, next))
> > -                 enqueue_node (next, &first, reachable);
> > +                   && !reachable.add (next))
> > +                 enqueue_node (next, &first, &reachable);
> >             }
> >           /* Mark references as reachable.  */
> > -         process_references (node, &first, before_inlining_p, reachable);
> > +         process_references (node, &first, before_inlining_p, &reachable);
> >         }
> >
> >        if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
> > @@ -375,8 +375,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >                     {
> >                       next = e->next_callee;
> >                       if (e->indirect_info->polymorphic)
> > -                       walk_polymorphic_call_targets (reachable_call_targets,
> > -                                                      e, &first, reachable,
> > +                       walk_polymorphic_call_targets (&reachable_call_targets,
> > +                                                      e, &first, &reachable,
> >                                                        before_inlining_p);
> >                     }
> >                 }
> > @@ -394,17 +394,16 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >                       if (DECL_EXTERNAL (e->callee->decl)
> >                           && e->callee->alias
> >                           && before_inlining_p)
> > -                       pointer_set_insert (reachable,
> > -                                           e->callee->function_symbol ());
> > -                     pointer_set_insert (reachable, e->callee);
> > +                       reachable.add (e->callee->function_symbol ());
> > +                     reachable.add (e->callee);
> >                     }
> > -                 enqueue_node (e->callee, &first, reachable);
> > +                 enqueue_node (e->callee, &first, &reachable);
> >                 }
> >
> >               /* When inline clone exists, mark body to be preserved so when removing
> >                  offline copy of the function we don't kill it.  */
> >               if (cnode->global.inlined_to)
> > -               pointer_set_insert (body_needed_for_clonning, cnode->decl);
> > +               body_needed_for_clonning.add (cnode->decl);
> >
> >               /* For non-inline clones, force their origins to the boundary and ensure
> >                  that body is not removed.  */
> > @@ -414,8 +413,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >                   cnode = cnode->clone_of;
> >                   if (noninline)
> >                     {
> > -                     pointer_set_insert (body_needed_for_clonning, cnode->decl);
> > -                     enqueue_node (cnode, &first, reachable);
> > +                     body_needed_for_clonning.add (cnode->decl);
> > +                     enqueue_node (cnode, &first, &reachable);
> >                     }
> >                 }
> >
> > @@ -429,8 +428,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >                    next;
> >                    next = next->simdclone->next_clone)
> >                 if (in_boundary_p
> > -                   || !pointer_set_insert (reachable, next))
> > -                 enqueue_node (next, &first, reachable);
> > +                   || !reachable.add (next))
> > +                 enqueue_node (next, &first, &reachable);
> >             }
> >         }
> >        /* When we see constructor of external variable, keep referred nodes in the
> > @@ -444,7 +443,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >         {
> >           struct ipa_ref *ref = NULL;
> >           for (int i = 0; node->iterate_reference (i, ref); i++)
> > -           enqueue_node (ref->referred, &first, reachable);
> > +           enqueue_node (ref->referred, &first, &reachable);
> >         }
> >      }
> >
> > @@ -462,9 +461,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >           changed = true;
> >         }
> >        /* If node is unreachable, remove its body.  */
> > -      else if (!pointer_set_contains (reachable, node))
> > +      else if (!reachable.contains (node))
> >          {
> > -         if (!pointer_set_contains (body_needed_for_clonning, node->decl))
> > +         if (!body_needed_for_clonning.contains (node->decl))
> >             node->release_body ();
> >           else if (!node->clone_of)
> >             gcc_assert (in_lto_p || DECL_RESULT (node->decl));
> > @@ -530,7 +529,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >           vnode->remove ();
> >           changed = true;
> >         }
> > -      else if (!pointer_set_contains (reachable, vnode))
> > +      else if (!reachable.contains (vnode))
> >          {
> >           tree init;
> >           if (vnode->definition)
> > @@ -557,10 +556,6 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >         vnode->aux = NULL;
> >      }
> >
> > -  pointer_set_destroy (reachable);
> > -  pointer_set_destroy (body_needed_for_clonning);
> > -  pointer_set_destroy (reachable_call_targets);
> > -
> >    /* Now update address_taken flags and try to promote functions to be local.  */
> >    if (file)
> >      fprintf (file, "\nClearing address taken flags:");
> > diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
> > index b1fcf67..42b0790 100644
> > --- a/gcc/lto-cgraph.c
> > +++ b/gcc/lto-cgraph.c
> > @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "params.h"
> >  #include "input.h"
> >  #include "hashtab.h"
> > +#include "hash-set.h"
> >  #include "langhooks.h"
> >  #include "bitmap.h"
> >  #include "function.h"
> > @@ -819,7 +820,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
> >    int i;
> >    lto_symtab_encoder_t encoder;
> >    lto_symtab_encoder_iterator lsei;
> > -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> > +  hash_set<void *> reachable_call_targets;
> >
> >    encoder = lto_symtab_encoder_new (false);
> >
> > @@ -902,8 +903,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
> >               vec <cgraph_node *>targets
> >                 = possible_polymorphic_call_targets
> >                     (edge, &final, &cache_token);
> > -             if (!pointer_set_insert (reachable_call_targets,
> > -                                      cache_token))
> > +             if (!reachable_call_targets.add (cache_token))
> >                 {
> >                   for (i = 0; i < targets.length (); i++)
> >                     {
> > @@ -923,7 +923,6 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
> >             }
> >      }
> >    lto_symtab_encoder_delete (in_encoder);
> > -  pointer_set_destroy (reachable_call_targets);
> >    return encoder;
> >  }
> >
> > diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
> > index 271fbd5..3fd9147 100644
> > --- a/gcc/lto-streamer-out.c
> > +++ b/gcc/lto-streamer-out.c
> > @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "params.h"
> >  #include "input.h"
> >  #include "hashtab.h"
> > +#include "hash-set.h"
> >  #include "basic-block.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> > @@ -2433,7 +2434,7 @@ lto_out_decl_state_written_size (struct lto_out_decl_state *state)
> >  static void
> >  write_symbol (struct streamer_tree_cache_d *cache,
> >               struct lto_output_stream *stream,
> > -             tree t, struct pointer_set_t *seen, bool alias)
> > +             tree t, hash_set<const char *> *seen, bool alias)
> >  {
> >    const char *name;
> >    enum gcc_plugin_symbol_kind kind;
> > @@ -2461,9 +2462,8 @@ write_symbol (struct streamer_tree_cache_d *cache,
> >       same name manipulations that ASM_OUTPUT_LABELREF does. */
> >    name = IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name) (name));
> >
> > -  if (pointer_set_contains (seen, name))
> > +  if (seen->add (name))
> >      return;
> > -  pointer_set_insert (seen, name);
> >
> >    streamer_tree_cache_lookup (cache, t, &slot_num);
> >    gcc_assert (slot_num != (unsigned)-1);
> > @@ -2588,7 +2588,6 @@ produce_symtab (struct output_block *ob)
> >  {
> >    struct streamer_tree_cache_d *cache = ob->writer_cache;
> >    char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
> > -  struct pointer_set_t *seen;
> >    struct lto_output_stream stream;
> >    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
> >    lto_symtab_encoder_iterator lsei;
> > @@ -2596,7 +2595,7 @@ produce_symtab (struct output_block *ob)
> >    lto_begin_section (section_name, false);
> >    free (section_name);
> >
> > -  seen = pointer_set_create ();
> > +  hash_set<const char *> seen;
> >    memset (&stream, 0, sizeof (stream));
> >
> >    /* Write the symbol table.
> > @@ -2609,7 +2608,7 @@ produce_symtab (struct output_block *ob)
> >
> >        if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
> >         continue;
> > -      write_symbol (cache, &stream, node->decl, seen, false);
> > +      write_symbol (cache, &stream, node->decl, &seen, false);
> >      }
> >    for (lsei = lsei_start (encoder);
> >         !lsei_end_p (lsei); lsei_next (&lsei))
> > @@ -2618,11 +2617,10 @@ produce_symtab (struct output_block *ob)
> >
> >        if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
> >         continue;
> > -      write_symbol (cache, &stream, node->decl, seen, false);
> > +      write_symbol (cache, &stream, node->decl, &seen, false);
> >      }
> >
> >    lto_write_stream (&stream);
> > -  pointer_set_destroy (seen);
> >
> >    lto_end_section ();
> >  }
> > diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
> > index cb08a88..a5bcf92 100644
> > --- a/gcc/lto/lto-partition.c
> > +++ b/gcc/lto/lto-partition.c
> > @@ -66,7 +66,7 @@ free_ltrans_partitions (void)
> >    for (idx = 0; ltrans_partitions.iterate (idx, &part); idx++)
> >      {
> >        if (part->initializers_visited)
> > -       pointer_set_destroy (part->initializers_visited);
> > +       delete part->initializers_visited;
> >        /* Symtab encoder is freed after streaming.  */
> >        free (part);
> >      }
> > @@ -101,8 +101,8 @@ add_references_to_partition (ltrans_partition part, symtab_node *node)
> >              && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
> >        {
> >         if (!part->initializers_visited)
> > -         part->initializers_visited = pointer_set_create ();
> > -       if (!pointer_set_insert (part->initializers_visited, ref->referred))
> > +         part->initializers_visited = new hash_set<symtab_node *>;
> > +       if (!part->initializers_visited->add (ref->referred))
> >           add_references_to_partition (part, ref->referred);
> >        }
> >  }
> > @@ -250,7 +250,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes)
> >
> >        /* After UNDO we no longer know what was visited.  */
> >        if (partition->initializers_visited)
> > -       pointer_set_destroy (partition->initializers_visited);
> > +       delete partition->initializers_visited;
> >        partition->initializers_visited = NULL;
> >
> >        if (!node->alias && (cnode = dyn_cast <cgraph_node *> (node)))
> > diff --git a/gcc/lto/lto-partition.h b/gcc/lto/lto-partition.h
> > index 8db61b3..50ec2fa 100644
> > --- a/gcc/lto/lto-partition.h
> > +++ b/gcc/lto/lto-partition.h
> > @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
> >  along with GCC; see the file COPYING3.  If not see
> >  <http://www.gnu.org/licenses/>.  */
> >
> > +#include "hash-set.h"
> >
> >  /* Structure describing ltrans partitions.  */
> >
> > @@ -25,7 +26,7 @@ struct ltrans_partition_def
> >    lto_symtab_encoder_t encoder;
> >    const char * name;
> >    int insns;
> > -  pointer_set_t *initializers_visited;
> > +  hash_set<symtab_node *> *initializers_visited;
> >  };
> >
> >  typedef struct ltrans_partition_def *ltrans_partition;
> > diff --git a/gcc/stmt.c b/gcc/stmt.c
> > index 0aae085..55ec279 100644
> > --- a/gcc/stmt.c
> > +++ b/gcc/stmt.c
> > @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "predict.h"
> >  #include "optabs.h"
> >  #include "target.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "basic-block.h"
> >  #include "tree-ssa-alias.h"
> > @@ -1183,7 +1184,7 @@ expand_case (gimple stmt)
> >       how to expand this switch().  */
> >    uniq = 0;
> >    count = 0;
> > -  struct pointer_set_t *seen_labels = pointer_set_create ();
> > +  hash_set<tree> seen_labels;
> >    compute_cases_per_edge (stmt);
> >
> >    for (i = ncases - 1; i >= 1; --i)
> > @@ -1203,7 +1204,7 @@ expand_case (gimple stmt)
> >
> >        /* If we have not seen this label yet, then increase the
> >          number of unique case node targets seen.  */
> > -      if (!pointer_set_insert (seen_labels, lab))
> > +      if (!seen_labels.add (lab))
> >         uniq++;
> >
> >        /* The bounds on the case range, LOW and HIGH, have to be converted
> > @@ -1231,7 +1232,6 @@ expand_case (gimple stmt)
> >            case_edge->probability / (intptr_t)(case_edge->aux),
> >            case_node_pool);
> >      }
> > -  pointer_set_destroy (seen_labels);
> >    reset_out_edges_aux (bb);
> >
> >    /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
> > diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> > index 6fee8a4..e034762 100644
> > --- a/gcc/tree-cfg.c
> > +++ b/gcc/tree-cfg.c
> > @@ -4691,7 +4691,7 @@ tree_node_can_be_shared (tree t)
> >  static tree
> >  verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
> >  {
> > -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> > +  hash_set<void *> *visited = (hash_set<void *> *) data;
> >
> >    if (tree_node_can_be_shared (*tp))
> >      {
> > @@ -4699,7 +4699,7 @@ verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
> >        return NULL;
> >      }
> >
> > -  if (pointer_set_insert (visited, *tp))
> > +  if (visited->add (*tp))
> >      return *tp;
> >
> >    return NULL;
> > @@ -4719,9 +4719,9 @@ static int
> >  verify_eh_throw_stmt_node (void **slot, void *data)
> >  {
> >    struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
> > -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> > +  hash_set<void *> *visited = (hash_set<void *> *) data;
> >
> > -  if (!pointer_set_contains (visited, node->stmt))
> > +  if (!visited->contains (node->stmt))
> >      {
> >        error ("dead STMT in EH table");
> >        debug_gimple_stmt (node->stmt);
> > @@ -4733,11 +4733,11 @@ verify_eh_throw_stmt_node (void **slot, void *data)
> >  /* Verify if the location LOCs block is in BLOCKS.  */
> >
> >  static bool
> > -verify_location (pointer_set_t *blocks, location_t loc)
> > +verify_location (hash_set<tree> *blocks, location_t loc)
> >  {
> >    tree block = LOCATION_BLOCK (loc);
> >    if (block != NULL_TREE
> > -      && !pointer_set_contains (blocks, block))
> > +      && !blocks->contains (block))
> >      {
> >        error ("location references block not in block tree");
> >        return true;
> > @@ -4770,7 +4770,7 @@ verify_expr_no_block (tree *tp, int *walk_subtrees, void *)
> >  static tree
> >  verify_expr_location_1 (tree *tp, int *walk_subtrees, void *data)
> >  {
> > -  struct pointer_set_t *blocks = (struct pointer_set_t *) data;
> > +  hash_set<tree> *blocks = (hash_set<tree> *) data;
> >
> >    if (TREE_CODE (*tp) == VAR_DECL
> >        && DECL_HAS_DEBUG_EXPR_P (*tp))
> > @@ -4816,12 +4816,12 @@ verify_expr_location (tree *tp, int *walk_subtrees, void *data)
> >  /* Insert all subblocks of BLOCK into BLOCKS and recurse.  */
> >
> >  static void
> > -collect_subblocks (pointer_set_t *blocks, tree block)
> > +collect_subblocks (hash_set<tree> *blocks, tree block)
> >  {
> >    tree t;
> >    for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
> >      {
> > -      pointer_set_insert (blocks, t);
> > +      blocks->add (t);
> >        collect_subblocks (blocks, t);
> >      }
> >  }
> > @@ -4833,18 +4833,17 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >  {
> >    basic_block bb;
> >    bool err = false;
> > -  struct pointer_set_t *visited, *visited_stmts, *blocks;
> >
> >    timevar_push (TV_TREE_STMT_VERIFY);
> > -  visited = pointer_set_create ();
> > -  visited_stmts = pointer_set_create ();
> > +  hash_set<void *> visited;
> > +  hash_set<gimple> visited_stmts;
> >
> >    /* Collect all BLOCKs referenced by the BLOCK tree of FN.  */
> > -  blocks = pointer_set_create ();
> > +  hash_set<tree> blocks;
> >    if (DECL_INITIAL (fn->decl))
> >      {
> > -      pointer_set_insert (blocks, DECL_INITIAL (fn->decl));
> > -      collect_subblocks (blocks, DECL_INITIAL (fn->decl));
> > +      blocks.add (DECL_INITIAL (fn->decl));
> > +      collect_subblocks (&blocks, DECL_INITIAL (fn->decl));
> >      }
> >
> >    FOR_EACH_BB_FN (bb, fn)
> > @@ -4857,7 +4856,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >           bool err2 = false;
> >           unsigned i;
> >
> > -         pointer_set_insert (visited_stmts, phi);
> > +         visited_stmts.add (phi);
> >
> >           if (gimple_bb (phi) != bb)
> >             {
> > @@ -4878,7 +4877,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >             {
> >               tree arg = gimple_phi_arg_def (phi, i);
> >               tree addr = walk_tree (&arg, verify_node_sharing_1,
> > -                                    visited, NULL);
> > +                                    &visited, NULL);
> >               if (addr)
> >                 {
> >                   error ("incorrect sharing of tree nodes");
> > @@ -4892,13 +4891,13 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >                   error ("virtual PHI with argument locations");
> >                   err2 = true;
> >                 }
> > -             addr = walk_tree (&arg, verify_expr_location_1, blocks, NULL);
> > +             addr = walk_tree (&arg, verify_expr_location_1, &blocks, NULL);
> >               if (addr)
> >                 {
> >                   debug_generic_expr (addr);
> >                   err2 = true;
> >                 }
> > -             err2 |= verify_location (blocks, loc);
> > +             err2 |= verify_location (&blocks, loc);
> >             }
> >
> >           if (err2)
> > @@ -4914,7 +4913,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >           tree addr;
> >           int lp_nr;
> >
> > -         pointer_set_insert (visited_stmts, stmt);
> > +         visited_stmts.add (stmt);
> >
> >           if (gimple_bb (stmt) != bb)
> >             {
> > @@ -4923,10 +4922,10 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >             }
> >
> >           err2 |= verify_gimple_stmt (stmt);
> > -         err2 |= verify_location (blocks, gimple_location (stmt));
> > +         err2 |= verify_location (&blocks, gimple_location (stmt));
> >
> >           memset (&wi, 0, sizeof (wi));
> > -         wi.info = (void *) visited;
> > +         wi.info = (void *) &visited;
> >           addr = walk_gimple_op (stmt, verify_node_sharing, &wi);
> >           if (addr)
> >             {
> > @@ -4936,7 +4935,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >             }
> >
> >           memset (&wi, 0, sizeof (wi));
> > -         wi.info = (void *) blocks;
> > +         wi.info = (void *) &blocks;
> >           addr = walk_gimple_op (stmt, verify_expr_location, &wi);
> >           if (addr)
> >             {
> > @@ -4992,14 +4991,11 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >    if (get_eh_throw_stmt_table (cfun))
> >      htab_traverse (get_eh_throw_stmt_table (cfun),
> >                    verify_eh_throw_stmt_node,
> > -                  visited_stmts);
> > +                  &visited_stmts);
> >
> >    if (err || eh_error_found)
> >      internal_error ("verify_gimple failed");
> >
> > -  pointer_set_destroy (visited);
> > -  pointer_set_destroy (visited_stmts);
> > -  pointer_set_destroy (blocks);
> >    verify_histograms ();
> >    timevar_pop (TV_TREE_STMT_VERIFY);
> >  }
> > diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> > index 34c48fa..9d462d1 100644
> > --- a/gcc/tree-core.h
> > +++ b/gcc/tree-core.h
> > @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #define GCC_TREE_CORE_H
> >
> >  #include "hashtab.h"
> > +#include "hash-set.h"
> >  #include "machmode.h"
> >  #include "input.h"
> >  #include "statistics.h"
> > @@ -45,7 +46,6 @@ struct fixed_value;
> >  struct ptr_info_def;
> >  struct range_info_def;
> >  struct die_struct;
> > -struct pointer_set_t;
> >
> >
> >  /*---------------------------------------------------------------------------
> > @@ -692,7 +692,7 @@ typedef tree (*walk_tree_fn) (tree *, int *, void *);
> >
> >  /* The type of a callback function that represents a custom walk_tree.  */
> >  typedef tree (*walk_tree_lh) (tree *, int *, tree (*) (tree *, int *, void *),
> > -                             void *, struct pointer_set_t*);
> > +                             void *, hash_set<tree> *);
> >
> >
> >  /*---------------------------------------------------------------------------
> > diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> > index df9a6fc..38842e8 100644
> > --- a/gcc/tree-eh.c
> > +++ b/gcc/tree-eh.c
> > @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "flags.h"
> >  #include "function.h"
> >  #include "except.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "basic-block.h"
> >  #include "tree-ssa-alias.h"
> > @@ -3578,7 +3579,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
> >         eh_catch c;
> >         edge_iterator ei;
> >         edge e;
> > -       struct pointer_set_t *seen_values = pointer_set_create ();
> > +       hash_set<tree> seen_values;
> >
> >         /* Collect the labels for a switch.  Zero the post_landing_pad
> >            field becase we'll no longer have anything keeping these labels
> > @@ -3605,12 +3606,12 @@ lower_eh_dispatch (basic_block src, gimple stmt)
> >                    attached to the handler anymore, we remove
> >                    the corresponding edge and then we delete unreachable
> >                    blocks at the end of this pass.  */
> > -               if (! pointer_set_contains (seen_values, TREE_VALUE (flt_node)))
> > +               if (! seen_values.contains (TREE_VALUE (flt_node)))
> >                   {
> >                     tree t = build_case_label (TREE_VALUE (flt_node),
> >                                                NULL, lab);
> >                     labels.safe_push (t);
> > -                   pointer_set_insert (seen_values, TREE_VALUE (flt_node));
> > +                   seen_values.add (TREE_VALUE (flt_node));
> >                     have_label = true;
> >                   }
> >
> > @@ -3662,7 +3663,6 @@ lower_eh_dispatch (basic_block src, gimple stmt)
> >             x = gimple_build_switch (filter, default_label, labels);
> >             gsi_insert_before (&gsi, x, GSI_SAME_STMT);
> >           }
> > -       pointer_set_destroy (seen_values);
> >        }
> >        break;
> >
> > diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> > index 33705b7..6af4912 100644
> > --- a/gcc/tree-inline.c
> > +++ b/gcc/tree-inline.c
> > @@ -1788,7 +1788,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
> >              expensive, copy_body can be told to watch for nontrivial
> >              changes.  */
> >           if (id->statements_to_fold)
> > -           pointer_set_insert (id->statements_to_fold, stmt);
> > +           id->statements_to_fold->add (stmt);
> >
> >           /* We're duplicating a CALL_EXPR.  Find any corresponding
> >              callgraph edges and update or duplicate them.  */
> > @@ -3507,7 +3507,6 @@ inline_forbidden_p (tree fndecl)
> >  {
> >    struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
> >    struct walk_stmt_info wi;
> > -  struct pointer_set_t *visited_nodes;
> >    basic_block bb;
> >    bool forbidden_p = false;
> >
> > @@ -3518,10 +3517,10 @@ inline_forbidden_p (tree fndecl)
> >
> >    /* Next, walk the statements of the function looking for
> >       constraucts we can't handle, or are non-optimal for inlining.  */
> > -  visited_nodes = pointer_set_create ();
> > +  hash_set<tree> visited_nodes;
> >    memset (&wi, 0, sizeof (wi));
> >    wi.info = (void *) fndecl;
> > -  wi.pset = visited_nodes;
> > +  wi.pset = &visited_nodes;
> >
> >    FOR_EACH_BB_FN (bb, fun)
> >      {
> > @@ -3533,7 +3532,6 @@ inline_forbidden_p (tree fndecl)
> >         break;
> >      }
> >
> > -  pointer_set_destroy (visited_nodes);
> >    return forbidden_p;
> >  }
> >
> > @@ -4531,7 +4529,7 @@ gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
> >     in the STATEMENTS pointer set.  */
> >
> >  static void
> > -fold_marked_statements (int first, struct pointer_set_t *statements)
> > +fold_marked_statements (int first, hash_set<gimple> *statements)
> >  {
> >    for (; first < n_basic_blocks_for_fn (cfun); first++)
> >      if (BASIC_BLOCK_FOR_FN (cfun, first))
> > @@ -4541,7 +4539,7 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
> >         for (gsi = gsi_start_bb (BASIC_BLOCK_FOR_FN (cfun, first));
> >              !gsi_end_p (gsi);
> >              gsi_next (&gsi))
> > -         if (pointer_set_contains (statements, gsi_stmt (gsi)))
> > +         if (statements->contains (gsi_stmt (gsi)))
> >             {
> >               gimple old_stmt = gsi_stmt (gsi);
> >               tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
> > @@ -4642,7 +4640,7 @@ optimize_inline_calls (tree fn)
> >    id.transform_return_to_modify = true;
> >    id.transform_parameter = true;
> >    id.transform_lang_insert_block = NULL;
> > -  id.statements_to_fold = pointer_set_create ();
> > +  id.statements_to_fold = new hash_set<gimple>;
> >
> >    push_gimplify_context ();
> >
> > @@ -4678,7 +4676,7 @@ optimize_inline_calls (tree fn)
> >
> >    /* Fold queued statements.  */
> >    fold_marked_statements (last, id.statements_to_fold);
> > -  pointer_set_destroy (id.statements_to_fold);
> > +  delete id.statements_to_fold;
> >
> >    gcc_assert (!id.debug_stmts.exists ());
> >
> > @@ -4920,7 +4918,6 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
> >  {
> >    copy_body_data id;
> >    struct walk_stmt_info wi;
> > -  struct pointer_set_t *visited;
> >    gimple_seq copy;
> >
> >    /* There's nothing to do for NULL_TREE.  */
> > @@ -4943,11 +4940,10 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
> >
> >    /* Walk the tree once to find local labels.  */
> >    memset (&wi, 0, sizeof (wi));
> > -  visited = pointer_set_create ();
> > +  hash_set<tree> visited;
> >    wi.info = &id;
> > -  wi.pset = visited;
> > +  wi.pset = &visited;
> >    walk_gimple_seq (seq, mark_local_labels_stmt, NULL, &wi);
> > -  pointer_set_destroy (visited);
> >
> >    copy = gimple_seq_copy (seq);
> >
> > @@ -5370,7 +5366,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
> >    memset (&id, 0, sizeof (id));
> >
> >    /* Generate a new name for the new version. */
> > -  id.statements_to_fold = pointer_set_create ();
> > +  id.statements_to_fold = new hash_set<gimple>;
> >
> >    id.decl_map = pointer_map_create ();
> >    id.debug_map = NULL;
> > @@ -5541,7 +5537,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
> >    free_dominance_info (CDI_POST_DOMINATORS);
> >
> >    fold_marked_statements (0, id.statements_to_fold);
> > -  pointer_set_destroy (id.statements_to_fold);
> > +  delete id.statements_to_fold;
> >    fold_cond_expr_cond ();
> >    delete_unreachable_blocks_update_callgraph (&id);
> >    if (id.dst_node->definition)
> > diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
> > index 2a5daaf..c13e6c7 100644
> > --- a/gcc/tree-inline.h
> > +++ b/gcc/tree-inline.h
> > @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
> >  #ifndef GCC_TREE_INLINE_H
> >  #define GCC_TREE_INLINE_H
> >
> > +#include "hash-set.h"
> > +
> >  struct cgraph_edge;
> >
> >  /* Indicate the desired behavior wrt call graph edges.  We can either
> > @@ -114,7 +116,7 @@ struct copy_body_data
> >    void (*transform_lang_insert_block) (tree);
> >
> >    /* Statements that might be possibly folded.  */
> > -  struct pointer_set_t *statements_to_fold;
> > +  hash_set<gimple> *statements_to_fold;
> >
> >    /* Entry basic block to currently copied body.  */
> >    basic_block entry_bb;
> > diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
> > index 185d87c..45c5cf7 100644
> > --- a/gcc/tree-nested.c
> > +++ b/gcc/tree-nested.c
> > @@ -95,7 +95,7 @@ struct nesting_info
> >
> >    struct pointer_map_t *field_map;
> >    struct pointer_map_t *var_map;
> > -  struct pointer_set_t *mem_refs;
> > +  hash_set<tree *> *mem_refs;
> >    bitmap suppress_expansion;
> >
> >    tree context;
> > @@ -732,7 +732,7 @@ create_nesting_tree (struct cgraph_node *cgn)
> >    struct nesting_info *info = XCNEW (struct nesting_info);
> >    info->field_map = pointer_map_create ();
> >    info->var_map = pointer_map_create ();
> > -  info->mem_refs = pointer_set_create ();
> > +  info->mem_refs = new hash_set<tree *>;
> >    info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
> >    info->context = cgn->decl;
> >
> > @@ -1651,7 +1651,7 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
> >          fold here, as the chain record type is not yet finalized.  */
> >        if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
> >           && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
> > -       pointer_set_insert (info->mem_refs, tp);
> > +       info->mem_refs->add (tp);
> >        wi->val_only = save_val_only;
> >        break;
> >
> > @@ -2655,8 +2655,8 @@ remap_vla_decls (tree block, struct nesting_info *root)
> >  }
> >
> >  /* Fold the MEM_REF *E.  */
> > -static bool
> > -fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED)
> > +bool
> > +fold_mem_refs (tree *const &e, void *data ATTRIBUTE_UNUSED)
> >  {
> >    tree *ref_p = CONST_CAST2 (tree *, const tree *, (const tree *)e);
> >    *ref_p = fold (*ref_p);
> > @@ -2878,7 +2878,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
> >      }
> >
> >    /* Fold the rewritten MEM_REF trees.  */
> > -  pointer_set_traverse (root->mem_refs, fold_mem_refs, NULL);
> > +  root->mem_refs->traverse<void *, fold_mem_refs> (NULL);
> >
> >    /* Dump the translated tree function.  */
> >    if (dump_file)
> > @@ -2933,7 +2933,7 @@ free_nesting_tree (struct nesting_info *root)
> >        next = iter_nestinfo_next (node);
> >        pointer_map_destroy (node->var_map);
> >        pointer_map_destroy (node->field_map);
> > -      pointer_set_destroy (node->mem_refs);
> > +      delete node->mem_refs;
> >        free (node);
> >        node = next;
> >      }
> > diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
> > index ca6e014..aee0331 100644
> > --- a/gcc/tree-pretty-print.c
> > +++ b/gcc/tree-pretty-print.c
> > @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "expr.h"
> >  #include "tree-pretty-print.h"
> >  #include "hashtab.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "gimple-expr.h"
> >  #include "cgraph.h"
> >  #include "langhooks.h"
> > @@ -103,14 +103,14 @@ debug_generic_stmt (tree t)
> >  DEBUG_FUNCTION void
> >  debug_tree_chain (tree t)
> >  {
> > -  struct pointer_set_t *seen = pointer_set_create ();
> > +  hash_set<tree> seen;
> >
> >    while (t)
> >      {
> >        print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
> >        fprintf (stderr, " ");
> >        t = TREE_CHAIN (t);
> > -      if (pointer_set_insert (seen, t))
> > +      if (seen.add (t))
> >         {
> >           fprintf (stderr, "... [cycled back to ");
> >           print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
> > @@ -119,8 +119,6 @@ debug_tree_chain (tree t)
> >         }
> >      }
> >    fprintf (stderr, "\n");
> > -
> > -  pointer_set_destroy (seen);
> >  }
> >
> >  /* Prints declaration DECL to the FILE with details specified by FLAGS.  */
> > diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
> > index 36d68a8..83c1b19 100644
> > --- a/gcc/tree-ssa-loop-niter.c
> > +++ b/gcc/tree-ssa-loop-niter.c
> > @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "basic-block.h"
> >  #include "gimple-pretty-print.h"
> >  #include "intl.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> > @@ -3281,7 +3282,7 @@ discover_iteration_bound_by_body_walk (struct loop *loop)
> >  static void
> >  maybe_lower_iteration_bound (struct loop *loop)
> >  {
> > -  pointer_set_t *not_executed_last_iteration = NULL;
> > +  hash_set<gimple> *not_executed_last_iteration = NULL;
> >    struct nb_iter_bound *elt;
> >    bool found_exit = false;
> >    vec<basic_block> queue = vNULL;
> > @@ -3300,8 +3301,8 @@ maybe_lower_iteration_bound (struct loop *loop)
> >           && wi::ltu_p (elt->bound, loop->nb_iterations_upper_bound))
> >         {
> >           if (!not_executed_last_iteration)
> > -           not_executed_last_iteration = pointer_set_create ();
> > -         pointer_set_insert (not_executed_last_iteration, elt->stmt);
> > +           not_executed_last_iteration = new hash_set<gimple>;
> > +         not_executed_last_iteration->add (elt->stmt);
> >         }
> >      }
> >    if (!not_executed_last_iteration)
> > @@ -3327,7 +3328,7 @@ maybe_lower_iteration_bound (struct loop *loop)
> >        for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> >         {
> >           gimple stmt = gsi_stmt (gsi);
> > -         if (pointer_set_contains (not_executed_last_iteration, stmt))
> > +         if (not_executed_last_iteration->contains (stmt))
> >             {
> >               stmt_found = true;
> >               break;
> > @@ -3376,7 +3377,7 @@ maybe_lower_iteration_bound (struct loop *loop)
> >      }
> >    BITMAP_FREE (visited);
> >    queue.release ();
> > -  pointer_set_destroy (not_executed_last_iteration);
> > +  delete not_executed_last_iteration;
> >  }
> >
> >  /* Records estimates on numbers of iterations of LOOP.  If USE_UNDEFINED_P
> > diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
> > index 052d760..3185d9a 100644
> > --- a/gcc/tree-ssa-phiopt.c
> > +++ b/gcc/tree-ssa-phiopt.c
> > @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "flags.h"
> >  #include "tm_p.h"
> >  #include "basic-block.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> > @@ -72,9 +73,9 @@ static bool abs_replacement (basic_block, basic_block,
> >  static bool neg_replacement (basic_block, basic_block,
> >                              edge, edge, gimple, tree, tree);
> >  static bool cond_store_replacement (basic_block, basic_block, edge, edge,
> > -                                   struct pointer_set_t *);
> > +                                   hash_set<tree> *);
> >  static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
> > -static struct pointer_set_t * get_non_trapping (void);
> > +static hash_set<tree> * get_non_trapping ();
> >  static void replace_phi_edge_with_variable (basic_block, edge, gimple, tree);
> >  static void hoist_adjacent_loads (basic_block, basic_block,
> >                                   basic_block, basic_block);
> > @@ -176,7 +177,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
> >    basic_block *bb_order;
> >    unsigned n, i;
> >    bool cfgchanged = false;
> > -  struct pointer_set_t *nontrap = 0;
> > +  hash_set<tree> *nontrap = 0;
> >
> >    if (do_store_elim)
> >      /* Calculate the set of non-trapping memory accesses.  */
> > @@ -363,7 +364,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
> >    free (bb_order);
> >
> >    if (do_store_elim)
> > -    pointer_set_destroy (nontrap);
> > +    delete nontrap;
> >    /* If the CFG has changed, we should cleanup the CFG.  */
> >    if (cfgchanged && do_store_elim)
> >      {
> > @@ -1469,7 +1470,7 @@ ssa_names_hasher::equal (const value_type *n1, const compare_type *n2)
> >  class nontrapping_dom_walker : public dom_walker
> >  {
> >  public:
> > -  nontrapping_dom_walker (cdi_direction direction, pointer_set_t *ps)
> > +  nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps)
> >      : dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {}
> >
> >    virtual void before_dom_children (basic_block);
> > @@ -1484,7 +1485,7 @@ private:
> >       the RHS.  */
> >    void add_or_mark_expr (basic_block, tree, bool);
> >
> > -  pointer_set_t *m_nontrapping;
> > +  hash_set<tree> *m_nontrapping;
> >
> >    /* The hash table for remembering what we've seen.  */
> >    hash_table<ssa_names_hasher> m_seen_ssa_names;
> > @@ -1572,7 +1573,7 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
> >          then we can't trap.  */
> >        if (found_bb && (((size_t)found_bb->aux) & 1) == 1)
> >         {
> > -         pointer_set_insert (m_nontrapping, exp);
> > +         m_nontrapping->add (exp);
> >         }
> >        else
> >          {
> > @@ -1601,11 +1602,11 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
> >     It will do a dominator walk over the whole function, and it will
> >     make use of the bb->aux pointers.  It returns a set of trees
> >     (the MEM_REFs itself) which can't trap.  */
> > -static struct pointer_set_t *
> > +static hash_set<tree> *
> >  get_non_trapping (void)
> >  {
> >    nt_call_phase = 0;
> > -  pointer_set_t *nontrap = pointer_set_create ();
> > +  hash_set<tree> *nontrap = new hash_set<tree>;
> >    /* We're going to do a dominator walk, so ensure that we have
> >       dominance information.  */
> >    calculate_dominance_info (CDI_DOMINATORS);
> > @@ -1634,7 +1635,7 @@ get_non_trapping (void)
> >
> >  static bool
> >  cond_store_replacement (basic_block middle_bb, basic_block join_bb,
> > -                       edge e0, edge e1, struct pointer_set_t *nontrap)
> > +                       edge e0, edge e1, hash_set<tree> *nontrap)
> >  {
> >    gimple assign = last_and_only_stmt (middle_bb);
> >    tree lhs, rhs, name, name2;
> > @@ -1659,7 +1660,7 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb,
> >    /* Prove that we can move the store down.  We could also check
> >       TREE_THIS_NOTRAP here, but in that case we also could move stores,
> >       whose value is not available readily, which we want to avoid.  */
> > -  if (!pointer_set_contains (nontrap, lhs))
> > +  if (!nontrap->contains (lhs))
> >      return false;
> >
> >    /* Now we've checked the constraints, so do the transformation:
> > diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
> > index 9807b42..3dee5ba 100644
> > --- a/gcc/tree-ssa-threadedge.c
> > +++ b/gcc/tree-ssa-threadedge.c
> > @@ -30,7 +30,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "function.h"
> >  #include "timevar.h"
> >  #include "dumpfile.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> >  #include "gimple-expr.h"
> > @@ -693,13 +693,13 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >      }
> >
> >    auto_vec<tree, alloc_count> fewvars;
> > -  pointer_set_t *vars = NULL;
> > +  hash_set<tree> *vars = NULL;
> >
> >    /* If we're already starting with 3/4 of alloc_count, go for a
> > -     pointer_set, otherwise start with an unordered stack-allocated
> > +     hash_set, otherwise start with an unordered stack-allocated
> >       VEC.  */
> >    if (i * 4 > alloc_count * 3)
> > -    vars = pointer_set_create ();
> > +    vars = new hash_set<tree>;
> >
> >    /* Now go through the initial debug stmts in DEST again, this time
> >       actually inserting in VARS or FEWVARS.  Don't bother checking for
> > @@ -720,7 +720,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >         gcc_unreachable ();
> >
> >        if (vars)
> > -       pointer_set_insert (vars, var);
> > +       vars->add (var);
> >        else
> >         fewvars.quick_push (var);
> >      }
> > @@ -754,7 +754,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >              or somesuch.  Adding `&& bb == src' to the condition
> >              below will preserve all potentially relevant debug
> >              notes.  */
> > -         if (vars && pointer_set_insert (vars, var))
> > +         if (vars && vars->add (var))
> >             continue;
> >           else if (!vars)
> >             {
> > @@ -769,11 +769,11 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >                 fewvars.quick_push (var);
> >               else
> >                 {
> > -                 vars = pointer_set_create ();
> > +                 vars = new hash_set<tree>;
> >                   for (i = 0; i < alloc_count; i++)
> > -                   pointer_set_insert (vars, fewvars[i]);
> > +                   vars->add (fewvars[i]);
> >                   fewvars.release ();
> > -                 pointer_set_insert (vars, var);
> > +                 vars->add (var);
> >                 }
> >             }
> >
> > @@ -786,7 +786,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >    while (bb != src && single_pred_p (bb));
> >
> >    if (vars)
> > -    pointer_set_destroy (vars);
> > +    delete vars;
> >    else if (fewvars.exists ())
> >      fewvars.release ();
> >  }
> > diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
> > index 64259fb..f2578b7 100644
> > --- a/gcc/tree-ssa-uninit.c
> > +++ b/gcc/tree-ssa-uninit.c
> > @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "function.h"
> >  #include "gimple-pretty-print.h"
> >  #include "bitmap.h"
> > +#include "hash-set.h"
> >  #include "pointer-set.h"
> >  #include "tree-ssa-alias.h"
> >  #include "internal-fn.h"
> > @@ -60,7 +61,7 @@ along with GCC; see the file COPYING3.  If not see
> >  /* Pointer set of potentially undefined ssa names, i.e.,
> >     ssa names that are defined by phi with operands that
> >     are not defined or potentially undefined.  */
> > -static pointer_set_t *possibly_undefined_names = 0;
> > +static hash_set<tree> *possibly_undefined_names = 0;
> >
> >  /* Bit mask handling macros.  */
> >  #define MASK_SET_BIT(mask, pos) mask |= (1 << pos)
> > @@ -89,7 +90,7 @@ has_undefined_value_p (tree t)
> >  {
> >    return (ssa_undefined_value_p (t)
> >            || (possibly_undefined_names
> > -              && pointer_set_contains (possibly_undefined_names, t)));
> > +              && possibly_undefined_names->contains (t)));
> >  }
> >
> >
> > @@ -648,13 +649,13 @@ find_predicates (pred_chain_union *preds,
> >  static void
> >  collect_phi_def_edges (gimple phi, basic_block cd_root,
> >                         vec<edge> *edges,
> > -                       pointer_set_t *visited_phis)
> > +                       hash_set<gimple> *visited_phis)
> >  {
> >    size_t i, n;
> >    edge opnd_edge;
> >    tree opnd;
> >
> > -  if (pointer_set_insert (visited_phis, phi))
> > +  if (visited_phis->add (phi))
> >      return;
> >
> >    n = gimple_phi_num_args (phi);
> > @@ -707,7 +708,6 @@ find_def_preds (pred_chain_union *preds, gimple phi)
> >    vec<edge> def_edges = vNULL;
> >    bool has_valid_pred = false;
> >    basic_block phi_bb, cd_root = 0;
> > -  pointer_set_t *visited_phis;
> >
> >    phi_bb = gimple_bb (phi);
> >    /* First find the closest dominating bb to be
> > @@ -716,9 +716,8 @@ find_def_preds (pred_chain_union *preds, gimple phi)
> >    if (!cd_root)
> >      return false;
> >
> > -  visited_phis = pointer_set_create ();
> > -  collect_phi_def_edges (phi, cd_root, &def_edges, visited_phis);
> > -  pointer_set_destroy (visited_phis);
> > +  hash_set<gimple> visited_phis;
> > +  collect_phi_def_edges (phi, cd_root, &def_edges, &visited_phis);
> >
> >    n = def_edges.length ();
> >    if (n == 0)
> > @@ -941,7 +940,7 @@ is_use_properly_guarded (gimple use_stmt,
> >                           basic_block use_bb,
> >                           gimple phi,
> >                           unsigned uninit_opnds,
> > -                         pointer_set_t *visited_phis);
> > +                         hash_set<gimple> *visited_phis);
> >
> >  /* Returns true if all uninitialized opnds are pruned. Returns false
> >     otherwise. PHI is the phi node with uninitialized operands,
> > @@ -983,7 +982,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
> >                                               gimple flag_def,
> >                                               tree boundary_cst,
> >                                               enum tree_code cmp_code,
> > -                                             pointer_set_t *visited_phis,
> > +                                             hash_set<gimple> *visited_phis,
> >                                               bitmap *visited_flag_phis)
> >  {
> >    unsigned i;
> > @@ -1153,7 +1152,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
> >  static bool
> >  use_pred_not_overlap_with_undef_path_pred (pred_chain_union preds,
> >                                            gimple phi, unsigned uninit_opnds,
> > -                                          pointer_set_t *visited_phis)
> > +                                          hash_set<gimple> *visited_phis)
> >  {
> >    unsigned int i, n;
> >    gimple flag_def = 0;
> > @@ -1818,11 +1817,11 @@ push_pred (pred_chain_union *norm_preds, pred_info pred)
> >
> >  inline static void
> >  push_to_worklist (tree op, vec<pred_info, va_heap, vl_ptr> *work_list,
> > -                  pointer_set_t *mark_set)
> > +                  hash_set<tree> *mark_set)
> >  {
> > -  if (pointer_set_contains (mark_set, op))
> > +  if (mark_set->contains (op))
> >      return;
> > -  pointer_set_insert (mark_set, op);
> > +  mark_set->add (op);
> >
> >    pred_info arg_pred;
> >    arg_pred.pred_lhs = op;
> > @@ -1907,7 +1906,7 @@ normalize_one_pred_1 (pred_chain_union *norm_preds,
> >                        pred_info pred,
> >                        enum tree_code and_or_code,
> >                        vec<pred_info, va_heap, vl_ptr> *work_list,
> > -                     pointer_set_t *mark_set)
> > +                     hash_set<tree> *mark_set)
> >  {
> >    if (!is_neq_zero_form_p (pred))
> >      {
> > @@ -1987,7 +1986,6 @@ normalize_one_pred (pred_chain_union *norm_preds,
> >                      pred_info pred)
> >  {
> >    vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
> > -  pointer_set_t *mark_set = NULL;
> >    enum tree_code and_or_code = ERROR_MARK;
> >    pred_chain norm_chain = vNULL;
> >
> > @@ -2015,19 +2013,18 @@ normalize_one_pred (pred_chain_union *norm_preds,
> >      }
> >
> >    work_list.safe_push (pred);
> > -  mark_set = pointer_set_create ();
> > +  hash_set<tree> mark_set;
> >
> >    while (!work_list.is_empty ())
> >      {
> >        pred_info a_pred = work_list.pop ();
> >        normalize_one_pred_1 (norm_preds, &norm_chain, a_pred,
> > -                            and_or_code, &work_list, mark_set);
> > +                            and_or_code, &work_list, &mark_set);
> >      }
> >    if (and_or_code == BIT_AND_EXPR)
> >      norm_preds->safe_push (norm_chain);
> >
> >    work_list.release ();
> > -  pointer_set_destroy (mark_set);
> >  }
> >
> >  static void
> > @@ -2035,26 +2032,25 @@ normalize_one_pred_chain (pred_chain_union *norm_preds,
> >                            pred_chain one_chain)
> >  {
> >    vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
> > -  pointer_set_t *mark_set = pointer_set_create ();
> > +  hash_set<tree> mark_set;
> >    pred_chain norm_chain = vNULL;
> >    size_t i;
> >
> >    for (i = 0; i < one_chain.length (); i++)
> >      {
> >        work_list.safe_push (one_chain[i]);
> > -      pointer_set_insert (mark_set, one_chain[i].pred_lhs);
> > +      mark_set.add (one_chain[i].pred_lhs);
> >      }
> >
> >    while (!work_list.is_empty ())
> >      {
> >        pred_info a_pred = work_list.pop ();
> >        normalize_one_pred_1 (0, &norm_chain, a_pred,
> > -                            BIT_AND_EXPR, &work_list, mark_set);
> > +                            BIT_AND_EXPR, &work_list, &mark_set);
> >      }
> >
> >    norm_preds->safe_push (norm_chain);
> >    work_list.release ();
> > -  pointer_set_destroy (mark_set);
> >  }
> >
> >  /* Normalize predicate chains PREDS and returns the normalized one.  */
> > @@ -2112,7 +2108,7 @@ is_use_properly_guarded (gimple use_stmt,
> >                           basic_block use_bb,
> >                           gimple phi,
> >                           unsigned uninit_opnds,
> > -                         pointer_set_t *visited_phis)
> > +                         hash_set<gimple> *visited_phis)
> >  {
> >    basic_block phi_bb;
> >    pred_chain_union preds = vNULL;
> > @@ -2120,7 +2116,7 @@ is_use_properly_guarded (gimple use_stmt,
> >    bool has_valid_preds = false;
> >    bool is_properly_guarded = false;
> >
> > -  if (pointer_set_insert (visited_phis, phi))
> > +  if (visited_phis->add (phi))
> >      return false;
> >
> >    phi_bb = gimple_bb (phi);
> > @@ -2181,7 +2177,7 @@ is_use_properly_guarded (gimple use_stmt,
> >  static gimple
> >  find_uninit_use (gimple phi, unsigned uninit_opnds,
> >                   vec<gimple> *worklist,
> > -                pointer_set_t *added_to_worklist)
> > +                hash_set<gimple> *added_to_worklist)
> >  {
> >    tree phi_result;
> >    use_operand_p use_p;
> > @@ -2192,28 +2188,22 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >
> >    FOR_EACH_IMM_USE_FAST (use_p, iter, phi_result)
> >      {
> > -      pointer_set_t *visited_phis;
> >        basic_block use_bb;
> >
> >        use_stmt = USE_STMT (use_p);
> >        if (is_gimple_debug (use_stmt))
> >         continue;
> >
> > -      visited_phis = pointer_set_create ();
> > -
> >        if (gimple_code (use_stmt) == GIMPLE_PHI)
> >         use_bb = gimple_phi_arg_edge (use_stmt,
> >                                       PHI_ARG_INDEX_FROM_USE (use_p))->src;
> >        else
> >         use_bb = gimple_bb (use_stmt);
> >
> > +      hash_set<gimple> visited_phis;
> >        if (is_use_properly_guarded (use_stmt, use_bb, phi, uninit_opnds,
> > -                                   visited_phis))
> > -        {
> > -          pointer_set_destroy (visited_phis);
> > -          continue;
> > -        }
> > -      pointer_set_destroy (visited_phis);
> > +                                   &visited_phis))
> > +       continue;
> >
> >        if (dump_file && (dump_flags & TDF_DETAILS))
> >          {
> > @@ -2226,7 +2216,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >
> >        /* Found a phi use that is not guarded,
> >           add the phi to the worklist.  */
> > -      if (!pointer_set_insert (added_to_worklist, use_stmt))
> > +      if (!added_to_worklist->add (use_stmt))
> >          {
> >            if (dump_file && (dump_flags & TDF_DETAILS))
> >              {
> > @@ -2235,7 +2225,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >              }
> >
> >            worklist->safe_push (use_stmt);
> > -          pointer_set_insert (possibly_undefined_names, phi_result);
> > +          possibly_undefined_names->add (phi_result);
> >          }
> >      }
> >
> > @@ -2252,7 +2242,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >
> >  static void
> >  warn_uninitialized_phi (gimple phi, vec<gimple> *worklist,
> > -                        pointer_set_t *added_to_worklist)
> > +                        hash_set<gimple> *added_to_worklist)
> >  {
> >    unsigned uninit_opnds;
> >    gimple uninit_use_stmt = 0;
> > @@ -2339,7 +2329,6 @@ pass_late_warn_uninitialized::execute (function *fun)
> >    basic_block bb;
> >    gimple_stmt_iterator gsi;
> >    vec<gimple> worklist = vNULL;
> > -  pointer_set_t *added_to_worklist;
> >
> >    calculate_dominance_info (CDI_DOMINATORS);
> >    calculate_dominance_info (CDI_POST_DOMINATORS);
> > @@ -2350,8 +2339,8 @@ pass_late_warn_uninitialized::execute (function *fun)
> >
> >    timevar_push (TV_TREE_UNINIT);
> >
> > -  possibly_undefined_names = pointer_set_create ();
> > -  added_to_worklist = pointer_set_create ();
> > +  possibly_undefined_names = new hash_set<tree>;
> > +  hash_set<gimple> added_to_worklist;
> >
> >    /* Initialize worklist  */
> >    FOR_EACH_BB_FN (bb, fun)
> > @@ -2373,7 +2362,7 @@ pass_late_warn_uninitialized::execute (function *fun)
> >                 && uninit_undefined_value_p (op))
> >               {
> >                 worklist.safe_push (phi);
> > -               pointer_set_insert (added_to_worklist, phi);
> > +               added_to_worklist.add (phi);
> >                 if (dump_file && (dump_flags & TDF_DETAILS))
> >                   {
> >                     fprintf (dump_file, "[WORKLIST]: add to initial list: ");
> > @@ -2388,12 +2377,11 @@ pass_late_warn_uninitialized::execute (function *fun)
> >      {
> >        gimple cur_phi = 0;
> >        cur_phi = worklist.pop ();
> > -      warn_uninitialized_phi (cur_phi, &worklist, added_to_worklist);
> > +      warn_uninitialized_phi (cur_phi, &worklist, &added_to_worklist);
> >      }
> >
> >    worklist.release ();
> > -  pointer_set_destroy (added_to_worklist);
> > -  pointer_set_destroy (possibly_undefined_names);
> > +  delete possibly_undefined_names;
> >    possibly_undefined_names = NULL;
> >    free_dominance_info (CDI_POST_DOMINATORS);
> >    timevar_pop (TV_TREE_UNINIT);
> > diff --git a/gcc/tree.c b/gcc/tree.c
> > index 6669a84..de1c9b6 100644
> > --- a/gcc/tree.c
> > +++ b/gcc/tree.c
> > @@ -5143,7 +5143,7 @@ struct free_lang_data_d
> >    vec<tree> worklist;
> >
> >    /* Set of traversed objects.  Used to avoid duplicate visits.  */
> > -  struct pointer_set_t *pset;
> > +  hash_set<tree> *pset;
> >
> >    /* Array of symbols to process with free_lang_data_in_decl.  */
> >    vec<tree> decls;
> > @@ -5208,7 +5208,7 @@ add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
> >  static inline void
> >  fld_worklist_push (tree t, struct free_lang_data_d *fld)
> >  {
> > -  if (t && !is_lang_specific (t) && !pointer_set_contains (fld->pset, t))
> > +  if (t && !is_lang_specific (t) && !fld->pset->contains (t))
> >      fld->worklist.safe_push ((t));
> >  }
> >
> > @@ -5374,7 +5374,7 @@ find_decls_types (tree t, struct free_lang_data_d *fld)
> >  {
> >    while (1)
> >      {
> > -      if (!pointer_set_contains (fld->pset, t))
> > +      if (!fld->pset->contains (t))
> >         walk_tree (&t, find_decls_types_r, fld, fld->pset);
> >        if (fld->worklist.is_empty ())
> >         break;
> > @@ -5584,7 +5584,7 @@ free_lang_data_in_cgraph (void)
> >    alias_pair *p;
> >
> >    /* Initialize sets and arrays to store referenced decls and types.  */
> > -  fld.pset = pointer_set_create ();
> > +  fld.pset = new hash_set<tree>;
> >    fld.worklist.create (0);
> >    fld.decls.create (100);
> >    fld.types.create (100);
> > @@ -5614,7 +5614,7 @@ free_lang_data_in_cgraph (void)
> >    FOR_EACH_VEC_ELT (fld.types, i, t)
> >      free_lang_data_in_type (t);
> >
> > -  pointer_set_destroy (fld.pset);
> > +  delete fld.pset;
> >    fld.worklist.release ();
> >    fld.decls.release ();
> >    fld.types.release ();
> > @@ -10819,7 +10819,7 @@ num_ending_zeros (const_tree x)
> >
> >  static tree
> >  walk_type_fields (tree type, walk_tree_fn func, void *data,
> > -                 struct pointer_set_t *pset, walk_tree_lh lh)
> > +                 hash_set<tree> *pset, walk_tree_lh lh)
> >  {
> >    tree result = NULL_TREE;
> >
> > @@ -10901,7 +10901,7 @@ walk_type_fields (tree type, walk_tree_fn func, void *data,
> >
> >  tree
> >  walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
> > -            struct pointer_set_t *pset, walk_tree_lh lh)
> > +            hash_set<tree> *pset, walk_tree_lh lh)
> >  {
> >    enum tree_code code;
> >    int walk_subtrees;
> > @@ -10922,7 +10922,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
> >
> >    /* Don't walk the same tree twice, if the user has requested
> >       that we avoid doing so.  */
> > -  if (pset && pointer_set_insert (pset, *tp))
> > +  if (pset && pset->add (*tp))
> >      return NULL_TREE;
> >
> >    /* Call the function.  */
> > @@ -11237,11 +11237,9 @@ walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data,
> >                                 walk_tree_lh lh)
> >  {
> >    tree result;
> > -  struct pointer_set_t *pset;
> >
> > -  pset = pointer_set_create ();
> > -  result = walk_tree_1 (tp, func, data, pset, lh);
> > -  pointer_set_destroy (pset);
> > +  hash_set<tree> pset;
> > +  result = walk_tree_1 (tp, func, data, &pset, lh);
> >    return result;
> >  }
> >
> > diff --git a/gcc/tree.h b/gcc/tree.h
> > index 2bb6d1f..c9f978a 100644
> > --- a/gcc/tree.h
> > +++ b/gcc/tree.h
> > @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #define GCC_TREE_H
> >
> >  #include "tree-core.h"
> > +#include "hash-set.h"
> >  #include "wide-int.h"
> >  #include "inchash.h"
> >
> > @@ -4328,7 +4329,7 @@ extern void using_eh_for_cleanups (void);
> >  extern bool using_eh_for_cleanups_p (void);
> >  extern const char *get_tree_code_name (enum tree_code);
> >  extern void set_call_expr_flags (tree, int);
> > -extern tree walk_tree_1 (tree*, walk_tree_fn, void*, struct pointer_set_t*,
> > +extern tree walk_tree_1 (tree*, walk_tree_fn, void*, hash_set<tree>*,
> >                          walk_tree_lh);
> >  extern tree walk_tree_without_duplicates_1 (tree*, walk_tree_fn, void*,
> >                                             walk_tree_lh);
> > diff --git a/gcc/value-prof.c b/gcc/value-prof.c
> > index 3e51539..ffdee65 100644
> > --- a/gcc/value-prof.c
> > +++ b/gcc/value-prof.c
> > @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "data-streamer.h"
> >  #include "builtins.h"
> >  #include "tree-nested.h"
> > +#include "hash-set.h"
> >
> >  /* In this file value profile based optimizations are placed.  Currently the
> >     following optimizations are implemented (for more detailed descriptions
> > @@ -515,10 +516,10 @@ static bool error_found = false;
> >  static int
> >  visit_hist (void **slot, void *data)
> >  {
> > -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> > +  hash_set<histogram_value> *visited = (hash_set<histogram_value> *) data;
> >    histogram_value hist = *(histogram_value *) slot;
> >
> > -  if (!pointer_set_contains (visited, hist)
> > +  if (!visited->contains (hist)
> >        && hist->type != HIST_TYPE_TIME_PROFILE)
> >      {
> >        error ("dead histogram");
> > @@ -538,10 +539,9 @@ verify_histograms (void)
> >    basic_block bb;
> >    gimple_stmt_iterator gsi;
> >    histogram_value hist;
> > -  struct pointer_set_t *visited_hists;
> >
> >    error_found = false;
> > -  visited_hists = pointer_set_create ();
> > +  hash_set<histogram_value> visited_hists;
> >    FOR_EACH_BB_FN (bb, cfun)
> >      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> >        {
> > @@ -558,12 +558,11 @@ verify_histograms (void)
> >                 dump_histogram_value (stderr, hist);
> >                 error_found = true;
> >               }
> > -            pointer_set_insert (visited_hists, hist);
> > +            visited_hists.add (hist);
> >           }
> >        }
> >    if (VALUE_HISTOGRAMS (cfun))
> > -    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, visited_hists);
> > -  pointer_set_destroy (visited_hists);
> > +    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, &visited_hists);
> >    if (error_found)
> >      internal_error ("verify_histograms failed");
> >  }
> > diff --git a/gcc/varasm.c b/gcc/varasm.c
> > index 819ec26..9d8602b 100644
> > --- a/gcc/varasm.c
> > +++ b/gcc/varasm.c
> > @@ -51,7 +51,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "common/common-target.h"
> >  #include "targhooks.h"
> >  #include "cgraph.h"
> > -#include "pointer-set.h"
> > +#include "hash-set.h"
> >  #include "asan.h"
> >  #include "basic-block.h"
> >
> > @@ -2249,7 +2249,7 @@ static bool pending_assemble_externals_processed;
> >
> >  /* Avoid O(external_decls**2) lookups in the pending_assemble_externals
> >     TREE_LIST in assemble_external.  */
> > -static struct pointer_set_t *pending_assemble_externals_set;
> > +static hash_set<tree> *pending_assemble_externals_set;
> >
> >  /* True if DECL is a function decl for which no out-of-line copy exists.
> >     It is assumed that DECL's assembler name has been set.  */
> > @@ -2303,7 +2303,7 @@ process_pending_assemble_externals (void)
> >
> >    pending_assemble_externals = 0;
> >    pending_assemble_externals_processed = true;
> > -  pointer_set_destroy (pending_assemble_externals_set);
> > +  delete pending_assemble_externals_set;
> >  #endif
> >  }
> >
> > @@ -2361,7 +2361,7 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
> >        return;
> >      }
> >
> > -  if (! pointer_set_insert (pending_assemble_externals_set, decl))
> > +  if (! pending_assemble_externals_set->add (decl))
> >      pending_assemble_externals = tree_cons (NULL, decl,
> >                                             pending_assemble_externals);
> >  #endif
> > @@ -5991,7 +5991,7 @@ init_varasm_once (void)
> >      readonly_data_section = text_section;
> >
> >  #ifdef ASM_OUTPUT_EXTERNAL
> > -  pending_assemble_externals_set = pointer_set_create ();
> > +  pending_assemble_externals_set = new hash_set<tree>;
> >  #endif
> >  }
> >
> > diff --git a/gcc/varpool.c b/gcc/varpool.c
> > index 74117e2..558767f 100644
> > --- a/gcc/varpool.c
> > +++ b/gcc/varpool.c
> > @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "tree-ssa-alias.h"
> >  #include "gimple.h"
> >  #include "lto-streamer.h"
> > +#include "hash-set.h"
> >
> >  const char * const tls_model_names[]={"none", "tls-emulated", "tls-real",
> >                                       "tls-global-dynamic", "tls-local-dynamic",
> > @@ -576,7 +577,7 @@ varpool_remove_unreferenced_decls (void)
> >    varpool_node *first = (varpool_node *)(void *)1;
> >    int i;
> >    struct ipa_ref *ref = NULL;
> > -  struct pointer_set_t *referenced = pointer_set_create ();
> > +  hash_set<varpool_node *> referenced;
> >
> >    if (seen_error ())
> >      return;
> > @@ -623,7 +624,7 @@ varpool_remove_unreferenced_decls (void)
> >               && vnode->analyzed)
> >             enqueue_node (vnode, &first);
> >           else
> > -           pointer_set_insert (referenced, node);
> > +           referenced.add (node);
> >         }
> >      }
> >    if (cgraph_dump_file)
> > @@ -635,13 +636,13 @@ varpool_remove_unreferenced_decls (void)
> >         {
> >            if (cgraph_dump_file)
> >             fprintf (cgraph_dump_file, " %s", node->asm_name ());
> > -         if (pointer_set_contains (referenced, node))
> > +         if (referenced.contains (node))
> >             node->remove_initializer ();
> >           else
> >             node->remove ();
> >         }
> >      }
> > -  pointer_set_destroy (referenced);
> > +
> >    if (cgraph_dump_file)
> >      fprintf (cgraph_dump_file, "\n");
> >  }
> > --
> > 2.0.1
> >
Andrew Pinski Aug. 4, 2014, 5:28 p.m. UTC | #5
> On Aug 4, 2014, at 10:15 AM, Trevor Saunders <tsaunders@mozilla.com> wrote:
> 
>> On Sat, Aug 02, 2014 at 03:44:17PM -0700, Andrew Pinski wrote:
>>> On Tue, Jul 29, 2014 at 5:50 AM,  <tsaunders@mozilla.com> wrote:
>>> From: Trevor Saunders <tsaunders@mozilla.com>
>>> 
>>> Hi,
>>> 
>>> this adds a hash_set wrapper around hash_table, and then replaces usage of pointer_set with it.
>>> 
>>> bootstrapped +regtested on x86_64-unknown-linux-gnu, ok?
>>> 
>>> Trev
>>> 
>>> ada/
>>> 
>>>        * gcc-interface/trans.c: Use hash_set instead of pointer_set.
>>> 
>>> c-family/
>>> 
>>>        * c-gimplify.c: Use hash_set instead of pointer_set.
>>> 
>>> c/
>>> 
>>>        * c-decl.c: Use hash_set instead of pointer_set.
>>> 
>>> cp/
>>> 
>>>        * class.c, cp-gimplify.c, cp-tree.h, decl.c, decl2.c, error.c,
>>>        method.c, name-lookup.c, pt.c, semantics.c, tree.c: Use hash_set
>>>        instead of pointer_set.
>>> 
>>> fortran/
>>> 
>>>        * openmp.c, trans-decl.c: Use hash_set instead of pointer_set.
>>> 
>>> gcc/
>>> 
>>>        * hash-set.h: new File.
>>>        * cfgexpand.c, cfgloop.c, cgraph.c, cgraphbuild.c, cgraphunit.c,
>>>        cprop.c, cse.c, gimple-walk.c, gimple-walk.h, gimplify.c, godump.c,
>>>        ipa-devirt.c, ipa-pure-const.c, ipa-visibility.c, ipa.c, lto-cgraph.c,
>>>        lto-streamer-out.c, stmt.c, tree-cfg.c, tree-core.h, tree-eh.c,
>>>        tree-inline.c, tree-inline.h, tree-nested.c, tree-pretty-print.c,
>>>        tree-ssa-loop-niter.c, tree-ssa-phiopt.c, tree-ssa-threadedge.c,
>>>        tree-ssa-uninit.c, tree.c, tree.h, value-prof.c, varasm.c,
>>>        varpool.c: Use hash_set instead of pointer_set.
>> 
>> 
>> This changelog is less than useful and really does not follow the
>> GCC/GNU coding style.  Please expand and place all functions which are
> 
> I'm pretty sure its written somewhere that format is ok, and there's
> precedent for it.

Where? I have seen the opposite in that this format to be used when doing changes like this. I have no quick way to find when a function was changed. 


>  Note the update all callers rule could also be used
> to just write
> 
>    (pointer_map_create): Rename to
>    (hash_set::hash_set): and update all callers.

This even less useful. 

> 
> now I agree its useless, but that's just the nature of something
> that just summarizes the diff.  it'd be no more useful if it
> included the headers for diff -p with some regexs to get rid of
> the line markers.
> 
>> changed in it.  I use ChangeLog entries when merging in code to see
>> which of the merged code I need to pick up.
> 
> just use a merge tool that isn't total garbage and let it handle
> everything but actual conflicts? or failing that just use diff -p that's
> going to be just about as accurate as what humans can reasonably be expected
> to produce.

I had a conflict which is why I noticed this issue in the first place. And I was using git merge :). 

Thanks,
Andrew



> 
> Trev
> 
>> 
>> Thanks,
>> Andrew Pinski
>> 
>> 
>> 
>>> 
>>> lto/
>>> 
>>>        * lto-partition.c, lto-partition.h: Use hash_set instead of
>>>        pointer_set.
>>> diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
>>> index f42ac7f..6961838 100644
>>> --- a/gcc/ada/gcc-interface/trans.c
>>> +++ b/gcc/ada/gcc-interface/trans.c
>>> @@ -36,7 +36,7 @@
>>> #include "output.h"
>>> #include "libfuncs.h"  /* For set_stack_check_libfunc.  */
>>> #include "tree-iterator.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> #include "gimple-expr.h"
>>> #include "gimplify.h"
>>> #include "bitmap.h"
>>> @@ -3054,7 +3054,7 @@ struct nrv_data
>>>   bitmap nrv;
>>>   tree result;
>>>   Node_Id gnat_ret;
>>> -  struct pointer_set_t *visited;
>>> +  hash_set<tree> *visited;
>>> };
>>> 
>>> /* Return true if T is a Named Return Value.  */
>>> @@ -3188,7 +3188,7 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
>>>   /* Avoid walking into the same tree more than once.  Unfortunately, we
>>>      can't just use walk_tree_without_duplicates because it would only
>>>      call us for the first occurrence of NRVs in the function body.  */
>>> -  if (pointer_set_insert (dp->visited, *tp))
>>> +  if (dp->visited->add (*tp))
>>>     *walk_subtrees = 0;
>>> 
>>>   return NULL_TREE;
>>> @@ -3328,7 +3328,7 @@ finalize_nrv_unc_r (tree *tp, int *walk_subtrees, void *data)
>>>   /* Avoid walking into the same tree more than once.  Unfortunately, we
>>>      can't just use walk_tree_without_duplicates because it would only
>>>      call us for the first occurrence of NRVs in the function body.  */
>>> -  if (pointer_set_insert (dp->visited, *tp))
>>> +  if (dp->visited->add (*tp))
>>>     *walk_subtrees = 0;
>>> 
>>>   return NULL_TREE;
>>> @@ -3376,13 +3376,13 @@ finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret
>>>   data.nrv = nrv;
>>>   data.result = DECL_RESULT (fndecl);
>>>   data.gnat_ret = gnat_ret;
>>> -  data.visited = pointer_set_create ();
>>> +  data.visited = new hash_set<tree>;
>>>   if (TYPE_RETURN_UNCONSTRAINED_P (TREE_TYPE (fndecl)))
>>>     func = finalize_nrv_unc_r;
>>>   else
>>>     func = finalize_nrv_r;
>>>   walk_tree (&DECL_SAVED_TREE (fndecl), func, &data, NULL);
>>> -  pointer_set_destroy (data.visited);
>>> +  delete data.visited;
>>> }
>>> 
>>> /* Return true if RET_VAL can be used as a Named Return Value for the
>>> diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
>>> index 2b5ce5b..4898217 100644
>>> --- a/gcc/c-family/c-gimplify.c
>>> +++ b/gcc/c-family/c-gimplify.c
>>> @@ -74,7 +74,7 @@ along with GCC; see the file COPYING3.  If not see
>>> static tree
>>> ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
>>> {
>>> -  struct pointer_set_t *pset = (struct pointer_set_t *) data;
>>> +  hash_set<tree> *pset = (hash_set<tree> *) data;
>>> 
>>>   /* Since walk_tree doesn't call the callback function on the decls
>>>      in BIND_EXPR_VARS, we have to walk them manually.  */
>>> @@ -116,10 +116,9 @@ c_genericize (tree fndecl)
>>> 
>>>   if (flag_sanitize & SANITIZE_BOUNDS)
>>>     {
>>> -      struct pointer_set_t *pset = pointer_set_create ();
>>> -      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, pset,
>>> -                pset);
>>> -      pointer_set_destroy (pset);
>>> +      hash_set<tree> pset;
>>> +      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
>>> +                &pset);
>>>     }
>>> 
>>>   /* Dump the C-specific tree IR.  */
>>> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
>>> index 2a4b439..050ddff 100644
>>> --- a/gcc/c/c-decl.c
>>> +++ b/gcc/c/c-decl.c
>>> @@ -59,7 +59,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "cgraph.h"
>>> #include "hash-table.h"
>>> #include "langhooks-def.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> #include "plugin.h"
>>> #include "c-family/c-ada-spec.h"
>>> #include "cilk.h"
>>> @@ -7221,17 +7221,17 @@ warn_cxx_compat_finish_struct (tree fieldlist)
>>>   if (!struct_parse_info->typedefs_seen.is_empty ()
>>>       && fieldlist != NULL_TREE)
>>>     {
>>> -      /* Use a pointer_set using the name of the typedef.  We can use
>>> -        a pointer_set because identifiers are interned.  */
>>> -      struct pointer_set_t *tset = pointer_set_create ();
>>> +      /* Use a hash_set<tree> using the name of the typedef.  We can use
>>> +        a hash_set<tree> because identifiers are interned.  */
>>> +      hash_set<tree> tset;
>>> 
>>>       FOR_EACH_VEC_ELT (struct_parse_info->typedefs_seen, ix, x)
>>> -       pointer_set_insert (tset, DECL_NAME (x));
>>> +       tset.add (DECL_NAME (x));
>>> 
>>>       for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
>>>        {
>>>          if (DECL_NAME (x) != NULL_TREE
>>> -             && pointer_set_contains (tset, DECL_NAME (x)))
>>> +             && tset.contains (DECL_NAME (x)))
>>>            {
>>>              warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
>>>                          ("using %qD as both field and typedef name is "
>>> @@ -7241,8 +7241,6 @@ warn_cxx_compat_finish_struct (tree fieldlist)
>>>                 the typedef name is used.  */
>>>            }
>>>        }
>>> -
>>> -      pointer_set_destroy (tset);
>>>     }
>>> 
>>>   /* For each field which has a binding and which was not defined in
>>> @@ -8189,7 +8187,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>>>   struct c_binding *b;
>>>   tree parm, decl, last;
>>>   tree parmids = arg_info->parms;
>>> -  struct pointer_set_t *seen_args = pointer_set_create ();
>>> +  hash_set<tree> seen_args;
>>> 
>>>   if (!in_system_header_at (input_location))
>>>     warning_at (DECL_SOURCE_LOCATION (fndecl),
>>> @@ -8220,7 +8218,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>>>                      "%qD declared as a non-parameter", decl);
>>>          /* If the declaration is already marked, we have a duplicate
>>>             name.  Complain and ignore the duplicate.  */
>>> -         else if (pointer_set_contains (seen_args, decl))
>>> +         else if (seen_args.contains (decl))
>>>            {
>>>              error_at (DECL_SOURCE_LOCATION (decl),
>>>                        "multiple parameters named %qD", decl);
>>> @@ -8269,7 +8267,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>>>        }
>>> 
>>>       TREE_PURPOSE (parm) = decl;
>>> -      pointer_set_insert (seen_args, decl);
>>> +      seen_args.add (decl);
>>>     }
>>> 
>>>   /* Now examine the parms chain for incomplete declarations
>>> @@ -8289,7 +8287,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>>>          TREE_TYPE (parm) = error_mark_node;
>>>        }
>>> 
>>> -      if (!pointer_set_contains (seen_args, parm))
>>> +      if (!seen_args.contains (parm))
>>>        {
>>>          error_at (DECL_SOURCE_LOCATION (parm),
>>>                    "declaration for parameter %qD but no such parameter",
>>> @@ -8324,8 +8322,6 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
>>>       DECL_CHAIN (last) = 0;
>>>     }
>>> 
>>> -  pointer_set_destroy (seen_args);
>>> -
>>>   /* If there was a previous prototype,
>>>      set the DECL_ARG_TYPE of each argument according to
>>>      the type previously specified, and report any mismatches.  */
>>> diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
>>> index 2f0ae71..b20be10 100644
>>> --- a/gcc/cfgexpand.c
>>> +++ b/gcc/cfgexpand.c
>>> @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "expr.h"
>>> #include "langhooks.h"
>>> #include "bitmap.h"
>>> +#include "hash-set.h"
>>> #include "pointer-set.h"
>>> #include "tree-ssa-alias.h"
>>> #include "internal-fn.h"
>>> @@ -594,7 +595,7 @@ stack_var_cmp (const void *a, const void *b)
>>> static void
>>> add_partitioned_vars_to_ptset (struct pt_solution *pt,
>>>                               struct pointer_map_t *decls_to_partitions,
>>> -                              struct pointer_set_t *visited, bitmap temp)
>>> +                              hash_set<bitmap> *visited, bitmap temp)
>>> {
>>>   bitmap_iterator bi;
>>>   unsigned i;
>>> @@ -604,7 +605,7 @@ add_partitioned_vars_to_ptset (struct pt_solution *pt,
>>>       || pt->vars == NULL
>>>       /* The pointed-to vars bitmap is shared, it is enough to
>>>         visit it once.  */
>>> -      || pointer_set_insert (visited, pt->vars))
>>> +      || visited->add (pt->vars))
>>>     return;
>>> 
>>>   bitmap_clear (temp);
>>> @@ -684,7 +685,7 @@ update_alias_info_with_stack_vars (void)
>>>   if (decls_to_partitions)
>>>     {
>>>       unsigned i;
>>> -      struct pointer_set_t *visited = pointer_set_create ();
>>> +      hash_set<bitmap> visited;
>>>       bitmap temp = BITMAP_ALLOC (&stack_var_bitmap_obstack);
>>> 
>>>       for (i = 1; i < num_ssa_names; i++)
>>> @@ -696,13 +697,12 @@ update_alias_info_with_stack_vars (void)
>>>              && POINTER_TYPE_P (TREE_TYPE (name))
>>>              && ((pi = SSA_NAME_PTR_INFO (name)) != NULL))
>>>            add_partitioned_vars_to_ptset (&pi->pt, decls_to_partitions,
>>> -                                          visited, temp);
>>> +                                          &visited, temp);
>>>        }
>>> 
>>>       add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped,
>>> -                                    decls_to_partitions, visited, temp);
>>> +                                    decls_to_partitions, &visited, temp);
>>> 
>>> -      pointer_set_destroy (visited);
>>>       pointer_map_destroy (decls_to_partitions);
>>>       BITMAP_FREE (temp);
>>>     }
>>> diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
>>> index 73f79ef..8f7e265 100644
>>> --- a/gcc/cfgloop.c
>>> +++ b/gcc/cfgloop.c
>>> @@ -28,7 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "diagnostic-core.h"
>>> #include "flags.h"
>>> #include "tree.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> #include "tree-ssa-alias.h"
>>> #include "internal-fn.h"
>>> #include "gimple-expr.h"
>>> @@ -650,11 +650,11 @@ find_subloop_latch_edge (struct loop *loop)
>>> /* Callback for make_forwarder_block.  Returns true if the edge E is marked
>>>    in the set MFB_REIS_SET.  */
>>> 
>>> -static struct pointer_set_t *mfb_reis_set;
>>> +static hash_set<edge> *mfb_reis_set;
>>> static bool
>>> mfb_redirect_edges_in_set (edge e)
>>> {
>>> -  return pointer_set_contains (mfb_reis_set, e);
>>> +  return mfb_reis_set->contains (e);
>>> }
>>> 
>>> /* Creates a subloop of LOOP with latch edge LATCH.  */
>>> @@ -666,15 +666,15 @@ form_subloop (struct loop *loop, edge latch)
>>>   edge e, new_entry;
>>>   struct loop *new_loop;
>>> 
>>> -  mfb_reis_set = pointer_set_create ();
>>> +  mfb_reis_set = new hash_set<edge>;
>>>   FOR_EACH_EDGE (e, ei, loop->header->preds)
>>>     {
>>>       if (e != latch)
>>> -       pointer_set_insert (mfb_reis_set, e);
>>> +       mfb_reis_set->add (e);
>>>     }
>>>   new_entry = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
>>>                                    NULL);
>>> -  pointer_set_destroy (mfb_reis_set);
>>> +  delete mfb_reis_set;
>>> 
>>>   loop->header = new_entry->src;
>>> 
>>> @@ -705,12 +705,12 @@ merge_latch_edges (struct loop *loop)
>>>       if (dump_file)
>>>        fprintf (dump_file, "Merged latch edges of loop %d\n", loop->num);
>>> 
>>> -      mfb_reis_set = pointer_set_create ();
>>> +      mfb_reis_set = new hash_set<edge>;
>>>       FOR_EACH_VEC_ELT (latches, i, e)
>>> -       pointer_set_insert (mfb_reis_set, e);
>>> +       mfb_reis_set->add (e);
>>>       latch = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
>>>                                    NULL);
>>> -      pointer_set_destroy (mfb_reis_set);
>>> +      delete mfb_reis_set;
>>> 
>>>       loop->header = latch->dest;
>>>       loop->latch = latch->src;
>>> diff --git a/gcc/cgraph.c b/gcc/cgraph.c
>>> index a5d0749..7c72399 100644
>>> --- a/gcc/cgraph.c
>>> +++ b/gcc/cgraph.c
>>> @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "tree-inline.h"
>>> #include "langhooks.h"
>>> #include "hashtab.h"
>>> +#include "hash-set.h"
>>> #include "toplev.h"
>>> #include "flags.h"
>>> #include "debug.h"
>>> @@ -2871,7 +2872,7 @@ cgraph_node::verify_node (void)
>>>     {
>>>       if (this_cfun->cfg)
>>>        {
>>> -         pointer_set_t *stmts = pointer_set_create ();
>>> +         hash_set<gimple> stmts;
>>>          int i;
>>>          struct ipa_ref *ref = NULL;
>>> 
>>> @@ -2881,13 +2882,13 @@ cgraph_node::verify_node (void)
>>>            {
>>>              for (gsi = gsi_start_phis (this_block);
>>>                   !gsi_end_p (gsi); gsi_next (&gsi))
>>> -               pointer_set_insert (stmts, gsi_stmt (gsi));
>>> +               stmts.add (gsi_stmt (gsi));
>>>              for (gsi = gsi_start_bb (this_block);
>>>                   !gsi_end_p (gsi);
>>>                   gsi_next (&gsi))
>>>                {
>>>                  gimple stmt = gsi_stmt (gsi);
>>> -                 pointer_set_insert (stmts, stmt);
>>> +                 stmts.add (stmt);
>>>                  if (is_gimple_call (stmt))
>>>                    {
>>>                      struct cgraph_edge *e = get_edge (stmt);
>>> @@ -2931,13 +2932,12 @@ cgraph_node::verify_node (void)
>>>                }
>>>              }
>>>            for (i = 0; iterate_reference (i, ref); i++)
>>> -             if (ref->stmt && !pointer_set_contains (stmts, ref->stmt))
>>> +             if (ref->stmt && !stmts.contains (ref->stmt))
>>>                {
>>>                  error ("reference to dead statement");
>>>                  cgraph_debug_gimple_stmt (this_cfun, ref->stmt);
>>>                  error_found = true;
>>>                }
>>> -           pointer_set_destroy (stmts);
>>>        }
>>>       else
>>>        /* No CFG available?!  */
>>> diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
>>> index 91811d7..a04958f 100644
>>> --- a/gcc/cgraphbuild.c
>>> +++ b/gcc/cgraphbuild.c
>>> @@ -322,7 +322,6 @@ pass_build_cgraph_edges::execute (function *fun)
>>> {
>>>   basic_block bb;
>>>   struct cgraph_node *node = cgraph_node::get (current_function_decl);
>>> -  struct pointer_set_t *visited_nodes = pointer_set_create ();
>>>   gimple_stmt_iterator gsi;
>>>   tree decl;
>>>   unsigned ix;
>>> @@ -386,7 +385,6 @@ pass_build_cgraph_edges::execute (function *fun)
>>>       varpool_node::finalize_decl (decl);
>>>   record_eh_tables (node, fun);
>>> 
>>> -  pointer_set_destroy (visited_nodes);
>>>   return 0;
>>> }
>>> 
>>> @@ -405,15 +403,14 @@ make_pass_build_cgraph_edges (gcc::context *ctxt)
>>> void
>>> record_references_in_initializer (tree decl, bool only_vars)
>>> {
>>> -  struct pointer_set_t *visited_nodes = pointer_set_create ();
>>>   varpool_node *node = varpool_node::get_create (decl);
>>> +  hash_set<tree> visited_nodes;
>>>   struct record_reference_ctx ctx = {false, NULL};
>>> 
>>>   ctx.varpool_node = node;
>>>   ctx.only_vars = only_vars;
>>>   walk_tree (&DECL_INITIAL (decl), record_reference,
>>> -             &ctx, visited_nodes);
>>> -  pointer_set_destroy (visited_nodes);
>>> +             &ctx, &visited_nodes);
>>> }
>>> 
>>> /* Rebuild cgraph edges for current function node.  This needs to be run after
>>> diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
>>> index 3080b9a..220b953 100644
>>> --- a/gcc/cgraphunit.c
>>> +++ b/gcc/cgraphunit.c
>>> @@ -845,7 +845,7 @@ varpool_node::finalize_decl (tree decl)
>>>    avoid udplicate work.  */
>>> 
>>> static void
>>> -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
>>> +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
>>>                               struct cgraph_edge *edge)
>>> {
>>>   unsigned int i;
>>> @@ -855,8 +855,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
>>>     = possible_polymorphic_call_targets
>>>        (edge, &final, &cache_token);
>>> 
>>> -  if (!pointer_set_insert (reachable_call_targets,
>>> -                          cache_token))
>>> +  if (!reachable_call_targets->add (cache_token))
>>>     {
>>>       if (cgraph_dump_file)
>>>        dump_possible_polymorphic_call_targets
>>> @@ -936,7 +935,7 @@ analyze_functions (void)
>>>   struct cgraph_node *first_handled = first_analyzed;
>>>   static varpool_node *first_analyzed_var;
>>>   varpool_node *first_handled_var = first_analyzed_var;
>>> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
>>> +  hash_set<void *> reachable_call_targets;
>>> 
>>>   symtab_node *node;
>>>   symtab_node *next;
>>> @@ -1035,7 +1034,7 @@ analyze_functions (void)
>>>                    {
>>>                      next = edge->next_callee;
>>>                      if (edge->indirect_info->polymorphic)
>>> -                       walk_polymorphic_call_targets (reachable_call_targets,
>>> +                       walk_polymorphic_call_targets (&reachable_call_targets,
>>>                                                       edge);
>>>                    }
>>>                }
>>> @@ -1123,7 +1122,6 @@ analyze_functions (void)
>>>       symtab_node::dump_table (cgraph_dump_file);
>>>     }
>>>   bitmap_obstack_release (NULL);
>>> -  pointer_set_destroy (reachable_call_targets);
>>>   ggc_collect ();
>>>   /* Initialize assembler name hash, in particular we want to trigger C++
>>>      mangling and same body alias creation before we free DECL_ARGUMENTS
>>> diff --git a/gcc/cp/class.c b/gcc/cp/class.c
>>> index 0f611e1..d9b34f7 100644
>>> --- a/gcc/cp/class.c
>>> +++ b/gcc/cp/class.c
>>> @@ -5359,15 +5359,15 @@ finalize_literal_type_property (tree t)
>>> void
>>> explain_non_literal_class (tree t)
>>> {
>>> -  static struct pointer_set_t *diagnosed;
>>> +  static hash_set<tree> *diagnosed;
>>> 
>>>   if (!CLASS_TYPE_P (t))
>>>     return;
>>>   t = TYPE_MAIN_VARIANT (t);
>>> 
>>>   if (diagnosed == NULL)
>>> -    diagnosed = pointer_set_create ();
>>> -  if (pointer_set_insert (diagnosed, t) != 0)
>>> +    diagnosed = new hash_set<tree>;
>>> +  if (diagnosed->add (t))
>>>     /* Already explained.  */
>>>     return;
>>> 
>>> diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
>>> index a35177b..3cfcbc6 100644
>>> --- a/gcc/cp/cp-gimplify.c
>>> +++ b/gcc/cp/cp-gimplify.c
>>> @@ -871,7 +871,7 @@ omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
>>> 
>>> struct cp_genericize_data
>>> {
>>> -  struct pointer_set_t *p_set;
>>> +  hash_set<tree> *p_set;
>>>   vec<tree> bind_expr_stack;
>>>   struct cp_genericize_omp_taskreg *omp_ctx;
>>> };
>>> @@ -884,7 +884,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
>>> {
>>>   tree stmt = *stmt_p;
>>>   struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
>>> -  struct pointer_set_t *p_set = wtd->p_set;
>>> +  hash_set<tree> *p_set = wtd->p_set;
>>> 
>>>   /* If in an OpenMP context, note var uses.  */
>>>   if (__builtin_expect (wtd->omp_ctx != NULL, 0)
>>> @@ -924,7 +924,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
>>>     }
>>> 
>>>   /* Other than invisiref parms, don't walk the same tree twice.  */
>>> -  if (pointer_set_contains (p_set, stmt))
>>> +  if (p_set->contains (stmt))
>>>     {
>>>       *walk_subtrees = 0;
>>>       return NULL_TREE;
>>> @@ -1199,7 +1199,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
>>>       return NULL;
>>>     }
>>> 
>>> -  pointer_set_insert (p_set, *stmt_p);
>>> +  p_set->add (*stmt_p);
>>> 
>>>   return NULL;
>>> }
>>> @@ -1211,11 +1211,11 @@ cp_genericize_tree (tree* t_p)
>>> {
>>>   struct cp_genericize_data wtd;
>>> 
>>> -  wtd.p_set = pointer_set_create ();
>>> +  wtd.p_set = new hash_set<tree>;
>>>   wtd.bind_expr_stack.create (0);
>>>   wtd.omp_ctx = NULL;
>>>   cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
>>> -  pointer_set_destroy (wtd.p_set);
>>> +  delete wtd.p_set;
>>>   wtd.bind_expr_stack.release ();
>>> }
>>> 
>>> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
>>> index 0c0d804..622de9c 100644
>>> --- a/gcc/cp/cp-tree.h
>>> +++ b/gcc/cp/cp-tree.h
>>> @@ -6028,7 +6028,7 @@ extern void verify_stmt_tree                      (tree);
>>> extern linkage_kind decl_linkage               (tree);
>>> extern duration_kind decl_storage_duration     (tree);
>>> extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
>>> -                             void*, struct pointer_set_t*);
>>> +                             void*, hash_set<tree> *);
>>> #define cp_walk_tree(tp,func,data,pset) \
>>>        walk_tree_1 (tp, func, data, pset, cp_walk_subtrees)
>>> #define cp_walk_tree_without_duplicates(tp,func,data) \
>>> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
>>> index aafb917..f70684f 100644
>>> --- a/gcc/cp/decl.c
>>> +++ b/gcc/cp/decl.c
>>> @@ -8198,7 +8198,7 @@ check_static_variable_definition (tree decl, tree type)
>>> static tree
>>> stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
>>> {
>>> -  struct pointer_set_t *pset = (struct pointer_set_t *)data;
>>> +  hash_set<tree> *pset = (hash_set<tree> *)data;
>>>   tree expr = *expr_p;
>>>   if (TREE_CODE (expr) == SAVE_EXPR)
>>>     {
>>> @@ -8218,10 +8218,9 @@ stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
>>> static void
>>> stabilize_vla_size (tree size)
>>> {
>>> -  struct pointer_set_t *pset = pointer_set_create ();
>>> +  hash_set<tree> pset;
>>>   /* Break out any function calls into temporary variables.  */
>>> -  cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
>>> -  pointer_set_destroy (pset);
>>> +  cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
>>> }
>>> 
>>> /* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
>>> diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
>>> index 8fa3145..d79665e 100644
>>> --- a/gcc/cp/decl2.c
>>> +++ b/gcc/cp/decl2.c
>>> @@ -3938,11 +3938,11 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
>>>    supported, collect and return all the functions for which we should
>>>    emit a hidden alias.  */
>>> 
>>> -static struct pointer_set_t *
>>> +static hash_set<tree> *
>>> collect_candidates_for_java_method_aliases (void)
>>> {
>>>   struct cgraph_node *node;
>>> -  struct pointer_set_t *candidates = NULL;
>>> +  hash_set<tree> *candidates = NULL;
>>> 
>>> #ifndef HAVE_GAS_HIDDEN
>>>   return candidates;
>>> @@ -3957,8 +3957,8 @@ collect_candidates_for_java_method_aliases (void)
>>>          && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
>>>        {
>>>          if (candidates == NULL)
>>> -           candidates = pointer_set_create ();
>>> -         pointer_set_insert (candidates, fndecl);
>>> +           candidates = new hash_set<tree>;
>>> +         candidates->add (fndecl);
>>>        }
>>>     }
>>> 
>>> @@ -3973,7 +3973,7 @@ collect_candidates_for_java_method_aliases (void)
>>>    by collect_candidates_for_java_method_aliases.  */
>>> 
>>> static void
>>> -build_java_method_aliases (struct pointer_set_t *candidates)
>>> +build_java_method_aliases (hash_set<tree> *candidates)
>>> {
>>>   struct cgraph_node *node;
>>> 
>>> @@ -3986,7 +3986,7 @@ build_java_method_aliases (struct pointer_set_t *candidates)
>>>       tree fndecl = node->decl;
>>> 
>>>       if (TREE_ASM_WRITTEN (fndecl)
>>> -         && pointer_set_contains (candidates, fndecl))
>>> +         && candidates->contains (fndecl))
>>>        {
>>>          /* Mangle the name in a predictable way; we need to reference
>>>             this from a java compiled object file.  */
>>> @@ -4296,7 +4296,7 @@ cp_write_global_declarations (void)
>>>   unsigned ssdf_count = 0;
>>>   int retries = 0;
>>>   tree decl;
>>> -  struct pointer_set_t *candidates;
>>> +  hash_set<tree> *candidates;
>>> 
>>>   locus = input_location;
>>>   at_eof = 1;
>>> @@ -4713,7 +4713,7 @@ cp_write_global_declarations (void)
>>>   if (candidates)
>>>     {
>>>       build_java_method_aliases (candidates);
>>> -      pointer_set_destroy (candidates);
>>> +      delete candidates;
>>>     }
>>> 
>>>   finish_repo ();
>>> diff --git a/gcc/cp/error.c b/gcc/cp/error.c
>>> index fa3bdc4..c8987ee 100644
>>> --- a/gcc/cp/error.c
>>> +++ b/gcc/cp/error.c
>>> @@ -1325,7 +1325,7 @@ dump_template_decl (cxx_pretty_printer *pp, tree t, int flags)
>>> 
>>> struct find_typenames_t
>>> {
>>> -  struct pointer_set_t *p_set;
>>> +  hash_set<tree> *p_set;
>>>   vec<tree, va_gc> *typenames;
>>> };
>>> 
>>> @@ -1351,7 +1351,7 @@ find_typenames_r (tree *tp, int *walk_subtrees, void *data)
>>>       return NULL_TREE;
>>>     }
>>> 
>>> -  if (mv && (mv == *tp || !pointer_set_insert (d->p_set, mv)))
>>> +  if (mv && (mv == *tp || !d->p_set->add (mv)))
>>>     vec_safe_push (d->typenames, mv);
>>> 
>>>   /* Search into class template arguments, which cp_walk_subtrees
>>> @@ -1367,11 +1367,11 @@ static vec<tree, va_gc> *
>>> find_typenames (tree t)
>>> {
>>>   struct find_typenames_t ft;
>>> -  ft.p_set = pointer_set_create ();
>>> +  ft.p_set = new hash_set<tree>;
>>>   ft.typenames = NULL;
>>>   cp_walk_tree (&TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
>>>                find_typenames_r, &ft, ft.p_set);
>>> -  pointer_set_destroy (ft.p_set);
>>> +  delete ft.p_set;
>>>   return ft.typenames;
>>> }
>>> 
>>> diff --git a/gcc/cp/method.c b/gcc/cp/method.c
>>> index e5fa0c1..65c5621 100644
>>> --- a/gcc/cp/method.c
>>> +++ b/gcc/cp/method.c
>>> @@ -1480,7 +1480,7 @@ maybe_explain_implicit_delete (tree decl)
>>>   if (DECL_DEFAULTED_FN (decl))
>>>     {
>>>       /* Not marked GTY; it doesn't need to be GC'd or written to PCH.  */
>>> -      static struct pointer_set_t *explained;
>>> +      static hash_set<tree> *explained;
>>> 
>>>       special_function_kind sfk;
>>>       location_t loc;
>>> @@ -1488,8 +1488,8 @@ maybe_explain_implicit_delete (tree decl)
>>>       tree ctype;
>>> 
>>>       if (!explained)
>>> -       explained = pointer_set_create ();
>>> -      if (pointer_set_insert (explained, decl))
>>> +       explained = new hash_set<tree>;
>>> +      if (explained->add (decl))
>>>        return true;
>>> 
>>>       sfk = special_function_p (decl);
>>> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
>>> index 75b46ac..6e779a6 100644
>>> --- a/gcc/cp/name-lookup.c
>>> +++ b/gcc/cp/name-lookup.c
>>> @@ -35,7 +35,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "debug.h"
>>> #include "c-family/c-pragma.h"
>>> #include "params.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> 
>>> /* The bindings for a particular name in a particular scope.  */
>>> 
>>> @@ -5152,7 +5152,7 @@ struct arg_lookup
>>>   vec<tree, va_gc> *namespaces;
>>>   vec<tree, va_gc> *classes;
>>>   tree functions;
>>> -  struct pointer_set_t *fn_set;
>>> +  hash_set<tree> *fn_set;
>>> };
>>> 
>>> static bool arg_assoc (struct arg_lookup*, tree);
>>> @@ -5175,7 +5175,7 @@ add_function (struct arg_lookup *k, tree fn)
>>>   if (!is_overloaded_fn (fn))
>>>     /* All names except those of (possibly overloaded) functions and
>>>        function templates are ignored.  */;
>>> -  else if (k->fn_set && pointer_set_insert (k->fn_set, fn))
>>> +  else if (k->fn_set && k->fn_set->add (fn))
>>>     /* It's already in the list.  */;
>>>   else if (!k->functions)
>>>     k->functions = fn;
>>> @@ -5639,9 +5639,9 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
>>>       /* We shouldn't be here if lookup found something other than
>>>         namespace-scope functions.  */
>>>       gcc_assert (DECL_NAMESPACE_SCOPE_P (OVL_CURRENT (fns)));
>>> -      k.fn_set = pointer_set_create ();
>>> +      k.fn_set = new hash_set<tree>;
>>>       for (ovl = fns; ovl; ovl = OVL_NEXT (ovl))
>>> -       pointer_set_insert (k.fn_set, OVL_CURRENT (ovl));
>>> +       k.fn_set->add (OVL_CURRENT (ovl));
>>>     }
>>>   else
>>>     k.fn_set = NULL;
>>> @@ -5661,8 +5661,7 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
>>> 
>>>   release_tree_vector (k.classes);
>>>   release_tree_vector (k.namespaces);
>>> -  if (k.fn_set)
>>> -    pointer_set_destroy (k.fn_set);
>>> +  delete k.fn_set;
>>> 
>>>   return fns;
>>> }
>>> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
>>> index b32cf6c..9b156f5 100644
>>> --- a/gcc/cp/pt.c
>>> +++ b/gcc/cp/pt.c
>>> @@ -147,7 +147,7 @@ static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
>>> static tree convert_template_argument (tree, tree, tree,
>>>                                       tsubst_flags_t, int, tree);
>>> static int for_each_template_parm (tree, tree_fn_t, void*,
>>> -                                  struct pointer_set_t*, bool);
>>> +                                  hash_set<tree> *, bool);
>>> static tree expand_template_argument_pack (tree);
>>> static tree build_template_parm_index (int, int, int, tree, tree);
>>> static bool inline_needs_template_parms (tree, bool);
>>> @@ -3080,7 +3080,7 @@ struct find_parameter_pack_data
>>>   tree* parameter_packs;
>>> 
>>>   /* Set of AST nodes that have been visited by the traversal.  */
>>> -  struct pointer_set_t *visited;
>>> +  hash_set<tree> *visited;
>>> };
>>> 
>>> /* Identifies all of the argument packs that occur in a template
>>> @@ -3243,9 +3243,9 @@ uses_parameter_packs (tree t)
>>>   tree parameter_packs = NULL_TREE;
>>>   struct find_parameter_pack_data ppd;
>>>   ppd.parameter_packs = &parameter_packs;
>>> -  ppd.visited = pointer_set_create ();
>>> +  ppd.visited = new hash_set<tree>;
>>>   cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
>>> -  pointer_set_destroy (ppd.visited);
>>> +  delete ppd.visited;
>>>   return parameter_packs != NULL_TREE;
>>> }
>>> 
>>> @@ -3292,7 +3292,7 @@ make_pack_expansion (tree arg)
>>> 
>>>       /* Determine which parameter packs will be used by the base
>>>          class expansion.  */
>>> -      ppd.visited = pointer_set_create ();
>>> +      ppd.visited = new hash_set<tree>;
>>>       ppd.parameter_packs = &parameter_packs;
>>>       cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
>>>                     &ppd, ppd.visited);
>>> @@ -3300,7 +3300,7 @@ make_pack_expansion (tree arg)
>>>       if (parameter_packs == NULL_TREE)
>>>         {
>>>           error ("base initializer expansion %<%T%> contains no parameter packs", arg);
>>> -          pointer_set_destroy (ppd.visited);
>>> +          delete ppd.visited;
>>>           return error_mark_node;
>>>         }
>>> 
>>> @@ -3317,7 +3317,7 @@ make_pack_expansion (tree arg)
>>>             }
>>>         }
>>> 
>>> -      pointer_set_destroy (ppd.visited);
>>> +      delete ppd.visited;
>>> 
>>>       /* Create the pack expansion type for the base type.  */
>>>       purpose = cxx_make_type (TYPE_PACK_EXPANSION);
>>> @@ -3352,9 +3352,9 @@ make_pack_expansion (tree arg)
>>> 
>>>   /* Determine which parameter packs will be expanded.  */
>>>   ppd.parameter_packs = &parameter_packs;
>>> -  ppd.visited = pointer_set_create ();
>>> +  ppd.visited = new hash_set<tree>;
>>>   cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
>>> -  pointer_set_destroy (ppd.visited);
>>> +  delete ppd.visited;
>>> 
>>>   /* Make sure we found some parameter packs.  */
>>>   if (parameter_packs == NULL_TREE)
>>> @@ -3399,9 +3399,9 @@ check_for_bare_parameter_packs (tree t)
>>>     t = TREE_TYPE (t);
>>> 
>>>   ppd.parameter_packs = &parameter_packs;
>>> -  ppd.visited = pointer_set_create ();
>>> +  ppd.visited = new hash_set<tree>;
>>>   cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
>>> -  pointer_set_destroy (ppd.visited);
>>> +  delete ppd.visited;
>>> 
>>>   if (parameter_packs)
>>>     {
>>> @@ -4381,11 +4381,11 @@ fixed_parameter_pack_p (tree parm)
>>>   tree parameter_packs = NULL_TREE;
>>>   struct find_parameter_pack_data ppd;
>>>   ppd.parameter_packs = &parameter_packs;
>>> -  ppd.visited = pointer_set_create ();
>>> +  ppd.visited = new hash_set<tree>;
>>> 
>>>   fixed_parameter_pack_p_1 (parm, &ppd);
>>> 
>>> -  pointer_set_destroy (ppd.visited);
>>> +  delete ppd.visited;
>>>   return parameter_packs;
>>> }
>>> 
>>> @@ -7907,7 +7907,7 @@ struct pair_fn_data
>>>   /* True when we should also visit template parameters that occur in
>>>      non-deduced contexts.  */
>>>   bool include_nondeduced_p;
>>> -  struct pointer_set_t *visited;
>>> +  hash_set<tree> *visited;
>>> };
>>> 
>>> /* Called from for_each_template_parm via walk_tree.  */
>>> @@ -8107,7 +8107,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
>>> 
>>> static int
>>> for_each_template_parm (tree t, tree_fn_t fn, void* data,
>>> -                       struct pointer_set_t *visited,
>>> +                       hash_set<tree> *visited,
>>>                        bool include_nondeduced_p)
>>> {
>>>   struct pair_fn_data pfd;
>>> @@ -8126,7 +8126,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
>>>   if (visited)
>>>     pfd.visited = visited;
>>>   else
>>> -    pfd.visited = pointer_set_create ();
>>> +    pfd.visited = new hash_set<tree>;
>>>   result = cp_walk_tree (&t,
>>>                         for_each_template_parm_r,
>>>                         &pfd,
>>> @@ -8135,7 +8135,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
>>>   /* Clean up.  */
>>>   if (!visited)
>>>     {
>>> -      pointer_set_destroy (pfd.visited);
>>> +      delete pfd.visited;
>>>       pfd.visited = 0;
>>>     }
>>> 
>>> diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
>>> index c87764d..735284e 100644
>>> --- a/gcc/cp/semantics.c
>>> +++ b/gcc/cp/semantics.c
>>> @@ -8031,7 +8031,7 @@ register_constexpr_fundef (tree fun, tree body)
>>> void
>>> explain_invalid_constexpr_fn (tree fun)
>>> {
>>> -  static struct pointer_set_t *diagnosed;
>>> +  static hash_set<tree> *diagnosed;
>>>   tree body;
>>>   location_t save_loc;
>>>   /* Only diagnose defaulted functions or instantiations.  */
>>> @@ -8039,8 +8039,8 @@ explain_invalid_constexpr_fn (tree fun)
>>>       && !is_instantiation_of_constexpr (fun))
>>>     return;
>>>   if (diagnosed == NULL)
>>> -    diagnosed = pointer_set_create ();
>>> -  if (pointer_set_insert (diagnosed, fun) != 0)
>>> +    diagnosed = new hash_set<tree>;
>>> +  if (diagnosed->add (fun))
>>>     /* Already explained.  */
>>>     return;
>>> 
>>> diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
>>> index f6c5693..697a02b 100644
>>> --- a/gcc/cp/tree.c
>>> +++ b/gcc/cp/tree.c
>>> @@ -3485,7 +3485,7 @@ cxx_type_hash_eq (const_tree typea, const_tree typeb)
>>> 
>>> tree
>>> cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
>>> -                 void *data, struct pointer_set_t *pset)
>>> +                 void *data, hash_set<tree> *pset)
>>> {
>>>   enum tree_code code = TREE_CODE (*tp);
>>>   tree result;
>>> diff --git a/gcc/cprop.c b/gcc/cprop.c
>>> index 6291c91..4234afa 100644
>>> --- a/gcc/cprop.c
>>> +++ b/gcc/cprop.c
>>> @@ -167,7 +167,7 @@ reg_available_p (const_rtx x, const_rtx insn ATTRIBUTE_UNUSED)
>>>    ??? May need to make things more elaborate.  Later, as necessary.  */
>>> 
>>> static unsigned int
>>> -hash_set (int regno, int hash_table_size)
>>> +hash_mod (int regno, int hash_table_size)
>>> {
>>>   return (unsigned) regno % hash_table_size;
>>> }
>>> @@ -187,7 +187,7 @@ insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table,
>>>   struct expr *cur_expr, *last_expr = NULL;
>>>   struct occr *cur_occr;
>>> 
>>> -  hash = hash_set (REGNO (dest), table->size);
>>> +  hash = hash_mod (REGNO (dest), table->size);
>>> 
>>>   for (cur_expr = table->table[hash]; cur_expr;
>>>        cur_expr = cur_expr->next_same_hash)
>>> @@ -483,7 +483,7 @@ compute_hash_table (struct hash_table_d *table)
>>> static struct expr *
>>> lookup_set (unsigned int regno, struct hash_table_d *table)
>>> {
>>> -  unsigned int hash = hash_set (regno, table->size);
>>> +  unsigned int hash = hash_mod (regno, table->size);
>>>   struct expr *expr;
>>> 
>>>   expr = table->table[hash];
>>> diff --git a/gcc/cse.c b/gcc/cse.c
>>> index 34f9364..dd9a076 100644
>>> --- a/gcc/cse.c
>>> +++ b/gcc/cse.c
>>> @@ -41,7 +41,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "tree-pass.h"
>>> #include "df.h"
>>> #include "dbgcnt.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> 
>>> /* The basic idea of common subexpression elimination is to go
>>>    through the code, keeping a record of expressions that would
>>> @@ -2906,7 +2906,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>>>                      enum machine_mode *pmode1, enum machine_mode *pmode2)
>>> {
>>>   rtx arg1, arg2;
>>> -  struct pointer_set_t *visited = NULL;
>>> +  hash_set<rtx> *visited = NULL;
>>>   /* Set nonzero when we find something of interest.  */
>>>   rtx x = NULL;
>>> 
>>> @@ -2923,8 +2923,8 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>>>       if (x)
>>>        {
>>>          if (!visited)
>>> -           visited = pointer_set_create ();
>>> -         pointer_set_insert (visited, x);
>>> +           visited = new hash_set<rtx>;
>>> +         visited->add (x);
>>>          x = 0;
>>>        }
>>> 
>>> @@ -3005,7 +3005,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>>>            continue;
>>> 
>>>          /* If it's a comparison we've used before, skip it.  */
>>> -         if (visited && pointer_set_contains (visited, p->exp))
>>> +         if (visited && visited->contains (p->exp))
>>>            continue;
>>> 
>>>          if (GET_CODE (p->exp) == COMPARE
>>> @@ -3087,7 +3087,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
>>>   *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0);
>>> 
>>>   if (visited)
>>> -    pointer_set_destroy (visited);
>>> +    delete visited;
>>>   return code;
>>> }
>>> 
>>> diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
>>> index 68ba70f..410efb1 100644
>>> --- a/gcc/fortran/openmp.c
>>> +++ b/gcc/fortran/openmp.c
>>> @@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "arith.h"
>>> #include "match.h"
>>> #include "parse.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> 
>>> /* Match an end of OpenMP directive.  End of OpenMP directive is optional
>>>    whitespace, followed by '\n' or comment '!'.  */
>>> @@ -3013,8 +3013,8 @@ resolve_omp_atomic (gfc_code *code)
>>> struct omp_context
>>> {
>>>   gfc_code *code;
>>> -  struct pointer_set_t *sharing_clauses;
>>> -  struct pointer_set_t *private_iterators;
>>> +  hash_set<gfc_symbol *> *sharing_clauses;
>>> +  hash_set<gfc_symbol *> *private_iterators;
>>>   struct omp_context *previous;
>>> } *omp_current_ctx;
>>> static gfc_code *omp_current_do_code;
>>> @@ -3057,8 +3057,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
>>>   int list;
>>> 
>>>   ctx.code = code;
>>> -  ctx.sharing_clauses = pointer_set_create ();
>>> -  ctx.private_iterators = pointer_set_create ();
>>> +  ctx.sharing_clauses = new hash_set<gfc_symbol *>;
>>> +  ctx.private_iterators = new hash_set<gfc_symbol *>;
>>>   ctx.previous = omp_current_ctx;
>>>   omp_current_ctx = &ctx;
>>> 
>>> @@ -3072,7 +3072,7 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
>>>       case OMP_LIST_REDUCTION:
>>>       case OMP_LIST_LINEAR:
>>>        for (n = omp_clauses->lists[list]; n; n = n->next)
>>> -         pointer_set_insert (ctx.sharing_clauses, n->sym);
>>> +         ctx.sharing_clauses->add (n->sym);
>>>        break;
>>>       default:
>>>        break;
>>> @@ -3097,8 +3097,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
>>>     }
>>> 
>>>   omp_current_ctx = ctx.previous;
>>> -  pointer_set_destroy (ctx.sharing_clauses);
>>> -  pointer_set_destroy (ctx.private_iterators);
>>> +  delete ctx.sharing_clauses;
>>> +  delete ctx.private_iterators;
>>> }
>>> 
>>> 
>>> @@ -3154,10 +3154,10 @@ gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym)
>>>   if (omp_current_ctx == NULL)
>>>     return;
>>> 
>>> -  if (pointer_set_contains (omp_current_ctx->sharing_clauses, sym))
>>> +  if (omp_current_ctx->sharing_clauses->contains (sym))
>>>     return;
>>> 
>>> -  if (! pointer_set_insert (omp_current_ctx->private_iterators, sym))
>>> +  if (! omp_current_ctx->private_iterators->add (sym))
>>>     {
>>>       gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
>>>       gfc_omp_namelist *p;
>>> diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
>>> index 8b56151..babe48f 100644
>>> --- a/gcc/fortran/trans-decl.c
>>> +++ b/gcc/fortran/trans-decl.c
>>> @@ -40,7 +40,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "cgraph.h"
>>> #include "debug.h"
>>> #include "gfortran.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> #include "constructor.h"
>>> #include "trans.h"
>>> #include "trans-types.h"
>>> @@ -63,7 +63,7 @@ static GTY(()) tree parent_fake_result_decl;
>>> static GTY(()) tree saved_function_decls;
>>> static GTY(()) tree saved_parent_function_decls;
>>> 
>>> -static struct pointer_set_t *nonlocal_dummy_decl_pset;
>>> +static hash_set<tree> *nonlocal_dummy_decl_pset;
>>> static GTY(()) tree nonlocal_dummy_decls;
>>> 
>>> /* Holds the variable DECLs that are locals.  */
>>> @@ -1094,9 +1094,9 @@ gfc_nonlocal_dummy_array_decl (gfc_symbol *sym)
>>>   tree decl, dummy;
>>> 
>>>   if (! nonlocal_dummy_decl_pset)
>>> -    nonlocal_dummy_decl_pset = pointer_set_create ();
>>> +    nonlocal_dummy_decl_pset = new hash_set<tree>;
>>> 
>>> -  if (pointer_set_insert (nonlocal_dummy_decl_pset, sym->backend_decl))
>>> +  if (nonlocal_dummy_decl_pset->add (sym->backend_decl))
>>>     return;
>>> 
>>>   dummy = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl);
>>> @@ -5861,7 +5861,7 @@ gfc_generate_function_code (gfc_namespace * ns)
>>>     {
>>>       BLOCK_VARS (DECL_INITIAL (fndecl))
>>>        = chainon (BLOCK_VARS (DECL_INITIAL (fndecl)), nonlocal_dummy_decls);
>>> -      pointer_set_destroy (nonlocal_dummy_decl_pset);
>>> +      delete nonlocal_dummy_decl_pset;
>>>       nonlocal_dummy_decls = NULL;
>>>       nonlocal_dummy_decl_pset = NULL;
>>>     }
>>> diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
>>> index b6f0495..f4f6757 100644
>>> --- a/gcc/gimple-walk.c
>>> +++ b/gcc/gimple-walk.c
>>> @@ -180,7 +180,7 @@ tree
>>> walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
>>>                struct walk_stmt_info *wi)
>>> {
>>> -  struct pointer_set_t *pset = (wi) ? wi->pset : NULL;
>>> +  hash_set<tree> *pset = (wi) ? wi->pset : NULL;
>>>   unsigned i;
>>>   tree ret = NULL_TREE;
>>> 
>>> diff --git a/gcc/gimple-walk.h b/gcc/gimple-walk.h
>>> index 555eb18..5b75fdc 100644
>>> --- a/gcc/gimple-walk.h
>>> +++ b/gcc/gimple-walk.h
>>> @@ -36,7 +36,7 @@ struct walk_stmt_info
>>>   /* Pointer map used to mark visited tree nodes when calling
>>>      walk_tree on each operand.  If set to NULL, duplicate tree nodes
>>>      will be visited more than once.  */
>>> -  struct pointer_set_t *pset;
>>> +  hash_set<tree> *pset;
>>> 
>>>   /* Operand returned by the callbacks.  This is set when calling
>>>      walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
>>> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
>>> index 4ab36d0..c0ae7cc 100644
>>> --- a/gcc/gimplify.c
>>> +++ b/gcc/gimplify.c
>>> @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "coretypes.h"
>>> #include "tree.h"
>>> #include "expr.h"
>>> +#include "hash-set.h"
>>> #include "pointer-set.h"
>>> #include "hash-table.h"
>>> #include "basic-block.h"
>>> @@ -134,7 +135,7 @@ struct gimplify_omp_ctx
>>> {
>>>   struct gimplify_omp_ctx *outer_context;
>>>   splay_tree variables;
>>> -  struct pointer_set_t *privatized_types;
>>> +  hash_set<tree> *privatized_types;
>>>   location_t location;
>>>   enum omp_clause_default_kind default_kind;
>>>   enum omp_region_type region_type;
>>> @@ -352,7 +353,7 @@ new_omp_context (enum omp_region_type region_type)
>>>   c = XCNEW (struct gimplify_omp_ctx);
>>>   c->outer_context = gimplify_omp_ctxp;
>>>   c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
>>> -  c->privatized_types = pointer_set_create ();
>>> +  c->privatized_types = new hash_set<tree>;
>>>   c->location = input_location;
>>>   c->region_type = region_type;
>>>   if ((region_type & ORT_TASK) == 0)
>>> @@ -369,7 +370,7 @@ static void
>>> delete_omp_context (struct gimplify_omp_ctx *c)
>>> {
>>>   splay_tree_delete (c->variables);
>>> -  pointer_set_destroy (c->privatized_types);
>>> +  delete c->privatized_types;
>>>   XDELETE (c);
>>> }
>>> 
>>> @@ -744,7 +745,7 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
>>>      copy their subtrees if we can make sure to do it only once.  */
>>>   if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
>>>     {
>>> -      if (data && !pointer_set_insert ((struct pointer_set_t *)data, t))
>>> +      if (data && !((hash_set<tree> *)data)->add (t))
>>>        ;
>>>       else
>>>        *walk_subtrees = 0;
>>> @@ -829,15 +830,14 @@ unshare_body (tree fndecl)
>>>   struct cgraph_node *cgn = cgraph_node::get (fndecl);
>>>   /* If the language requires deep unsharing, we need a pointer set to make
>>>      sure we don't repeatedly unshare subtrees of unshareable nodes.  */
>>> -  struct pointer_set_t *visited
>>> -    = lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
>>> +  hash_set<tree> *visited
>>> +    = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
>>> 
>>>   copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
>>>   copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
>>>   copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
>>> 
>>> -  if (visited)
>>> -    pointer_set_destroy (visited);
>>> +  delete visited;
>>> 
>>>   if (cgn)
>>>     for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
>>> @@ -1733,7 +1733,7 @@ gimplify_conversion (tree *expr_p)
>>> }
>>> 
>>> /* Nonlocal VLAs seen in the current function.  */
>>> -static struct pointer_set_t *nonlocal_vlas;
>>> +static hash_set<tree> *nonlocal_vlas;
>>> 
>>> /* The VAR_DECLs created for nonlocal VLAs for debug info purposes.  */
>>> static tree nonlocal_vla_vars;
>>> @@ -1784,7 +1784,7 @@ gimplify_var_or_parm_decl (tree *expr_p)
>>>                 && (ctx->region_type == ORT_WORKSHARE
>>>                     || ctx->region_type == ORT_SIMD))
>>>            ctx = ctx->outer_context;
>>> -         if (!ctx && !pointer_set_insert (nonlocal_vlas, decl))
>>> +         if (!ctx && !nonlocal_vlas->add (decl))
>>>            {
>>>              tree copy = copy_node (decl);
>>> 
>>> @@ -5463,7 +5463,7 @@ omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
>>>     return;
>>>   type = TYPE_MAIN_VARIANT (type);
>>> 
>>> -  if (pointer_set_insert (ctx->privatized_types, type))
>>> +  if (ctx->privatized_types->add (type))
>>>     return;
>>> 
>>>   switch (TREE_CODE (type))
>>> @@ -8766,7 +8766,7 @@ gimplify_body (tree fndecl, bool do_parms)
>>> 
>>>   cgn = cgraph_node::get (fndecl);
>>>   if (cgn && cgn->origin)
>>> -    nonlocal_vlas = pointer_set_create ();
>>> +    nonlocal_vlas = new hash_set<tree>;
>>> 
>>>   /* Make sure input_location isn't set to something weird.  */
>>>   input_location = DECL_SOURCE_LOCATION (fndecl);
>>> @@ -8830,7 +8830,7 @@ gimplify_body (tree fndecl, bool do_parms)
>>>                         nonlocal_vla_vars);
>>>          nonlocal_vla_vars = NULL_TREE;
>>>        }
>>> -      pointer_set_destroy (nonlocal_vlas);
>>> +      delete nonlocal_vlas;
>>>       nonlocal_vlas = NULL;
>>>     }
>>> 
>>> diff --git a/gcc/godump.c b/gcc/godump.c
>>> index 2afd7f1..7566f4d 100644
>>> --- a/gcc/godump.c
>>> +++ b/gcc/godump.c
>>> @@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "diagnostic-core.h"
>>> #include "tree.h"
>>> #include "ggc.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> #include "obstack.h"
>>> #include "debug.h"
>>> #include "wide-int-print.h"
>>> @@ -525,11 +525,11 @@ go_type_decl (tree decl, int local)
>>> struct godump_container
>>> {
>>>   /* DECLs that we have already seen.  */
>>> -  struct pointer_set_t *decls_seen;
>>> +  hash_set<tree> decls_seen;
>>> 
>>>   /* Types which may potentially have to be defined as dummy
>>>      types.  */
>>> -  struct pointer_set_t *pot_dummy_types;
>>> +  hash_set<const char *> pot_dummy_types;
>>> 
>>>   /* Go keywords.  */
>>>   htab_t keyword_hash;
>>> @@ -569,8 +569,8 @@ go_format_type (struct godump_container *container, tree type,
>>>   ob = &container->type_obstack;
>>> 
>>>   if (TYPE_NAME (type) != NULL_TREE
>>> -      && (pointer_set_contains (container->decls_seen, type)
>>> -         || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
>>> +      && (container->decls_seen.contains (type)
>>> +         || container->decls_seen.contains (TYPE_NAME (type)))
>>>       && (AGGREGATE_TYPE_P (type)
>>>          || POINTER_TYPE_P (type)
>>>          || TREE_CODE (type) == FUNCTION_TYPE))
>>> @@ -590,7 +590,7 @@ go_format_type (struct godump_container *container, tree type,
>>>       return ret;
>>>     }
>>> 
>>> -  pointer_set_insert (container->decls_seen, type);
>>> +  container->decls_seen.add (type);
>>> 
>>>   switch (TREE_CODE (type))
>>>     {
>>> @@ -697,8 +697,7 @@ go_format_type (struct godump_container *container, tree type,
>>>             definition.  So this struct or union is a potential dummy
>>>             type.  */
>>>          if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
>>> -           pointer_set_insert (container->pot_dummy_types,
>>> -                               IDENTIFIER_POINTER (name));
>>> +           container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
>>> 
>>>          return ret;
>>>         }
>>> @@ -948,10 +947,10 @@ go_output_typedef (struct godump_container *container, tree decl)
>>>      separately.  */
>>>   if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
>>>       && TYPE_SIZE (TREE_TYPE (decl)) != 0
>>> -      && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
>>> +      && !container->decls_seen.contains (TREE_TYPE (decl))
>>>       && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
>>> -         || !pointer_set_contains (container->decls_seen,
>>> -                                   TYPE_CANONICAL (TREE_TYPE (decl)))))
>>> +         || !container->decls_seen.contains
>>> +                                   (TYPE_CANONICAL (TREE_TYPE (decl)))))
>>>     {
>>>       tree element;
>>> 
>>> @@ -988,10 +987,9 @@ go_output_typedef (struct godump_container *container, tree decl)
>>>          mhval->value = xstrdup (buf);
>>>          *slot = mhval;
>>>        }
>>> -      pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
>>> +      container->decls_seen.add (TREE_TYPE (decl));
>>>       if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
>>> -       pointer_set_insert (container->decls_seen,
>>> -                           TYPE_CANONICAL (TREE_TYPE (decl)));
>>> +       container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
>>>     }
>>> 
>>>   if (DECL_NAME (decl) != NULL_TREE)
>>> @@ -1027,7 +1025,7 @@ go_output_typedef (struct godump_container *container, tree decl)
>>>                     size);
>>>        }
>>> 
>>> -      pointer_set_insert (container->decls_seen, decl);
>>> +      container->decls_seen.add (decl);
>>>     }
>>>   else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
>>>     {
>>> @@ -1072,11 +1070,11 @@ go_output_var (struct godump_container *container, tree decl)
>>> {
>>>   bool is_valid;
>>> 
>>> -  if (pointer_set_contains (container->decls_seen, decl)
>>> -      || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
>>> +  if (container->decls_seen.contains (decl)
>>> +      || container->decls_seen.contains (DECL_NAME (decl)))
>>>     return;
>>> -  pointer_set_insert (container->decls_seen, decl);
>>> -  pointer_set_insert (container->decls_seen, DECL_NAME (decl));
>>> +  container->decls_seen.add (decl);
>>> +  container->decls_seen.add (DECL_NAME (decl));
>>> 
>>>   is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
>>>   if (is_valid
>>> @@ -1103,11 +1101,10 @@ go_output_var (struct godump_container *container, tree decl)
>>>     {
>>>       tree type_name = TYPE_NAME (TREE_TYPE (decl));
>>>       if (TREE_CODE (type_name) == IDENTIFIER_NODE)
>>> -       pointer_set_insert (container->pot_dummy_types,
>>> -                           IDENTIFIER_POINTER (type_name));
>>> +       container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
>>>       else if (TREE_CODE (type_name) == TYPE_DECL)
>>> -       pointer_set_insert (container->pot_dummy_types,
>>> -                           IDENTIFIER_POINTER (DECL_NAME (type_name)));
>>> +       container->pot_dummy_types.add
>>> +                           (IDENTIFIER_POINTER (DECL_NAME (type_name)));
>>>     }
>>> }
>>> 
>>> @@ -1147,10 +1144,10 @@ keyword_hash_init (struct godump_container *container)
>>> 
>>> /* Traversing the pot_dummy_types and seeing which types are present
>>>    in the global types hash table and creating dummy definitions if
>>> -   not found.  This function is invoked by pointer_set_traverse.  */
>>> +   not found.  This function is invoked by hash_set::traverse.  */
>>> 
>>> -static bool
>>> -find_dummy_types (const void *ptr, void *adata)
>>> +bool
>>> +find_dummy_types (const char *const &ptr, godump_container *adata)
>>> {
>>>   struct godump_container *data = (struct godump_container *) adata;
>>>   const char *type = (const char *) ptr;
>>> @@ -1175,8 +1172,6 @@ go_finish (const char *filename)
>>> 
>>>   real_debug_hooks->finish (filename);
>>> 
>>> -  container.decls_seen = pointer_set_create ();
>>> -  container.pot_dummy_types = pointer_set_create ();
>>>   container.type_hash = htab_create (100, htab_hash_string,
>>>                                      string_hash_eq, NULL);
>>>   container.invalid_hash = htab_create (10, htab_hash_string,
>>> @@ -1211,11 +1206,9 @@ go_finish (const char *filename)
>>>   htab_traverse_noresize (macro_hash, go_print_macro, NULL);
>>> 
>>>   /* To emit dummy definitions.  */
>>> -  pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
>>> -                        (void *) &container);
>>> +  container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
>>> +                        (&container);
>>> 
>>> -  pointer_set_destroy (container.decls_seen);
>>> -  pointer_set_destroy (container.pot_dummy_types);
>>>   htab_delete (container.type_hash);
>>>   htab_delete (container.invalid_hash);
>>>   htab_delete (container.keyword_hash);
>>> diff --git a/gcc/hash-set.h b/gcc/hash-set.h
>>> new file mode 100644
>>> index 0000000..47bae9e
>>> --- /dev/null
>>> +++ b/gcc/hash-set.h
>>> @@ -0,0 +1,173 @@
>>> +/* A type-safe hash set.
>>> +   Copyright (C) 2014 Free Software Foundation, Inc.
>>> +
>>> +This file is part of GCC.
>>> +
>>> +GCC is free software; you can redistribute it and/or modify it under
>>> +the terms of the GNU General Public License as published by the Free
>>> +Software Foundation; either version 3, or (at your option) any later
>>> +version.
>>> +
>>> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
>>> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
>>> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
>>> +for more details.
>>> +
>>> +You should have received a copy of the GNU General Public License
>>> +along with GCC; see the file COPYING3.  If not see
>>> +<http://www.gnu.org/licenses/>.  */
>>> +
>>> +
>>> +#ifndef hash_set_h
>>> +#define hash_set_h
>>> +
>>> +#include "hash-table.h"
>>> +
>>> +/* implement default behavior for traits when types allow it.  */
>>> +
>>> +struct default_hashset_traits
>>> +{
>>> +  /* Hashes the passed in key.  */
>>> +
>>> +  template<typename T>
>>> +  static hashval_t
>>> +  hash (T *p)
>>> +    {
>>> +      return uintptr_t(p) >> 3;
>>> +    }
>>> +
>>> +  template<typename T> static hashval_t hash(const T &v) { return v; }
>>> +
>>> +  /* Return true if the two keys passed as arguments are equal.  */
>>> +
>>> +  template<typename T>
>>> +  static bool
>>> +  equal (const T &a, const T &b)
>>> +    {
>>> +      return a == b;
>>> +    }
>>> +
>>> +  /* Called to dispose of the key before marking the entry as deleted.  */
>>> +
>>> +  template<typename T> static void remove (T &v) { v.~T (); }
>>> +
>>> +  /* Mark the passed in entry as being deleted.  */
>>> +
>>> +  template<typename T>
>>> +  static void
>>> +  mark_deleted (T *&e)
>>> +    {
>>> +      e = reinterpret_cast<void *> (1);
>>> +    }
>>> +
>>> +  /* Mark the passed in entry as being empty.  */
>>> +
>>> +  template<typename T>
>>> +  static void
>>> +  mark_empty (T *&e)
>>> +    {
>>> +      e = NULL;
>>> +    }
>>> +
>>> +  /* Return true if the passed in entry is marked as deleted.  */
>>> +
>>> +  template<typename T>
>>> +  static bool
>>> +  is_deleted (T *e)
>>> +    {
>>> +      return e == reinterpret_cast<void *> (1);
>>> +    }
>>> +
>>> +  /* Return true if the passed in entry is marked as empty.  */
>>> +
>>> +  template<typename T> static bool is_empty (T *e) { return e == NULL; }
>>> +};
>>> +
>>> +template<typename Key, typename Traits = default_hashset_traits>
>>> +class hash_set
>>> +{
>>> +  struct hash_entry
>>> +  {
>>> +    Key m_key;
>>> +
>>> +    typedef hash_entry value_type;
>>> +    typedef Key compare_type;
>>> +    typedef int store_values_directly;
>>> +
>>> +    static hashval_t hash (const hash_entry &e)
>>> +      {
>>> +               return Traits::hash (e.m_key);
>>> +      }
>>> +
>>> +    static bool equal (const hash_entry &a, const Key &b)
>>> +               {
>>> +         return Traits::equal (a.m_key, b);
>>> +               }
>>> +
>>> +    static void remove (hash_entry &e) { Traits::remove (e.m_key); }
>>> +
>>> +    static void
>>> +    mark_deleted (hash_entry &e)
>>> +      {
>>> +               Traits::mark_deleted (e.m_key);
>>> +      }
>>> +
>>> +    static bool is_deleted (const hash_entry &e)
>>> +      {
>>> +               return Traits::is_deleted (e.m_key);
>>> +      }
>>> +
>>> +    static void
>>> +    mark_empty (hash_entry &e)
>>> +      {
>>> +       Traits::mark_empty (e.m_key);
>>> +      }
>>> +
>>> +    static bool
>>> +    is_empty (const hash_entry &e)
>>> +      {
>>> +       return Traits::is_empty (e.m_key);
>>> +      }
>>> +  };
>>> +
>>> +public:
>>> +  explicit hash_set (size_t n = 13) : m_table (n) {}
>>> +
>>> +  /* If key k isn't already in the map add it to the map, and
>>> +     return false.  Otherwise return true.  */
>>> +
>>> +  bool add (const Key &k)
>>> +    {
>>> +      hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
>>> +                                                  INSERT);
>>> +      bool existed = !hash_entry::is_empty (*e);
>>> +      if (!existed)
>>> +       e->m_key = k;
>>> +
>>> +      return existed;
>>> +    }
>>> +
>>> +  /* if the passed in key is in the map return its value otherwise NULL.  */
>>> +
>>> +  bool contains (const Key &k)
>>> +    {
>>> +      hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
>>> +      return !Traits::is_empty (e.m_key);
>>> +    }
>>> +
>>> +  /* Call the call back on each pair of key and value with the passed in
>>> +     arg.  */
>>> +
>>> +  template<typename Arg, bool (*f)(const Key &, Arg)>
>>> +  void traverse (Arg a) const
>>> +    {
>>> +      for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
>>> +          iter != m_table.end (); ++iter)
>>> +       f ((*iter).m_key, a);
>>> +    }
>>> +
>>> +private:
>>> +  hash_table<hash_entry> m_table;
>>> +};
>>> +
>>> +#endif
>>> diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
>>> index 127d58d..70a70a7 100644
>>> --- a/gcc/ipa-devirt.c
>>> +++ b/gcc/ipa-devirt.c
>>> @@ -115,7 +115,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "cgraph.h"
>>> #include "expr.h"
>>> #include "tree-pass.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> #include "target.h"
>>> #include "hash-table.h"
>>> #include "inchash.h"
>>> @@ -134,7 +134,8 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "stor-layout.h"
>>> #include "intl.h"
>>> 
>>> -static bool odr_types_equivalent_p (tree, tree, bool, bool *, pointer_set_t *);
>>> +static bool odr_types_equivalent_p (tree, tree, bool, bool *,
>>> +                                   hash_set<tree> *);
>>> 
>>> static bool odr_violation_reported = false;
>>> 
>>> @@ -144,7 +145,7 @@ const ipa_polymorphic_call_context ipa_dummy_polymorphic_call_context
>>>    = {0, NULL, false, true};
>>> 
>>> /* Pointer set of all call targets appearing in the cache.  */
>>> -static pointer_set_t *cached_polymorphic_call_targets;
>>> +static hash_set<cgraph_node *> *cached_polymorphic_call_targets;
>>> 
>>> /* The node of type inheritance graph.  For each type unique in
>>>    One Defintion Rule (ODR) sense, we produce one node linking all
>>> @@ -163,7 +164,7 @@ struct GTY(()) odr_type_d
>>>   /* All equivalent types, if more than one.  */
>>>   vec<tree, va_gc> *types;
>>>   /* Set of all equivalent types, if NON-NULL.  */
>>> -  pointer_set_t * GTY((skip)) types_set;
>>> +  hash_set<tree> * GTY((skip)) types_set;
>>> 
>>>   /* Unique ID indexing the type in odr_types array.  */
>>>   int id;
>>> @@ -409,7 +410,7 @@ odr_hasher::remove (value_type *v)
>>>   v->bases.release ();
>>>   v->derived_types.release ();
>>>   if (v->types_set)
>>> -    pointer_set_destroy (v->types_set);
>>> +    delete v->types_set;
>>>   ggc_free (v);
>>> }
>>> 
>>> @@ -439,7 +440,7 @@ set_type_binfo (tree type, tree binfo)
>>> /* Compare T2 and T2 based on name or structure.  */
>>> 
>>> static bool
>>> -odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
>>> +odr_subtypes_equivalent_p (tree t1, tree t2, hash_set<tree> *visited)
>>> {
>>>   bool an1, an2;
>>> 
>>> @@ -473,7 +474,7 @@ odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
>>>       /* This should really be a pair hash, but for the moment we do not need
>>>         100% reliability and it would be better to compare all ODR types so
>>>         recursion here is needed only for component types.  */
>>> -      if (pointer_set_insert (visited, t1))
>>> +      if (visited->add (t1))
>>>        return true;
>>>       return odr_types_equivalent_p (t1, t2, false, NULL, visited);
>>>     }
>>> @@ -562,7 +563,7 @@ warn_types_mismatch (tree t1, tree t2)
>>>    gimple_canonical_types_compatible_p.  */
>>> 
>>> static bool
>>> -odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, pointer_set_t *visited)
>>> +odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, hash_set<tree> *visited)
>>> {
>>>   /* Check first for the obvious case of pointer identity.  */
>>>   if (t1 == t2)
>>> @@ -938,7 +939,7 @@ add_type_duplicate (odr_type val, tree type)
>>> {
>>>   bool build_bases = false;
>>>   if (!val->types_set)
>>> -    val->types_set = pointer_set_create ();
>>> +    val->types_set = new hash_set<tree>;
>>> 
>>>   /* Always prefer complete type to be the leader.  */
>>>   if (!COMPLETE_TYPE_P (val->type)
>>> @@ -952,20 +953,20 @@ add_type_duplicate (odr_type val, tree type)
>>>     }
>>> 
>>>   /* See if this duplicate is new.  */
>>> -  if (!pointer_set_insert (val->types_set, type))
>>> +  if (!val->types_set->add (type))
>>>     {
>>>       bool merge = true;
>>>       bool base_mismatch = false;
>>>       unsigned int i,j;
>>>       bool warned = false;
>>> -      pointer_set_t *visited = pointer_set_create ();
>>> +      hash_set<tree> visited;
>>> 
>>>       gcc_assert (in_lto_p);
>>>       vec_safe_push (val->types, type);
>>> 
>>>       /* First we compare memory layout.  */
>>>       if (!odr_types_equivalent_p (val->type, type, !flag_ltrans && !val->odr_violated,
>>> -                                  &warned, visited))
>>> +                                  &warned, &visited))
>>>        {
>>>          merge = false;
>>>          odr_violation_reported = true;
>>> @@ -980,7 +981,6 @@ add_type_duplicate (odr_type val, tree type)
>>>              putc ('\n',cgraph_dump_file);
>>>            }
>>>        }
>>> -      pointer_set_destroy (visited);
>>> 
>>>       /* Next sanity check that bases are the same.  If not, we will end
>>>         up producing wrong answers.  */
>>> @@ -1356,7 +1356,7 @@ referenced_from_vtable_p (struct cgraph_node *node)
>>> 
>>> static void
>>> maybe_record_node (vec <cgraph_node *> &nodes,
>>> -                  tree target, pointer_set_t *inserted,
>>> +                  tree target, hash_set<tree> *inserted,
>>>                   bool can_refer,
>>>                   bool *completep)
>>> {
>>> @@ -1422,10 +1422,9 @@ maybe_record_node (vec <cgraph_node *> &nodes,
>>>     {
>>>       gcc_assert (!target_node->global.inlined_to);
>>>       gcc_assert (target_node->real_symbol_p ());
>>> -      if (!pointer_set_insert (inserted, target_node->decl))
>>> +      if (!inserted->add (target))
>>>        {
>>> -         pointer_set_insert (cached_polymorphic_call_targets,
>>> -                             target_node);
>>> +         cached_polymorphic_call_targets->add (target_node);
>>>          nodes.safe_push (target_node);
>>>        }
>>>     }
>>> @@ -1465,8 +1464,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
>>>                          HOST_WIDE_INT otr_token,
>>>                          tree outer_type,
>>>                          HOST_WIDE_INT offset,
>>> -                         pointer_set_t *inserted,
>>> -                         pointer_set_t *matched_vtables,
>>> +                         hash_set<tree> *inserted,
>>> +                         hash_set<tree> *matched_vtables,
>>>                          bool anonymous,
>>>                          bool *completep)
>>> {
>>> @@ -1519,8 +1518,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
>>>        }
>>>       gcc_assert (inner_binfo);
>>>       if (bases_to_consider
>>> -         ? !pointer_set_contains (matched_vtables, BINFO_VTABLE (inner_binfo))
>>> -         : !pointer_set_insert (matched_vtables, BINFO_VTABLE (inner_binfo)))
>>> +         ? !matched_vtables->contains (BINFO_VTABLE (inner_binfo))
>>> +         : !matched_vtables->add (BINFO_VTABLE (inner_binfo)))
>>>        {
>>>          bool can_refer;
>>>          tree target = gimple_get_virt_method_for_binfo (otr_token,
>>> @@ -1559,8 +1558,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
>>> 
>>> static void
>>> possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes,
>>> -                                    pointer_set_t *inserted,
>>> -                                    pointer_set_t *matched_vtables,
>>> +                                    hash_set<tree> *inserted,
>>> +                                    hash_set<tree> *matched_vtables,
>>>                                     tree otr_type,
>>>                                     odr_type type,
>>>                                     HOST_WIDE_INT otr_token,
>>> @@ -1684,7 +1683,7 @@ free_polymorphic_call_targets_hash ()
>>>     {
>>>       delete polymorphic_call_target_hash;
>>>       polymorphic_call_target_hash = NULL;
>>> -      pointer_set_destroy (cached_polymorphic_call_targets);
>>> +      delete cached_polymorphic_call_targets;
>>>       cached_polymorphic_call_targets = NULL;
>>>     }
>>> }
>>> @@ -1695,7 +1694,7 @@ static void
>>> devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
>>> {
>>>   if (cached_polymorphic_call_targets
>>> -      && pointer_set_contains (cached_polymorphic_call_targets, n))
>>> +      && cached_polymorphic_call_targets->contains (n))
>>>     free_polymorphic_call_targets_hash ();
>>> }
>>> 
>>> @@ -2277,8 +2276,8 @@ record_targets_from_bases (tree otr_type,
>>>                           tree outer_type,
>>>                           HOST_WIDE_INT offset,
>>>                           vec <cgraph_node *> &nodes,
>>> -                          pointer_set_t *inserted,
>>> -                          pointer_set_t *matched_vtables,
>>> +                          hash_set<tree> *inserted,
>>> +                          hash_set<tree> *matched_vtables,
>>>                           bool *completep)
>>> {
>>>   while (true)
>>> @@ -2319,7 +2318,7 @@ record_targets_from_bases (tree otr_type,
>>>          return;
>>>        }
>>>       gcc_assert (base_binfo);
>>> -      if (!pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo)))
>>> +      if (!matched_vtables->add (BINFO_VTABLE (base_binfo)))
>>>        {
>>>          bool can_refer;
>>>          tree target = gimple_get_virt_method_for_binfo (otr_token,
>>> @@ -2327,7 +2326,7 @@ record_targets_from_bases (tree otr_type,
>>>                                                          &can_refer);
>>>          if (!target || ! DECL_CXX_DESTRUCTOR_P (target))
>>>            maybe_record_node (nodes, target, inserted, can_refer, completep);
>>> -         pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo));
>>> +         matched_vtables->add (BINFO_VTABLE (base_binfo));
>>>        }
>>>     }
>>> }
>>> @@ -2377,8 +2376,6 @@ possible_polymorphic_call_targets (tree otr_type,
>>>                                   int *nonconstruction_targetsp)
>>> {
>>>   static struct cgraph_node_hook_list *node_removal_hook_holder;
>>> -  pointer_set_t *inserted;
>>> -  pointer_set_t *matched_vtables;
>>>   vec <cgraph_node *> nodes = vNULL;
>>>   vec <tree> bases_to_consider = vNULL;
>>>   odr_type type, outer_type;
>>> @@ -2457,7 +2454,7 @@ possible_polymorphic_call_targets (tree otr_type,
>>>   /* Initialize query cache.  */
>>>   if (!cached_polymorphic_call_targets)
>>>     {
>>> -      cached_polymorphic_call_targets = pointer_set_create ();
>>> +      cached_polymorphic_call_targets = new hash_set<cgraph_node *>;
>>>       polymorphic_call_target_hash
>>>                = new polymorphic_call_target_hash_type (23);
>>>       if (!node_removal_hook_holder)
>>> @@ -2496,8 +2493,8 @@ possible_polymorphic_call_targets (tree otr_type,
>>>   (*slot)->otr_token = otr_token;
>>>   (*slot)->context = context;
>>> 
>>> -  inserted = pointer_set_create ();
>>> -  matched_vtables = pointer_set_create ();
>>> +  hash_set<tree> inserted;
>>> +  hash_set<tree> matched_vtables;
>>> 
>>>   /* First see virtual method of type itself.  */
>>>   binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type),
>>> @@ -2526,7 +2523,7 @@ possible_polymorphic_call_targets (tree otr_type,
>>> 
>>>   /* If OUTER_TYPE is abstract, we know we are not seeing its instance.  */
>>>   if (type_possibly_instantiated_p (outer_type->type))
>>> -    maybe_record_node (nodes, target, inserted, can_refer, &complete);
>>> +    maybe_record_node (nodes, target, &inserted, can_refer, &complete);
>>>   else
>>>     {
>>>       skipped = true;
>>> @@ -2534,7 +2531,7 @@ possible_polymorphic_call_targets (tree otr_type,
>>>     }
>>> 
>>>   if (binfo)
>>> -    pointer_set_insert (matched_vtables, BINFO_VTABLE (binfo));
>>> +    matched_vtables.add (BINFO_VTABLE (binfo));
>>> 
>>>   /* Next walk recursively all derived types.  */
>>>   if (context.maybe_derived_type)
>>> @@ -2544,8 +2541,8 @@ possible_polymorphic_call_targets (tree otr_type,
>>>       if (!type->all_derivations_known)
>>>        complete = false;
>>>       for (i = 0; i < outer_type->derived_types.length(); i++)
>>> -       possible_polymorphic_call_targets_1 (nodes, inserted,
>>> -                                            matched_vtables,
>>> +       possible_polymorphic_call_targets_1 (nodes, &inserted,
>>> +                                            &matched_vtables,
>>>                                             otr_type,
>>>                                             outer_type->derived_types[i],
>>>                                             otr_token, outer_type->type,
>>> @@ -2571,12 +2568,12 @@ possible_polymorphic_call_targets (tree otr_type,
>>>              || (context.maybe_derived_type
>>>                  && !type_all_derivations_known_p (outer_type->type))))
>>>        record_targets_from_bases (otr_type, otr_token, outer_type->type,
>>> -                                  context.offset, nodes, inserted,
>>> -                                  matched_vtables, &complete);
>>> +                                  context.offset, nodes, &inserted,
>>> +                                  &matched_vtables, &complete);
>>>       if (skipped)
>>> -        maybe_record_node (nodes, target, inserted, can_refer, &complete);
>>> +        maybe_record_node (nodes, target, &inserted, can_refer, &complete);
>>>       for (i = 0; i < bases_to_consider.length(); i++)
>>> -        maybe_record_node (nodes, bases_to_consider[i], inserted, can_refer, &complete);
>>> +        maybe_record_node (nodes, bases_to_consider[i], &inserted, can_refer, &complete);
>>>     }
>>>   bases_to_consider.release();
>>> 
>>> @@ -2587,8 +2584,6 @@ possible_polymorphic_call_targets (tree otr_type,
>>>   if (nonconstruction_targetsp)
>>>     *nonconstruction_targetsp = (*slot)->nonconstruction_targets;
>>> 
>>> -  pointer_set_destroy (inserted);
>>> -  pointer_set_destroy (matched_vtables);
>>>   timevar_pop (TV_IPA_VIRTUAL_CALL);
>>>   return nodes;
>>> }
>>> @@ -2744,7 +2739,7 @@ static unsigned int
>>> ipa_devirt (void)
>>> {
>>>   struct cgraph_node *n;
>>> -  struct pointer_set_t *bad_call_targets = pointer_set_create ();
>>> +  hash_set<void *> bad_call_targets;
>>>   struct cgraph_edge *e;
>>> 
>>>   int npolymorphic = 0, nspeculated = 0, nconverted = 0, ncold = 0;
>>> @@ -2792,8 +2787,7 @@ ipa_devirt (void)
>>>                if (!dump_file)
>>>                  continue;
>>>              }
>>> -           if (pointer_set_contains (bad_call_targets,
>>> -                                     cache_token))
>>> +           if (bad_call_targets.contains (cache_token))
>>>              {
>>>                if (dump_file)
>>>                  fprintf (dump_file, "Target list is known to be useless\n\n");
>>> @@ -2818,7 +2812,7 @@ ipa_devirt (void)
>>>                }
>>>            if (!likely_target)
>>>              {
>>> -               pointer_set_insert (bad_call_targets, cache_token);
>>> +               bad_call_targets.add (cache_token);
>>>                continue;
>>>              }
>>>            /* This is reached only when dumping; check if we agree or disagree
>>> @@ -2905,7 +2899,6 @@ ipa_devirt (void)
>>>       if (update)
>>>        inline_update_overall_summary (n);
>>>     }
>>> -  pointer_set_destroy (bad_call_targets);
>>> 
>>>   if (dump_file)
>>>     fprintf (dump_file,
>>> diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
>>> index 2c281be..b964502 100644
>>> --- a/gcc/ipa-pure-const.c
>>> +++ b/gcc/ipa-pure-const.c
>>> @@ -65,8 +65,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "tree-scalar-evolution.h"
>>> #include "intl.h"
>>> #include "opts.h"
>>> -
>>> -static struct pointer_set_t *visited_nodes;
>>> +#include "hash-set.h"
>>> 
>>> /* Lattice values for const and pure functions.  Everything starts out
>>>    being const, then may drop to pure and then neither depending on
>>> @@ -133,13 +132,13 @@ function_always_visible_to_compiler_p (tree decl)
>>> 
>>> /* Emit suggestion about attribute ATTRIB_NAME for DECL.  KNOWN_FINITE
>>>    is true if the function is known to be finite.  The diagnostic is
>>> -   controlled by OPTION.  WARNED_ABOUT is a pointer_set unique for
>>> +   controlled by OPTION.  WARNED_ABOUT is a hash_set<tree> unique for
>>>    OPTION, this function may initialize it and it is always returned
>>>    by the function.  */
>>> 
>>> -static struct pointer_set_t *
>>> +static hash_set<tree> *
>>> suggest_attribute (int option, tree decl, bool known_finite,
>>> -                  struct pointer_set_t *warned_about,
>>> +                  hash_set<tree> *warned_about,
>>>                   const char * attrib_name)
>>> {
>>>   if (!option_enabled (option, &global_options))
>>> @@ -149,10 +148,10 @@ suggest_attribute (int option, tree decl, bool known_finite,
>>>     return warned_about;
>>> 
>>>   if (!warned_about)
>>> -    warned_about = pointer_set_create ();
>>> -  if (pointer_set_contains (warned_about, decl))
>>> +    warned_about = new hash_set<tree>;
>>> +  if (warned_about->contains (decl))
>>>     return warned_about;
>>> -  pointer_set_insert (warned_about, decl);
>>> +  warned_about->add (decl);
>>>   warning_at (DECL_SOURCE_LOCATION (decl),
>>>              option,
>>>              known_finite
>>> @@ -168,7 +167,7 @@ suggest_attribute (int option, tree decl, bool known_finite,
>>> static void
>>> warn_function_pure (tree decl, bool known_finite)
>>> {
>>> -  static struct pointer_set_t *warned_about;
>>> +  static hash_set<tree> *warned_about;
>>> 
>>>   warned_about
>>>     = suggest_attribute (OPT_Wsuggest_attribute_pure, decl,
>>> @@ -181,7 +180,7 @@ warn_function_pure (tree decl, bool known_finite)
>>> static void
>>> warn_function_const (tree decl, bool known_finite)
>>> {
>>> -  static struct pointer_set_t *warned_about;
>>> +  static hash_set<tree> *warned_about;
>>>   warned_about
>>>     = suggest_attribute (OPT_Wsuggest_attribute_const, decl,
>>>                         known_finite, warned_about, "const");
>>> @@ -190,7 +189,7 @@ warn_function_const (tree decl, bool known_finite)
>>> static void
>>> warn_function_noreturn (tree decl)
>>> {
>>> -  static struct pointer_set_t *warned_about;
>>> +  static hash_set<tree> *warned_about;
>>>   if (!lang_hooks.missing_noreturn_ok_p (decl)
>>>       && targetm.warn_func_return (decl))
>>>     warned_about
>>> @@ -846,11 +845,8 @@ add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
>>>      static declarations.  We do not need to scan them more than once
>>>      since all we would be interested in are the addressof
>>>      operations.  */
>>> -  visited_nodes = pointer_set_create ();
>>>   if (node->get_availability () > AVAIL_INTERPOSABLE)
>>>     set_function_state (node, analyze_function (node, true));
>>> -  pointer_set_destroy (visited_nodes);
>>> -  visited_nodes = NULL;
>>> }
>>> 
>>> /* Called when new clone is inserted to callgraph late.  */
>>> @@ -912,12 +908,6 @@ pure_const_generate_summary (void)
>>> 
>>>   register_hooks ();
>>> 
>>> -  /* There are some shared nodes, in particular the initializers on
>>> -     static declarations.  We do not need to scan them more than once
>>> -     since all we would be interested in are the addressof
>>> -     operations.  */
>>> -  visited_nodes = pointer_set_create ();
>>> -
>>>   /* Process all of the functions.
>>> 
>>>      We process AVAIL_INTERPOSABLE functions.  We can not use the results
>>> @@ -927,9 +917,6 @@ pure_const_generate_summary (void)
>>>   FOR_EACH_DEFINED_FUNCTION (node)
>>>     if (node->get_availability () >= AVAIL_INTERPOSABLE)
>>>       set_function_state (node, analyze_function (node, true));
>>> -
>>> -  pointer_set_destroy (visited_nodes);
>>> -  visited_nodes = NULL;
>>> }
>>> 
>>> 
>>> diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
>>> index 4720ee9..bca2bc7 100644
>>> --- a/gcc/ipa-visibility.c
>>> +++ b/gcc/ipa-visibility.c
>>> @@ -687,12 +687,11 @@ function_and_variable_visibility (bool whole_program)
>>>              }
>>>          if (found)
>>>            {
>>> -             struct pointer_set_t *visited_nodes = pointer_set_create ();
>>> +             hash_set<tree> visited_nodes;
>>> 
>>>              vnode->get_constructor ();
>>>              walk_tree (&DECL_INITIAL (vnode->decl),
>>> -                        update_vtable_references, NULL, visited_nodes);
>>> -             pointer_set_destroy (visited_nodes);
>>> +                        update_vtable_references, NULL, &visited_nodes);
>>>              vnode->remove_all_references ();
>>>              record_references_in_initializer (vnode->decl, false);
>>>            }
>>> diff --git a/gcc/ipa.c b/gcc/ipa.c
>>> index 8198b17..1081e89 100644
>>> --- a/gcc/ipa.c
>>> +++ b/gcc/ipa.c
>>> @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "cgraph.h"
>>> #include "tree-pass.h"
>>> #include "hash-map.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> #include "gimple-expr.h"
>>> #include "gimplify.h"
>>> #include "flags.h"
>>> @@ -84,14 +84,14 @@ update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined
>>> 
>>> static void
>>> enqueue_node (symtab_node *node, symtab_node **first,
>>> -             struct pointer_set_t *reachable)
>>> +             hash_set<symtab_node *> *reachable)
>>> {
>>>   /* Node is still in queue; do nothing.  */
>>>   if (node->aux && node->aux != (void *) 2)
>>>     return;
>>>   /* Node was already processed as unreachable, re-enqueue
>>>      only if it became reachable now.  */
>>> -  if (node->aux == (void *)2 && !pointer_set_contains (reachable, node))
>>> +  if (node->aux == (void *)2 && !reachable->contains (node))
>>>     return;
>>>   node->aux = *first;
>>>   *first = node;
>>> @@ -103,7 +103,7 @@ static void
>>> process_references (symtab_node *snode,
>>>                    symtab_node **first,
>>>                    bool before_inlining_p,
>>> -                   struct pointer_set_t *reachable)
>>> +                   hash_set<symtab_node *> *reachable)
>>> {
>>>   int i;
>>>   struct ipa_ref *ref = NULL;
>>> @@ -124,7 +124,7 @@ process_references (symtab_node *snode,
>>>                      && flag_wpa
>>>                      && ctor_for_folding (node->decl)
>>>                         != error_mark_node))))
>>> -       pointer_set_insert (reachable, node);
>>> +       reachable->add (node);
>>>       enqueue_node (node, first, reachable);
>>>     }
>>> }
>>> @@ -138,10 +138,11 @@ process_references (symtab_node *snode,
>>>    possible.  */
>>> 
>>> static void
>>> -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
>>> +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
>>>                               struct cgraph_edge *edge,
>>>                               symtab_node **first,
>>> -                              pointer_set_t *reachable, bool before_inlining_p)
>>> +                              hash_set<symtab_node *> *reachable,
>>> +                              bool before_inlining_p)
>>> {
>>>   unsigned int i;
>>>   void *cache_token;
>>> @@ -150,8 +151,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
>>>     = possible_polymorphic_call_targets
>>>        (edge, &final, &cache_token);
>>> 
>>> -  if (!pointer_set_insert (reachable_call_targets,
>>> -                          cache_token))
>>> +  if (!reachable_call_targets->add (cache_token))
>>>     {
>>>       for (i = 0; i < targets.length (); i++)
>>>        {
>>> @@ -172,7 +172,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
>>>                   && (cgraph_state < CGRAPH_STATE_IPA_SSA
>>>                       || !lookup_attribute ("always_inline",
>>>                                             DECL_ATTRIBUTES (n->decl)))))
>>> -            pointer_set_insert (reachable, n);
>>> +            reachable->add (n);
>>> 
>>>          /* Even after inlining we want to keep the possible targets in the
>>>             boundary, so late passes can still produce direct call even if
>>> @@ -276,9 +276,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>   struct cgraph_node *node, *next;
>>>   varpool_node *vnode, *vnext;
>>>   bool changed = false;
>>> -  struct pointer_set_t *reachable = pointer_set_create ();
>>> -  struct pointer_set_t *body_needed_for_clonning = pointer_set_create ();
>>> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
>>> +  hash_set<symtab_node *> reachable;
>>> +  hash_set<tree> body_needed_for_clonning;
>>> +  hash_set<void *> reachable_call_targets;
>>> 
>>>   timevar_push (TV_IPA_UNREACHABLE);
>>>   if (optimize && flag_devirtualize)
>>> @@ -304,8 +304,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>          && !node->can_remove_if_no_direct_calls_and_refs_p ())
>>>        {
>>>          gcc_assert (!node->global.inlined_to);
>>> -         pointer_set_insert (reachable, node);
>>> -         enqueue_node (node, &first, reachable);
>>> +         reachable.add (node);
>>> +         enqueue_node (node, &first, &reachable);
>>>        }
>>>       else
>>>        gcc_assert (!node->aux);
>>> @@ -316,14 +316,14 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>     if (!vnode->can_remove_if_no_refs_p()
>>>        && !vnode->in_other_partition)
>>>       {
>>> -       pointer_set_insert (reachable, vnode);
>>> -       enqueue_node (vnode, &first, reachable);
>>> +       reachable.add (vnode);
>>> +       enqueue_node (vnode, &first, &reachable);
>>>       }
>>> 
>>>   /* Perform reachability analysis.  */
>>>   while (first != (symtab_node *) (void *) 1)
>>>     {
>>> -      bool in_boundary_p = !pointer_set_contains (reachable, first);
>>> +      bool in_boundary_p = !reachable.contains (first);
>>>       symtab_node *node = first;
>>> 
>>>       first = (symtab_node *)first->aux;
>>> @@ -340,7 +340,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>              struct cgraph_node *origin_node
>>>              = cgraph_node::get_create (DECL_ABSTRACT_ORIGIN (node->decl));
>>>              origin_node->used_as_abstract_origin = true;
>>> -             enqueue_node (origin_node, &first, reachable);
>>> +             enqueue_node (origin_node, &first, &reachable);
>>>            }
>>>          /* If any symbol in a comdat group is reachable, force
>>>             all externally visible symbols in the same comdat
>>> @@ -353,11 +353,11 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>                   next != node;
>>>                   next = next->same_comdat_group)
>>>                if (!next->comdat_local_p ()
>>> -                   && !pointer_set_insert (reachable, next))
>>> -                 enqueue_node (next, &first, reachable);
>>> +                   && !reachable.add (next))
>>> +                 enqueue_node (next, &first, &reachable);
>>>            }
>>>          /* Mark references as reachable.  */
>>> -         process_references (node, &first, before_inlining_p, reachable);
>>> +         process_references (node, &first, before_inlining_p, &reachable);
>>>        }
>>> 
>>>       if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
>>> @@ -375,8 +375,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>                    {
>>>                      next = e->next_callee;
>>>                      if (e->indirect_info->polymorphic)
>>> -                       walk_polymorphic_call_targets (reachable_call_targets,
>>> -                                                      e, &first, reachable,
>>> +                       walk_polymorphic_call_targets (&reachable_call_targets,
>>> +                                                      e, &first, &reachable,
>>>                                                       before_inlining_p);
>>>                    }
>>>                }
>>> @@ -394,17 +394,16 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>                      if (DECL_EXTERNAL (e->callee->decl)
>>>                          && e->callee->alias
>>>                          && before_inlining_p)
>>> -                       pointer_set_insert (reachable,
>>> -                                           e->callee->function_symbol ());
>>> -                     pointer_set_insert (reachable, e->callee);
>>> +                       reachable.add (e->callee->function_symbol ());
>>> +                     reachable.add (e->callee);
>>>                    }
>>> -                 enqueue_node (e->callee, &first, reachable);
>>> +                 enqueue_node (e->callee, &first, &reachable);
>>>                }
>>> 
>>>              /* When inline clone exists, mark body to be preserved so when removing
>>>                 offline copy of the function we don't kill it.  */
>>>              if (cnode->global.inlined_to)
>>> -               pointer_set_insert (body_needed_for_clonning, cnode->decl);
>>> +               body_needed_for_clonning.add (cnode->decl);
>>> 
>>>              /* For non-inline clones, force their origins to the boundary and ensure
>>>                 that body is not removed.  */
>>> @@ -414,8 +413,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>                  cnode = cnode->clone_of;
>>>                  if (noninline)
>>>                    {
>>> -                     pointer_set_insert (body_needed_for_clonning, cnode->decl);
>>> -                     enqueue_node (cnode, &first, reachable);
>>> +                     body_needed_for_clonning.add (cnode->decl);
>>> +                     enqueue_node (cnode, &first, &reachable);
>>>                    }
>>>                }
>>> 
>>> @@ -429,8 +428,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>                   next;
>>>                   next = next->simdclone->next_clone)
>>>                if (in_boundary_p
>>> -                   || !pointer_set_insert (reachable, next))
>>> -                 enqueue_node (next, &first, reachable);
>>> +                   || !reachable.add (next))
>>> +                 enqueue_node (next, &first, &reachable);
>>>            }
>>>        }
>>>       /* When we see constructor of external variable, keep referred nodes in the
>>> @@ -444,7 +443,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>        {
>>>          struct ipa_ref *ref = NULL;
>>>          for (int i = 0; node->iterate_reference (i, ref); i++)
>>> -           enqueue_node (ref->referred, &first, reachable);
>>> +           enqueue_node (ref->referred, &first, &reachable);
>>>        }
>>>     }
>>> 
>>> @@ -462,9 +461,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>          changed = true;
>>>        }
>>>       /* If node is unreachable, remove its body.  */
>>> -      else if (!pointer_set_contains (reachable, node))
>>> +      else if (!reachable.contains (node))
>>>         {
>>> -         if (!pointer_set_contains (body_needed_for_clonning, node->decl))
>>> +         if (!body_needed_for_clonning.contains (node->decl))
>>>            node->release_body ();
>>>          else if (!node->clone_of)
>>>            gcc_assert (in_lto_p || DECL_RESULT (node->decl));
>>> @@ -530,7 +529,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>          vnode->remove ();
>>>          changed = true;
>>>        }
>>> -      else if (!pointer_set_contains (reachable, vnode))
>>> +      else if (!reachable.contains (vnode))
>>>         {
>>>          tree init;
>>>          if (vnode->definition)
>>> @@ -557,10 +556,6 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
>>>        vnode->aux = NULL;
>>>     }
>>> 
>>> -  pointer_set_destroy (reachable);
>>> -  pointer_set_destroy (body_needed_for_clonning);
>>> -  pointer_set_destroy (reachable_call_targets);
>>> -
>>>   /* Now update address_taken flags and try to promote functions to be local.  */
>>>   if (file)
>>>     fprintf (file, "\nClearing address taken flags:");
>>> diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
>>> index b1fcf67..42b0790 100644
>>> --- a/gcc/lto-cgraph.c
>>> +++ b/gcc/lto-cgraph.c
>>> @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "params.h"
>>> #include "input.h"
>>> #include "hashtab.h"
>>> +#include "hash-set.h"
>>> #include "langhooks.h"
>>> #include "bitmap.h"
>>> #include "function.h"
>>> @@ -819,7 +820,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
>>>   int i;
>>>   lto_symtab_encoder_t encoder;
>>>   lto_symtab_encoder_iterator lsei;
>>> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
>>> +  hash_set<void *> reachable_call_targets;
>>> 
>>>   encoder = lto_symtab_encoder_new (false);
>>> 
>>> @@ -902,8 +903,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
>>>              vec <cgraph_node *>targets
>>>                = possible_polymorphic_call_targets
>>>                    (edge, &final, &cache_token);
>>> -             if (!pointer_set_insert (reachable_call_targets,
>>> -                                      cache_token))
>>> +             if (!reachable_call_targets.add (cache_token))
>>>                {
>>>                  for (i = 0; i < targets.length (); i++)
>>>                    {
>>> @@ -923,7 +923,6 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
>>>            }
>>>     }
>>>   lto_symtab_encoder_delete (in_encoder);
>>> -  pointer_set_destroy (reachable_call_targets);
>>>   return encoder;
>>> }
>>> 
>>> diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
>>> index 271fbd5..3fd9147 100644
>>> --- a/gcc/lto-streamer-out.c
>>> +++ b/gcc/lto-streamer-out.c
>>> @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "params.h"
>>> #include "input.h"
>>> #include "hashtab.h"
>>> +#include "hash-set.h"
>>> #include "basic-block.h"
>>> #include "tree-ssa-alias.h"
>>> #include "internal-fn.h"
>>> @@ -2433,7 +2434,7 @@ lto_out_decl_state_written_size (struct lto_out_decl_state *state)
>>> static void
>>> write_symbol (struct streamer_tree_cache_d *cache,
>>>              struct lto_output_stream *stream,
>>> -             tree t, struct pointer_set_t *seen, bool alias)
>>> +             tree t, hash_set<const char *> *seen, bool alias)
>>> {
>>>   const char *name;
>>>   enum gcc_plugin_symbol_kind kind;
>>> @@ -2461,9 +2462,8 @@ write_symbol (struct streamer_tree_cache_d *cache,
>>>      same name manipulations that ASM_OUTPUT_LABELREF does. */
>>>   name = IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name) (name));
>>> 
>>> -  if (pointer_set_contains (seen, name))
>>> +  if (seen->add (name))
>>>     return;
>>> -  pointer_set_insert (seen, name);
>>> 
>>>   streamer_tree_cache_lookup (cache, t, &slot_num);
>>>   gcc_assert (slot_num != (unsigned)-1);
>>> @@ -2588,7 +2588,6 @@ produce_symtab (struct output_block *ob)
>>> {
>>>   struct streamer_tree_cache_d *cache = ob->writer_cache;
>>>   char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
>>> -  struct pointer_set_t *seen;
>>>   struct lto_output_stream stream;
>>>   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
>>>   lto_symtab_encoder_iterator lsei;
>>> @@ -2596,7 +2595,7 @@ produce_symtab (struct output_block *ob)
>>>   lto_begin_section (section_name, false);
>>>   free (section_name);
>>> 
>>> -  seen = pointer_set_create ();
>>> +  hash_set<const char *> seen;
>>>   memset (&stream, 0, sizeof (stream));
>>> 
>>>   /* Write the symbol table.
>>> @@ -2609,7 +2608,7 @@ produce_symtab (struct output_block *ob)
>>> 
>>>       if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
>>>        continue;
>>> -      write_symbol (cache, &stream, node->decl, seen, false);
>>> +      write_symbol (cache, &stream, node->decl, &seen, false);
>>>     }
>>>   for (lsei = lsei_start (encoder);
>>>        !lsei_end_p (lsei); lsei_next (&lsei))
>>> @@ -2618,11 +2617,10 @@ produce_symtab (struct output_block *ob)
>>> 
>>>       if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
>>>        continue;
>>> -      write_symbol (cache, &stream, node->decl, seen, false);
>>> +      write_symbol (cache, &stream, node->decl, &seen, false);
>>>     }
>>> 
>>>   lto_write_stream (&stream);
>>> -  pointer_set_destroy (seen);
>>> 
>>>   lto_end_section ();
>>> }
>>> diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
>>> index cb08a88..a5bcf92 100644
>>> --- a/gcc/lto/lto-partition.c
>>> +++ b/gcc/lto/lto-partition.c
>>> @@ -66,7 +66,7 @@ free_ltrans_partitions (void)
>>>   for (idx = 0; ltrans_partitions.iterate (idx, &part); idx++)
>>>     {
>>>       if (part->initializers_visited)
>>> -       pointer_set_destroy (part->initializers_visited);
>>> +       delete part->initializers_visited;
>>>       /* Symtab encoder is freed after streaming.  */
>>>       free (part);
>>>     }
>>> @@ -101,8 +101,8 @@ add_references_to_partition (ltrans_partition part, symtab_node *node)
>>>             && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
>>>       {
>>>        if (!part->initializers_visited)
>>> -         part->initializers_visited = pointer_set_create ();
>>> -       if (!pointer_set_insert (part->initializers_visited, ref->referred))
>>> +         part->initializers_visited = new hash_set<symtab_node *>;
>>> +       if (!part->initializers_visited->add (ref->referred))
>>>          add_references_to_partition (part, ref->referred);
>>>       }
>>> }
>>> @@ -250,7 +250,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes)
>>> 
>>>       /* After UNDO we no longer know what was visited.  */
>>>       if (partition->initializers_visited)
>>> -       pointer_set_destroy (partition->initializers_visited);
>>> +       delete partition->initializers_visited;
>>>       partition->initializers_visited = NULL;
>>> 
>>>       if (!node->alias && (cnode = dyn_cast <cgraph_node *> (node)))
>>> diff --git a/gcc/lto/lto-partition.h b/gcc/lto/lto-partition.h
>>> index 8db61b3..50ec2fa 100644
>>> --- a/gcc/lto/lto-partition.h
>>> +++ b/gcc/lto/lto-partition.h
>>> @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
>>> along with GCC; see the file COPYING3.  If not see
>>> <http://www.gnu.org/licenses/>.  */
>>> 
>>> +#include "hash-set.h"
>>> 
>>> /* Structure describing ltrans partitions.  */
>>> 
>>> @@ -25,7 +26,7 @@ struct ltrans_partition_def
>>>   lto_symtab_encoder_t encoder;
>>>   const char * name;
>>>   int insns;
>>> -  pointer_set_t *initializers_visited;
>>> +  hash_set<symtab_node *> *initializers_visited;
>>> };
>>> 
>>> typedef struct ltrans_partition_def *ltrans_partition;
>>> diff --git a/gcc/stmt.c b/gcc/stmt.c
>>> index 0aae085..55ec279 100644
>>> --- a/gcc/stmt.c
>>> +++ b/gcc/stmt.c
>>> @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "predict.h"
>>> #include "optabs.h"
>>> #include "target.h"
>>> +#include "hash-set.h"
>>> #include "pointer-set.h"
>>> #include "basic-block.h"
>>> #include "tree-ssa-alias.h"
>>> @@ -1183,7 +1184,7 @@ expand_case (gimple stmt)
>>>      how to expand this switch().  */
>>>   uniq = 0;
>>>   count = 0;
>>> -  struct pointer_set_t *seen_labels = pointer_set_create ();
>>> +  hash_set<tree> seen_labels;
>>>   compute_cases_per_edge (stmt);
>>> 
>>>   for (i = ncases - 1; i >= 1; --i)
>>> @@ -1203,7 +1204,7 @@ expand_case (gimple stmt)
>>> 
>>>       /* If we have not seen this label yet, then increase the
>>>         number of unique case node targets seen.  */
>>> -      if (!pointer_set_insert (seen_labels, lab))
>>> +      if (!seen_labels.add (lab))
>>>        uniq++;
>>> 
>>>       /* The bounds on the case range, LOW and HIGH, have to be converted
>>> @@ -1231,7 +1232,6 @@ expand_case (gimple stmt)
>>>           case_edge->probability / (intptr_t)(case_edge->aux),
>>>           case_node_pool);
>>>     }
>>> -  pointer_set_destroy (seen_labels);
>>>   reset_out_edges_aux (bb);
>>> 
>>>   /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
>>> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
>>> index 6fee8a4..e034762 100644
>>> --- a/gcc/tree-cfg.c
>>> +++ b/gcc/tree-cfg.c
>>> @@ -4691,7 +4691,7 @@ tree_node_can_be_shared (tree t)
>>> static tree
>>> verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
>>> {
>>> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
>>> +  hash_set<void *> *visited = (hash_set<void *> *) data;
>>> 
>>>   if (tree_node_can_be_shared (*tp))
>>>     {
>>> @@ -4699,7 +4699,7 @@ verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
>>>       return NULL;
>>>     }
>>> 
>>> -  if (pointer_set_insert (visited, *tp))
>>> +  if (visited->add (*tp))
>>>     return *tp;
>>> 
>>>   return NULL;
>>> @@ -4719,9 +4719,9 @@ static int
>>> verify_eh_throw_stmt_node (void **slot, void *data)
>>> {
>>>   struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
>>> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
>>> +  hash_set<void *> *visited = (hash_set<void *> *) data;
>>> 
>>> -  if (!pointer_set_contains (visited, node->stmt))
>>> +  if (!visited->contains (node->stmt))
>>>     {
>>>       error ("dead STMT in EH table");
>>>       debug_gimple_stmt (node->stmt);
>>> @@ -4733,11 +4733,11 @@ verify_eh_throw_stmt_node (void **slot, void *data)
>>> /* Verify if the location LOCs block is in BLOCKS.  */
>>> 
>>> static bool
>>> -verify_location (pointer_set_t *blocks, location_t loc)
>>> +verify_location (hash_set<tree> *blocks, location_t loc)
>>> {
>>>   tree block = LOCATION_BLOCK (loc);
>>>   if (block != NULL_TREE
>>> -      && !pointer_set_contains (blocks, block))
>>> +      && !blocks->contains (block))
>>>     {
>>>       error ("location references block not in block tree");
>>>       return true;
>>> @@ -4770,7 +4770,7 @@ verify_expr_no_block (tree *tp, int *walk_subtrees, void *)
>>> static tree
>>> verify_expr_location_1 (tree *tp, int *walk_subtrees, void *data)
>>> {
>>> -  struct pointer_set_t *blocks = (struct pointer_set_t *) data;
>>> +  hash_set<tree> *blocks = (hash_set<tree> *) data;
>>> 
>>>   if (TREE_CODE (*tp) == VAR_DECL
>>>       && DECL_HAS_DEBUG_EXPR_P (*tp))
>>> @@ -4816,12 +4816,12 @@ verify_expr_location (tree *tp, int *walk_subtrees, void *data)
>>> /* Insert all subblocks of BLOCK into BLOCKS and recurse.  */
>>> 
>>> static void
>>> -collect_subblocks (pointer_set_t *blocks, tree block)
>>> +collect_subblocks (hash_set<tree> *blocks, tree block)
>>> {
>>>   tree t;
>>>   for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
>>>     {
>>> -      pointer_set_insert (blocks, t);
>>> +      blocks->add (t);
>>>       collect_subblocks (blocks, t);
>>>     }
>>> }
>>> @@ -4833,18 +4833,17 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>>> {
>>>   basic_block bb;
>>>   bool err = false;
>>> -  struct pointer_set_t *visited, *visited_stmts, *blocks;
>>> 
>>>   timevar_push (TV_TREE_STMT_VERIFY);
>>> -  visited = pointer_set_create ();
>>> -  visited_stmts = pointer_set_create ();
>>> +  hash_set<void *> visited;
>>> +  hash_set<gimple> visited_stmts;
>>> 
>>>   /* Collect all BLOCKs referenced by the BLOCK tree of FN.  */
>>> -  blocks = pointer_set_create ();
>>> +  hash_set<tree> blocks;
>>>   if (DECL_INITIAL (fn->decl))
>>>     {
>>> -      pointer_set_insert (blocks, DECL_INITIAL (fn->decl));
>>> -      collect_subblocks (blocks, DECL_INITIAL (fn->decl));
>>> +      blocks.add (DECL_INITIAL (fn->decl));
>>> +      collect_subblocks (&blocks, DECL_INITIAL (fn->decl));
>>>     }
>>> 
>>>   FOR_EACH_BB_FN (bb, fn)
>>> @@ -4857,7 +4856,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>>>          bool err2 = false;
>>>          unsigned i;
>>> 
>>> -         pointer_set_insert (visited_stmts, phi);
>>> +         visited_stmts.add (phi);
>>> 
>>>          if (gimple_bb (phi) != bb)
>>>            {
>>> @@ -4878,7 +4877,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>>>            {
>>>              tree arg = gimple_phi_arg_def (phi, i);
>>>              tree addr = walk_tree (&arg, verify_node_sharing_1,
>>> -                                    visited, NULL);
>>> +                                    &visited, NULL);
>>>              if (addr)
>>>                {
>>>                  error ("incorrect sharing of tree nodes");
>>> @@ -4892,13 +4891,13 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>>>                  error ("virtual PHI with argument locations");
>>>                  err2 = true;
>>>                }
>>> -             addr = walk_tree (&arg, verify_expr_location_1, blocks, NULL);
>>> +             addr = walk_tree (&arg, verify_expr_location_1, &blocks, NULL);
>>>              if (addr)
>>>                {
>>>                  debug_generic_expr (addr);
>>>                  err2 = true;
>>>                }
>>> -             err2 |= verify_location (blocks, loc);
>>> +             err2 |= verify_location (&blocks, loc);
>>>            }
>>> 
>>>          if (err2)
>>> @@ -4914,7 +4913,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>>>          tree addr;
>>>          int lp_nr;
>>> 
>>> -         pointer_set_insert (visited_stmts, stmt);
>>> +         visited_stmts.add (stmt);
>>> 
>>>          if (gimple_bb (stmt) != bb)
>>>            {
>>> @@ -4923,10 +4922,10 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>>>            }
>>> 
>>>          err2 |= verify_gimple_stmt (stmt);
>>> -         err2 |= verify_location (blocks, gimple_location (stmt));
>>> +         err2 |= verify_location (&blocks, gimple_location (stmt));
>>> 
>>>          memset (&wi, 0, sizeof (wi));
>>> -         wi.info = (void *) visited;
>>> +         wi.info = (void *) &visited;
>>>          addr = walk_gimple_op (stmt, verify_node_sharing, &wi);
>>>          if (addr)
>>>            {
>>> @@ -4936,7 +4935,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>>>            }
>>> 
>>>          memset (&wi, 0, sizeof (wi));
>>> -         wi.info = (void *) blocks;
>>> +         wi.info = (void *) &blocks;
>>>          addr = walk_gimple_op (stmt, verify_expr_location, &wi);
>>>          if (addr)
>>>            {
>>> @@ -4992,14 +4991,11 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>>>   if (get_eh_throw_stmt_table (cfun))
>>>     htab_traverse (get_eh_throw_stmt_table (cfun),
>>>                   verify_eh_throw_stmt_node,
>>> -                  visited_stmts);
>>> +                  &visited_stmts);
>>> 
>>>   if (err || eh_error_found)
>>>     internal_error ("verify_gimple failed");
>>> 
>>> -  pointer_set_destroy (visited);
>>> -  pointer_set_destroy (visited_stmts);
>>> -  pointer_set_destroy (blocks);
>>>   verify_histograms ();
>>>   timevar_pop (TV_TREE_STMT_VERIFY);
>>> }
>>> diff --git a/gcc/tree-core.h b/gcc/tree-core.h
>>> index 34c48fa..9d462d1 100644
>>> --- a/gcc/tree-core.h
>>> +++ b/gcc/tree-core.h
>>> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #define GCC_TREE_CORE_H
>>> 
>>> #include "hashtab.h"
>>> +#include "hash-set.h"
>>> #include "machmode.h"
>>> #include "input.h"
>>> #include "statistics.h"
>>> @@ -45,7 +46,6 @@ struct fixed_value;
>>> struct ptr_info_def;
>>> struct range_info_def;
>>> struct die_struct;
>>> -struct pointer_set_t;
>>> 
>>> 
>>> /*---------------------------------------------------------------------------
>>> @@ -692,7 +692,7 @@ typedef tree (*walk_tree_fn) (tree *, int *, void *);
>>> 
>>> /* The type of a callback function that represents a custom walk_tree.  */
>>> typedef tree (*walk_tree_lh) (tree *, int *, tree (*) (tree *, int *, void *),
>>> -                             void *, struct pointer_set_t*);
>>> +                             void *, hash_set<tree> *);
>>> 
>>> 
>>> /*---------------------------------------------------------------------------
>>> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
>>> index df9a6fc..38842e8 100644
>>> --- a/gcc/tree-eh.c
>>> +++ b/gcc/tree-eh.c
>>> @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "flags.h"
>>> #include "function.h"
>>> #include "except.h"
>>> +#include "hash-set.h"
>>> #include "pointer-set.h"
>>> #include "basic-block.h"
>>> #include "tree-ssa-alias.h"
>>> @@ -3578,7 +3579,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>>>        eh_catch c;
>>>        edge_iterator ei;
>>>        edge e;
>>> -       struct pointer_set_t *seen_values = pointer_set_create ();
>>> +       hash_set<tree> seen_values;
>>> 
>>>        /* Collect the labels for a switch.  Zero the post_landing_pad
>>>           field becase we'll no longer have anything keeping these labels
>>> @@ -3605,12 +3606,12 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>>>                   attached to the handler anymore, we remove
>>>                   the corresponding edge and then we delete unreachable
>>>                   blocks at the end of this pass.  */
>>> -               if (! pointer_set_contains (seen_values, TREE_VALUE (flt_node)))
>>> +               if (! seen_values.contains (TREE_VALUE (flt_node)))
>>>                  {
>>>                    tree t = build_case_label (TREE_VALUE (flt_node),
>>>                                               NULL, lab);
>>>                    labels.safe_push (t);
>>> -                   pointer_set_insert (seen_values, TREE_VALUE (flt_node));
>>> +                   seen_values.add (TREE_VALUE (flt_node));
>>>                    have_label = true;
>>>                  }
>>> 
>>> @@ -3662,7 +3663,6 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>>>            x = gimple_build_switch (filter, default_label, labels);
>>>            gsi_insert_before (&gsi, x, GSI_SAME_STMT);
>>>          }
>>> -       pointer_set_destroy (seen_values);
>>>       }
>>>       break;
>>> 
>>> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
>>> index 33705b7..6af4912 100644
>>> --- a/gcc/tree-inline.c
>>> +++ b/gcc/tree-inline.c
>>> @@ -1788,7 +1788,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
>>>             expensive, copy_body can be told to watch for nontrivial
>>>             changes.  */
>>>          if (id->statements_to_fold)
>>> -           pointer_set_insert (id->statements_to_fold, stmt);
>>> +           id->statements_to_fold->add (stmt);
>>> 
>>>          /* We're duplicating a CALL_EXPR.  Find any corresponding
>>>             callgraph edges and update or duplicate them.  */
>>> @@ -3507,7 +3507,6 @@ inline_forbidden_p (tree fndecl)
>>> {
>>>   struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
>>>   struct walk_stmt_info wi;
>>> -  struct pointer_set_t *visited_nodes;
>>>   basic_block bb;
>>>   bool forbidden_p = false;
>>> 
>>> @@ -3518,10 +3517,10 @@ inline_forbidden_p (tree fndecl)
>>> 
>>>   /* Next, walk the statements of the function looking for
>>>      constraucts we can't handle, or are non-optimal for inlining.  */
>>> -  visited_nodes = pointer_set_create ();
>>> +  hash_set<tree> visited_nodes;
>>>   memset (&wi, 0, sizeof (wi));
>>>   wi.info = (void *) fndecl;
>>> -  wi.pset = visited_nodes;
>>> +  wi.pset = &visited_nodes;
>>> 
>>>   FOR_EACH_BB_FN (bb, fun)
>>>     {
>>> @@ -3533,7 +3532,6 @@ inline_forbidden_p (tree fndecl)
>>>        break;
>>>     }
>>> 
>>> -  pointer_set_destroy (visited_nodes);
>>>   return forbidden_p;
>>> }
>>> 
>>> @@ -4531,7 +4529,7 @@ gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
>>>    in the STATEMENTS pointer set.  */
>>> 
>>> static void
>>> -fold_marked_statements (int first, struct pointer_set_t *statements)
>>> +fold_marked_statements (int first, hash_set<gimple> *statements)
>>> {
>>>   for (; first < n_basic_blocks_for_fn (cfun); first++)
>>>     if (BASIC_BLOCK_FOR_FN (cfun, first))
>>> @@ -4541,7 +4539,7 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
>>>        for (gsi = gsi_start_bb (BASIC_BLOCK_FOR_FN (cfun, first));
>>>             !gsi_end_p (gsi);
>>>             gsi_next (&gsi))
>>> -         if (pointer_set_contains (statements, gsi_stmt (gsi)))
>>> +         if (statements->contains (gsi_stmt (gsi)))
>>>            {
>>>              gimple old_stmt = gsi_stmt (gsi);
>>>              tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
>>> @@ -4642,7 +4640,7 @@ optimize_inline_calls (tree fn)
>>>   id.transform_return_to_modify = true;
>>>   id.transform_parameter = true;
>>>   id.transform_lang_insert_block = NULL;
>>> -  id.statements_to_fold = pointer_set_create ();
>>> +  id.statements_to_fold = new hash_set<gimple>;
>>> 
>>>   push_gimplify_context ();
>>> 
>>> @@ -4678,7 +4676,7 @@ optimize_inline_calls (tree fn)
>>> 
>>>   /* Fold queued statements.  */
>>>   fold_marked_statements (last, id.statements_to_fold);
>>> -  pointer_set_destroy (id.statements_to_fold);
>>> +  delete id.statements_to_fold;
>>> 
>>>   gcc_assert (!id.debug_stmts.exists ());
>>> 
>>> @@ -4920,7 +4918,6 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
>>> {
>>>   copy_body_data id;
>>>   struct walk_stmt_info wi;
>>> -  struct pointer_set_t *visited;
>>>   gimple_seq copy;
>>> 
>>>   /* There's nothing to do for NULL_TREE.  */
>>> @@ -4943,11 +4940,10 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
>>> 
>>>   /* Walk the tree once to find local labels.  */
>>>   memset (&wi, 0, sizeof (wi));
>>> -  visited = pointer_set_create ();
>>> +  hash_set<tree> visited;
>>>   wi.info = &id;
>>> -  wi.pset = visited;
>>> +  wi.pset = &visited;
>>>   walk_gimple_seq (seq, mark_local_labels_stmt, NULL, &wi);
>>> -  pointer_set_destroy (visited);
>>> 
>>>   copy = gimple_seq_copy (seq);
>>> 
>>> @@ -5370,7 +5366,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
>>>   memset (&id, 0, sizeof (id));
>>> 
>>>   /* Generate a new name for the new version. */
>>> -  id.statements_to_fold = pointer_set_create ();
>>> +  id.statements_to_fold = new hash_set<gimple>;
>>> 
>>>   id.decl_map = pointer_map_create ();
>>>   id.debug_map = NULL;
>>> @@ -5541,7 +5537,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
>>>   free_dominance_info (CDI_POST_DOMINATORS);
>>> 
>>>   fold_marked_statements (0, id.statements_to_fold);
>>> -  pointer_set_destroy (id.statements_to_fold);
>>> +  delete id.statements_to_fold;
>>>   fold_cond_expr_cond ();
>>>   delete_unreachable_blocks_update_callgraph (&id);
>>>   if (id.dst_node->definition)
>>> diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
>>> index 2a5daaf..c13e6c7 100644
>>> --- a/gcc/tree-inline.h
>>> +++ b/gcc/tree-inline.h
>>> @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
>>> #ifndef GCC_TREE_INLINE_H
>>> #define GCC_TREE_INLINE_H
>>> 
>>> +#include "hash-set.h"
>>> +
>>> struct cgraph_edge;
>>> 
>>> /* Indicate the desired behavior wrt call graph edges.  We can either
>>> @@ -114,7 +116,7 @@ struct copy_body_data
>>>   void (*transform_lang_insert_block) (tree);
>>> 
>>>   /* Statements that might be possibly folded.  */
>>> -  struct pointer_set_t *statements_to_fold;
>>> +  hash_set<gimple> *statements_to_fold;
>>> 
>>>   /* Entry basic block to currently copied body.  */
>>>   basic_block entry_bb;
>>> diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
>>> index 185d87c..45c5cf7 100644
>>> --- a/gcc/tree-nested.c
>>> +++ b/gcc/tree-nested.c
>>> @@ -95,7 +95,7 @@ struct nesting_info
>>> 
>>>   struct pointer_map_t *field_map;
>>>   struct pointer_map_t *var_map;
>>> -  struct pointer_set_t *mem_refs;
>>> +  hash_set<tree *> *mem_refs;
>>>   bitmap suppress_expansion;
>>> 
>>>   tree context;
>>> @@ -732,7 +732,7 @@ create_nesting_tree (struct cgraph_node *cgn)
>>>   struct nesting_info *info = XCNEW (struct nesting_info);
>>>   info->field_map = pointer_map_create ();
>>>   info->var_map = pointer_map_create ();
>>> -  info->mem_refs = pointer_set_create ();
>>> +  info->mem_refs = new hash_set<tree *>;
>>>   info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
>>>   info->context = cgn->decl;
>>> 
>>> @@ -1651,7 +1651,7 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
>>>         fold here, as the chain record type is not yet finalized.  */
>>>       if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
>>>          && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
>>> -       pointer_set_insert (info->mem_refs, tp);
>>> +       info->mem_refs->add (tp);
>>>       wi->val_only = save_val_only;
>>>       break;
>>> 
>>> @@ -2655,8 +2655,8 @@ remap_vla_decls (tree block, struct nesting_info *root)
>>> }
>>> 
>>> /* Fold the MEM_REF *E.  */
>>> -static bool
>>> -fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED)
>>> +bool
>>> +fold_mem_refs (tree *const &e, void *data ATTRIBUTE_UNUSED)
>>> {
>>>   tree *ref_p = CONST_CAST2 (tree *, const tree *, (const tree *)e);
>>>   *ref_p = fold (*ref_p);
>>> @@ -2878,7 +2878,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
>>>     }
>>> 
>>>   /* Fold the rewritten MEM_REF trees.  */
>>> -  pointer_set_traverse (root->mem_refs, fold_mem_refs, NULL);
>>> +  root->mem_refs->traverse<void *, fold_mem_refs> (NULL);
>>> 
>>>   /* Dump the translated tree function.  */
>>>   if (dump_file)
>>> @@ -2933,7 +2933,7 @@ free_nesting_tree (struct nesting_info *root)
>>>       next = iter_nestinfo_next (node);
>>>       pointer_map_destroy (node->var_map);
>>>       pointer_map_destroy (node->field_map);
>>> -      pointer_set_destroy (node->mem_refs);
>>> +      delete node->mem_refs;
>>>       free (node);
>>>       node = next;
>>>     }
>>> diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
>>> index ca6e014..aee0331 100644
>>> --- a/gcc/tree-pretty-print.c
>>> +++ b/gcc/tree-pretty-print.c
>>> @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "expr.h"
>>> #include "tree-pretty-print.h"
>>> #include "hashtab.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> #include "gimple-expr.h"
>>> #include "cgraph.h"
>>> #include "langhooks.h"
>>> @@ -103,14 +103,14 @@ debug_generic_stmt (tree t)
>>> DEBUG_FUNCTION void
>>> debug_tree_chain (tree t)
>>> {
>>> -  struct pointer_set_t *seen = pointer_set_create ();
>>> +  hash_set<tree> seen;
>>> 
>>>   while (t)
>>>     {
>>>       print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
>>>       fprintf (stderr, " ");
>>>       t = TREE_CHAIN (t);
>>> -      if (pointer_set_insert (seen, t))
>>> +      if (seen.add (t))
>>>        {
>>>          fprintf (stderr, "... [cycled back to ");
>>>          print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
>>> @@ -119,8 +119,6 @@ debug_tree_chain (tree t)
>>>        }
>>>     }
>>>   fprintf (stderr, "\n");
>>> -
>>> -  pointer_set_destroy (seen);
>>> }
>>> 
>>> /* Prints declaration DECL to the FILE with details specified by FLAGS.  */
>>> diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
>>> index 36d68a8..83c1b19 100644
>>> --- a/gcc/tree-ssa-loop-niter.c
>>> +++ b/gcc/tree-ssa-loop-niter.c
>>> @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "basic-block.h"
>>> #include "gimple-pretty-print.h"
>>> #include "intl.h"
>>> +#include "hash-set.h"
>>> #include "pointer-set.h"
>>> #include "tree-ssa-alias.h"
>>> #include "internal-fn.h"
>>> @@ -3281,7 +3282,7 @@ discover_iteration_bound_by_body_walk (struct loop *loop)
>>> static void
>>> maybe_lower_iteration_bound (struct loop *loop)
>>> {
>>> -  pointer_set_t *not_executed_last_iteration = NULL;
>>> +  hash_set<gimple> *not_executed_last_iteration = NULL;
>>>   struct nb_iter_bound *elt;
>>>   bool found_exit = false;
>>>   vec<basic_block> queue = vNULL;
>>> @@ -3300,8 +3301,8 @@ maybe_lower_iteration_bound (struct loop *loop)
>>>          && wi::ltu_p (elt->bound, loop->nb_iterations_upper_bound))
>>>        {
>>>          if (!not_executed_last_iteration)
>>> -           not_executed_last_iteration = pointer_set_create ();
>>> -         pointer_set_insert (not_executed_last_iteration, elt->stmt);
>>> +           not_executed_last_iteration = new hash_set<gimple>;
>>> +         not_executed_last_iteration->add (elt->stmt);
>>>        }
>>>     }
>>>   if (!not_executed_last_iteration)
>>> @@ -3327,7 +3328,7 @@ maybe_lower_iteration_bound (struct loop *loop)
>>>       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>>>        {
>>>          gimple stmt = gsi_stmt (gsi);
>>> -         if (pointer_set_contains (not_executed_last_iteration, stmt))
>>> +         if (not_executed_last_iteration->contains (stmt))
>>>            {
>>>              stmt_found = true;
>>>              break;
>>> @@ -3376,7 +3377,7 @@ maybe_lower_iteration_bound (struct loop *loop)
>>>     }
>>>   BITMAP_FREE (visited);
>>>   queue.release ();
>>> -  pointer_set_destroy (not_executed_last_iteration);
>>> +  delete not_executed_last_iteration;
>>> }
>>> 
>>> /* Records estimates on numbers of iterations of LOOP.  If USE_UNDEFINED_P
>>> diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
>>> index 052d760..3185d9a 100644
>>> --- a/gcc/tree-ssa-phiopt.c
>>> +++ b/gcc/tree-ssa-phiopt.c
>>> @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "flags.h"
>>> #include "tm_p.h"
>>> #include "basic-block.h"
>>> +#include "hash-set.h"
>>> #include "pointer-set.h"
>>> #include "tree-ssa-alias.h"
>>> #include "internal-fn.h"
>>> @@ -72,9 +73,9 @@ static bool abs_replacement (basic_block, basic_block,
>>> static bool neg_replacement (basic_block, basic_block,
>>>                             edge, edge, gimple, tree, tree);
>>> static bool cond_store_replacement (basic_block, basic_block, edge, edge,
>>> -                                   struct pointer_set_t *);
>>> +                                   hash_set<tree> *);
>>> static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
>>> -static struct pointer_set_t * get_non_trapping (void);
>>> +static hash_set<tree> * get_non_trapping ();
>>> static void replace_phi_edge_with_variable (basic_block, edge, gimple, tree);
>>> static void hoist_adjacent_loads (basic_block, basic_block,
>>>                                  basic_block, basic_block);
>>> @@ -176,7 +177,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
>>>   basic_block *bb_order;
>>>   unsigned n, i;
>>>   bool cfgchanged = false;
>>> -  struct pointer_set_t *nontrap = 0;
>>> +  hash_set<tree> *nontrap = 0;
>>> 
>>>   if (do_store_elim)
>>>     /* Calculate the set of non-trapping memory accesses.  */
>>> @@ -363,7 +364,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
>>>   free (bb_order);
>>> 
>>>   if (do_store_elim)
>>> -    pointer_set_destroy (nontrap);
>>> +    delete nontrap;
>>>   /* If the CFG has changed, we should cleanup the CFG.  */
>>>   if (cfgchanged && do_store_elim)
>>>     {
>>> @@ -1469,7 +1470,7 @@ ssa_names_hasher::equal (const value_type *n1, const compare_type *n2)
>>> class nontrapping_dom_walker : public dom_walker
>>> {
>>> public:
>>> -  nontrapping_dom_walker (cdi_direction direction, pointer_set_t *ps)
>>> +  nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps)
>>>     : dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {}
>>> 
>>>   virtual void before_dom_children (basic_block);
>>> @@ -1484,7 +1485,7 @@ private:
>>>      the RHS.  */
>>>   void add_or_mark_expr (basic_block, tree, bool);
>>> 
>>> -  pointer_set_t *m_nontrapping;
>>> +  hash_set<tree> *m_nontrapping;
>>> 
>>>   /* The hash table for remembering what we've seen.  */
>>>   hash_table<ssa_names_hasher> m_seen_ssa_names;
>>> @@ -1572,7 +1573,7 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
>>>         then we can't trap.  */
>>>       if (found_bb && (((size_t)found_bb->aux) & 1) == 1)
>>>        {
>>> -         pointer_set_insert (m_nontrapping, exp);
>>> +         m_nontrapping->add (exp);
>>>        }
>>>       else
>>>         {
>>> @@ -1601,11 +1602,11 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
>>>    It will do a dominator walk over the whole function, and it will
>>>    make use of the bb->aux pointers.  It returns a set of trees
>>>    (the MEM_REFs itself) which can't trap.  */
>>> -static struct pointer_set_t *
>>> +static hash_set<tree> *
>>> get_non_trapping (void)
>>> {
>>>   nt_call_phase = 0;
>>> -  pointer_set_t *nontrap = pointer_set_create ();
>>> +  hash_set<tree> *nontrap = new hash_set<tree>;
>>>   /* We're going to do a dominator walk, so ensure that we have
>>>      dominance information.  */
>>>   calculate_dominance_info (CDI_DOMINATORS);
>>> @@ -1634,7 +1635,7 @@ get_non_trapping (void)
>>> 
>>> static bool
>>> cond_store_replacement (basic_block middle_bb, basic_block join_bb,
>>> -                       edge e0, edge e1, struct pointer_set_t *nontrap)
>>> +                       edge e0, edge e1, hash_set<tree> *nontrap)
>>> {
>>>   gimple assign = last_and_only_stmt (middle_bb);
>>>   tree lhs, rhs, name, name2;
>>> @@ -1659,7 +1660,7 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb,
>>>   /* Prove that we can move the store down.  We could also check
>>>      TREE_THIS_NOTRAP here, but in that case we also could move stores,
>>>      whose value is not available readily, which we want to avoid.  */
>>> -  if (!pointer_set_contains (nontrap, lhs))
>>> +  if (!nontrap->contains (lhs))
>>>     return false;
>>> 
>>>   /* Now we've checked the constraints, so do the transformation:
>>> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
>>> index 9807b42..3dee5ba 100644
>>> --- a/gcc/tree-ssa-threadedge.c
>>> +++ b/gcc/tree-ssa-threadedge.c
>>> @@ -30,7 +30,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "function.h"
>>> #include "timevar.h"
>>> #include "dumpfile.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> #include "tree-ssa-alias.h"
>>> #include "internal-fn.h"
>>> #include "gimple-expr.h"
>>> @@ -693,13 +693,13 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>>>     }
>>> 
>>>   auto_vec<tree, alloc_count> fewvars;
>>> -  pointer_set_t *vars = NULL;
>>> +  hash_set<tree> *vars = NULL;
>>> 
>>>   /* If we're already starting with 3/4 of alloc_count, go for a
>>> -     pointer_set, otherwise start with an unordered stack-allocated
>>> +     hash_set, otherwise start with an unordered stack-allocated
>>>      VEC.  */
>>>   if (i * 4 > alloc_count * 3)
>>> -    vars = pointer_set_create ();
>>> +    vars = new hash_set<tree>;
>>> 
>>>   /* Now go through the initial debug stmts in DEST again, this time
>>>      actually inserting in VARS or FEWVARS.  Don't bother checking for
>>> @@ -720,7 +720,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>>>        gcc_unreachable ();
>>> 
>>>       if (vars)
>>> -       pointer_set_insert (vars, var);
>>> +       vars->add (var);
>>>       else
>>>        fewvars.quick_push (var);
>>>     }
>>> @@ -754,7 +754,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>>>             or somesuch.  Adding `&& bb == src' to the condition
>>>             below will preserve all potentially relevant debug
>>>             notes.  */
>>> -         if (vars && pointer_set_insert (vars, var))
>>> +         if (vars && vars->add (var))
>>>            continue;
>>>          else if (!vars)
>>>            {
>>> @@ -769,11 +769,11 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>>>                fewvars.quick_push (var);
>>>              else
>>>                {
>>> -                 vars = pointer_set_create ();
>>> +                 vars = new hash_set<tree>;
>>>                  for (i = 0; i < alloc_count; i++)
>>> -                   pointer_set_insert (vars, fewvars[i]);
>>> +                   vars->add (fewvars[i]);
>>>                  fewvars.release ();
>>> -                 pointer_set_insert (vars, var);
>>> +                 vars->add (var);
>>>                }
>>>            }
>>> 
>>> @@ -786,7 +786,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
>>>   while (bb != src && single_pred_p (bb));
>>> 
>>>   if (vars)
>>> -    pointer_set_destroy (vars);
>>> +    delete vars;
>>>   else if (fewvars.exists ())
>>>     fewvars.release ();
>>> }
>>> diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
>>> index 64259fb..f2578b7 100644
>>> --- a/gcc/tree-ssa-uninit.c
>>> +++ b/gcc/tree-ssa-uninit.c
>>> @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "function.h"
>>> #include "gimple-pretty-print.h"
>>> #include "bitmap.h"
>>> +#include "hash-set.h"
>>> #include "pointer-set.h"
>>> #include "tree-ssa-alias.h"
>>> #include "internal-fn.h"
>>> @@ -60,7 +61,7 @@ along with GCC; see the file COPYING3.  If not see
>>> /* Pointer set of potentially undefined ssa names, i.e.,
>>>    ssa names that are defined by phi with operands that
>>>    are not defined or potentially undefined.  */
>>> -static pointer_set_t *possibly_undefined_names = 0;
>>> +static hash_set<tree> *possibly_undefined_names = 0;
>>> 
>>> /* Bit mask handling macros.  */
>>> #define MASK_SET_BIT(mask, pos) mask |= (1 << pos)
>>> @@ -89,7 +90,7 @@ has_undefined_value_p (tree t)
>>> {
>>>   return (ssa_undefined_value_p (t)
>>>           || (possibly_undefined_names
>>> -              && pointer_set_contains (possibly_undefined_names, t)));
>>> +              && possibly_undefined_names->contains (t)));
>>> }
>>> 
>>> 
>>> @@ -648,13 +649,13 @@ find_predicates (pred_chain_union *preds,
>>> static void
>>> collect_phi_def_edges (gimple phi, basic_block cd_root,
>>>                        vec<edge> *edges,
>>> -                       pointer_set_t *visited_phis)
>>> +                       hash_set<gimple> *visited_phis)
>>> {
>>>   size_t i, n;
>>>   edge opnd_edge;
>>>   tree opnd;
>>> 
>>> -  if (pointer_set_insert (visited_phis, phi))
>>> +  if (visited_phis->add (phi))
>>>     return;
>>> 
>>>   n = gimple_phi_num_args (phi);
>>> @@ -707,7 +708,6 @@ find_def_preds (pred_chain_union *preds, gimple phi)
>>>   vec<edge> def_edges = vNULL;
>>>   bool has_valid_pred = false;
>>>   basic_block phi_bb, cd_root = 0;
>>> -  pointer_set_t *visited_phis;
>>> 
>>>   phi_bb = gimple_bb (phi);
>>>   /* First find the closest dominating bb to be
>>> @@ -716,9 +716,8 @@ find_def_preds (pred_chain_union *preds, gimple phi)
>>>   if (!cd_root)
>>>     return false;
>>> 
>>> -  visited_phis = pointer_set_create ();
>>> -  collect_phi_def_edges (phi, cd_root, &def_edges, visited_phis);
>>> -  pointer_set_destroy (visited_phis);
>>> +  hash_set<gimple> visited_phis;
>>> +  collect_phi_def_edges (phi, cd_root, &def_edges, &visited_phis);
>>> 
>>>   n = def_edges.length ();
>>>   if (n == 0)
>>> @@ -941,7 +940,7 @@ is_use_properly_guarded (gimple use_stmt,
>>>                          basic_block use_bb,
>>>                          gimple phi,
>>>                          unsigned uninit_opnds,
>>> -                         pointer_set_t *visited_phis);
>>> +                         hash_set<gimple> *visited_phis);
>>> 
>>> /* Returns true if all uninitialized opnds are pruned. Returns false
>>>    otherwise. PHI is the phi node with uninitialized operands,
>>> @@ -983,7 +982,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
>>>                                              gimple flag_def,
>>>                                              tree boundary_cst,
>>>                                              enum tree_code cmp_code,
>>> -                                             pointer_set_t *visited_phis,
>>> +                                             hash_set<gimple> *visited_phis,
>>>                                              bitmap *visited_flag_phis)
>>> {
>>>   unsigned i;
>>> @@ -1153,7 +1152,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
>>> static bool
>>> use_pred_not_overlap_with_undef_path_pred (pred_chain_union preds,
>>>                                           gimple phi, unsigned uninit_opnds,
>>> -                                          pointer_set_t *visited_phis)
>>> +                                          hash_set<gimple> *visited_phis)
>>> {
>>>   unsigned int i, n;
>>>   gimple flag_def = 0;
>>> @@ -1818,11 +1817,11 @@ push_pred (pred_chain_union *norm_preds, pred_info pred)
>>> 
>>> inline static void
>>> push_to_worklist (tree op, vec<pred_info, va_heap, vl_ptr> *work_list,
>>> -                  pointer_set_t *mark_set)
>>> +                  hash_set<tree> *mark_set)
>>> {
>>> -  if (pointer_set_contains (mark_set, op))
>>> +  if (mark_set->contains (op))
>>>     return;
>>> -  pointer_set_insert (mark_set, op);
>>> +  mark_set->add (op);
>>> 
>>>   pred_info arg_pred;
>>>   arg_pred.pred_lhs = op;
>>> @@ -1907,7 +1906,7 @@ normalize_one_pred_1 (pred_chain_union *norm_preds,
>>>                       pred_info pred,
>>>                       enum tree_code and_or_code,
>>>                       vec<pred_info, va_heap, vl_ptr> *work_list,
>>> -                     pointer_set_t *mark_set)
>>> +                     hash_set<tree> *mark_set)
>>> {
>>>   if (!is_neq_zero_form_p (pred))
>>>     {
>>> @@ -1987,7 +1986,6 @@ normalize_one_pred (pred_chain_union *norm_preds,
>>>                     pred_info pred)
>>> {
>>>   vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
>>> -  pointer_set_t *mark_set = NULL;
>>>   enum tree_code and_or_code = ERROR_MARK;
>>>   pred_chain norm_chain = vNULL;
>>> 
>>> @@ -2015,19 +2013,18 @@ normalize_one_pred (pred_chain_union *norm_preds,
>>>     }
>>> 
>>>   work_list.safe_push (pred);
>>> -  mark_set = pointer_set_create ();
>>> +  hash_set<tree> mark_set;
>>> 
>>>   while (!work_list.is_empty ())
>>>     {
>>>       pred_info a_pred = work_list.pop ();
>>>       normalize_one_pred_1 (norm_preds, &norm_chain, a_pred,
>>> -                            and_or_code, &work_list, mark_set);
>>> +                            and_or_code, &work_list, &mark_set);
>>>     }
>>>   if (and_or_code == BIT_AND_EXPR)
>>>     norm_preds->safe_push (norm_chain);
>>> 
>>>   work_list.release ();
>>> -  pointer_set_destroy (mark_set);
>>> }
>>> 
>>> static void
>>> @@ -2035,26 +2032,25 @@ normalize_one_pred_chain (pred_chain_union *norm_preds,
>>>                           pred_chain one_chain)
>>> {
>>>   vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
>>> -  pointer_set_t *mark_set = pointer_set_create ();
>>> +  hash_set<tree> mark_set;
>>>   pred_chain norm_chain = vNULL;
>>>   size_t i;
>>> 
>>>   for (i = 0; i < one_chain.length (); i++)
>>>     {
>>>       work_list.safe_push (one_chain[i]);
>>> -      pointer_set_insert (mark_set, one_chain[i].pred_lhs);
>>> +      mark_set.add (one_chain[i].pred_lhs);
>>>     }
>>> 
>>>   while (!work_list.is_empty ())
>>>     {
>>>       pred_info a_pred = work_list.pop ();
>>>       normalize_one_pred_1 (0, &norm_chain, a_pred,
>>> -                            BIT_AND_EXPR, &work_list, mark_set);
>>> +                            BIT_AND_EXPR, &work_list, &mark_set);
>>>     }
>>> 
>>>   norm_preds->safe_push (norm_chain);
>>>   work_list.release ();
>>> -  pointer_set_destroy (mark_set);
>>> }
>>> 
>>> /* Normalize predicate chains PREDS and returns the normalized one.  */
>>> @@ -2112,7 +2108,7 @@ is_use_properly_guarded (gimple use_stmt,
>>>                          basic_block use_bb,
>>>                          gimple phi,
>>>                          unsigned uninit_opnds,
>>> -                         pointer_set_t *visited_phis)
>>> +                         hash_set<gimple> *visited_phis)
>>> {
>>>   basic_block phi_bb;
>>>   pred_chain_union preds = vNULL;
>>> @@ -2120,7 +2116,7 @@ is_use_properly_guarded (gimple use_stmt,
>>>   bool has_valid_preds = false;
>>>   bool is_properly_guarded = false;
>>> 
>>> -  if (pointer_set_insert (visited_phis, phi))
>>> +  if (visited_phis->add (phi))
>>>     return false;
>>> 
>>>   phi_bb = gimple_bb (phi);
>>> @@ -2181,7 +2177,7 @@ is_use_properly_guarded (gimple use_stmt,
>>> static gimple
>>> find_uninit_use (gimple phi, unsigned uninit_opnds,
>>>                  vec<gimple> *worklist,
>>> -                pointer_set_t *added_to_worklist)
>>> +                hash_set<gimple> *added_to_worklist)
>>> {
>>>   tree phi_result;
>>>   use_operand_p use_p;
>>> @@ -2192,28 +2188,22 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>>> 
>>>   FOR_EACH_IMM_USE_FAST (use_p, iter, phi_result)
>>>     {
>>> -      pointer_set_t *visited_phis;
>>>       basic_block use_bb;
>>> 
>>>       use_stmt = USE_STMT (use_p);
>>>       if (is_gimple_debug (use_stmt))
>>>        continue;
>>> 
>>> -      visited_phis = pointer_set_create ();
>>> -
>>>       if (gimple_code (use_stmt) == GIMPLE_PHI)
>>>        use_bb = gimple_phi_arg_edge (use_stmt,
>>>                                      PHI_ARG_INDEX_FROM_USE (use_p))->src;
>>>       else
>>>        use_bb = gimple_bb (use_stmt);
>>> 
>>> +      hash_set<gimple> visited_phis;
>>>       if (is_use_properly_guarded (use_stmt, use_bb, phi, uninit_opnds,
>>> -                                   visited_phis))
>>> -        {
>>> -          pointer_set_destroy (visited_phis);
>>> -          continue;
>>> -        }
>>> -      pointer_set_destroy (visited_phis);
>>> +                                   &visited_phis))
>>> +       continue;
>>> 
>>>       if (dump_file && (dump_flags & TDF_DETAILS))
>>>         {
>>> @@ -2226,7 +2216,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>>> 
>>>       /* Found a phi use that is not guarded,
>>>          add the phi to the worklist.  */
>>> -      if (!pointer_set_insert (added_to_worklist, use_stmt))
>>> +      if (!added_to_worklist->add (use_stmt))
>>>         {
>>>           if (dump_file && (dump_flags & TDF_DETAILS))
>>>             {
>>> @@ -2235,7 +2225,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>>>             }
>>> 
>>>           worklist->safe_push (use_stmt);
>>> -          pointer_set_insert (possibly_undefined_names, phi_result);
>>> +          possibly_undefined_names->add (phi_result);
>>>         }
>>>     }
>>> 
>>> @@ -2252,7 +2242,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
>>> 
>>> static void
>>> warn_uninitialized_phi (gimple phi, vec<gimple> *worklist,
>>> -                        pointer_set_t *added_to_worklist)
>>> +                        hash_set<gimple> *added_to_worklist)
>>> {
>>>   unsigned uninit_opnds;
>>>   gimple uninit_use_stmt = 0;
>>> @@ -2339,7 +2329,6 @@ pass_late_warn_uninitialized::execute (function *fun)
>>>   basic_block bb;
>>>   gimple_stmt_iterator gsi;
>>>   vec<gimple> worklist = vNULL;
>>> -  pointer_set_t *added_to_worklist;
>>> 
>>>   calculate_dominance_info (CDI_DOMINATORS);
>>>   calculate_dominance_info (CDI_POST_DOMINATORS);
>>> @@ -2350,8 +2339,8 @@ pass_late_warn_uninitialized::execute (function *fun)
>>> 
>>>   timevar_push (TV_TREE_UNINIT);
>>> 
>>> -  possibly_undefined_names = pointer_set_create ();
>>> -  added_to_worklist = pointer_set_create ();
>>> +  possibly_undefined_names = new hash_set<tree>;
>>> +  hash_set<gimple> added_to_worklist;
>>> 
>>>   /* Initialize worklist  */
>>>   FOR_EACH_BB_FN (bb, fun)
>>> @@ -2373,7 +2362,7 @@ pass_late_warn_uninitialized::execute (function *fun)
>>>                && uninit_undefined_value_p (op))
>>>              {
>>>                worklist.safe_push (phi);
>>> -               pointer_set_insert (added_to_worklist, phi);
>>> +               added_to_worklist.add (phi);
>>>                if (dump_file && (dump_flags & TDF_DETAILS))
>>>                  {
>>>                    fprintf (dump_file, "[WORKLIST]: add to initial list: ");
>>> @@ -2388,12 +2377,11 @@ pass_late_warn_uninitialized::execute (function *fun)
>>>     {
>>>       gimple cur_phi = 0;
>>>       cur_phi = worklist.pop ();
>>> -      warn_uninitialized_phi (cur_phi, &worklist, added_to_worklist);
>>> +      warn_uninitialized_phi (cur_phi, &worklist, &added_to_worklist);
>>>     }
>>> 
>>>   worklist.release ();
>>> -  pointer_set_destroy (added_to_worklist);
>>> -  pointer_set_destroy (possibly_undefined_names);
>>> +  delete possibly_undefined_names;
>>>   possibly_undefined_names = NULL;
>>>   free_dominance_info (CDI_POST_DOMINATORS);
>>>   timevar_pop (TV_TREE_UNINIT);
>>> diff --git a/gcc/tree.c b/gcc/tree.c
>>> index 6669a84..de1c9b6 100644
>>> --- a/gcc/tree.c
>>> +++ b/gcc/tree.c
>>> @@ -5143,7 +5143,7 @@ struct free_lang_data_d
>>>   vec<tree> worklist;
>>> 
>>>   /* Set of traversed objects.  Used to avoid duplicate visits.  */
>>> -  struct pointer_set_t *pset;
>>> +  hash_set<tree> *pset;
>>> 
>>>   /* Array of symbols to process with free_lang_data_in_decl.  */
>>>   vec<tree> decls;
>>> @@ -5208,7 +5208,7 @@ add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
>>> static inline void
>>> fld_worklist_push (tree t, struct free_lang_data_d *fld)
>>> {
>>> -  if (t && !is_lang_specific (t) && !pointer_set_contains (fld->pset, t))
>>> +  if (t && !is_lang_specific (t) && !fld->pset->contains (t))
>>>     fld->worklist.safe_push ((t));
>>> }
>>> 
>>> @@ -5374,7 +5374,7 @@ find_decls_types (tree t, struct free_lang_data_d *fld)
>>> {
>>>   while (1)
>>>     {
>>> -      if (!pointer_set_contains (fld->pset, t))
>>> +      if (!fld->pset->contains (t))
>>>        walk_tree (&t, find_decls_types_r, fld, fld->pset);
>>>       if (fld->worklist.is_empty ())
>>>        break;
>>> @@ -5584,7 +5584,7 @@ free_lang_data_in_cgraph (void)
>>>   alias_pair *p;
>>> 
>>>   /* Initialize sets and arrays to store referenced decls and types.  */
>>> -  fld.pset = pointer_set_create ();
>>> +  fld.pset = new hash_set<tree>;
>>>   fld.worklist.create (0);
>>>   fld.decls.create (100);
>>>   fld.types.create (100);
>>> @@ -5614,7 +5614,7 @@ free_lang_data_in_cgraph (void)
>>>   FOR_EACH_VEC_ELT (fld.types, i, t)
>>>     free_lang_data_in_type (t);
>>> 
>>> -  pointer_set_destroy (fld.pset);
>>> +  delete fld.pset;
>>>   fld.worklist.release ();
>>>   fld.decls.release ();
>>>   fld.types.release ();
>>> @@ -10819,7 +10819,7 @@ num_ending_zeros (const_tree x)
>>> 
>>> static tree
>>> walk_type_fields (tree type, walk_tree_fn func, void *data,
>>> -                 struct pointer_set_t *pset, walk_tree_lh lh)
>>> +                 hash_set<tree> *pset, walk_tree_lh lh)
>>> {
>>>   tree result = NULL_TREE;
>>> 
>>> @@ -10901,7 +10901,7 @@ walk_type_fields (tree type, walk_tree_fn func, void *data,
>>> 
>>> tree
>>> walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
>>> -            struct pointer_set_t *pset, walk_tree_lh lh)
>>> +            hash_set<tree> *pset, walk_tree_lh lh)
>>> {
>>>   enum tree_code code;
>>>   int walk_subtrees;
>>> @@ -10922,7 +10922,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
>>> 
>>>   /* Don't walk the same tree twice, if the user has requested
>>>      that we avoid doing so.  */
>>> -  if (pset && pointer_set_insert (pset, *tp))
>>> +  if (pset && pset->add (*tp))
>>>     return NULL_TREE;
>>> 
>>>   /* Call the function.  */
>>> @@ -11237,11 +11237,9 @@ walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data,
>>>                                walk_tree_lh lh)
>>> {
>>>   tree result;
>>> -  struct pointer_set_t *pset;
>>> 
>>> -  pset = pointer_set_create ();
>>> -  result = walk_tree_1 (tp, func, data, pset, lh);
>>> -  pointer_set_destroy (pset);
>>> +  hash_set<tree> pset;
>>> +  result = walk_tree_1 (tp, func, data, &pset, lh);
>>>   return result;
>>> }
>>> 
>>> diff --git a/gcc/tree.h b/gcc/tree.h
>>> index 2bb6d1f..c9f978a 100644
>>> --- a/gcc/tree.h
>>> +++ b/gcc/tree.h
>>> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #define GCC_TREE_H
>>> 
>>> #include "tree-core.h"
>>> +#include "hash-set.h"
>>> #include "wide-int.h"
>>> #include "inchash.h"
>>> 
>>> @@ -4328,7 +4329,7 @@ extern void using_eh_for_cleanups (void);
>>> extern bool using_eh_for_cleanups_p (void);
>>> extern const char *get_tree_code_name (enum tree_code);
>>> extern void set_call_expr_flags (tree, int);
>>> -extern tree walk_tree_1 (tree*, walk_tree_fn, void*, struct pointer_set_t*,
>>> +extern tree walk_tree_1 (tree*, walk_tree_fn, void*, hash_set<tree>*,
>>>                         walk_tree_lh);
>>> extern tree walk_tree_without_duplicates_1 (tree*, walk_tree_fn, void*,
>>>                                            walk_tree_lh);
>>> diff --git a/gcc/value-prof.c b/gcc/value-prof.c
>>> index 3e51539..ffdee65 100644
>>> --- a/gcc/value-prof.c
>>> +++ b/gcc/value-prof.c
>>> @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "data-streamer.h"
>>> #include "builtins.h"
>>> #include "tree-nested.h"
>>> +#include "hash-set.h"
>>> 
>>> /* In this file value profile based optimizations are placed.  Currently the
>>>    following optimizations are implemented (for more detailed descriptions
>>> @@ -515,10 +516,10 @@ static bool error_found = false;
>>> static int
>>> visit_hist (void **slot, void *data)
>>> {
>>> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
>>> +  hash_set<histogram_value> *visited = (hash_set<histogram_value> *) data;
>>>   histogram_value hist = *(histogram_value *) slot;
>>> 
>>> -  if (!pointer_set_contains (visited, hist)
>>> +  if (!visited->contains (hist)
>>>       && hist->type != HIST_TYPE_TIME_PROFILE)
>>>     {
>>>       error ("dead histogram");
>>> @@ -538,10 +539,9 @@ verify_histograms (void)
>>>   basic_block bb;
>>>   gimple_stmt_iterator gsi;
>>>   histogram_value hist;
>>> -  struct pointer_set_t *visited_hists;
>>> 
>>>   error_found = false;
>>> -  visited_hists = pointer_set_create ();
>>> +  hash_set<histogram_value> visited_hists;
>>>   FOR_EACH_BB_FN (bb, cfun)
>>>     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>>>       {
>>> @@ -558,12 +558,11 @@ verify_histograms (void)
>>>                dump_histogram_value (stderr, hist);
>>>                error_found = true;
>>>              }
>>> -            pointer_set_insert (visited_hists, hist);
>>> +            visited_hists.add (hist);
>>>          }
>>>       }
>>>   if (VALUE_HISTOGRAMS (cfun))
>>> -    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, visited_hists);
>>> -  pointer_set_destroy (visited_hists);
>>> +    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, &visited_hists);
>>>   if (error_found)
>>>     internal_error ("verify_histograms failed");
>>> }
>>> diff --git a/gcc/varasm.c b/gcc/varasm.c
>>> index 819ec26..9d8602b 100644
>>> --- a/gcc/varasm.c
>>> +++ b/gcc/varasm.c
>>> @@ -51,7 +51,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "common/common-target.h"
>>> #include "targhooks.h"
>>> #include "cgraph.h"
>>> -#include "pointer-set.h"
>>> +#include "hash-set.h"
>>> #include "asan.h"
>>> #include "basic-block.h"
>>> 
>>> @@ -2249,7 +2249,7 @@ static bool pending_assemble_externals_processed;
>>> 
>>> /* Avoid O(external_decls**2) lookups in the pending_assemble_externals
>>>    TREE_LIST in assemble_external.  */
>>> -static struct pointer_set_t *pending_assemble_externals_set;
>>> +static hash_set<tree> *pending_assemble_externals_set;
>>> 
>>> /* True if DECL is a function decl for which no out-of-line copy exists.
>>>    It is assumed that DECL's assembler name has been set.  */
>>> @@ -2303,7 +2303,7 @@ process_pending_assemble_externals (void)
>>> 
>>>   pending_assemble_externals = 0;
>>>   pending_assemble_externals_processed = true;
>>> -  pointer_set_destroy (pending_assemble_externals_set);
>>> +  delete pending_assemble_externals_set;
>>> #endif
>>> }
>>> 
>>> @@ -2361,7 +2361,7 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
>>>       return;
>>>     }
>>> 
>>> -  if (! pointer_set_insert (pending_assemble_externals_set, decl))
>>> +  if (! pending_assemble_externals_set->add (decl))
>>>     pending_assemble_externals = tree_cons (NULL, decl,
>>>                                            pending_assemble_externals);
>>> #endif
>>> @@ -5991,7 +5991,7 @@ init_varasm_once (void)
>>>     readonly_data_section = text_section;
>>> 
>>> #ifdef ASM_OUTPUT_EXTERNAL
>>> -  pending_assemble_externals_set = pointer_set_create ();
>>> +  pending_assemble_externals_set = new hash_set<tree>;
>>> #endif
>>> }
>>> 
>>> diff --git a/gcc/varpool.c b/gcc/varpool.c
>>> index 74117e2..558767f 100644
>>> --- a/gcc/varpool.c
>>> +++ b/gcc/varpool.c
>>> @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
>>> #include "tree-ssa-alias.h"
>>> #include "gimple.h"
>>> #include "lto-streamer.h"
>>> +#include "hash-set.h"
>>> 
>>> const char * const tls_model_names[]={"none", "tls-emulated", "tls-real",
>>>                                      "tls-global-dynamic", "tls-local-dynamic",
>>> @@ -576,7 +577,7 @@ varpool_remove_unreferenced_decls (void)
>>>   varpool_node *first = (varpool_node *)(void *)1;
>>>   int i;
>>>   struct ipa_ref *ref = NULL;
>>> -  struct pointer_set_t *referenced = pointer_set_create ();
>>> +  hash_set<varpool_node *> referenced;
>>> 
>>>   if (seen_error ())
>>>     return;
>>> @@ -623,7 +624,7 @@ varpool_remove_unreferenced_decls (void)
>>>              && vnode->analyzed)
>>>            enqueue_node (vnode, &first);
>>>          else
>>> -           pointer_set_insert (referenced, node);
>>> +           referenced.add (node);
>>>        }
>>>     }
>>>   if (cgraph_dump_file)
>>> @@ -635,13 +636,13 @@ varpool_remove_unreferenced_decls (void)
>>>        {
>>>           if (cgraph_dump_file)
>>>            fprintf (cgraph_dump_file, " %s", node->asm_name ());
>>> -         if (pointer_set_contains (referenced, node))
>>> +         if (referenced.contains (node))
>>>            node->remove_initializer ();
>>>          else
>>>            node->remove ();
>>>        }
>>>     }
>>> -  pointer_set_destroy (referenced);
>>> +
>>>   if (cgraph_dump_file)
>>>     fprintf (cgraph_dump_file, "\n");
>>> }
>>> --
>>> 2.0.1
>>>
Jeff Law Aug. 4, 2014, 5:40 p.m. UTC | #6
On 08/04/14 11:15, Trevor Saunders wrote:
> On Sat, Aug 02, 2014 at 03:44:17PM -0700, Andrew Pinski wrote:
>> On Tue, Jul 29, 2014 at 5:50 AM,  <tsaunders@mozilla.com> wrote:
>>> From: Trevor Saunders <tsaunders@mozilla.com>
>>>
>>> Hi,
>>>
>>> this adds a hash_set wrapper around hash_table, and then replaces usage of pointer_set with it.
>>>
>>> bootstrapped +regtested on x86_64-unknown-linux-gnu, ok?
>>>
>>> Trev
>>>
>>> ada/
>>>
>>>          * gcc-interface/trans.c: Use hash_set instead of pointer_set.
>>>
>>> c-family/
>>>
>>>          * c-gimplify.c: Use hash_set instead of pointer_set.
>>>
>>> c/
>>>
>>>          * c-decl.c: Use hash_set instead of pointer_set.
>>>
>>> cp/
>>>
>>>          * class.c, cp-gimplify.c, cp-tree.h, decl.c, decl2.c, error.c,
>>>          method.c, name-lookup.c, pt.c, semantics.c, tree.c: Use hash_set
>>>          instead of pointer_set.
>>>
>>> fortran/
>>>
>>>          * openmp.c, trans-decl.c: Use hash_set instead of pointer_set.
>>>
>>> gcc/
>>>
>>>          * hash-set.h: new File.
>>>          * cfgexpand.c, cfgloop.c, cgraph.c, cgraphbuild.c, cgraphunit.c,
>>>          cprop.c, cse.c, gimple-walk.c, gimple-walk.h, gimplify.c, godump.c,
>>>          ipa-devirt.c, ipa-pure-const.c, ipa-visibility.c, ipa.c, lto-cgraph.c,
>>>          lto-streamer-out.c, stmt.c, tree-cfg.c, tree-core.h, tree-eh.c,
>>>          tree-inline.c, tree-inline.h, tree-nested.c, tree-pretty-print.c,
>>>          tree-ssa-loop-niter.c, tree-ssa-phiopt.c, tree-ssa-threadedge.c,
>>>          tree-ssa-uninit.c, tree.c, tree.h, value-prof.c, varasm.c,
>>>          varpool.c: Use hash_set instead of pointer_set.
>>
>>
>> This changelog is less than useful and really does not follow the
>> GCC/GNU coding style.  Please expand and place all functions which are
>
> I'm pretty sure its written somewhere that format is ok, and there's
> precedent for it.  Note the update all callers rule could also be used
> to just write
Note we discussed this at Cauldron and there was a general consensus 
that the "update all callers" style was reasonable.

FWIW, that's actually be approved for use in GCC for a very long time. 
We've allowed using that style, without having to list each function 
changed, since the late 90s.

jeff
Trevor Saunders Aug. 4, 2014, 5:46 p.m. UTC | #7
On Mon, Aug 04, 2014 at 10:28:26AM -0700, pinskia@gmail.com wrote:
> 
> 
> > On Aug 4, 2014, at 10:15 AM, Trevor Saunders <tsaunders@mozilla.com> wrote:
> > 
> >> On Sat, Aug 02, 2014 at 03:44:17PM -0700, Andrew Pinski wrote:
> >>> On Tue, Jul 29, 2014 at 5:50 AM,  <tsaunders@mozilla.com> wrote:
> >>> From: Trevor Saunders <tsaunders@mozilla.com>
> >>> 
> >>> Hi,
> >>> 
> >>> this adds a hash_set wrapper around hash_table, and then replaces usage of pointer_set with it.
> >>> 
> >>> bootstrapped +regtested on x86_64-unknown-linux-gnu, ok?
> >>> 
> >>> Trev
> >>> 
> >>> ada/
> >>> 
> >>>        * gcc-interface/trans.c: Use hash_set instead of pointer_set.
> >>> 
> >>> c-family/
> >>> 
> >>>        * c-gimplify.c: Use hash_set instead of pointer_set.
> >>> 
> >>> c/
> >>> 
> >>>        * c-decl.c: Use hash_set instead of pointer_set.
> >>> 
> >>> cp/
> >>> 
> >>>        * class.c, cp-gimplify.c, cp-tree.h, decl.c, decl2.c, error.c,
> >>>        method.c, name-lookup.c, pt.c, semantics.c, tree.c: Use hash_set
> >>>        instead of pointer_set.
> >>> 
> >>> fortran/
> >>> 
> >>>        * openmp.c, trans-decl.c: Use hash_set instead of pointer_set.
> >>> 
> >>> gcc/
> >>> 
> >>>        * hash-set.h: new File.
> >>>        * cfgexpand.c, cfgloop.c, cgraph.c, cgraphbuild.c, cgraphunit.c,
> >>>        cprop.c, cse.c, gimple-walk.c, gimple-walk.h, gimplify.c, godump.c,
> >>>        ipa-devirt.c, ipa-pure-const.c, ipa-visibility.c, ipa.c, lto-cgraph.c,
> >>>        lto-streamer-out.c, stmt.c, tree-cfg.c, tree-core.h, tree-eh.c,
> >>>        tree-inline.c, tree-inline.h, tree-nested.c, tree-pretty-print.c,
> >>>        tree-ssa-loop-niter.c, tree-ssa-phiopt.c, tree-ssa-threadedge.c,
> >>>        tree-ssa-uninit.c, tree.c, tree.h, value-prof.c, varasm.c,
> >>>        varpool.c: Use hash_set instead of pointer_set.
> >> 
> >> 
> >> This changelog is less than useful and really does not follow the
> >> GCC/GNU coding style.  Please expand and place all functions which are
> > 
> > I'm pretty sure its written somewhere that format is ok, and there's
> > precedent for it.
> 
> Where? I have seen the opposite in that this format to be used when doing changes like this. I have no quick way to find when a function was changed. 

 git blaim?

> >  Note the update all callers rule could also be used
> > to just write
> > 
> >    (pointer_map_create): Rename to
> >    (hash_set::hash_set): and update all callers.
> 
> This even less useful. 

sure, but valid per
http://www.gnu.org/prep/standards/html_node/Simple-Changes.html#Simple-Changes

> > now I agree its useless, but that's just the nature of something
> > that just summarizes the diff.  it'd be no more useful if it
> > included the headers for diff -p with some regexs to get rid of
> > the line markers.
> > 
> >> changed in it.  I use ChangeLog entries when merging in code to see
> >> which of the merged code I need to pick up.
> > 
> > just use a merge tool that isn't total garbage and let it handle
> > everything but actual conflicts? or failing that just use diff -p that's
> > going to be just about as accurate as what humans can reasonably be expected
> > to produce.
> 
> I had a conflict which is why I noticed this issue in the first place. And I was using git merge :). 

I bet git log or blaim would get you better data faster.

Trev

> 
> Thanks,
> Andrew
> 
> 
> 
> > 
> > Trev
> > 
> >> 
> >> Thanks,
> >> Andrew Pinski
> >> 
> >> 
> >> 
> >>> 
> >>> lto/
> >>> 
> >>>        * lto-partition.c, lto-partition.h: Use hash_set instead of
> >>>        pointer_set.
> >>> diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
> >>> index f42ac7f..6961838 100644
> >>> --- a/gcc/ada/gcc-interface/trans.c
> >>> +++ b/gcc/ada/gcc-interface/trans.c
> >>> @@ -36,7 +36,7 @@
> >>> #include "output.h"
> >>> #include "libfuncs.h"  /* For set_stack_check_libfunc.  */
> >>> #include "tree-iterator.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> #include "gimple-expr.h"
> >>> #include "gimplify.h"
> >>> #include "bitmap.h"
> >>> @@ -3054,7 +3054,7 @@ struct nrv_data
> >>>   bitmap nrv;
> >>>   tree result;
> >>>   Node_Id gnat_ret;
> >>> -  struct pointer_set_t *visited;
> >>> +  hash_set<tree> *visited;
> >>> };
> >>> 
> >>> /* Return true if T is a Named Return Value.  */
> >>> @@ -3188,7 +3188,7 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
> >>>   /* Avoid walking into the same tree more than once.  Unfortunately, we
> >>>      can't just use walk_tree_without_duplicates because it would only
> >>>      call us for the first occurrence of NRVs in the function body.  */
> >>> -  if (pointer_set_insert (dp->visited, *tp))
> >>> +  if (dp->visited->add (*tp))
> >>>     *walk_subtrees = 0;
> >>> 
> >>>   return NULL_TREE;
> >>> @@ -3328,7 +3328,7 @@ finalize_nrv_unc_r (tree *tp, int *walk_subtrees, void *data)
> >>>   /* Avoid walking into the same tree more than once.  Unfortunately, we
> >>>      can't just use walk_tree_without_duplicates because it would only
> >>>      call us for the first occurrence of NRVs in the function body.  */
> >>> -  if (pointer_set_insert (dp->visited, *tp))
> >>> +  if (dp->visited->add (*tp))
> >>>     *walk_subtrees = 0;
> >>> 
> >>>   return NULL_TREE;
> >>> @@ -3376,13 +3376,13 @@ finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret
> >>>   data.nrv = nrv;
> >>>   data.result = DECL_RESULT (fndecl);
> >>>   data.gnat_ret = gnat_ret;
> >>> -  data.visited = pointer_set_create ();
> >>> +  data.visited = new hash_set<tree>;
> >>>   if (TYPE_RETURN_UNCONSTRAINED_P (TREE_TYPE (fndecl)))
> >>>     func = finalize_nrv_unc_r;
> >>>   else
> >>>     func = finalize_nrv_r;
> >>>   walk_tree (&DECL_SAVED_TREE (fndecl), func, &data, NULL);
> >>> -  pointer_set_destroy (data.visited);
> >>> +  delete data.visited;
> >>> }
> >>> 
> >>> /* Return true if RET_VAL can be used as a Named Return Value for the
> >>> diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
> >>> index 2b5ce5b..4898217 100644
> >>> --- a/gcc/c-family/c-gimplify.c
> >>> +++ b/gcc/c-family/c-gimplify.c
> >>> @@ -74,7 +74,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> static tree
> >>> ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
> >>> {
> >>> -  struct pointer_set_t *pset = (struct pointer_set_t *) data;
> >>> +  hash_set<tree> *pset = (hash_set<tree> *) data;
> >>> 
> >>>   /* Since walk_tree doesn't call the callback function on the decls
> >>>      in BIND_EXPR_VARS, we have to walk them manually.  */
> >>> @@ -116,10 +116,9 @@ c_genericize (tree fndecl)
> >>> 
> >>>   if (flag_sanitize & SANITIZE_BOUNDS)
> >>>     {
> >>> -      struct pointer_set_t *pset = pointer_set_create ();
> >>> -      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, pset,
> >>> -                pset);
> >>> -      pointer_set_destroy (pset);
> >>> +      hash_set<tree> pset;
> >>> +      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
> >>> +                &pset);
> >>>     }
> >>> 
> >>>   /* Dump the C-specific tree IR.  */
> >>> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> >>> index 2a4b439..050ddff 100644
> >>> --- a/gcc/c/c-decl.c
> >>> +++ b/gcc/c/c-decl.c
> >>> @@ -59,7 +59,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "cgraph.h"
> >>> #include "hash-table.h"
> >>> #include "langhooks-def.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> #include "plugin.h"
> >>> #include "c-family/c-ada-spec.h"
> >>> #include "cilk.h"
> >>> @@ -7221,17 +7221,17 @@ warn_cxx_compat_finish_struct (tree fieldlist)
> >>>   if (!struct_parse_info->typedefs_seen.is_empty ()
> >>>       && fieldlist != NULL_TREE)
> >>>     {
> >>> -      /* Use a pointer_set using the name of the typedef.  We can use
> >>> -        a pointer_set because identifiers are interned.  */
> >>> -      struct pointer_set_t *tset = pointer_set_create ();
> >>> +      /* Use a hash_set<tree> using the name of the typedef.  We can use
> >>> +        a hash_set<tree> because identifiers are interned.  */
> >>> +      hash_set<tree> tset;
> >>> 
> >>>       FOR_EACH_VEC_ELT (struct_parse_info->typedefs_seen, ix, x)
> >>> -       pointer_set_insert (tset, DECL_NAME (x));
> >>> +       tset.add (DECL_NAME (x));
> >>> 
> >>>       for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
> >>>        {
> >>>          if (DECL_NAME (x) != NULL_TREE
> >>> -             && pointer_set_contains (tset, DECL_NAME (x)))
> >>> +             && tset.contains (DECL_NAME (x)))
> >>>            {
> >>>              warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
> >>>                          ("using %qD as both field and typedef name is "
> >>> @@ -7241,8 +7241,6 @@ warn_cxx_compat_finish_struct (tree fieldlist)
> >>>                 the typedef name is used.  */
> >>>            }
> >>>        }
> >>> -
> >>> -      pointer_set_destroy (tset);
> >>>     }
> >>> 
> >>>   /* For each field which has a binding and which was not defined in
> >>> @@ -8189,7 +8187,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >>>   struct c_binding *b;
> >>>   tree parm, decl, last;
> >>>   tree parmids = arg_info->parms;
> >>> -  struct pointer_set_t *seen_args = pointer_set_create ();
> >>> +  hash_set<tree> seen_args;
> >>> 
> >>>   if (!in_system_header_at (input_location))
> >>>     warning_at (DECL_SOURCE_LOCATION (fndecl),
> >>> @@ -8220,7 +8218,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >>>                      "%qD declared as a non-parameter", decl);
> >>>          /* If the declaration is already marked, we have a duplicate
> >>>             name.  Complain and ignore the duplicate.  */
> >>> -         else if (pointer_set_contains (seen_args, decl))
> >>> +         else if (seen_args.contains (decl))
> >>>            {
> >>>              error_at (DECL_SOURCE_LOCATION (decl),
> >>>                        "multiple parameters named %qD", decl);
> >>> @@ -8269,7 +8267,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >>>        }
> >>> 
> >>>       TREE_PURPOSE (parm) = decl;
> >>> -      pointer_set_insert (seen_args, decl);
> >>> +      seen_args.add (decl);
> >>>     }
> >>> 
> >>>   /* Now examine the parms chain for incomplete declarations
> >>> @@ -8289,7 +8287,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >>>          TREE_TYPE (parm) = error_mark_node;
> >>>        }
> >>> 
> >>> -      if (!pointer_set_contains (seen_args, parm))
> >>> +      if (!seen_args.contains (parm))
> >>>        {
> >>>          error_at (DECL_SOURCE_LOCATION (parm),
> >>>                    "declaration for parameter %qD but no such parameter",
> >>> @@ -8324,8 +8322,6 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
> >>>       DECL_CHAIN (last) = 0;
> >>>     }
> >>> 
> >>> -  pointer_set_destroy (seen_args);
> >>> -
> >>>   /* If there was a previous prototype,
> >>>      set the DECL_ARG_TYPE of each argument according to
> >>>      the type previously specified, and report any mismatches.  */
> >>> diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
> >>> index 2f0ae71..b20be10 100644
> >>> --- a/gcc/cfgexpand.c
> >>> +++ b/gcc/cfgexpand.c
> >>> @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "expr.h"
> >>> #include "langhooks.h"
> >>> #include "bitmap.h"
> >>> +#include "hash-set.h"
> >>> #include "pointer-set.h"
> >>> #include "tree-ssa-alias.h"
> >>> #include "internal-fn.h"
> >>> @@ -594,7 +595,7 @@ stack_var_cmp (const void *a, const void *b)
> >>> static void
> >>> add_partitioned_vars_to_ptset (struct pt_solution *pt,
> >>>                               struct pointer_map_t *decls_to_partitions,
> >>> -                              struct pointer_set_t *visited, bitmap temp)
> >>> +                              hash_set<bitmap> *visited, bitmap temp)
> >>> {
> >>>   bitmap_iterator bi;
> >>>   unsigned i;
> >>> @@ -604,7 +605,7 @@ add_partitioned_vars_to_ptset (struct pt_solution *pt,
> >>>       || pt->vars == NULL
> >>>       /* The pointed-to vars bitmap is shared, it is enough to
> >>>         visit it once.  */
> >>> -      || pointer_set_insert (visited, pt->vars))
> >>> +      || visited->add (pt->vars))
> >>>     return;
> >>> 
> >>>   bitmap_clear (temp);
> >>> @@ -684,7 +685,7 @@ update_alias_info_with_stack_vars (void)
> >>>   if (decls_to_partitions)
> >>>     {
> >>>       unsigned i;
> >>> -      struct pointer_set_t *visited = pointer_set_create ();
> >>> +      hash_set<bitmap> visited;
> >>>       bitmap temp = BITMAP_ALLOC (&stack_var_bitmap_obstack);
> >>> 
> >>>       for (i = 1; i < num_ssa_names; i++)
> >>> @@ -696,13 +697,12 @@ update_alias_info_with_stack_vars (void)
> >>>              && POINTER_TYPE_P (TREE_TYPE (name))
> >>>              && ((pi = SSA_NAME_PTR_INFO (name)) != NULL))
> >>>            add_partitioned_vars_to_ptset (&pi->pt, decls_to_partitions,
> >>> -                                          visited, temp);
> >>> +                                          &visited, temp);
> >>>        }
> >>> 
> >>>       add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped,
> >>> -                                    decls_to_partitions, visited, temp);
> >>> +                                    decls_to_partitions, &visited, temp);
> >>> 
> >>> -      pointer_set_destroy (visited);
> >>>       pointer_map_destroy (decls_to_partitions);
> >>>       BITMAP_FREE (temp);
> >>>     }
> >>> diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
> >>> index 73f79ef..8f7e265 100644
> >>> --- a/gcc/cfgloop.c
> >>> +++ b/gcc/cfgloop.c
> >>> @@ -28,7 +28,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "diagnostic-core.h"
> >>> #include "flags.h"
> >>> #include "tree.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> #include "tree-ssa-alias.h"
> >>> #include "internal-fn.h"
> >>> #include "gimple-expr.h"
> >>> @@ -650,11 +650,11 @@ find_subloop_latch_edge (struct loop *loop)
> >>> /* Callback for make_forwarder_block.  Returns true if the edge E is marked
> >>>    in the set MFB_REIS_SET.  */
> >>> 
> >>> -static struct pointer_set_t *mfb_reis_set;
> >>> +static hash_set<edge> *mfb_reis_set;
> >>> static bool
> >>> mfb_redirect_edges_in_set (edge e)
> >>> {
> >>> -  return pointer_set_contains (mfb_reis_set, e);
> >>> +  return mfb_reis_set->contains (e);
> >>> }
> >>> 
> >>> /* Creates a subloop of LOOP with latch edge LATCH.  */
> >>> @@ -666,15 +666,15 @@ form_subloop (struct loop *loop, edge latch)
> >>>   edge e, new_entry;
> >>>   struct loop *new_loop;
> >>> 
> >>> -  mfb_reis_set = pointer_set_create ();
> >>> +  mfb_reis_set = new hash_set<edge>;
> >>>   FOR_EACH_EDGE (e, ei, loop->header->preds)
> >>>     {
> >>>       if (e != latch)
> >>> -       pointer_set_insert (mfb_reis_set, e);
> >>> +       mfb_reis_set->add (e);
> >>>     }
> >>>   new_entry = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
> >>>                                    NULL);
> >>> -  pointer_set_destroy (mfb_reis_set);
> >>> +  delete mfb_reis_set;
> >>> 
> >>>   loop->header = new_entry->src;
> >>> 
> >>> @@ -705,12 +705,12 @@ merge_latch_edges (struct loop *loop)
> >>>       if (dump_file)
> >>>        fprintf (dump_file, "Merged latch edges of loop %d\n", loop->num);
> >>> 
> >>> -      mfb_reis_set = pointer_set_create ();
> >>> +      mfb_reis_set = new hash_set<edge>;
> >>>       FOR_EACH_VEC_ELT (latches, i, e)
> >>> -       pointer_set_insert (mfb_reis_set, e);
> >>> +       mfb_reis_set->add (e);
> >>>       latch = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
> >>>                                    NULL);
> >>> -      pointer_set_destroy (mfb_reis_set);
> >>> +      delete mfb_reis_set;
> >>> 
> >>>       loop->header = latch->dest;
> >>>       loop->latch = latch->src;
> >>> diff --git a/gcc/cgraph.c b/gcc/cgraph.c
> >>> index a5d0749..7c72399 100644
> >>> --- a/gcc/cgraph.c
> >>> +++ b/gcc/cgraph.c
> >>> @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "tree-inline.h"
> >>> #include "langhooks.h"
> >>> #include "hashtab.h"
> >>> +#include "hash-set.h"
> >>> #include "toplev.h"
> >>> #include "flags.h"
> >>> #include "debug.h"
> >>> @@ -2871,7 +2872,7 @@ cgraph_node::verify_node (void)
> >>>     {
> >>>       if (this_cfun->cfg)
> >>>        {
> >>> -         pointer_set_t *stmts = pointer_set_create ();
> >>> +         hash_set<gimple> stmts;
> >>>          int i;
> >>>          struct ipa_ref *ref = NULL;
> >>> 
> >>> @@ -2881,13 +2882,13 @@ cgraph_node::verify_node (void)
> >>>            {
> >>>              for (gsi = gsi_start_phis (this_block);
> >>>                   !gsi_end_p (gsi); gsi_next (&gsi))
> >>> -               pointer_set_insert (stmts, gsi_stmt (gsi));
> >>> +               stmts.add (gsi_stmt (gsi));
> >>>              for (gsi = gsi_start_bb (this_block);
> >>>                   !gsi_end_p (gsi);
> >>>                   gsi_next (&gsi))
> >>>                {
> >>>                  gimple stmt = gsi_stmt (gsi);
> >>> -                 pointer_set_insert (stmts, stmt);
> >>> +                 stmts.add (stmt);
> >>>                  if (is_gimple_call (stmt))
> >>>                    {
> >>>                      struct cgraph_edge *e = get_edge (stmt);
> >>> @@ -2931,13 +2932,12 @@ cgraph_node::verify_node (void)
> >>>                }
> >>>              }
> >>>            for (i = 0; iterate_reference (i, ref); i++)
> >>> -             if (ref->stmt && !pointer_set_contains (stmts, ref->stmt))
> >>> +             if (ref->stmt && !stmts.contains (ref->stmt))
> >>>                {
> >>>                  error ("reference to dead statement");
> >>>                  cgraph_debug_gimple_stmt (this_cfun, ref->stmt);
> >>>                  error_found = true;
> >>>                }
> >>> -           pointer_set_destroy (stmts);
> >>>        }
> >>>       else
> >>>        /* No CFG available?!  */
> >>> diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
> >>> index 91811d7..a04958f 100644
> >>> --- a/gcc/cgraphbuild.c
> >>> +++ b/gcc/cgraphbuild.c
> >>> @@ -322,7 +322,6 @@ pass_build_cgraph_edges::execute (function *fun)
> >>> {
> >>>   basic_block bb;
> >>>   struct cgraph_node *node = cgraph_node::get (current_function_decl);
> >>> -  struct pointer_set_t *visited_nodes = pointer_set_create ();
> >>>   gimple_stmt_iterator gsi;
> >>>   tree decl;
> >>>   unsigned ix;
> >>> @@ -386,7 +385,6 @@ pass_build_cgraph_edges::execute (function *fun)
> >>>       varpool_node::finalize_decl (decl);
> >>>   record_eh_tables (node, fun);
> >>> 
> >>> -  pointer_set_destroy (visited_nodes);
> >>>   return 0;
> >>> }
> >>> 
> >>> @@ -405,15 +403,14 @@ make_pass_build_cgraph_edges (gcc::context *ctxt)
> >>> void
> >>> record_references_in_initializer (tree decl, bool only_vars)
> >>> {
> >>> -  struct pointer_set_t *visited_nodes = pointer_set_create ();
> >>>   varpool_node *node = varpool_node::get_create (decl);
> >>> +  hash_set<tree> visited_nodes;
> >>>   struct record_reference_ctx ctx = {false, NULL};
> >>> 
> >>>   ctx.varpool_node = node;
> >>>   ctx.only_vars = only_vars;
> >>>   walk_tree (&DECL_INITIAL (decl), record_reference,
> >>> -             &ctx, visited_nodes);
> >>> -  pointer_set_destroy (visited_nodes);
> >>> +             &ctx, &visited_nodes);
> >>> }
> >>> 
> >>> /* Rebuild cgraph edges for current function node.  This needs to be run after
> >>> diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> >>> index 3080b9a..220b953 100644
> >>> --- a/gcc/cgraphunit.c
> >>> +++ b/gcc/cgraphunit.c
> >>> @@ -845,7 +845,7 @@ varpool_node::finalize_decl (tree decl)
> >>>    avoid udplicate work.  */
> >>> 
> >>> static void
> >>> -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> >>> +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
> >>>                               struct cgraph_edge *edge)
> >>> {
> >>>   unsigned int i;
> >>> @@ -855,8 +855,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> >>>     = possible_polymorphic_call_targets
> >>>        (edge, &final, &cache_token);
> >>> 
> >>> -  if (!pointer_set_insert (reachable_call_targets,
> >>> -                          cache_token))
> >>> +  if (!reachable_call_targets->add (cache_token))
> >>>     {
> >>>       if (cgraph_dump_file)
> >>>        dump_possible_polymorphic_call_targets
> >>> @@ -936,7 +935,7 @@ analyze_functions (void)
> >>>   struct cgraph_node *first_handled = first_analyzed;
> >>>   static varpool_node *first_analyzed_var;
> >>>   varpool_node *first_handled_var = first_analyzed_var;
> >>> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> >>> +  hash_set<void *> reachable_call_targets;
> >>> 
> >>>   symtab_node *node;
> >>>   symtab_node *next;
> >>> @@ -1035,7 +1034,7 @@ analyze_functions (void)
> >>>                    {
> >>>                      next = edge->next_callee;
> >>>                      if (edge->indirect_info->polymorphic)
> >>> -                       walk_polymorphic_call_targets (reachable_call_targets,
> >>> +                       walk_polymorphic_call_targets (&reachable_call_targets,
> >>>                                                       edge);
> >>>                    }
> >>>                }
> >>> @@ -1123,7 +1122,6 @@ analyze_functions (void)
> >>>       symtab_node::dump_table (cgraph_dump_file);
> >>>     }
> >>>   bitmap_obstack_release (NULL);
> >>> -  pointer_set_destroy (reachable_call_targets);
> >>>   ggc_collect ();
> >>>   /* Initialize assembler name hash, in particular we want to trigger C++
> >>>      mangling and same body alias creation before we free DECL_ARGUMENTS
> >>> diff --git a/gcc/cp/class.c b/gcc/cp/class.c
> >>> index 0f611e1..d9b34f7 100644
> >>> --- a/gcc/cp/class.c
> >>> +++ b/gcc/cp/class.c
> >>> @@ -5359,15 +5359,15 @@ finalize_literal_type_property (tree t)
> >>> void
> >>> explain_non_literal_class (tree t)
> >>> {
> >>> -  static struct pointer_set_t *diagnosed;
> >>> +  static hash_set<tree> *diagnosed;
> >>> 
> >>>   if (!CLASS_TYPE_P (t))
> >>>     return;
> >>>   t = TYPE_MAIN_VARIANT (t);
> >>> 
> >>>   if (diagnosed == NULL)
> >>> -    diagnosed = pointer_set_create ();
> >>> -  if (pointer_set_insert (diagnosed, t) != 0)
> >>> +    diagnosed = new hash_set<tree>;
> >>> +  if (diagnosed->add (t))
> >>>     /* Already explained.  */
> >>>     return;
> >>> 
> >>> diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
> >>> index a35177b..3cfcbc6 100644
> >>> --- a/gcc/cp/cp-gimplify.c
> >>> +++ b/gcc/cp/cp-gimplify.c
> >>> @@ -871,7 +871,7 @@ omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
> >>> 
> >>> struct cp_genericize_data
> >>> {
> >>> -  struct pointer_set_t *p_set;
> >>> +  hash_set<tree> *p_set;
> >>>   vec<tree> bind_expr_stack;
> >>>   struct cp_genericize_omp_taskreg *omp_ctx;
> >>> };
> >>> @@ -884,7 +884,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
> >>> {
> >>>   tree stmt = *stmt_p;
> >>>   struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
> >>> -  struct pointer_set_t *p_set = wtd->p_set;
> >>> +  hash_set<tree> *p_set = wtd->p_set;
> >>> 
> >>>   /* If in an OpenMP context, note var uses.  */
> >>>   if (__builtin_expect (wtd->omp_ctx != NULL, 0)
> >>> @@ -924,7 +924,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
> >>>     }
> >>> 
> >>>   /* Other than invisiref parms, don't walk the same tree twice.  */
> >>> -  if (pointer_set_contains (p_set, stmt))
> >>> +  if (p_set->contains (stmt))
> >>>     {
> >>>       *walk_subtrees = 0;
> >>>       return NULL_TREE;
> >>> @@ -1199,7 +1199,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
> >>>       return NULL;
> >>>     }
> >>> 
> >>> -  pointer_set_insert (p_set, *stmt_p);
> >>> +  p_set->add (*stmt_p);
> >>> 
> >>>   return NULL;
> >>> }
> >>> @@ -1211,11 +1211,11 @@ cp_genericize_tree (tree* t_p)
> >>> {
> >>>   struct cp_genericize_data wtd;
> >>> 
> >>> -  wtd.p_set = pointer_set_create ();
> >>> +  wtd.p_set = new hash_set<tree>;
> >>>   wtd.bind_expr_stack.create (0);
> >>>   wtd.omp_ctx = NULL;
> >>>   cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
> >>> -  pointer_set_destroy (wtd.p_set);
> >>> +  delete wtd.p_set;
> >>>   wtd.bind_expr_stack.release ();
> >>> }
> >>> 
> >>> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> >>> index 0c0d804..622de9c 100644
> >>> --- a/gcc/cp/cp-tree.h
> >>> +++ b/gcc/cp/cp-tree.h
> >>> @@ -6028,7 +6028,7 @@ extern void verify_stmt_tree                      (tree);
> >>> extern linkage_kind decl_linkage               (tree);
> >>> extern duration_kind decl_storage_duration     (tree);
> >>> extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
> >>> -                             void*, struct pointer_set_t*);
> >>> +                             void*, hash_set<tree> *);
> >>> #define cp_walk_tree(tp,func,data,pset) \
> >>>        walk_tree_1 (tp, func, data, pset, cp_walk_subtrees)
> >>> #define cp_walk_tree_without_duplicates(tp,func,data) \
> >>> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> >>> index aafb917..f70684f 100644
> >>> --- a/gcc/cp/decl.c
> >>> +++ b/gcc/cp/decl.c
> >>> @@ -8198,7 +8198,7 @@ check_static_variable_definition (tree decl, tree type)
> >>> static tree
> >>> stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
> >>> {
> >>> -  struct pointer_set_t *pset = (struct pointer_set_t *)data;
> >>> +  hash_set<tree> *pset = (hash_set<tree> *)data;
> >>>   tree expr = *expr_p;
> >>>   if (TREE_CODE (expr) == SAVE_EXPR)
> >>>     {
> >>> @@ -8218,10 +8218,9 @@ stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
> >>> static void
> >>> stabilize_vla_size (tree size)
> >>> {
> >>> -  struct pointer_set_t *pset = pointer_set_create ();
> >>> +  hash_set<tree> pset;
> >>>   /* Break out any function calls into temporary variables.  */
> >>> -  cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
> >>> -  pointer_set_destroy (pset);
> >>> +  cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
> >>> }
> >>> 
> >>> /* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
> >>> diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
> >>> index 8fa3145..d79665e 100644
> >>> --- a/gcc/cp/decl2.c
> >>> +++ b/gcc/cp/decl2.c
> >>> @@ -3938,11 +3938,11 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
> >>>    supported, collect and return all the functions for which we should
> >>>    emit a hidden alias.  */
> >>> 
> >>> -static struct pointer_set_t *
> >>> +static hash_set<tree> *
> >>> collect_candidates_for_java_method_aliases (void)
> >>> {
> >>>   struct cgraph_node *node;
> >>> -  struct pointer_set_t *candidates = NULL;
> >>> +  hash_set<tree> *candidates = NULL;
> >>> 
> >>> #ifndef HAVE_GAS_HIDDEN
> >>>   return candidates;
> >>> @@ -3957,8 +3957,8 @@ collect_candidates_for_java_method_aliases (void)
> >>>          && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
> >>>        {
> >>>          if (candidates == NULL)
> >>> -           candidates = pointer_set_create ();
> >>> -         pointer_set_insert (candidates, fndecl);
> >>> +           candidates = new hash_set<tree>;
> >>> +         candidates->add (fndecl);
> >>>        }
> >>>     }
> >>> 
> >>> @@ -3973,7 +3973,7 @@ collect_candidates_for_java_method_aliases (void)
> >>>    by collect_candidates_for_java_method_aliases.  */
> >>> 
> >>> static void
> >>> -build_java_method_aliases (struct pointer_set_t *candidates)
> >>> +build_java_method_aliases (hash_set<tree> *candidates)
> >>> {
> >>>   struct cgraph_node *node;
> >>> 
> >>> @@ -3986,7 +3986,7 @@ build_java_method_aliases (struct pointer_set_t *candidates)
> >>>       tree fndecl = node->decl;
> >>> 
> >>>       if (TREE_ASM_WRITTEN (fndecl)
> >>> -         && pointer_set_contains (candidates, fndecl))
> >>> +         && candidates->contains (fndecl))
> >>>        {
> >>>          /* Mangle the name in a predictable way; we need to reference
> >>>             this from a java compiled object file.  */
> >>> @@ -4296,7 +4296,7 @@ cp_write_global_declarations (void)
> >>>   unsigned ssdf_count = 0;
> >>>   int retries = 0;
> >>>   tree decl;
> >>> -  struct pointer_set_t *candidates;
> >>> +  hash_set<tree> *candidates;
> >>> 
> >>>   locus = input_location;
> >>>   at_eof = 1;
> >>> @@ -4713,7 +4713,7 @@ cp_write_global_declarations (void)
> >>>   if (candidates)
> >>>     {
> >>>       build_java_method_aliases (candidates);
> >>> -      pointer_set_destroy (candidates);
> >>> +      delete candidates;
> >>>     }
> >>> 
> >>>   finish_repo ();
> >>> diff --git a/gcc/cp/error.c b/gcc/cp/error.c
> >>> index fa3bdc4..c8987ee 100644
> >>> --- a/gcc/cp/error.c
> >>> +++ b/gcc/cp/error.c
> >>> @@ -1325,7 +1325,7 @@ dump_template_decl (cxx_pretty_printer *pp, tree t, int flags)
> >>> 
> >>> struct find_typenames_t
> >>> {
> >>> -  struct pointer_set_t *p_set;
> >>> +  hash_set<tree> *p_set;
> >>>   vec<tree, va_gc> *typenames;
> >>> };
> >>> 
> >>> @@ -1351,7 +1351,7 @@ find_typenames_r (tree *tp, int *walk_subtrees, void *data)
> >>>       return NULL_TREE;
> >>>     }
> >>> 
> >>> -  if (mv && (mv == *tp || !pointer_set_insert (d->p_set, mv)))
> >>> +  if (mv && (mv == *tp || !d->p_set->add (mv)))
> >>>     vec_safe_push (d->typenames, mv);
> >>> 
> >>>   /* Search into class template arguments, which cp_walk_subtrees
> >>> @@ -1367,11 +1367,11 @@ static vec<tree, va_gc> *
> >>> find_typenames (tree t)
> >>> {
> >>>   struct find_typenames_t ft;
> >>> -  ft.p_set = pointer_set_create ();
> >>> +  ft.p_set = new hash_set<tree>;
> >>>   ft.typenames = NULL;
> >>>   cp_walk_tree (&TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
> >>>                find_typenames_r, &ft, ft.p_set);
> >>> -  pointer_set_destroy (ft.p_set);
> >>> +  delete ft.p_set;
> >>>   return ft.typenames;
> >>> }
> >>> 
> >>> diff --git a/gcc/cp/method.c b/gcc/cp/method.c
> >>> index e5fa0c1..65c5621 100644
> >>> --- a/gcc/cp/method.c
> >>> +++ b/gcc/cp/method.c
> >>> @@ -1480,7 +1480,7 @@ maybe_explain_implicit_delete (tree decl)
> >>>   if (DECL_DEFAULTED_FN (decl))
> >>>     {
> >>>       /* Not marked GTY; it doesn't need to be GC'd or written to PCH.  */
> >>> -      static struct pointer_set_t *explained;
> >>> +      static hash_set<tree> *explained;
> >>> 
> >>>       special_function_kind sfk;
> >>>       location_t loc;
> >>> @@ -1488,8 +1488,8 @@ maybe_explain_implicit_delete (tree decl)
> >>>       tree ctype;
> >>> 
> >>>       if (!explained)
> >>> -       explained = pointer_set_create ();
> >>> -      if (pointer_set_insert (explained, decl))
> >>> +       explained = new hash_set<tree>;
> >>> +      if (explained->add (decl))
> >>>        return true;
> >>> 
> >>>       sfk = special_function_p (decl);
> >>> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> >>> index 75b46ac..6e779a6 100644
> >>> --- a/gcc/cp/name-lookup.c
> >>> +++ b/gcc/cp/name-lookup.c
> >>> @@ -35,7 +35,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "debug.h"
> >>> #include "c-family/c-pragma.h"
> >>> #include "params.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> 
> >>> /* The bindings for a particular name in a particular scope.  */
> >>> 
> >>> @@ -5152,7 +5152,7 @@ struct arg_lookup
> >>>   vec<tree, va_gc> *namespaces;
> >>>   vec<tree, va_gc> *classes;
> >>>   tree functions;
> >>> -  struct pointer_set_t *fn_set;
> >>> +  hash_set<tree> *fn_set;
> >>> };
> >>> 
> >>> static bool arg_assoc (struct arg_lookup*, tree);
> >>> @@ -5175,7 +5175,7 @@ add_function (struct arg_lookup *k, tree fn)
> >>>   if (!is_overloaded_fn (fn))
> >>>     /* All names except those of (possibly overloaded) functions and
> >>>        function templates are ignored.  */;
> >>> -  else if (k->fn_set && pointer_set_insert (k->fn_set, fn))
> >>> +  else if (k->fn_set && k->fn_set->add (fn))
> >>>     /* It's already in the list.  */;
> >>>   else if (!k->functions)
> >>>     k->functions = fn;
> >>> @@ -5639,9 +5639,9 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
> >>>       /* We shouldn't be here if lookup found something other than
> >>>         namespace-scope functions.  */
> >>>       gcc_assert (DECL_NAMESPACE_SCOPE_P (OVL_CURRENT (fns)));
> >>> -      k.fn_set = pointer_set_create ();
> >>> +      k.fn_set = new hash_set<tree>;
> >>>       for (ovl = fns; ovl; ovl = OVL_NEXT (ovl))
> >>> -       pointer_set_insert (k.fn_set, OVL_CURRENT (ovl));
> >>> +       k.fn_set->add (OVL_CURRENT (ovl));
> >>>     }
> >>>   else
> >>>     k.fn_set = NULL;
> >>> @@ -5661,8 +5661,7 @@ lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
> >>> 
> >>>   release_tree_vector (k.classes);
> >>>   release_tree_vector (k.namespaces);
> >>> -  if (k.fn_set)
> >>> -    pointer_set_destroy (k.fn_set);
> >>> +  delete k.fn_set;
> >>> 
> >>>   return fns;
> >>> }
> >>> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> >>> index b32cf6c..9b156f5 100644
> >>> --- a/gcc/cp/pt.c
> >>> +++ b/gcc/cp/pt.c
> >>> @@ -147,7 +147,7 @@ static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
> >>> static tree convert_template_argument (tree, tree, tree,
> >>>                                       tsubst_flags_t, int, tree);
> >>> static int for_each_template_parm (tree, tree_fn_t, void*,
> >>> -                                  struct pointer_set_t*, bool);
> >>> +                                  hash_set<tree> *, bool);
> >>> static tree expand_template_argument_pack (tree);
> >>> static tree build_template_parm_index (int, int, int, tree, tree);
> >>> static bool inline_needs_template_parms (tree, bool);
> >>> @@ -3080,7 +3080,7 @@ struct find_parameter_pack_data
> >>>   tree* parameter_packs;
> >>> 
> >>>   /* Set of AST nodes that have been visited by the traversal.  */
> >>> -  struct pointer_set_t *visited;
> >>> +  hash_set<tree> *visited;
> >>> };
> >>> 
> >>> /* Identifies all of the argument packs that occur in a template
> >>> @@ -3243,9 +3243,9 @@ uses_parameter_packs (tree t)
> >>>   tree parameter_packs = NULL_TREE;
> >>>   struct find_parameter_pack_data ppd;
> >>>   ppd.parameter_packs = &parameter_packs;
> >>> -  ppd.visited = pointer_set_create ();
> >>> +  ppd.visited = new hash_set<tree>;
> >>>   cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
> >>> -  pointer_set_destroy (ppd.visited);
> >>> +  delete ppd.visited;
> >>>   return parameter_packs != NULL_TREE;
> >>> }
> >>> 
> >>> @@ -3292,7 +3292,7 @@ make_pack_expansion (tree arg)
> >>> 
> >>>       /* Determine which parameter packs will be used by the base
> >>>          class expansion.  */
> >>> -      ppd.visited = pointer_set_create ();
> >>> +      ppd.visited = new hash_set<tree>;
> >>>       ppd.parameter_packs = &parameter_packs;
> >>>       cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
> >>>                     &ppd, ppd.visited);
> >>> @@ -3300,7 +3300,7 @@ make_pack_expansion (tree arg)
> >>>       if (parameter_packs == NULL_TREE)
> >>>         {
> >>>           error ("base initializer expansion %<%T%> contains no parameter packs", arg);
> >>> -          pointer_set_destroy (ppd.visited);
> >>> +          delete ppd.visited;
> >>>           return error_mark_node;
> >>>         }
> >>> 
> >>> @@ -3317,7 +3317,7 @@ make_pack_expansion (tree arg)
> >>>             }
> >>>         }
> >>> 
> >>> -      pointer_set_destroy (ppd.visited);
> >>> +      delete ppd.visited;
> >>> 
> >>>       /* Create the pack expansion type for the base type.  */
> >>>       purpose = cxx_make_type (TYPE_PACK_EXPANSION);
> >>> @@ -3352,9 +3352,9 @@ make_pack_expansion (tree arg)
> >>> 
> >>>   /* Determine which parameter packs will be expanded.  */
> >>>   ppd.parameter_packs = &parameter_packs;
> >>> -  ppd.visited = pointer_set_create ();
> >>> +  ppd.visited = new hash_set<tree>;
> >>>   cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
> >>> -  pointer_set_destroy (ppd.visited);
> >>> +  delete ppd.visited;
> >>> 
> >>>   /* Make sure we found some parameter packs.  */
> >>>   if (parameter_packs == NULL_TREE)
> >>> @@ -3399,9 +3399,9 @@ check_for_bare_parameter_packs (tree t)
> >>>     t = TREE_TYPE (t);
> >>> 
> >>>   ppd.parameter_packs = &parameter_packs;
> >>> -  ppd.visited = pointer_set_create ();
> >>> +  ppd.visited = new hash_set<tree>;
> >>>   cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
> >>> -  pointer_set_destroy (ppd.visited);
> >>> +  delete ppd.visited;
> >>> 
> >>>   if (parameter_packs)
> >>>     {
> >>> @@ -4381,11 +4381,11 @@ fixed_parameter_pack_p (tree parm)
> >>>   tree parameter_packs = NULL_TREE;
> >>>   struct find_parameter_pack_data ppd;
> >>>   ppd.parameter_packs = &parameter_packs;
> >>> -  ppd.visited = pointer_set_create ();
> >>> +  ppd.visited = new hash_set<tree>;
> >>> 
> >>>   fixed_parameter_pack_p_1 (parm, &ppd);
> >>> 
> >>> -  pointer_set_destroy (ppd.visited);
> >>> +  delete ppd.visited;
> >>>   return parameter_packs;
> >>> }
> >>> 
> >>> @@ -7907,7 +7907,7 @@ struct pair_fn_data
> >>>   /* True when we should also visit template parameters that occur in
> >>>      non-deduced contexts.  */
> >>>   bool include_nondeduced_p;
> >>> -  struct pointer_set_t *visited;
> >>> +  hash_set<tree> *visited;
> >>> };
> >>> 
> >>> /* Called from for_each_template_parm via walk_tree.  */
> >>> @@ -8107,7 +8107,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
> >>> 
> >>> static int
> >>> for_each_template_parm (tree t, tree_fn_t fn, void* data,
> >>> -                       struct pointer_set_t *visited,
> >>> +                       hash_set<tree> *visited,
> >>>                        bool include_nondeduced_p)
> >>> {
> >>>   struct pair_fn_data pfd;
> >>> @@ -8126,7 +8126,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
> >>>   if (visited)
> >>>     pfd.visited = visited;
> >>>   else
> >>> -    pfd.visited = pointer_set_create ();
> >>> +    pfd.visited = new hash_set<tree>;
> >>>   result = cp_walk_tree (&t,
> >>>                         for_each_template_parm_r,
> >>>                         &pfd,
> >>> @@ -8135,7 +8135,7 @@ for_each_template_parm (tree t, tree_fn_t fn, void* data,
> >>>   /* Clean up.  */
> >>>   if (!visited)
> >>>     {
> >>> -      pointer_set_destroy (pfd.visited);
> >>> +      delete pfd.visited;
> >>>       pfd.visited = 0;
> >>>     }
> >>> 
> >>> diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
> >>> index c87764d..735284e 100644
> >>> --- a/gcc/cp/semantics.c
> >>> +++ b/gcc/cp/semantics.c
> >>> @@ -8031,7 +8031,7 @@ register_constexpr_fundef (tree fun, tree body)
> >>> void
> >>> explain_invalid_constexpr_fn (tree fun)
> >>> {
> >>> -  static struct pointer_set_t *diagnosed;
> >>> +  static hash_set<tree> *diagnosed;
> >>>   tree body;
> >>>   location_t save_loc;
> >>>   /* Only diagnose defaulted functions or instantiations.  */
> >>> @@ -8039,8 +8039,8 @@ explain_invalid_constexpr_fn (tree fun)
> >>>       && !is_instantiation_of_constexpr (fun))
> >>>     return;
> >>>   if (diagnosed == NULL)
> >>> -    diagnosed = pointer_set_create ();
> >>> -  if (pointer_set_insert (diagnosed, fun) != 0)
> >>> +    diagnosed = new hash_set<tree>;
> >>> +  if (diagnosed->add (fun))
> >>>     /* Already explained.  */
> >>>     return;
> >>> 
> >>> diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
> >>> index f6c5693..697a02b 100644
> >>> --- a/gcc/cp/tree.c
> >>> +++ b/gcc/cp/tree.c
> >>> @@ -3485,7 +3485,7 @@ cxx_type_hash_eq (const_tree typea, const_tree typeb)
> >>> 
> >>> tree
> >>> cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
> >>> -                 void *data, struct pointer_set_t *pset)
> >>> +                 void *data, hash_set<tree> *pset)
> >>> {
> >>>   enum tree_code code = TREE_CODE (*tp);
> >>>   tree result;
> >>> diff --git a/gcc/cprop.c b/gcc/cprop.c
> >>> index 6291c91..4234afa 100644
> >>> --- a/gcc/cprop.c
> >>> +++ b/gcc/cprop.c
> >>> @@ -167,7 +167,7 @@ reg_available_p (const_rtx x, const_rtx insn ATTRIBUTE_UNUSED)
> >>>    ??? May need to make things more elaborate.  Later, as necessary.  */
> >>> 
> >>> static unsigned int
> >>> -hash_set (int regno, int hash_table_size)
> >>> +hash_mod (int regno, int hash_table_size)
> >>> {
> >>>   return (unsigned) regno % hash_table_size;
> >>> }
> >>> @@ -187,7 +187,7 @@ insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table,
> >>>   struct expr *cur_expr, *last_expr = NULL;
> >>>   struct occr *cur_occr;
> >>> 
> >>> -  hash = hash_set (REGNO (dest), table->size);
> >>> +  hash = hash_mod (REGNO (dest), table->size);
> >>> 
> >>>   for (cur_expr = table->table[hash]; cur_expr;
> >>>        cur_expr = cur_expr->next_same_hash)
> >>> @@ -483,7 +483,7 @@ compute_hash_table (struct hash_table_d *table)
> >>> static struct expr *
> >>> lookup_set (unsigned int regno, struct hash_table_d *table)
> >>> {
> >>> -  unsigned int hash = hash_set (regno, table->size);
> >>> +  unsigned int hash = hash_mod (regno, table->size);
> >>>   struct expr *expr;
> >>> 
> >>>   expr = table->table[hash];
> >>> diff --git a/gcc/cse.c b/gcc/cse.c
> >>> index 34f9364..dd9a076 100644
> >>> --- a/gcc/cse.c
> >>> +++ b/gcc/cse.c
> >>> @@ -41,7 +41,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "tree-pass.h"
> >>> #include "df.h"
> >>> #include "dbgcnt.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> 
> >>> /* The basic idea of common subexpression elimination is to go
> >>>    through the code, keeping a record of expressions that would
> >>> @@ -2906,7 +2906,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >>>                      enum machine_mode *pmode1, enum machine_mode *pmode2)
> >>> {
> >>>   rtx arg1, arg2;
> >>> -  struct pointer_set_t *visited = NULL;
> >>> +  hash_set<rtx> *visited = NULL;
> >>>   /* Set nonzero when we find something of interest.  */
> >>>   rtx x = NULL;
> >>> 
> >>> @@ -2923,8 +2923,8 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >>>       if (x)
> >>>        {
> >>>          if (!visited)
> >>> -           visited = pointer_set_create ();
> >>> -         pointer_set_insert (visited, x);
> >>> +           visited = new hash_set<rtx>;
> >>> +         visited->add (x);
> >>>          x = 0;
> >>>        }
> >>> 
> >>> @@ -3005,7 +3005,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >>>            continue;
> >>> 
> >>>          /* If it's a comparison we've used before, skip it.  */
> >>> -         if (visited && pointer_set_contains (visited, p->exp))
> >>> +         if (visited && visited->contains (p->exp))
> >>>            continue;
> >>> 
> >>>          if (GET_CODE (p->exp) == COMPARE
> >>> @@ -3087,7 +3087,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
> >>>   *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0);
> >>> 
> >>>   if (visited)
> >>> -    pointer_set_destroy (visited);
> >>> +    delete visited;
> >>>   return code;
> >>> }
> >>> 
> >>> diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
> >>> index 68ba70f..410efb1 100644
> >>> --- a/gcc/fortran/openmp.c
> >>> +++ b/gcc/fortran/openmp.c
> >>> @@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "arith.h"
> >>> #include "match.h"
> >>> #include "parse.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> 
> >>> /* Match an end of OpenMP directive.  End of OpenMP directive is optional
> >>>    whitespace, followed by '\n' or comment '!'.  */
> >>> @@ -3013,8 +3013,8 @@ resolve_omp_atomic (gfc_code *code)
> >>> struct omp_context
> >>> {
> >>>   gfc_code *code;
> >>> -  struct pointer_set_t *sharing_clauses;
> >>> -  struct pointer_set_t *private_iterators;
> >>> +  hash_set<gfc_symbol *> *sharing_clauses;
> >>> +  hash_set<gfc_symbol *> *private_iterators;
> >>>   struct omp_context *previous;
> >>> } *omp_current_ctx;
> >>> static gfc_code *omp_current_do_code;
> >>> @@ -3057,8 +3057,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
> >>>   int list;
> >>> 
> >>>   ctx.code = code;
> >>> -  ctx.sharing_clauses = pointer_set_create ();
> >>> -  ctx.private_iterators = pointer_set_create ();
> >>> +  ctx.sharing_clauses = new hash_set<gfc_symbol *>;
> >>> +  ctx.private_iterators = new hash_set<gfc_symbol *>;
> >>>   ctx.previous = omp_current_ctx;
> >>>   omp_current_ctx = &ctx;
> >>> 
> >>> @@ -3072,7 +3072,7 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
> >>>       case OMP_LIST_REDUCTION:
> >>>       case OMP_LIST_LINEAR:
> >>>        for (n = omp_clauses->lists[list]; n; n = n->next)
> >>> -         pointer_set_insert (ctx.sharing_clauses, n->sym);
> >>> +         ctx.sharing_clauses->add (n->sym);
> >>>        break;
> >>>       default:
> >>>        break;
> >>> @@ -3097,8 +3097,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
> >>>     }
> >>> 
> >>>   omp_current_ctx = ctx.previous;
> >>> -  pointer_set_destroy (ctx.sharing_clauses);
> >>> -  pointer_set_destroy (ctx.private_iterators);
> >>> +  delete ctx.sharing_clauses;
> >>> +  delete ctx.private_iterators;
> >>> }
> >>> 
> >>> 
> >>> @@ -3154,10 +3154,10 @@ gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym)
> >>>   if (omp_current_ctx == NULL)
> >>>     return;
> >>> 
> >>> -  if (pointer_set_contains (omp_current_ctx->sharing_clauses, sym))
> >>> +  if (omp_current_ctx->sharing_clauses->contains (sym))
> >>>     return;
> >>> 
> >>> -  if (! pointer_set_insert (omp_current_ctx->private_iterators, sym))
> >>> +  if (! omp_current_ctx->private_iterators->add (sym))
> >>>     {
> >>>       gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
> >>>       gfc_omp_namelist *p;
> >>> diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
> >>> index 8b56151..babe48f 100644
> >>> --- a/gcc/fortran/trans-decl.c
> >>> +++ b/gcc/fortran/trans-decl.c
> >>> @@ -40,7 +40,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "cgraph.h"
> >>> #include "debug.h"
> >>> #include "gfortran.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> #include "constructor.h"
> >>> #include "trans.h"
> >>> #include "trans-types.h"
> >>> @@ -63,7 +63,7 @@ static GTY(()) tree parent_fake_result_decl;
> >>> static GTY(()) tree saved_function_decls;
> >>> static GTY(()) tree saved_parent_function_decls;
> >>> 
> >>> -static struct pointer_set_t *nonlocal_dummy_decl_pset;
> >>> +static hash_set<tree> *nonlocal_dummy_decl_pset;
> >>> static GTY(()) tree nonlocal_dummy_decls;
> >>> 
> >>> /* Holds the variable DECLs that are locals.  */
> >>> @@ -1094,9 +1094,9 @@ gfc_nonlocal_dummy_array_decl (gfc_symbol *sym)
> >>>   tree decl, dummy;
> >>> 
> >>>   if (! nonlocal_dummy_decl_pset)
> >>> -    nonlocal_dummy_decl_pset = pointer_set_create ();
> >>> +    nonlocal_dummy_decl_pset = new hash_set<tree>;
> >>> 
> >>> -  if (pointer_set_insert (nonlocal_dummy_decl_pset, sym->backend_decl))
> >>> +  if (nonlocal_dummy_decl_pset->add (sym->backend_decl))
> >>>     return;
> >>> 
> >>>   dummy = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl);
> >>> @@ -5861,7 +5861,7 @@ gfc_generate_function_code (gfc_namespace * ns)
> >>>     {
> >>>       BLOCK_VARS (DECL_INITIAL (fndecl))
> >>>        = chainon (BLOCK_VARS (DECL_INITIAL (fndecl)), nonlocal_dummy_decls);
> >>> -      pointer_set_destroy (nonlocal_dummy_decl_pset);
> >>> +      delete nonlocal_dummy_decl_pset;
> >>>       nonlocal_dummy_decls = NULL;
> >>>       nonlocal_dummy_decl_pset = NULL;
> >>>     }
> >>> diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
> >>> index b6f0495..f4f6757 100644
> >>> --- a/gcc/gimple-walk.c
> >>> +++ b/gcc/gimple-walk.c
> >>> @@ -180,7 +180,7 @@ tree
> >>> walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
> >>>                struct walk_stmt_info *wi)
> >>> {
> >>> -  struct pointer_set_t *pset = (wi) ? wi->pset : NULL;
> >>> +  hash_set<tree> *pset = (wi) ? wi->pset : NULL;
> >>>   unsigned i;
> >>>   tree ret = NULL_TREE;
> >>> 
> >>> diff --git a/gcc/gimple-walk.h b/gcc/gimple-walk.h
> >>> index 555eb18..5b75fdc 100644
> >>> --- a/gcc/gimple-walk.h
> >>> +++ b/gcc/gimple-walk.h
> >>> @@ -36,7 +36,7 @@ struct walk_stmt_info
> >>>   /* Pointer map used to mark visited tree nodes when calling
> >>>      walk_tree on each operand.  If set to NULL, duplicate tree nodes
> >>>      will be visited more than once.  */
> >>> -  struct pointer_set_t *pset;
> >>> +  hash_set<tree> *pset;
> >>> 
> >>>   /* Operand returned by the callbacks.  This is set when calling
> >>>      walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
> >>> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> >>> index 4ab36d0..c0ae7cc 100644
> >>> --- a/gcc/gimplify.c
> >>> +++ b/gcc/gimplify.c
> >>> @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "coretypes.h"
> >>> #include "tree.h"
> >>> #include "expr.h"
> >>> +#include "hash-set.h"
> >>> #include "pointer-set.h"
> >>> #include "hash-table.h"
> >>> #include "basic-block.h"
> >>> @@ -134,7 +135,7 @@ struct gimplify_omp_ctx
> >>> {
> >>>   struct gimplify_omp_ctx *outer_context;
> >>>   splay_tree variables;
> >>> -  struct pointer_set_t *privatized_types;
> >>> +  hash_set<tree> *privatized_types;
> >>>   location_t location;
> >>>   enum omp_clause_default_kind default_kind;
> >>>   enum omp_region_type region_type;
> >>> @@ -352,7 +353,7 @@ new_omp_context (enum omp_region_type region_type)
> >>>   c = XCNEW (struct gimplify_omp_ctx);
> >>>   c->outer_context = gimplify_omp_ctxp;
> >>>   c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
> >>> -  c->privatized_types = pointer_set_create ();
> >>> +  c->privatized_types = new hash_set<tree>;
> >>>   c->location = input_location;
> >>>   c->region_type = region_type;
> >>>   if ((region_type & ORT_TASK) == 0)
> >>> @@ -369,7 +370,7 @@ static void
> >>> delete_omp_context (struct gimplify_omp_ctx *c)
> >>> {
> >>>   splay_tree_delete (c->variables);
> >>> -  pointer_set_destroy (c->privatized_types);
> >>> +  delete c->privatized_types;
> >>>   XDELETE (c);
> >>> }
> >>> 
> >>> @@ -744,7 +745,7 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
> >>>      copy their subtrees if we can make sure to do it only once.  */
> >>>   if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
> >>>     {
> >>> -      if (data && !pointer_set_insert ((struct pointer_set_t *)data, t))
> >>> +      if (data && !((hash_set<tree> *)data)->add (t))
> >>>        ;
> >>>       else
> >>>        *walk_subtrees = 0;
> >>> @@ -829,15 +830,14 @@ unshare_body (tree fndecl)
> >>>   struct cgraph_node *cgn = cgraph_node::get (fndecl);
> >>>   /* If the language requires deep unsharing, we need a pointer set to make
> >>>      sure we don't repeatedly unshare subtrees of unshareable nodes.  */
> >>> -  struct pointer_set_t *visited
> >>> -    = lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
> >>> +  hash_set<tree> *visited
> >>> +    = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
> >>> 
> >>>   copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
> >>>   copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
> >>>   copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
> >>> 
> >>> -  if (visited)
> >>> -    pointer_set_destroy (visited);
> >>> +  delete visited;
> >>> 
> >>>   if (cgn)
> >>>     for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
> >>> @@ -1733,7 +1733,7 @@ gimplify_conversion (tree *expr_p)
> >>> }
> >>> 
> >>> /* Nonlocal VLAs seen in the current function.  */
> >>> -static struct pointer_set_t *nonlocal_vlas;
> >>> +static hash_set<tree> *nonlocal_vlas;
> >>> 
> >>> /* The VAR_DECLs created for nonlocal VLAs for debug info purposes.  */
> >>> static tree nonlocal_vla_vars;
> >>> @@ -1784,7 +1784,7 @@ gimplify_var_or_parm_decl (tree *expr_p)
> >>>                 && (ctx->region_type == ORT_WORKSHARE
> >>>                     || ctx->region_type == ORT_SIMD))
> >>>            ctx = ctx->outer_context;
> >>> -         if (!ctx && !pointer_set_insert (nonlocal_vlas, decl))
> >>> +         if (!ctx && !nonlocal_vlas->add (decl))
> >>>            {
> >>>              tree copy = copy_node (decl);
> >>> 
> >>> @@ -5463,7 +5463,7 @@ omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
> >>>     return;
> >>>   type = TYPE_MAIN_VARIANT (type);
> >>> 
> >>> -  if (pointer_set_insert (ctx->privatized_types, type))
> >>> +  if (ctx->privatized_types->add (type))
> >>>     return;
> >>> 
> >>>   switch (TREE_CODE (type))
> >>> @@ -8766,7 +8766,7 @@ gimplify_body (tree fndecl, bool do_parms)
> >>> 
> >>>   cgn = cgraph_node::get (fndecl);
> >>>   if (cgn && cgn->origin)
> >>> -    nonlocal_vlas = pointer_set_create ();
> >>> +    nonlocal_vlas = new hash_set<tree>;
> >>> 
> >>>   /* Make sure input_location isn't set to something weird.  */
> >>>   input_location = DECL_SOURCE_LOCATION (fndecl);
> >>> @@ -8830,7 +8830,7 @@ gimplify_body (tree fndecl, bool do_parms)
> >>>                         nonlocal_vla_vars);
> >>>          nonlocal_vla_vars = NULL_TREE;
> >>>        }
> >>> -      pointer_set_destroy (nonlocal_vlas);
> >>> +      delete nonlocal_vlas;
> >>>       nonlocal_vlas = NULL;
> >>>     }
> >>> 
> >>> diff --git a/gcc/godump.c b/gcc/godump.c
> >>> index 2afd7f1..7566f4d 100644
> >>> --- a/gcc/godump.c
> >>> +++ b/gcc/godump.c
> >>> @@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "diagnostic-core.h"
> >>> #include "tree.h"
> >>> #include "ggc.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> #include "obstack.h"
> >>> #include "debug.h"
> >>> #include "wide-int-print.h"
> >>> @@ -525,11 +525,11 @@ go_type_decl (tree decl, int local)
> >>> struct godump_container
> >>> {
> >>>   /* DECLs that we have already seen.  */
> >>> -  struct pointer_set_t *decls_seen;
> >>> +  hash_set<tree> decls_seen;
> >>> 
> >>>   /* Types which may potentially have to be defined as dummy
> >>>      types.  */
> >>> -  struct pointer_set_t *pot_dummy_types;
> >>> +  hash_set<const char *> pot_dummy_types;
> >>> 
> >>>   /* Go keywords.  */
> >>>   htab_t keyword_hash;
> >>> @@ -569,8 +569,8 @@ go_format_type (struct godump_container *container, tree type,
> >>>   ob = &container->type_obstack;
> >>> 
> >>>   if (TYPE_NAME (type) != NULL_TREE
> >>> -      && (pointer_set_contains (container->decls_seen, type)
> >>> -         || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
> >>> +      && (container->decls_seen.contains (type)
> >>> +         || container->decls_seen.contains (TYPE_NAME (type)))
> >>>       && (AGGREGATE_TYPE_P (type)
> >>>          || POINTER_TYPE_P (type)
> >>>          || TREE_CODE (type) == FUNCTION_TYPE))
> >>> @@ -590,7 +590,7 @@ go_format_type (struct godump_container *container, tree type,
> >>>       return ret;
> >>>     }
> >>> 
> >>> -  pointer_set_insert (container->decls_seen, type);
> >>> +  container->decls_seen.add (type);
> >>> 
> >>>   switch (TREE_CODE (type))
> >>>     {
> >>> @@ -697,8 +697,7 @@ go_format_type (struct godump_container *container, tree type,
> >>>             definition.  So this struct or union is a potential dummy
> >>>             type.  */
> >>>          if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
> >>> -           pointer_set_insert (container->pot_dummy_types,
> >>> -                               IDENTIFIER_POINTER (name));
> >>> +           container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
> >>> 
> >>>          return ret;
> >>>         }
> >>> @@ -948,10 +947,10 @@ go_output_typedef (struct godump_container *container, tree decl)
> >>>      separately.  */
> >>>   if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
> >>>       && TYPE_SIZE (TREE_TYPE (decl)) != 0
> >>> -      && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
> >>> +      && !container->decls_seen.contains (TREE_TYPE (decl))
> >>>       && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
> >>> -         || !pointer_set_contains (container->decls_seen,
> >>> -                                   TYPE_CANONICAL (TREE_TYPE (decl)))))
> >>> +         || !container->decls_seen.contains
> >>> +                                   (TYPE_CANONICAL (TREE_TYPE (decl)))))
> >>>     {
> >>>       tree element;
> >>> 
> >>> @@ -988,10 +987,9 @@ go_output_typedef (struct godump_container *container, tree decl)
> >>>          mhval->value = xstrdup (buf);
> >>>          *slot = mhval;
> >>>        }
> >>> -      pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
> >>> +      container->decls_seen.add (TREE_TYPE (decl));
> >>>       if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
> >>> -       pointer_set_insert (container->decls_seen,
> >>> -                           TYPE_CANONICAL (TREE_TYPE (decl)));
> >>> +       container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
> >>>     }
> >>> 
> >>>   if (DECL_NAME (decl) != NULL_TREE)
> >>> @@ -1027,7 +1025,7 @@ go_output_typedef (struct godump_container *container, tree decl)
> >>>                     size);
> >>>        }
> >>> 
> >>> -      pointer_set_insert (container->decls_seen, decl);
> >>> +      container->decls_seen.add (decl);
> >>>     }
> >>>   else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
> >>>     {
> >>> @@ -1072,11 +1070,11 @@ go_output_var (struct godump_container *container, tree decl)
> >>> {
> >>>   bool is_valid;
> >>> 
> >>> -  if (pointer_set_contains (container->decls_seen, decl)
> >>> -      || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
> >>> +  if (container->decls_seen.contains (decl)
> >>> +      || container->decls_seen.contains (DECL_NAME (decl)))
> >>>     return;
> >>> -  pointer_set_insert (container->decls_seen, decl);
> >>> -  pointer_set_insert (container->decls_seen, DECL_NAME (decl));
> >>> +  container->decls_seen.add (decl);
> >>> +  container->decls_seen.add (DECL_NAME (decl));
> >>> 
> >>>   is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
> >>>   if (is_valid
> >>> @@ -1103,11 +1101,10 @@ go_output_var (struct godump_container *container, tree decl)
> >>>     {
> >>>       tree type_name = TYPE_NAME (TREE_TYPE (decl));
> >>>       if (TREE_CODE (type_name) == IDENTIFIER_NODE)
> >>> -       pointer_set_insert (container->pot_dummy_types,
> >>> -                           IDENTIFIER_POINTER (type_name));
> >>> +       container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
> >>>       else if (TREE_CODE (type_name) == TYPE_DECL)
> >>> -       pointer_set_insert (container->pot_dummy_types,
> >>> -                           IDENTIFIER_POINTER (DECL_NAME (type_name)));
> >>> +       container->pot_dummy_types.add
> >>> +                           (IDENTIFIER_POINTER (DECL_NAME (type_name)));
> >>>     }
> >>> }
> >>> 
> >>> @@ -1147,10 +1144,10 @@ keyword_hash_init (struct godump_container *container)
> >>> 
> >>> /* Traversing the pot_dummy_types and seeing which types are present
> >>>    in the global types hash table and creating dummy definitions if
> >>> -   not found.  This function is invoked by pointer_set_traverse.  */
> >>> +   not found.  This function is invoked by hash_set::traverse.  */
> >>> 
> >>> -static bool
> >>> -find_dummy_types (const void *ptr, void *adata)
> >>> +bool
> >>> +find_dummy_types (const char *const &ptr, godump_container *adata)
> >>> {
> >>>   struct godump_container *data = (struct godump_container *) adata;
> >>>   const char *type = (const char *) ptr;
> >>> @@ -1175,8 +1172,6 @@ go_finish (const char *filename)
> >>> 
> >>>   real_debug_hooks->finish (filename);
> >>> 
> >>> -  container.decls_seen = pointer_set_create ();
> >>> -  container.pot_dummy_types = pointer_set_create ();
> >>>   container.type_hash = htab_create (100, htab_hash_string,
> >>>                                      string_hash_eq, NULL);
> >>>   container.invalid_hash = htab_create (10, htab_hash_string,
> >>> @@ -1211,11 +1206,9 @@ go_finish (const char *filename)
> >>>   htab_traverse_noresize (macro_hash, go_print_macro, NULL);
> >>> 
> >>>   /* To emit dummy definitions.  */
> >>> -  pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
> >>> -                        (void *) &container);
> >>> +  container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
> >>> +                        (&container);
> >>> 
> >>> -  pointer_set_destroy (container.decls_seen);
> >>> -  pointer_set_destroy (container.pot_dummy_types);
> >>>   htab_delete (container.type_hash);
> >>>   htab_delete (container.invalid_hash);
> >>>   htab_delete (container.keyword_hash);
> >>> diff --git a/gcc/hash-set.h b/gcc/hash-set.h
> >>> new file mode 100644
> >>> index 0000000..47bae9e
> >>> --- /dev/null
> >>> +++ b/gcc/hash-set.h
> >>> @@ -0,0 +1,173 @@
> >>> +/* A type-safe hash set.
> >>> +   Copyright (C) 2014 Free Software Foundation, Inc.
> >>> +
> >>> +This file is part of GCC.
> >>> +
> >>> +GCC is free software; you can redistribute it and/or modify it under
> >>> +the terms of the GNU General Public License as published by the Free
> >>> +Software Foundation; either version 3, or (at your option) any later
> >>> +version.
> >>> +
> >>> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> >>> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> >>> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> >>> +for more details.
> >>> +
> >>> +You should have received a copy of the GNU General Public License
> >>> +along with GCC; see the file COPYING3.  If not see
> >>> +<http://www.gnu.org/licenses/>.  */
> >>> +
> >>> +
> >>> +#ifndef hash_set_h
> >>> +#define hash_set_h
> >>> +
> >>> +#include "hash-table.h"
> >>> +
> >>> +/* implement default behavior for traits when types allow it.  */
> >>> +
> >>> +struct default_hashset_traits
> >>> +{
> >>> +  /* Hashes the passed in key.  */
> >>> +
> >>> +  template<typename T>
> >>> +  static hashval_t
> >>> +  hash (T *p)
> >>> +    {
> >>> +      return uintptr_t(p) >> 3;
> >>> +    }
> >>> +
> >>> +  template<typename T> static hashval_t hash(const T &v) { return v; }
> >>> +
> >>> +  /* Return true if the two keys passed as arguments are equal.  */
> >>> +
> >>> +  template<typename T>
> >>> +  static bool
> >>> +  equal (const T &a, const T &b)
> >>> +    {
> >>> +      return a == b;
> >>> +    }
> >>> +
> >>> +  /* Called to dispose of the key before marking the entry as deleted.  */
> >>> +
> >>> +  template<typename T> static void remove (T &v) { v.~T (); }
> >>> +
> >>> +  /* Mark the passed in entry as being deleted.  */
> >>> +
> >>> +  template<typename T>
> >>> +  static void
> >>> +  mark_deleted (T *&e)
> >>> +    {
> >>> +      e = reinterpret_cast<void *> (1);
> >>> +    }
> >>> +
> >>> +  /* Mark the passed in entry as being empty.  */
> >>> +
> >>> +  template<typename T>
> >>> +  static void
> >>> +  mark_empty (T *&e)
> >>> +    {
> >>> +      e = NULL;
> >>> +    }
> >>> +
> >>> +  /* Return true if the passed in entry is marked as deleted.  */
> >>> +
> >>> +  template<typename T>
> >>> +  static bool
> >>> +  is_deleted (T *e)
> >>> +    {
> >>> +      return e == reinterpret_cast<void *> (1);
> >>> +    }
> >>> +
> >>> +  /* Return true if the passed in entry is marked as empty.  */
> >>> +
> >>> +  template<typename T> static bool is_empty (T *e) { return e == NULL; }
> >>> +};
> >>> +
> >>> +template<typename Key, typename Traits = default_hashset_traits>
> >>> +class hash_set
> >>> +{
> >>> +  struct hash_entry
> >>> +  {
> >>> +    Key m_key;
> >>> +
> >>> +    typedef hash_entry value_type;
> >>> +    typedef Key compare_type;
> >>> +    typedef int store_values_directly;
> >>> +
> >>> +    static hashval_t hash (const hash_entry &e)
> >>> +      {
> >>> +               return Traits::hash (e.m_key);
> >>> +      }
> >>> +
> >>> +    static bool equal (const hash_entry &a, const Key &b)
> >>> +               {
> >>> +         return Traits::equal (a.m_key, b);
> >>> +               }
> >>> +
> >>> +    static void remove (hash_entry &e) { Traits::remove (e.m_key); }
> >>> +
> >>> +    static void
> >>> +    mark_deleted (hash_entry &e)
> >>> +      {
> >>> +               Traits::mark_deleted (e.m_key);
> >>> +      }
> >>> +
> >>> +    static bool is_deleted (const hash_entry &e)
> >>> +      {
> >>> +               return Traits::is_deleted (e.m_key);
> >>> +      }
> >>> +
> >>> +    static void
> >>> +    mark_empty (hash_entry &e)
> >>> +      {
> >>> +       Traits::mark_empty (e.m_key);
> >>> +      }
> >>> +
> >>> +    static bool
> >>> +    is_empty (const hash_entry &e)
> >>> +      {
> >>> +       return Traits::is_empty (e.m_key);
> >>> +      }
> >>> +  };
> >>> +
> >>> +public:
> >>> +  explicit hash_set (size_t n = 13) : m_table (n) {}
> >>> +
> >>> +  /* If key k isn't already in the map add it to the map, and
> >>> +     return false.  Otherwise return true.  */
> >>> +
> >>> +  bool add (const Key &k)
> >>> +    {
> >>> +      hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
> >>> +                                                  INSERT);
> >>> +      bool existed = !hash_entry::is_empty (*e);
> >>> +      if (!existed)
> >>> +       e->m_key = k;
> >>> +
> >>> +      return existed;
> >>> +    }
> >>> +
> >>> +  /* if the passed in key is in the map return its value otherwise NULL.  */
> >>> +
> >>> +  bool contains (const Key &k)
> >>> +    {
> >>> +      hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
> >>> +      return !Traits::is_empty (e.m_key);
> >>> +    }
> >>> +
> >>> +  /* Call the call back on each pair of key and value with the passed in
> >>> +     arg.  */
> >>> +
> >>> +  template<typename Arg, bool (*f)(const Key &, Arg)>
> >>> +  void traverse (Arg a) const
> >>> +    {
> >>> +      for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
> >>> +          iter != m_table.end (); ++iter)
> >>> +       f ((*iter).m_key, a);
> >>> +    }
> >>> +
> >>> +private:
> >>> +  hash_table<hash_entry> m_table;
> >>> +};
> >>> +
> >>> +#endif
> >>> diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
> >>> index 127d58d..70a70a7 100644
> >>> --- a/gcc/ipa-devirt.c
> >>> +++ b/gcc/ipa-devirt.c
> >>> @@ -115,7 +115,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "cgraph.h"
> >>> #include "expr.h"
> >>> #include "tree-pass.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> #include "target.h"
> >>> #include "hash-table.h"
> >>> #include "inchash.h"
> >>> @@ -134,7 +134,8 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "stor-layout.h"
> >>> #include "intl.h"
> >>> 
> >>> -static bool odr_types_equivalent_p (tree, tree, bool, bool *, pointer_set_t *);
> >>> +static bool odr_types_equivalent_p (tree, tree, bool, bool *,
> >>> +                                   hash_set<tree> *);
> >>> 
> >>> static bool odr_violation_reported = false;
> >>> 
> >>> @@ -144,7 +145,7 @@ const ipa_polymorphic_call_context ipa_dummy_polymorphic_call_context
> >>>    = {0, NULL, false, true};
> >>> 
> >>> /* Pointer set of all call targets appearing in the cache.  */
> >>> -static pointer_set_t *cached_polymorphic_call_targets;
> >>> +static hash_set<cgraph_node *> *cached_polymorphic_call_targets;
> >>> 
> >>> /* The node of type inheritance graph.  For each type unique in
> >>>    One Defintion Rule (ODR) sense, we produce one node linking all
> >>> @@ -163,7 +164,7 @@ struct GTY(()) odr_type_d
> >>>   /* All equivalent types, if more than one.  */
> >>>   vec<tree, va_gc> *types;
> >>>   /* Set of all equivalent types, if NON-NULL.  */
> >>> -  pointer_set_t * GTY((skip)) types_set;
> >>> +  hash_set<tree> * GTY((skip)) types_set;
> >>> 
> >>>   /* Unique ID indexing the type in odr_types array.  */
> >>>   int id;
> >>> @@ -409,7 +410,7 @@ odr_hasher::remove (value_type *v)
> >>>   v->bases.release ();
> >>>   v->derived_types.release ();
> >>>   if (v->types_set)
> >>> -    pointer_set_destroy (v->types_set);
> >>> +    delete v->types_set;
> >>>   ggc_free (v);
> >>> }
> >>> 
> >>> @@ -439,7 +440,7 @@ set_type_binfo (tree type, tree binfo)
> >>> /* Compare T2 and T2 based on name or structure.  */
> >>> 
> >>> static bool
> >>> -odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
> >>> +odr_subtypes_equivalent_p (tree t1, tree t2, hash_set<tree> *visited)
> >>> {
> >>>   bool an1, an2;
> >>> 
> >>> @@ -473,7 +474,7 @@ odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
> >>>       /* This should really be a pair hash, but for the moment we do not need
> >>>         100% reliability and it would be better to compare all ODR types so
> >>>         recursion here is needed only for component types.  */
> >>> -      if (pointer_set_insert (visited, t1))
> >>> +      if (visited->add (t1))
> >>>        return true;
> >>>       return odr_types_equivalent_p (t1, t2, false, NULL, visited);
> >>>     }
> >>> @@ -562,7 +563,7 @@ warn_types_mismatch (tree t1, tree t2)
> >>>    gimple_canonical_types_compatible_p.  */
> >>> 
> >>> static bool
> >>> -odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, pointer_set_t *visited)
> >>> +odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, hash_set<tree> *visited)
> >>> {
> >>>   /* Check first for the obvious case of pointer identity.  */
> >>>   if (t1 == t2)
> >>> @@ -938,7 +939,7 @@ add_type_duplicate (odr_type val, tree type)
> >>> {
> >>>   bool build_bases = false;
> >>>   if (!val->types_set)
> >>> -    val->types_set = pointer_set_create ();
> >>> +    val->types_set = new hash_set<tree>;
> >>> 
> >>>   /* Always prefer complete type to be the leader.  */
> >>>   if (!COMPLETE_TYPE_P (val->type)
> >>> @@ -952,20 +953,20 @@ add_type_duplicate (odr_type val, tree type)
> >>>     }
> >>> 
> >>>   /* See if this duplicate is new.  */
> >>> -  if (!pointer_set_insert (val->types_set, type))
> >>> +  if (!val->types_set->add (type))
> >>>     {
> >>>       bool merge = true;
> >>>       bool base_mismatch = false;
> >>>       unsigned int i,j;
> >>>       bool warned = false;
> >>> -      pointer_set_t *visited = pointer_set_create ();
> >>> +      hash_set<tree> visited;
> >>> 
> >>>       gcc_assert (in_lto_p);
> >>>       vec_safe_push (val->types, type);
> >>> 
> >>>       /* First we compare memory layout.  */
> >>>       if (!odr_types_equivalent_p (val->type, type, !flag_ltrans && !val->odr_violated,
> >>> -                                  &warned, visited))
> >>> +                                  &warned, &visited))
> >>>        {
> >>>          merge = false;
> >>>          odr_violation_reported = true;
> >>> @@ -980,7 +981,6 @@ add_type_duplicate (odr_type val, tree type)
> >>>              putc ('\n',cgraph_dump_file);
> >>>            }
> >>>        }
> >>> -      pointer_set_destroy (visited);
> >>> 
> >>>       /* Next sanity check that bases are the same.  If not, we will end
> >>>         up producing wrong answers.  */
> >>> @@ -1356,7 +1356,7 @@ referenced_from_vtable_p (struct cgraph_node *node)
> >>> 
> >>> static void
> >>> maybe_record_node (vec <cgraph_node *> &nodes,
> >>> -                  tree target, pointer_set_t *inserted,
> >>> +                  tree target, hash_set<tree> *inserted,
> >>>                   bool can_refer,
> >>>                   bool *completep)
> >>> {
> >>> @@ -1422,10 +1422,9 @@ maybe_record_node (vec <cgraph_node *> &nodes,
> >>>     {
> >>>       gcc_assert (!target_node->global.inlined_to);
> >>>       gcc_assert (target_node->real_symbol_p ());
> >>> -      if (!pointer_set_insert (inserted, target_node->decl))
> >>> +      if (!inserted->add (target))
> >>>        {
> >>> -         pointer_set_insert (cached_polymorphic_call_targets,
> >>> -                             target_node);
> >>> +         cached_polymorphic_call_targets->add (target_node);
> >>>          nodes.safe_push (target_node);
> >>>        }
> >>>     }
> >>> @@ -1465,8 +1464,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
> >>>                          HOST_WIDE_INT otr_token,
> >>>                          tree outer_type,
> >>>                          HOST_WIDE_INT offset,
> >>> -                         pointer_set_t *inserted,
> >>> -                         pointer_set_t *matched_vtables,
> >>> +                         hash_set<tree> *inserted,
> >>> +                         hash_set<tree> *matched_vtables,
> >>>                          bool anonymous,
> >>>                          bool *completep)
> >>> {
> >>> @@ -1519,8 +1518,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
> >>>        }
> >>>       gcc_assert (inner_binfo);
> >>>       if (bases_to_consider
> >>> -         ? !pointer_set_contains (matched_vtables, BINFO_VTABLE (inner_binfo))
> >>> -         : !pointer_set_insert (matched_vtables, BINFO_VTABLE (inner_binfo)))
> >>> +         ? !matched_vtables->contains (BINFO_VTABLE (inner_binfo))
> >>> +         : !matched_vtables->add (BINFO_VTABLE (inner_binfo)))
> >>>        {
> >>>          bool can_refer;
> >>>          tree target = gimple_get_virt_method_for_binfo (otr_token,
> >>> @@ -1559,8 +1558,8 @@ record_target_from_binfo (vec <cgraph_node *> &nodes,
> >>> 
> >>> static void
> >>> possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes,
> >>> -                                    pointer_set_t *inserted,
> >>> -                                    pointer_set_t *matched_vtables,
> >>> +                                    hash_set<tree> *inserted,
> >>> +                                    hash_set<tree> *matched_vtables,
> >>>                                     tree otr_type,
> >>>                                     odr_type type,
> >>>                                     HOST_WIDE_INT otr_token,
> >>> @@ -1684,7 +1683,7 @@ free_polymorphic_call_targets_hash ()
> >>>     {
> >>>       delete polymorphic_call_target_hash;
> >>>       polymorphic_call_target_hash = NULL;
> >>> -      pointer_set_destroy (cached_polymorphic_call_targets);
> >>> +      delete cached_polymorphic_call_targets;
> >>>       cached_polymorphic_call_targets = NULL;
> >>>     }
> >>> }
> >>> @@ -1695,7 +1694,7 @@ static void
> >>> devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
> >>> {
> >>>   if (cached_polymorphic_call_targets
> >>> -      && pointer_set_contains (cached_polymorphic_call_targets, n))
> >>> +      && cached_polymorphic_call_targets->contains (n))
> >>>     free_polymorphic_call_targets_hash ();
> >>> }
> >>> 
> >>> @@ -2277,8 +2276,8 @@ record_targets_from_bases (tree otr_type,
> >>>                           tree outer_type,
> >>>                           HOST_WIDE_INT offset,
> >>>                           vec <cgraph_node *> &nodes,
> >>> -                          pointer_set_t *inserted,
> >>> -                          pointer_set_t *matched_vtables,
> >>> +                          hash_set<tree> *inserted,
> >>> +                          hash_set<tree> *matched_vtables,
> >>>                           bool *completep)
> >>> {
> >>>   while (true)
> >>> @@ -2319,7 +2318,7 @@ record_targets_from_bases (tree otr_type,
> >>>          return;
> >>>        }
> >>>       gcc_assert (base_binfo);
> >>> -      if (!pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo)))
> >>> +      if (!matched_vtables->add (BINFO_VTABLE (base_binfo)))
> >>>        {
> >>>          bool can_refer;
> >>>          tree target = gimple_get_virt_method_for_binfo (otr_token,
> >>> @@ -2327,7 +2326,7 @@ record_targets_from_bases (tree otr_type,
> >>>                                                          &can_refer);
> >>>          if (!target || ! DECL_CXX_DESTRUCTOR_P (target))
> >>>            maybe_record_node (nodes, target, inserted, can_refer, completep);
> >>> -         pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo));
> >>> +         matched_vtables->add (BINFO_VTABLE (base_binfo));
> >>>        }
> >>>     }
> >>> }
> >>> @@ -2377,8 +2376,6 @@ possible_polymorphic_call_targets (tree otr_type,
> >>>                                   int *nonconstruction_targetsp)
> >>> {
> >>>   static struct cgraph_node_hook_list *node_removal_hook_holder;
> >>> -  pointer_set_t *inserted;
> >>> -  pointer_set_t *matched_vtables;
> >>>   vec <cgraph_node *> nodes = vNULL;
> >>>   vec <tree> bases_to_consider = vNULL;
> >>>   odr_type type, outer_type;
> >>> @@ -2457,7 +2454,7 @@ possible_polymorphic_call_targets (tree otr_type,
> >>>   /* Initialize query cache.  */
> >>>   if (!cached_polymorphic_call_targets)
> >>>     {
> >>> -      cached_polymorphic_call_targets = pointer_set_create ();
> >>> +      cached_polymorphic_call_targets = new hash_set<cgraph_node *>;
> >>>       polymorphic_call_target_hash
> >>>                = new polymorphic_call_target_hash_type (23);
> >>>       if (!node_removal_hook_holder)
> >>> @@ -2496,8 +2493,8 @@ possible_polymorphic_call_targets (tree otr_type,
> >>>   (*slot)->otr_token = otr_token;
> >>>   (*slot)->context = context;
> >>> 
> >>> -  inserted = pointer_set_create ();
> >>> -  matched_vtables = pointer_set_create ();
> >>> +  hash_set<tree> inserted;
> >>> +  hash_set<tree> matched_vtables;
> >>> 
> >>>   /* First see virtual method of type itself.  */
> >>>   binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type),
> >>> @@ -2526,7 +2523,7 @@ possible_polymorphic_call_targets (tree otr_type,
> >>> 
> >>>   /* If OUTER_TYPE is abstract, we know we are not seeing its instance.  */
> >>>   if (type_possibly_instantiated_p (outer_type->type))
> >>> -    maybe_record_node (nodes, target, inserted, can_refer, &complete);
> >>> +    maybe_record_node (nodes, target, &inserted, can_refer, &complete);
> >>>   else
> >>>     {
> >>>       skipped = true;
> >>> @@ -2534,7 +2531,7 @@ possible_polymorphic_call_targets (tree otr_type,
> >>>     }
> >>> 
> >>>   if (binfo)
> >>> -    pointer_set_insert (matched_vtables, BINFO_VTABLE (binfo));
> >>> +    matched_vtables.add (BINFO_VTABLE (binfo));
> >>> 
> >>>   /* Next walk recursively all derived types.  */
> >>>   if (context.maybe_derived_type)
> >>> @@ -2544,8 +2541,8 @@ possible_polymorphic_call_targets (tree otr_type,
> >>>       if (!type->all_derivations_known)
> >>>        complete = false;
> >>>       for (i = 0; i < outer_type->derived_types.length(); i++)
> >>> -       possible_polymorphic_call_targets_1 (nodes, inserted,
> >>> -                                            matched_vtables,
> >>> +       possible_polymorphic_call_targets_1 (nodes, &inserted,
> >>> +                                            &matched_vtables,
> >>>                                             otr_type,
> >>>                                             outer_type->derived_types[i],
> >>>                                             otr_token, outer_type->type,
> >>> @@ -2571,12 +2568,12 @@ possible_polymorphic_call_targets (tree otr_type,
> >>>              || (context.maybe_derived_type
> >>>                  && !type_all_derivations_known_p (outer_type->type))))
> >>>        record_targets_from_bases (otr_type, otr_token, outer_type->type,
> >>> -                                  context.offset, nodes, inserted,
> >>> -                                  matched_vtables, &complete);
> >>> +                                  context.offset, nodes, &inserted,
> >>> +                                  &matched_vtables, &complete);
> >>>       if (skipped)
> >>> -        maybe_record_node (nodes, target, inserted, can_refer, &complete);
> >>> +        maybe_record_node (nodes, target, &inserted, can_refer, &complete);
> >>>       for (i = 0; i < bases_to_consider.length(); i++)
> >>> -        maybe_record_node (nodes, bases_to_consider[i], inserted, can_refer, &complete);
> >>> +        maybe_record_node (nodes, bases_to_consider[i], &inserted, can_refer, &complete);
> >>>     }
> >>>   bases_to_consider.release();
> >>> 
> >>> @@ -2587,8 +2584,6 @@ possible_polymorphic_call_targets (tree otr_type,
> >>>   if (nonconstruction_targetsp)
> >>>     *nonconstruction_targetsp = (*slot)->nonconstruction_targets;
> >>> 
> >>> -  pointer_set_destroy (inserted);
> >>> -  pointer_set_destroy (matched_vtables);
> >>>   timevar_pop (TV_IPA_VIRTUAL_CALL);
> >>>   return nodes;
> >>> }
> >>> @@ -2744,7 +2739,7 @@ static unsigned int
> >>> ipa_devirt (void)
> >>> {
> >>>   struct cgraph_node *n;
> >>> -  struct pointer_set_t *bad_call_targets = pointer_set_create ();
> >>> +  hash_set<void *> bad_call_targets;
> >>>   struct cgraph_edge *e;
> >>> 
> >>>   int npolymorphic = 0, nspeculated = 0, nconverted = 0, ncold = 0;
> >>> @@ -2792,8 +2787,7 @@ ipa_devirt (void)
> >>>                if (!dump_file)
> >>>                  continue;
> >>>              }
> >>> -           if (pointer_set_contains (bad_call_targets,
> >>> -                                     cache_token))
> >>> +           if (bad_call_targets.contains (cache_token))
> >>>              {
> >>>                if (dump_file)
> >>>                  fprintf (dump_file, "Target list is known to be useless\n\n");
> >>> @@ -2818,7 +2812,7 @@ ipa_devirt (void)
> >>>                }
> >>>            if (!likely_target)
> >>>              {
> >>> -               pointer_set_insert (bad_call_targets, cache_token);
> >>> +               bad_call_targets.add (cache_token);
> >>>                continue;
> >>>              }
> >>>            /* This is reached only when dumping; check if we agree or disagree
> >>> @@ -2905,7 +2899,6 @@ ipa_devirt (void)
> >>>       if (update)
> >>>        inline_update_overall_summary (n);
> >>>     }
> >>> -  pointer_set_destroy (bad_call_targets);
> >>> 
> >>>   if (dump_file)
> >>>     fprintf (dump_file,
> >>> diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
> >>> index 2c281be..b964502 100644
> >>> --- a/gcc/ipa-pure-const.c
> >>> +++ b/gcc/ipa-pure-const.c
> >>> @@ -65,8 +65,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "tree-scalar-evolution.h"
> >>> #include "intl.h"
> >>> #include "opts.h"
> >>> -
> >>> -static struct pointer_set_t *visited_nodes;
> >>> +#include "hash-set.h"
> >>> 
> >>> /* Lattice values for const and pure functions.  Everything starts out
> >>>    being const, then may drop to pure and then neither depending on
> >>> @@ -133,13 +132,13 @@ function_always_visible_to_compiler_p (tree decl)
> >>> 
> >>> /* Emit suggestion about attribute ATTRIB_NAME for DECL.  KNOWN_FINITE
> >>>    is true if the function is known to be finite.  The diagnostic is
> >>> -   controlled by OPTION.  WARNED_ABOUT is a pointer_set unique for
> >>> +   controlled by OPTION.  WARNED_ABOUT is a hash_set<tree> unique for
> >>>    OPTION, this function may initialize it and it is always returned
> >>>    by the function.  */
> >>> 
> >>> -static struct pointer_set_t *
> >>> +static hash_set<tree> *
> >>> suggest_attribute (int option, tree decl, bool known_finite,
> >>> -                  struct pointer_set_t *warned_about,
> >>> +                  hash_set<tree> *warned_about,
> >>>                   const char * attrib_name)
> >>> {
> >>>   if (!option_enabled (option, &global_options))
> >>> @@ -149,10 +148,10 @@ suggest_attribute (int option, tree decl, bool known_finite,
> >>>     return warned_about;
> >>> 
> >>>   if (!warned_about)
> >>> -    warned_about = pointer_set_create ();
> >>> -  if (pointer_set_contains (warned_about, decl))
> >>> +    warned_about = new hash_set<tree>;
> >>> +  if (warned_about->contains (decl))
> >>>     return warned_about;
> >>> -  pointer_set_insert (warned_about, decl);
> >>> +  warned_about->add (decl);
> >>>   warning_at (DECL_SOURCE_LOCATION (decl),
> >>>              option,
> >>>              known_finite
> >>> @@ -168,7 +167,7 @@ suggest_attribute (int option, tree decl, bool known_finite,
> >>> static void
> >>> warn_function_pure (tree decl, bool known_finite)
> >>> {
> >>> -  static struct pointer_set_t *warned_about;
> >>> +  static hash_set<tree> *warned_about;
> >>> 
> >>>   warned_about
> >>>     = suggest_attribute (OPT_Wsuggest_attribute_pure, decl,
> >>> @@ -181,7 +180,7 @@ warn_function_pure (tree decl, bool known_finite)
> >>> static void
> >>> warn_function_const (tree decl, bool known_finite)
> >>> {
> >>> -  static struct pointer_set_t *warned_about;
> >>> +  static hash_set<tree> *warned_about;
> >>>   warned_about
> >>>     = suggest_attribute (OPT_Wsuggest_attribute_const, decl,
> >>>                         known_finite, warned_about, "const");
> >>> @@ -190,7 +189,7 @@ warn_function_const (tree decl, bool known_finite)
> >>> static void
> >>> warn_function_noreturn (tree decl)
> >>> {
> >>> -  static struct pointer_set_t *warned_about;
> >>> +  static hash_set<tree> *warned_about;
> >>>   if (!lang_hooks.missing_noreturn_ok_p (decl)
> >>>       && targetm.warn_func_return (decl))
> >>>     warned_about
> >>> @@ -846,11 +845,8 @@ add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
> >>>      static declarations.  We do not need to scan them more than once
> >>>      since all we would be interested in are the addressof
> >>>      operations.  */
> >>> -  visited_nodes = pointer_set_create ();
> >>>   if (node->get_availability () > AVAIL_INTERPOSABLE)
> >>>     set_function_state (node, analyze_function (node, true));
> >>> -  pointer_set_destroy (visited_nodes);
> >>> -  visited_nodes = NULL;
> >>> }
> >>> 
> >>> /* Called when new clone is inserted to callgraph late.  */
> >>> @@ -912,12 +908,6 @@ pure_const_generate_summary (void)
> >>> 
> >>>   register_hooks ();
> >>> 
> >>> -  /* There are some shared nodes, in particular the initializers on
> >>> -     static declarations.  We do not need to scan them more than once
> >>> -     since all we would be interested in are the addressof
> >>> -     operations.  */
> >>> -  visited_nodes = pointer_set_create ();
> >>> -
> >>>   /* Process all of the functions.
> >>> 
> >>>      We process AVAIL_INTERPOSABLE functions.  We can not use the results
> >>> @@ -927,9 +917,6 @@ pure_const_generate_summary (void)
> >>>   FOR_EACH_DEFINED_FUNCTION (node)
> >>>     if (node->get_availability () >= AVAIL_INTERPOSABLE)
> >>>       set_function_state (node, analyze_function (node, true));
> >>> -
> >>> -  pointer_set_destroy (visited_nodes);
> >>> -  visited_nodes = NULL;
> >>> }
> >>> 
> >>> 
> >>> diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
> >>> index 4720ee9..bca2bc7 100644
> >>> --- a/gcc/ipa-visibility.c
> >>> +++ b/gcc/ipa-visibility.c
> >>> @@ -687,12 +687,11 @@ function_and_variable_visibility (bool whole_program)
> >>>              }
> >>>          if (found)
> >>>            {
> >>> -             struct pointer_set_t *visited_nodes = pointer_set_create ();
> >>> +             hash_set<tree> visited_nodes;
> >>> 
> >>>              vnode->get_constructor ();
> >>>              walk_tree (&DECL_INITIAL (vnode->decl),
> >>> -                        update_vtable_references, NULL, visited_nodes);
> >>> -             pointer_set_destroy (visited_nodes);
> >>> +                        update_vtable_references, NULL, &visited_nodes);
> >>>              vnode->remove_all_references ();
> >>>              record_references_in_initializer (vnode->decl, false);
> >>>            }
> >>> diff --git a/gcc/ipa.c b/gcc/ipa.c
> >>> index 8198b17..1081e89 100644
> >>> --- a/gcc/ipa.c
> >>> +++ b/gcc/ipa.c
> >>> @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "cgraph.h"
> >>> #include "tree-pass.h"
> >>> #include "hash-map.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> #include "gimple-expr.h"
> >>> #include "gimplify.h"
> >>> #include "flags.h"
> >>> @@ -84,14 +84,14 @@ update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined
> >>> 
> >>> static void
> >>> enqueue_node (symtab_node *node, symtab_node **first,
> >>> -             struct pointer_set_t *reachable)
> >>> +             hash_set<symtab_node *> *reachable)
> >>> {
> >>>   /* Node is still in queue; do nothing.  */
> >>>   if (node->aux && node->aux != (void *) 2)
> >>>     return;
> >>>   /* Node was already processed as unreachable, re-enqueue
> >>>      only if it became reachable now.  */
> >>> -  if (node->aux == (void *)2 && !pointer_set_contains (reachable, node))
> >>> +  if (node->aux == (void *)2 && !reachable->contains (node))
> >>>     return;
> >>>   node->aux = *first;
> >>>   *first = node;
> >>> @@ -103,7 +103,7 @@ static void
> >>> process_references (symtab_node *snode,
> >>>                    symtab_node **first,
> >>>                    bool before_inlining_p,
> >>> -                   struct pointer_set_t *reachable)
> >>> +                   hash_set<symtab_node *> *reachable)
> >>> {
> >>>   int i;
> >>>   struct ipa_ref *ref = NULL;
> >>> @@ -124,7 +124,7 @@ process_references (symtab_node *snode,
> >>>                      && flag_wpa
> >>>                      && ctor_for_folding (node->decl)
> >>>                         != error_mark_node))))
> >>> -       pointer_set_insert (reachable, node);
> >>> +       reachable->add (node);
> >>>       enqueue_node (node, first, reachable);
> >>>     }
> >>> }
> >>> @@ -138,10 +138,11 @@ process_references (symtab_node *snode,
> >>>    possible.  */
> >>> 
> >>> static void
> >>> -walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> >>> +walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
> >>>                               struct cgraph_edge *edge,
> >>>                               symtab_node **first,
> >>> -                              pointer_set_t *reachable, bool before_inlining_p)
> >>> +                              hash_set<symtab_node *> *reachable,
> >>> +                              bool before_inlining_p)
> >>> {
> >>>   unsigned int i;
> >>>   void *cache_token;
> >>> @@ -150,8 +151,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> >>>     = possible_polymorphic_call_targets
> >>>        (edge, &final, &cache_token);
> >>> 
> >>> -  if (!pointer_set_insert (reachable_call_targets,
> >>> -                          cache_token))
> >>> +  if (!reachable_call_targets->add (cache_token))
> >>>     {
> >>>       for (i = 0; i < targets.length (); i++)
> >>>        {
> >>> @@ -172,7 +172,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
> >>>                   && (cgraph_state < CGRAPH_STATE_IPA_SSA
> >>>                       || !lookup_attribute ("always_inline",
> >>>                                             DECL_ATTRIBUTES (n->decl)))))
> >>> -            pointer_set_insert (reachable, n);
> >>> +            reachable->add (n);
> >>> 
> >>>          /* Even after inlining we want to keep the possible targets in the
> >>>             boundary, so late passes can still produce direct call even if
> >>> @@ -276,9 +276,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>   struct cgraph_node *node, *next;
> >>>   varpool_node *vnode, *vnext;
> >>>   bool changed = false;
> >>> -  struct pointer_set_t *reachable = pointer_set_create ();
> >>> -  struct pointer_set_t *body_needed_for_clonning = pointer_set_create ();
> >>> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> >>> +  hash_set<symtab_node *> reachable;
> >>> +  hash_set<tree> body_needed_for_clonning;
> >>> +  hash_set<void *> reachable_call_targets;
> >>> 
> >>>   timevar_push (TV_IPA_UNREACHABLE);
> >>>   if (optimize && flag_devirtualize)
> >>> @@ -304,8 +304,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>          && !node->can_remove_if_no_direct_calls_and_refs_p ())
> >>>        {
> >>>          gcc_assert (!node->global.inlined_to);
> >>> -         pointer_set_insert (reachable, node);
> >>> -         enqueue_node (node, &first, reachable);
> >>> +         reachable.add (node);
> >>> +         enqueue_node (node, &first, &reachable);
> >>>        }
> >>>       else
> >>>        gcc_assert (!node->aux);
> >>> @@ -316,14 +316,14 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>     if (!vnode->can_remove_if_no_refs_p()
> >>>        && !vnode->in_other_partition)
> >>>       {
> >>> -       pointer_set_insert (reachable, vnode);
> >>> -       enqueue_node (vnode, &first, reachable);
> >>> +       reachable.add (vnode);
> >>> +       enqueue_node (vnode, &first, &reachable);
> >>>       }
> >>> 
> >>>   /* Perform reachability analysis.  */
> >>>   while (first != (symtab_node *) (void *) 1)
> >>>     {
> >>> -      bool in_boundary_p = !pointer_set_contains (reachable, first);
> >>> +      bool in_boundary_p = !reachable.contains (first);
> >>>       symtab_node *node = first;
> >>> 
> >>>       first = (symtab_node *)first->aux;
> >>> @@ -340,7 +340,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>              struct cgraph_node *origin_node
> >>>              = cgraph_node::get_create (DECL_ABSTRACT_ORIGIN (node->decl));
> >>>              origin_node->used_as_abstract_origin = true;
> >>> -             enqueue_node (origin_node, &first, reachable);
> >>> +             enqueue_node (origin_node, &first, &reachable);
> >>>            }
> >>>          /* If any symbol in a comdat group is reachable, force
> >>>             all externally visible symbols in the same comdat
> >>> @@ -353,11 +353,11 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>                   next != node;
> >>>                   next = next->same_comdat_group)
> >>>                if (!next->comdat_local_p ()
> >>> -                   && !pointer_set_insert (reachable, next))
> >>> -                 enqueue_node (next, &first, reachable);
> >>> +                   && !reachable.add (next))
> >>> +                 enqueue_node (next, &first, &reachable);
> >>>            }
> >>>          /* Mark references as reachable.  */
> >>> -         process_references (node, &first, before_inlining_p, reachable);
> >>> +         process_references (node, &first, before_inlining_p, &reachable);
> >>>        }
> >>> 
> >>>       if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
> >>> @@ -375,8 +375,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>                    {
> >>>                      next = e->next_callee;
> >>>                      if (e->indirect_info->polymorphic)
> >>> -                       walk_polymorphic_call_targets (reachable_call_targets,
> >>> -                                                      e, &first, reachable,
> >>> +                       walk_polymorphic_call_targets (&reachable_call_targets,
> >>> +                                                      e, &first, &reachable,
> >>>                                                       before_inlining_p);
> >>>                    }
> >>>                }
> >>> @@ -394,17 +394,16 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>                      if (DECL_EXTERNAL (e->callee->decl)
> >>>                          && e->callee->alias
> >>>                          && before_inlining_p)
> >>> -                       pointer_set_insert (reachable,
> >>> -                                           e->callee->function_symbol ());
> >>> -                     pointer_set_insert (reachable, e->callee);
> >>> +                       reachable.add (e->callee->function_symbol ());
> >>> +                     reachable.add (e->callee);
> >>>                    }
> >>> -                 enqueue_node (e->callee, &first, reachable);
> >>> +                 enqueue_node (e->callee, &first, &reachable);
> >>>                }
> >>> 
> >>>              /* When inline clone exists, mark body to be preserved so when removing
> >>>                 offline copy of the function we don't kill it.  */
> >>>              if (cnode->global.inlined_to)
> >>> -               pointer_set_insert (body_needed_for_clonning, cnode->decl);
> >>> +               body_needed_for_clonning.add (cnode->decl);
> >>> 
> >>>              /* For non-inline clones, force their origins to the boundary and ensure
> >>>                 that body is not removed.  */
> >>> @@ -414,8 +413,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>                  cnode = cnode->clone_of;
> >>>                  if (noninline)
> >>>                    {
> >>> -                     pointer_set_insert (body_needed_for_clonning, cnode->decl);
> >>> -                     enqueue_node (cnode, &first, reachable);
> >>> +                     body_needed_for_clonning.add (cnode->decl);
> >>> +                     enqueue_node (cnode, &first, &reachable);
> >>>                    }
> >>>                }
> >>> 
> >>> @@ -429,8 +428,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>                   next;
> >>>                   next = next->simdclone->next_clone)
> >>>                if (in_boundary_p
> >>> -                   || !pointer_set_insert (reachable, next))
> >>> -                 enqueue_node (next, &first, reachable);
> >>> +                   || !reachable.add (next))
> >>> +                 enqueue_node (next, &first, &reachable);
> >>>            }
> >>>        }
> >>>       /* When we see constructor of external variable, keep referred nodes in the
> >>> @@ -444,7 +443,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>        {
> >>>          struct ipa_ref *ref = NULL;
> >>>          for (int i = 0; node->iterate_reference (i, ref); i++)
> >>> -           enqueue_node (ref->referred, &first, reachable);
> >>> +           enqueue_node (ref->referred, &first, &reachable);
> >>>        }
> >>>     }
> >>> 
> >>> @@ -462,9 +461,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>          changed = true;
> >>>        }
> >>>       /* If node is unreachable, remove its body.  */
> >>> -      else if (!pointer_set_contains (reachable, node))
> >>> +      else if (!reachable.contains (node))
> >>>         {
> >>> -         if (!pointer_set_contains (body_needed_for_clonning, node->decl))
> >>> +         if (!body_needed_for_clonning.contains (node->decl))
> >>>            node->release_body ();
> >>>          else if (!node->clone_of)
> >>>            gcc_assert (in_lto_p || DECL_RESULT (node->decl));
> >>> @@ -530,7 +529,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>          vnode->remove ();
> >>>          changed = true;
> >>>        }
> >>> -      else if (!pointer_set_contains (reachable, vnode))
> >>> +      else if (!reachable.contains (vnode))
> >>>         {
> >>>          tree init;
> >>>          if (vnode->definition)
> >>> @@ -557,10 +556,6 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
> >>>        vnode->aux = NULL;
> >>>     }
> >>> 
> >>> -  pointer_set_destroy (reachable);
> >>> -  pointer_set_destroy (body_needed_for_clonning);
> >>> -  pointer_set_destroy (reachable_call_targets);
> >>> -
> >>>   /* Now update address_taken flags and try to promote functions to be local.  */
> >>>   if (file)
> >>>     fprintf (file, "\nClearing address taken flags:");
> >>> diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
> >>> index b1fcf67..42b0790 100644
> >>> --- a/gcc/lto-cgraph.c
> >>> +++ b/gcc/lto-cgraph.c
> >>> @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "params.h"
> >>> #include "input.h"
> >>> #include "hashtab.h"
> >>> +#include "hash-set.h"
> >>> #include "langhooks.h"
> >>> #include "bitmap.h"
> >>> #include "function.h"
> >>> @@ -819,7 +820,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
> >>>   int i;
> >>>   lto_symtab_encoder_t encoder;
> >>>   lto_symtab_encoder_iterator lsei;
> >>> -  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
> >>> +  hash_set<void *> reachable_call_targets;
> >>> 
> >>>   encoder = lto_symtab_encoder_new (false);
> >>> 
> >>> @@ -902,8 +903,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
> >>>              vec <cgraph_node *>targets
> >>>                = possible_polymorphic_call_targets
> >>>                    (edge, &final, &cache_token);
> >>> -             if (!pointer_set_insert (reachable_call_targets,
> >>> -                                      cache_token))
> >>> +             if (!reachable_call_targets.add (cache_token))
> >>>                {
> >>>                  for (i = 0; i < targets.length (); i++)
> >>>                    {
> >>> @@ -923,7 +923,6 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
> >>>            }
> >>>     }
> >>>   lto_symtab_encoder_delete (in_encoder);
> >>> -  pointer_set_destroy (reachable_call_targets);
> >>>   return encoder;
> >>> }
> >>> 
> >>> diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
> >>> index 271fbd5..3fd9147 100644
> >>> --- a/gcc/lto-streamer-out.c
> >>> +++ b/gcc/lto-streamer-out.c
> >>> @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "params.h"
> >>> #include "input.h"
> >>> #include "hashtab.h"
> >>> +#include "hash-set.h"
> >>> #include "basic-block.h"
> >>> #include "tree-ssa-alias.h"
> >>> #include "internal-fn.h"
> >>> @@ -2433,7 +2434,7 @@ lto_out_decl_state_written_size (struct lto_out_decl_state *state)
> >>> static void
> >>> write_symbol (struct streamer_tree_cache_d *cache,
> >>>              struct lto_output_stream *stream,
> >>> -             tree t, struct pointer_set_t *seen, bool alias)
> >>> +             tree t, hash_set<const char *> *seen, bool alias)
> >>> {
> >>>   const char *name;
> >>>   enum gcc_plugin_symbol_kind kind;
> >>> @@ -2461,9 +2462,8 @@ write_symbol (struct streamer_tree_cache_d *cache,
> >>>      same name manipulations that ASM_OUTPUT_LABELREF does. */
> >>>   name = IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name) (name));
> >>> 
> >>> -  if (pointer_set_contains (seen, name))
> >>> +  if (seen->add (name))
> >>>     return;
> >>> -  pointer_set_insert (seen, name);
> >>> 
> >>>   streamer_tree_cache_lookup (cache, t, &slot_num);
> >>>   gcc_assert (slot_num != (unsigned)-1);
> >>> @@ -2588,7 +2588,6 @@ produce_symtab (struct output_block *ob)
> >>> {
> >>>   struct streamer_tree_cache_d *cache = ob->writer_cache;
> >>>   char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
> >>> -  struct pointer_set_t *seen;
> >>>   struct lto_output_stream stream;
> >>>   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
> >>>   lto_symtab_encoder_iterator lsei;
> >>> @@ -2596,7 +2595,7 @@ produce_symtab (struct output_block *ob)
> >>>   lto_begin_section (section_name, false);
> >>>   free (section_name);
> >>> 
> >>> -  seen = pointer_set_create ();
> >>> +  hash_set<const char *> seen;
> >>>   memset (&stream, 0, sizeof (stream));
> >>> 
> >>>   /* Write the symbol table.
> >>> @@ -2609,7 +2608,7 @@ produce_symtab (struct output_block *ob)
> >>> 
> >>>       if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
> >>>        continue;
> >>> -      write_symbol (cache, &stream, node->decl, seen, false);
> >>> +      write_symbol (cache, &stream, node->decl, &seen, false);
> >>>     }
> >>>   for (lsei = lsei_start (encoder);
> >>>        !lsei_end_p (lsei); lsei_next (&lsei))
> >>> @@ -2618,11 +2617,10 @@ produce_symtab (struct output_block *ob)
> >>> 
> >>>       if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
> >>>        continue;
> >>> -      write_symbol (cache, &stream, node->decl, seen, false);
> >>> +      write_symbol (cache, &stream, node->decl, &seen, false);
> >>>     }
> >>> 
> >>>   lto_write_stream (&stream);
> >>> -  pointer_set_destroy (seen);
> >>> 
> >>>   lto_end_section ();
> >>> }
> >>> diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
> >>> index cb08a88..a5bcf92 100644
> >>> --- a/gcc/lto/lto-partition.c
> >>> +++ b/gcc/lto/lto-partition.c
> >>> @@ -66,7 +66,7 @@ free_ltrans_partitions (void)
> >>>   for (idx = 0; ltrans_partitions.iterate (idx, &part); idx++)
> >>>     {
> >>>       if (part->initializers_visited)
> >>> -       pointer_set_destroy (part->initializers_visited);
> >>> +       delete part->initializers_visited;
> >>>       /* Symtab encoder is freed after streaming.  */
> >>>       free (part);
> >>>     }
> >>> @@ -101,8 +101,8 @@ add_references_to_partition (ltrans_partition part, symtab_node *node)
> >>>             && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
> >>>       {
> >>>        if (!part->initializers_visited)
> >>> -         part->initializers_visited = pointer_set_create ();
> >>> -       if (!pointer_set_insert (part->initializers_visited, ref->referred))
> >>> +         part->initializers_visited = new hash_set<symtab_node *>;
> >>> +       if (!part->initializers_visited->add (ref->referred))
> >>>          add_references_to_partition (part, ref->referred);
> >>>       }
> >>> }
> >>> @@ -250,7 +250,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes)
> >>> 
> >>>       /* After UNDO we no longer know what was visited.  */
> >>>       if (partition->initializers_visited)
> >>> -       pointer_set_destroy (partition->initializers_visited);
> >>> +       delete partition->initializers_visited;
> >>>       partition->initializers_visited = NULL;
> >>> 
> >>>       if (!node->alias && (cnode = dyn_cast <cgraph_node *> (node)))
> >>> diff --git a/gcc/lto/lto-partition.h b/gcc/lto/lto-partition.h
> >>> index 8db61b3..50ec2fa 100644
> >>> --- a/gcc/lto/lto-partition.h
> >>> +++ b/gcc/lto/lto-partition.h
> >>> @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
> >>> along with GCC; see the file COPYING3.  If not see
> >>> <http://www.gnu.org/licenses/>.  */
> >>> 
> >>> +#include "hash-set.h"
> >>> 
> >>> /* Structure describing ltrans partitions.  */
> >>> 
> >>> @@ -25,7 +26,7 @@ struct ltrans_partition_def
> >>>   lto_symtab_encoder_t encoder;
> >>>   const char * name;
> >>>   int insns;
> >>> -  pointer_set_t *initializers_visited;
> >>> +  hash_set<symtab_node *> *initializers_visited;
> >>> };
> >>> 
> >>> typedef struct ltrans_partition_def *ltrans_partition;
> >>> diff --git a/gcc/stmt.c b/gcc/stmt.c
> >>> index 0aae085..55ec279 100644
> >>> --- a/gcc/stmt.c
> >>> +++ b/gcc/stmt.c
> >>> @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "predict.h"
> >>> #include "optabs.h"
> >>> #include "target.h"
> >>> +#include "hash-set.h"
> >>> #include "pointer-set.h"
> >>> #include "basic-block.h"
> >>> #include "tree-ssa-alias.h"
> >>> @@ -1183,7 +1184,7 @@ expand_case (gimple stmt)
> >>>      how to expand this switch().  */
> >>>   uniq = 0;
> >>>   count = 0;
> >>> -  struct pointer_set_t *seen_labels = pointer_set_create ();
> >>> +  hash_set<tree> seen_labels;
> >>>   compute_cases_per_edge (stmt);
> >>> 
> >>>   for (i = ncases - 1; i >= 1; --i)
> >>> @@ -1203,7 +1204,7 @@ expand_case (gimple stmt)
> >>> 
> >>>       /* If we have not seen this label yet, then increase the
> >>>         number of unique case node targets seen.  */
> >>> -      if (!pointer_set_insert (seen_labels, lab))
> >>> +      if (!seen_labels.add (lab))
> >>>        uniq++;
> >>> 
> >>>       /* The bounds on the case range, LOW and HIGH, have to be converted
> >>> @@ -1231,7 +1232,6 @@ expand_case (gimple stmt)
> >>>           case_edge->probability / (intptr_t)(case_edge->aux),
> >>>           case_node_pool);
> >>>     }
> >>> -  pointer_set_destroy (seen_labels);
> >>>   reset_out_edges_aux (bb);
> >>> 
> >>>   /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
> >>> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> >>> index 6fee8a4..e034762 100644
> >>> --- a/gcc/tree-cfg.c
> >>> +++ b/gcc/tree-cfg.c
> >>> @@ -4691,7 +4691,7 @@ tree_node_can_be_shared (tree t)
> >>> static tree
> >>> verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
> >>> {
> >>> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> >>> +  hash_set<void *> *visited = (hash_set<void *> *) data;
> >>> 
> >>>   if (tree_node_can_be_shared (*tp))
> >>>     {
> >>> @@ -4699,7 +4699,7 @@ verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
> >>>       return NULL;
> >>>     }
> >>> 
> >>> -  if (pointer_set_insert (visited, *tp))
> >>> +  if (visited->add (*tp))
> >>>     return *tp;
> >>> 
> >>>   return NULL;
> >>> @@ -4719,9 +4719,9 @@ static int
> >>> verify_eh_throw_stmt_node (void **slot, void *data)
> >>> {
> >>>   struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
> >>> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> >>> +  hash_set<void *> *visited = (hash_set<void *> *) data;
> >>> 
> >>> -  if (!pointer_set_contains (visited, node->stmt))
> >>> +  if (!visited->contains (node->stmt))
> >>>     {
> >>>       error ("dead STMT in EH table");
> >>>       debug_gimple_stmt (node->stmt);
> >>> @@ -4733,11 +4733,11 @@ verify_eh_throw_stmt_node (void **slot, void *data)
> >>> /* Verify if the location LOCs block is in BLOCKS.  */
> >>> 
> >>> static bool
> >>> -verify_location (pointer_set_t *blocks, location_t loc)
> >>> +verify_location (hash_set<tree> *blocks, location_t loc)
> >>> {
> >>>   tree block = LOCATION_BLOCK (loc);
> >>>   if (block != NULL_TREE
> >>> -      && !pointer_set_contains (blocks, block))
> >>> +      && !blocks->contains (block))
> >>>     {
> >>>       error ("location references block not in block tree");
> >>>       return true;
> >>> @@ -4770,7 +4770,7 @@ verify_expr_no_block (tree *tp, int *walk_subtrees, void *)
> >>> static tree
> >>> verify_expr_location_1 (tree *tp, int *walk_subtrees, void *data)
> >>> {
> >>> -  struct pointer_set_t *blocks = (struct pointer_set_t *) data;
> >>> +  hash_set<tree> *blocks = (hash_set<tree> *) data;
> >>> 
> >>>   if (TREE_CODE (*tp) == VAR_DECL
> >>>       && DECL_HAS_DEBUG_EXPR_P (*tp))
> >>> @@ -4816,12 +4816,12 @@ verify_expr_location (tree *tp, int *walk_subtrees, void *data)
> >>> /* Insert all subblocks of BLOCK into BLOCKS and recurse.  */
> >>> 
> >>> static void
> >>> -collect_subblocks (pointer_set_t *blocks, tree block)
> >>> +collect_subblocks (hash_set<tree> *blocks, tree block)
> >>> {
> >>>   tree t;
> >>>   for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
> >>>     {
> >>> -      pointer_set_insert (blocks, t);
> >>> +      blocks->add (t);
> >>>       collect_subblocks (blocks, t);
> >>>     }
> >>> }
> >>> @@ -4833,18 +4833,17 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >>> {
> >>>   basic_block bb;
> >>>   bool err = false;
> >>> -  struct pointer_set_t *visited, *visited_stmts, *blocks;
> >>> 
> >>>   timevar_push (TV_TREE_STMT_VERIFY);
> >>> -  visited = pointer_set_create ();
> >>> -  visited_stmts = pointer_set_create ();
> >>> +  hash_set<void *> visited;
> >>> +  hash_set<gimple> visited_stmts;
> >>> 
> >>>   /* Collect all BLOCKs referenced by the BLOCK tree of FN.  */
> >>> -  blocks = pointer_set_create ();
> >>> +  hash_set<tree> blocks;
> >>>   if (DECL_INITIAL (fn->decl))
> >>>     {
> >>> -      pointer_set_insert (blocks, DECL_INITIAL (fn->decl));
> >>> -      collect_subblocks (blocks, DECL_INITIAL (fn->decl));
> >>> +      blocks.add (DECL_INITIAL (fn->decl));
> >>> +      collect_subblocks (&blocks, DECL_INITIAL (fn->decl));
> >>>     }
> >>> 
> >>>   FOR_EACH_BB_FN (bb, fn)
> >>> @@ -4857,7 +4856,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >>>          bool err2 = false;
> >>>          unsigned i;
> >>> 
> >>> -         pointer_set_insert (visited_stmts, phi);
> >>> +         visited_stmts.add (phi);
> >>> 
> >>>          if (gimple_bb (phi) != bb)
> >>>            {
> >>> @@ -4878,7 +4877,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >>>            {
> >>>              tree arg = gimple_phi_arg_def (phi, i);
> >>>              tree addr = walk_tree (&arg, verify_node_sharing_1,
> >>> -                                    visited, NULL);
> >>> +                                    &visited, NULL);
> >>>              if (addr)
> >>>                {
> >>>                  error ("incorrect sharing of tree nodes");
> >>> @@ -4892,13 +4891,13 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >>>                  error ("virtual PHI with argument locations");
> >>>                  err2 = true;
> >>>                }
> >>> -             addr = walk_tree (&arg, verify_expr_location_1, blocks, NULL);
> >>> +             addr = walk_tree (&arg, verify_expr_location_1, &blocks, NULL);
> >>>              if (addr)
> >>>                {
> >>>                  debug_generic_expr (addr);
> >>>                  err2 = true;
> >>>                }
> >>> -             err2 |= verify_location (blocks, loc);
> >>> +             err2 |= verify_location (&blocks, loc);
> >>>            }
> >>> 
> >>>          if (err2)
> >>> @@ -4914,7 +4913,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >>>          tree addr;
> >>>          int lp_nr;
> >>> 
> >>> -         pointer_set_insert (visited_stmts, stmt);
> >>> +         visited_stmts.add (stmt);
> >>> 
> >>>          if (gimple_bb (stmt) != bb)
> >>>            {
> >>> @@ -4923,10 +4922,10 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >>>            }
> >>> 
> >>>          err2 |= verify_gimple_stmt (stmt);
> >>> -         err2 |= verify_location (blocks, gimple_location (stmt));
> >>> +         err2 |= verify_location (&blocks, gimple_location (stmt));
> >>> 
> >>>          memset (&wi, 0, sizeof (wi));
> >>> -         wi.info = (void *) visited;
> >>> +         wi.info = (void *) &visited;
> >>>          addr = walk_gimple_op (stmt, verify_node_sharing, &wi);
> >>>          if (addr)
> >>>            {
> >>> @@ -4936,7 +4935,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >>>            }
> >>> 
> >>>          memset (&wi, 0, sizeof (wi));
> >>> -         wi.info = (void *) blocks;
> >>> +         wi.info = (void *) &blocks;
> >>>          addr = walk_gimple_op (stmt, verify_expr_location, &wi);
> >>>          if (addr)
> >>>            {
> >>> @@ -4992,14 +4991,11 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
> >>>   if (get_eh_throw_stmt_table (cfun))
> >>>     htab_traverse (get_eh_throw_stmt_table (cfun),
> >>>                   verify_eh_throw_stmt_node,
> >>> -                  visited_stmts);
> >>> +                  &visited_stmts);
> >>> 
> >>>   if (err || eh_error_found)
> >>>     internal_error ("verify_gimple failed");
> >>> 
> >>> -  pointer_set_destroy (visited);
> >>> -  pointer_set_destroy (visited_stmts);
> >>> -  pointer_set_destroy (blocks);
> >>>   verify_histograms ();
> >>>   timevar_pop (TV_TREE_STMT_VERIFY);
> >>> }
> >>> diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> >>> index 34c48fa..9d462d1 100644
> >>> --- a/gcc/tree-core.h
> >>> +++ b/gcc/tree-core.h
> >>> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #define GCC_TREE_CORE_H
> >>> 
> >>> #include "hashtab.h"
> >>> +#include "hash-set.h"
> >>> #include "machmode.h"
> >>> #include "input.h"
> >>> #include "statistics.h"
> >>> @@ -45,7 +46,6 @@ struct fixed_value;
> >>> struct ptr_info_def;
> >>> struct range_info_def;
> >>> struct die_struct;
> >>> -struct pointer_set_t;
> >>> 
> >>> 
> >>> /*---------------------------------------------------------------------------
> >>> @@ -692,7 +692,7 @@ typedef tree (*walk_tree_fn) (tree *, int *, void *);
> >>> 
> >>> /* The type of a callback function that represents a custom walk_tree.  */
> >>> typedef tree (*walk_tree_lh) (tree *, int *, tree (*) (tree *, int *, void *),
> >>> -                             void *, struct pointer_set_t*);
> >>> +                             void *, hash_set<tree> *);
> >>> 
> >>> 
> >>> /*---------------------------------------------------------------------------
> >>> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> >>> index df9a6fc..38842e8 100644
> >>> --- a/gcc/tree-eh.c
> >>> +++ b/gcc/tree-eh.c
> >>> @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "flags.h"
> >>> #include "function.h"
> >>> #include "except.h"
> >>> +#include "hash-set.h"
> >>> #include "pointer-set.h"
> >>> #include "basic-block.h"
> >>> #include "tree-ssa-alias.h"
> >>> @@ -3578,7 +3579,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
> >>>        eh_catch c;
> >>>        edge_iterator ei;
> >>>        edge e;
> >>> -       struct pointer_set_t *seen_values = pointer_set_create ();
> >>> +       hash_set<tree> seen_values;
> >>> 
> >>>        /* Collect the labels for a switch.  Zero the post_landing_pad
> >>>           field becase we'll no longer have anything keeping these labels
> >>> @@ -3605,12 +3606,12 @@ lower_eh_dispatch (basic_block src, gimple stmt)
> >>>                   attached to the handler anymore, we remove
> >>>                   the corresponding edge and then we delete unreachable
> >>>                   blocks at the end of this pass.  */
> >>> -               if (! pointer_set_contains (seen_values, TREE_VALUE (flt_node)))
> >>> +               if (! seen_values.contains (TREE_VALUE (flt_node)))
> >>>                  {
> >>>                    tree t = build_case_label (TREE_VALUE (flt_node),
> >>>                                               NULL, lab);
> >>>                    labels.safe_push (t);
> >>> -                   pointer_set_insert (seen_values, TREE_VALUE (flt_node));
> >>> +                   seen_values.add (TREE_VALUE (flt_node));
> >>>                    have_label = true;
> >>>                  }
> >>> 
> >>> @@ -3662,7 +3663,6 @@ lower_eh_dispatch (basic_block src, gimple stmt)
> >>>            x = gimple_build_switch (filter, default_label, labels);
> >>>            gsi_insert_before (&gsi, x, GSI_SAME_STMT);
> >>>          }
> >>> -       pointer_set_destroy (seen_values);
> >>>       }
> >>>       break;
> >>> 
> >>> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> >>> index 33705b7..6af4912 100644
> >>> --- a/gcc/tree-inline.c
> >>> +++ b/gcc/tree-inline.c
> >>> @@ -1788,7 +1788,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
> >>>             expensive, copy_body can be told to watch for nontrivial
> >>>             changes.  */
> >>>          if (id->statements_to_fold)
> >>> -           pointer_set_insert (id->statements_to_fold, stmt);
> >>> +           id->statements_to_fold->add (stmt);
> >>> 
> >>>          /* We're duplicating a CALL_EXPR.  Find any corresponding
> >>>             callgraph edges and update or duplicate them.  */
> >>> @@ -3507,7 +3507,6 @@ inline_forbidden_p (tree fndecl)
> >>> {
> >>>   struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
> >>>   struct walk_stmt_info wi;
> >>> -  struct pointer_set_t *visited_nodes;
> >>>   basic_block bb;
> >>>   bool forbidden_p = false;
> >>> 
> >>> @@ -3518,10 +3517,10 @@ inline_forbidden_p (tree fndecl)
> >>> 
> >>>   /* Next, walk the statements of the function looking for
> >>>      constraucts we can't handle, or are non-optimal for inlining.  */
> >>> -  visited_nodes = pointer_set_create ();
> >>> +  hash_set<tree> visited_nodes;
> >>>   memset (&wi, 0, sizeof (wi));
> >>>   wi.info = (void *) fndecl;
> >>> -  wi.pset = visited_nodes;
> >>> +  wi.pset = &visited_nodes;
> >>> 
> >>>   FOR_EACH_BB_FN (bb, fun)
> >>>     {
> >>> @@ -3533,7 +3532,6 @@ inline_forbidden_p (tree fndecl)
> >>>        break;
> >>>     }
> >>> 
> >>> -  pointer_set_destroy (visited_nodes);
> >>>   return forbidden_p;
> >>> }
> >>> 
> >>> @@ -4531,7 +4529,7 @@ gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
> >>>    in the STATEMENTS pointer set.  */
> >>> 
> >>> static void
> >>> -fold_marked_statements (int first, struct pointer_set_t *statements)
> >>> +fold_marked_statements (int first, hash_set<gimple> *statements)
> >>> {
> >>>   for (; first < n_basic_blocks_for_fn (cfun); first++)
> >>>     if (BASIC_BLOCK_FOR_FN (cfun, first))
> >>> @@ -4541,7 +4539,7 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
> >>>        for (gsi = gsi_start_bb (BASIC_BLOCK_FOR_FN (cfun, first));
> >>>             !gsi_end_p (gsi);
> >>>             gsi_next (&gsi))
> >>> -         if (pointer_set_contains (statements, gsi_stmt (gsi)))
> >>> +         if (statements->contains (gsi_stmt (gsi)))
> >>>            {
> >>>              gimple old_stmt = gsi_stmt (gsi);
> >>>              tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
> >>> @@ -4642,7 +4640,7 @@ optimize_inline_calls (tree fn)
> >>>   id.transform_return_to_modify = true;
> >>>   id.transform_parameter = true;
> >>>   id.transform_lang_insert_block = NULL;
> >>> -  id.statements_to_fold = pointer_set_create ();
> >>> +  id.statements_to_fold = new hash_set<gimple>;
> >>> 
> >>>   push_gimplify_context ();
> >>> 
> >>> @@ -4678,7 +4676,7 @@ optimize_inline_calls (tree fn)
> >>> 
> >>>   /* Fold queued statements.  */
> >>>   fold_marked_statements (last, id.statements_to_fold);
> >>> -  pointer_set_destroy (id.statements_to_fold);
> >>> +  delete id.statements_to_fold;
> >>> 
> >>>   gcc_assert (!id.debug_stmts.exists ());
> >>> 
> >>> @@ -4920,7 +4918,6 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
> >>> {
> >>>   copy_body_data id;
> >>>   struct walk_stmt_info wi;
> >>> -  struct pointer_set_t *visited;
> >>>   gimple_seq copy;
> >>> 
> >>>   /* There's nothing to do for NULL_TREE.  */
> >>> @@ -4943,11 +4940,10 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
> >>> 
> >>>   /* Walk the tree once to find local labels.  */
> >>>   memset (&wi, 0, sizeof (wi));
> >>> -  visited = pointer_set_create ();
> >>> +  hash_set<tree> visited;
> >>>   wi.info = &id;
> >>> -  wi.pset = visited;
> >>> +  wi.pset = &visited;
> >>>   walk_gimple_seq (seq, mark_local_labels_stmt, NULL, &wi);
> >>> -  pointer_set_destroy (visited);
> >>> 
> >>>   copy = gimple_seq_copy (seq);
> >>> 
> >>> @@ -5370,7 +5366,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
> >>>   memset (&id, 0, sizeof (id));
> >>> 
> >>>   /* Generate a new name for the new version. */
> >>> -  id.statements_to_fold = pointer_set_create ();
> >>> +  id.statements_to_fold = new hash_set<gimple>;
> >>> 
> >>>   id.decl_map = pointer_map_create ();
> >>>   id.debug_map = NULL;
> >>> @@ -5541,7 +5537,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
> >>>   free_dominance_info (CDI_POST_DOMINATORS);
> >>> 
> >>>   fold_marked_statements (0, id.statements_to_fold);
> >>> -  pointer_set_destroy (id.statements_to_fold);
> >>> +  delete id.statements_to_fold;
> >>>   fold_cond_expr_cond ();
> >>>   delete_unreachable_blocks_update_callgraph (&id);
> >>>   if (id.dst_node->definition)
> >>> diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
> >>> index 2a5daaf..c13e6c7 100644
> >>> --- a/gcc/tree-inline.h
> >>> +++ b/gcc/tree-inline.h
> >>> @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
> >>> #ifndef GCC_TREE_INLINE_H
> >>> #define GCC_TREE_INLINE_H
> >>> 
> >>> +#include "hash-set.h"
> >>> +
> >>> struct cgraph_edge;
> >>> 
> >>> /* Indicate the desired behavior wrt call graph edges.  We can either
> >>> @@ -114,7 +116,7 @@ struct copy_body_data
> >>>   void (*transform_lang_insert_block) (tree);
> >>> 
> >>>   /* Statements that might be possibly folded.  */
> >>> -  struct pointer_set_t *statements_to_fold;
> >>> +  hash_set<gimple> *statements_to_fold;
> >>> 
> >>>   /* Entry basic block to currently copied body.  */
> >>>   basic_block entry_bb;
> >>> diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
> >>> index 185d87c..45c5cf7 100644
> >>> --- a/gcc/tree-nested.c
> >>> +++ b/gcc/tree-nested.c
> >>> @@ -95,7 +95,7 @@ struct nesting_info
> >>> 
> >>>   struct pointer_map_t *field_map;
> >>>   struct pointer_map_t *var_map;
> >>> -  struct pointer_set_t *mem_refs;
> >>> +  hash_set<tree *> *mem_refs;
> >>>   bitmap suppress_expansion;
> >>> 
> >>>   tree context;
> >>> @@ -732,7 +732,7 @@ create_nesting_tree (struct cgraph_node *cgn)
> >>>   struct nesting_info *info = XCNEW (struct nesting_info);
> >>>   info->field_map = pointer_map_create ();
> >>>   info->var_map = pointer_map_create ();
> >>> -  info->mem_refs = pointer_set_create ();
> >>> +  info->mem_refs = new hash_set<tree *>;
> >>>   info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
> >>>   info->context = cgn->decl;
> >>> 
> >>> @@ -1651,7 +1651,7 @@ convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
> >>>         fold here, as the chain record type is not yet finalized.  */
> >>>       if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
> >>>          && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
> >>> -       pointer_set_insert (info->mem_refs, tp);
> >>> +       info->mem_refs->add (tp);
> >>>       wi->val_only = save_val_only;
> >>>       break;
> >>> 
> >>> @@ -2655,8 +2655,8 @@ remap_vla_decls (tree block, struct nesting_info *root)
> >>> }
> >>> 
> >>> /* Fold the MEM_REF *E.  */
> >>> -static bool
> >>> -fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED)
> >>> +bool
> >>> +fold_mem_refs (tree *const &e, void *data ATTRIBUTE_UNUSED)
> >>> {
> >>>   tree *ref_p = CONST_CAST2 (tree *, const tree *, (const tree *)e);
> >>>   *ref_p = fold (*ref_p);
> >>> @@ -2878,7 +2878,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
> >>>     }
> >>> 
> >>>   /* Fold the rewritten MEM_REF trees.  */
> >>> -  pointer_set_traverse (root->mem_refs, fold_mem_refs, NULL);
> >>> +  root->mem_refs->traverse<void *, fold_mem_refs> (NULL);
> >>> 
> >>>   /* Dump the translated tree function.  */
> >>>   if (dump_file)
> >>> @@ -2933,7 +2933,7 @@ free_nesting_tree (struct nesting_info *root)
> >>>       next = iter_nestinfo_next (node);
> >>>       pointer_map_destroy (node->var_map);
> >>>       pointer_map_destroy (node->field_map);
> >>> -      pointer_set_destroy (node->mem_refs);
> >>> +      delete node->mem_refs;
> >>>       free (node);
> >>>       node = next;
> >>>     }
> >>> diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
> >>> index ca6e014..aee0331 100644
> >>> --- a/gcc/tree-pretty-print.c
> >>> +++ b/gcc/tree-pretty-print.c
> >>> @@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "expr.h"
> >>> #include "tree-pretty-print.h"
> >>> #include "hashtab.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> #include "gimple-expr.h"
> >>> #include "cgraph.h"
> >>> #include "langhooks.h"
> >>> @@ -103,14 +103,14 @@ debug_generic_stmt (tree t)
> >>> DEBUG_FUNCTION void
> >>> debug_tree_chain (tree t)
> >>> {
> >>> -  struct pointer_set_t *seen = pointer_set_create ();
> >>> +  hash_set<tree> seen;
> >>> 
> >>>   while (t)
> >>>     {
> >>>       print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
> >>>       fprintf (stderr, " ");
> >>>       t = TREE_CHAIN (t);
> >>> -      if (pointer_set_insert (seen, t))
> >>> +      if (seen.add (t))
> >>>        {
> >>>          fprintf (stderr, "... [cycled back to ");
> >>>          print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
> >>> @@ -119,8 +119,6 @@ debug_tree_chain (tree t)
> >>>        }
> >>>     }
> >>>   fprintf (stderr, "\n");
> >>> -
> >>> -  pointer_set_destroy (seen);
> >>> }
> >>> 
> >>> /* Prints declaration DECL to the FILE with details specified by FLAGS.  */
> >>> diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
> >>> index 36d68a8..83c1b19 100644
> >>> --- a/gcc/tree-ssa-loop-niter.c
> >>> +++ b/gcc/tree-ssa-loop-niter.c
> >>> @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "basic-block.h"
> >>> #include "gimple-pretty-print.h"
> >>> #include "intl.h"
> >>> +#include "hash-set.h"
> >>> #include "pointer-set.h"
> >>> #include "tree-ssa-alias.h"
> >>> #include "internal-fn.h"
> >>> @@ -3281,7 +3282,7 @@ discover_iteration_bound_by_body_walk (struct loop *loop)
> >>> static void
> >>> maybe_lower_iteration_bound (struct loop *loop)
> >>> {
> >>> -  pointer_set_t *not_executed_last_iteration = NULL;
> >>> +  hash_set<gimple> *not_executed_last_iteration = NULL;
> >>>   struct nb_iter_bound *elt;
> >>>   bool found_exit = false;
> >>>   vec<basic_block> queue = vNULL;
> >>> @@ -3300,8 +3301,8 @@ maybe_lower_iteration_bound (struct loop *loop)
> >>>          && wi::ltu_p (elt->bound, loop->nb_iterations_upper_bound))
> >>>        {
> >>>          if (!not_executed_last_iteration)
> >>> -           not_executed_last_iteration = pointer_set_create ();
> >>> -         pointer_set_insert (not_executed_last_iteration, elt->stmt);
> >>> +           not_executed_last_iteration = new hash_set<gimple>;
> >>> +         not_executed_last_iteration->add (elt->stmt);
> >>>        }
> >>>     }
> >>>   if (!not_executed_last_iteration)
> >>> @@ -3327,7 +3328,7 @@ maybe_lower_iteration_bound (struct loop *loop)
> >>>       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> >>>        {
> >>>          gimple stmt = gsi_stmt (gsi);
> >>> -         if (pointer_set_contains (not_executed_last_iteration, stmt))
> >>> +         if (not_executed_last_iteration->contains (stmt))
> >>>            {
> >>>              stmt_found = true;
> >>>              break;
> >>> @@ -3376,7 +3377,7 @@ maybe_lower_iteration_bound (struct loop *loop)
> >>>     }
> >>>   BITMAP_FREE (visited);
> >>>   queue.release ();
> >>> -  pointer_set_destroy (not_executed_last_iteration);
> >>> +  delete not_executed_last_iteration;
> >>> }
> >>> 
> >>> /* Records estimates on numbers of iterations of LOOP.  If USE_UNDEFINED_P
> >>> diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
> >>> index 052d760..3185d9a 100644
> >>> --- a/gcc/tree-ssa-phiopt.c
> >>> +++ b/gcc/tree-ssa-phiopt.c
> >>> @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "flags.h"
> >>> #include "tm_p.h"
> >>> #include "basic-block.h"
> >>> +#include "hash-set.h"
> >>> #include "pointer-set.h"
> >>> #include "tree-ssa-alias.h"
> >>> #include "internal-fn.h"
> >>> @@ -72,9 +73,9 @@ static bool abs_replacement (basic_block, basic_block,
> >>> static bool neg_replacement (basic_block, basic_block,
> >>>                             edge, edge, gimple, tree, tree);
> >>> static bool cond_store_replacement (basic_block, basic_block, edge, edge,
> >>> -                                   struct pointer_set_t *);
> >>> +                                   hash_set<tree> *);
> >>> static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
> >>> -static struct pointer_set_t * get_non_trapping (void);
> >>> +static hash_set<tree> * get_non_trapping ();
> >>> static void replace_phi_edge_with_variable (basic_block, edge, gimple, tree);
> >>> static void hoist_adjacent_loads (basic_block, basic_block,
> >>>                                  basic_block, basic_block);
> >>> @@ -176,7 +177,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
> >>>   basic_block *bb_order;
> >>>   unsigned n, i;
> >>>   bool cfgchanged = false;
> >>> -  struct pointer_set_t *nontrap = 0;
> >>> +  hash_set<tree> *nontrap = 0;
> >>> 
> >>>   if (do_store_elim)
> >>>     /* Calculate the set of non-trapping memory accesses.  */
> >>> @@ -363,7 +364,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
> >>>   free (bb_order);
> >>> 
> >>>   if (do_store_elim)
> >>> -    pointer_set_destroy (nontrap);
> >>> +    delete nontrap;
> >>>   /* If the CFG has changed, we should cleanup the CFG.  */
> >>>   if (cfgchanged && do_store_elim)
> >>>     {
> >>> @@ -1469,7 +1470,7 @@ ssa_names_hasher::equal (const value_type *n1, const compare_type *n2)
> >>> class nontrapping_dom_walker : public dom_walker
> >>> {
> >>> public:
> >>> -  nontrapping_dom_walker (cdi_direction direction, pointer_set_t *ps)
> >>> +  nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps)
> >>>     : dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {}
> >>> 
> >>>   virtual void before_dom_children (basic_block);
> >>> @@ -1484,7 +1485,7 @@ private:
> >>>      the RHS.  */
> >>>   void add_or_mark_expr (basic_block, tree, bool);
> >>> 
> >>> -  pointer_set_t *m_nontrapping;
> >>> +  hash_set<tree> *m_nontrapping;
> >>> 
> >>>   /* The hash table for remembering what we've seen.  */
> >>>   hash_table<ssa_names_hasher> m_seen_ssa_names;
> >>> @@ -1572,7 +1573,7 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
> >>>         then we can't trap.  */
> >>>       if (found_bb && (((size_t)found_bb->aux) & 1) == 1)
> >>>        {
> >>> -         pointer_set_insert (m_nontrapping, exp);
> >>> +         m_nontrapping->add (exp);
> >>>        }
> >>>       else
> >>>         {
> >>> @@ -1601,11 +1602,11 @@ nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
> >>>    It will do a dominator walk over the whole function, and it will
> >>>    make use of the bb->aux pointers.  It returns a set of trees
> >>>    (the MEM_REFs itself) which can't trap.  */
> >>> -static struct pointer_set_t *
> >>> +static hash_set<tree> *
> >>> get_non_trapping (void)
> >>> {
> >>>   nt_call_phase = 0;
> >>> -  pointer_set_t *nontrap = pointer_set_create ();
> >>> +  hash_set<tree> *nontrap = new hash_set<tree>;
> >>>   /* We're going to do a dominator walk, so ensure that we have
> >>>      dominance information.  */
> >>>   calculate_dominance_info (CDI_DOMINATORS);
> >>> @@ -1634,7 +1635,7 @@ get_non_trapping (void)
> >>> 
> >>> static bool
> >>> cond_store_replacement (basic_block middle_bb, basic_block join_bb,
> >>> -                       edge e0, edge e1, struct pointer_set_t *nontrap)
> >>> +                       edge e0, edge e1, hash_set<tree> *nontrap)
> >>> {
> >>>   gimple assign = last_and_only_stmt (middle_bb);
> >>>   tree lhs, rhs, name, name2;
> >>> @@ -1659,7 +1660,7 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb,
> >>>   /* Prove that we can move the store down.  We could also check
> >>>      TREE_THIS_NOTRAP here, but in that case we also could move stores,
> >>>      whose value is not available readily, which we want to avoid.  */
> >>> -  if (!pointer_set_contains (nontrap, lhs))
> >>> +  if (!nontrap->contains (lhs))
> >>>     return false;
> >>> 
> >>>   /* Now we've checked the constraints, so do the transformation:
> >>> diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
> >>> index 9807b42..3dee5ba 100644
> >>> --- a/gcc/tree-ssa-threadedge.c
> >>> +++ b/gcc/tree-ssa-threadedge.c
> >>> @@ -30,7 +30,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "function.h"
> >>> #include "timevar.h"
> >>> #include "dumpfile.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> #include "tree-ssa-alias.h"
> >>> #include "internal-fn.h"
> >>> #include "gimple-expr.h"
> >>> @@ -693,13 +693,13 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >>>     }
> >>> 
> >>>   auto_vec<tree, alloc_count> fewvars;
> >>> -  pointer_set_t *vars = NULL;
> >>> +  hash_set<tree> *vars = NULL;
> >>> 
> >>>   /* If we're already starting with 3/4 of alloc_count, go for a
> >>> -     pointer_set, otherwise start with an unordered stack-allocated
> >>> +     hash_set, otherwise start with an unordered stack-allocated
> >>>      VEC.  */
> >>>   if (i * 4 > alloc_count * 3)
> >>> -    vars = pointer_set_create ();
> >>> +    vars = new hash_set<tree>;
> >>> 
> >>>   /* Now go through the initial debug stmts in DEST again, this time
> >>>      actually inserting in VARS or FEWVARS.  Don't bother checking for
> >>> @@ -720,7 +720,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >>>        gcc_unreachable ();
> >>> 
> >>>       if (vars)
> >>> -       pointer_set_insert (vars, var);
> >>> +       vars->add (var);
> >>>       else
> >>>        fewvars.quick_push (var);
> >>>     }
> >>> @@ -754,7 +754,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >>>             or somesuch.  Adding `&& bb == src' to the condition
> >>>             below will preserve all potentially relevant debug
> >>>             notes.  */
> >>> -         if (vars && pointer_set_insert (vars, var))
> >>> +         if (vars && vars->add (var))
> >>>            continue;
> >>>          else if (!vars)
> >>>            {
> >>> @@ -769,11 +769,11 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >>>                fewvars.quick_push (var);
> >>>              else
> >>>                {
> >>> -                 vars = pointer_set_create ();
> >>> +                 vars = new hash_set<tree>;
> >>>                  for (i = 0; i < alloc_count; i++)
> >>> -                   pointer_set_insert (vars, fewvars[i]);
> >>> +                   vars->add (fewvars[i]);
> >>>                  fewvars.release ();
> >>> -                 pointer_set_insert (vars, var);
> >>> +                 vars->add (var);
> >>>                }
> >>>            }
> >>> 
> >>> @@ -786,7 +786,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
> >>>   while (bb != src && single_pred_p (bb));
> >>> 
> >>>   if (vars)
> >>> -    pointer_set_destroy (vars);
> >>> +    delete vars;
> >>>   else if (fewvars.exists ())
> >>>     fewvars.release ();
> >>> }
> >>> diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
> >>> index 64259fb..f2578b7 100644
> >>> --- a/gcc/tree-ssa-uninit.c
> >>> +++ b/gcc/tree-ssa-uninit.c
> >>> @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "function.h"
> >>> #include "gimple-pretty-print.h"
> >>> #include "bitmap.h"
> >>> +#include "hash-set.h"
> >>> #include "pointer-set.h"
> >>> #include "tree-ssa-alias.h"
> >>> #include "internal-fn.h"
> >>> @@ -60,7 +61,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> /* Pointer set of potentially undefined ssa names, i.e.,
> >>>    ssa names that are defined by phi with operands that
> >>>    are not defined or potentially undefined.  */
> >>> -static pointer_set_t *possibly_undefined_names = 0;
> >>> +static hash_set<tree> *possibly_undefined_names = 0;
> >>> 
> >>> /* Bit mask handling macros.  */
> >>> #define MASK_SET_BIT(mask, pos) mask |= (1 << pos)
> >>> @@ -89,7 +90,7 @@ has_undefined_value_p (tree t)
> >>> {
> >>>   return (ssa_undefined_value_p (t)
> >>>           || (possibly_undefined_names
> >>> -              && pointer_set_contains (possibly_undefined_names, t)));
> >>> +              && possibly_undefined_names->contains (t)));
> >>> }
> >>> 
> >>> 
> >>> @@ -648,13 +649,13 @@ find_predicates (pred_chain_union *preds,
> >>> static void
> >>> collect_phi_def_edges (gimple phi, basic_block cd_root,
> >>>                        vec<edge> *edges,
> >>> -                       pointer_set_t *visited_phis)
> >>> +                       hash_set<gimple> *visited_phis)
> >>> {
> >>>   size_t i, n;
> >>>   edge opnd_edge;
> >>>   tree opnd;
> >>> 
> >>> -  if (pointer_set_insert (visited_phis, phi))
> >>> +  if (visited_phis->add (phi))
> >>>     return;
> >>> 
> >>>   n = gimple_phi_num_args (phi);
> >>> @@ -707,7 +708,6 @@ find_def_preds (pred_chain_union *preds, gimple phi)
> >>>   vec<edge> def_edges = vNULL;
> >>>   bool has_valid_pred = false;
> >>>   basic_block phi_bb, cd_root = 0;
> >>> -  pointer_set_t *visited_phis;
> >>> 
> >>>   phi_bb = gimple_bb (phi);
> >>>   /* First find the closest dominating bb to be
> >>> @@ -716,9 +716,8 @@ find_def_preds (pred_chain_union *preds, gimple phi)
> >>>   if (!cd_root)
> >>>     return false;
> >>> 
> >>> -  visited_phis = pointer_set_create ();
> >>> -  collect_phi_def_edges (phi, cd_root, &def_edges, visited_phis);
> >>> -  pointer_set_destroy (visited_phis);
> >>> +  hash_set<gimple> visited_phis;
> >>> +  collect_phi_def_edges (phi, cd_root, &def_edges, &visited_phis);
> >>> 
> >>>   n = def_edges.length ();
> >>>   if (n == 0)
> >>> @@ -941,7 +940,7 @@ is_use_properly_guarded (gimple use_stmt,
> >>>                          basic_block use_bb,
> >>>                          gimple phi,
> >>>                          unsigned uninit_opnds,
> >>> -                         pointer_set_t *visited_phis);
> >>> +                         hash_set<gimple> *visited_phis);
> >>> 
> >>> /* Returns true if all uninitialized opnds are pruned. Returns false
> >>>    otherwise. PHI is the phi node with uninitialized operands,
> >>> @@ -983,7 +982,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
> >>>                                              gimple flag_def,
> >>>                                              tree boundary_cst,
> >>>                                              enum tree_code cmp_code,
> >>> -                                             pointer_set_t *visited_phis,
> >>> +                                             hash_set<gimple> *visited_phis,
> >>>                                              bitmap *visited_flag_phis)
> >>> {
> >>>   unsigned i;
> >>> @@ -1153,7 +1152,7 @@ prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
> >>> static bool
> >>> use_pred_not_overlap_with_undef_path_pred (pred_chain_union preds,
> >>>                                           gimple phi, unsigned uninit_opnds,
> >>> -                                          pointer_set_t *visited_phis)
> >>> +                                          hash_set<gimple> *visited_phis)
> >>> {
> >>>   unsigned int i, n;
> >>>   gimple flag_def = 0;
> >>> @@ -1818,11 +1817,11 @@ push_pred (pred_chain_union *norm_preds, pred_info pred)
> >>> 
> >>> inline static void
> >>> push_to_worklist (tree op, vec<pred_info, va_heap, vl_ptr> *work_list,
> >>> -                  pointer_set_t *mark_set)
> >>> +                  hash_set<tree> *mark_set)
> >>> {
> >>> -  if (pointer_set_contains (mark_set, op))
> >>> +  if (mark_set->contains (op))
> >>>     return;
> >>> -  pointer_set_insert (mark_set, op);
> >>> +  mark_set->add (op);
> >>> 
> >>>   pred_info arg_pred;
> >>>   arg_pred.pred_lhs = op;
> >>> @@ -1907,7 +1906,7 @@ normalize_one_pred_1 (pred_chain_union *norm_preds,
> >>>                       pred_info pred,
> >>>                       enum tree_code and_or_code,
> >>>                       vec<pred_info, va_heap, vl_ptr> *work_list,
> >>> -                     pointer_set_t *mark_set)
> >>> +                     hash_set<tree> *mark_set)
> >>> {
> >>>   if (!is_neq_zero_form_p (pred))
> >>>     {
> >>> @@ -1987,7 +1986,6 @@ normalize_one_pred (pred_chain_union *norm_preds,
> >>>                     pred_info pred)
> >>> {
> >>>   vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
> >>> -  pointer_set_t *mark_set = NULL;
> >>>   enum tree_code and_or_code = ERROR_MARK;
> >>>   pred_chain norm_chain = vNULL;
> >>> 
> >>> @@ -2015,19 +2013,18 @@ normalize_one_pred (pred_chain_union *norm_preds,
> >>>     }
> >>> 
> >>>   work_list.safe_push (pred);
> >>> -  mark_set = pointer_set_create ();
> >>> +  hash_set<tree> mark_set;
> >>> 
> >>>   while (!work_list.is_empty ())
> >>>     {
> >>>       pred_info a_pred = work_list.pop ();
> >>>       normalize_one_pred_1 (norm_preds, &norm_chain, a_pred,
> >>> -                            and_or_code, &work_list, mark_set);
> >>> +                            and_or_code, &work_list, &mark_set);
> >>>     }
> >>>   if (and_or_code == BIT_AND_EXPR)
> >>>     norm_preds->safe_push (norm_chain);
> >>> 
> >>>   work_list.release ();
> >>> -  pointer_set_destroy (mark_set);
> >>> }
> >>> 
> >>> static void
> >>> @@ -2035,26 +2032,25 @@ normalize_one_pred_chain (pred_chain_union *norm_preds,
> >>>                           pred_chain one_chain)
> >>> {
> >>>   vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
> >>> -  pointer_set_t *mark_set = pointer_set_create ();
> >>> +  hash_set<tree> mark_set;
> >>>   pred_chain norm_chain = vNULL;
> >>>   size_t i;
> >>> 
> >>>   for (i = 0; i < one_chain.length (); i++)
> >>>     {
> >>>       work_list.safe_push (one_chain[i]);
> >>> -      pointer_set_insert (mark_set, one_chain[i].pred_lhs);
> >>> +      mark_set.add (one_chain[i].pred_lhs);
> >>>     }
> >>> 
> >>>   while (!work_list.is_empty ())
> >>>     {
> >>>       pred_info a_pred = work_list.pop ();
> >>>       normalize_one_pred_1 (0, &norm_chain, a_pred,
> >>> -                            BIT_AND_EXPR, &work_list, mark_set);
> >>> +                            BIT_AND_EXPR, &work_list, &mark_set);
> >>>     }
> >>> 
> >>>   norm_preds->safe_push (norm_chain);
> >>>   work_list.release ();
> >>> -  pointer_set_destroy (mark_set);
> >>> }
> >>> 
> >>> /* Normalize predicate chains PREDS and returns the normalized one.  */
> >>> @@ -2112,7 +2108,7 @@ is_use_properly_guarded (gimple use_stmt,
> >>>                          basic_block use_bb,
> >>>                          gimple phi,
> >>>                          unsigned uninit_opnds,
> >>> -                         pointer_set_t *visited_phis)
> >>> +                         hash_set<gimple> *visited_phis)
> >>> {
> >>>   basic_block phi_bb;
> >>>   pred_chain_union preds = vNULL;
> >>> @@ -2120,7 +2116,7 @@ is_use_properly_guarded (gimple use_stmt,
> >>>   bool has_valid_preds = false;
> >>>   bool is_properly_guarded = false;
> >>> 
> >>> -  if (pointer_set_insert (visited_phis, phi))
> >>> +  if (visited_phis->add (phi))
> >>>     return false;
> >>> 
> >>>   phi_bb = gimple_bb (phi);
> >>> @@ -2181,7 +2177,7 @@ is_use_properly_guarded (gimple use_stmt,
> >>> static gimple
> >>> find_uninit_use (gimple phi, unsigned uninit_opnds,
> >>>                  vec<gimple> *worklist,
> >>> -                pointer_set_t *added_to_worklist)
> >>> +                hash_set<gimple> *added_to_worklist)
> >>> {
> >>>   tree phi_result;
> >>>   use_operand_p use_p;
> >>> @@ -2192,28 +2188,22 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >>> 
> >>>   FOR_EACH_IMM_USE_FAST (use_p, iter, phi_result)
> >>>     {
> >>> -      pointer_set_t *visited_phis;
> >>>       basic_block use_bb;
> >>> 
> >>>       use_stmt = USE_STMT (use_p);
> >>>       if (is_gimple_debug (use_stmt))
> >>>        continue;
> >>> 
> >>> -      visited_phis = pointer_set_create ();
> >>> -
> >>>       if (gimple_code (use_stmt) == GIMPLE_PHI)
> >>>        use_bb = gimple_phi_arg_edge (use_stmt,
> >>>                                      PHI_ARG_INDEX_FROM_USE (use_p))->src;
> >>>       else
> >>>        use_bb = gimple_bb (use_stmt);
> >>> 
> >>> +      hash_set<gimple> visited_phis;
> >>>       if (is_use_properly_guarded (use_stmt, use_bb, phi, uninit_opnds,
> >>> -                                   visited_phis))
> >>> -        {
> >>> -          pointer_set_destroy (visited_phis);
> >>> -          continue;
> >>> -        }
> >>> -      pointer_set_destroy (visited_phis);
> >>> +                                   &visited_phis))
> >>> +       continue;
> >>> 
> >>>       if (dump_file && (dump_flags & TDF_DETAILS))
> >>>         {
> >>> @@ -2226,7 +2216,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >>> 
> >>>       /* Found a phi use that is not guarded,
> >>>          add the phi to the worklist.  */
> >>> -      if (!pointer_set_insert (added_to_worklist, use_stmt))
> >>> +      if (!added_to_worklist->add (use_stmt))
> >>>         {
> >>>           if (dump_file && (dump_flags & TDF_DETAILS))
> >>>             {
> >>> @@ -2235,7 +2225,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >>>             }
> >>> 
> >>>           worklist->safe_push (use_stmt);
> >>> -          pointer_set_insert (possibly_undefined_names, phi_result);
> >>> +          possibly_undefined_names->add (phi_result);
> >>>         }
> >>>     }
> >>> 
> >>> @@ -2252,7 +2242,7 @@ find_uninit_use (gimple phi, unsigned uninit_opnds,
> >>> 
> >>> static void
> >>> warn_uninitialized_phi (gimple phi, vec<gimple> *worklist,
> >>> -                        pointer_set_t *added_to_worklist)
> >>> +                        hash_set<gimple> *added_to_worklist)
> >>> {
> >>>   unsigned uninit_opnds;
> >>>   gimple uninit_use_stmt = 0;
> >>> @@ -2339,7 +2329,6 @@ pass_late_warn_uninitialized::execute (function *fun)
> >>>   basic_block bb;
> >>>   gimple_stmt_iterator gsi;
> >>>   vec<gimple> worklist = vNULL;
> >>> -  pointer_set_t *added_to_worklist;
> >>> 
> >>>   calculate_dominance_info (CDI_DOMINATORS);
> >>>   calculate_dominance_info (CDI_POST_DOMINATORS);
> >>> @@ -2350,8 +2339,8 @@ pass_late_warn_uninitialized::execute (function *fun)
> >>> 
> >>>   timevar_push (TV_TREE_UNINIT);
> >>> 
> >>> -  possibly_undefined_names = pointer_set_create ();
> >>> -  added_to_worklist = pointer_set_create ();
> >>> +  possibly_undefined_names = new hash_set<tree>;
> >>> +  hash_set<gimple> added_to_worklist;
> >>> 
> >>>   /* Initialize worklist  */
> >>>   FOR_EACH_BB_FN (bb, fun)
> >>> @@ -2373,7 +2362,7 @@ pass_late_warn_uninitialized::execute (function *fun)
> >>>                && uninit_undefined_value_p (op))
> >>>              {
> >>>                worklist.safe_push (phi);
> >>> -               pointer_set_insert (added_to_worklist, phi);
> >>> +               added_to_worklist.add (phi);
> >>>                if (dump_file && (dump_flags & TDF_DETAILS))
> >>>                  {
> >>>                    fprintf (dump_file, "[WORKLIST]: add to initial list: ");
> >>> @@ -2388,12 +2377,11 @@ pass_late_warn_uninitialized::execute (function *fun)
> >>>     {
> >>>       gimple cur_phi = 0;
> >>>       cur_phi = worklist.pop ();
> >>> -      warn_uninitialized_phi (cur_phi, &worklist, added_to_worklist);
> >>> +      warn_uninitialized_phi (cur_phi, &worklist, &added_to_worklist);
> >>>     }
> >>> 
> >>>   worklist.release ();
> >>> -  pointer_set_destroy (added_to_worklist);
> >>> -  pointer_set_destroy (possibly_undefined_names);
> >>> +  delete possibly_undefined_names;
> >>>   possibly_undefined_names = NULL;
> >>>   free_dominance_info (CDI_POST_DOMINATORS);
> >>>   timevar_pop (TV_TREE_UNINIT);
> >>> diff --git a/gcc/tree.c b/gcc/tree.c
> >>> index 6669a84..de1c9b6 100644
> >>> --- a/gcc/tree.c
> >>> +++ b/gcc/tree.c
> >>> @@ -5143,7 +5143,7 @@ struct free_lang_data_d
> >>>   vec<tree> worklist;
> >>> 
> >>>   /* Set of traversed objects.  Used to avoid duplicate visits.  */
> >>> -  struct pointer_set_t *pset;
> >>> +  hash_set<tree> *pset;
> >>> 
> >>>   /* Array of symbols to process with free_lang_data_in_decl.  */
> >>>   vec<tree> decls;
> >>> @@ -5208,7 +5208,7 @@ add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
> >>> static inline void
> >>> fld_worklist_push (tree t, struct free_lang_data_d *fld)
> >>> {
> >>> -  if (t && !is_lang_specific (t) && !pointer_set_contains (fld->pset, t))
> >>> +  if (t && !is_lang_specific (t) && !fld->pset->contains (t))
> >>>     fld->worklist.safe_push ((t));
> >>> }
> >>> 
> >>> @@ -5374,7 +5374,7 @@ find_decls_types (tree t, struct free_lang_data_d *fld)
> >>> {
> >>>   while (1)
> >>>     {
> >>> -      if (!pointer_set_contains (fld->pset, t))
> >>> +      if (!fld->pset->contains (t))
> >>>        walk_tree (&t, find_decls_types_r, fld, fld->pset);
> >>>       if (fld->worklist.is_empty ())
> >>>        break;
> >>> @@ -5584,7 +5584,7 @@ free_lang_data_in_cgraph (void)
> >>>   alias_pair *p;
> >>> 
> >>>   /* Initialize sets and arrays to store referenced decls and types.  */
> >>> -  fld.pset = pointer_set_create ();
> >>> +  fld.pset = new hash_set<tree>;
> >>>   fld.worklist.create (0);
> >>>   fld.decls.create (100);
> >>>   fld.types.create (100);
> >>> @@ -5614,7 +5614,7 @@ free_lang_data_in_cgraph (void)
> >>>   FOR_EACH_VEC_ELT (fld.types, i, t)
> >>>     free_lang_data_in_type (t);
> >>> 
> >>> -  pointer_set_destroy (fld.pset);
> >>> +  delete fld.pset;
> >>>   fld.worklist.release ();
> >>>   fld.decls.release ();
> >>>   fld.types.release ();
> >>> @@ -10819,7 +10819,7 @@ num_ending_zeros (const_tree x)
> >>> 
> >>> static tree
> >>> walk_type_fields (tree type, walk_tree_fn func, void *data,
> >>> -                 struct pointer_set_t *pset, walk_tree_lh lh)
> >>> +                 hash_set<tree> *pset, walk_tree_lh lh)
> >>> {
> >>>   tree result = NULL_TREE;
> >>> 
> >>> @@ -10901,7 +10901,7 @@ walk_type_fields (tree type, walk_tree_fn func, void *data,
> >>> 
> >>> tree
> >>> walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
> >>> -            struct pointer_set_t *pset, walk_tree_lh lh)
> >>> +            hash_set<tree> *pset, walk_tree_lh lh)
> >>> {
> >>>   enum tree_code code;
> >>>   int walk_subtrees;
> >>> @@ -10922,7 +10922,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
> >>> 
> >>>   /* Don't walk the same tree twice, if the user has requested
> >>>      that we avoid doing so.  */
> >>> -  if (pset && pointer_set_insert (pset, *tp))
> >>> +  if (pset && pset->add (*tp))
> >>>     return NULL_TREE;
> >>> 
> >>>   /* Call the function.  */
> >>> @@ -11237,11 +11237,9 @@ walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data,
> >>>                                walk_tree_lh lh)
> >>> {
> >>>   tree result;
> >>> -  struct pointer_set_t *pset;
> >>> 
> >>> -  pset = pointer_set_create ();
> >>> -  result = walk_tree_1 (tp, func, data, pset, lh);
> >>> -  pointer_set_destroy (pset);
> >>> +  hash_set<tree> pset;
> >>> +  result = walk_tree_1 (tp, func, data, &pset, lh);
> >>>   return result;
> >>> }
> >>> 
> >>> diff --git a/gcc/tree.h b/gcc/tree.h
> >>> index 2bb6d1f..c9f978a 100644
> >>> --- a/gcc/tree.h
> >>> +++ b/gcc/tree.h
> >>> @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #define GCC_TREE_H
> >>> 
> >>> #include "tree-core.h"
> >>> +#include "hash-set.h"
> >>> #include "wide-int.h"
> >>> #include "inchash.h"
> >>> 
> >>> @@ -4328,7 +4329,7 @@ extern void using_eh_for_cleanups (void);
> >>> extern bool using_eh_for_cleanups_p (void);
> >>> extern const char *get_tree_code_name (enum tree_code);
> >>> extern void set_call_expr_flags (tree, int);
> >>> -extern tree walk_tree_1 (tree*, walk_tree_fn, void*, struct pointer_set_t*,
> >>> +extern tree walk_tree_1 (tree*, walk_tree_fn, void*, hash_set<tree>*,
> >>>                         walk_tree_lh);
> >>> extern tree walk_tree_without_duplicates_1 (tree*, walk_tree_fn, void*,
> >>>                                            walk_tree_lh);
> >>> diff --git a/gcc/value-prof.c b/gcc/value-prof.c
> >>> index 3e51539..ffdee65 100644
> >>> --- a/gcc/value-prof.c
> >>> +++ b/gcc/value-prof.c
> >>> @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "data-streamer.h"
> >>> #include "builtins.h"
> >>> #include "tree-nested.h"
> >>> +#include "hash-set.h"
> >>> 
> >>> /* In this file value profile based optimizations are placed.  Currently the
> >>>    following optimizations are implemented (for more detailed descriptions
> >>> @@ -515,10 +516,10 @@ static bool error_found = false;
> >>> static int
> >>> visit_hist (void **slot, void *data)
> >>> {
> >>> -  struct pointer_set_t *visited = (struct pointer_set_t *) data;
> >>> +  hash_set<histogram_value> *visited = (hash_set<histogram_value> *) data;
> >>>   histogram_value hist = *(histogram_value *) slot;
> >>> 
> >>> -  if (!pointer_set_contains (visited, hist)
> >>> +  if (!visited->contains (hist)
> >>>       && hist->type != HIST_TYPE_TIME_PROFILE)
> >>>     {
> >>>       error ("dead histogram");
> >>> @@ -538,10 +539,9 @@ verify_histograms (void)
> >>>   basic_block bb;
> >>>   gimple_stmt_iterator gsi;
> >>>   histogram_value hist;
> >>> -  struct pointer_set_t *visited_hists;
> >>> 
> >>>   error_found = false;
> >>> -  visited_hists = pointer_set_create ();
> >>> +  hash_set<histogram_value> visited_hists;
> >>>   FOR_EACH_BB_FN (bb, cfun)
> >>>     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> >>>       {
> >>> @@ -558,12 +558,11 @@ verify_histograms (void)
> >>>                dump_histogram_value (stderr, hist);
> >>>                error_found = true;
> >>>              }
> >>> -            pointer_set_insert (visited_hists, hist);
> >>> +            visited_hists.add (hist);
> >>>          }
> >>>       }
> >>>   if (VALUE_HISTOGRAMS (cfun))
> >>> -    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, visited_hists);
> >>> -  pointer_set_destroy (visited_hists);
> >>> +    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, &visited_hists);
> >>>   if (error_found)
> >>>     internal_error ("verify_histograms failed");
> >>> }
> >>> diff --git a/gcc/varasm.c b/gcc/varasm.c
> >>> index 819ec26..9d8602b 100644
> >>> --- a/gcc/varasm.c
> >>> +++ b/gcc/varasm.c
> >>> @@ -51,7 +51,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "common/common-target.h"
> >>> #include "targhooks.h"
> >>> #include "cgraph.h"
> >>> -#include "pointer-set.h"
> >>> +#include "hash-set.h"
> >>> #include "asan.h"
> >>> #include "basic-block.h"
> >>> 
> >>> @@ -2249,7 +2249,7 @@ static bool pending_assemble_externals_processed;
> >>> 
> >>> /* Avoid O(external_decls**2) lookups in the pending_assemble_externals
> >>>    TREE_LIST in assemble_external.  */
> >>> -static struct pointer_set_t *pending_assemble_externals_set;
> >>> +static hash_set<tree> *pending_assemble_externals_set;
> >>> 
> >>> /* True if DECL is a function decl for which no out-of-line copy exists.
> >>>    It is assumed that DECL's assembler name has been set.  */
> >>> @@ -2303,7 +2303,7 @@ process_pending_assemble_externals (void)
> >>> 
> >>>   pending_assemble_externals = 0;
> >>>   pending_assemble_externals_processed = true;
> >>> -  pointer_set_destroy (pending_assemble_externals_set);
> >>> +  delete pending_assemble_externals_set;
> >>> #endif
> >>> }
> >>> 
> >>> @@ -2361,7 +2361,7 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
> >>>       return;
> >>>     }
> >>> 
> >>> -  if (! pointer_set_insert (pending_assemble_externals_set, decl))
> >>> +  if (! pending_assemble_externals_set->add (decl))
> >>>     pending_assemble_externals = tree_cons (NULL, decl,
> >>>                                            pending_assemble_externals);
> >>> #endif
> >>> @@ -5991,7 +5991,7 @@ init_varasm_once (void)
> >>>     readonly_data_section = text_section;
> >>> 
> >>> #ifdef ASM_OUTPUT_EXTERNAL
> >>> -  pending_assemble_externals_set = pointer_set_create ();
> >>> +  pending_assemble_externals_set = new hash_set<tree>;
> >>> #endif
> >>> }
> >>> 
> >>> diff --git a/gcc/varpool.c b/gcc/varpool.c
> >>> index 74117e2..558767f 100644
> >>> --- a/gcc/varpool.c
> >>> +++ b/gcc/varpool.c
> >>> @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
> >>> #include "tree-ssa-alias.h"
> >>> #include "gimple.h"
> >>> #include "lto-streamer.h"
> >>> +#include "hash-set.h"
> >>> 
> >>> const char * const tls_model_names[]={"none", "tls-emulated", "tls-real",
> >>>                                      "tls-global-dynamic", "tls-local-dynamic",
> >>> @@ -576,7 +577,7 @@ varpool_remove_unreferenced_decls (void)
> >>>   varpool_node *first = (varpool_node *)(void *)1;
> >>>   int i;
> >>>   struct ipa_ref *ref = NULL;
> >>> -  struct pointer_set_t *referenced = pointer_set_create ();
> >>> +  hash_set<varpool_node *> referenced;
> >>> 
> >>>   if (seen_error ())
> >>>     return;
> >>> @@ -623,7 +624,7 @@ varpool_remove_unreferenced_decls (void)
> >>>              && vnode->analyzed)
> >>>            enqueue_node (vnode, &first);
> >>>          else
> >>> -           pointer_set_insert (referenced, node);
> >>> +           referenced.add (node);
> >>>        }
> >>>     }
> >>>   if (cgraph_dump_file)
> >>> @@ -635,13 +636,13 @@ varpool_remove_unreferenced_decls (void)
> >>>        {
> >>>           if (cgraph_dump_file)
> >>>            fprintf (cgraph_dump_file, " %s", node->asm_name ());
> >>> -         if (pointer_set_contains (referenced, node))
> >>> +         if (referenced.contains (node))
> >>>            node->remove_initializer ();
> >>>          else
> >>>            node->remove ();
> >>>        }
> >>>     }
> >>> -  pointer_set_destroy (referenced);
> >>> +
> >>>   if (cgraph_dump_file)
> >>>     fprintf (cgraph_dump_file, "\n");
> >>> }
> >>> --
> >>> 2.0.1
> >>>
Mike Stump Aug. 4, 2014, 6:10 p.m. UTC | #8
On Aug 4, 2014, at 10:46 AM, Trevor Saunders <tsaunders@mozilla.com> wrote:
> 
>> I had a conflict which is why I noticed this issue in the first place. And I was using git merge :). 
> 
> I bet git log or blaim would get you better data faster.

So, git merging I would recommend:

[merge]
        conflictstyle = diff3
[rerere]
        enabled = 1

if you don’t already.  I think diff3 should be the default it is so handy.
diff mbox

Patch

diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index f42ac7f..6961838 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -36,7 +36,7 @@ 
 #include "output.h"
 #include "libfuncs.h"	/* For set_stack_check_libfunc.  */
 #include "tree-iterator.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 #include "gimple-expr.h"
 #include "gimplify.h"
 #include "bitmap.h"
@@ -3054,7 +3054,7 @@  struct nrv_data
   bitmap nrv;
   tree result;
   Node_Id gnat_ret;
-  struct pointer_set_t *visited;
+  hash_set<tree> *visited;
 };
 
 /* Return true if T is a Named Return Value.  */
@@ -3188,7 +3188,7 @@  finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
   /* Avoid walking into the same tree more than once.  Unfortunately, we
      can't just use walk_tree_without_duplicates because it would only
      call us for the first occurrence of NRVs in the function body.  */
-  if (pointer_set_insert (dp->visited, *tp))
+  if (dp->visited->add (*tp))
     *walk_subtrees = 0;
 
   return NULL_TREE;
@@ -3328,7 +3328,7 @@  finalize_nrv_unc_r (tree *tp, int *walk_subtrees, void *data)
   /* Avoid walking into the same tree more than once.  Unfortunately, we
      can't just use walk_tree_without_duplicates because it would only
      call us for the first occurrence of NRVs in the function body.  */
-  if (pointer_set_insert (dp->visited, *tp))
+  if (dp->visited->add (*tp))
     *walk_subtrees = 0;
 
   return NULL_TREE;
@@ -3376,13 +3376,13 @@  finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret
   data.nrv = nrv;
   data.result = DECL_RESULT (fndecl);
   data.gnat_ret = gnat_ret;
-  data.visited = pointer_set_create ();
+  data.visited = new hash_set<tree>;
   if (TYPE_RETURN_UNCONSTRAINED_P (TREE_TYPE (fndecl)))
     func = finalize_nrv_unc_r;
   else
     func = finalize_nrv_r;
   walk_tree (&DECL_SAVED_TREE (fndecl), func, &data, NULL);
-  pointer_set_destroy (data.visited);
+  delete data.visited;
 }
 
 /* Return true if RET_VAL can be used as a Named Return Value for the
diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
index 2b5ce5b..4898217 100644
--- a/gcc/c-family/c-gimplify.c
+++ b/gcc/c-family/c-gimplify.c
@@ -74,7 +74,7 @@  along with GCC; see the file COPYING3.  If not see
 static tree
 ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
 {
-  struct pointer_set_t *pset = (struct pointer_set_t *) data;
+  hash_set<tree> *pset = (hash_set<tree> *) data;
 
   /* Since walk_tree doesn't call the callback function on the decls
      in BIND_EXPR_VARS, we have to walk them manually.  */
@@ -116,10 +116,9 @@  c_genericize (tree fndecl)
 
   if (flag_sanitize & SANITIZE_BOUNDS)
     {
-      struct pointer_set_t *pset = pointer_set_create ();
-      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, pset,
-		 pset);
-      pointer_set_destroy (pset);
+      hash_set<tree> pset;
+      walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
+		 &pset);
     }
 
   /* Dump the C-specific tree IR.  */
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 2a4b439..050ddff 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -59,7 +59,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "hash-table.h"
 #include "langhooks-def.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 #include "plugin.h"
 #include "c-family/c-ada-spec.h"
 #include "cilk.h"
@@ -7221,17 +7221,17 @@  warn_cxx_compat_finish_struct (tree fieldlist)
   if (!struct_parse_info->typedefs_seen.is_empty ()
       && fieldlist != NULL_TREE)
     {
-      /* Use a pointer_set using the name of the typedef.  We can use
-	 a pointer_set because identifiers are interned.  */
-      struct pointer_set_t *tset = pointer_set_create ();
+      /* Use a hash_set<tree> using the name of the typedef.  We can use
+	 a hash_set<tree> because identifiers are interned.  */
+      hash_set<tree> tset;
 
       FOR_EACH_VEC_ELT (struct_parse_info->typedefs_seen, ix, x)
-	pointer_set_insert (tset, DECL_NAME (x));
+	tset.add (DECL_NAME (x));
 
       for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
 	{
 	  if (DECL_NAME (x) != NULL_TREE
-	      && pointer_set_contains (tset, DECL_NAME (x)))
+	      && tset.contains (DECL_NAME (x)))
 	    {
 	      warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
 			  ("using %qD as both field and typedef name is "
@@ -7241,8 +7241,6 @@  warn_cxx_compat_finish_struct (tree fieldlist)
 		 the typedef name is used.  */
 	    }
 	}
-
-      pointer_set_destroy (tset);
     }
 
   /* For each field which has a binding and which was not defined in
@@ -8189,7 +8187,7 @@  store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
   struct c_binding *b;
   tree parm, decl, last;
   tree parmids = arg_info->parms;
-  struct pointer_set_t *seen_args = pointer_set_create ();
+  hash_set<tree> seen_args;
 
   if (!in_system_header_at (input_location))
     warning_at (DECL_SOURCE_LOCATION (fndecl),
@@ -8220,7 +8218,7 @@  store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
 		      "%qD declared as a non-parameter", decl);
 	  /* If the declaration is already marked, we have a duplicate
 	     name.  Complain and ignore the duplicate.  */
-	  else if (pointer_set_contains (seen_args, decl))
+	  else if (seen_args.contains (decl))
 	    {
 	      error_at (DECL_SOURCE_LOCATION (decl),
 			"multiple parameters named %qD", decl);
@@ -8269,7 +8267,7 @@  store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
 	}
 
       TREE_PURPOSE (parm) = decl;
-      pointer_set_insert (seen_args, decl);
+      seen_args.add (decl);
     }
 
   /* Now examine the parms chain for incomplete declarations
@@ -8289,7 +8287,7 @@  store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
 	  TREE_TYPE (parm) = error_mark_node;
 	}
 
-      if (!pointer_set_contains (seen_args, parm))
+      if (!seen_args.contains (parm))
 	{
 	  error_at (DECL_SOURCE_LOCATION (parm),
 		    "declaration for parameter %qD but no such parameter",
@@ -8324,8 +8322,6 @@  store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
       DECL_CHAIN (last) = 0;
     }
 
-  pointer_set_destroy (seen_args);
-
   /* If there was a previous prototype,
      set the DECL_ARG_TYPE of each argument according to
      the type previously specified, and report any mismatches.  */
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 2f0ae71..b20be10 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -35,6 +35,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "expr.h"
 #include "langhooks.h"
 #include "bitmap.h"
+#include "hash-set.h"
 #include "pointer-set.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
@@ -594,7 +595,7 @@  stack_var_cmp (const void *a, const void *b)
 static void
 add_partitioned_vars_to_ptset (struct pt_solution *pt,
 			       struct pointer_map_t *decls_to_partitions,
-			       struct pointer_set_t *visited, bitmap temp)
+			       hash_set<bitmap> *visited, bitmap temp)
 {
   bitmap_iterator bi;
   unsigned i;
@@ -604,7 +605,7 @@  add_partitioned_vars_to_ptset (struct pt_solution *pt,
       || pt->vars == NULL
       /* The pointed-to vars bitmap is shared, it is enough to
 	 visit it once.  */
-      || pointer_set_insert (visited, pt->vars))
+      || visited->add (pt->vars))
     return;
 
   bitmap_clear (temp);
@@ -684,7 +685,7 @@  update_alias_info_with_stack_vars (void)
   if (decls_to_partitions)
     {
       unsigned i;
-      struct pointer_set_t *visited = pointer_set_create ();
+      hash_set<bitmap> visited;
       bitmap temp = BITMAP_ALLOC (&stack_var_bitmap_obstack);
 
       for (i = 1; i < num_ssa_names; i++)
@@ -696,13 +697,12 @@  update_alias_info_with_stack_vars (void)
 	      && POINTER_TYPE_P (TREE_TYPE (name))
 	      && ((pi = SSA_NAME_PTR_INFO (name)) != NULL))
 	    add_partitioned_vars_to_ptset (&pi->pt, decls_to_partitions,
-					   visited, temp);
+					   &visited, temp);
 	}
 
       add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped,
-				     decls_to_partitions, visited, temp);
+				     decls_to_partitions, &visited, temp);
 
-      pointer_set_destroy (visited);
       pointer_map_destroy (decls_to_partitions);
       BITMAP_FREE (temp);
     }
diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
index 73f79ef..8f7e265 100644
--- a/gcc/cfgloop.c
+++ b/gcc/cfgloop.c
@@ -28,7 +28,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-core.h"
 #include "flags.h"
 #include "tree.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
 #include "gimple-expr.h"
@@ -650,11 +650,11 @@  find_subloop_latch_edge (struct loop *loop)
 /* Callback for make_forwarder_block.  Returns true if the edge E is marked
    in the set MFB_REIS_SET.  */
 
-static struct pointer_set_t *mfb_reis_set;
+static hash_set<edge> *mfb_reis_set;
 static bool
 mfb_redirect_edges_in_set (edge e)
 {
-  return pointer_set_contains (mfb_reis_set, e);
+  return mfb_reis_set->contains (e);
 }
 
 /* Creates a subloop of LOOP with latch edge LATCH.  */
@@ -666,15 +666,15 @@  form_subloop (struct loop *loop, edge latch)
   edge e, new_entry;
   struct loop *new_loop;
 
-  mfb_reis_set = pointer_set_create ();
+  mfb_reis_set = new hash_set<edge>;
   FOR_EACH_EDGE (e, ei, loop->header->preds)
     {
       if (e != latch)
-	pointer_set_insert (mfb_reis_set, e);
+	mfb_reis_set->add (e);
     }
   new_entry = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
 				    NULL);
-  pointer_set_destroy (mfb_reis_set);
+  delete mfb_reis_set;
 
   loop->header = new_entry->src;
 
@@ -705,12 +705,12 @@  merge_latch_edges (struct loop *loop)
       if (dump_file)
 	fprintf (dump_file, "Merged latch edges of loop %d\n", loop->num);
 
-      mfb_reis_set = pointer_set_create ();
+      mfb_reis_set = new hash_set<edge>;
       FOR_EACH_VEC_ELT (latches, i, e)
-	pointer_set_insert (mfb_reis_set, e);
+	mfb_reis_set->add (e);
       latch = make_forwarder_block (loop->header, mfb_redirect_edges_in_set,
 				    NULL);
-      pointer_set_destroy (mfb_reis_set);
+      delete mfb_reis_set;
 
       loop->header = latch->dest;
       loop->latch = latch->src;
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index a5d0749..7c72399 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -34,6 +34,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-inline.h"
 #include "langhooks.h"
 #include "hashtab.h"
+#include "hash-set.h"
 #include "toplev.h"
 #include "flags.h"
 #include "debug.h"
@@ -2871,7 +2872,7 @@  cgraph_node::verify_node (void)
     {
       if (this_cfun->cfg)
 	{
-	  pointer_set_t *stmts = pointer_set_create ();
+	  hash_set<gimple> stmts;
 	  int i;
 	  struct ipa_ref *ref = NULL;
 
@@ -2881,13 +2882,13 @@  cgraph_node::verify_node (void)
 	    {
 	      for (gsi = gsi_start_phis (this_block);
 		   !gsi_end_p (gsi); gsi_next (&gsi))
-		pointer_set_insert (stmts, gsi_stmt (gsi));
+		stmts.add (gsi_stmt (gsi));
 	      for (gsi = gsi_start_bb (this_block);
 		   !gsi_end_p (gsi);
 		   gsi_next (&gsi))
 		{
 		  gimple stmt = gsi_stmt (gsi);
-		  pointer_set_insert (stmts, stmt);
+		  stmts.add (stmt);
 		  if (is_gimple_call (stmt))
 		    {
 		      struct cgraph_edge *e = get_edge (stmt);
@@ -2931,13 +2932,12 @@  cgraph_node::verify_node (void)
 		}
 	      }
 	    for (i = 0; iterate_reference (i, ref); i++)
-	      if (ref->stmt && !pointer_set_contains (stmts, ref->stmt))
+	      if (ref->stmt && !stmts.contains (ref->stmt))
 		{
 		  error ("reference to dead statement");
 		  cgraph_debug_gimple_stmt (this_cfun, ref->stmt);
 		  error_found = true;
 		}
-	    pointer_set_destroy (stmts);
 	}
       else
 	/* No CFG available?!  */
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index 91811d7..a04958f 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -322,7 +322,6 @@  pass_build_cgraph_edges::execute (function *fun)
 {
   basic_block bb;
   struct cgraph_node *node = cgraph_node::get (current_function_decl);
-  struct pointer_set_t *visited_nodes = pointer_set_create ();
   gimple_stmt_iterator gsi;
   tree decl;
   unsigned ix;
@@ -386,7 +385,6 @@  pass_build_cgraph_edges::execute (function *fun)
       varpool_node::finalize_decl (decl);
   record_eh_tables (node, fun);
 
-  pointer_set_destroy (visited_nodes);
   return 0;
 }
 
@@ -405,15 +403,14 @@  make_pass_build_cgraph_edges (gcc::context *ctxt)
 void
 record_references_in_initializer (tree decl, bool only_vars)
 {
-  struct pointer_set_t *visited_nodes = pointer_set_create ();
   varpool_node *node = varpool_node::get_create (decl);
+  hash_set<tree> visited_nodes;
   struct record_reference_ctx ctx = {false, NULL};
 
   ctx.varpool_node = node;
   ctx.only_vars = only_vars;
   walk_tree (&DECL_INITIAL (decl), record_reference,
-             &ctx, visited_nodes);
-  pointer_set_destroy (visited_nodes);
+             &ctx, &visited_nodes);
 }
 
 /* Rebuild cgraph edges for current function node.  This needs to be run after
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 3080b9a..220b953 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -845,7 +845,7 @@  varpool_node::finalize_decl (tree decl)
    avoid udplicate work.  */
 
 static void
-walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
+walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
 			       struct cgraph_edge *edge)
 {
   unsigned int i;
@@ -855,8 +855,7 @@  walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
     = possible_polymorphic_call_targets
 	(edge, &final, &cache_token);
 
-  if (!pointer_set_insert (reachable_call_targets,
-			   cache_token))
+  if (!reachable_call_targets->add (cache_token))
     {
       if (cgraph_dump_file)
 	dump_possible_polymorphic_call_targets 
@@ -936,7 +935,7 @@  analyze_functions (void)
   struct cgraph_node *first_handled = first_analyzed;
   static varpool_node *first_analyzed_var;
   varpool_node *first_handled_var = first_analyzed_var;
-  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
+  hash_set<void *> reachable_call_targets;
 
   symtab_node *node;
   symtab_node *next;
@@ -1035,7 +1034,7 @@  analyze_functions (void)
 		    {
 		      next = edge->next_callee;
 		      if (edge->indirect_info->polymorphic)
-			walk_polymorphic_call_targets (reachable_call_targets,
+			walk_polymorphic_call_targets (&reachable_call_targets,
 						       edge);
 		    }
 		}
@@ -1123,7 +1122,6 @@  analyze_functions (void)
       symtab_node::dump_table (cgraph_dump_file);
     }
   bitmap_obstack_release (NULL);
-  pointer_set_destroy (reachable_call_targets);
   ggc_collect ();
   /* Initialize assembler name hash, in particular we want to trigger C++
      mangling and same body alias creation before we free DECL_ARGUMENTS
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 0f611e1..d9b34f7 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5359,15 +5359,15 @@  finalize_literal_type_property (tree t)
 void
 explain_non_literal_class (tree t)
 {
-  static struct pointer_set_t *diagnosed;
+  static hash_set<tree> *diagnosed;
 
   if (!CLASS_TYPE_P (t))
     return;
   t = TYPE_MAIN_VARIANT (t);
 
   if (diagnosed == NULL)
-    diagnosed = pointer_set_create ();
-  if (pointer_set_insert (diagnosed, t) != 0)
+    diagnosed = new hash_set<tree>;
+  if (diagnosed->add (t))
     /* Already explained.  */
     return;
 
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index a35177b..3cfcbc6 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -871,7 +871,7 @@  omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
 
 struct cp_genericize_data
 {
-  struct pointer_set_t *p_set;
+  hash_set<tree> *p_set;
   vec<tree> bind_expr_stack;
   struct cp_genericize_omp_taskreg *omp_ctx;
 };
@@ -884,7 +884,7 @@  cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
 {
   tree stmt = *stmt_p;
   struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
-  struct pointer_set_t *p_set = wtd->p_set;
+  hash_set<tree> *p_set = wtd->p_set;
 
   /* If in an OpenMP context, note var uses.  */
   if (__builtin_expect (wtd->omp_ctx != NULL, 0)
@@ -924,7 +924,7 @@  cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
     }
 
   /* Other than invisiref parms, don't walk the same tree twice.  */
-  if (pointer_set_contains (p_set, stmt))
+  if (p_set->contains (stmt))
     {
       *walk_subtrees = 0;
       return NULL_TREE;
@@ -1199,7 +1199,7 @@  cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
       return NULL;
     }    
 
-  pointer_set_insert (p_set, *stmt_p);
+  p_set->add (*stmt_p);
 
   return NULL;
 }
@@ -1211,11 +1211,11 @@  cp_genericize_tree (tree* t_p)
 {
   struct cp_genericize_data wtd;
 
-  wtd.p_set = pointer_set_create ();
+  wtd.p_set = new hash_set<tree>;
   wtd.bind_expr_stack.create (0);
   wtd.omp_ctx = NULL;
   cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
-  pointer_set_destroy (wtd.p_set);
+  delete wtd.p_set;
   wtd.bind_expr_stack.release ();
 }
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0c0d804..622de9c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6028,7 +6028,7 @@  extern void verify_stmt_tree			(tree);
 extern linkage_kind decl_linkage		(tree);
 extern duration_kind decl_storage_duration	(tree);
 extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
-			      void*, struct pointer_set_t*);
+			      void*, hash_set<tree> *);
 #define cp_walk_tree(tp,func,data,pset) \
 	walk_tree_1 (tp, func, data, pset, cp_walk_subtrees)
 #define cp_walk_tree_without_duplicates(tp,func,data) \
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index aafb917..f70684f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8198,7 +8198,7 @@  check_static_variable_definition (tree decl, tree type)
 static tree
 stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
 {
-  struct pointer_set_t *pset = (struct pointer_set_t *)data;
+  hash_set<tree> *pset = (hash_set<tree> *)data;
   tree expr = *expr_p;
   if (TREE_CODE (expr) == SAVE_EXPR)
     {
@@ -8218,10 +8218,9 @@  stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
 static void
 stabilize_vla_size (tree size)
 {
-  struct pointer_set_t *pset = pointer_set_create ();
+  hash_set<tree> pset;
   /* Break out any function calls into temporary variables.  */
-  cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
-  pointer_set_destroy (pset);
+  cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
 }
 
 /* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 8fa3145..d79665e 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3938,11 +3938,11 @@  generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
    supported, collect and return all the functions for which we should
    emit a hidden alias.  */
 
-static struct pointer_set_t *
+static hash_set<tree> *
 collect_candidates_for_java_method_aliases (void)
 {
   struct cgraph_node *node;
-  struct pointer_set_t *candidates = NULL;
+  hash_set<tree> *candidates = NULL;
 
 #ifndef HAVE_GAS_HIDDEN
   return candidates;
@@ -3957,8 +3957,8 @@  collect_candidates_for_java_method_aliases (void)
 	  && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
 	{
 	  if (candidates == NULL)
-	    candidates = pointer_set_create ();
-	  pointer_set_insert (candidates, fndecl);
+	    candidates = new hash_set<tree>;
+	  candidates->add (fndecl);
 	}
     }
 
@@ -3973,7 +3973,7 @@  collect_candidates_for_java_method_aliases (void)
    by collect_candidates_for_java_method_aliases.  */
 
 static void
-build_java_method_aliases (struct pointer_set_t *candidates)
+build_java_method_aliases (hash_set<tree> *candidates)
 {
   struct cgraph_node *node;
 
@@ -3986,7 +3986,7 @@  build_java_method_aliases (struct pointer_set_t *candidates)
       tree fndecl = node->decl;
 
       if (TREE_ASM_WRITTEN (fndecl)
-	  && pointer_set_contains (candidates, fndecl))
+	  && candidates->contains (fndecl))
 	{
 	  /* Mangle the name in a predictable way; we need to reference
 	     this from a java compiled object file.  */
@@ -4296,7 +4296,7 @@  cp_write_global_declarations (void)
   unsigned ssdf_count = 0;
   int retries = 0;
   tree decl;
-  struct pointer_set_t *candidates;
+  hash_set<tree> *candidates;
 
   locus = input_location;
   at_eof = 1;
@@ -4713,7 +4713,7 @@  cp_write_global_declarations (void)
   if (candidates)
     {
       build_java_method_aliases (candidates);
-      pointer_set_destroy (candidates);
+      delete candidates;
     }
 
   finish_repo ();
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index fa3bdc4..c8987ee 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1325,7 +1325,7 @@  dump_template_decl (cxx_pretty_printer *pp, tree t, int flags)
 
 struct find_typenames_t
 {
-  struct pointer_set_t *p_set;
+  hash_set<tree> *p_set;
   vec<tree, va_gc> *typenames;
 };
 
@@ -1351,7 +1351,7 @@  find_typenames_r (tree *tp, int *walk_subtrees, void *data)
       return NULL_TREE;
     }
 
-  if (mv && (mv == *tp || !pointer_set_insert (d->p_set, mv)))
+  if (mv && (mv == *tp || !d->p_set->add (mv)))
     vec_safe_push (d->typenames, mv);
 
   /* Search into class template arguments, which cp_walk_subtrees
@@ -1367,11 +1367,11 @@  static vec<tree, va_gc> *
 find_typenames (tree t)
 {
   struct find_typenames_t ft;
-  ft.p_set = pointer_set_create ();
+  ft.p_set = new hash_set<tree>;
   ft.typenames = NULL;
   cp_walk_tree (&TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
 		find_typenames_r, &ft, ft.p_set);
-  pointer_set_destroy (ft.p_set);
+  delete ft.p_set;
   return ft.typenames;
 }
 
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index e5fa0c1..65c5621 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1480,7 +1480,7 @@  maybe_explain_implicit_delete (tree decl)
   if (DECL_DEFAULTED_FN (decl))
     {
       /* Not marked GTY; it doesn't need to be GC'd or written to PCH.  */
-      static struct pointer_set_t *explained;
+      static hash_set<tree> *explained;
 
       special_function_kind sfk;
       location_t loc;
@@ -1488,8 +1488,8 @@  maybe_explain_implicit_delete (tree decl)
       tree ctype;
 
       if (!explained)
-	explained = pointer_set_create ();
-      if (pointer_set_insert (explained, decl))
+	explained = new hash_set<tree>;
+      if (explained->add (decl))
 	return true;
 
       sfk = special_function_p (decl);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 75b46ac..6e779a6 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -35,7 +35,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "debug.h"
 #include "c-family/c-pragma.h"
 #include "params.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 
 /* The bindings for a particular name in a particular scope.  */
 
@@ -5152,7 +5152,7 @@  struct arg_lookup
   vec<tree, va_gc> *namespaces;
   vec<tree, va_gc> *classes;
   tree functions;
-  struct pointer_set_t *fn_set;
+  hash_set<tree> *fn_set;
 };
 
 static bool arg_assoc (struct arg_lookup*, tree);
@@ -5175,7 +5175,7 @@  add_function (struct arg_lookup *k, tree fn)
   if (!is_overloaded_fn (fn))
     /* All names except those of (possibly overloaded) functions and
        function templates are ignored.  */;
-  else if (k->fn_set && pointer_set_insert (k->fn_set, fn))
+  else if (k->fn_set && k->fn_set->add (fn))
     /* It's already in the list.  */;
   else if (!k->functions)
     k->functions = fn;
@@ -5639,9 +5639,9 @@  lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
       /* We shouldn't be here if lookup found something other than
 	 namespace-scope functions.  */
       gcc_assert (DECL_NAMESPACE_SCOPE_P (OVL_CURRENT (fns)));
-      k.fn_set = pointer_set_create ();
+      k.fn_set = new hash_set<tree>;
       for (ovl = fns; ovl; ovl = OVL_NEXT (ovl))
-	pointer_set_insert (k.fn_set, OVL_CURRENT (ovl));
+	k.fn_set->add (OVL_CURRENT (ovl));
     }
   else
     k.fn_set = NULL;
@@ -5661,8 +5661,7 @@  lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
 
   release_tree_vector (k.classes);
   release_tree_vector (k.namespaces);
-  if (k.fn_set)
-    pointer_set_destroy (k.fn_set);
+  delete k.fn_set;
     
   return fns;
 }
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b32cf6c..9b156f5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -147,7 +147,7 @@  static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
 static tree convert_template_argument (tree, tree, tree,
 				       tsubst_flags_t, int, tree);
 static int for_each_template_parm (tree, tree_fn_t, void*,
-				   struct pointer_set_t*, bool);
+				   hash_set<tree> *, bool);
 static tree expand_template_argument_pack (tree);
 static tree build_template_parm_index (int, int, int, tree, tree);
 static bool inline_needs_template_parms (tree, bool);
@@ -3080,7 +3080,7 @@  struct find_parameter_pack_data
   tree* parameter_packs;
 
   /* Set of AST nodes that have been visited by the traversal.  */
-  struct pointer_set_t *visited;
+  hash_set<tree> *visited;
 };
 
 /* Identifies all of the argument packs that occur in a template
@@ -3243,9 +3243,9 @@  uses_parameter_packs (tree t)
   tree parameter_packs = NULL_TREE;
   struct find_parameter_pack_data ppd;
   ppd.parameter_packs = &parameter_packs;
-  ppd.visited = pointer_set_create ();
+  ppd.visited = new hash_set<tree>;
   cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
-  pointer_set_destroy (ppd.visited);
+  delete ppd.visited;
   return parameter_packs != NULL_TREE;
 }
 
@@ -3292,7 +3292,7 @@  make_pack_expansion (tree arg)
 
       /* Determine which parameter packs will be used by the base
          class expansion.  */
-      ppd.visited = pointer_set_create ();
+      ppd.visited = new hash_set<tree>;
       ppd.parameter_packs = &parameter_packs;
       cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r, 
                     &ppd, ppd.visited);
@@ -3300,7 +3300,7 @@  make_pack_expansion (tree arg)
       if (parameter_packs == NULL_TREE)
         {
           error ("base initializer expansion %<%T%> contains no parameter packs", arg);
-          pointer_set_destroy (ppd.visited);
+          delete ppd.visited;
           return error_mark_node;
         }
 
@@ -3317,7 +3317,7 @@  make_pack_expansion (tree arg)
             }
         }
 
-      pointer_set_destroy (ppd.visited);
+      delete ppd.visited;
 
       /* Create the pack expansion type for the base type.  */
       purpose = cxx_make_type (TYPE_PACK_EXPANSION);
@@ -3352,9 +3352,9 @@  make_pack_expansion (tree arg)
 
   /* Determine which parameter packs will be expanded.  */
   ppd.parameter_packs = &parameter_packs;
-  ppd.visited = pointer_set_create ();
+  ppd.visited = new hash_set<tree>;
   cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
-  pointer_set_destroy (ppd.visited);
+  delete ppd.visited;
 
   /* Make sure we found some parameter packs.  */
   if (parameter_packs == NULL_TREE)
@@ -3399,9 +3399,9 @@  check_for_bare_parameter_packs (tree t)
     t = TREE_TYPE (t);
 
   ppd.parameter_packs = &parameter_packs;
-  ppd.visited = pointer_set_create ();
+  ppd.visited = new hash_set<tree>;
   cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
-  pointer_set_destroy (ppd.visited);
+  delete ppd.visited;
 
   if (parameter_packs) 
     {
@@ -4381,11 +4381,11 @@  fixed_parameter_pack_p (tree parm)
   tree parameter_packs = NULL_TREE;
   struct find_parameter_pack_data ppd;
   ppd.parameter_packs = &parameter_packs;
-  ppd.visited = pointer_set_create ();
+  ppd.visited = new hash_set<tree>;
 
   fixed_parameter_pack_p_1 (parm, &ppd);
 
-  pointer_set_destroy (ppd.visited);
+  delete ppd.visited;
   return parameter_packs;
 }
 
@@ -7907,7 +7907,7 @@  struct pair_fn_data
   /* True when we should also visit template parameters that occur in
      non-deduced contexts.  */
   bool include_nondeduced_p;
-  struct pointer_set_t *visited;
+  hash_set<tree> *visited;
 };
 
 /* Called from for_each_template_parm via walk_tree.  */
@@ -8107,7 +8107,7 @@  for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
 
 static int
 for_each_template_parm (tree t, tree_fn_t fn, void* data,
-			struct pointer_set_t *visited,
+			hash_set<tree> *visited,
 			bool include_nondeduced_p)
 {
   struct pair_fn_data pfd;
@@ -8126,7 +8126,7 @@  for_each_template_parm (tree t, tree_fn_t fn, void* data,
   if (visited)
     pfd.visited = visited;
   else
-    pfd.visited = pointer_set_create ();
+    pfd.visited = new hash_set<tree>;
   result = cp_walk_tree (&t,
 		         for_each_template_parm_r,
 		         &pfd,
@@ -8135,7 +8135,7 @@  for_each_template_parm (tree t, tree_fn_t fn, void* data,
   /* Clean up.  */
   if (!visited)
     {
-      pointer_set_destroy (pfd.visited);
+      delete pfd.visited;
       pfd.visited = 0;
     }
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index c87764d..735284e 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8031,7 +8031,7 @@  register_constexpr_fundef (tree fun, tree body)
 void
 explain_invalid_constexpr_fn (tree fun)
 {
-  static struct pointer_set_t *diagnosed;
+  static hash_set<tree> *diagnosed;
   tree body;
   location_t save_loc;
   /* Only diagnose defaulted functions or instantiations.  */
@@ -8039,8 +8039,8 @@  explain_invalid_constexpr_fn (tree fun)
       && !is_instantiation_of_constexpr (fun))
     return;
   if (diagnosed == NULL)
-    diagnosed = pointer_set_create ();
-  if (pointer_set_insert (diagnosed, fun) != 0)
+    diagnosed = new hash_set<tree>;
+  if (diagnosed->add (fun))
     /* Already explained.  */
     return;
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index f6c5693..697a02b 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -3485,7 +3485,7 @@  cxx_type_hash_eq (const_tree typea, const_tree typeb)
 
 tree
 cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
-		  void *data, struct pointer_set_t *pset)
+		  void *data, hash_set<tree> *pset)
 {
   enum tree_code code = TREE_CODE (*tp);
   tree result;
diff --git a/gcc/cprop.c b/gcc/cprop.c
index 6291c91..4234afa 100644
--- a/gcc/cprop.c
+++ b/gcc/cprop.c
@@ -167,7 +167,7 @@  reg_available_p (const_rtx x, const_rtx insn ATTRIBUTE_UNUSED)
    ??? May need to make things more elaborate.  Later, as necessary.  */
 
 static unsigned int
-hash_set (int regno, int hash_table_size)
+hash_mod (int regno, int hash_table_size)
 {
   return (unsigned) regno % hash_table_size;
 }
@@ -187,7 +187,7 @@  insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table,
   struct expr *cur_expr, *last_expr = NULL;
   struct occr *cur_occr;
 
-  hash = hash_set (REGNO (dest), table->size);
+  hash = hash_mod (REGNO (dest), table->size);
 
   for (cur_expr = table->table[hash]; cur_expr;
        cur_expr = cur_expr->next_same_hash)
@@ -483,7 +483,7 @@  compute_hash_table (struct hash_table_d *table)
 static struct expr *
 lookup_set (unsigned int regno, struct hash_table_d *table)
 {
-  unsigned int hash = hash_set (regno, table->size);
+  unsigned int hash = hash_mod (regno, table->size);
   struct expr *expr;
 
   expr = table->table[hash];
diff --git a/gcc/cse.c b/gcc/cse.c
index 34f9364..dd9a076 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -41,7 +41,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "df.h"
 #include "dbgcnt.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 
 /* The basic idea of common subexpression elimination is to go
    through the code, keeping a record of expressions that would
@@ -2906,7 +2906,7 @@  find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
 		      enum machine_mode *pmode1, enum machine_mode *pmode2)
 {
   rtx arg1, arg2;
-  struct pointer_set_t *visited = NULL;
+  hash_set<rtx> *visited = NULL;
   /* Set nonzero when we find something of interest.  */
   rtx x = NULL;
 
@@ -2923,8 +2923,8 @@  find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
       if (x)
 	{
 	  if (!visited)
-	    visited = pointer_set_create ();
-	  pointer_set_insert (visited, x);
+	    visited = new hash_set<rtx>;
+	  visited->add (x);
 	  x = 0;
 	}
 
@@ -3005,7 +3005,7 @@  find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
 	    continue;
 
 	  /* If it's a comparison we've used before, skip it.  */
-	  if (visited && pointer_set_contains (visited, p->exp))
+	  if (visited && visited->contains (p->exp))
 	    continue;
 
 	  if (GET_CODE (p->exp) == COMPARE
@@ -3087,7 +3087,7 @@  find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
   *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0);
 
   if (visited)
-    pointer_set_destroy (visited);
+    delete visited;
   return code;
 }
 
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 68ba70f..410efb1 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -26,7 +26,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "arith.h"
 #include "match.h"
 #include "parse.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 
 /* Match an end of OpenMP directive.  End of OpenMP directive is optional
    whitespace, followed by '\n' or comment '!'.  */
@@ -3013,8 +3013,8 @@  resolve_omp_atomic (gfc_code *code)
 struct omp_context
 {
   gfc_code *code;
-  struct pointer_set_t *sharing_clauses;
-  struct pointer_set_t *private_iterators;
+  hash_set<gfc_symbol *> *sharing_clauses;
+  hash_set<gfc_symbol *> *private_iterators;
   struct omp_context *previous;
 } *omp_current_ctx;
 static gfc_code *omp_current_do_code;
@@ -3057,8 +3057,8 @@  gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
   int list;
 
   ctx.code = code;
-  ctx.sharing_clauses = pointer_set_create ();
-  ctx.private_iterators = pointer_set_create ();
+  ctx.sharing_clauses = new hash_set<gfc_symbol *>;
+  ctx.private_iterators = new hash_set<gfc_symbol *>;
   ctx.previous = omp_current_ctx;
   omp_current_ctx = &ctx;
 
@@ -3072,7 +3072,7 @@  gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
       case OMP_LIST_REDUCTION:
       case OMP_LIST_LINEAR:
 	for (n = omp_clauses->lists[list]; n; n = n->next)
-	  pointer_set_insert (ctx.sharing_clauses, n->sym);
+	  ctx.sharing_clauses->add (n->sym);
 	break;
       default:
 	break;
@@ -3097,8 +3097,8 @@  gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
     }
 
   omp_current_ctx = ctx.previous;
-  pointer_set_destroy (ctx.sharing_clauses);
-  pointer_set_destroy (ctx.private_iterators);
+  delete ctx.sharing_clauses;
+  delete ctx.private_iterators;
 }
 
 
@@ -3154,10 +3154,10 @@  gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym)
   if (omp_current_ctx == NULL)
     return;
 
-  if (pointer_set_contains (omp_current_ctx->sharing_clauses, sym))
+  if (omp_current_ctx->sharing_clauses->contains (sym))
     return;
 
-  if (! pointer_set_insert (omp_current_ctx->private_iterators, sym))
+  if (! omp_current_ctx->private_iterators->add (sym))
     {
       gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
       gfc_omp_namelist *p;
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 8b56151..babe48f 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -40,7 +40,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "debug.h"
 #include "gfortran.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 #include "constructor.h"
 #include "trans.h"
 #include "trans-types.h"
@@ -63,7 +63,7 @@  static GTY(()) tree parent_fake_result_decl;
 static GTY(()) tree saved_function_decls;
 static GTY(()) tree saved_parent_function_decls;
 
-static struct pointer_set_t *nonlocal_dummy_decl_pset;
+static hash_set<tree> *nonlocal_dummy_decl_pset;
 static GTY(()) tree nonlocal_dummy_decls;
 
 /* Holds the variable DECLs that are locals.  */
@@ -1094,9 +1094,9 @@  gfc_nonlocal_dummy_array_decl (gfc_symbol *sym)
   tree decl, dummy;
 
   if (! nonlocal_dummy_decl_pset)
-    nonlocal_dummy_decl_pset = pointer_set_create ();
+    nonlocal_dummy_decl_pset = new hash_set<tree>;
 
-  if (pointer_set_insert (nonlocal_dummy_decl_pset, sym->backend_decl))
+  if (nonlocal_dummy_decl_pset->add (sym->backend_decl))
     return;
 
   dummy = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl);
@@ -5861,7 +5861,7 @@  gfc_generate_function_code (gfc_namespace * ns)
     {
       BLOCK_VARS (DECL_INITIAL (fndecl))
 	= chainon (BLOCK_VARS (DECL_INITIAL (fndecl)), nonlocal_dummy_decls);
-      pointer_set_destroy (nonlocal_dummy_decl_pset);
+      delete nonlocal_dummy_decl_pset;
       nonlocal_dummy_decls = NULL;
       nonlocal_dummy_decl_pset = NULL;
     }
diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
index b6f0495..f4f6757 100644
--- a/gcc/gimple-walk.c
+++ b/gcc/gimple-walk.c
@@ -180,7 +180,7 @@  tree
 walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
 		struct walk_stmt_info *wi)
 {
-  struct pointer_set_t *pset = (wi) ? wi->pset : NULL;
+  hash_set<tree> *pset = (wi) ? wi->pset : NULL;
   unsigned i;
   tree ret = NULL_TREE;
 
diff --git a/gcc/gimple-walk.h b/gcc/gimple-walk.h
index 555eb18..5b75fdc 100644
--- a/gcc/gimple-walk.h
+++ b/gcc/gimple-walk.h
@@ -36,7 +36,7 @@  struct walk_stmt_info
   /* Pointer map used to mark visited tree nodes when calling
      walk_tree on each operand.  If set to NULL, duplicate tree nodes
      will be visited more than once.  */
-  struct pointer_set_t *pset;
+  hash_set<tree> *pset;
 
   /* Operand returned by the callbacks.  This is set when calling
      walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4ab36d0..c0ae7cc 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -25,6 +25,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tree.h"
 #include "expr.h"
+#include "hash-set.h"
 #include "pointer-set.h"
 #include "hash-table.h"
 #include "basic-block.h"
@@ -134,7 +135,7 @@  struct gimplify_omp_ctx
 {
   struct gimplify_omp_ctx *outer_context;
   splay_tree variables;
-  struct pointer_set_t *privatized_types;
+  hash_set<tree> *privatized_types;
   location_t location;
   enum omp_clause_default_kind default_kind;
   enum omp_region_type region_type;
@@ -352,7 +353,7 @@  new_omp_context (enum omp_region_type region_type)
   c = XCNEW (struct gimplify_omp_ctx);
   c->outer_context = gimplify_omp_ctxp;
   c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
-  c->privatized_types = pointer_set_create ();
+  c->privatized_types = new hash_set<tree>;
   c->location = input_location;
   c->region_type = region_type;
   if ((region_type & ORT_TASK) == 0)
@@ -369,7 +370,7 @@  static void
 delete_omp_context (struct gimplify_omp_ctx *c)
 {
   splay_tree_delete (c->variables);
-  pointer_set_destroy (c->privatized_types);
+  delete c->privatized_types;
   XDELETE (c);
 }
 
@@ -744,7 +745,7 @@  mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
      copy their subtrees if we can make sure to do it only once.  */
   if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
     {
-      if (data && !pointer_set_insert ((struct pointer_set_t *)data, t))
+      if (data && !((hash_set<tree> *)data)->add (t))
 	;
       else
 	*walk_subtrees = 0;
@@ -829,15 +830,14 @@  unshare_body (tree fndecl)
   struct cgraph_node *cgn = cgraph_node::get (fndecl);
   /* If the language requires deep unsharing, we need a pointer set to make
      sure we don't repeatedly unshare subtrees of unshareable nodes.  */
-  struct pointer_set_t *visited
-    = lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
+  hash_set<tree> *visited
+    = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
 
   copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
   copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
   copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
 
-  if (visited)
-    pointer_set_destroy (visited);
+  delete visited;
 
   if (cgn)
     for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
@@ -1733,7 +1733,7 @@  gimplify_conversion (tree *expr_p)
 }
 
 /* Nonlocal VLAs seen in the current function.  */
-static struct pointer_set_t *nonlocal_vlas;
+static hash_set<tree> *nonlocal_vlas;
 
 /* The VAR_DECLs created for nonlocal VLAs for debug info purposes.  */
 static tree nonlocal_vla_vars;
@@ -1784,7 +1784,7 @@  gimplify_var_or_parm_decl (tree *expr_p)
 		 && (ctx->region_type == ORT_WORKSHARE
 		     || ctx->region_type == ORT_SIMD))
 	    ctx = ctx->outer_context;
-	  if (!ctx && !pointer_set_insert (nonlocal_vlas, decl))
+	  if (!ctx && !nonlocal_vlas->add (decl))
 	    {
 	      tree copy = copy_node (decl);
 
@@ -5463,7 +5463,7 @@  omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
     return;
   type = TYPE_MAIN_VARIANT (type);
 
-  if (pointer_set_insert (ctx->privatized_types, type))
+  if (ctx->privatized_types->add (type))
     return;
 
   switch (TREE_CODE (type))
@@ -8766,7 +8766,7 @@  gimplify_body (tree fndecl, bool do_parms)
 
   cgn = cgraph_node::get (fndecl);
   if (cgn && cgn->origin)
-    nonlocal_vlas = pointer_set_create ();
+    nonlocal_vlas = new hash_set<tree>;
 
   /* Make sure input_location isn't set to something weird.  */
   input_location = DECL_SOURCE_LOCATION (fndecl);
@@ -8830,7 +8830,7 @@  gimplify_body (tree fndecl, bool do_parms)
 			 nonlocal_vla_vars);
 	  nonlocal_vla_vars = NULL_TREE;
 	}
-      pointer_set_destroy (nonlocal_vlas);
+      delete nonlocal_vlas;
       nonlocal_vlas = NULL;
     }
 
diff --git a/gcc/godump.c b/gcc/godump.c
index 2afd7f1..7566f4d 100644
--- a/gcc/godump.c
+++ b/gcc/godump.c
@@ -33,7 +33,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-core.h"
 #include "tree.h"
 #include "ggc.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 #include "obstack.h"
 #include "debug.h"
 #include "wide-int-print.h"
@@ -525,11 +525,11 @@  go_type_decl (tree decl, int local)
 struct godump_container
 {
   /* DECLs that we have already seen.  */
-  struct pointer_set_t *decls_seen;
+  hash_set<tree> decls_seen;
 
   /* Types which may potentially have to be defined as dummy
      types.  */
-  struct pointer_set_t *pot_dummy_types;
+  hash_set<const char *> pot_dummy_types;
 
   /* Go keywords.  */
   htab_t keyword_hash;
@@ -569,8 +569,8 @@  go_format_type (struct godump_container *container, tree type,
   ob = &container->type_obstack;
 
   if (TYPE_NAME (type) != NULL_TREE
-      && (pointer_set_contains (container->decls_seen, type)
-	  || pointer_set_contains (container->decls_seen, TYPE_NAME (type)))
+      && (container->decls_seen.contains (type)
+	  || container->decls_seen.contains (TYPE_NAME (type)))
       && (AGGREGATE_TYPE_P (type)
 	  || POINTER_TYPE_P (type)
 	  || TREE_CODE (type) == FUNCTION_TYPE))
@@ -590,7 +590,7 @@  go_format_type (struct godump_container *container, tree type,
       return ret;
     }
 
-  pointer_set_insert (container->decls_seen, type);
+  container->decls_seen.add (type);
 
   switch (TREE_CODE (type))
     {
@@ -697,8 +697,7 @@  go_format_type (struct godump_container *container, tree type,
 	     definition.  So this struct or union is a potential dummy
 	     type.  */
 	  if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
-	    pointer_set_insert (container->pot_dummy_types,
-				IDENTIFIER_POINTER (name));
+	    container->pot_dummy_types.add (IDENTIFIER_POINTER (name));
 
 	  return ret;
         }
@@ -948,10 +947,10 @@  go_output_typedef (struct godump_container *container, tree decl)
      separately.  */
   if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE
       && TYPE_SIZE (TREE_TYPE (decl)) != 0
-      && !pointer_set_contains (container->decls_seen, TREE_TYPE (decl))
+      && !container->decls_seen.contains (TREE_TYPE (decl))
       && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE
-	  || !pointer_set_contains (container->decls_seen,
-				    TYPE_CANONICAL (TREE_TYPE (decl)))))
+	  || !container->decls_seen.contains
+				    (TYPE_CANONICAL (TREE_TYPE (decl)))))
     {
       tree element;
 
@@ -988,10 +987,9 @@  go_output_typedef (struct godump_container *container, tree decl)
 	  mhval->value = xstrdup (buf);
 	  *slot = mhval;
 	}
-      pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
+      container->decls_seen.add (TREE_TYPE (decl));
       if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
-	pointer_set_insert (container->decls_seen,
-			    TYPE_CANONICAL (TREE_TYPE (decl)));
+	container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl)));
     }
 
   if (DECL_NAME (decl) != NULL_TREE)
@@ -1027,7 +1025,7 @@  go_output_typedef (struct godump_container *container, tree decl)
 		     size);
 	}
 
-      pointer_set_insert (container->decls_seen, decl);
+      container->decls_seen.add (decl);
     }
   else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
     {
@@ -1072,11 +1070,11 @@  go_output_var (struct godump_container *container, tree decl)
 {
   bool is_valid;
 
-  if (pointer_set_contains (container->decls_seen, decl)
-      || pointer_set_contains (container->decls_seen, DECL_NAME (decl)))
+  if (container->decls_seen.contains (decl)
+      || container->decls_seen.contains (DECL_NAME (decl)))
     return;
-  pointer_set_insert (container->decls_seen, decl);
-  pointer_set_insert (container->decls_seen, DECL_NAME (decl));
+  container->decls_seen.add (decl);
+  container->decls_seen.add (DECL_NAME (decl));
 
   is_valid = go_format_type (container, TREE_TYPE (decl), true, false);
   if (is_valid
@@ -1103,11 +1101,10 @@  go_output_var (struct godump_container *container, tree decl)
     {
       tree type_name = TYPE_NAME (TREE_TYPE (decl));
       if (TREE_CODE (type_name) == IDENTIFIER_NODE)
-	pointer_set_insert (container->pot_dummy_types,
-			    IDENTIFIER_POINTER (type_name));
+	container->pot_dummy_types.add (IDENTIFIER_POINTER (type_name));
       else if (TREE_CODE (type_name) == TYPE_DECL)
-	pointer_set_insert (container->pot_dummy_types,
-			    IDENTIFIER_POINTER (DECL_NAME (type_name)));
+	container->pot_dummy_types.add
+			    (IDENTIFIER_POINTER (DECL_NAME (type_name)));
     }
 }
 
@@ -1147,10 +1144,10 @@  keyword_hash_init (struct godump_container *container)
 
 /* Traversing the pot_dummy_types and seeing which types are present
    in the global types hash table and creating dummy definitions if
-   not found.  This function is invoked by pointer_set_traverse.  */
+   not found.  This function is invoked by hash_set::traverse.  */
 
-static bool
-find_dummy_types (const void *ptr, void *adata)
+bool
+find_dummy_types (const char *const &ptr, godump_container *adata)
 {
   struct godump_container *data = (struct godump_container *) adata;
   const char *type = (const char *) ptr;
@@ -1175,8 +1172,6 @@  go_finish (const char *filename)
 
   real_debug_hooks->finish (filename);
 
-  container.decls_seen = pointer_set_create ();
-  container.pot_dummy_types = pointer_set_create ();
   container.type_hash = htab_create (100, htab_hash_string,
                                      string_hash_eq, NULL);
   container.invalid_hash = htab_create (10, htab_hash_string,
@@ -1211,11 +1206,9 @@  go_finish (const char *filename)
   htab_traverse_noresize (macro_hash, go_print_macro, NULL);
 
   /* To emit dummy definitions.  */
-  pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
-                        (void *) &container);
+  container.pot_dummy_types.traverse<godump_container *, find_dummy_types>
+                        (&container);
 
-  pointer_set_destroy (container.decls_seen);
-  pointer_set_destroy (container.pot_dummy_types);
   htab_delete (container.type_hash);
   htab_delete (container.invalid_hash);
   htab_delete (container.keyword_hash);
diff --git a/gcc/hash-set.h b/gcc/hash-set.h
new file mode 100644
index 0000000..47bae9e
--- /dev/null
+++ b/gcc/hash-set.h
@@ -0,0 +1,173 @@ 
+/* A type-safe hash set.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+#ifndef hash_set_h
+#define hash_set_h
+
+#include "hash-table.h"
+
+/* implement default behavior for traits when types allow it.  */
+
+struct default_hashset_traits
+{
+  /* Hashes the passed in key.  */
+
+  template<typename T>
+  static hashval_t
+  hash (T *p)
+    {
+      return uintptr_t(p) >> 3;
+    }
+
+  template<typename T> static hashval_t hash(const T &v) { return v; }
+
+  /* Return true if the two keys passed as arguments are equal.  */
+
+  template<typename T>
+  static bool
+  equal (const T &a, const T &b)
+    {
+      return a == b;
+    }
+
+  /* Called to dispose of the key before marking the entry as deleted.  */
+
+  template<typename T> static void remove (T &v) { v.~T (); }
+
+  /* Mark the passed in entry as being deleted.  */
+
+  template<typename T>
+  static void
+  mark_deleted (T *&e)
+    {
+      e = reinterpret_cast<void *> (1);
+    }
+
+  /* Mark the passed in entry as being empty.  */
+
+  template<typename T>
+  static void
+  mark_empty (T *&e)
+    {
+      e = NULL;
+    }
+
+  /* Return true if the passed in entry is marked as deleted.  */
+
+  template<typename T>
+  static bool
+  is_deleted (T *e)
+    {
+      return e == reinterpret_cast<void *> (1);
+    }
+
+  /* Return true if the passed in entry is marked as empty.  */
+
+  template<typename T> static bool is_empty (T *e) { return e == NULL; }
+};
+
+template<typename Key, typename Traits = default_hashset_traits>
+class hash_set
+{
+  struct hash_entry
+  {
+    Key m_key;
+
+    typedef hash_entry value_type;
+    typedef Key compare_type;
+    typedef int store_values_directly;
+
+    static hashval_t hash (const hash_entry &e)
+      {
+       	return Traits::hash (e.m_key);
+      }
+
+    static bool equal (const hash_entry &a, const Key &b)
+       	{
+	  return Traits::equal (a.m_key, b);
+       	}
+
+    static void remove (hash_entry &e) { Traits::remove (e.m_key); }
+
+    static void
+    mark_deleted (hash_entry &e)
+      {
+       	Traits::mark_deleted (e.m_key);
+      }
+
+    static bool is_deleted (const hash_entry &e)
+      {
+       	return Traits::is_deleted (e.m_key);
+      }
+
+    static void
+    mark_empty (hash_entry &e)
+      {
+	Traits::mark_empty (e.m_key);
+      }
+
+    static bool
+    is_empty (const hash_entry &e)
+      {
+	return Traits::is_empty (e.m_key);
+      }
+  };
+
+public:
+  explicit hash_set (size_t n = 13) : m_table (n) {}
+
+  /* If key k isn't already in the map add it to the map, and
+     return false.  Otherwise return true.  */
+
+  bool add (const Key &k)
+    {
+      hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
+						   INSERT);
+      bool existed = !hash_entry::is_empty (*e);
+      if (!existed)
+	e->m_key = k;
+
+      return existed;
+    }
+
+  /* if the passed in key is in the map return its value otherwise NULL.  */
+
+  bool contains (const Key &k)
+    {
+      hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
+      return !Traits::is_empty (e.m_key);
+    }
+
+  /* Call the call back on each pair of key and value with the passed in
+     arg.  */
+
+  template<typename Arg, bool (*f)(const Key &, Arg)>
+  void traverse (Arg a) const
+    {
+      for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
+	   iter != m_table.end (); ++iter)
+	f ((*iter).m_key, a);
+    }
+
+private:
+  hash_table<hash_entry> m_table;
+};
+
+#endif
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 127d58d..70a70a7 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -115,7 +115,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "expr.h"
 #include "tree-pass.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 #include "target.h"
 #include "hash-table.h"
 #include "inchash.h"
@@ -134,7 +134,8 @@  along with GCC; see the file COPYING3.  If not see
 #include "stor-layout.h"
 #include "intl.h"
 
-static bool odr_types_equivalent_p (tree, tree, bool, bool *, pointer_set_t *);
+static bool odr_types_equivalent_p (tree, tree, bool, bool *,
+				    hash_set<tree> *);
 
 static bool odr_violation_reported = false;
 
@@ -144,7 +145,7 @@  const ipa_polymorphic_call_context ipa_dummy_polymorphic_call_context
    = {0, NULL, false, true};
 
 /* Pointer set of all call targets appearing in the cache.  */
-static pointer_set_t *cached_polymorphic_call_targets;
+static hash_set<cgraph_node *> *cached_polymorphic_call_targets;
 
 /* The node of type inheritance graph.  For each type unique in
    One Defintion Rule (ODR) sense, we produce one node linking all 
@@ -163,7 +164,7 @@  struct GTY(()) odr_type_d
   /* All equivalent types, if more than one.  */
   vec<tree, va_gc> *types;
   /* Set of all equivalent types, if NON-NULL.  */
-  pointer_set_t * GTY((skip)) types_set;
+  hash_set<tree> * GTY((skip)) types_set;
 
   /* Unique ID indexing the type in odr_types array.  */
   int id;
@@ -409,7 +410,7 @@  odr_hasher::remove (value_type *v)
   v->bases.release ();
   v->derived_types.release ();
   if (v->types_set)
-    pointer_set_destroy (v->types_set);
+    delete v->types_set;
   ggc_free (v);
 }
 
@@ -439,7 +440,7 @@  set_type_binfo (tree type, tree binfo)
 /* Compare T2 and T2 based on name or structure.  */
 
 static bool
-odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
+odr_subtypes_equivalent_p (tree t1, tree t2, hash_set<tree> *visited)
 {
   bool an1, an2;
 
@@ -473,7 +474,7 @@  odr_subtypes_equivalent_p (tree t1, tree t2, pointer_set_t *visited)
       /* This should really be a pair hash, but for the moment we do not need
 	 100% reliability and it would be better to compare all ODR types so
 	 recursion here is needed only for component types.  */
-      if (pointer_set_insert (visited, t1))
+      if (visited->add (t1))
 	return true;
       return odr_types_equivalent_p (t1, t2, false, NULL, visited);
     }
@@ -562,7 +563,7 @@  warn_types_mismatch (tree t1, tree t2)
    gimple_canonical_types_compatible_p.  */
 
 static bool
-odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, pointer_set_t *visited)
+odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, hash_set<tree> *visited)
 {
   /* Check first for the obvious case of pointer identity.  */
   if (t1 == t2)
@@ -938,7 +939,7 @@  add_type_duplicate (odr_type val, tree type)
 {
   bool build_bases = false;
   if (!val->types_set)
-    val->types_set = pointer_set_create ();
+    val->types_set = new hash_set<tree>;
 
   /* Always prefer complete type to be the leader.  */
   if (!COMPLETE_TYPE_P (val->type)
@@ -952,20 +953,20 @@  add_type_duplicate (odr_type val, tree type)
     }
 
   /* See if this duplicate is new.  */
-  if (!pointer_set_insert (val->types_set, type))
+  if (!val->types_set->add (type))
     {
       bool merge = true;
       bool base_mismatch = false;
       unsigned int i,j;
       bool warned = false;
-      pointer_set_t *visited = pointer_set_create ();
+      hash_set<tree> visited;
 
       gcc_assert (in_lto_p);
       vec_safe_push (val->types, type);
 
       /* First we compare memory layout.  */
       if (!odr_types_equivalent_p (val->type, type, !flag_ltrans && !val->odr_violated,
-				   &warned, visited))
+				   &warned, &visited))
 	{
 	  merge = false;
 	  odr_violation_reported = true;
@@ -980,7 +981,6 @@  add_type_duplicate (odr_type val, tree type)
 	      putc ('\n',cgraph_dump_file);
 	    }
 	}
-      pointer_set_destroy (visited);
 
       /* Next sanity check that bases are the same.  If not, we will end
 	 up producing wrong answers.  */
@@ -1356,7 +1356,7 @@  referenced_from_vtable_p (struct cgraph_node *node)
 
 static void
 maybe_record_node (vec <cgraph_node *> &nodes,
-		   tree target, pointer_set_t *inserted,
+		   tree target, hash_set<tree> *inserted,
 		   bool can_refer,
 		   bool *completep)
 {
@@ -1422,10 +1422,9 @@  maybe_record_node (vec <cgraph_node *> &nodes,
     {
       gcc_assert (!target_node->global.inlined_to);
       gcc_assert (target_node->real_symbol_p ());
-      if (!pointer_set_insert (inserted, target_node->decl))
+      if (!inserted->add (target))
 	{
-	  pointer_set_insert (cached_polymorphic_call_targets,
-			      target_node);
+	  cached_polymorphic_call_targets->add (target_node);
 	  nodes.safe_push (target_node);
 	}
     }
@@ -1465,8 +1464,8 @@  record_target_from_binfo (vec <cgraph_node *> &nodes,
 			  HOST_WIDE_INT otr_token,
 			  tree outer_type,
 			  HOST_WIDE_INT offset,
-			  pointer_set_t *inserted,
-			  pointer_set_t *matched_vtables,
+			  hash_set<tree> *inserted,
+			  hash_set<tree> *matched_vtables,
 			  bool anonymous,
 			  bool *completep)
 {
@@ -1519,8 +1518,8 @@  record_target_from_binfo (vec <cgraph_node *> &nodes,
 	}
       gcc_assert (inner_binfo);
       if (bases_to_consider
-	  ? !pointer_set_contains (matched_vtables, BINFO_VTABLE (inner_binfo))
-	  : !pointer_set_insert (matched_vtables, BINFO_VTABLE (inner_binfo)))
+	  ? !matched_vtables->contains (BINFO_VTABLE (inner_binfo))
+	  : !matched_vtables->add (BINFO_VTABLE (inner_binfo)))
 	{
 	  bool can_refer;
 	  tree target = gimple_get_virt_method_for_binfo (otr_token,
@@ -1559,8 +1558,8 @@  record_target_from_binfo (vec <cgraph_node *> &nodes,
 
 static void
 possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes,
-				     pointer_set_t *inserted,
-				     pointer_set_t *matched_vtables,
+				     hash_set<tree> *inserted,
+				     hash_set<tree> *matched_vtables,
 				     tree otr_type,
 				     odr_type type,
 				     HOST_WIDE_INT otr_token,
@@ -1684,7 +1683,7 @@  free_polymorphic_call_targets_hash ()
     {
       delete polymorphic_call_target_hash;
       polymorphic_call_target_hash = NULL;
-      pointer_set_destroy (cached_polymorphic_call_targets);
+      delete cached_polymorphic_call_targets;
       cached_polymorphic_call_targets = NULL;
     }
 }
@@ -1695,7 +1694,7 @@  static void
 devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
 {
   if (cached_polymorphic_call_targets
-      && pointer_set_contains (cached_polymorphic_call_targets, n))
+      && cached_polymorphic_call_targets->contains (n))
     free_polymorphic_call_targets_hash ();
 }
 
@@ -2277,8 +2276,8 @@  record_targets_from_bases (tree otr_type,
 			   tree outer_type,
 			   HOST_WIDE_INT offset,
 			   vec <cgraph_node *> &nodes,
-			   pointer_set_t *inserted,
-			   pointer_set_t *matched_vtables,
+			   hash_set<tree> *inserted,
+			   hash_set<tree> *matched_vtables,
 			   bool *completep)
 {
   while (true)
@@ -2319,7 +2318,7 @@  record_targets_from_bases (tree otr_type,
 	  return;
 	}
       gcc_assert (base_binfo);
-      if (!pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo)))
+      if (!matched_vtables->add (BINFO_VTABLE (base_binfo)))
 	{
 	  bool can_refer;
 	  tree target = gimple_get_virt_method_for_binfo (otr_token,
@@ -2327,7 +2326,7 @@  record_targets_from_bases (tree otr_type,
 							  &can_refer);
 	  if (!target || ! DECL_CXX_DESTRUCTOR_P (target))
 	    maybe_record_node (nodes, target, inserted, can_refer, completep);
-	  pointer_set_insert (matched_vtables, BINFO_VTABLE (base_binfo));
+	  matched_vtables->add (BINFO_VTABLE (base_binfo));
 	}
     }
 }
@@ -2377,8 +2376,6 @@  possible_polymorphic_call_targets (tree otr_type,
 				   int *nonconstruction_targetsp)
 {
   static struct cgraph_node_hook_list *node_removal_hook_holder;
-  pointer_set_t *inserted;
-  pointer_set_t *matched_vtables;
   vec <cgraph_node *> nodes = vNULL;
   vec <tree> bases_to_consider = vNULL;
   odr_type type, outer_type;
@@ -2457,7 +2454,7 @@  possible_polymorphic_call_targets (tree otr_type,
   /* Initialize query cache.  */
   if (!cached_polymorphic_call_targets)
     {
-      cached_polymorphic_call_targets = pointer_set_create ();
+      cached_polymorphic_call_targets = new hash_set<cgraph_node *>;
       polymorphic_call_target_hash
        	= new polymorphic_call_target_hash_type (23);
       if (!node_removal_hook_holder)
@@ -2496,8 +2493,8 @@  possible_polymorphic_call_targets (tree otr_type,
   (*slot)->otr_token = otr_token;
   (*slot)->context = context;
 
-  inserted = pointer_set_create ();
-  matched_vtables = pointer_set_create ();
+  hash_set<tree> inserted;
+  hash_set<tree> matched_vtables;
 
   /* First see virtual method of type itself.  */
   binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type),
@@ -2526,7 +2523,7 @@  possible_polymorphic_call_targets (tree otr_type,
 
   /* If OUTER_TYPE is abstract, we know we are not seeing its instance.  */
   if (type_possibly_instantiated_p (outer_type->type))
-    maybe_record_node (nodes, target, inserted, can_refer, &complete);
+    maybe_record_node (nodes, target, &inserted, can_refer, &complete);
   else
     {
       skipped = true;
@@ -2534,7 +2531,7 @@  possible_polymorphic_call_targets (tree otr_type,
     }
 
   if (binfo)
-    pointer_set_insert (matched_vtables, BINFO_VTABLE (binfo));
+    matched_vtables.add (BINFO_VTABLE (binfo));
 
   /* Next walk recursively all derived types.  */
   if (context.maybe_derived_type)
@@ -2544,8 +2541,8 @@  possible_polymorphic_call_targets (tree otr_type,
       if (!type->all_derivations_known)
 	complete = false;
       for (i = 0; i < outer_type->derived_types.length(); i++)
-	possible_polymorphic_call_targets_1 (nodes, inserted,
-					     matched_vtables,
+	possible_polymorphic_call_targets_1 (nodes, &inserted,
+					     &matched_vtables,
 					     otr_type,
 					     outer_type->derived_types[i],
 					     otr_token, outer_type->type,
@@ -2571,12 +2568,12 @@  possible_polymorphic_call_targets (tree otr_type,
 	      || (context.maybe_derived_type
 	          && !type_all_derivations_known_p (outer_type->type))))
 	record_targets_from_bases (otr_type, otr_token, outer_type->type,
-				   context.offset, nodes, inserted,
-				   matched_vtables, &complete);
+				   context.offset, nodes, &inserted,
+				   &matched_vtables, &complete);
       if (skipped)
-        maybe_record_node (nodes, target, inserted, can_refer, &complete);
+        maybe_record_node (nodes, target, &inserted, can_refer, &complete);
       for (i = 0; i < bases_to_consider.length(); i++)
-        maybe_record_node (nodes, bases_to_consider[i], inserted, can_refer, &complete);
+        maybe_record_node (nodes, bases_to_consider[i], &inserted, can_refer, &complete);
     }
   bases_to_consider.release();
 
@@ -2587,8 +2584,6 @@  possible_polymorphic_call_targets (tree otr_type,
   if (nonconstruction_targetsp)
     *nonconstruction_targetsp = (*slot)->nonconstruction_targets;
 
-  pointer_set_destroy (inserted);
-  pointer_set_destroy (matched_vtables);
   timevar_pop (TV_IPA_VIRTUAL_CALL);
   return nodes;
 }
@@ -2744,7 +2739,7 @@  static unsigned int
 ipa_devirt (void)
 {
   struct cgraph_node *n;
-  struct pointer_set_t *bad_call_targets = pointer_set_create ();
+  hash_set<void *> bad_call_targets;
   struct cgraph_edge *e;
 
   int npolymorphic = 0, nspeculated = 0, nconverted = 0, ncold = 0;
@@ -2792,8 +2787,7 @@  ipa_devirt (void)
 		if (!dump_file)
 		  continue;
 	      }
-	    if (pointer_set_contains (bad_call_targets,
-				      cache_token))
+	    if (bad_call_targets.contains (cache_token))
 	      {
 		if (dump_file)
 		  fprintf (dump_file, "Target list is known to be useless\n\n");
@@ -2818,7 +2812,7 @@  ipa_devirt (void)
 		}
 	    if (!likely_target)
 	      {
-		pointer_set_insert (bad_call_targets, cache_token);
+		bad_call_targets.add (cache_token);
 	        continue;
 	      }
 	    /* This is reached only when dumping; check if we agree or disagree
@@ -2905,7 +2899,6 @@  ipa_devirt (void)
       if (update)
 	inline_update_overall_summary (n);
     }
-  pointer_set_destroy (bad_call_targets);
 
   if (dump_file)
     fprintf (dump_file,
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 2c281be..b964502 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -65,8 +65,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-scalar-evolution.h"
 #include "intl.h"
 #include "opts.h"
-
-static struct pointer_set_t *visited_nodes;
+#include "hash-set.h"
 
 /* Lattice values for const and pure functions.  Everything starts out
    being const, then may drop to pure and then neither depending on
@@ -133,13 +132,13 @@  function_always_visible_to_compiler_p (tree decl)
 
 /* Emit suggestion about attribute ATTRIB_NAME for DECL.  KNOWN_FINITE
    is true if the function is known to be finite.  The diagnostic is
-   controlled by OPTION.  WARNED_ABOUT is a pointer_set unique for
+   controlled by OPTION.  WARNED_ABOUT is a hash_set<tree> unique for
    OPTION, this function may initialize it and it is always returned
    by the function.  */
 
-static struct pointer_set_t *
+static hash_set<tree> *
 suggest_attribute (int option, tree decl, bool known_finite,
-		   struct pointer_set_t *warned_about,
+		   hash_set<tree> *warned_about,
 		   const char * attrib_name)
 {
   if (!option_enabled (option, &global_options))
@@ -149,10 +148,10 @@  suggest_attribute (int option, tree decl, bool known_finite,
     return warned_about;
 
   if (!warned_about)
-    warned_about = pointer_set_create (); 
-  if (pointer_set_contains (warned_about, decl))
+    warned_about = new hash_set<tree>;
+  if (warned_about->contains (decl))
     return warned_about;
-  pointer_set_insert (warned_about, decl);
+  warned_about->add (decl);
   warning_at (DECL_SOURCE_LOCATION (decl),
 	      option,
 	      known_finite
@@ -168,7 +167,7 @@  suggest_attribute (int option, tree decl, bool known_finite,
 static void
 warn_function_pure (tree decl, bool known_finite)
 {
-  static struct pointer_set_t *warned_about;
+  static hash_set<tree> *warned_about;
 
   warned_about 
     = suggest_attribute (OPT_Wsuggest_attribute_pure, decl,
@@ -181,7 +180,7 @@  warn_function_pure (tree decl, bool known_finite)
 static void
 warn_function_const (tree decl, bool known_finite)
 {
-  static struct pointer_set_t *warned_about;
+  static hash_set<tree> *warned_about;
   warned_about 
     = suggest_attribute (OPT_Wsuggest_attribute_const, decl,
 			 known_finite, warned_about, "const");
@@ -190,7 +189,7 @@  warn_function_const (tree decl, bool known_finite)
 static void
 warn_function_noreturn (tree decl)
 {
-  static struct pointer_set_t *warned_about;
+  static hash_set<tree> *warned_about;
   if (!lang_hooks.missing_noreturn_ok_p (decl)
       && targetm.warn_func_return (decl))
     warned_about 
@@ -846,11 +845,8 @@  add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
      static declarations.  We do not need to scan them more than once
      since all we would be interested in are the addressof
      operations.  */
-  visited_nodes = pointer_set_create ();
   if (node->get_availability () > AVAIL_INTERPOSABLE)
     set_function_state (node, analyze_function (node, true));
-  pointer_set_destroy (visited_nodes);
-  visited_nodes = NULL;
 }
 
 /* Called when new clone is inserted to callgraph late.  */
@@ -912,12 +908,6 @@  pure_const_generate_summary (void)
 
   register_hooks ();
 
-  /* There are some shared nodes, in particular the initializers on
-     static declarations.  We do not need to scan them more than once
-     since all we would be interested in are the addressof
-     operations.  */
-  visited_nodes = pointer_set_create ();
-
   /* Process all of the functions.
 
      We process AVAIL_INTERPOSABLE functions.  We can not use the results
@@ -927,9 +917,6 @@  pure_const_generate_summary (void)
   FOR_EACH_DEFINED_FUNCTION (node)
     if (node->get_availability () >= AVAIL_INTERPOSABLE)
       set_function_state (node, analyze_function (node, true));
-
-  pointer_set_destroy (visited_nodes);
-  visited_nodes = NULL;
 }
 
 
diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
index 4720ee9..bca2bc7 100644
--- a/gcc/ipa-visibility.c
+++ b/gcc/ipa-visibility.c
@@ -687,12 +687,11 @@  function_and_variable_visibility (bool whole_program)
 	      }
 	  if (found)
 	    {
-	      struct pointer_set_t *visited_nodes = pointer_set_create ();
+	      hash_set<tree> visited_nodes;
 
 	      vnode->get_constructor ();
 	      walk_tree (&DECL_INITIAL (vnode->decl),
-			 update_vtable_references, NULL, visited_nodes);
-	      pointer_set_destroy (visited_nodes);
+			 update_vtable_references, NULL, &visited_nodes);
 	      vnode->remove_all_references ();
 	      record_references_in_initializer (vnode->decl, false);
 	    }
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 8198b17..1081e89 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -27,7 +27,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "tree-pass.h"
 #include "hash-map.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 #include "gimple-expr.h"
 #include "gimplify.h"
 #include "flags.h"
@@ -84,14 +84,14 @@  update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined
 
 static void
 enqueue_node (symtab_node *node, symtab_node **first,
-	      struct pointer_set_t *reachable)
+	      hash_set<symtab_node *> *reachable)
 {
   /* Node is still in queue; do nothing.  */
   if (node->aux && node->aux != (void *) 2)
     return;
   /* Node was already processed as unreachable, re-enqueue
      only if it became reachable now.  */
-  if (node->aux == (void *)2 && !pointer_set_contains (reachable, node))
+  if (node->aux == (void *)2 && !reachable->contains (node))
     return;
   node->aux = *first;
   *first = node;
@@ -103,7 +103,7 @@  static void
 process_references (symtab_node *snode,
 		    symtab_node **first,
 		    bool before_inlining_p,
-		    struct pointer_set_t *reachable)
+		    hash_set<symtab_node *> *reachable)
 {
   int i;
   struct ipa_ref *ref = NULL;
@@ -124,7 +124,7 @@  process_references (symtab_node *snode,
 		      && flag_wpa
 		      && ctor_for_folding (node->decl)
 		         != error_mark_node))))
-	pointer_set_insert (reachable, node);
+	reachable->add (node);
       enqueue_node (node, first, reachable);
     }
 }
@@ -138,10 +138,11 @@  process_references (symtab_node *snode,
    possible.  */
 
 static void
-walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
+walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
 			       struct cgraph_edge *edge,
 			       symtab_node **first,
-			       pointer_set_t *reachable, bool before_inlining_p)
+			       hash_set<symtab_node *> *reachable,
+			       bool before_inlining_p)
 {
   unsigned int i;
   void *cache_token;
@@ -150,8 +151,7 @@  walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
     = possible_polymorphic_call_targets
 	(edge, &final, &cache_token);
 
-  if (!pointer_set_insert (reachable_call_targets,
-			   cache_token))
+  if (!reachable_call_targets->add (cache_token))
     {
       for (i = 0; i < targets.length (); i++)
 	{
@@ -172,7 +172,7 @@  walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
 		   && (cgraph_state < CGRAPH_STATE_IPA_SSA
 		       || !lookup_attribute ("always_inline",
 					     DECL_ATTRIBUTES (n->decl)))))
-	     pointer_set_insert (reachable, n);
+	     reachable->add (n);
 
 	  /* Even after inlining we want to keep the possible targets in the
 	     boundary, so late passes can still produce direct call even if
@@ -276,9 +276,9 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
   struct cgraph_node *node, *next;
   varpool_node *vnode, *vnext;
   bool changed = false;
-  struct pointer_set_t *reachable = pointer_set_create ();
-  struct pointer_set_t *body_needed_for_clonning = pointer_set_create ();
-  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
+  hash_set<symtab_node *> reachable;
+  hash_set<tree> body_needed_for_clonning;
+  hash_set<void *> reachable_call_targets;
 
   timevar_push (TV_IPA_UNREACHABLE);
   if (optimize && flag_devirtualize)
@@ -304,8 +304,8 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 	  && !node->can_remove_if_no_direct_calls_and_refs_p ())
 	{
 	  gcc_assert (!node->global.inlined_to);
-	  pointer_set_insert (reachable, node);
-	  enqueue_node (node, &first, reachable);
+	  reachable.add (node);
+	  enqueue_node (node, &first, &reachable);
 	}
       else
 	gcc_assert (!node->aux);
@@ -316,14 +316,14 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
     if (!vnode->can_remove_if_no_refs_p()
 	&& !vnode->in_other_partition)
       {
-	pointer_set_insert (reachable, vnode);
-	enqueue_node (vnode, &first, reachable);
+	reachable.add (vnode);
+	enqueue_node (vnode, &first, &reachable);
       }
 
   /* Perform reachability analysis.  */
   while (first != (symtab_node *) (void *) 1)
     {
-      bool in_boundary_p = !pointer_set_contains (reachable, first);
+      bool in_boundary_p = !reachable.contains (first);
       symtab_node *node = first;
 
       first = (symtab_node *)first->aux;
@@ -340,7 +340,7 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 	      struct cgraph_node *origin_node
 	      = cgraph_node::get_create (DECL_ABSTRACT_ORIGIN (node->decl));
 	      origin_node->used_as_abstract_origin = true;
-	      enqueue_node (origin_node, &first, reachable);
+	      enqueue_node (origin_node, &first, &reachable);
 	    }
 	  /* If any symbol in a comdat group is reachable, force
 	     all externally visible symbols in the same comdat
@@ -353,11 +353,11 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 		   next != node;
 		   next = next->same_comdat_group)
 		if (!next->comdat_local_p ()
-		    && !pointer_set_insert (reachable, next))
-		  enqueue_node (next, &first, reachable);
+		    && !reachable.add (next))
+		  enqueue_node (next, &first, &reachable);
 	    }
 	  /* Mark references as reachable.  */
-	  process_references (node, &first, before_inlining_p, reachable);
+	  process_references (node, &first, before_inlining_p, &reachable);
 	}
 
       if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
@@ -375,8 +375,8 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 		    {
 		      next = e->next_callee;
 		      if (e->indirect_info->polymorphic)
-			walk_polymorphic_call_targets (reachable_call_targets,
-						       e, &first, reachable,
+			walk_polymorphic_call_targets (&reachable_call_targets,
+						       e, &first, &reachable,
 						       before_inlining_p);
 		    }
 		}
@@ -394,17 +394,16 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 		      if (DECL_EXTERNAL (e->callee->decl)
 			  && e->callee->alias
 			  && before_inlining_p)
-			pointer_set_insert (reachable,
-					    e->callee->function_symbol ());
-		      pointer_set_insert (reachable, e->callee);
+			reachable.add (e->callee->function_symbol ());
+		      reachable.add (e->callee);
 		    }
-		  enqueue_node (e->callee, &first, reachable);
+		  enqueue_node (e->callee, &first, &reachable);
 		}
 
 	      /* When inline clone exists, mark body to be preserved so when removing
 		 offline copy of the function we don't kill it.  */
 	      if (cnode->global.inlined_to)
-	        pointer_set_insert (body_needed_for_clonning, cnode->decl);
+	        body_needed_for_clonning.add (cnode->decl);
 
 	      /* For non-inline clones, force their origins to the boundary and ensure
 		 that body is not removed.  */
@@ -414,8 +413,8 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 		  cnode = cnode->clone_of;
 		  if (noninline)
 		    {
-		      pointer_set_insert (body_needed_for_clonning, cnode->decl);
-		      enqueue_node (cnode, &first, reachable);
+		      body_needed_for_clonning.add (cnode->decl);
+		      enqueue_node (cnode, &first, &reachable);
 		    }
 		}
 
@@ -429,8 +428,8 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 		   next;
 		   next = next->simdclone->next_clone)
 		if (in_boundary_p
-		    || !pointer_set_insert (reachable, next))
-		  enqueue_node (next, &first, reachable);
+		    || !reachable.add (next))
+		  enqueue_node (next, &first, &reachable);
 	    }
 	}
       /* When we see constructor of external variable, keep referred nodes in the
@@ -444,7 +443,7 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 	{
 	  struct ipa_ref *ref = NULL;
 	  for (int i = 0; node->iterate_reference (i, ref); i++)
-	    enqueue_node (ref->referred, &first, reachable);
+	    enqueue_node (ref->referred, &first, &reachable);
 	}
     }
 
@@ -462,9 +461,9 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 	  changed = true;
 	}
       /* If node is unreachable, remove its body.  */
-      else if (!pointer_set_contains (reachable, node))
+      else if (!reachable.contains (node))
         {
-	  if (!pointer_set_contains (body_needed_for_clonning, node->decl))
+	  if (!body_needed_for_clonning.contains (node->decl))
 	    node->release_body ();
 	  else if (!node->clone_of)
 	    gcc_assert (in_lto_p || DECL_RESULT (node->decl));
@@ -530,7 +529,7 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 	  vnode->remove ();
 	  changed = true;
 	}
-      else if (!pointer_set_contains (reachable, vnode))
+      else if (!reachable.contains (vnode))
         {
 	  tree init;
 	  if (vnode->definition)
@@ -557,10 +556,6 @@  symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 	vnode->aux = NULL;
     }
 
-  pointer_set_destroy (reachable);
-  pointer_set_destroy (body_needed_for_clonning);
-  pointer_set_destroy (reachable_call_targets);
-
   /* Now update address_taken flags and try to promote functions to be local.  */
   if (file)
     fprintf (file, "\nClearing address taken flags:");
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index b1fcf67..42b0790 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -37,6 +37,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 #include "input.h"
 #include "hashtab.h"
+#include "hash-set.h"
 #include "langhooks.h"
 #include "bitmap.h"
 #include "function.h"
@@ -819,7 +820,7 @@  compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
   int i;
   lto_symtab_encoder_t encoder;
   lto_symtab_encoder_iterator lsei;
-  struct pointer_set_t *reachable_call_targets = pointer_set_create ();
+  hash_set<void *> reachable_call_targets;
 
   encoder = lto_symtab_encoder_new (false);
 
@@ -902,8 +903,7 @@  compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
 	      vec <cgraph_node *>targets
 		= possible_polymorphic_call_targets
 		    (edge, &final, &cache_token);
-	      if (!pointer_set_insert (reachable_call_targets,
-				       cache_token))
+	      if (!reachable_call_targets.add (cache_token))
 		{
 		  for (i = 0; i < targets.length (); i++)
 		    {
@@ -923,7 +923,6 @@  compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
 	    }
     }
   lto_symtab_encoder_delete (in_encoder);
-  pointer_set_destroy (reachable_call_targets);
   return encoder;
 }
 
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 271fbd5..3fd9147 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -32,6 +32,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 #include "input.h"
 #include "hashtab.h"
+#include "hash-set.h"
 #include "basic-block.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
@@ -2433,7 +2434,7 @@  lto_out_decl_state_written_size (struct lto_out_decl_state *state)
 static void
 write_symbol (struct streamer_tree_cache_d *cache,
 	      struct lto_output_stream *stream,
-	      tree t, struct pointer_set_t *seen, bool alias)
+	      tree t, hash_set<const char *> *seen, bool alias)
 {
   const char *name;
   enum gcc_plugin_symbol_kind kind;
@@ -2461,9 +2462,8 @@  write_symbol (struct streamer_tree_cache_d *cache,
      same name manipulations that ASM_OUTPUT_LABELREF does. */
   name = IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name) (name));
 
-  if (pointer_set_contains (seen, name))
+  if (seen->add (name))
     return;
-  pointer_set_insert (seen, name);
 
   streamer_tree_cache_lookup (cache, t, &slot_num);
   gcc_assert (slot_num != (unsigned)-1);
@@ -2588,7 +2588,6 @@  produce_symtab (struct output_block *ob)
 {
   struct streamer_tree_cache_d *cache = ob->writer_cache;
   char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
-  struct pointer_set_t *seen;
   struct lto_output_stream stream;
   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
   lto_symtab_encoder_iterator lsei;
@@ -2596,7 +2595,7 @@  produce_symtab (struct output_block *ob)
   lto_begin_section (section_name, false);
   free (section_name);
 
-  seen = pointer_set_create ();
+  hash_set<const char *> seen;
   memset (&stream, 0, sizeof (stream));
 
   /* Write the symbol table.
@@ -2609,7 +2608,7 @@  produce_symtab (struct output_block *ob)
 
       if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
 	continue;
-      write_symbol (cache, &stream, node->decl, seen, false);
+      write_symbol (cache, &stream, node->decl, &seen, false);
     }
   for (lsei = lsei_start (encoder);
        !lsei_end_p (lsei); lsei_next (&lsei))
@@ -2618,11 +2617,10 @@  produce_symtab (struct output_block *ob)
 
       if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
 	continue;
-      write_symbol (cache, &stream, node->decl, seen, false);
+      write_symbol (cache, &stream, node->decl, &seen, false);
     }
 
   lto_write_stream (&stream);
-  pointer_set_destroy (seen);
 
   lto_end_section ();
 }
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index cb08a88..a5bcf92 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -66,7 +66,7 @@  free_ltrans_partitions (void)
   for (idx = 0; ltrans_partitions.iterate (idx, &part); idx++)
     {
       if (part->initializers_visited)
-	pointer_set_destroy (part->initializers_visited);
+	delete part->initializers_visited;
       /* Symtab encoder is freed after streaming.  */
       free (part);
     }
@@ -101,8 +101,8 @@  add_references_to_partition (ltrans_partition part, symtab_node *node)
 	     && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
       {
 	if (!part->initializers_visited)
-	  part->initializers_visited = pointer_set_create ();
-	if (!pointer_set_insert (part->initializers_visited, ref->referred))
+	  part->initializers_visited = new hash_set<symtab_node *>;
+	if (!part->initializers_visited->add (ref->referred))
 	  add_references_to_partition (part, ref->referred);
       }
 }
@@ -250,7 +250,7 @@  undo_partition (ltrans_partition partition, unsigned int n_nodes)
 
       /* After UNDO we no longer know what was visited.  */
       if (partition->initializers_visited)
-	pointer_set_destroy (partition->initializers_visited);
+	delete partition->initializers_visited;
       partition->initializers_visited = NULL;
 
       if (!node->alias && (cnode = dyn_cast <cgraph_node *> (node)))
diff --git a/gcc/lto/lto-partition.h b/gcc/lto/lto-partition.h
index 8db61b3..50ec2fa 100644
--- a/gcc/lto/lto-partition.h
+++ b/gcc/lto/lto-partition.h
@@ -17,6 +17,7 @@  You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+#include "hash-set.h"
 
 /* Structure describing ltrans partitions.  */
 
@@ -25,7 +26,7 @@  struct ltrans_partition_def
   lto_symtab_encoder_t encoder;
   const char * name;
   int insns;
-  pointer_set_t *initializers_visited;
+  hash_set<symtab_node *> *initializers_visited;
 };
 
 typedef struct ltrans_partition_def *ltrans_partition;
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 0aae085..55ec279 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -47,6 +47,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "predict.h"
 #include "optabs.h"
 #include "target.h"
+#include "hash-set.h"
 #include "pointer-set.h"
 #include "basic-block.h"
 #include "tree-ssa-alias.h"
@@ -1183,7 +1184,7 @@  expand_case (gimple stmt)
      how to expand this switch().  */
   uniq = 0;
   count = 0;
-  struct pointer_set_t *seen_labels = pointer_set_create ();
+  hash_set<tree> seen_labels;
   compute_cases_per_edge (stmt);
 
   for (i = ncases - 1; i >= 1; --i)
@@ -1203,7 +1204,7 @@  expand_case (gimple stmt)
 
       /* If we have not seen this label yet, then increase the
 	 number of unique case node targets seen.  */
-      if (!pointer_set_insert (seen_labels, lab))
+      if (!seen_labels.add (lab))
 	uniq++;
 
       /* The bounds on the case range, LOW and HIGH, have to be converted
@@ -1231,7 +1232,6 @@  expand_case (gimple stmt)
           case_edge->probability / (intptr_t)(case_edge->aux),
           case_node_pool);
     }
-  pointer_set_destroy (seen_labels);
   reset_out_edges_aux (bb);
 
   /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 6fee8a4..e034762 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4691,7 +4691,7 @@  tree_node_can_be_shared (tree t)
 static tree
 verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
 {
-  struct pointer_set_t *visited = (struct pointer_set_t *) data;
+  hash_set<void *> *visited = (hash_set<void *> *) data;
 
   if (tree_node_can_be_shared (*tp))
     {
@@ -4699,7 +4699,7 @@  verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
       return NULL;
     }
 
-  if (pointer_set_insert (visited, *tp))
+  if (visited->add (*tp))
     return *tp;
 
   return NULL;
@@ -4719,9 +4719,9 @@  static int
 verify_eh_throw_stmt_node (void **slot, void *data)
 {
   struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
-  struct pointer_set_t *visited = (struct pointer_set_t *) data;
+  hash_set<void *> *visited = (hash_set<void *> *) data;
 
-  if (!pointer_set_contains (visited, node->stmt))
+  if (!visited->contains (node->stmt))
     {
       error ("dead STMT in EH table");
       debug_gimple_stmt (node->stmt);
@@ -4733,11 +4733,11 @@  verify_eh_throw_stmt_node (void **slot, void *data)
 /* Verify if the location LOCs block is in BLOCKS.  */
 
 static bool
-verify_location (pointer_set_t *blocks, location_t loc)
+verify_location (hash_set<tree> *blocks, location_t loc)
 {
   tree block = LOCATION_BLOCK (loc);
   if (block != NULL_TREE
-      && !pointer_set_contains (blocks, block))
+      && !blocks->contains (block))
     {
       error ("location references block not in block tree");
       return true;
@@ -4770,7 +4770,7 @@  verify_expr_no_block (tree *tp, int *walk_subtrees, void *)
 static tree
 verify_expr_location_1 (tree *tp, int *walk_subtrees, void *data)
 {
-  struct pointer_set_t *blocks = (struct pointer_set_t *) data;
+  hash_set<tree> *blocks = (hash_set<tree> *) data;
 
   if (TREE_CODE (*tp) == VAR_DECL
       && DECL_HAS_DEBUG_EXPR_P (*tp))
@@ -4816,12 +4816,12 @@  verify_expr_location (tree *tp, int *walk_subtrees, void *data)
 /* Insert all subblocks of BLOCK into BLOCKS and recurse.  */
 
 static void
-collect_subblocks (pointer_set_t *blocks, tree block)
+collect_subblocks (hash_set<tree> *blocks, tree block)
 {
   tree t;
   for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
     {
-      pointer_set_insert (blocks, t);
+      blocks->add (t);
       collect_subblocks (blocks, t);
     }
 }
@@ -4833,18 +4833,17 @@  verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
 {
   basic_block bb;
   bool err = false;
-  struct pointer_set_t *visited, *visited_stmts, *blocks;
 
   timevar_push (TV_TREE_STMT_VERIFY);
-  visited = pointer_set_create ();
-  visited_stmts = pointer_set_create ();
+  hash_set<void *> visited;
+  hash_set<gimple> visited_stmts;
 
   /* Collect all BLOCKs referenced by the BLOCK tree of FN.  */
-  blocks = pointer_set_create ();
+  hash_set<tree> blocks;
   if (DECL_INITIAL (fn->decl))
     {
-      pointer_set_insert (blocks, DECL_INITIAL (fn->decl));
-      collect_subblocks (blocks, DECL_INITIAL (fn->decl));
+      blocks.add (DECL_INITIAL (fn->decl));
+      collect_subblocks (&blocks, DECL_INITIAL (fn->decl));
     }
 
   FOR_EACH_BB_FN (bb, fn)
@@ -4857,7 +4856,7 @@  verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
 	  bool err2 = false;
 	  unsigned i;
 
-	  pointer_set_insert (visited_stmts, phi);
+	  visited_stmts.add (phi);
 
 	  if (gimple_bb (phi) != bb)
 	    {
@@ -4878,7 +4877,7 @@  verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
 	    {
 	      tree arg = gimple_phi_arg_def (phi, i);
 	      tree addr = walk_tree (&arg, verify_node_sharing_1,
-				     visited, NULL);
+				     &visited, NULL);
 	      if (addr)
 		{
 		  error ("incorrect sharing of tree nodes");
@@ -4892,13 +4891,13 @@  verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
 		  error ("virtual PHI with argument locations");
 		  err2 = true;
 		}
-	      addr = walk_tree (&arg, verify_expr_location_1, blocks, NULL);
+	      addr = walk_tree (&arg, verify_expr_location_1, &blocks, NULL);
 	      if (addr)
 		{
 		  debug_generic_expr (addr);
 		  err2 = true;
 		}
-	      err2 |= verify_location (blocks, loc);
+	      err2 |= verify_location (&blocks, loc);
 	    }
 
 	  if (err2)
@@ -4914,7 +4913,7 @@  verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
 	  tree addr;
 	  int lp_nr;
 
-	  pointer_set_insert (visited_stmts, stmt);
+	  visited_stmts.add (stmt);
 
 	  if (gimple_bb (stmt) != bb)
 	    {
@@ -4923,10 +4922,10 @@  verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
 	    }
 
 	  err2 |= verify_gimple_stmt (stmt);
-	  err2 |= verify_location (blocks, gimple_location (stmt));
+	  err2 |= verify_location (&blocks, gimple_location (stmt));
 
 	  memset (&wi, 0, sizeof (wi));
-	  wi.info = (void *) visited;
+	  wi.info = (void *) &visited;
 	  addr = walk_gimple_op (stmt, verify_node_sharing, &wi);
 	  if (addr)
 	    {
@@ -4936,7 +4935,7 @@  verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
 	    }
 
 	  memset (&wi, 0, sizeof (wi));
-	  wi.info = (void *) blocks;
+	  wi.info = (void *) &blocks;
 	  addr = walk_gimple_op (stmt, verify_expr_location, &wi);
 	  if (addr)
 	    {
@@ -4992,14 +4991,11 @@  verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
   if (get_eh_throw_stmt_table (cfun))
     htab_traverse (get_eh_throw_stmt_table (cfun),
 		   verify_eh_throw_stmt_node,
-		   visited_stmts);
+		   &visited_stmts);
 
   if (err || eh_error_found)
     internal_error ("verify_gimple failed");
 
-  pointer_set_destroy (visited);
-  pointer_set_destroy (visited_stmts);
-  pointer_set_destroy (blocks);
   verify_histograms ();
   timevar_pop (TV_TREE_STMT_VERIFY);
 }
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 34c48fa..9d462d1 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -21,6 +21,7 @@  along with GCC; see the file COPYING3.  If not see
 #define GCC_TREE_CORE_H
 
 #include "hashtab.h"
+#include "hash-set.h"
 #include "machmode.h"
 #include "input.h"
 #include "statistics.h"
@@ -45,7 +46,6 @@  struct fixed_value;
 struct ptr_info_def;
 struct range_info_def;
 struct die_struct;
-struct pointer_set_t;
 
 
 /*---------------------------------------------------------------------------
@@ -692,7 +692,7 @@  typedef tree (*walk_tree_fn) (tree *, int *, void *);
 
 /* The type of a callback function that represents a custom walk_tree.  */
 typedef tree (*walk_tree_lh) (tree *, int *, tree (*) (tree *, int *, void *),
-			      void *, struct pointer_set_t*);
+			      void *, hash_set<tree> *);
 
 
 /*---------------------------------------------------------------------------
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index df9a6fc..38842e8 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -28,6 +28,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "function.h"
 #include "except.h"
+#include "hash-set.h"
 #include "pointer-set.h"
 #include "basic-block.h"
 #include "tree-ssa-alias.h"
@@ -3578,7 +3579,7 @@  lower_eh_dispatch (basic_block src, gimple stmt)
 	eh_catch c;
 	edge_iterator ei;
 	edge e;
-	struct pointer_set_t *seen_values = pointer_set_create ();
+	hash_set<tree> seen_values;
 
 	/* Collect the labels for a switch.  Zero the post_landing_pad
 	   field becase we'll no longer have anything keeping these labels
@@ -3605,12 +3606,12 @@  lower_eh_dispatch (basic_block src, gimple stmt)
 		   attached to the handler anymore, we remove 
 		   the corresponding edge and then we delete unreachable 
 		   blocks at the end of this pass.  */
-		if (! pointer_set_contains (seen_values, TREE_VALUE (flt_node)))
+		if (! seen_values.contains (TREE_VALUE (flt_node)))
 		  {
 		    tree t = build_case_label (TREE_VALUE (flt_node),
 					       NULL, lab);
 		    labels.safe_push (t);
-		    pointer_set_insert (seen_values, TREE_VALUE (flt_node));
+		    seen_values.add (TREE_VALUE (flt_node));
 		    have_label = true;
 		  }
 
@@ -3662,7 +3663,6 @@  lower_eh_dispatch (basic_block src, gimple stmt)
 	    x = gimple_build_switch (filter, default_label, labels);
 	    gsi_insert_before (&gsi, x, GSI_SAME_STMT);
 	  }
-	pointer_set_destroy (seen_values);
       }
       break;
 
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 33705b7..6af4912 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1788,7 +1788,7 @@  copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 	     expensive, copy_body can be told to watch for nontrivial
 	     changes.  */
 	  if (id->statements_to_fold)
-	    pointer_set_insert (id->statements_to_fold, stmt);
+	    id->statements_to_fold->add (stmt);
 
 	  /* We're duplicating a CALL_EXPR.  Find any corresponding
 	     callgraph edges and update or duplicate them.  */
@@ -3507,7 +3507,6 @@  inline_forbidden_p (tree fndecl)
 {
   struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
   struct walk_stmt_info wi;
-  struct pointer_set_t *visited_nodes;
   basic_block bb;
   bool forbidden_p = false;
 
@@ -3518,10 +3517,10 @@  inline_forbidden_p (tree fndecl)
 
   /* Next, walk the statements of the function looking for
      constraucts we can't handle, or are non-optimal for inlining.  */
-  visited_nodes = pointer_set_create ();
+  hash_set<tree> visited_nodes;
   memset (&wi, 0, sizeof (wi));
   wi.info = (void *) fndecl;
-  wi.pset = visited_nodes;
+  wi.pset = &visited_nodes;
 
   FOR_EACH_BB_FN (bb, fun)
     {
@@ -3533,7 +3532,6 @@  inline_forbidden_p (tree fndecl)
 	break;
     }
 
-  pointer_set_destroy (visited_nodes);
   return forbidden_p;
 }
 
@@ -4531,7 +4529,7 @@  gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
    in the STATEMENTS pointer set.  */
 
 static void
-fold_marked_statements (int first, struct pointer_set_t *statements)
+fold_marked_statements (int first, hash_set<gimple> *statements)
 {
   for (; first < n_basic_blocks_for_fn (cfun); first++)
     if (BASIC_BLOCK_FOR_FN (cfun, first))
@@ -4541,7 +4539,7 @@  fold_marked_statements (int first, struct pointer_set_t *statements)
 	for (gsi = gsi_start_bb (BASIC_BLOCK_FOR_FN (cfun, first));
 	     !gsi_end_p (gsi);
 	     gsi_next (&gsi))
-	  if (pointer_set_contains (statements, gsi_stmt (gsi)))
+	  if (statements->contains (gsi_stmt (gsi)))
 	    {
 	      gimple old_stmt = gsi_stmt (gsi);
 	      tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
@@ -4642,7 +4640,7 @@  optimize_inline_calls (tree fn)
   id.transform_return_to_modify = true;
   id.transform_parameter = true;
   id.transform_lang_insert_block = NULL;
-  id.statements_to_fold = pointer_set_create ();
+  id.statements_to_fold = new hash_set<gimple>;
 
   push_gimplify_context ();
 
@@ -4678,7 +4676,7 @@  optimize_inline_calls (tree fn)
 
   /* Fold queued statements.  */
   fold_marked_statements (last, id.statements_to_fold);
-  pointer_set_destroy (id.statements_to_fold);
+  delete id.statements_to_fold;
 
   gcc_assert (!id.debug_stmts.exists ());
 
@@ -4920,7 +4918,6 @@  copy_gimple_seq_and_replace_locals (gimple_seq seq)
 {
   copy_body_data id;
   struct walk_stmt_info wi;
-  struct pointer_set_t *visited;
   gimple_seq copy;
 
   /* There's nothing to do for NULL_TREE.  */
@@ -4943,11 +4940,10 @@  copy_gimple_seq_and_replace_locals (gimple_seq seq)
 
   /* Walk the tree once to find local labels.  */
   memset (&wi, 0, sizeof (wi));
-  visited = pointer_set_create ();
+  hash_set<tree> visited;
   wi.info = &id;
-  wi.pset = visited;
+  wi.pset = &visited;
   walk_gimple_seq (seq, mark_local_labels_stmt, NULL, &wi);
-  pointer_set_destroy (visited);
 
   copy = gimple_seq_copy (seq);
 
@@ -5370,7 +5366,7 @@  tree_function_versioning (tree old_decl, tree new_decl,
   memset (&id, 0, sizeof (id));
 
   /* Generate a new name for the new version. */
-  id.statements_to_fold = pointer_set_create ();
+  id.statements_to_fold = new hash_set<gimple>;
 
   id.decl_map = pointer_map_create ();
   id.debug_map = NULL;
@@ -5541,7 +5537,7 @@  tree_function_versioning (tree old_decl, tree new_decl,
   free_dominance_info (CDI_POST_DOMINATORS);
 
   fold_marked_statements (0, id.statements_to_fold);
-  pointer_set_destroy (id.statements_to_fold);
+  delete id.statements_to_fold;
   fold_cond_expr_cond ();
   delete_unreachable_blocks_update_callgraph (&id);
   if (id.dst_node->definition)
diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
index 2a5daaf..c13e6c7 100644
--- a/gcc/tree-inline.h
+++ b/gcc/tree-inline.h
@@ -21,6 +21,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_TREE_INLINE_H
 #define GCC_TREE_INLINE_H
 
+#include "hash-set.h"
+
 struct cgraph_edge;
 
 /* Indicate the desired behavior wrt call graph edges.  We can either
@@ -114,7 +116,7 @@  struct copy_body_data
   void (*transform_lang_insert_block) (tree);
 
   /* Statements that might be possibly folded.  */
-  struct pointer_set_t *statements_to_fold;
+  hash_set<gimple> *statements_to_fold;
 
   /* Entry basic block to currently copied body.  */
   basic_block entry_bb;
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 185d87c..45c5cf7 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -95,7 +95,7 @@  struct nesting_info
 
   struct pointer_map_t *field_map;
   struct pointer_map_t *var_map;
-  struct pointer_set_t *mem_refs;
+  hash_set<tree *> *mem_refs;
   bitmap suppress_expansion;
 
   tree context;
@@ -732,7 +732,7 @@  create_nesting_tree (struct cgraph_node *cgn)
   struct nesting_info *info = XCNEW (struct nesting_info);
   info->field_map = pointer_map_create ();
   info->var_map = pointer_map_create ();
-  info->mem_refs = pointer_set_create ();
+  info->mem_refs = new hash_set<tree *>;
   info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
   info->context = cgn->decl;
 
@@ -1651,7 +1651,7 @@  convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
 	 fold here, as the chain record type is not yet finalized.  */
       if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
 	  && !DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
-	pointer_set_insert (info->mem_refs, tp);
+	info->mem_refs->add (tp);
       wi->val_only = save_val_only;
       break;
 
@@ -2655,8 +2655,8 @@  remap_vla_decls (tree block, struct nesting_info *root)
 }
 
 /* Fold the MEM_REF *E.  */
-static bool
-fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED)
+bool
+fold_mem_refs (tree *const &e, void *data ATTRIBUTE_UNUSED)
 {
   tree *ref_p = CONST_CAST2 (tree *, const tree *, (const tree *)e);
   *ref_p = fold (*ref_p);
@@ -2878,7 +2878,7 @@  finalize_nesting_tree_1 (struct nesting_info *root)
     }
 
   /* Fold the rewritten MEM_REF trees.  */
-  pointer_set_traverse (root->mem_refs, fold_mem_refs, NULL);
+  root->mem_refs->traverse<void *, fold_mem_refs> (NULL);
 
   /* Dump the translated tree function.  */
   if (dump_file)
@@ -2933,7 +2933,7 @@  free_nesting_tree (struct nesting_info *root)
       next = iter_nestinfo_next (node);
       pointer_map_destroy (node->var_map);
       pointer_map_destroy (node->field_map);
-      pointer_set_destroy (node->mem_refs);
+      delete node->mem_refs;
       free (node);
       node = next;
     }
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index ca6e014..aee0331 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -27,7 +27,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "expr.h"
 #include "tree-pretty-print.h"
 #include "hashtab.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 #include "gimple-expr.h"
 #include "cgraph.h"
 #include "langhooks.h"
@@ -103,14 +103,14 @@  debug_generic_stmt (tree t)
 DEBUG_FUNCTION void
 debug_tree_chain (tree t)
 {
-  struct pointer_set_t *seen = pointer_set_create ();
+  hash_set<tree> seen;
 
   while (t)
     {
       print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
       fprintf (stderr, " ");
       t = TREE_CHAIN (t);
-      if (pointer_set_insert (seen, t))
+      if (seen.add (t))
 	{
 	  fprintf (stderr, "... [cycled back to ");
 	  print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS|TDF_UID);
@@ -119,8 +119,6 @@  debug_tree_chain (tree t)
 	}
     }
   fprintf (stderr, "\n");
-
-  pointer_set_destroy (seen);
 }
 
 /* Prints declaration DECL to the FILE with details specified by FLAGS.  */
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 36d68a8..83c1b19 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -28,6 +28,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "basic-block.h"
 #include "gimple-pretty-print.h"
 #include "intl.h"
+#include "hash-set.h"
 #include "pointer-set.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
@@ -3281,7 +3282,7 @@  discover_iteration_bound_by_body_walk (struct loop *loop)
 static void
 maybe_lower_iteration_bound (struct loop *loop)
 {
-  pointer_set_t *not_executed_last_iteration = NULL;
+  hash_set<gimple> *not_executed_last_iteration = NULL;
   struct nb_iter_bound *elt;
   bool found_exit = false;
   vec<basic_block> queue = vNULL;
@@ -3300,8 +3301,8 @@  maybe_lower_iteration_bound (struct loop *loop)
 	  && wi::ltu_p (elt->bound, loop->nb_iterations_upper_bound))
 	{
 	  if (!not_executed_last_iteration)
-	    not_executed_last_iteration = pointer_set_create ();
-	  pointer_set_insert (not_executed_last_iteration, elt->stmt);
+	    not_executed_last_iteration = new hash_set<gimple>;
+	  not_executed_last_iteration->add (elt->stmt);
 	}
     }
   if (!not_executed_last_iteration)
@@ -3327,7 +3328,7 @@  maybe_lower_iteration_bound (struct loop *loop)
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
 	{
 	  gimple stmt = gsi_stmt (gsi);
-	  if (pointer_set_contains (not_executed_last_iteration, stmt))
+	  if (not_executed_last_iteration->contains (stmt))
 	    {
 	      stmt_found = true;
 	      break;
@@ -3376,7 +3377,7 @@  maybe_lower_iteration_bound (struct loop *loop)
     }
   BITMAP_FREE (visited);
   queue.release ();
-  pointer_set_destroy (not_executed_last_iteration);
+  delete not_executed_last_iteration;
 }
 
 /* Records estimates on numbers of iterations of LOOP.  If USE_UNDEFINED_P
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 052d760..3185d9a 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -27,6 +27,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "tm_p.h"
 #include "basic-block.h"
+#include "hash-set.h"
 #include "pointer-set.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
@@ -72,9 +73,9 @@  static bool abs_replacement (basic_block, basic_block,
 static bool neg_replacement (basic_block, basic_block,
 			     edge, edge, gimple, tree, tree);
 static bool cond_store_replacement (basic_block, basic_block, edge, edge,
-				    struct pointer_set_t *);
+				    hash_set<tree> *);
 static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
-static struct pointer_set_t * get_non_trapping (void);
+static hash_set<tree> * get_non_trapping ();
 static void replace_phi_edge_with_variable (basic_block, edge, gimple, tree);
 static void hoist_adjacent_loads (basic_block, basic_block,
 				  basic_block, basic_block);
@@ -176,7 +177,7 @@  tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
   basic_block *bb_order;
   unsigned n, i;
   bool cfgchanged = false;
-  struct pointer_set_t *nontrap = 0;
+  hash_set<tree> *nontrap = 0;
 
   if (do_store_elim)
     /* Calculate the set of non-trapping memory accesses.  */
@@ -363,7 +364,7 @@  tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
   free (bb_order);
 
   if (do_store_elim)
-    pointer_set_destroy (nontrap);
+    delete nontrap;
   /* If the CFG has changed, we should cleanup the CFG.  */
   if (cfgchanged && do_store_elim)
     {
@@ -1469,7 +1470,7 @@  ssa_names_hasher::equal (const value_type *n1, const compare_type *n2)
 class nontrapping_dom_walker : public dom_walker
 {
 public:
-  nontrapping_dom_walker (cdi_direction direction, pointer_set_t *ps)
+  nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps)
     : dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {}
 
   virtual void before_dom_children (basic_block);
@@ -1484,7 +1485,7 @@  private:
      the RHS.  */
   void add_or_mark_expr (basic_block, tree, bool);
 
-  pointer_set_t *m_nontrapping;
+  hash_set<tree> *m_nontrapping;
 
   /* The hash table for remembering what we've seen.  */
   hash_table<ssa_names_hasher> m_seen_ssa_names;
@@ -1572,7 +1573,7 @@  nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
 	 then we can't trap.  */
       if (found_bb && (((size_t)found_bb->aux) & 1) == 1)
 	{
-	  pointer_set_insert (m_nontrapping, exp);
+	  m_nontrapping->add (exp);
 	}
       else
         {
@@ -1601,11 +1602,11 @@  nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
    It will do a dominator walk over the whole function, and it will
    make use of the bb->aux pointers.  It returns a set of trees
    (the MEM_REFs itself) which can't trap.  */
-static struct pointer_set_t *
+static hash_set<tree> *
 get_non_trapping (void)
 {
   nt_call_phase = 0;
-  pointer_set_t *nontrap = pointer_set_create ();
+  hash_set<tree> *nontrap = new hash_set<tree>;
   /* We're going to do a dominator walk, so ensure that we have
      dominance information.  */
   calculate_dominance_info (CDI_DOMINATORS);
@@ -1634,7 +1635,7 @@  get_non_trapping (void)
 
 static bool
 cond_store_replacement (basic_block middle_bb, basic_block join_bb,
-			edge e0, edge e1, struct pointer_set_t *nontrap)
+			edge e0, edge e1, hash_set<tree> *nontrap)
 {
   gimple assign = last_and_only_stmt (middle_bb);
   tree lhs, rhs, name, name2;
@@ -1659,7 +1660,7 @@  cond_store_replacement (basic_block middle_bb, basic_block join_bb,
   /* Prove that we can move the store down.  We could also check
      TREE_THIS_NOTRAP here, but in that case we also could move stores,
      whose value is not available readily, which we want to avoid.  */
-  if (!pointer_set_contains (nontrap, lhs))
+  if (!nontrap->contains (lhs))
     return false;
 
   /* Now we've checked the constraints, so do the transformation:
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 9807b42..3dee5ba 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -30,7 +30,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "function.h"
 #include "timevar.h"
 #include "dumpfile.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
 #include "gimple-expr.h"
@@ -693,13 +693,13 @@  propagate_threaded_block_debug_into (basic_block dest, basic_block src)
     }
 
   auto_vec<tree, alloc_count> fewvars;
-  pointer_set_t *vars = NULL;
+  hash_set<tree> *vars = NULL;
 
   /* If we're already starting with 3/4 of alloc_count, go for a
-     pointer_set, otherwise start with an unordered stack-allocated
+     hash_set, otherwise start with an unordered stack-allocated
      VEC.  */
   if (i * 4 > alloc_count * 3)
-    vars = pointer_set_create ();
+    vars = new hash_set<tree>;
 
   /* Now go through the initial debug stmts in DEST again, this time
      actually inserting in VARS or FEWVARS.  Don't bother checking for
@@ -720,7 +720,7 @@  propagate_threaded_block_debug_into (basic_block dest, basic_block src)
 	gcc_unreachable ();
 
       if (vars)
-	pointer_set_insert (vars, var);
+	vars->add (var);
       else
 	fewvars.quick_push (var);
     }
@@ -754,7 +754,7 @@  propagate_threaded_block_debug_into (basic_block dest, basic_block src)
 	     or somesuch.  Adding `&& bb == src' to the condition
 	     below will preserve all potentially relevant debug
 	     notes.  */
-	  if (vars && pointer_set_insert (vars, var))
+	  if (vars && vars->add (var))
 	    continue;
 	  else if (!vars)
 	    {
@@ -769,11 +769,11 @@  propagate_threaded_block_debug_into (basic_block dest, basic_block src)
 		fewvars.quick_push (var);
 	      else
 		{
-		  vars = pointer_set_create ();
+		  vars = new hash_set<tree>;
 		  for (i = 0; i < alloc_count; i++)
-		    pointer_set_insert (vars, fewvars[i]);
+		    vars->add (fewvars[i]);
 		  fewvars.release ();
-		  pointer_set_insert (vars, var);
+		  vars->add (var);
 		}
 	    }
 
@@ -786,7 +786,7 @@  propagate_threaded_block_debug_into (basic_block dest, basic_block src)
   while (bb != src && single_pred_p (bb));
 
   if (vars)
-    pointer_set_destroy (vars);
+    delete vars;
   else if (fewvars.exists ())
     fewvars.release ();
 }
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 64259fb..f2578b7 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -29,6 +29,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "function.h"
 #include "gimple-pretty-print.h"
 #include "bitmap.h"
+#include "hash-set.h"
 #include "pointer-set.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
@@ -60,7 +61,7 @@  along with GCC; see the file COPYING3.  If not see
 /* Pointer set of potentially undefined ssa names, i.e.,
    ssa names that are defined by phi with operands that
    are not defined or potentially undefined.  */
-static pointer_set_t *possibly_undefined_names = 0;
+static hash_set<tree> *possibly_undefined_names = 0;
 
 /* Bit mask handling macros.  */
 #define MASK_SET_BIT(mask, pos) mask |= (1 << pos)
@@ -89,7 +90,7 @@  has_undefined_value_p (tree t)
 {
   return (ssa_undefined_value_p (t)
           || (possibly_undefined_names
-              && pointer_set_contains (possibly_undefined_names, t)));
+              && possibly_undefined_names->contains (t)));
 }
 
 
@@ -648,13 +649,13 @@  find_predicates (pred_chain_union *preds,
 static void
 collect_phi_def_edges (gimple phi, basic_block cd_root,
                        vec<edge> *edges,
-                       pointer_set_t *visited_phis)
+                       hash_set<gimple> *visited_phis)
 {
   size_t i, n;
   edge opnd_edge;
   tree opnd;
 
-  if (pointer_set_insert (visited_phis, phi))
+  if (visited_phis->add (phi))
     return;
 
   n = gimple_phi_num_args (phi);
@@ -707,7 +708,6 @@  find_def_preds (pred_chain_union *preds, gimple phi)
   vec<edge> def_edges = vNULL;
   bool has_valid_pred = false;
   basic_block phi_bb, cd_root = 0;
-  pointer_set_t *visited_phis;
 
   phi_bb = gimple_bb (phi);
   /* First find the closest dominating bb to be
@@ -716,9 +716,8 @@  find_def_preds (pred_chain_union *preds, gimple phi)
   if (!cd_root)
     return false;
 
-  visited_phis = pointer_set_create ();
-  collect_phi_def_edges (phi, cd_root, &def_edges, visited_phis);
-  pointer_set_destroy (visited_phis);
+  hash_set<gimple> visited_phis;
+  collect_phi_def_edges (phi, cd_root, &def_edges, &visited_phis);
 
   n = def_edges.length ();
   if (n == 0)
@@ -941,7 +940,7 @@  is_use_properly_guarded (gimple use_stmt,
                          basic_block use_bb,
                          gimple phi,
                          unsigned uninit_opnds,
-                         pointer_set_t *visited_phis);
+                         hash_set<gimple> *visited_phis);
 
 /* Returns true if all uninitialized opnds are pruned. Returns false
    otherwise. PHI is the phi node with uninitialized operands,
@@ -983,7 +982,7 @@  prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
 					      gimple flag_def,
 					      tree boundary_cst,
 					      enum tree_code cmp_code,
-					      pointer_set_t *visited_phis,
+					      hash_set<gimple> *visited_phis,
 					      bitmap *visited_flag_phis)
 {
   unsigned i;
@@ -1153,7 +1152,7 @@  prune_uninit_phi_opnds_in_unrealizable_paths (gimple phi,
 static bool
 use_pred_not_overlap_with_undef_path_pred (pred_chain_union preds,
 				           gimple phi, unsigned uninit_opnds,
-					   pointer_set_t *visited_phis)
+					   hash_set<gimple> *visited_phis)
 {
   unsigned int i, n;
   gimple flag_def = 0;
@@ -1818,11 +1817,11 @@  push_pred (pred_chain_union *norm_preds, pred_info pred)
 
 inline static void
 push_to_worklist (tree op, vec<pred_info, va_heap, vl_ptr> *work_list,
-                  pointer_set_t *mark_set)
+                  hash_set<tree> *mark_set)
 {
-  if (pointer_set_contains (mark_set, op))
+  if (mark_set->contains (op))
     return;
-  pointer_set_insert (mark_set, op);
+  mark_set->add (op);
 
   pred_info arg_pred;
   arg_pred.pred_lhs = op;
@@ -1907,7 +1906,7 @@  normalize_one_pred_1 (pred_chain_union *norm_preds,
                       pred_info pred,
                       enum tree_code and_or_code,
                       vec<pred_info, va_heap, vl_ptr> *work_list,
-		      pointer_set_t *mark_set)
+		      hash_set<tree> *mark_set)
 {
   if (!is_neq_zero_form_p (pred))
     {
@@ -1987,7 +1986,6 @@  normalize_one_pred (pred_chain_union *norm_preds,
                     pred_info pred)
 {
   vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
-  pointer_set_t *mark_set = NULL;
   enum tree_code and_or_code = ERROR_MARK;
   pred_chain norm_chain = vNULL;
 
@@ -2015,19 +2013,18 @@  normalize_one_pred (pred_chain_union *norm_preds,
     }
 
   work_list.safe_push (pred);
-  mark_set = pointer_set_create ();
+  hash_set<tree> mark_set;
 
   while (!work_list.is_empty ())
     {
       pred_info a_pred = work_list.pop ();
       normalize_one_pred_1 (norm_preds, &norm_chain, a_pred,
-                            and_or_code, &work_list, mark_set);
+                            and_or_code, &work_list, &mark_set);
     }
   if (and_or_code == BIT_AND_EXPR)
     norm_preds->safe_push (norm_chain);
 
   work_list.release ();
-  pointer_set_destroy (mark_set);
 }
 
 static void
@@ -2035,26 +2032,25 @@  normalize_one_pred_chain (pred_chain_union *norm_preds,
                           pred_chain one_chain)
 {
   vec<pred_info, va_heap, vl_ptr> work_list = vNULL;
-  pointer_set_t *mark_set = pointer_set_create ();
+  hash_set<tree> mark_set;
   pred_chain norm_chain = vNULL;
   size_t i;
 
   for (i = 0; i < one_chain.length (); i++)
     {
       work_list.safe_push (one_chain[i]);
-      pointer_set_insert (mark_set, one_chain[i].pred_lhs);
+      mark_set.add (one_chain[i].pred_lhs);
     }
 
   while (!work_list.is_empty ())
     {
       pred_info a_pred = work_list.pop ();
       normalize_one_pred_1 (0, &norm_chain, a_pred,
-                            BIT_AND_EXPR, &work_list, mark_set);
+                            BIT_AND_EXPR, &work_list, &mark_set);
     }
 
   norm_preds->safe_push (norm_chain);
   work_list.release ();
-  pointer_set_destroy (mark_set);
 }
 
 /* Normalize predicate chains PREDS and returns the normalized one.  */
@@ -2112,7 +2108,7 @@  is_use_properly_guarded (gimple use_stmt,
                          basic_block use_bb,
                          gimple phi,
                          unsigned uninit_opnds,
-                         pointer_set_t *visited_phis)
+                         hash_set<gimple> *visited_phis)
 {
   basic_block phi_bb;
   pred_chain_union preds = vNULL;
@@ -2120,7 +2116,7 @@  is_use_properly_guarded (gimple use_stmt,
   bool has_valid_preds = false;
   bool is_properly_guarded = false;
 
-  if (pointer_set_insert (visited_phis, phi))
+  if (visited_phis->add (phi))
     return false;
 
   phi_bb = gimple_bb (phi);
@@ -2181,7 +2177,7 @@  is_use_properly_guarded (gimple use_stmt,
 static gimple
 find_uninit_use (gimple phi, unsigned uninit_opnds,
                  vec<gimple> *worklist,
-		 pointer_set_t *added_to_worklist)
+		 hash_set<gimple> *added_to_worklist)
 {
   tree phi_result;
   use_operand_p use_p;
@@ -2192,28 +2188,22 @@  find_uninit_use (gimple phi, unsigned uninit_opnds,
 
   FOR_EACH_IMM_USE_FAST (use_p, iter, phi_result)
     {
-      pointer_set_t *visited_phis;
       basic_block use_bb;
 
       use_stmt = USE_STMT (use_p);
       if (is_gimple_debug (use_stmt))
 	continue;
 
-      visited_phis = pointer_set_create ();
-
       if (gimple_code (use_stmt) == GIMPLE_PHI)
 	use_bb = gimple_phi_arg_edge (use_stmt,
 				      PHI_ARG_INDEX_FROM_USE (use_p))->src;
       else
 	use_bb = gimple_bb (use_stmt);
 
+      hash_set<gimple> visited_phis;
       if (is_use_properly_guarded (use_stmt, use_bb, phi, uninit_opnds,
-                                   visited_phis))
-        {
-          pointer_set_destroy (visited_phis);
-          continue;
-        }
-      pointer_set_destroy (visited_phis);
+                                   &visited_phis))
+	continue;
 
       if (dump_file && (dump_flags & TDF_DETAILS))
         {
@@ -2226,7 +2216,7 @@  find_uninit_use (gimple phi, unsigned uninit_opnds,
 
       /* Found a phi use that is not guarded,
          add the phi to the worklist.  */
-      if (!pointer_set_insert (added_to_worklist, use_stmt))
+      if (!added_to_worklist->add (use_stmt))
         {
           if (dump_file && (dump_flags & TDF_DETAILS))
             {
@@ -2235,7 +2225,7 @@  find_uninit_use (gimple phi, unsigned uninit_opnds,
             }
 
           worklist->safe_push (use_stmt);
-          pointer_set_insert (possibly_undefined_names, phi_result);
+          possibly_undefined_names->add (phi_result);
         }
     }
 
@@ -2252,7 +2242,7 @@  find_uninit_use (gimple phi, unsigned uninit_opnds,
 
 static void
 warn_uninitialized_phi (gimple phi, vec<gimple> *worklist,
-                        pointer_set_t *added_to_worklist)
+                        hash_set<gimple> *added_to_worklist)
 {
   unsigned uninit_opnds;
   gimple uninit_use_stmt = 0;
@@ -2339,7 +2329,6 @@  pass_late_warn_uninitialized::execute (function *fun)
   basic_block bb;
   gimple_stmt_iterator gsi;
   vec<gimple> worklist = vNULL;
-  pointer_set_t *added_to_worklist;
 
   calculate_dominance_info (CDI_DOMINATORS);
   calculate_dominance_info (CDI_POST_DOMINATORS);
@@ -2350,8 +2339,8 @@  pass_late_warn_uninitialized::execute (function *fun)
 
   timevar_push (TV_TREE_UNINIT);
 
-  possibly_undefined_names = pointer_set_create ();
-  added_to_worklist = pointer_set_create ();
+  possibly_undefined_names = new hash_set<tree>;
+  hash_set<gimple> added_to_worklist;
 
   /* Initialize worklist  */
   FOR_EACH_BB_FN (bb, fun)
@@ -2373,7 +2362,7 @@  pass_late_warn_uninitialized::execute (function *fun)
 		&& uninit_undefined_value_p (op))
 	      {
 		worklist.safe_push (phi);
-		pointer_set_insert (added_to_worklist, phi);
+		added_to_worklist.add (phi);
 		if (dump_file && (dump_flags & TDF_DETAILS))
 		  {
 		    fprintf (dump_file, "[WORKLIST]: add to initial list: ");
@@ -2388,12 +2377,11 @@  pass_late_warn_uninitialized::execute (function *fun)
     {
       gimple cur_phi = 0;
       cur_phi = worklist.pop ();
-      warn_uninitialized_phi (cur_phi, &worklist, added_to_worklist);
+      warn_uninitialized_phi (cur_phi, &worklist, &added_to_worklist);
     }
 
   worklist.release ();
-  pointer_set_destroy (added_to_worklist);
-  pointer_set_destroy (possibly_undefined_names);
+  delete possibly_undefined_names;
   possibly_undefined_names = NULL;
   free_dominance_info (CDI_POST_DOMINATORS);
   timevar_pop (TV_TREE_UNINIT);
diff --git a/gcc/tree.c b/gcc/tree.c
index 6669a84..de1c9b6 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5143,7 +5143,7 @@  struct free_lang_data_d
   vec<tree> worklist;
 
   /* Set of traversed objects.  Used to avoid duplicate visits.  */
-  struct pointer_set_t *pset;
+  hash_set<tree> *pset;
 
   /* Array of symbols to process with free_lang_data_in_decl.  */
   vec<tree> decls;
@@ -5208,7 +5208,7 @@  add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
 static inline void
 fld_worklist_push (tree t, struct free_lang_data_d *fld)
 {
-  if (t && !is_lang_specific (t) && !pointer_set_contains (fld->pset, t))
+  if (t && !is_lang_specific (t) && !fld->pset->contains (t))
     fld->worklist.safe_push ((t));
 }
 
@@ -5374,7 +5374,7 @@  find_decls_types (tree t, struct free_lang_data_d *fld)
 {
   while (1)
     {
-      if (!pointer_set_contains (fld->pset, t))
+      if (!fld->pset->contains (t))
 	walk_tree (&t, find_decls_types_r, fld, fld->pset);
       if (fld->worklist.is_empty ())
 	break;
@@ -5584,7 +5584,7 @@  free_lang_data_in_cgraph (void)
   alias_pair *p;
 
   /* Initialize sets and arrays to store referenced decls and types.  */
-  fld.pset = pointer_set_create ();
+  fld.pset = new hash_set<tree>;
   fld.worklist.create (0);
   fld.decls.create (100);
   fld.types.create (100);
@@ -5614,7 +5614,7 @@  free_lang_data_in_cgraph (void)
   FOR_EACH_VEC_ELT (fld.types, i, t)
     free_lang_data_in_type (t);
 
-  pointer_set_destroy (fld.pset);
+  delete fld.pset;
   fld.worklist.release ();
   fld.decls.release ();
   fld.types.release ();
@@ -10819,7 +10819,7 @@  num_ending_zeros (const_tree x)
 
 static tree
 walk_type_fields (tree type, walk_tree_fn func, void *data,
-		  struct pointer_set_t *pset, walk_tree_lh lh)
+		  hash_set<tree> *pset, walk_tree_lh lh)
 {
   tree result = NULL_TREE;
 
@@ -10901,7 +10901,7 @@  walk_type_fields (tree type, walk_tree_fn func, void *data,
 
 tree
 walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
-	     struct pointer_set_t *pset, walk_tree_lh lh)
+	     hash_set<tree> *pset, walk_tree_lh lh)
 {
   enum tree_code code;
   int walk_subtrees;
@@ -10922,7 +10922,7 @@  walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
 
   /* Don't walk the same tree twice, if the user has requested
      that we avoid doing so.  */
-  if (pset && pointer_set_insert (pset, *tp))
+  if (pset && pset->add (*tp))
     return NULL_TREE;
 
   /* Call the function.  */
@@ -11237,11 +11237,9 @@  walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data,
 				walk_tree_lh lh)
 {
   tree result;
-  struct pointer_set_t *pset;
 
-  pset = pointer_set_create ();
-  result = walk_tree_1 (tp, func, data, pset, lh);
-  pointer_set_destroy (pset);
+  hash_set<tree> pset;
+  result = walk_tree_1 (tp, func, data, &pset, lh);
   return result;
 }
 
diff --git a/gcc/tree.h b/gcc/tree.h
index 2bb6d1f..c9f978a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -21,6 +21,7 @@  along with GCC; see the file COPYING3.  If not see
 #define GCC_TREE_H
 
 #include "tree-core.h"
+#include "hash-set.h"
 #include "wide-int.h"
 #include "inchash.h"
 
@@ -4328,7 +4329,7 @@  extern void using_eh_for_cleanups (void);
 extern bool using_eh_for_cleanups_p (void);
 extern const char *get_tree_code_name (enum tree_code);
 extern void set_call_expr_flags (tree, int);
-extern tree walk_tree_1 (tree*, walk_tree_fn, void*, struct pointer_set_t*,
+extern tree walk_tree_1 (tree*, walk_tree_fn, void*, hash_set<tree>*,
 			 walk_tree_lh);
 extern tree walk_tree_without_duplicates_1 (tree*, walk_tree_fn, void*,
 					    walk_tree_lh);
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index 3e51539..ffdee65 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -59,6 +59,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "data-streamer.h"
 #include "builtins.h"
 #include "tree-nested.h"
+#include "hash-set.h"
 
 /* In this file value profile based optimizations are placed.  Currently the
    following optimizations are implemented (for more detailed descriptions
@@ -515,10 +516,10 @@  static bool error_found = false;
 static int
 visit_hist (void **slot, void *data)
 {
-  struct pointer_set_t *visited = (struct pointer_set_t *) data;
+  hash_set<histogram_value> *visited = (hash_set<histogram_value> *) data;
   histogram_value hist = *(histogram_value *) slot;
 
-  if (!pointer_set_contains (visited, hist)
+  if (!visited->contains (hist)
       && hist->type != HIST_TYPE_TIME_PROFILE)
     {
       error ("dead histogram");
@@ -538,10 +539,9 @@  verify_histograms (void)
   basic_block bb;
   gimple_stmt_iterator gsi;
   histogram_value hist;
-  struct pointer_set_t *visited_hists;
 
   error_found = false;
-  visited_hists = pointer_set_create ();
+  hash_set<histogram_value> visited_hists;
   FOR_EACH_BB_FN (bb, cfun)
     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
       {
@@ -558,12 +558,11 @@  verify_histograms (void)
 		dump_histogram_value (stderr, hist);
 		error_found = true;
 	      }
-            pointer_set_insert (visited_hists, hist);
+            visited_hists.add (hist);
 	  }
       }
   if (VALUE_HISTOGRAMS (cfun))
-    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, visited_hists);
-  pointer_set_destroy (visited_hists);
+    htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, &visited_hists);
   if (error_found)
     internal_error ("verify_histograms failed");
 }
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 819ec26..9d8602b 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -51,7 +51,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "common/common-target.h"
 #include "targhooks.h"
 #include "cgraph.h"
-#include "pointer-set.h"
+#include "hash-set.h"
 #include "asan.h"
 #include "basic-block.h"
 
@@ -2249,7 +2249,7 @@  static bool pending_assemble_externals_processed;
 
 /* Avoid O(external_decls**2) lookups in the pending_assemble_externals
    TREE_LIST in assemble_external.  */
-static struct pointer_set_t *pending_assemble_externals_set;
+static hash_set<tree> *pending_assemble_externals_set;
 
 /* True if DECL is a function decl for which no out-of-line copy exists.
    It is assumed that DECL's assembler name has been set.  */
@@ -2303,7 +2303,7 @@  process_pending_assemble_externals (void)
 
   pending_assemble_externals = 0;
   pending_assemble_externals_processed = true;
-  pointer_set_destroy (pending_assemble_externals_set);
+  delete pending_assemble_externals_set;
 #endif
 }
 
@@ -2361,7 +2361,7 @@  assemble_external (tree decl ATTRIBUTE_UNUSED)
       return;
     }
 
-  if (! pointer_set_insert (pending_assemble_externals_set, decl))
+  if (! pending_assemble_externals_set->add (decl))
     pending_assemble_externals = tree_cons (NULL, decl,
 					    pending_assemble_externals);
 #endif
@@ -5991,7 +5991,7 @@  init_varasm_once (void)
     readonly_data_section = text_section;
 
 #ifdef ASM_OUTPUT_EXTERNAL
-  pending_assemble_externals_set = pointer_set_create ();
+  pending_assemble_externals_set = new hash_set<tree>;
 #endif
 }
 
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 74117e2..558767f 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -38,6 +38,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-alias.h"
 #include "gimple.h"
 #include "lto-streamer.h"
+#include "hash-set.h"
 
 const char * const tls_model_names[]={"none", "tls-emulated", "tls-real",
 				      "tls-global-dynamic", "tls-local-dynamic",
@@ -576,7 +577,7 @@  varpool_remove_unreferenced_decls (void)
   varpool_node *first = (varpool_node *)(void *)1;
   int i;
   struct ipa_ref *ref = NULL;
-  struct pointer_set_t *referenced = pointer_set_create ();
+  hash_set<varpool_node *> referenced;
 
   if (seen_error ())
     return;
@@ -623,7 +624,7 @@  varpool_remove_unreferenced_decls (void)
 	      && vnode->analyzed)
 	    enqueue_node (vnode, &first);
 	  else
-	    pointer_set_insert (referenced, node);
+	    referenced.add (node);
 	}
     }
   if (cgraph_dump_file)
@@ -635,13 +636,13 @@  varpool_remove_unreferenced_decls (void)
 	{
           if (cgraph_dump_file)
 	    fprintf (cgraph_dump_file, " %s", node->asm_name ());
-	  if (pointer_set_contains (referenced, node))
+	  if (referenced.contains (node))
 	    node->remove_initializer ();
 	  else
 	    node->remove ();
 	}
     }
-  pointer_set_destroy (referenced);
+
   if (cgraph_dump_file)
     fprintf (cgraph_dump_file, "\n");
 }