Daily bump.
[gcc.git] / gcc / tree-ssa-structalias.c
index 924a0deec435f615b0fb6be4fa0bd23f3879c0d1..36213772f4cb19f5d90a6bb5755f45e76a13b78b 100644 (file)
@@ -1,5 +1,5 @@
 /* Tree based points-to analysis
-   Copyright (C) 2005-2013 Free Software Foundation, Inc.
+   Copyright (C) 2005-2014 Free Software Foundation, Inc.
    Contributed by Daniel Berlin <dberlin@dberlin.org>
 
    This file is part of GCC.
 #include "bitmap.h"
 #include "sbitmap.h"
 #include "flags.h"
+#include "predict.h"
+#include "vec.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "hard-reg-set.h"
+#include "input.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
 #include "basic-block.h"
 #include "tree.h"
 #include "stor-layout.h"
 #include "stmt.h"
-#include "pointer-set.h"
 #include "hash-table.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
@@ -39,6 +48,9 @@
 #include "gimple.h"
 #include "gimple-iterator.h"
 #include "gimple-ssa.h"
+#include "hash-map.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
 #include "cgraph.h"
 #include "stringpool.h"
 #include "tree-ssanames.h"
@@ -47,7 +59,6 @@
 #include "tree-dfa.h"
 #include "tree-inline.h"
 #include "diagnostic-core.h"
-#include "function.h"
 #include "tree-pass.h"
 #include "alloc-pool.h"
 #include "splay-tree.h"
@@ -319,7 +330,7 @@ static inline bool type_can_have_subvars (const_tree);
 static alloc_pool variable_info_pool;
 
 /* Map varinfo to final pt_solution.  */
-static pointer_map_t *final_solutions;
+static hash_map<varinfo_t, pt_solution *> *final_solutions;
 struct obstack final_solutions_obstack;
 
 /* Table of variable info structures for constraint variables.
@@ -345,7 +356,7 @@ vi_next (varinfo_t vi)
 
 /* Static IDs for the special variables.  Variable ID zero is unused
    and used as terminator for the sub-variable chain.  */
-enum { nothing_id = 1, anything_id = 2, readonly_id = 3,
+enum { nothing_id = 1, anything_id = 2, string_id = 3,
        escaped_id = 4, nonlocal_id = 5,
        storedanything_id = 6, integer_id = 7 };
 
@@ -393,19 +404,19 @@ new_var_info (tree t, const char *name)
 
 /* A map mapping call statements to per-stmt variables for uses
    and clobbers specific to the call.  */
-static struct pointer_map_t *call_stmt_vars;
+static hash_map<gimple, varinfo_t> *call_stmt_vars;
 
 /* Lookup or create the variable for the call statement CALL.  */
 
 static varinfo_t
 get_call_vi (gimple call)
 {
-  void **slot_p;
   varinfo_t vi, vi2;
 
-  slot_p = pointer_map_insert (call_stmt_vars, call);
-  if (*slot_p)
-    return (varinfo_t) *slot_p;
+  bool existed;
+  varinfo_t *slot_p = &call_stmt_vars->get_or_insert (call, &existed);
+  if (existed)
+    return *slot_p;
 
   vi = new_var_info (NULL_TREE, "CALLUSED");
   vi->offset = 0;
@@ -421,7 +432,7 @@ get_call_vi (gimple call)
 
   vi->next = vi2->id;
 
-  *slot_p = (void *) vi;
+  *slot_p = vi;
   return vi;
 }
 
@@ -431,11 +442,9 @@ get_call_vi (gimple call)
 static varinfo_t
 lookup_call_use_vi (gimple call)
 {
-  void **slot_p;
-
-  slot_p = pointer_map_contains (call_stmt_vars, call);
+  varinfo_t *slot_p = call_stmt_vars->get (call);
   if (slot_p)
-    return (varinfo_t) *slot_p;
+    return *slot_p;
 
   return NULL;
 }
@@ -993,23 +1002,28 @@ set_union_with_increment  (bitmap to, bitmap delta, HOST_WIDE_INT inc,
        changed |= bitmap_set_bit (to, i);
       else
        {
-         unsigned HOST_WIDE_INT fieldoffset = vi->offset + inc;
+         HOST_WIDE_INT fieldoffset = vi->offset + inc;
+         unsigned HOST_WIDE_INT size = vi->size;
 
          /* If the offset makes the pointer point to before the
             variable use offset zero for the field lookup.  */
-         if (inc < 0
-             && fieldoffset > vi->offset)
-           fieldoffset = 0;
-
-         vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
-
-         changed |= bitmap_set_bit (to, vi->id);
-         /* If the result is not exactly at fieldoffset include the next
-            field as well.  See get_constraint_for_ptr_offset for more
-            rationale.  */
-         if (vi->offset != fieldoffset
-             && vi->next != 0)
-           changed |= bitmap_set_bit (to, vi->next);
+         if (fieldoffset < 0)
+           vi = get_varinfo (vi->head);
+         else
+           vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
+
+         do
+           {
+             changed |= bitmap_set_bit (to, vi->id);
+             if (vi->is_full_var
+                 || vi->next == 0)
+               break;
+
+             /* We have to include all fields that overlap the current field
+                shifted by inc.  */
+             vi = vi_next (vi);
+           }
+         while (vi->offset < fieldoffset + size);
        }
     }
 
@@ -1618,16 +1632,21 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
     {
       varinfo_t v = get_varinfo (j);
       HOST_WIDE_INT fieldoffset = v->offset + roffset;
+      unsigned HOST_WIDE_INT size = v->size;
       unsigned int t;
 
       if (v->is_full_var)
-       fieldoffset = v->offset;
+       ;
       else if (roffset != 0)
-       v = first_vi_for_offset (v, fieldoffset);
-      /* If the access is outside of the variable we can ignore it.  */
-      if (!v)
-       continue;
+       {
+         if (fieldoffset < 0)
+           v = get_varinfo (v->head);
+         else
+           v = first_or_preceding_vi_for_offset (v, fieldoffset);
+       }
 
+      /* We have to include all fields that overlap the current field
+        shifted by roffset.  */
       do
        {
          t = find (v->id);
@@ -1644,16 +1663,13 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
                   && add_graph_edge (graph, lhs, t))
            flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
 
-         /* If the variable is not exactly at the requested offset
-            we have to include the next one.  */
-         if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset
+         if (v->is_full_var
              || v->next == 0)
            break;
 
          v = vi_next (v);
-         fieldoffset = v->offset;
        }
-      while (1);
+      while (v->offset < fieldoffset + size);
     }
 
 done:
@@ -1716,15 +1732,20 @@ do_ds_constraint (constraint_t c, bitmap delta, bitmap *expanded_delta)
       varinfo_t v = get_varinfo (j);
       unsigned int t;
       HOST_WIDE_INT fieldoffset = v->offset + loff;
+      unsigned HOST_WIDE_INT size = v->size;
 
       if (v->is_full_var)
-       fieldoffset = v->offset;
+       ;
       else if (loff != 0)
-       v = first_vi_for_offset (v, fieldoffset);
-      /* If the access is outside of the variable we can ignore it.  */
-      if (!v)
-       continue;
+       {
+         if (fieldoffset < 0)
+           v = get_varinfo (v->head);
+         else
+           v = first_or_preceding_vi_for_offset (v, fieldoffset);
+       }
 
