]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree-ssa-structalias.c
Merge from trunk.
[thirdparty/gcc.git] / gcc / tree-ssa-structalias.c
index 31c04aa8bb3bfc954e237d6ee15ef52ee51ccb23..0258c0e5263c4f8492aae1b15b14190dbdf3b8f1 100644 (file)
 #include "ggc.h"
 #include "obstack.h"
 #include "bitmap.h"
+#include "sbitmap.h"
 #include "flags.h"
 #include "basic-block.h"
 #include "tree.h"
-#include "tree-flow.h"
+#include "stor-layout.h"
+#include "stmt.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "stringpool.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
+#include "expr.h"
+#include "tree-dfa.h"
 #include "tree-inline.h"
 #include "diagnostic-core.h"
-#include "gimple.h"
-#include "hashtab.h"
+#include "hash-table.h"
 #include "function.h"
-#include "cgraph.h"
 #include "tree-pass.h"
 #include "alloc-pool.h"
 #include "splay-tree.h"
 #include "params.h"
-#include "cgraph.h"
 #include "alias.h"
 #include "pointer-set.h"
 
@@ -268,8 +276,12 @@ struct variable_info
   /* True if this represents a IPA function info.  */
   unsigned int is_fn_info : 1;
 
-  /* A link to the variable for the next field in this structure.  */
-  struct variable_info *next;
+  /* The ID of the variable for the next field in this structure
+     or zero for the last field in this structure.  */
+  unsigned next;
+
+  /* The ID of the variable for the first field in this structure.  */
+  unsigned head;
 
   /* Offset of this variable, in bits, from the base variable  */
   unsigned HOST_WIDE_INT offset;
@@ -319,10 +331,20 @@ get_varinfo (unsigned int n)
   return varmap[n];
 }
 
-/* Static IDs for the special variables.  */
-enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
-       escaped_id = 3, nonlocal_id = 4,
-       storedanything_id = 5, integer_id = 6 };
+/* Return the next variable in the list of sub-variables of VI
+   or NULL if VI is the last sub-variable.  */
+
+static inline varinfo_t
+vi_next (varinfo_t vi)
+{
+  return get_varinfo (vi->next);
+}
+
+/* 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,
+       escaped_id = 4, nonlocal_id = 5,
+       storedanything_id = 6, integer_id = 7 };
 
 /* Return a new variable info structure consisting for a variable
    named NAME, and using constraint graph node NODE.  Append it
@@ -355,7 +377,8 @@ new_var_info (tree t, const char *name)
                              && DECL_HARD_REGISTER (t)));
   ret->solution = BITMAP_ALLOC (&pta_obstack);
   ret->oldsolution = NULL;
-  ret->next = NULL;
+  ret->next = 0;
+  ret->head = ret->id;
 
   stats.total_vars++;
 
@@ -367,7 +390,7 @@ 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.  */
-struct pointer_map_t *call_stmt_vars;
+static struct pointer_map_t *call_stmt_vars;
 
 /* Lookup or create the variable for the call statement CALL.  */
 
@@ -387,12 +410,14 @@ get_call_vi (gimple call)
   vi->fullsize = 2;
   vi->is_full_var = true;
 
-  vi->next = vi2 = new_var_info (NULL_TREE, "CALLCLOBBERED");
+  vi2 = new_var_info (NULL_TREE, "CALLCLOBBERED");
   vi2->offset = 1;
   vi2->size = 1;
   vi2->fullsize = 2;
   vi2->is_full_var = true;
 
+  vi->next = vi2->id;
+
   *slot_p = (void *) vi;
   return vi;
 }
@@ -422,7 +447,7 @@ lookup_call_clobber_vi (gimple call)
   if (!uses)
     return NULL;
 
-  return uses->next;
+  return vi_next (uses);
 }
 
 /* Lookup or create the variable for the call statement CALL representing
@@ -440,7 +465,7 @@ get_call_use_vi (gimple call)
 static varinfo_t ATTRIBUTE_UNUSED
 get_call_clobber_vi (gimple call)
 {
-  return get_call_vi (call)->next;
+  return vi_next (get_call_vi (call));
 }
 
 
@@ -465,7 +490,7 @@ struct constraint_expr
 };
 
 /* Use 0x8000... as special unknown offset.  */
-#define UNKNOWN_OFFSET ((HOST_WIDE_INT)-1 << (HOST_BITS_PER_WIDE_INT-1))
+#define UNKNOWN_OFFSET HOST_WIDE_INT_MIN
 
 typedef struct constraint_expr ce_s;
 static void get_constraint_for_1 (tree, vec<ce_s> *, bool, bool);
