OSDN Git Service

2010-07-13 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-structalias.c
index 28bb0bb..68e0cac 100644 (file)
 #include "obstack.h"
 #include "bitmap.h"
 #include "flags.h"
-#include "rtl.h"
-#include "tm_p.h"
-#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "output.h"
 #include "tree.h"
 #include "tree-flow.h"
 #include "tree-inline.h"
-#include "diagnostic.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "gimple.h"
 #include "hashtab.h"
    keep the set of called functions for indirect calls.
 
    And probably more.  */
-
-static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
+static GTY ((if_marked ("tree_map_marked_p"), param_is (struct heapvar_map)))
 htab_t heapvar_for_stmt;
 
 static bool use_field_sensitive = true;
@@ -383,7 +379,7 @@ heapvar_insert (tree from, unsigned HOST_WIDE_INT offset, tree to)
   struct heapvar_map *h;
   void **loc;
 
-  h = GGC_NEW (struct heapvar_map);
+  h = ggc_alloc_heapvar_map ();
   h->map.base.from = from;
   h->offset = offset;
   h->map.hash = heapvar_map_hash (h);
@@ -719,7 +715,7 @@ void debug_sa_points_to_info (void);
 
 /* Print out constraint C to stderr.  */
 
-void
+DEBUG_FUNCTION void
 debug_constraint (constraint_t c)
 {
   dump_constraint (stderr, c);
@@ -738,7 +734,7 @@ dump_constraints (FILE *file, int from)
 
 /* Print out all constraints to stderr.  */
 
-void
+DEBUG_FUNCTION void
 debug_constraints (void)
 {
   dump_constraints (stderr, 0);
@@ -828,7 +824,7 @@ dump_constraint_graph (FILE *file)
 
 /* Print out the constraint graph to stderr.  */
 
-void
+DEBUG_FUNCTION void
 debug_constraint_graph (void)
 {
   dump_constraint_graph (stderr);
@@ -2759,10 +2755,14 @@ lookup_vi_for_tree (tree t)
 static const char *
 alias_get_name (tree decl)
 {
-  const char *res = get_name (decl);
+  const char *res;
   char *temp;
   int num_printed = 0;
 
+  if (DECL_ASSEMBLER_NAME_SET_P (decl))
+    res = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  else
+    res= get_name (decl);
   if (res != NULL)
     return res;
 
@@ -2837,7 +2837,8 @@ get_constraint_for_ssa_var (tree t, VEC(ce_s, heap) **results, bool address_p)
   /* For parameters, get at the points-to set for the actual parm
      decl.  */
   if (TREE_CODE (t) == SSA_NAME
-      && TREE_CODE (SSA_NAME_VAR (t)) == PARM_DECL
+      && (TREE_CODE (SSA_NAME_VAR (t)) == PARM_DECL
+         || TREE_CODE (SSA_NAME_VAR (t)) == RESULT_DECL)
       && SSA_NAME_IS_DEFAULT_DEF (t))
     {
       get_constraint_for_ssa_var (SSA_NAME_VAR (t), results, address_p);
@@ -2940,6 +2941,12 @@ type_could_have_pointers (tree type)
   if (TREE_CODE (type) == ARRAY_TYPE)
     return type_could_have_pointers (TREE_TYPE (type));
 
+  /* A function or method can consume pointers.
+     ???  We could be more precise here.  */
+  if (TREE_CODE (type) == FUNCTION_TYPE
+      || TREE_CODE (type) == METHOD_TYPE)
+    return true;
+
   return AGGREGATE_TYPE_P (type);
 }
 
@@ -2949,7 +2956,11 @@ type_could_have_pointers (tree type)
 static bool
 could_have_pointers (tree t)
 {
-  return type_could_have_pointers (TREE_TYPE (t));
+  return (((TREE_CODE (t) == VAR_DECL
+           || TREE_CODE (t) == PARM_DECL
+           || TREE_CODE (t) == RESULT_DECL)
+          && (TREE_PUBLIC (t) || DECL_EXTERNAL (t) || TREE_ADDRESSABLE (t)))
+         || type_could_have_pointers (TREE_TYPE (t)));
 }
 
 /* Return the position, in bits, of FIELD_DECL from the beginning of its
@@ -3098,7 +3109,8 @@ get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results,
      &0->a.b */
   forzero = t;
   while (handled_component_p (forzero)
-        || INDIRECT_REF_P (forzero))
+        || INDIRECT_REF_P (forzero)
+        || TREE_CODE (forzero) == MEM_REF)
     forzero = TREE_OPERAND (forzero, 0);
 
   if (CONSTANT_CLASS_P (forzero) && integer_zerop (forzero))
@@ -3280,16 +3292,18 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p)
      in that case *NULL does not fail, so it _should_ alias *anything.
      It is not worth adding a new option or renaming the existing one,
      since this case is relatively obscure.  */
-  if (flag_delete_null_pointer_checks
-      && ((TREE_CODE (t) == INTEGER_CST
-          && integer_zerop (t))
-         /* The only valid CONSTRUCTORs in gimple with pointer typed
-            elements are zero-initializer.  But in IPA mode we also
-            process global initializers, so verify at least.  */
-         || (TREE_CODE (t) == CONSTRUCTOR
-             && CONSTRUCTOR_NELTS (t) == 0)))
-    {
-      temp.var = nothing_id;
+  if ((TREE_CODE (t) == INTEGER_CST
+       && integer_zerop (t))
+      /* The only valid CONSTRUCTORs in gimple with pointer typed
+        elements are zero-initializer.  But in IPA mode we also
+        process global initializers, so verify at least.  */
+      || (TREE_CODE (t) == CONSTRUCTOR
+         && CONSTRUCTOR_NELTS (t) == 0))
+    {
+      if (flag_delete_null_pointer_checks)
+       temp.var = nothing_id;
+      else
+       temp.var = anything_id;
       temp.type = ADDRESSOF;
       temp.offset = 0;
       VEC_safe_push (ce_s, heap, *results, &temp);
@@ -3323,9 +3337,10 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p)
       {
        switch (TREE_CODE (t))
          {
-         case INDIRECT_REF:
+         case MEM_REF:
            {
-             get_constraint_for_1 (TREE_OPERAND (t, 0), results, address_p);
+             get_constraint_for_ptr_offset (TREE_OPERAND (t, 0),
+                                            TREE_OPERAND (t, 1), results);
              do_deref (results);
              return;
            }
@@ -3583,11 +3598,11 @@ make_transitive_closure_constraints (varinfo_t vi)
   process_constraint (new_constraint (lhs, rhs));
 }
 
-/* Create a new artificial heap variable with NAME and make a
-   constraint from it to LHS.  Return the created variable.  */
+/* Create a new artificial heap variable with NAME.
+   Return the created variable.  */
 
 static varinfo_t
-make_constraint_from_heapvar (varinfo_t lhs, const char *name)
+make_heapvar_for (varinfo_t lhs, const char *name)
 {
   varinfo_t vi;
   tree heapvar = heapvar_lookup (lhs->decl, lhs->offset);
@@ -3619,6 +3634,16 @@ make_constraint_from_heapvar (varinfo_t lhs, const char *name)
   vi->is_full_var = true;
   insert_vi_for_tree (heapvar, vi);
 
+  return vi;
+}
+
+/* Create a new artificial heap variable with NAME and make a
+   constraint from it to LHS.  Return the created variable.  */
+
+static varinfo_t
+make_constraint_from_heapvar (varinfo_t lhs, const char *name)
+{
+  varinfo_t vi = make_heapvar_for (lhs, name);
   make_constraint_from (lhs, vi->id);
 
   return vi;
@@ -3693,17 +3718,61 @@ handle_rhs_call (gimple stmt, VEC(ce_s, heap) **results)
 {
   struct constraint_expr rhsc;
   unsigned i;
+  bool returns_uses = false;
 
   for (i = 0; i < gimple_call_num_args (stmt); ++i)
     {
       tree arg = gimple_call_arg (stmt, i);
+      int flags = gimple_call_arg_flags (stmt, i);
 
-      /* Find those pointers being passed, and make sure they end up
-        pointing to anything.  */
-      if (could_have_pointers (arg))
+      /* If the argument is not used or it does not contain pointers
+        we can ignore it.  */
+      if ((flags & EAF_UNUSED)
+         || !could_have_pointers (arg))
+       continue;
+
+      /* As we compute ESCAPED context-insensitive we do not gain
+         any precision with just EAF_NOCLOBBER but not EAF_NOESCAPE
+        set.  The argument would still get clobbered through the
+        escape solution.
+        ???  We might get away with less (and more precise) constraints
+        if using a temporary for transitively closing things.  */
+      if ((flags & EAF_NOCLOBBER)
+          && (flags & EAF_NOESCAPE))
+       {
+         varinfo_t uses = get_call_use_vi (stmt);
+         if (!(flags & EAF_DIRECT))
+           make_transitive_closure_constraints (uses);
+         make_constraint_to (uses->id, arg);
+         returns_uses = true;
+       }
+      else if (flags & EAF_NOESCAPE)
+       {
+         varinfo_t uses = get_call_use_vi (stmt);
+         varinfo_t clobbers = get_call_clobber_vi (stmt);
+         if (!(flags & EAF_DIRECT))
+           {
+             make_transitive_closure_constraints (uses);
+             make_transitive_closure_constraints (clobbers);
+           }
+         make_constraint_to (uses->id, arg);
+         make_constraint_to (clobbers->id, arg);
+         returns_uses = true;
+       }
+      else
        make_escape_constraint (arg);
     }
 
+  /* If we added to the calls uses solution make sure we account for
+     pointers to it to be returned.  */
+  if (returns_uses)
+    {
+      rhsc.var = get_call_use_vi (stmt)->id;
+      rhsc.offset = 0;
+      rhsc.type = SCALAR;
+      VEC_safe_push (ce_s, heap, *results, &rhsc);
+    }
+
   /* The static chain escapes as well.  */
   if (gimple_call_chain (stmt))
     make_escape_constraint (gimple_call_chain (stmt));
@@ -3736,44 +3805,63 @@ handle_rhs_call (gimple stmt, VEC(ce_s, heap) **results)
    the LHS point to global and escaped variables.  */
 
 static void
-handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc, tree fndecl)
+handle_lhs_call (gimple stmt, tree lhs, int flags, VEC(ce_s, heap) *rhsc,
+                tree fndecl)
 {
   VEC(ce_s, heap) *lhsc = NULL;
 
   get_constraint_for (lhs, &lhsc);
-
-  if (flags & ECF_MALLOC)
+  /* If the store is to a global decl make sure to
+     add proper escape constraints.  */
+  lhs = get_base_address (lhs);
+  if (lhs
+      && DECL_P (lhs)
+      && is_global_var (lhs))
+    {
+      struct constraint_expr tmpc;
+      tmpc.var = escaped_id;
+      tmpc.offset = 0;
+      tmpc.type = SCALAR;
+      VEC_safe_push (ce_s, heap, lhsc, &tmpc);
+    }
+
+  /* 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))
+    {
+      tree arg;
+      rhsc = NULL;
+      arg = gimple_call_arg (stmt, flags & ERF_RETURN_ARG_MASK);
+      get_constraint_for (arg, &rhsc);
+      process_all_all_constraints (lhsc, rhsc);
+      VEC_free (ce_s, heap, rhsc);
+    }
+  else if (flags & ERF_NOALIAS)
     {
       varinfo_t vi;
-      vi = make_constraint_from_heapvar (get_vi_for_tree (lhs), "HEAP");
+      struct constraint_expr tmpc;
+      rhsc = NULL;
+      vi = make_heapvar_for (get_vi_for_tree (lhs), "HEAP");
       /* We delay marking allocated storage global until we know if
          it escapes.  */
       DECL_EXTERNAL (vi->decl) = 0;
       vi->is_global_var = 0;
       /* If this is not a real malloc call assume the memory was
-         initialized and thus may point to global memory.  All
+        initialized and thus may point to global memory.  All
         builtin functions with the malloc attribute behave in a sane way.  */
       if (!fndecl
          || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
        make_constraint_from (vi, nonlocal_id);
+      tmpc.var = vi->id;
+      tmpc.offset = 0;
+      tmpc.type = ADDRESSOF;
+      VEC_safe_push (ce_s, heap, rhsc, &tmpc);
     }
-  else if (VEC_length (ce_s, rhsc) > 0)
-    {
-      /* If the store is to a global decl make sure to
-        add proper escape constraints.  */
-      lhs = get_base_address (lhs);
-      if (lhs
-         && DECL_P (lhs)
-         && is_global_var (lhs))
-       {
-         struct constraint_expr tmpc;
-         tmpc.var = escaped_id;
-         tmpc.offset = 0;
-         tmpc.type = SCALAR;
-         VEC_safe_push (ce_s, heap, lhsc, &tmpc);
-       }
-      process_all_all_constraints (lhsc, rhsc);
-    }
+
+  process_all_all_constraints (lhsc, rhsc);
+
   VEC_free (ce_s, heap, lhsc);
 }
 
@@ -3896,7 +3984,8 @@ get_fi_for_callee (gimple call)
   if (TREE_CODE (decl) == SSA_NAME)
     {
       if (TREE_CODE (decl) == SSA_NAME
-         && TREE_CODE (SSA_NAME_VAR (decl)) == PARM_DECL
+         && (TREE_CODE (SSA_NAME_VAR (decl)) == PARM_DECL
+             || TREE_CODE (SSA_NAME_VAR (decl)) == RESULT_DECL)
          && SSA_NAME_IS_DEFAULT_DEF (decl))
        decl = SSA_NAME_VAR (decl);
       return get_vi_for_tree (decl);
@@ -4155,6 +4244,25 @@ find_func_aliases (gimple origt)
          /* va_end doesn't have any effect that matters.  */
          case BUILT_IN_VA_END:
            return;
+         /* Alternate return.  Simply give up for now.  */
+         case BUILT_IN_RETURN:
+           {
+             fi = NULL;
+             if (!in_ipa_mode
+                 || !(fi = get_vi_for_tree (cfun->decl)))
+               make_constraint_from (get_varinfo (escaped_id), anything_id);
+             else if (in_ipa_mode
+                      && fi != NULL)
+               {
+                 struct constraint_expr lhs, rhs;
+                 lhs = get_function_part_constraint (fi, fi_result);
+                 rhs.var = anything_id;
+                 rhs.offset = 0;
+                 rhs.type = SCALAR;
+                 process_constraint (new_constraint (lhs, rhs));
+               }
+             return;
+           }
          /* printf-style functions may have hooks to set pointers to
             point to somewhere into the generated string.  Leave them
             for a later excercise...  */
@@ -4186,7 +4294,7 @@ find_func_aliases (gimple origt)
            handle_rhs_call (t, &rhsc);
          if (gimple_call_lhs (t)
              && could_have_pointers (gimple_call_lhs (t)))
-           handle_lhs_call (gimple_call_lhs (t), flags, rhsc, fndecl);
+           handle_lhs_call (t, gimple_call_lhs (t), flags, rhsc, fndecl);
          VEC_free (ce_s, heap, rhsc);
        }
       else
@@ -4220,7 +4328,7 @@ find_func_aliases (gimple origt)
          /* If we are returning a value, assign it to the result.  */
          lhsop = gimple_call_lhs (t);
          if (lhsop
-             && could_have_pointers (lhsop))
+             && type_could_have_pointers (TREE_TYPE (lhsop)))
            {
              struct constraint_expr rhs;
              struct constraint_expr *lhsp;
@@ -4274,7 +4382,7 @@ find_func_aliases (gimple origt)
      operations with pointer result, others are dealt with as escape
      points if they have pointer operands.  */
   else if (is_gimple_assign (t)
-          && could_have_pointers (gimple_assign_lhs (t)))
+          && type_could_have_pointers (TREE_TYPE (gimple_assign_lhs (t))))
     {
       /* Otherwise, just a regular assignment statement.  */
       tree lhsop = gimple_assign_lhs (t);
@@ -4290,6 +4398,14 @@ find_func_aliases (gimple origt)
          if (gimple_assign_rhs_code (t) == POINTER_PLUS_EXPR)
            get_constraint_for_ptr_offset (gimple_assign_rhs1 (t),
                                           gimple_assign_rhs2 (t), &rhsc);
+         else if (gimple_assign_rhs_code (t) == BIT_AND_EXPR
+                  && TREE_CODE (gimple_assign_rhs2 (t)) == INTEGER_CST)
+           {
+             /* Aligning a pointer via a BIT_AND_EXPR is offsetting
+                the pointer.  Handle it by offsetting it by UNKNOWN.  */
+             get_constraint_for_ptr_offset (gimple_assign_rhs1 (t),
+                                            NULL_TREE, &rhsc);
+           }
          else if ((CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (t))
                    && !(POINTER_TYPE_P (gimple_expr_type (t))
                         && !POINTER_TYPE_P (TREE_TYPE (rhsop))))
@@ -4469,7 +4585,11 @@ find_func_clobbers (gimple origt)
        tem = TREE_OPERAND (tem, 0);
       if ((DECL_P (tem)
           && !auto_var_in_fn_p (tem, cfun->decl))
-         || INDIRECT_REF_P (tem))
+         || 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))))
        {
          struct constraint_expr lhsc, *rhsp;
          unsigned i;
@@ -4493,7 +4613,11 @@ find_func_clobbers (gimple origt)
        tem = TREE_OPERAND (tem, 0);
       if ((DECL_P (tem)
           && !auto_var_in_fn_p (tem, cfun->decl))
-         || INDIRECT_REF_P (tem))
+         || 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))))
        {
          struct constraint_expr lhs, *rhsp;
          unsigned i;
@@ -4843,7 +4967,7 @@ var_can_have_subvars (const_tree v)
 
 static bool
 push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
-                            HOST_WIDE_INT offset)
+                            HOST_WIDE_INT offset, bool must_have_pointers_p)
 {
   tree field;
   bool empty_p = true;
@@ -4868,7 +4992,8 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
            || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
          push = true;
        else if (!push_fields_onto_fieldstack
-                   (TREE_TYPE (field), fieldstack, offset + foff)
+                   (TREE_TYPE (field), fieldstack, offset + foff,
+                    must_have_pointers_p)
                 && (DECL_SIZE (field)
                     && !integer_zerop (DECL_SIZE (field))))
          /* Empty structures may have actual size, like in C++.  So
@@ -4894,6 +5019,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
                && !pair->has_unknown_size
                && !has_unknown_size
                && pair->offset + (HOST_WIDE_INT)pair->size == offset + foff
+               && !must_have_pointers_p
                && !could_have_pointers (field))
              {
                pair->size += TREE_INT_CST_LOW (DECL_SIZE (field));
@@ -4907,7 +5033,8 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
                  pair->size = TREE_INT_CST_LOW (DECL_SIZE (field));
                else
                  pair->size = -1;
-               pair->may_have_pointers = could_have_pointers (field);
+               pair->may_have_pointers
+                 = must_have_pointers_p || could_have_pointers (field);
                pair->only_restrict_pointers
                  = (!has_unknown_size
                     && POINTER_TYPE_P (TREE_TYPE (field))
@@ -4948,7 +5075,7 @@ count_num_arguments (tree decl, bool *is_varargs)
 /* Creation function node for DECL, using NAME, and return the index
    of the variable we've created for the function.  */
 
-static unsigned int
+static varinfo_t
 create_function_info_for (tree decl, const char *name)
 {
   struct function *fn = DECL_STRUCT_FUNCTION (decl);
@@ -5121,7 +5248,7 @@ create_function_info_for (tree decl, const char *name)
       prev_vi = argvi;
     }
 
-  return vi->id;
+  return vi;
 }
 
 