+      /* We have to include all fields that overlap the current field
+        shifted by loff.  */
       do
        {
          if (v->may_have_pointers)
@@ -1750,16 +1771,13 @@ do_ds_constraint (constraint_t c, bitmap delta, bitmap *expanded_delta)
                bitmap_set_bit (changed, t);
            }
 
-         /* If the variable is not exactly at the requested offset
-            we have to include the next one.  */
-         if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset
+         if (v->is_full_var
              || v->next == 0)
            break;
 
          v = vi_next (v);
-         fieldoffset = v->offset;
        }
-      while (1);
+      while (v->offset < fieldoffset + size);
     }
 }
 
@@ -1918,25 +1936,26 @@ equiv_class_hasher::equal (const value_type *eql1, const compare_type *eql2)
 
 /* A hashtable for mapping a bitmap of labels->pointer equivalence
    classes.  */
-static hash_table <equiv_class_hasher> pointer_equiv_class_table;
+static hash_table<equiv_class_hasher> *pointer_equiv_class_table;
 
 /* A hashtable for mapping a bitmap of labels->location equivalence
    classes.  */
-static hash_table <equiv_class_hasher> location_equiv_class_table;
+static hash_table<equiv_class_hasher> *location_equiv_class_table;
 
 /* Lookup a equivalence class in TABLE by the bitmap of LABELS with
    hash HAS it contains.  Sets *REF_LABELS to the bitmap LABELS
    is equivalent to.  */
 
 static equiv_class_label *
-equiv_class_lookup_or_add (hash_table <equiv_class_hasher> table, bitmap labels)
+equiv_class_lookup_or_add (hash_table<equiv_class_hasher> *table,
+                          bitmap labels)
 {
   equiv_class_label **slot;
   equiv_class_label ecl;
 
   ecl.labels = labels;
   ecl.hashcode = bitmap_hash (labels);
-  slot = table.find_slot_with_hash (&ecl, ecl.hashcode, INSERT);
+  slot = table->find_slot (&ecl, INSERT);
   if (!*slot)
     {
       *slot = XNEW (struct equiv_class_label);
@@ -2272,8 +2291,9 @@ perform_var_substitution (constraint_graph_t graph)
   struct scc_info *si = init_scc_info (size);
 
   bitmap_obstack_initialize (&iteration_obstack);
-  pointer_equiv_class_table.create (511);
-  location_equiv_class_table.create (511);
+  pointer_equiv_class_table = new hash_table<equiv_class_hasher> (511);
+  location_equiv_class_table
+    = new hash_table<equiv_class_hasher> (511);
   pointer_equiv_class = 1;
   location_equiv_class = 1;
 
@@ -2406,8 +2426,10 @@ free_var_substitution_info (struct scc_info *si)
   free (graph->points_to);
   free (graph->eq_rep);
   sbitmap_free (graph->direct_nodes);
-  pointer_equiv_class_table.dispose ();
-  location_equiv_class_table.dispose ();
+  delete pointer_equiv_class_table;
+  pointer_equiv_class_table = NULL;
+  delete location_equiv_class_table;
+  location_equiv_class_table = NULL;
   bitmap_obstack_release (&iteration_obstack);
 }
 
@@ -2781,7 +2803,7 @@ solve_graph (constraint_graph_t graph)
 }
 
 /* Map from trees to variable infos.  */
-static struct pointer_map_t *vi_for_tree;
+static hash_map<tree, varinfo_t> *vi_for_tree;
 
 
 /* Insert ID as the variable id for tree T in the vi_for_tree map.  */
@@ -2789,10 +2811,8 @@ static struct pointer_map_t *vi_for_tree;
 static void
 insert_vi_for_tree (tree t, varinfo_t vi)
 {
-  void **slot = pointer_map_insert (vi_for_tree, t);
   gcc_assert (vi);
-  gcc_assert (*slot == NULL);
-  *slot = vi;
+  gcc_assert (!vi_for_tree->put (t, vi));
 }
 
 /* Find the variable info for tree T in VI_FOR_TREE.  If T does not
@@ -2801,11 +2821,11 @@ insert_vi_for_tree (tree t, varinfo_t vi)
 static varinfo_t
 lookup_vi_for_tree (tree t)
 {
-  void **slot = pointer_map_contains (vi_for_tree, t);
+  varinfo_t *slot = vi_for_tree->get (t);
   if (slot == NULL)
     return NULL;
 
-  return (varinfo_t) *slot;
+  return *slot;
 }
 
 /* Return a printable name for DECL  */
@@ -2863,11 +2883,11 @@ alias_get_name (tree decl)
 static varinfo_t
 get_vi_for_tree (tree t)
 {
-  void **slot = pointer_map_contains (vi_for_tree, t);
+  varinfo_t *slot = vi_for_tree->get (t);
   if (slot == NULL)
     return get_varinfo (create_variable_info_for (t, alias_get_name (t)));
 
-  return (varinfo_t) *slot;
+  return *slot;
 }
 
 /* Get a scalar constraint expression for a new temporary variable.  */