@@ -581,7 +606,7 @@ static constraint_graph_t graph;
 static unsigned int
 find (unsigned int node)
 {
-  gcc_assert (node < graph->size);
+  gcc_checking_assert (node < graph->size);
   if (graph->rep[node] != node)
     return graph->rep[node] = find (graph->rep[node]);
   return node;
@@ -595,7 +620,7 @@ find (unsigned int node)
 static bool
 unite (unsigned int to, unsigned int from)
 {
-  gcc_assert (to < graph->size && from < graph->size);
+  gcc_checking_assert (to < graph->size && from < graph->size);
   if (to != from && graph->rep[from] != to)
     {
       graph->rep[from] = to;
@@ -701,8 +726,10 @@ dump_constraint_graph (FILE *file)
 
   /* The next lines print the nodes in the graph together with the
      complex constraints attached to them.  */
-  for (i = 0; i < graph->size; i++)
+  for (i = 1; i < graph->size; i++)
     {
+      if (i == FIRST_REF_NODE)
+       continue;
       if (find (i) != i)
        continue;
       if (i < FIRST_REF_NODE)
@@ -726,7 +753,7 @@ dump_constraint_graph (FILE *file)
 
   /* Go over the edges.  */
   fprintf (file, "\n  // Edges in the constraint graph:\n");
-  for (i = 0; i < graph->size; i++)
+  for (i = 1; i < graph->size; i++)
     {
       unsigned j;
       bitmap_iterator bi;
@@ -881,63 +908,71 @@ constraint_set_union (vec<constraint_t> *to,
     }
 }
 
-/* Expands the solution in SET to all sub-fields of variables included.
-   Union the expanded result into RESULT.  */
+/* Expands the solution in SET to all sub-fields of variables included.  */
 
 static void
-solution_set_expand (bitmap result, bitmap set)
+solution_set_expand (bitmap set)
 {
   bitmap_iterator bi;
-  bitmap vars = NULL;
   unsigned j;
 
-  /* In a first pass record all variables we need to add all
-     sub-fields off.  This avoids quadratic behavior.  */
+  /* In a first pass expand to the head of the variables we need to
+     add all sub-fields off.  This avoids quadratic behavior.  */
   EXECUTE_IF_SET_IN_BITMAP (set, 0, j, bi)
     {
       varinfo_t v = get_varinfo (j);
       if (v->is_artificial_var
          || v->is_full_var)
        continue;
-      v = lookup_vi_for_tree (v->decl);
-      if (vars == NULL)
-       vars = BITMAP_ALLOC (NULL);
-      bitmap_set_bit (vars, v->id);
+      bitmap_set_bit (set, v->head);
     }
 
-  /* In the second pass now do the addition to the solution and
-     to speed up solving add it to the delta as well.  */
-  if (vars != NULL)
+  /* In the second pass now expand all head variables with subfields.  */
+  EXECUTE_IF_SET_IN_BITMAP (set, 0, j, bi)
     {
-      EXECUTE_IF_SET_IN_BITMAP (vars, 0, j, bi)
-       {
-         varinfo_t v = get_varinfo (j);
-         for (; v != NULL; v = v->next)
-           bitmap_set_bit (result, v->id);
-       }
-      BITMAP_FREE (vars);
+      varinfo_t v = get_varinfo (j);
+      if (v->is_artificial_var
+         || v->is_full_var
+         || v->head != j)
+       continue;
+      for (v = vi_next (v); v != NULL; v = vi_next (v))
+       bitmap_set_bit (set, v->id);
     }
 }
 
-/* Take a solution set SET, add OFFSET to each member of the set, and
-   overwrite SET with the result when done.  */
+/* Union solution sets TO and FROM, and add INC to each member of FROM in the
+   process.  */
 
-static void
-solution_set_add (bitmap set, HOST_WIDE_INT offset)
+static bool
+set_union_with_increment  (bitmap to, bitmap from, HOST_WIDE_INT inc)
 {
-  bitmap result = BITMAP_ALLOC (&iteration_obstack);
-  unsigned int i;
+  bool changed = false;
   bitmap_iterator bi;
+  unsigned int i;
+
+  /* If the solution of FROM contains anything it is good enough to transfer
+     this to TO.  */
+  if (bitmap_bit_p (from, anything_id))
+    return bitmap_set_bit (to, anything_id);
+
+  /* For zero offset simply union the solution into the destination.  */
+  if (inc == 0)
+    return bitmap_ior_into (to, from);
 
   /* If the offset is unknown we have to expand the solution to
      all subfields.  */
-  if (offset == UNKNOWN_OFFSET)
+  if (inc == UNKNOWN_OFFSET)
     {
-      solution_set_expand (set, set);
-      return;
+      bitmap tmp = BITMAP_ALLOC (&iteration_obstack);
+      bitmap_copy (tmp, from);
+      solution_set_expand (tmp);
+      changed |= bitmap_ior_into (to, tmp);
+      BITMAP_FREE (tmp);
+      return changed;
     }
 
-  EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
+  /* For non-zero offset union the offsetted solution into the destination.  */
+  EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
     {
       varinfo_t vi = get_varinfo (i);
 
@@ -946,54 +981,30 @@ solution_set_add (bitmap set, HOST_WIDE_INT offset)
       if (vi->is_artificial_var
          || vi->is_unknown_size_var
          || vi->is_full_var)
-       bitmap_set_bit (result, i);
+       changed |= bitmap_set_bit (to, i);
       else
        {
-         unsigned HOST_WIDE_INT fieldoffset = vi->offset + offset;
+         unsigned HOST_WIDE_INT fieldoffset = vi->offset + inc;
 
          /* If the offset makes the pointer point to before the
             variable use offset zero for the field lookup.  */
-         if (offset < 0
+         if (inc < 0
              && fieldoffset > vi->offset)
            fieldoffset = 0;
 
-         if (offset != 0)
-           vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
+         vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
 
-         bitmap_set_bit (result, vi->id);
+         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 != NULL)
-           bitmap_set_bit (result, vi->next->id);
+             && vi->next != 0)
+           changed |= bitmap_set_bit (to, vi->next);
        }
     }
 
-  bitmap_copy (set, result);
-  BITMAP_FREE (result);
-}
-
-/* Union solution sets TO and FROM, and add INC to each member of FROM in the
-   process.  */
-
-static bool
-set_union_with_increment  (bitmap to, bitmap from, HOST_WIDE_INT inc)
-{
-  if (inc == 0)
-    return bitmap_ior_into (to, from);
-  else
-    {
-      bitmap tmp;
-      bool res;
-
-      tmp = BITMAP_ALLOC (&iteration_obstack);
-      bitmap_copy (tmp, from);
-      solution_set_add (tmp, inc);
-      res = bitmap_ior_into (to, tmp);
-      BITMAP_FREE (tmp);
-      return res;
-    }
+  return changed;
 }
 
 /* Insert constraint C into the list of complex constraints for graph
@@ -1023,7 +1034,7 @@ merge_node_constraints (constraint_graph_t graph, unsigned int to,
   unsigned int i;
   constraint_t c;
 
-  gcc_assert (find (from) == to);
+  gcc_checking_assert (find (from) == to);
 
   /* Move all complex constraints from src node into to node  */
   FOR_EACH_VEC_ELT (graph->complex[from], i, c)
@@ -1143,16 +1154,6 @@ add_graph_edge (constraint_graph_t graph, unsigned int to,
 }
 
 
-/* Return true if {DEST.SRC} is an existing graph edge in GRAPH.  */
-
-static bool
-valid_graph_edge (constraint_graph_t graph, unsigned int src,
-                 unsigned int dest)
-{
-  return (graph->succs[dest]
-         && bitmap_bit_p (graph->succs[dest], src));
-}
-
 /* Initialize the constraint graph structure to contain SIZE nodes.  */
 
 static void
@@ -1200,7 +1201,7 @@ build_pred_graph (void)
   graph->address_taken = BITMAP_ALLOC (&predbitmap_obstack);
   bitmap_clear (graph->direct_nodes);
 
-  for (j = 0; j < FIRST_REF_NODE; j++)
+  for (j = 1; j < FIRST_REF_NODE; j++)
     {
       if (!get_varinfo (j)->is_special_var)
        bitmap_set_bit (graph->direct_nodes, j);
@@ -1254,11 +1255,11 @@ build_pred_graph (void)
           v = get_varinfo (rhsvar);
           if (!v->is_full_var)
             {
-              v = lookup_vi_for_tree (v->decl);
+              v = get_varinfo (v->head);
               do
                 {
                   bitmap_clear_bit (graph->direct_nodes, v->id);
-                  v = v->next;
+                  v = vi_next (v);
                 }
               while (v != NULL);
             }
@@ -1319,7 +1320,7 @@ build_succ_graph (void)
       else if (rhs.type == ADDRESSOF)
        {
          /* x = &y */
-         gcc_assert (find (rhs.var) == rhs.var);
+         gcc_checking_assert (find (rhs.var) == rhs.var);
          bitmap_set_bit (get_varinfo (lhsvar)->solution, rhsvar);
        }
       else if (lhsvar > anything_id
@@ -1396,14 +1397,11 @@ scc_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
 
       if (!bitmap_bit_p (si->visited, w))
        scc_visit (graph, si, w);
-      {
-       unsigned int t = find (w);
-       unsigned int nnode = find (n);
-       gcc_assert (nnode == n);
 
-       if (si->dfs[t] < si->dfs[nnode])
-         si->dfs[n] = si->dfs[t];
-      }
+      unsigned int t = find (w);
+      gcc_checking_assert (find (n) == n);
+      if (si->dfs[t] < si->dfs[n])
+       si->dfs[n] = si->dfs[t];
     }
 
   /* See if any components have been identified.  */
@@ -1458,8 +1456,8 @@ static void
 unify_nodes (constraint_graph_t graph, unsigned int to, unsigned int from,
             bool update_changed)
 {
+  gcc_checking_assert (to != from && find (to) == to);
 
-  gcc_assert (to != from && find (to) == to);
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "Unifying %s to %s\n",
             get_varinfo (from)->name,
@@ -1477,35 +1475,30 @@ unify_nodes (constraint_graph_t graph, unsigned int to, unsigned int from,
      as changed, decrease the changed count.  */
 
   if (update_changed
-      && bitmap_bit_p (changed, from))
-    {
-      bitmap_clear_bit (changed, from);
-      bitmap_set_bit (changed, to);
-    }
-  if (get_varinfo (from)->solution)
+      && bitmap_clear_bit (changed, from))
+    bitmap_set_bit (changed, to);
+  varinfo_t fromvi = get_varinfo (from);
+  if (fromvi->solution)
     {
       /* If the solution changes because of the merging, we need to mark
         the variable as changed.  */
-      if (bitmap_ior_into (get_varinfo (to)->solution,
-                          get_varinfo (from)->solution))
+      varinfo_t tovi = get_varinfo (to);
+      if (bitmap_ior_into (tovi->solution, fromvi->solution))
        {
          if (update_changed)
            bitmap_set_bit (changed, to);
        }
 
-      BITMAP_FREE (get_varinfo (from)->solution);
-      if (get_varinfo (from)->oldsolution)
-       BITMAP_FREE (get_varinfo (from)->oldsolution);
+      BITMAP_FREE (fromvi->solution);
+      if (fromvi->oldsolution)
+       BITMAP_FREE (fromvi->oldsolution);
 
       if (stats.iterations > 0
-         && get_varinfo (to)->oldsolution)
-       BITMAP_FREE (get_varinfo (to)->oldsolution);
-    }
-  if (valid_graph_edge (graph, to, to))
-    {
-      if (graph->succs[to])
-       bitmap_clear_bit (graph->succs[to], to);
+         && tovi->oldsolution)
+       BITMAP_FREE (tovi->oldsolution);
     }
+  if (graph->succs[to])
+    bitmap_clear_bit (graph->succs[to], to);
 }
 
 /* Information needed to compute the topological ordering of a graph.  */
@@ -1581,7 +1574,7 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
   HOST_WIDE_INT roffset = c->rhs.offset;
 
   /* Our IL does not allow this.  */
-  gcc_assert (c->lhs.offset == 0);
+  gcc_checking_assert (c->lhs.offset == 0);
 
   /* If the solution of Y contains anything it is good enough to transfer
      this to the LHS.  */
@@ -1596,7 +1589,7 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
      dereferenced at all valid offsets.  */
   if (roffset == UNKNOWN_OFFSET)
     {
-      solution_set_expand (delta, delta);
+      solution_set_expand (delta);
       /* No further offset processing is necessary.  */
       roffset = 0;
     }
@@ -1636,10 +1629,10 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
          /* 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
-             || v->next == NULL)
+             || v->next == 0)
            break;
 
-         v = v->next;
+         v = vi_next (v);
          fieldoffset = v->offset;
        }
       while (1);
@@ -1668,7 +1661,7 @@ do_ds_constraint (constraint_t c, bitmap delta)
   bool escaped_p = false;
 
   /* Our IL does not allow this.  */
-  gcc_assert (c->rhs.offset == 0);
+  gcc_checking_assert (c->rhs.offset == 0);
 
   /* If the solution of y contains ANYTHING simply use the ANYTHING
      solution.  This avoids needlessly increasing the points-to sets.  */
@@ -1694,7 +1687,7 @@ do_ds_constraint (constraint_t c, bitmap delta)
      dereferenced at all valid offsets.  */
   if (loff == UNKNOWN_OFFSET)
     {
-      solution_set_expand (delta, delta);
+      solution_set_expand (delta);
       loff = 0;
     }
 
@@ -1742,10 +1735,10 @@ do_ds_constraint (constraint_t c, bitmap delta)
          /* 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
-             || v->next == NULL)
+             || v->next == 0)
            break;
 
-         v = v->next;
+         v = vi_next (v);
          fieldoffset = v->offset;
        }
       while (1);
@@ -1762,7 +1755,7 @@ do_complex_constraint (constraint_graph_t graph, constraint_t c, bitmap delta)
     {
       if (c->rhs.type == ADDRESSOF)
        {
-         gcc_unreachable();
+         gcc_unreachable ();
        }
       else
        {
@@ -1782,17 +1775,14 @@ do_complex_constraint (constraint_graph_t graph, constraint_t c, bitmap delta)
       bitmap solution;
       bool flag = false;
 
-      gcc_assert (c->rhs.type == SCALAR && c->lhs.type == SCALAR);
+      gcc_checking_assert (c->rhs.type == SCALAR && c->lhs.type == SCALAR);
       solution = get_varinfo (c->rhs.var)->solution;
       tmp = get_varinfo (c->lhs.var)->solution;
 
       flag = set_union_with_increment (tmp, solution, c->rhs.offset);
 
       if (flag)
-       {
-         get_varinfo (c->lhs.var)->solution = tmp;
-         bitmap_set_bit (changed, c->lhs.var);
-       }
+       bitmap_set_bit (changed, c->lhs.var);
     }
 }
 
@@ -1880,48 +1870,54 @@ typedef struct equiv_class_label
 } *equiv_class_label_t;
 typedef const struct equiv_class_label *const_equiv_class_label_t;
 
-/* A hashtable for mapping a bitmap of labels->pointer equivalence
-   classes.  */
-static htab_t pointer_equiv_class_table;
+/* Equiv_class_label hashtable helpers.  */
 
-/* A hashtable for mapping a bitmap of labels->location equivalence
-   classes.  */
-static htab_t location_equiv_class_table;
+struct equiv_class_hasher : typed_free_remove <equiv_class_label>
+{
+  typedef equiv_class_label value_type;
+  typedef equiv_class_label compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
 
 /* Hash function for a equiv_class_label_t */
 
-static hashval_t
-equiv_class_label_hash (const void *p)
+inline hashval_t
+equiv_class_hasher::hash (const value_type *ecl)
 {
-  const_equiv_class_label_t const ecl = (const_equiv_class_label_t) p;
   return ecl->hashcode;
 }
 
 /* Equality function for two equiv_class_label_t's.  */
 
-static int
-equiv_class_label_eq (const void *p1, const void *p2)
+inline bool
+equiv_class_hasher::equal (const value_type *eql1, const compare_type *eql2)
 {
-  const_equiv_class_label_t const eql1 = (const_equiv_class_label_t) p1;
-  const_equiv_class_label_t const eql2 = (const_equiv_class_label_t) p2;
   return (eql1->hashcode == eql2->hashcode
          && bitmap_equal_p (eql1->labels, eql2->labels));
 }
 
+/* A hashtable for mapping a bitmap of labels->pointer equivalence
+   classes.  */
+static hash_table <equiv_class_hasher> pointer_equiv_class_table;
+
+/* A hashtable for mapping a bitmap of labels->location equivalence
+   classes.  */
+static hash_table <equiv_class_hasher> location_equiv_class_table;
+
 /* Lookup a equivalence class in TABLE by the bitmap of LABELS with
    hash HAS it contains.  Sets *REF_LABELS to the bitmap LABELS
    is equivalent to.  */
 
 static equiv_class_label *
-equiv_class_lookup_or_add (htab_t table, bitmap labels)
+equiv_class_lookup_or_add (hash_table <equiv_class_hasher> table, bitmap labels)
 {
   equiv_class_label **slot;
   equiv_class_label ecl;
 
   ecl.labels = labels;
   ecl.hashcode = bitmap_hash (labels);
-  slot = (equiv_class_label **) htab_find_slot_with_hash (table, &ecl,
-                                                         ecl.hashcode, INSERT);
+  slot = table.find_slot_with_hash (&ecl, ecl.hashcode, INSERT);
   if (!*slot)
     {
       *slot = XNEW (struct equiv_class_label);
@@ -1992,7 +1988,7 @@ condense_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
   bitmap_iterator bi;
   unsigned int my_dfs;
 
-  gcc_assert (si->node_mapping[n] == n);
+  gcc_checking_assert (si->node_mapping[n] == n);
   bitmap_set_bit (si->visited, n);
   si->dfs[n] = si->current_index ++;
   my_dfs = si->dfs[n];
@@ -2007,14 +2003,11 @@ condense_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
 
       if (!bitmap_bit_p (si->visited, w))
        condense_visit (graph, si, w);
-      {
-       unsigned int t = si->node_mapping[w];
-       unsigned int nnode = si->node_mapping[n];
-       gcc_assert (nnode == n);
 
-       if (si->dfs[t] < si->dfs[nnode])
-         si->dfs[n] = si->dfs[t];
-      }
+      unsigned int t = si->node_mapping[w];
+      gcc_checking_assert (si->node_mapping[n] == n);
+      if (si->dfs[t] < si->dfs[n])
+       si->dfs[n] = si->dfs[t];
     }
 
   /* Visit all the implicit predecessors.  */
@@ -2027,14 +2020,11 @@ condense_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
 
       if (!bitmap_bit_p (si->visited, w))
        condense_visit (graph, si, w);
-      {
-       unsigned int t = si->node_mapping[w];
-       unsigned int nnode = si->node_mapping[n];
-       gcc_assert (nnode == n);
 
-       if (si->dfs[t] < si->dfs[nnode])
-         si->dfs[n] = si->dfs[t];
-      }
+      unsigned int t = si->node_mapping[w];
+      gcc_assert (si->node_mapping[n] == n);
+      if (si->dfs[t] < si->dfs[n])
+       si->dfs[n] = si->dfs[t];
     }
 
   /* See if any components have been identified.  */
@@ -2077,7 +2067,24 @@ condense_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
     si->scc_stack.safe_push (n);
 }
 
-/* Label pointer equivalences.  */
+/* Label pointer equivalences.
+
+   This performs a value numbering of the constraint graph to
+   discover which variables will always have the same points-to sets
+   under the current set of constraints.
+
+   The way it value numbers is to store the set of points-to bits
+   generated by the constraints and graph edges.  This is just used as a
+   hash and equality comparison.  The *actual set of points-to bits* is
+   completely irrelevant, in that we don't care about being able to
+   extract them later.
+
+   The equality values (currently bitmaps) just have to satisfy a few
+   constraints, the main ones being:
+   1. The combining operation must be order independent.
+   2. The end result of a given set of operations must be unique iff the
+      combination of input values is unique
+   3. Hashable.  */
 
 static void
 label_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
@@ -2114,7 +2121,7 @@ label_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
                }
            }
          else
-           bitmap_ior_into(graph->points_to[n], graph->points_to[w]);
+           bitmap_ior_into (graph->points_to[n], graph->points_to[w]);
        }
     }
 