@@ -5184,7 +5311,10 @@ create_variable_info_for_1 (tree decl, const char *name)
       bool notokay = false;
       unsigned int i;
 
-      push_fields_onto_fieldstack (decl_type, &fieldstack, 0);
+      push_fields_onto_fieldstack (decl_type, &fieldstack, 0,
+                                  TREE_PUBLIC (decl)
+                                  || DECL_EXTERNAL (decl)
+                                  || TREE_ADDRESSABLE (decl));
 
       for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
        if (fo->has_unknown_size
@@ -5342,7 +5472,7 @@ dump_solution_for_var (FILE *file, unsigned int var)
 
 /* Print the points-to solution for VAR to stdout.  */
 
-void
+DEBUG_FUNCTION void
 debug_solution_for_var (unsigned int var)
 {
   dump_solution_for_var (stdout, var);
@@ -5624,7 +5754,8 @@ find_what_p_points_to (tree p)
   /* For parameters, get at the points-to set for the actual parm
      decl.  */
   if (TREE_CODE (p) == SSA_NAME
-      && TREE_CODE (SSA_NAME_VAR (p)) == PARM_DECL
+      && (TREE_CODE (SSA_NAME_VAR (p)) == PARM_DECL
+         || TREE_CODE (SSA_NAME_VAR (p)) == RESULT_DECL)
       && SSA_NAME_IS_DEFAULT_DEF (p))
     lookup_p = SSA_NAME_VAR (p);
 
@@ -5690,6 +5821,17 @@ pt_solution_set (struct pt_solution *pt, bitmap vars,
   pt->vars_contains_restrict = vars_contains_restrict;
 }
 
+/* Set the points-to solution *PT to point only to the variable VAR.  */
+
+void
+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_UID (var));
+  pt->vars_contains_global = is_global_var (var);
+}
+
 /* Computes the union of the points-to solutions *DEST and *SRC and
    stores the result in *DEST.  This changes the points-to bitmap
    of *DEST and thus may not be used if that might be shared.
@@ -5943,7 +6085,7 @@ dump_sa_points_to_info (FILE *outfile)
 
 /* Debug points-to information to stderr.  */
 