@@ -2918,10 +2938,10 @@ get_constraint_for_ssa_var (tree t, vec<ce_s> *results, bool address_p)
   if (TREE_CODE (t) == VAR_DECL
       && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
     {
-      varpool_node *node = varpool_get_node (t);
+      varpool_node *node = varpool_node::get (t);
       if (node && node->alias && node->analyzed)
        {
-         node = varpool_variable_node (node, NULL);
+         node = node->ultimate_alias_target ();
          t = node->decl;
        }
     }
@@ -2930,14 +2950,6 @@ get_constraint_for_ssa_var (tree t, vec<ce_s> *results, bool address_p)
   cexpr.var = vi->id;
   cexpr.type = SCALAR;
   cexpr.offset = 0;
-  /* If we determine the result is "anything", and we know this is readonly,
-     say it points to readonly memory instead.  */
-  if (cexpr.var == anything_id && TREE_READONLY (t))
-    {
-      gcc_unreachable ();
-      cexpr.type = ADDRESSOF;
-      cexpr.var = readonly_id;
-    }
 
   /* If we are not taking the address of the constraint expr, add all
      sub-fiels of the variable as well.  */
@@ -3056,14 +3068,13 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
   else
     {
       /* Sign-extend the offset.  */
-      double_int soffset = tree_to_double_int (offset)
-                          .sext (TYPE_PRECISION (TREE_TYPE (offset)));
-      if (!soffset.fits_shwi ())
+      offset_int soffset = offset_int::from (offset, SIGNED);
+      if (!wi::fits_shwi_p (soffset))
        rhsoffset = UNKNOWN_OFFSET;
       else
        {
          /* Make sure the bit-offset also fits.  */
-         HOST_WIDE_INT rhsunitoffset = soffset.low;
+         HOST_WIDE_INT rhsunitoffset = soffset.to_shwi ();
          rhsoffset = rhsunitoffset * BITS_PER_UNIT;
          if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
            rhsoffset = UNKNOWN_OFFSET;
@@ -3086,7 +3097,7 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
       if (c.type == ADDRESSOF
          /* If this varinfo represents a full variable just use it.  */
          && curr->is_full_var)
-       c.offset = 0;
+       ;
       else if (c.type == ADDRESSOF
               /* If we do not know the offset add all subfields.  */
               && rhsoffset == UNKNOWN_OFFSET)
@@ -3109,38 +3120,39 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
          varinfo_t temp;
          unsigned HOST_WIDE_INT offset = curr->offset + rhsoffset;
 
-         /* Search the sub-field which overlaps with the
-            pointed-to offset.  If the result is outside of the variable
-            we have to provide a conservative result, as the variable is
-            still reachable from the resulting pointer (even though it
-            technically cannot point to anything).  The last and first
-            sub-fields are such conservative results.
-            ???  If we always had a sub-field for &object + 1 then
-            we could represent this in a more precise way.  */
+         /* If curr->offset + rhsoffset is less than zero adjust it.  */
          if (rhsoffset < 0
              && curr->offset < offset)
            offset = 0;
-         temp = first_or_preceding_vi_for_offset (curr, offset);
 
-         /* If the found variable is not exactly at the pointed to
-            result, we have to include the next variable in the
-            solution as well.  Otherwise two increments by offset / 2
-            do not result in the same or a conservative superset
-            solution.  */
-         if (temp->offset != offset
-             && temp->next != 0)
+         /* We have to include all fields that overlap the current
+            field shifted by rhsoffset.  And we include at least
+            the last or the first field of the variable to represent
+            reachability of off-bound addresses, in particular &object + 1,
+            conservatively correct.  */
+         temp = first_or_preceding_vi_for_offset (curr, offset);
+         c.var = temp->id;
+         c.offset = 0;
+         temp = vi_next (temp);
+         while (temp
+                && temp->offset < offset + curr->size)
            {
              struct constraint_expr c2;
-             c2.var = temp->next;
+             c2.var = temp->id;
              c2.type = ADDRESSOF;
              c2.offset = 0;
              results->safe_push (c2);
+             temp = vi_next (temp);
            }
-         c.var = temp->id;
-         c.offset = 0;
+       }
+      else if (c.type == SCALAR)
+       {
+         gcc_assert (c.offset == 0);
+         c.offset = rhsoffset;
        }
       else
-       c.offset = rhsoffset;
+       /* We shouldn't get any DEREFs here.  */
+       gcc_unreachable ();
 
       (*results)[j] = c;
     }
@@ -3372,10 +3384,11 @@ get_constraint_for_1 (tree t, vec<ce_s> *results, bool address_p,
       return;
     }
 
-  /* String constants are read-only.  */
+  /* String constants are read-only, ideally we'd have a CONST_DECL
+     for those.  */
   if (TREE_CODE (t) == STRING_CST)
     {
-      temp.var = readonly_id;
+      temp.var = string_id;
       temp.type = SCALAR;
       temp.offset = 0;
       results->safe_push (temp);
@@ -3965,7 +3978,6 @@ handle_lhs_call (gimple stmt, tree lhs, int flags, vec<ce_s> rhsc,
 
   /* If the call returns an argument unmodified override the rhs
      constraints.  */
-  flags = gimple_call_return_flags (stmt);
   if (flags & ERF_RETURNS_ARG
       && (flags & ERF_RETURN_ARG_MASK) < gimple_call_num_args (stmt))
     {
@@ -3982,7 +3994,7 @@ handle_lhs_call (gimple stmt, tree lhs, int flags, vec<ce_s> rhsc,
       struct constraint_expr tmpc;
       rhsc.create (0);
       vi = make_heapvar ("HEAP");
-      /* We marking allocated storage local, we deal with it becoming
+      /* We are marking allocated storage local, we deal with it becoming
          global by escaping and setting of vars_contains_escaped_heap.  */
       DECL_EXTERNAL (vi->decl) = 0;
       vi->is_global_var = 0;
@@ -4126,11 +4138,11 @@ get_fi_for_callee (gimple call)
    was handled, otherwise false.  */
 
 static bool
-find_func_aliases_for_builtin_call (gimple t)
+find_func_aliases_for_builtin_call (struct function *fn, gimple t)
 {
   tree fndecl = gimple_call_fndecl (t);
-  vec<ce_s> lhsc = vNULL;
-  vec<ce_s> rhsc = vNULL;
+  auto_vec<ce_s, 2> lhsc;
+  auto_vec<ce_s, 4> rhsc;
   varinfo_t fi;
 
   if (gimple_call_builtin_p (t, BUILT_IN_NORMAL))
@@ -4183,16 +4195,14 @@ find_func_aliases_for_builtin_call (gimple t)
              else
                get_constraint_for (dest, &rhsc);
              process_all_all_constraints (lhsc, rhsc);
-             lhsc.release ();
-             rhsc.release ();
+             lhsc.truncate (0);
+             rhsc.truncate (0);
            }
          get_constraint_for_ptr_offset (dest, NULL_TREE, &lhsc);
          get_constraint_for_ptr_offset (src, NULL_TREE, &rhsc);
          do_deref (&lhsc);
          do_deref (&rhsc);
          process_all_all_constraints (lhsc, rhsc);
-         lhsc.release ();
-         rhsc.release ();
          return true;
        }
       case BUILT_IN_MEMSET:
@@ -4209,8 +4219,7 @@ find_func_aliases_for_builtin_call (gimple t)
              get_constraint_for (res, &lhsc);
              get_constraint_for (dest, &rhsc);
              process_all_all_constraints (lhsc, rhsc);
-             lhsc.release ();
-             rhsc.release ();
+             lhsc.truncate (0);
            }
          get_constraint_for_ptr_offset (dest, NULL_TREE, &lhsc);
          do_deref (&lhsc);
@@ -4228,7 +4237,24 @@ find_func_aliases_for_builtin_call (gimple t)
          ac.offset = 0;
          FOR_EACH_VEC_ELT (lhsc, i, lhsp)
              process_constraint (new_constraint (*lhsp, ac));
-         lhsc.release ();
+         return true;
+       }
+      case BUILT_IN_POSIX_MEMALIGN:
+        {
+         tree ptrptr = gimple_call_arg (t, 0);
+         get_constraint_for (ptrptr, &lhsc);
+         do_deref (&lhsc);
+         varinfo_t vi = make_heapvar ("HEAP");
+         /* We are marking allocated storage local, we deal with it becoming
+            global by escaping and setting of vars_contains_escaped_heap.  */
+         DECL_EXTERNAL (vi->decl) = 0;
+         vi->is_global_var = 0;
+         struct constraint_expr tmpc;
+         tmpc.var = vi->id;
+         tmpc.offset = 0;
+         tmpc.type = ADDRESSOF;
+         rhsc.safe_push (tmpc);
+         process_all_all_constraints (lhsc, rhsc);
          return true;
        }
       case BUILT_IN_ASSUME_ALIGNED:
@@ -4240,8 +4266,6 @@ find_func_aliases_for_builtin_call (gimple t)
              get_constraint_for (res, &lhsc);
              get_constraint_for (dest, &rhsc);
              process_all_all_constraints (lhsc, rhsc);
-             lhsc.release ();
-             rhsc.release ();
            }
          return true;
        }
@@ -4270,9 +4294,11 @@ find_func_aliases_for_builtin_call (gimple t)
        return true;
       case BUILT_IN_STRDUP:
       case BUILT_IN_STRNDUP:
+      case BUILT_IN_REALLOC:
        if (gimple_call_lhs (t))
          {
-           handle_lhs_call (t, gimple_call_lhs (t), gimple_call_flags (t),
+           handle_lhs_call (t, gimple_call_lhs (t),
+                            gimple_call_return_flags (t) | ERF_NOALIAS,
                             vNULL, fndecl);
            get_constraint_for_ptr_offset (gimple_call_lhs (t),
                                           NULL_TREE, &lhsc);
@@ -4281,8 +4307,17 @@ find_func_aliases_for_builtin_call (gimple t)
            do_deref (&lhsc);
            do_deref (&rhsc);
            process_all_all_constraints (lhsc, rhsc);
-           lhsc.release ();
-           rhsc.release ();
+           lhsc.truncate (0);
+           rhsc.truncate (0);
+           /* For realloc the resulting pointer can be equal to the
+              argument as well.  But only doing this wouldn't be
+              correct because with ptr == 0 realloc behaves like malloc.  */
+           if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_REALLOC)
+             {
+               get_constraint_for (gimple_call_lhs (t), &lhsc);
+               get_constraint_for (gimple_call_arg (t, 0), &rhsc);
+               process_all_all_constraints (lhsc, rhsc);
+             }
            return true;
          }
        break;
@@ -4305,8 +4340,6 @@ find_func_aliases_for_builtin_call (gimple t)
            rhsc.safe_push (nul);
            get_constraint_for (gimple_call_lhs (t), &lhsc);
            process_all_all_constraints (lhsc, rhsc);
-           lhsc.release ();
-           rhsc.release ();
          }
        return true;
       /* Trampolines are special - they set up passing the static
@@ -4328,8 +4361,8 @@ find_func_aliases_for_builtin_call (gimple t)
                  lhs = get_function_part_constraint (nfi, fi_static_chain);
                  get_constraint_for (frame, &rhsc);
                  FOR_EACH_VEC_ELT (rhsc, i, rhsp)
-                     process_constraint (new_constraint (lhs, *rhsp));
-                 rhsc.release ();
+                   process_constraint (new_constraint (lhs, *rhsp));
+                 rhsc.truncate (0);
 
                  /* Make the frame point to the function for
                     the trampoline adjustment call.  */
@@ -4337,8 +4370,6 @@ find_func_aliases_for_builtin_call (gimple t)
                  do_deref (&lhsc);
                  get_constraint_for (nfunc, &rhsc);
                  process_all_all_constraints (lhsc, rhsc);
-                 rhsc.release ();
-                 lhsc.release ();
 
                  return true;
                }
@@ -4357,8 +4388,6 @@ find_func_aliases_for_builtin_call (gimple t)
              get_constraint_for (tramp, &rhsc);
              do_deref (&rhsc);
              process_all_all_constraints (lhsc, rhsc);
-             rhsc.release ();
-             lhsc.release ();
            }
          return true;
        }
@@ -4380,8 +4409,6 @@ find_func_aliases_for_builtin_call (gimple t)
          do_deref (&lhsc);
          get_constraint_for (src, &rhsc);
          process_all_all_constraints (lhsc, rhsc);
-         lhsc.release ();
-         rhsc.release ();
          return true;
        }
       CASE_BUILT_IN_TM_LOAD (1):
@@ -4402,8 +4429,6 @@ find_func_aliases_for_builtin_call (gimple t)
          get_constraint_for (addr, &rhsc);
          do_deref (&rhsc);
          process_all_all_constraints (lhsc, rhsc);
-         lhsc.release ();
-         rhsc.release ();
          return true;
        }
       /* Variadic argument handling needs to be handled in IPA
@@ -4420,7 +4445,7 @@ find_func_aliases_for_builtin_call (gimple t)
             and otherwise are just all nonlocal variables.  */
          if (in_ipa_mode)
            {
-             fi = lookup_vi_for_tree (cfun->decl);
+             fi = lookup_vi_for_tree (fn->decl);
              rhs = get_function_part_constraint (fi, ~0);
              rhs.type = ADDRESSOF;
            }
@@ -4432,7 +4457,6 @@ find_func_aliases_for_builtin_call (gimple t)
            }
          FOR_EACH_VEC_ELT (lhsc, i, lhsp)
            process_constraint (new_constraint (*lhsp, rhs));
-         lhsc.release ();
          /* va_list is clobbered.  */
          make_constraint_to (get_call_clobber_vi (t)->id, valist);
          return true;
@@ -4445,7 +4469,7 @@ find_func_aliases_for_builtin_call (gimple t)
        {
          fi = NULL;
          if (!in_ipa_mode
-             || !(fi = get_vi_for_tree (cfun->decl)))
+             || !(fi = get_vi_for_tree (fn->decl)))
            make_constraint_from (get_varinfo (escaped_id), anything_id);
          else if (in_ipa_mode
                   && fi != NULL)
@@ -4472,23 +4496,21 @@ find_func_aliases_for_builtin_call (gimple t)
 /* Create constraints for the call T.  */
 
 static void
-find_func_aliases_for_call (gimple t)
+find_func_aliases_for_call (struct function *fn, gimple t)
 {
   tree fndecl = gimple_call_fndecl (t);
-  vec<ce_s> lhsc = vNULL;
-  vec<ce_s> rhsc = vNULL;
   varinfo_t fi;
 
   if (fndecl != NULL_TREE
       && DECL_BUILT_IN (fndecl)
-      && find_func_aliases_for_builtin_call (t))
+      && find_func_aliases_for_builtin_call (fn, t))
     return;
 
   fi = get_fi_for_callee (t);
   if (!in_ipa_mode
       || (fndecl && !fi->is_fn_info))
     {
-      vec<ce_s> rhsc = vNULL;
+      auto_vec<ce_s, 16> rhsc;
       int flags = gimple_call_flags (t);
 
       /* Const functions can return their arguments and addresses
@@ -4506,11 +4528,12 @@ find_func_aliases_for_call (gimple t)
       else
        handle_rhs_call (t, &rhsc);
       if (gimple_call_lhs (t))
-       handle_lhs_call (t, gimple_call_lhs (t), flags, rhsc, fndecl);
-      rhsc.release ();
+       handle_lhs_call (t, gimple_call_lhs (t),
+                        gimple_call_return_flags (t), rhsc, fndecl);
     }
   else
     {
+      auto_vec<ce_s, 2> rhsc;
       tree lhsop;
       unsigned j;
 
@@ -4536,6 +4559,7 @@ find_func_aliases_for_call (gimple t)
       lhsop = gimple_call_lhs (t);
       if (lhsop)
        {
+         auto_vec<ce_s, 2> lhsc;
          struct constraint_expr rhs;
          struct constraint_expr *lhsp;
 
@@ -4545,11 +4569,11 @@ find_func_aliases_for_call (gimple t)
              && DECL_RESULT (fndecl)
              && DECL_BY_REFERENCE (DECL_RESULT (fndecl)))
            {
-             vec<ce_s> tem = vNULL;
-             tem.safe_push (rhs);
+             auto_vec<ce_s, 2> tem;
+             tem.quick_push (rhs);
              do_deref (&tem);
+             gcc_checking_assert (tem.length () == 1);
              rhs = tem[0];
-             tem.release ();
            }
          FOR_EACH_VEC_ELT (lhsc, j, lhsp)
            process_constraint (new_constraint (*lhsp, rhs));
@@ -4568,7 +4592,7 @@ find_func_aliases_for_call (gimple t)
          lhs = get_function_part_constraint (fi, fi_result);
          FOR_EACH_VEC_ELT (rhsc, j, rhsp)
            process_constraint (new_constraint (lhs, *rhsp));
-         rhsc.release ();
+         rhsc.truncate (0);
        }
 
       /* If we use a static chain, pass it along.  */
@@ -4591,11 +4615,11 @@ find_func_aliases_for_call (gimple t)
    when building alias sets and computing alias grouping heuristics.  */
 
 static void
-find_func_aliases (gimple origt)
+find_func_aliases (struct function *fn, gimple origt)
 {
   gimple t = origt;
-  vec<ce_s> lhsc = vNULL;
-  vec<ce_s> rhsc = vNULL;
+  auto_vec<ce_s, 16> lhsc;
+  auto_vec<ce_s, 16> rhsc;
   struct constraint_expr *c;
   varinfo_t fi;
 
@@ -4635,7 +4659,7 @@ find_func_aliases (gimple origt)
      In non-ipa mode, we need to generate constraints for each
      pointer passed by address.  */
   else if (is_gimple_call (t))
-    find_func_aliases_for_call (t);
+    find_func_aliases_for_call (fn, t);
     
   /* Otherwise, just a regular assignment statement.  Only care about
      operations with pointer result, others are dealt with as escape
@@ -4681,14 +4705,13 @@ find_func_aliases (gimple origt)
          else if (code == COND_EXPR)
            {
              /* The result is a merge of both COND_EXPR arms.  */
-             vec<ce_s> tmp = vNULL;
+             auto_vec<ce_s, 2> tmp;
              struct constraint_expr *rhsp;
              unsigned i;
              get_constraint_for_rhs (gimple_assign_rhs2 (t), &rhsc);
              get_constraint_for_rhs (gimple_assign_rhs3 (t), &tmp);
              FOR_EACH_VEC_ELT (tmp, i, rhsp)
                rhsc.safe_push (*rhsp);
-             tmp.release ();
            }
          else if (truth_value_p (code))
            /* Truth value results are not pointer (parts).  Or at least
@@ -4697,7 +4720,7 @@ find_func_aliases (gimple origt)
          else
            {
              /* All other operations are merges.  */
-             vec<ce_s> tmp = vNULL;
+             auto_vec<ce_s, 4> tmp;
              struct constraint_expr *rhsp;
              unsigned i, j;
              get_constraint_for_rhs (gimple_assign_rhs1 (t), &rhsc);
@@ -4708,7 +4731,6 @@ find_func_aliases (gimple origt)
                    rhsc.safe_push (*rhsp);
                  tmp.truncate (0);
                }