@@ -2164,6 +2171,77 @@ label_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
     }
 }
 
+/* Print the pred graph in dot format.  */
+
+static void
+dump_pred_graph (struct scc_info *si, FILE *file)
+{
+  unsigned int i;
+
+  /* Only print the graph if it has already been initialized:  */
+  if (!graph)
+    return;
+
+  /* Prints the header of the dot file:  */
+  fprintf (file, "strict digraph {\n");
+  fprintf (file, "  node [\n    shape = box\n  ]\n");
+  fprintf (file, "  edge [\n    fontsize = \"12\"\n  ]\n");
+  fprintf (file, "\n  // List of nodes and complex constraints in "
+          "the constraint graph:\n");
+
+  /* The next lines print the nodes in the graph together with the
+     complex constraints attached to them.  */
+  for (i = 1; i < graph->size; i++)
+    {
+      if (i == FIRST_REF_NODE)
+       continue;
+      if (si->node_mapping[i] != i)
+       continue;
+      if (i < FIRST_REF_NODE)
+       fprintf (file, "\"%s\"", get_varinfo (i)->name);
+      else
+       fprintf (file, "\"*%s\"", get_varinfo (i - FIRST_REF_NODE)->name);
+      if (graph->points_to[i]
+         && !bitmap_empty_p (graph->points_to[i]))
+       {
+         fprintf (file, "[label=\"%s = {", get_varinfo (i)->name);
+         unsigned j;
+         bitmap_iterator bi;
+         EXECUTE_IF_SET_IN_BITMAP (graph->points_to[i], 0, j, bi)
+           fprintf (file, " %d", j);
+         fprintf (file, " }\"]");
+       }
+      fprintf (file, ";\n");
+    }
+
+  /* Go over the edges.  */
+  fprintf (file, "\n  // Edges in the constraint graph:\n");
+  for (i = 1; i < graph->size; i++)
+    {
+      unsigned j;
+      bitmap_iterator bi;
+      if (si->node_mapping[i] != i)
+       continue;
+      EXECUTE_IF_IN_NONNULL_BITMAP (graph->preds[i], 0, j, bi)
+       {
+         unsigned from = si->node_mapping[j];
+         if (from < FIRST_REF_NODE)
+           fprintf (file, "\"%s\"", get_varinfo (from)->name);
+         else
+           fprintf (file, "\"*%s\"", get_varinfo (from - FIRST_REF_NODE)->name);
+         fprintf (file, " -> ");
+         if (i < FIRST_REF_NODE)
+           fprintf (file, "\"%s\"", get_varinfo (i)->name);
+         else
+           fprintf (file, "\"*%s\"", get_varinfo (i - FIRST_REF_NODE)->name);
+         fprintf (file, ";\n");
+       }
+    }
+
+  /* Prints the tail of the dot file.  */
+  fprintf (file, "}\n");
+}
+
 /* Perform offline variable substitution, discovering equivalence
    classes, and eliminating non-pointer variables.  */
 