-void
+DEBUG_FUNCTION void
 debug_sa_points_to_info (void)
 {
   dump_sa_points_to_info (stderr);
@@ -6534,7 +6676,7 @@ gate_ipa_pta (void)
   return (optimize
          && flag_ipa_pta
          /* Don't bother doing anything if the program has errors.  */
-         && !(errorcount || sorrycount));
+         && !seen_error ());
 }
 
 /* IPA PTA solutions for ESCAPED.  */
@@ -6557,6 +6699,9 @@ ipa_pta_execute (void)
   /* Build the constraints.  */
   for (node = cgraph_nodes; node; node = node->next)
     {
+      struct cgraph_node *alias;
+      varinfo_t vi;
+
       /* 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.  */
@@ -6564,13 +6709,26 @@ ipa_pta_execute (void)
          || node->clone_of)
        continue;
 
-      create_function_info_for (node->decl,
-                               cgraph_node_name (node));
+      vi = create_function_info_for (node->decl,
+                                    alias_get_name (node->decl));
+
+      /* Associate the varinfo node with all aliases.  */
+      for (alias = node->same_body; alias; alias = alias->next)
+       insert_vi_for_tree (alias->decl, vi);
     }
 
   /* Create constraints for global variables and their initializers.  */
   for (var = varpool_nodes; var; var = var->next)
-    get_vi_for_tree (var->decl);
+    {
+      struct varpool_node *alias;
+      varinfo_t vi;
+
+      vi = get_vi_for_tree (var->decl);
+
+      /* Associate the varinfo node with all aliases.  */
+      for (alias = var->extra_name; alias; alias = alias->next)
+       insert_vi_for_tree (alias->decl, vi);
+    }
 
   if (dump_file)
     {
@@ -6593,9 +6751,14 @@ ipa_pta_execute (void)
        continue;
 
       if (dump_file)
-       fprintf (dump_file,
-                "Generating constraints for %s\n",
-                cgraph_node_name (node));
+       {
+         fprintf (dump_file,
+                  "Generating constraints for %s", cgraph_node_name (node));
+         if (DECL_ASSEMBLER_NAME_SET_P (node->decl))
+           fprintf (dump_file, " (%s)",
+                    IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
+         fprintf (dump_file, "\n");
+       }
 
       func = DECL_STRUCT_FUNCTION (node->decl);
       old_func_decl = current_function_decl;