-             tmp.release ();
            }
          process_all_all_constraints (lhsc, rhsc);
        }
@@ -4726,7 +4748,7 @@ find_func_aliases (gimple origt)
     {
       fi = NULL;
       if (!in_ipa_mode
-         || !(fi = get_vi_for_tree (cfun->decl)))
+         || !(fi = get_vi_for_tree (fn->decl)))
        make_escape_constraint (gimple_return_retval (t));
       else if (in_ipa_mode
               && fi != NULL)
@@ -4770,7 +4792,7 @@ find_func_aliases (gimple origt)
             any global memory.  */
          if (op)
            {
-             vec<ce_s> lhsc = vNULL;
+             auto_vec<ce_s, 2> lhsc;
              struct constraint_expr rhsc, *lhsp;
              unsigned j;
              get_constraint_for (op, &lhsc);
@@ -4779,7 +4801,6 @@ find_func_aliases (gimple origt)
              rhsc.type = SCALAR;
              FOR_EACH_VEC_ELT (lhsc, j, lhsp)
                process_constraint (new_constraint (*lhsp, rhsc));
-             lhsc.release ();
            }
        }
       for (i = 0; i < gimple_asm_ninputs (t); ++i)
@@ -4802,9 +4823,6 @@ find_func_aliases (gimple origt)
            make_escape_constraint (op);
        }
     }
-
-  rhsc.release ();
-  lhsc.release ();
 }
 
 
@@ -4829,11 +4847,11 @@ process_ipa_clobber (varinfo_t fi, tree ptr)
    IPA constraint builder.  */
 
 static void
-find_func_clobbers (gimple origt)
+find_func_clobbers (struct function *fn, gimple origt)
 {
   gimple t = origt;
-  vec<ce_s> lhsc = vNULL;
-  auto_vec<ce_s> rhsc;
+  auto_vec<ce_s, 16> lhsc;
+  auto_vec<ce_s, 16> rhsc;
   varinfo_t fi;
 
   /* Add constraints for clobbered/used in IPA mode.
@@ -4847,7 +4865,7 @@ find_func_clobbers (gimple origt)
     return;
 
   /* We'd better have function information for the current function.  */
-  fi = lookup_vi_for_tree (cfun->decl);
+  fi = lookup_vi_for_tree (fn->decl);
   gcc_assert (fi != NULL);
 
   /* Account for stores in assignments and calls.  */
@@ -4859,12 +4877,12 @@ find_func_clobbers (gimple origt)
       while (handled_component_p (tem))
        tem = TREE_OPERAND (tem, 0);
       if ((DECL_P (tem)
-          && !auto_var_in_fn_p (tem, cfun->decl))
+          && !auto_var_in_fn_p (tem, fn->decl))
          || INDIRECT_REF_P (tem)
          || (TREE_CODE (tem) == MEM_REF
              && !(TREE_CODE (TREE_OPERAND (tem, 0)) == ADDR_EXPR
                   && auto_var_in_fn_p
-                       (TREE_OPERAND (TREE_OPERAND (tem, 0), 0), cfun->decl))))
+                       (TREE_OPERAND (TREE_OPERAND (tem, 0), 0), fn->decl))))
        {
          struct constraint_expr lhsc, *rhsp;
          unsigned i;
@@ -4872,7 +4890,7 @@ find_func_clobbers (gimple origt)
          get_constraint_for_address_of (lhs, &rhsc);
          FOR_EACH_VEC_ELT (rhsc, i, rhsp)
            process_constraint (new_constraint (lhsc, *rhsp));
-         rhsc.release ();
+         rhsc.truncate (0);
        }
     }
 
@@ -4887,12 +4905,12 @@ find_func_clobbers (gimple origt)
       while (handled_component_p (tem))
        tem = TREE_OPERAND (tem, 0);
       if ((DECL_P (tem)
-          && !auto_var_in_fn_p (tem, cfun->decl))
+          && !auto_var_in_fn_p (tem, fn->decl))
          || INDIRECT_REF_P (tem)
          || (TREE_CODE (tem) == MEM_REF
              && !(TREE_CODE (TREE_OPERAND (tem, 0)) == ADDR_EXPR
                   && auto_var_in_fn_p
-                       (TREE_OPERAND (TREE_OPERAND (tem, 0), 0), cfun->decl))))
+                       (TREE_OPERAND (TREE_OPERAND (tem, 0), 0), fn->decl))))
        {
          struct constraint_expr lhs, *rhsp;
          unsigned i;
@@ -4900,7 +4918,7 @@ find_func_clobbers (gimple origt)
          get_constraint_for_address_of (rhs, &rhsc);
          FOR_EACH_VEC_ELT (rhsc, i, rhsp)
            process_constraint (new_constraint (lhs, *rhsp));
-         rhsc.release ();
+         rhsc.truncate (0);
        }
     }
 
@@ -4948,18 +4966,17 @@ find_func_clobbers (gimple origt)
              lhs = get_function_part_constraint (fi, fi_clobbers);
              FOR_EACH_VEC_ELT (lhsc, i, lhsp)
                process_constraint (new_constraint (lhs, *lhsp));