@@ -2175,27 +2253,33 @@ perform_var_substitution (constraint_graph_t graph)
   struct scc_info *si = init_scc_info (size);
 
   bitmap_obstack_initialize (&iteration_obstack);
-  pointer_equiv_class_table = htab_create (511, equiv_class_label_hash,
-                                          equiv_class_label_eq, free);
-  location_equiv_class_table = htab_create (511, equiv_class_label_hash,
-                                           equiv_class_label_eq, free);
+  pointer_equiv_class_table.create (511);
+  location_equiv_class_table.create (511);
   pointer_equiv_class = 1;
   location_equiv_class = 1;
 
   /* Condense the nodes, which means to find SCC's, count incoming
      predecessors, and unite nodes in SCC's.  */
-  for (i = 0; i < FIRST_REF_NODE; i++)
+  for (i = 1; i < FIRST_REF_NODE; i++)
     if (!bitmap_bit_p (si->visited, si->node_mapping[i]))
       condense_visit (graph, si, si->node_mapping[i]);
 
+  if (dump_file && (dump_flags & TDF_GRAPH))
+    {
+      fprintf (dump_file, "\n\n// The constraint graph before var-substitution "
+              "in dot format:\n");
+      dump_pred_graph (si, dump_file);
+      fprintf (dump_file, "\n\n");
+    }
+
   bitmap_clear (si->visited);
   /* Actually the label the nodes for pointer equivalences  */
-  for (i = 0; i < FIRST_REF_NODE; i++)
+  for (i = 1; i < FIRST_REF_NODE; i++)
     if (!bitmap_bit_p (si->visited, si->node_mapping[i]))
       label_visit (graph, si, si->node_mapping[i]);
 
   /* Calculate location equivalence labels.  */
-  for (i = 0; i < FIRST_REF_NODE; i++)
+  for (i = 1; i < FIRST_REF_NODE; i++)
     {
       bitmap pointed_by;
       bitmap_iterator bi;
@@ -2233,27 +2317,46 @@ perform_var_substitution (constraint_graph_t graph)
     }
 
   if (dump_file && (dump_flags & TDF_DETAILS))
-    for (i = 0; i < FIRST_REF_NODE; i++)
+    for (i = 1; i < FIRST_REF_NODE; i++)
       {
        unsigned j = si->node_mapping[i];
        if (j != i)
-         fprintf (dump_file, "%s node id %d (%s) mapped to SCC leader "
-                  "node id %d (%s)\n",
-                   bitmap_bit_p (graph->direct_nodes, i)
-                   ? "Direct" : "Indirect", i, get_varinfo (i)->name,
-                   j, get_varinfo (j)->name);
+         {
+           fprintf (dump_file, "%s node id %d ",
+                    bitmap_bit_p (graph->direct_nodes, i)
+                    ? "Direct" : "Indirect", i);
+           if (i < FIRST_REF_NODE)
+             fprintf (dump_file, "\"%s\"", get_varinfo (i)->name);
+           else
+             fprintf (dump_file, "\"*%s\"",
+                      get_varinfo (i - FIRST_REF_NODE)->name);
+           fprintf (dump_file, " mapped to SCC leader node id %d ", j);
+           if (j < FIRST_REF_NODE)
+             fprintf (dump_file, "\"%s\"\n", get_varinfo (j)->name);
+           else
+             fprintf (dump_file, "\"*%s\"\n",
+                      get_varinfo (j - FIRST_REF_NODE)->name);
+         }
        else
-         fprintf (dump_file,
-                  "Equivalence classes for %s node id %d (%s): pointer %d"
-                  ", location %d\n",
-                  bitmap_bit_p (graph->direct_nodes, i)
-                  ? "direct" : "indirect", i, get_varinfo (i)->name,
-                  graph->pointer_label[i], graph->loc_label[i]);
+         {
+           fprintf (dump_file,
+                    "Equivalence classes for %s node id %d ",
+                    bitmap_bit_p (graph->direct_nodes, i)
+                    ? "direct" : "indirect", i);
+           if (i < FIRST_REF_NODE)
+             fprintf (dump_file, "\"%s\"", get_varinfo (i)->name);
+           else
+             fprintf (dump_file, "\"*%s\"",
+                      get_varinfo (i - FIRST_REF_NODE)->name);
+           fprintf (dump_file,
+                    ": pointer %d, location %d\n",
+                    graph->pointer_label[i], graph->loc_label[i]);
+         }
       }
 
   /* Quickly eliminate our non-pointer variables.  */
 
-  for (i = 0; i < FIRST_REF_NODE; i++)
+  for (i = 1; i < FIRST_REF_NODE; i++)
     {
       unsigned int node = si->node_mapping[i];
 
@@ -2284,8 +2387,8 @@ free_var_substitution_info (struct scc_info *si)
   free (graph->points_to);
   free (graph->eq_rep);
   sbitmap_free (graph->direct_nodes);
-  htab_delete (pointer_equiv_class_table);
-  htab_delete (location_equiv_class_table);
+  pointer_equiv_class_table.dispose ();
+  location_equiv_class_table.dispose ();
   bitmap_obstack_release (&iteration_obstack);
 }
 