-             lhsc.release ();
              get_constraint_for_ptr_offset (src, NULL_TREE, &rhsc);
              lhs = get_function_part_constraint (fi, fi_uses);
              FOR_EACH_VEC_ELT (rhsc, i, rhsp)
                process_constraint (new_constraint (lhs, *rhsp));
-             rhsc.release ();
              return;
            }
          /* The following function clobbers memory pointed to by
             its argument.  */
          case BUILT_IN_MEMSET:
          case BUILT_IN_MEMSET_CHK:
+         case BUILT_IN_POSIX_MEMALIGN:
            {
              tree dest = gimple_call_arg (t, 0);
              unsigned i;
@@ -4968,7 +4985,6 @@ find_func_clobbers (gimple origt)
              lhs = get_function_part_constraint (fi, fi_clobbers);
              FOR_EACH_VEC_ELT (lhsc, i, lhsp)
                process_constraint (new_constraint (lhs, *lhsp));
-             lhsc.release ();
              return;
            }
          /* The following functions clobber their second and third
@@ -5038,7 +5054,7 @@ find_func_clobbers (gimple origt)
          get_constraint_for_address_of (arg, &rhsc);
          FOR_EACH_VEC_ELT (rhsc, j, rhsp)
            process_constraint (new_constraint (lhs, *rhsp));
-         rhsc.release ();
+         rhsc.truncate (0);
        }
 
       /* Build constraints for propagating clobbers/uses along the
@@ -5603,6 +5619,7 @@ create_variable_info_for_1 (tree decl, const char *name)
   auto_vec<fieldoff_s> fieldstack;
   fieldoff_s *fo;
   unsigned int i;
+  varpool_node *vnode;
 
   if (!declsize
       || !tree_fits_uhwi_p (declsize))
@@ -5624,7 +5641,8 @@ create_variable_info_for_1 (tree decl, const char *name)
         in IPA mode.  Else we'd have to parse arbitrary initializers.  */
       && !(in_ipa_mode
           && is_global_var (decl)
-          && DECL_INITIAL (decl)))
+          && (vnode = varpool_node::get (decl))
+          && vnode->get_constructor ()))
     {
       fieldoff_s *fo = NULL;
       bool notokay = false;
@@ -5742,21 +5760,21 @@ create_variable_info_for (tree decl, const char *name)
         for it.  */
       else
        {
-         varpool_node *vnode = varpool_get_node (decl);
+         varpool_node *vnode = varpool_node::get (decl);
 
          /* For escaped variables initialize them from nonlocal.  */
-         if (!varpool_all_refs_explicit_p (vnode))
+         if (!vnode->all_refs_explicit_p ())
            make_copy_constraint (vi, nonlocal_id);
 
          /* If this is a global variable with an initializer and we are in
             IPA mode generate constraints for it.  */
-         if (DECL_INITIAL (decl)
+         if (vnode->get_constructor ()
              && vnode->definition)
            {
              auto_vec<ce_s> rhsc;
              struct constraint_expr lhs, *rhsp;
              unsigned i;
-             get_constraint_for_rhs (DECL_INITIAL (decl), &rhsc);
+             get_constraint_for_rhs (vnode->get_constructor (), &rhsc);
              lhs.var = vi->id;
              lhs.offset = 0;
              lhs.type = SCALAR;
@@ -5764,7 +5782,7 @@ create_variable_info_for (tree decl, const char *name)
                process_constraint (new_constraint (lhs, *rhsp));
              /* If this is a variable that escapes from the unit
                 the initializer escapes as well.  */
-             if (!varpool_all_refs_explicit_p (vnode))
+             if (!vnode->all_refs_explicit_p ())
                {
                  lhs.var = escaped_id;
                  lhs.offset = 0;
@@ -5803,26 +5821,26 @@ dump_solution_for_var (FILE *file, unsigned int var)
   fprintf (file, "\n");
 }
 
-/* Print the points-to solution for VAR to stdout.  */
+/* Print the points-to solution for VAR to stderr.  */
 
 DEBUG_FUNCTION void
 debug_solution_for_var (unsigned int var)
 {
-  dump_solution_for_var (stdout, var);
+  dump_solution_for_var (stderr, var);
 }
 
 /* Create varinfo structures for all of the variables in the
    function for intraprocedural mode.  */
 
 static void
-intra_create_variable_infos (void)
+intra_create_variable_infos (struct function *fn)
 {
   tree t;
 
   /* For each incoming pointer argument arg, create the constraint ARG
      = NONLOCAL or a dummy variable if it is a restrict qualified
      passed-by-reference argument.  */
-  for (t = DECL_ARGUMENTS (current_function_decl); t; t = DECL_CHAIN (t))
+  for (t = DECL_ARGUMENTS (fn->decl); t; t = DECL_CHAIN (t))
     {
       varinfo_t p = get_vi_for_tree (t);
 
@@ -5874,19 +5892,19 @@ intra_create_variable_infos (void)
     }
 
   /* Add a constraint for a result decl that is passed by reference.  */
-  if (DECL_RESULT (cfun->decl)
-      && DECL_BY_REFERENCE (DECL_RESULT (cfun->decl)))
+  if (DECL_RESULT (fn->decl)
+      && DECL_BY_REFERENCE (DECL_RESULT (fn->decl)))
     {
-      varinfo_t p, result_vi = get_vi_for_tree (DECL_RESULT (cfun->decl));
+      varinfo_t p, result_vi = get_vi_for_tree (DECL_RESULT (fn->decl));
 
       for (p = result_vi; p; p = vi_next (p))
        make_constraint_from (p, nonlocal_id);
     }
 
   /* Add a constraint for the incoming static chain parameter.  */
-  if (cfun->static_chain_decl != NULL_TREE)
+  if (fn->static_chain_decl != NULL_TREE)
     {
-      varinfo_t p, chain_vi = get_vi_for_tree (cfun->static_chain_decl);
+      varinfo_t p, chain_vi = get_vi_for_tree (fn->static_chain_decl);
 
       for (p = chain_vi; p; p = vi_next (p))
        make_constraint_from (p, nonlocal_id);
@@ -5931,7 +5949,7 @@ shared_bitmap_hasher::equal (const value_type *sbi1, const compare_type *sbi2)
 
 /* Shared_bitmap hashtable.  */
 
-static hash_table <shared_bitmap_hasher> shared_bitmap_table;
+static hash_table<shared_bitmap_hasher> *shared_bitmap_table;
 
 /* Lookup a bitmap in the shared bitmap hashtable, and return an already
    existing instance if there is one, NULL otherwise.  */
@@ -5945,8 +5963,7 @@ shared_bitmap_lookup (bitmap pt_vars)
   sbi.pt_vars = pt_vars;
   sbi.hashcode = bitmap_hash (pt_vars);
 
-  slot = shared_bitmap_table.find_slot_with_hash (&sbi, sbi.hashcode,
-                                                 NO_INSERT);
+  slot = shared_bitmap_table->find_slot (&sbi, NO_INSERT);
   if (!slot)
     return NULL;
   else
@@ -5965,7 +5982,7 @@ shared_bitmap_add (bitmap pt_vars)
   sbi->pt_vars = pt_vars;
   sbi->hashcode = bitmap_hash (pt_vars);
 
-  slot = shared_bitmap_table.find_slot_with_hash (sbi, sbi->hashcode, INSERT);
+  slot = shared_bitmap_table->find_slot (sbi, INSERT);
   gcc_assert (!*slot);
   *slot = sbi;
 }
@@ -6029,7 +6046,6 @@ find_what_var_points_to (varinfo_t orig_vi)
   bitmap finished_solution;
   bitmap result;
   varinfo_t vi;
-  void **slot;
   struct pt_solution *pt;
 
   /* This variable may have been collapsed, let's get the real
@@ -6037,9 +6053,9 @@ find_what_var_points_to (varinfo_t orig_vi)
   vi = get_varinfo (find (orig_vi->id));
 
   /* See if we have already computed the solution and return it.  */
-  slot = pointer_map_insert (final_solutions, vi);
+  pt_solution **slot = &final_solutions->get_or_insert (vi);
   if (*slot != NULL)
-    return *(struct pt_solution *)*slot;
+    return **slot;
 
   *slot = pt = XOBNEW (&final_solutions_obstack, struct pt_solution);
   memset (pt, 0, sizeof (struct pt_solution));
@@ -6060,14 +6076,18 @@ find_what_var_points_to (varinfo_t orig_vi)
                pt->ipa_escaped = 1;
              else
                pt->escaped = 1;
+             /* Expand some special vars of ESCAPED in-place here.  */
+             varinfo_t evi = get_varinfo (find (escaped_id));
+             if (bitmap_bit_p (evi->solution, nonlocal_id))
+               pt->nonlocal = 1;
            }
          else if (vi->id == nonlocal_id)
            pt->nonlocal = 1;
          else if (vi->is_heap_var)
            /* We represent heapvars in the points-to set properly.  */
            ;
-         else if (vi->id == readonly_id)
-           /* Nobody cares.  */
+         else if (vi->id == string_id)
+           /* Nobody cares - STRING_CSTs are read-only entities.  */
            ;
          else if (vi->id == anything_id
                   || vi->id == integer_id)
@@ -6455,7 +6475,7 @@ init_base_vars (void)
   struct constraint_expr lhs, rhs;
   varinfo_t var_anything;
   varinfo_t var_nothing;
-  varinfo_t var_readonly;
+  varinfo_t var_string;
   varinfo_t var_escaped;
   varinfo_t var_nonlocal;
   varinfo_t var_storedanything;
@@ -6501,27 +6521,17 @@ init_base_vars (void)
      but this one are redundant.  */
   constraints.safe_push (new_constraint (lhs, rhs));
 
-  /* Create the READONLY variable, used to represent that a variable
-     points to readonly memory.  */
-  var_readonly = new_var_info (NULL_TREE, "READONLY");
-  gcc_assert (var_readonly->id == readonly_id);
-  var_readonly->is_artificial_var = 1;
-  var_readonly->offset = 0;
-  var_readonly->size = ~0;
-  var_readonly->fullsize = ~0;
-  var_readonly->is_special_var = 1;
-
-  /* readonly memory points to anything, in order to make deref
-     easier.  In reality, it points to anything the particular
-     readonly variable can point to, but we don't track this
-     separately. */
-  lhs.type = SCALAR;
-  lhs.var = readonly_id;
-  lhs.offset = 0;
-  rhs.type = ADDRESSOF;
-  rhs.var = readonly_id;  /* FIXME */
-  rhs.offset = 0;
-  process_constraint (new_constraint (lhs, rhs));
+  /* Create the STRING variable, used to represent that a variable
+     points to a string literal.  String literals don't contain
+     pointers so STRING doesn't point to anything.  */
+  var_string = new_var_info (NULL_TREE, "STRING");
+  gcc_assert (var_string->id == string_id);
+  var_string->is_artificial_var = 1;
+  var_string->offset = 0;
+  var_string->size = ~0;
+  var_string->fullsize = ~0;
+  var_string->is_special_var = 1;
+  var_string->may_have_pointers = 0;
 
   /* Create the ESCAPED variable, used to represent the set of escaped
      memory.  */
@@ -6635,16 +6645,16 @@ init_alias_vars (void)
                                          sizeof (struct variable_info), 30);
   constraints.create (8);
   varmap.create (8);
-  vi_for_tree = pointer_map_create ();
-  call_stmt_vars = pointer_map_create ();
+  vi_for_tree = new hash_map<tree, varinfo_t>;
+  call_stmt_vars = new hash_map<gimple, varinfo_t>;
 
   memset (&stats, 0, sizeof (stats));
-  shared_bitmap_table.create (511);
+  shared_bitmap_table = new hash_table<shared_bitmap_hasher> (511);
   init_base_vars ();
 
   gcc_obstack_init (&fake_var_decl_obstack);
 
-  final_solutions = pointer_map_create ();
+  final_solutions = new hash_map<varinfo_t, pt_solution *>;
   gcc_obstack_init (&final_solutions_obstack);
 }
 
@@ -6771,7 +6781,7 @@ compute_points_to_sets (void)
 
   init_alias_vars ();
 
-  intra_create_variable_infos ();
+  intra_create_variable_infos (cfun);
 
   /* Now walk all statements and build the constraint set.  */
   FOR_EACH_BB_FN (bb, cfun)
@@ -6783,14 +6793,14 @@ compute_points_to_sets (void)
          gimple phi = gsi_stmt (gsi);
 
          if (! virtual_operand_p (gimple_phi_result (phi)))
-           find_func_aliases (phi);
+           find_func_aliases (cfun, phi);
        }
 
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
          gimple stmt = gsi_stmt (gsi);
 
-         find_func_aliases (stmt);
+         find_func_aliases (cfun, stmt);
        }
     }
 