@@ -2303,7 +2406,7 @@ find_equivalent_node (constraint_graph_t graph,
 
   if (!bitmap_bit_p (graph->address_taken, node))
     {
-      gcc_assert (label < graph->size);
+      gcc_checking_assert (label < graph->size);
 
       if (graph->eq_rep[label] != -1)
        {
@@ -2320,7 +2423,7 @@ find_equivalent_node (constraint_graph_t graph,
     }
   else
     {
-      gcc_assert (label < graph->size);
+      gcc_checking_assert (label < graph->size);
       graph->pe[node] = label;
       if (graph->pe_rep[label] == -1)
        graph->pe_rep[label] = node;
@@ -2340,7 +2443,7 @@ unite_pointer_equivalences (constraint_graph_t graph)
 
   /* Go through the pointer equivalences and unite them to their
      representative, if they aren't already.  */
-  for (i = 0; i < FIRST_REF_NODE; i++)
+  for (i = 1; i < FIRST_REF_NODE; i++)
     {
       unsigned int label = graph->pe[i];
       if (label)
@@ -2400,11 +2503,12 @@ rewrite_constraints (constraint_graph_t graph,
                     struct scc_info *si)
 {
   int i;
-  unsigned int j;
   constraint_t c;
 
-  for (j = 0; j < graph->size; j++)
+#ifdef ENABLE_CHECKING
+  for (unsigned int j = 0; j < graph->size; j++)
     gcc_assert (find (j) == j);
+#endif
 
   FOR_EACH_VEC_ELT (constraints, i, c)
     {
@@ -2456,7 +2560,6 @@ rewrite_constraints (constraint_graph_t graph,
       rhsvar = find_equivalent_node (graph, rhsvar, rhslabel);
       c->lhs.var = lhsvar;
       c->rhs.var = rhsvar;
-
     }
 }
 
@@ -2517,7 +2620,7 @@ solve_graph (constraint_graph_t graph)
   changed = BITMAP_ALLOC (NULL);
 
   /* Mark all initial non-collapsed nodes as changed.  */
-  for (i = 0; i < size; i++)
+  for (i = 1; i < size; i++)
     {
       varinfo_t ivi = get_varinfo (i);
       if (find (i) == i && !bitmap_empty_p (ivi->solution)
@@ -2564,8 +2667,19 @@ solve_graph (constraint_graph_t graph)
              varinfo_t vi = get_varinfo (i);
              bool solution_empty;
 
-             /* Compute the changed set of solution bits.  */
-             if (vi->oldsolution)
+             /* Compute the changed set of solution bits.  If anything
+                is in the solution just propagate that.  */
+             if (bitmap_bit_p (vi->solution, anything_id))
+               {
+                 /* If anything is also in the old solution there is
+                    nothing to do.
+                    ???  But we shouldn't ended up with "changed" set ...  */
+                 if (vi->oldsolution
+                     && bitmap_bit_p (vi->oldsolution, anything_id))
+                   continue;
+                 bitmap_copy (pts, get_varinfo (find (anything_id))->solution);
+               }
+             else if (vi->oldsolution)
                bitmap_and_compl (pts, vi->solution, vi->oldsolution);
              else
                bitmap_copy (pts, vi->solution);
@@ -2629,13 +2743,10 @@ solve_graph (constraint_graph_t graph)
                      if (i == eff_escaped_id)
                        flag = bitmap_set_bit (tmp, escaped_id);
                      else
-                       flag = set_union_with_increment (tmp, pts, 0);
+                       flag = bitmap_ior_into (tmp, pts);
 
                      if (flag)
-                       {
-                         get_varinfo (to)->solution = tmp;
-                         bitmap_set_bit (changed, to);
-                       }
+                       bitmap_set_bit (changed, to);
                    }
                }
            }
@@ -2788,10 +2899,10 @@ get_constraint_for_ssa_var (tree t, vec<ce_s> *results, bool address_p)
       && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
     {
       struct varpool_node *node = varpool_get_node (t);
-      if (node && node->alias)
+      if (node && node->alias && node->analyzed)
        {
          node = varpool_variable_node (node, NULL);
-         t = node->symbol.decl;
+         t = node->decl;
        }
     }
 
@@ -2813,7 +2924,7 @@ get_constraint_for_ssa_var (tree t, vec<ce_s> *results, bool address_p)
   if (!address_p
       && !vi->is_full_var)
     {
-      for (; vi; vi = vi->next)
+      for (; vi; vi = vi_next (vi))
        {
          cexpr.var = vi->id;
          results->safe_push (cexpr);
@@ -2887,12 +2998,12 @@ process_constraint (constraint_t t)
 static HOST_WIDE_INT
 bitpos_of_field (const tree fdecl)
 {
-  if (!host_integerp (DECL_FIELD_OFFSET (fdecl), 0)
-      || !host_integerp (DECL_FIELD_BIT_OFFSET (fdecl), 0))
+  if (!tree_fits_shwi_p (DECL_FIELD_OFFSET (fdecl))
+      || !tree_fits_shwi_p (DECL_FIELD_BIT_OFFSET (fdecl)))
     return -1;
 
-  return (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (fdecl)) * BITS_PER_UNIT
-         + TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (fdecl)));
+  return (tree_to_shwi (DECL_FIELD_OFFSET (fdecl)) * BITS_PER_UNIT
+         + tree_to_shwi (DECL_FIELD_BIT_OFFSET (fdecl)));
 }
 
 
@@ -2925,14 +3036,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;
@@ -2960,7 +3070,7 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
               /* If we do not know the offset add all subfields.  */
               && rhsoffset == UNKNOWN_OFFSET)
        {
-         varinfo_t temp = lookup_vi_for_tree (curr->decl);
+         varinfo_t temp = get_varinfo (curr->head);
          do
            {
              struct constraint_expr c2;
@@ -2969,7 +3079,7 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
              c2.offset = 0;
              if (c2.var != c.var)
                results->safe_push (c2);
-             temp = temp->next;
+             temp = vi_next (temp);
            }
          while (temp);
        }
@@ -2997,10 +3107,10 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
             do not result in the same or a conservative superset
             solution.  */
          if (temp->offset != offset
-             && temp->next != NULL)
+             && temp->next != 0)
            {
              struct constraint_expr c2;
-             c2.var = temp->next->id;
+             c2.var = temp->next;
              c2.type = ADDRESSOF;
              c2.offset = 0;
              results->safe_push (c2);
@@ -3103,7 +3213,7 @@ get_constraint_for_component_ref (tree t, vec<ce_s> *results,
          varinfo_t curr;
          results->pop ();
          cexpr.offset = 0;
-         for (curr = get_varinfo (cexpr.var); curr; curr = curr->next)
+         for (curr = get_varinfo (cexpr.var); curr; curr = vi_next (curr))
            {
              if (ranges_overlap_p (curr->offset, curr->size,
                                    bitpos, bitmaxsize))
@@ -3120,8 +3230,8 @@ get_constraint_for_component_ref (tree t, vec<ce_s> *results,
          if (address_p && results->length () == 0)
            {
              curr = get_varinfo (cexpr.var);
-             while (curr->next != NULL)
-               curr = curr->next;
+             while (curr->next != 0)
+               curr = vi_next (curr);
              cexpr.var = curr->id;
              results->safe_push (cexpr);
            }
@@ -3317,16 +3427,16 @@ get_constraint_for_1 (tree t, vec<ce_s> *results, bool address_p,
                return;
 
              vi = get_varinfo (cs.var);
-             curr = vi->next;
+             curr = vi_next (vi);
              if (!vi->is_full_var
                  && curr)
                {
                  unsigned HOST_WIDE_INT size;
-                 if (host_integerp (TYPE_SIZE (TREE_TYPE (t)), 1))
-                   size = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (t)));
+                 if (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (t))))
+                   size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (t)));
                  else
                    size = -1;
-                 for (; curr; curr = curr->next)
+                 for (; curr; curr = vi_next (curr))
                    {
                      if (curr->offset - vi->offset < size)
                        {
@@ -3889,8 +3999,8 @@ 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 delay marking allocated storage global until we know if
-         it escapes.  */
+      /* We 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;
       /* If this is not a real malloc call assume the memory was
@@ -4215,8 +4325,8 @@ 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();
+           lhsc.release ();
+           rhsc.release ();
          }
        return true;
       /* Trampolines are special - they set up passing the static
@@ -4371,7 +4481,7 @@ find_func_aliases_for_builtin_call (gimple t)
        }
       /* printf-style functions may have hooks to set pointers to
         point to somewhere into the generated string.  Leave them
-        for a later excercise...  */
+        for a later exercise...  */
       default:
        /* Fallthru to general call handling.  */;
       }
@@ -4568,7 +4678,11 @@ find_func_aliases (gimple origt)
 
          get_constraint_for (lhsop, &lhsc);
 
-         if (code == POINTER_PLUS_EXPR)
+         if (FLOAT_TYPE_P (TREE_TYPE (lhsop)))
+           /* If the operation produces a floating point result then
+              assume the value is not produced to transfer a pointer.  */
+           ;
+         else if (code == POINTER_PLUS_EXPR)
            get_constraint_for_ptr_offset (gimple_assign_rhs1 (t),
                                           gimple_assign_rhs2 (t), &rhsc);
          else if (code == BIT_AND_EXPR
@@ -4925,7 +5039,7 @@ find_func_clobbers (gimple origt)
            return;
          /* printf-style functions may have hooks to set pointers to
             point to somewhere into the generated string.  Leave them
-            for a later excercise...  */
+            for a later exercise...  */
          default:
            /* Fallthru to general call handling.  */;
          }
@@ -5022,7 +5136,7 @@ first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset)
   /* If we cannot reach offset from start, lookup the first field
      and start from there.  */
   if (start->offset > offset)
-    start = lookup_vi_for_tree (start->decl);
+    start = get_varinfo (start->head);
 
   while (start)
     {
@@ -5034,7 +5148,7 @@ first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset)
          && (offset - start->offset) < start->size)
        return start;
 
-      start= start->next;
+      start = vi_next (start);
     }
 
   return NULL;
@@ -5051,7 +5165,7 @@ first_or_preceding_vi_for_offset (varinfo_t start,
   /* If we cannot reach offset from start, lookup the first field
      and start from there.  */
   if (start->offset > offset)
-    start = lookup_vi_for_tree (start->decl);
+    start = get_varinfo (start->head);
 
   /* We may not find a variable in the field list with the actual
      offset when when we have glommed a structure to a variable.
@@ -5062,7 +5176,7 @@ first_or_preceding_vi_for_offset (varinfo_t start,
   while (start->next
         && offset >= start->offset
         && !((offset - start->offset) < start->size))
-    start = start->next;
+    start = vi_next (start);
 
   return start;
 }
@@ -5237,7 +5351,7 @@ push_fields_onto_fieldstack (tree type, vec<fieldoff_s> *fieldstack,
              }
 
            if (!DECL_SIZE (field)
-               || !host_integerp (DECL_SIZE (field), 1))
+               || !tree_fits_uhwi_p (DECL_SIZE (field)))
              has_unknown_size = true;
 
            /* If adjacent fields do not contain pointers merge them.  */
@@ -5249,7 +5363,7 @@ push_fields_onto_fieldstack (tree type, vec<fieldoff_s> *fieldstack,
                && !pair->has_unknown_size
                && pair->offset + (HOST_WIDE_INT)pair->size == offset + foff)
              {
-               pair->size += TREE_INT_CST_LOW (DECL_SIZE (field));
+               pair->size += tree_to_uhwi (DECL_SIZE (field));
              }
            else
              {
@@ -5257,7 +5371,7 @@ push_fields_onto_fieldstack (tree type, vec<fieldoff_s> *fieldstack,
                e.offset = offset + foff;
                e.has_unknown_size = has_unknown_size;
                if (!has_unknown_size)
-                 e.size = TREE_INT_CST_LOW (DECL_SIZE (field));
+                 e.size = tree_to_uhwi (DECL_SIZE (field));
                else
                  e.size = -1;
                e.must_have_pointers = must_have_pointers_p;
@@ -5345,7 +5459,7 @@ create_function_info_for (tree decl, const char *name)
       clobbervi->is_full_var = true;
       clobbervi->is_global_var = false;
       gcc_assert (prev_vi->offset < clobbervi->offset);
-      prev_vi->next = clobbervi;
+      prev_vi->next = clobbervi->id;
       prev_vi = clobbervi;
 
       asprintf (&tempname, "%s.use", name);
@@ -5359,7 +5473,7 @@ create_function_info_for (tree decl, const char *name)
       usevi->is_full_var = true;
       usevi->is_global_var = false;
       gcc_assert (prev_vi->offset < usevi->offset);
-      prev_vi->next = usevi;
+      prev_vi->next = usevi->id;
       prev_vi = usevi;
     }
 
@@ -5381,7 +5495,7 @@ create_function_info_for (tree decl, const char *name)
       chainvi->is_full_var = true;
       chainvi->is_global_var = false;
       gcc_assert (prev_vi->offset < chainvi->offset);
-      prev_vi->next = chainvi;
+      prev_vi->next = chainvi->id;
       prev_vi = chainvi;
       insert_vi_for_tree (fn->static_chain_decl, chainvi);
     }
@@ -5410,7 +5524,7 @@ create_function_info_for (tree decl, const char *name)
       if (DECL_RESULT (decl))
        resultvi->may_have_pointers = true;
       gcc_assert (prev_vi->offset < resultvi->offset);
-      prev_vi->next = resultvi;
+      prev_vi->next = resultvi->id;
       prev_vi = resultvi;
       if (DECL_RESULT (decl))
        insert_vi_for_tree (DECL_RESULT (decl), resultvi);
@@ -5440,7 +5554,7 @@ create_function_info_for (tree decl, const char *name)
       if (arg)
        argvi->may_have_pointers = true;
       gcc_assert (prev_vi->offset < argvi->offset);
-      prev_vi->next = argvi;
+      prev_vi->next = argvi->id;
       prev_vi = argvi;
       if (arg)
        {
@@ -5471,7 +5585,7 @@ create_function_info_for (tree decl, const char *name)
       argvi->is_heap_var = true;
       argvi->fullsize = vi->fullsize;
       gcc_assert (prev_vi->offset < argvi->offset);
-      prev_vi->next = argvi;
+      prev_vi->next = argvi->id;
       prev_vi = argvi;
     }
 
@@ -5513,7 +5627,7 @@ create_variable_info_for_1 (tree decl, const char *name)
   unsigned int i;
 
   if (!declsize
-      || !host_integerp (declsize, 1))
+      || !tree_fits_uhwi_p (declsize))
     {
       vi = new_var_info (decl, name);
       vi->offset = 0;
@@ -5574,7 +5688,7 @@ create_variable_info_for_1 (tree decl, const char *name)
       vi = new_var_info (decl, name);
       vi->offset = 0;
       vi->may_have_pointers = true;
-      vi->fullsize = TREE_INT_CST_LOW (declsize);
+      vi->fullsize = tree_to_uhwi (declsize);
       vi->size = vi->fullsize;
       vi->is_full_var = true;
       fieldstack.release ();
@@ -5582,10 +5696,10 @@ create_variable_info_for_1 (tree decl, const char *name)
     }
 
   vi = new_var_info (decl, name);
-  vi->fullsize = TREE_INT_CST_LOW (declsize);
+  vi->fullsize = tree_to_uhwi (declsize);
   for (i = 0, newvi = vi;
        fieldstack.iterate (i, &fo);
-       ++i, newvi = newvi->next)
+       ++i, newvi = vi_next (newvi))
     {
       const char *newname = "NULL";
       char *tempname;
@@ -5604,7 +5718,11 @@ create_variable_info_for_1 (tree decl, const char *name)
       newvi->may_have_pointers = fo->may_have_pointers;
       newvi->only_restrict_pointers = fo->only_restrict_pointers;
       if (i + 1 < fieldstack.length ())
-       newvi->next = new_var_info (decl, name);
+       {
+         varinfo_t tem = new_var_info (decl, name);
+         newvi->next = tem->id;
+         tem->head = vi->id;
+       }
     }
 
   fieldstack.release ();