@@ -6887,13 +6897,14 @@ delete_points_to_sets (void)
 {
   unsigned int i;
 
-  shared_bitmap_table.dispose ();
+  delete shared_bitmap_table;
+  shared_bitmap_table = NULL;
   if (dump_file && (dump_flags & TDF_STATS))
     fprintf (dump_file, "Points to sets created:%d\n",
             stats.points_to_sets_created);
 
-  pointer_map_destroy (vi_for_tree);
-  pointer_map_destroy (call_stmt_vars);
+  delete vi_for_tree;
+  delete call_stmt_vars;
   bitmap_obstack_release (&pta_obstack);
   constraints.release ();
 
@@ -6914,7 +6925,7 @@ delete_points_to_sets (void)
 
   obstack_free (&fake_var_decl_obstack, NULL);
 
-  pointer_map_destroy (final_solutions);
+  delete final_solutions;
   obstack_free (&final_solutions_obstack, NULL);
 }
 
@@ -6958,12 +6969,6 @@ compute_may_aliases (void)
   return 0;
 }
 
-static bool
-gate_tree_pta (void)
-{
-  return flag_tree_pta;
-}
-
 /* A dummy pass to cause points-to information to be computed via
    TODO_rebuild_alias.  */
 
@@ -6974,8 +6979,6 @@ const pass_data pass_data_build_alias =
   GIMPLE_PASS, /* type */
   "alias", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_gate */
-  false, /* has_execute */
   TV_NONE, /* tv_id */
   ( PROP_cfg | PROP_ssa ), /* properties_required */
   0, /* properties_provided */
@@ -6992,7 +6995,7 @@ public:
   {}
 
   /* opt_pass methods: */
-  bool gate () { return gate_tree_pta (); }
+  virtual bool gate (function *) { return flag_tree_pta; }
 
 }; // class pass_build_alias
 
@@ -7014,8 +7017,6 @@ const pass_data pass_data_build_ealias =
   GIMPLE_PASS, /* type */
   "ealias", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_gate */
-  false, /* has_execute */
   TV_NONE, /* tv_id */
   ( PROP_cfg | PROP_ssa ), /* properties_required */
   0, /* properties_provided */