@@ -5624,7 +5742,7 @@ create_variable_info_for (tree decl, const char *name)
     return id;
 
   /* Create initial constraints for globals.  */
-  for (; vi; vi = vi->next)
+  for (; vi; vi = vi_next (vi))
     {
       if (!vi->may_have_pointers
          || !vi->is_global_var)
@@ -5657,7 +5775,7 @@ create_variable_info_for (tree decl, const char *name)
          /* If this is a global variable with an initializer and we are in
             IPA mode generate constraints for it.  */
          if (DECL_INITIAL (decl)
-             && vnode->analyzed)
+             && vnode->definition)
            {
              vec<ce_s> rhsc = vNULL;
              struct constraint_expr lhs, *rhsp;
@@ -5754,7 +5872,7 @@ intra_create_variable_infos (void)
          rhsc.type = ADDRESSOF;
          rhsc.offset = 0;
          process_constraint (new_constraint (lhsc, rhsc));
-         for (; vi; vi = vi->next)
+         for (; vi; vi = vi_next (vi))
            if (vi->may_have_pointers)
              {
                if (vi->only_restrict_pointers)
@@ -5770,7 +5888,7 @@ intra_create_variable_infos (void)
        make_constraint_from_global_restrict (p, "PARM_RESTRICT");
       else
        {
-         for (; p; p = p->next)
+         for (; p; p = vi_next (p))
            {
              if (p->only_restrict_pointers)
                make_constraint_from_global_restrict (p, "PARM_RESTRICT");
@@ -5786,7 +5904,7 @@ intra_create_variable_infos (void)
     {
       varinfo_t p, result_vi = get_vi_for_tree (DECL_RESULT (cfun->decl));
 
-      for (p = result_vi; p; p = p->next)
+      for (p = result_vi; p; p = vi_next (p))
        make_constraint_from (p, nonlocal_id);
     }
 
@@ -5795,7 +5913,7 @@ intra_create_variable_infos (void)
     {
       varinfo_t p, chain_vi = get_vi_for_tree (cfun->static_chain_decl);
 
-      for (p = chain_vi; p; p = p->next)
+      for (p = chain_vi; p; p = vi_next (p))
        make_constraint_from (p, nonlocal_id);
     }
 }
@@ -5810,45 +5928,54 @@ typedef struct shared_bitmap_info
 } *shared_bitmap_info_t;
 typedef const struct shared_bitmap_info *const_shared_bitmap_info_t;
 
-static htab_t shared_bitmap_table;
+/* Shared_bitmap hashtable helpers.  */
+
+struct shared_bitmap_hasher : typed_free_remove <shared_bitmap_info>
+{
+  typedef shared_bitmap_info value_type;
+  typedef shared_bitmap_info compare_type;
+  static inline hashval_t hash (const value_type *);
+  static inline bool equal (const value_type *, const compare_type *);
+};
 
 /* Hash function for a shared_bitmap_info_t */
 
-static hashval_t
-shared_bitmap_hash (const void *p)
+inline hashval_t
+shared_bitmap_hasher::hash (const value_type *bi)
 {
-  const_shared_bitmap_info_t const bi = (const_shared_bitmap_info_t) p;
   return bi->hashcode;
 }
 
 /* Equality function for two shared_bitmap_info_t's. */
 
-static int
-shared_bitmap_eq (const void *p1, const void *p2)
+inline bool
+shared_bitmap_hasher::equal (const value_type *sbi1, const compare_type *sbi2)
 {
-  const_shared_bitmap_info_t const sbi1 = (const_shared_bitmap_info_t) p1;
-  const_shared_bitmap_info_t const sbi2 = (const_shared_bitmap_info_t) p2;
   return bitmap_equal_p (sbi1->pt_vars, sbi2->pt_vars);
 }
 
+/* Shared_bitmap hashtable.  */
+
+static hash_table <shared_bitmap_hasher> shared_bitmap_table;
+
 /* Lookup a bitmap in the shared bitmap hashtable, and return an already
    existing instance if there is one, NULL otherwise.  */
 
 static bitmap
 shared_bitmap_lookup (bitmap pt_vars)
 {
-  void **slot;
+  shared_bitmap_info **slot;
   struct shared_bitmap_info sbi;
 
   sbi.pt_vars = pt_vars;
   sbi.hashcode = bitmap_hash (pt_vars);
 
-  slot = htab_find_slot_with_hash (shared_bitmap_table, &sbi,
-                                  sbi.hashcode, NO_INSERT);
+  slot = shared_bitmap_table.find_slot_with_hash (&sbi, sbi.hashcode,
+                                                 NO_INSERT);
   if (!slot)
     return NULL;
   else
-    return ((shared_bitmap_info_t) *slot)->pt_vars;
+    return (*slot)->pt_vars;
 }
 
 
@@ -5857,16 +5984,15 @@ shared_bitmap_lookup (bitmap pt_vars)
 static void
 shared_bitmap_add (bitmap pt_vars)
 {
-  void **slot;
+  shared_bitmap_info **slot;
   shared_bitmap_info_t sbi = XNEW (struct shared_bitmap_info);
 
   sbi->pt_vars = pt_vars;
   sbi->hashcode = bitmap_hash (pt_vars);
 
-  slot = htab_find_slot_with_hash (shared_bitmap_table, sbi,
-                                  sbi->hashcode, INSERT);
+  slot = shared_bitmap_table.find_slot_with_hash (sbi, sbi->hashcode, INSERT);
   gcc_assert (!*slot);
-  *slot = (void *) sbi;
+  *slot = sbi;
 }
 
 
@@ -5877,6 +6003,9 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
 {
   unsigned int i;
   bitmap_iterator bi;
+  varinfo_t escaped_vi = get_varinfo (find (escaped_id));
+  bool everything_escaped
+    = escaped_vi->solution && bitmap_bit_p (escaped_vi->solution, anything_id);
 
   EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
     {
@@ -5887,6 +6016,14 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
       if (vi->is_artificial_var && !vi->is_heap_var)
        continue;
 
+      if (everything_escaped
+         || (escaped_vi->solution
+             && bitmap_bit_p (escaped_vi->solution, i)))
+       {
+         pt->vars_contains_escaped = true;
+         pt->vars_contains_escaped_heap = vi->is_heap_var;
+       }
+
       if (TREE_CODE (vi->decl) == VAR_DECL
          || TREE_CODE (vi->decl) == PARM_DECL
          || TREE_CODE (vi->decl) == RESULT_DECL)
@@ -5901,7 +6038,7 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
             set contains global variables.  */
          bitmap_set_bit (into, DECL_PT_UID (vi->decl));
          if (vi->is_global_var)
-           pt->vars_contains_global = true;
+           pt->vars_contains_nonlocal = true;
        }
     }
 }
@@ -6058,11 +6195,15 @@ pt_solution_reset (struct pt_solution *pt)
    it contains restrict tag variables.  */
 
 void
-pt_solution_set (struct pt_solution *pt, bitmap vars, bool vars_contains_global)
+pt_solution_set (struct pt_solution *pt, bitmap vars,
+                bool vars_contains_nonlocal)
 {
   memset (pt, 0, sizeof (struct pt_solution));
   pt->vars = vars;
-  pt->vars_contains_global = vars_contains_global;
+  pt->vars_contains_nonlocal = vars_contains_nonlocal;
+  pt->vars_contains_escaped
+    = (cfun->gimple_df->escaped.anything
+       || bitmap_intersect_p (cfun->gimple_df->escaped.vars, vars));
 }
 
 /* Set the points-to solution *PT to point only to the variable VAR.  */
@@ -6073,7 +6214,10 @@ pt_solution_set_var (struct pt_solution *pt, tree var)
   memset (pt, 0, sizeof (struct pt_solution));
   pt->vars = BITMAP_GGC_ALLOC ();
   bitmap_set_bit (pt->vars, DECL_PT_UID (var));
-  pt->vars_contains_global = is_global_var (var);
+  pt->vars_contains_nonlocal = is_global_var (var);
+  pt->vars_contains_escaped
+    = (cfun->gimple_df->escaped.anything
+       || bitmap_bit_p (cfun->gimple_df->escaped.vars, DECL_PT_UID (var)));
 }
 
 /* Computes the union of the points-to solutions *DEST and *SRC and
@@ -6096,7 +6240,9 @@ pt_solution_ior_into (struct pt_solution *dest, struct pt_solution *src)
   dest->escaped |= src->escaped;
   dest->ipa_escaped |= src->ipa_escaped;
   dest->null |= src->null;
-  dest->vars_contains_global |= src->vars_contains_global;
+  dest->vars_contains_nonlocal |= src->vars_contains_nonlocal;
+  dest->vars_contains_escaped |= src->vars_contains_escaped;
+  dest->vars_contains_escaped_heap |= src->vars_contains_escaped_heap;
   if (!src->vars)
     return;
 
@@ -6153,9 +6299,14 @@ pt_solution_includes_global (struct pt_solution *pt)
 {
   if (pt->anything
       || pt->nonlocal
-      || pt->vars_contains_global)
+      || pt->vars_contains_nonlocal
+      /* The following is a hack to make the malloc escape hack work.
+         In reality we'd need different sets for escaped-through-return
+        and escaped-to-callees and passes would need to be updated.  */
+      || pt->vars_contains_escaped_heap)
     return true;
 