@@ -7032,7 +7033,7 @@ public:
   {}
 
   /* opt_pass methods: */
-  bool gate () { return gate_tree_pta (); }
+  virtual bool gate (function *) { return flag_tree_pta; }
 
 }; // class pass_build_ealias
 
@@ -7045,16 +7046,6 @@ make_pass_build_ealias (gcc::context *ctxt)
 }
 
 
-/* Return true if we should execute IPA PTA.  */
-static bool
-gate_ipa_pta (void)
-{
-  return (optimize
-         && flag_ipa_pta
-         /* Don't bother doing anything if the program has errors.  */
-         && !seen_error ());
-}
-
 /* IPA PTA solutions for ESCAPED.  */
 struct pt_solution ipa_escaped_pt
   = { true, false, false, false, false, false, false, false, NULL };
@@ -7084,7 +7075,7 @@ ipa_pta_execute (void)
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      dump_symtab (dump_file);
+      symtab_node::dump_table (dump_file);
       fprintf (dump_file, "\n");
     }
 
@@ -7095,15 +7086,16 @@ ipa_pta_execute (void)
       /* Nodes without a body are not interesting.  Especially do not
          visit clones at this point for now - we get duplicate decls
         there for inline clones at least.  */
-      if (!cgraph_function_with_gimple_body_p (node) || node->clone_of)
+      if (!node->has_gimple_body_p () || node->clone_of)
        continue;
-      cgraph_get_body (node);
+      node->get_body ();
 
       gcc_assert (!node->clone_of);
 
       vi = create_function_info_for (node->decl,
                                     alias_get_name (node->decl));
-      cgraph_for_node_and_aliases (node, associate_varinfo_to_alias, vi, true);
+      node->call_for_symbol_thunks_and_aliases
+       (associate_varinfo_to_alias, vi, true);
     }
 
   /* Create constraints for global variables and their initializers.  */
@@ -7130,7 +7122,7 @@ ipa_pta_execute (void)
       basic_block bb;
 
       /* Nodes without a body are not interesting.  */
-      if (!cgraph_function_with_gimple_body_p (node) || node->clone_of)
+      if (!node->has_gimple_body_p () || node->clone_of)
        continue;
 
       if (dump_file)
@@ -7145,7 +7137,7 @@ ipa_pta_execute (void)
        }
 
       func = DECL_STRUCT_FUNCTION (node->decl);
-      push_cfun (func);
+      gcc_assert (cfun == NULL);
 
       /* For externally visible or attribute used annotated functions use
         local constraints for their arguments.
@@ -7155,7 +7147,7 @@ ipa_pta_execute (void)
          || node->externally_visible
          || node->force_output)
        {
-         intra_create_variable_infos ();
+         intra_create_variable_infos (func);
 
          /* We also need to make function return values escape.  Nothing
             escapes by returning from main though.  */
@@ -7190,20 +7182,18 @@ ipa_pta_execute (void)
              gimple phi = gsi_stmt (gsi);
 
              if (! virtual_operand_p (gimple_phi_result (phi)))
-               find_func_aliases (phi);
+               find_func_aliases (func, phi);
            }
 
          for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
            {
              gimple stmt = gsi_stmt (gsi);
 
-             find_func_aliases (stmt);
-             find_func_clobbers (stmt);
+             find_func_aliases (func, stmt);
+             find_func_clobbers (func, stmt);
            }
        }
 
-      pop_cfun ();
-
       if (dump_file)
        {
          fprintf (dump_file, "\n");
@@ -7233,13 +7223,10 @@ ipa_pta_execute (void)
       tree ptr;
       struct function *fn;
       unsigned i;
-      varinfo_t fi;
       basic_block bb;
-      struct pt_solution uses, clobbers;
-      struct cgraph_edge *e;
 
       /* Nodes without a body are not interesting.  */
-      if (!cgraph_function_with_gimple_body_p (node) || node->clone_of)
+      if (!node->has_gimple_body_p () || node->clone_of)
        continue;
 
       fn = DECL_STRUCT_FUNCTION (node->decl);
@@ -7252,21 +7239,6 @@ ipa_pta_execute (void)
            find_what_p_points_to (ptr);
        }
 
-      /* Compute the call-use and call-clobber sets for all direct calls.  */
-      fi = lookup_vi_for_tree (node->decl);
-      gcc_assert (fi->is_fn_info);
-      clobbers
-       = find_what_var_points_to (first_vi_for_offset (fi, fi_clobbers));
-      uses = find_what_var_points_to (first_vi_for_offset (fi, fi_uses));
-      for (e = node->callers; e; e = e->next_caller)
-       {
-         if (!e->call_stmt)
-           continue;
-
-         *gimple_call_clobber_set (e->call_stmt) = clobbers;
-         *gimple_call_use_set (e->call_stmt) = uses;
-       }
-
       /* Compute the call-use and call-clobber sets for indirect calls
         and calls to external functions.  */
       FOR_EACH_BB_FN (bb, fn)
@@ -7277,17 +7249,27 @@ ipa_pta_execute (void)
            {
              gimple stmt = gsi_stmt (gsi);
              struct pt_solution *pt;
-             varinfo_t vi;
+             varinfo_t vi, fi;
              tree decl;
 
              if (!is_gimple_call (stmt))
                continue;
 
-             /* Handle direct calls to external functions.  */
+             /* Handle direct calls to functions with body.  */
              decl = gimple_call_fndecl (stmt);
              if (decl
-                 && (!(fi = lookup_vi_for_tree (decl))
-                     || !fi->is_fn_info))
+                 && (fi = lookup_vi_for_tree (decl))
+                 && fi->is_fn_info)
+               {
+                 *gimple_call_clobber_set (stmt)
+                    = find_what_var_points_to
+                        (first_vi_for_offset (fi, fi_clobbers));
+                 *gimple_call_use_set (stmt)
+                    = find_what_var_points_to
+                        (first_vi_for_offset (fi, fi_uses));
+               }
+             /* Handle direct calls to external functions.  */
+             else if (decl)
                {
                  pt = gimple_call_use_set (stmt);
                  if (gimple_call_flags (stmt) & ECF_CONST)
@@ -7331,10 +7313,9 @@ ipa_pta_execute (void)
                      pt->nonlocal = 1;
                    }
                }
-
              /* Handle indirect calls.  */
-             if (!decl
-                 && (fi = get_fi_for_callee (stmt)))
+             else if (!decl
+                      && (fi = get_fi_for_callee (stmt)))
                {
                  /* We need to accumulate all clobbers/uses of all possible
                     callees.  */
@@ -7408,8 +7389,6 @@ const pass_data pass_data_ipa_pta =
   SIMPLE_IPA_PASS, /* type */
   "pta", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
   TV_IPA_PTA, /* tv_id */
   0, /* properties_required */
   0, /* properties_provided */
@@ -7426,8 +7405,15 @@ public:
   {}
 
   /* opt_pass methods: */
-  bool gate () { return gate_ipa_pta (); }
-  unsigned int execute () { return ipa_pta_execute (); }
+  virtual bool gate (function *)
+    {
+      return (optimize
+             && flag_ipa_pta
+             /* Don't bother doing anything if the program has errors.  */
+             && !seen_error ());
+    }
+
+  virtual unsigned int execute (function *) { return ipa_pta_execute (); }
 
 }; // class pass_ipa_pta