+  /* 'escaped' is also a placeholder so we have to look into it.  */
   if (pt->escaped)
     return pt_solution_includes_global (&cfun->gimple_df->escaped);
 
@@ -6225,28 +6376,19 @@ pt_solutions_intersect_1 (struct pt_solution *pt1, struct pt_solution *pt2)
      any global memory they alias.  */
   if ((pt1->nonlocal
        && (pt2->nonlocal
-          || pt2->vars_contains_global))
+          || pt2->vars_contains_nonlocal))
       || (pt2->nonlocal
-         && pt1->vars_contains_global))
+         && pt1->vars_contains_nonlocal))
     return true;
 
-  /* Check the escaped solution if required.  */
-  if ((pt1->escaped || pt2->escaped)
-      && !pt_solution_empty_p (&cfun->gimple_df->escaped))
-    {
-      /* If both point to escaped memory and that solution
-        is not empty they alias.  */
-      if (pt1->escaped && pt2->escaped)
-       return true;
-
-      /* If either points to escaped memory see if the escaped solution
-        intersects with the other.  */
-      if ((pt1->escaped
-          && pt_solutions_intersect_1 (&cfun->gimple_df->escaped, pt2))
-         || (pt2->escaped
-             && pt_solutions_intersect_1 (&cfun->gimple_df->escaped, pt1)))
-       return true;
-    }
+  /* If either points to all escaped memory and the other points to
+     any escaped memory they alias.  */
+  if ((pt1->escaped
+       && (pt2->escaped
+          || pt2->vars_contains_escaped))
+      || (pt2->escaped
+         && pt1->vars_contains_escaped))
+    return true;
 
   /* Check the escaped solution if required.
      ???  Do we need to check the local against the IPA escaped sets?  */
@@ -6310,7 +6452,7 @@ dump_sa_points_to_info (FILE *outfile)
               stats.num_implicit_edges);
     }
 
-  for (i = 0; i < varmap.length (); i++)
+  for (i = 1; i < varmap.length (); i++)
     {
       varinfo_t vi = get_varinfo (i);
       if (!vi->may_have_pointers)
@@ -6344,6 +6486,9 @@ init_base_vars (void)
   varinfo_t var_storedanything;
   varinfo_t var_integer;
 
+  /* Variable ID zero is reserved and should be NULL.  */
+  varmap.safe_push (NULL);
+
   /* Create the NULL variable, used to represent that a variable points
      to NULL.  */
   var_nothing = new_var_info (NULL_TREE, "NULL");
@@ -6363,7 +6508,6 @@ init_base_vars (void)
   var_anything->is_artificial_var = 1;
   var_anything->size = ~0;
   var_anything->offset = 0;
-  var_anything->next = NULL;
   var_anything->fullsize = ~0;
   var_anything->is_special_var = 1;
 
@@ -6390,7 +6534,6 @@ init_base_vars (void)
   var_readonly->offset = 0;
   var_readonly->size = ~0;
   var_readonly->fullsize = ~0;
-  var_readonly->next = NULL;
   var_readonly->is_special_var = 1;
 
   /* readonly memory points to anything, in order to make deref
@@ -6487,7 +6630,6 @@ init_base_vars (void)
   var_integer->size = ~0;
   var_integer->fullsize = ~0;
   var_integer->offset = 0;
-  var_integer->next = NULL;
   var_integer->is_special_var = 1;
 
   /* INTEGER = ANYTHING, because we don't know where a dereference of
@@ -6522,8 +6664,7 @@ init_alias_vars (void)
   call_stmt_vars = pointer_map_create ();
 
   memset (&stats, 0, sizeof (stats));
-  shared_bitmap_table = htab_create (511, shared_bitmap_hash,
-                                    shared_bitmap_eq, free);
+  shared_bitmap_table.create (511);
   init_base_vars ();
 
   gcc_obstack_init (&fake_var_decl_obstack);
@@ -6542,7 +6683,7 @@ remove_preds_and_fake_succs (constraint_graph_t graph)
 
   /* Clear the implicit ref and address nodes from the successor
      lists.  */
-  for (i = 0; i < FIRST_REF_NODE; i++)
+  for (i = 1; i < FIRST_REF_NODE; i++)
     {
       if (graph->succs[i])
        bitmap_clear_range (graph->succs[i], FIRST_REF_NODE,
@@ -6550,7 +6691,7 @@ remove_preds_and_fake_succs (constraint_graph_t graph)
     }
 
   /* Free the successor list for the non-ref nodes.  */
-  for (i = FIRST_REF_NODE; i < graph->size; i++)
+  for (i = FIRST_REF_NODE + 1; i < graph->size; i++)
     {
       if (graph->succs[i])
        BITMAP_FREE (graph->succs[i]);
@@ -6695,13 +6836,6 @@ compute_points_to_sets (void)
      points-to solution queries.  */
   cfun->gimple_df->escaped.escaped = 0;
 
-  /* Mark escaped HEAP variables as global.  */
-  FOR_EACH_VEC_ELT (varmap, i, vi)
-    if (vi->is_heap_var
-       && !vi->is_global_var)
-      DECL_EXTERNAL (vi->decl) = vi->is_global_var
-       = pt_solution_includes (&cfun->gimple_df->escaped, vi->decl);
-
   /* Compute the points-to sets for pointer SSA_NAMEs.  */
   for (i = 0; i < num_ssa_names; ++i)
     {
@@ -6778,7 +6912,7 @@ delete_points_to_sets (void)
 {
   unsigned int i;
 
-  htab_delete (shared_bitmap_table);
+  shared_bitmap_table.dispose ();
   if (dump_file && (dump_flags & TDF_STATS))
     fprintf (dump_file, "Points to sets created:%d\n",
             stats.points_to_sets_created);
@@ -6858,49 +6992,83 @@ gate_tree_pta (void)
 /* A dummy pass to cause points-to information to be computed via
    TODO_rebuild_alias.  */
 
-struct gimple_opt_pass pass_build_alias =
-{
- {
-  GIMPLE_PASS,
-  "alias",                 /* name */
-  OPTGROUP_NONE,            /* optinfo_flags */
-  gate_tree_pta,           /* gate */
-  NULL,                     /* execute */
-  NULL,                     /* sub */
-  NULL,                     /* next */
-  0,                        /* static_pass_number */
-  TV_NONE,                  /* tv_id */
-  PROP_cfg | PROP_ssa,      /* properties_required */
-  0,                       /* properties_provided */
-  0,                        /* properties_destroyed */
-  0,                        /* todo_flags_start */
-  TODO_rebuild_alias        /* todo_flags_finish */
- }
+namespace {
+
+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 */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_rebuild_alias, /* todo_flags_finish */
 };
 
+class pass_build_alias : public gimple_opt_pass
+{
+public:
+  pass_build_alias (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_build_alias, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_tree_pta (); }
+
+}; // class pass_build_alias
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_build_alias (gcc::context *ctxt)
+{
+  return new pass_build_alias (ctxt);
+}
+
 /* A dummy pass to cause points-to information to be computed via
    TODO_rebuild_alias.  */
 
-struct gimple_opt_pass pass_build_ealias =
-{
- {
-  GIMPLE_PASS,
-  "ealias",                /* name */
-  OPTGROUP_NONE,            /* optinfo_flags */
-  gate_tree_pta,           /* gate */
-  NULL,                     /* execute */
-  NULL,                     /* sub */
-  NULL,                     /* next */
-  0,                        /* static_pass_number */
-  TV_NONE,                  /* tv_id */
-  PROP_cfg | PROP_ssa,      /* properties_required */
-  0,                       /* properties_provided */
-  0,                        /* properties_destroyed */
-  0,                        /* todo_flags_start */
-  TODO_rebuild_alias        /* todo_flags_finish */
- }
+namespace {
+
+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 */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_rebuild_alias, /* todo_flags_finish */
 };
 
+class pass_build_ealias : public gimple_opt_pass
+{
+public:
+  pass_build_ealias (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_build_ealias, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_tree_pta (); }
+
+}; // class pass_build_ealias
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_build_ealias (gcc::context *ctxt)
+{
+  return new pass_build_ealias (ctxt);
+}
+
 
 /* Return true if we should execute IPA PTA.  */
 static bool
@@ -6914,15 +7082,16 @@ gate_ipa_pta (void)
 
 /* IPA PTA solutions for ESCAPED.  */
 struct pt_solution ipa_escaped_pt
-  = { true, false, false, false, false, false, NULL };
+  = { true, false, false, false, false, false, false, false, NULL };
 
 /* Associate node with varinfo DATA. Worker for
    cgraph_for_node_and_aliases.  */
 static bool
 associate_varinfo_to_alias (struct cgraph_node *node, void *data)
 {
-  if (node->alias || node->thunk.thunk_p)
-    insert_vi_for_tree (node->symbol.decl, (varinfo_t)data);
+  if ((node->alias || node->thunk.thunk_p)
+      && node->analyzed)
+    insert_vi_for_tree (node->decl, (varinfo_t)data);
   return false;
 }
 
@@ -6951,23 +7120,24 @@ 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))
+      if (!cgraph_function_with_gimple_body_p (node) || node->clone_of)
        continue;
+      cgraph_get_body (node);
 
       gcc_assert (!node->clone_of);
 
-      vi = create_function_info_for (node->symbol.decl,
-                                    alias_get_name (node->symbol.decl));
+      vi = create_function_info_for (node->decl,
+                                    alias_get_name (node->decl));
       cgraph_for_node_and_aliases (node, associate_varinfo_to_alias, vi, true);
     }
 
   /* Create constraints for global variables and their initializers.  */
   FOR_EACH_VARIABLE (var)
     {
-      if (var->alias)
+      if (var->alias && var->analyzed)
        continue;
 
-      get_vi_for_tree (var->symbol.decl);
+      get_vi_for_tree (var->decl);
     }
 
   if (dump_file)
@@ -6985,39 +7155,39 @@ ipa_pta_execute (void)
       basic_block bb;
 
       /* Nodes without a body are not interesting.  */
-      if (!cgraph_function_with_gimple_body_p (node))
+      if (!cgraph_function_with_gimple_body_p (node) || node->clone_of)
        continue;
 
       if (dump_file)
        {
          fprintf (dump_file,
-                  "Generating constraints for %s", cgraph_node_name (node));
-         if (DECL_ASSEMBLER_NAME_SET_P (node->symbol.decl))
+                  "Generating constraints for %s", node->name ());
+         if (DECL_ASSEMBLER_NAME_SET_P (node->decl))
            fprintf (dump_file, " (%s)",
                     IDENTIFIER_POINTER
-                      (DECL_ASSEMBLER_NAME (node->symbol.decl)));
+                      (DECL_ASSEMBLER_NAME (node->decl)));
          fprintf (dump_file, "\n");
        }
 
-      func = DECL_STRUCT_FUNCTION (node->symbol.decl);
+      func = DECL_STRUCT_FUNCTION (node->decl);
       push_cfun (func);
 
       /* For externally visible or attribute used annotated functions use
         local constraints for their arguments.
         For local functions we see all callers and thus do not need initial
         constraints for parameters.  */
-      if (node->symbol.used_from_other_partition
-         || node->symbol.externally_visible
-         || node->symbol.force_output)
+      if (node->used_from_other_partition
+         || node->externally_visible
+         || node->force_output)
        {
          intra_create_variable_infos ();
 
          /* We also need to make function return values escape.  Nothing
             escapes by returning from main though.  */
-         if (!MAIN_NAME_P (DECL_NAME (node->symbol.decl)))
+         if (!MAIN_NAME_P (DECL_NAME (node->decl)))
            {
              varinfo_t fi, rvi;
-             fi = lookup_vi_for_tree (node->symbol.decl);
+             fi = lookup_vi_for_tree (node->decl);
              rvi = first_vi_for_offset (fi, fi_result);
              if (rvi && rvi->offset == fi_result)
                {
@@ -7094,10 +7264,10 @@ ipa_pta_execute (void)
       struct cgraph_edge *e;
 
       /* Nodes without a body are not interesting.  */
-      if (!cgraph_function_with_gimple_body_p (node))
+      if (!cgraph_function_with_gimple_body_p (node) || node->clone_of)
        continue;
 
-      fn = DECL_STRUCT_FUNCTION (node->symbol.decl);
+      fn = DECL_STRUCT_FUNCTION (node->decl);
 
       /* Compute the points-to sets for pointer SSA_NAMEs.  */
       FOR_EACH_VEC_ELT (*fn->gimple_df->ssa_names, i, ptr)
@@ -7108,7 +7278,7 @@ ipa_pta_execute (void)
        }
 
       /* Compute the call-use and call-clobber sets for all direct calls.  */
-      fi = lookup_vi_for_tree (node->symbol.decl);
+      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));
@@ -7256,22 +7426,40 @@ ipa_pta_execute (void)
   return 0;
 }
 
-struct simple_ipa_opt_pass pass_ipa_pta =
-{
- {
-  SIMPLE_IPA_PASS,
-  "pta",                               /* name */
-  OPTGROUP_NONE,                        /* optinfo_flags */
-  gate_ipa_pta,                        /* gate */
-  ipa_pta_execute,                     /* execute */
-  NULL,                                        /* sub */
-  NULL,                                        /* next */
-  0,                                   /* static_pass_number */
-  TV_IPA_PTA,                  /* tv_id */
-  0,                                   /* properties_required */
-  0,                                   /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
-  TODO_update_ssa                       /* todo_flags_finish */
- }
+namespace {
+
+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 */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
 };
+
+class pass_ipa_pta : public simple_ipa_opt_pass
+{
+public:
+  pass_ipa_pta (gcc::context *ctxt)
+    : simple_ipa_opt_pass (pass_data_ipa_pta, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_ipa_pta (); }
+  unsigned int execute () { return ipa_pta_execute (); }
+
+}; // class pass_ipa_pta
+
+} // anon namespace
+
+simple_ipa_opt_pass *
+make_pass_ipa_pta (gcc::context *ctxt)
+{
+  return new pass_ipa_pta (ctxt);
+}