OSDN Git Service

* lib/target-supports.exp
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-structalias.c
index ad5482a..50ef0b6 100644 (file)
@@ -290,18 +290,39 @@ enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
        escaped_id = 3, nonlocal_id = 4, callused_id = 5,
        storedanything_id = 6, integer_id = 7 };
 
+struct GTY(()) heapvar_map {
+  struct tree_map map;
+  unsigned HOST_WIDE_INT offset;
+};
+
+static int
+heapvar_map_eq (const void *p1, const void *p2)
+{
+  const struct heapvar_map *h1 = (const struct heapvar_map *)p1;
+  const struct heapvar_map *h2 = (const struct heapvar_map *)p2;
+  return (h1->map.base.from == h2->map.base.from
+         && h1->offset == h2->offset);
+}
+
+static unsigned int
+heapvar_map_hash (struct heapvar_map *h)
+{
+  return iterative_hash_host_wide_int (h->offset,
+                                      htab_hash_pointer (h->map.base.from));
+}
+
 /* Lookup a heap var for FROM, and return it if we find one.  */
 
 static tree
-heapvar_lookup (tree from)
+heapvar_lookup (tree from, unsigned HOST_WIDE_INT offset)
 {
-  struct tree_map *h, in;
-  in.base.from = from;
-
-  h = (struct tree_map *) htab_find_with_hash (heapvar_for_stmt, &in,
-                                              htab_hash_pointer (from));
+  struct heapvar_map *h, in;
+  in.map.base.from = from;
+  in.offset = offset;
+  h = (struct heapvar_map *) htab_find_with_hash (heapvar_for_stmt, &in,
+                                                 heapvar_map_hash (&in));
   if (h)
-    return h->to;
+    return h->map.to;
   return NULL_TREE;
 }
 
@@ -309,17 +330,19 @@ heapvar_lookup (tree from)
    hashtable.  */
 
 static void
-heapvar_insert (tree from, tree to)
+heapvar_insert (tree from, unsigned HOST_WIDE_INT offset, tree to)
 {
-  struct tree_map *h;
+  struct heapvar_map *h;
   void **loc;
 
-  h = GGC_NEW (struct tree_map);
-  h->hash = htab_hash_pointer (from);
-  h->base.from = from;
-  h->to = to;
-  loc = htab_find_slot_with_hash (heapvar_for_stmt, h, h->hash, INSERT);
-  *(struct tree_map **) loc = h;
+  h = GGC_NEW (struct heapvar_map);
+  h->map.base.from = from;
+  h->offset = offset;
+  h->map.hash = heapvar_map_hash (h);
+  h->map.to = to;
+  loc = htab_find_slot_with_hash (heapvar_for_stmt, h, h->map.hash, INSERT);
+  gcc_assert (*loc == NULL);
+  *(struct heapvar_map **) loc = h;
 }
 
 /* Return a new variable info structure consisting for a variable
@@ -337,10 +360,11 @@ new_var_info (tree t, const char *name)
   ret->decl = t;
   /* Vars without decl are artificial and do not have sub-variables.  */
   ret->is_artificial_var = (t == NULL_TREE);
-  ret->is_full_var = (t == NULL_TREE);
-  ret->is_heap_var = false;
   ret->is_special_var = false;
   ret->is_unknown_size_var = false;
+  ret->is_full_var = (t == NULL_TREE);
+  ret->is_heap_var = false;
+  ret->is_restrict_var = false;
   ret->may_have_pointers = true;
   ret->is_global_var = (t == NULL_TREE);
   if (t && DECL_P (t))
@@ -3364,7 +3388,7 @@ static varinfo_t
 make_constraint_from_heapvar (varinfo_t lhs, const char *name)
 {
   varinfo_t vi;
-  tree heapvar = heapvar_lookup (lhs->decl);
+  tree heapvar = heapvar_lookup (lhs->decl, lhs->offset);
 
   if (heapvar == NULL_TREE)
     {
@@ -3372,7 +3396,7 @@ make_constraint_from_heapvar (varinfo_t lhs, const char *name)
       heapvar = create_tmp_var_raw (ptr_type_node, name);
       DECL_EXTERNAL (heapvar) = 1;
 
-      heapvar_insert (lhs->decl, heapvar);
+      heapvar_insert (lhs->decl, lhs->offset, heapvar);
 
       ann = get_var_ann (heapvar);
       ann->is_heapvar = 1;
@@ -3387,6 +3411,7 @@ make_constraint_from_heapvar (varinfo_t lhs, const char *name)
   vi->is_artificial_var = true;
   vi->is_heap_var = true;
   vi->is_unknown_size_var = true;
+  vi->offset = 0;
   vi->fullsize = ~0;
   vi->size = ~0;
   vi->is_full_var = true;
@@ -3473,7 +3498,10 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
     {
       varinfo_t vi;
       vi = make_constraint_from_heapvar (get_vi_for_tree (lhs), "HEAP");
-      make_copy_constraint (vi, nonlocal_id);
+      /* We delay marking allocated storage global until we know if
+         it escapes.  */
+      DECL_EXTERNAL (vi->decl) = 0;
+      vi->is_global_var = 0;
     }
   else if (VEC_length (ce_s, rhsc) > 0)
     {
@@ -3910,6 +3938,13 @@ find_func_aliases (gimple origt)
     {
       make_escape_constraint (gimple_assign_rhs1 (t));
     }
+  /* Handle escapes through return.  */
+  else if (gimple_code (t) == GIMPLE_RETURN
+          && gimple_return_retval (t) != NULL_TREE
+          && could_have_pointers (gimple_return_retval (t)))
+    {
+      make_escape_constraint (gimple_return_retval (t));
+    }
   /* Handle asms conservatively by adding escape constraints to everything.  */
   else if (gimple_code (t) == GIMPLE_ASM)
     {
@@ -4776,8 +4811,10 @@ find_what_var_points_to (varinfo_t vi, struct pt_solution *pt)
          else if (vi->is_heap_var)
            /* We represent heapvars in the points-to set properly.  */
            ;
+         else if (vi->id == readonly_id)
+           /* Nobody cares.  */
+           ;
          else if (vi->id == anything_id
-                  || vi->id == readonly_id
                   || vi->id == integer_id)
            pt->anything = 1;
        }
@@ -4873,6 +4910,28 @@ pt_solution_reset (struct pt_solution *pt)
   pt->anything = true;
 }
 
+/* Set the points-to solution *PT to point only to the variables
+   in VARS.  */
+
+void
+pt_solution_set (struct pt_solution *pt, bitmap vars)
+{
+  bitmap_iterator bi;
+  unsigned i;
+
+  memset (pt, 0, sizeof (struct pt_solution));
+  pt->vars = vars;
+  EXECUTE_IF_SET_IN_BITMAP (vars, 0, i, bi)
+    {
+      tree var = referenced_var_lookup (i);
+      if (is_global_var (var))
+       {
+         pt->vars_contains_global = true;
+         break;
+       }
+    }
+}
+
 /* Return true if the points-to solution *PT is empty.  */
 
 static bool
@@ -5327,7 +5386,7 @@ static void
 init_alias_heapvars (void)
 {
   if (!heapvar_for_stmt)
-    heapvar_for_stmt = htab_create_ggc (11, tree_map_hash, tree_map_eq,
+    heapvar_for_stmt = htab_create_ggc (11, tree_map_hash, heapvar_map_eq,
                                        NULL);
 }
 
@@ -5350,6 +5409,7 @@ compute_points_to_sets (void)
   struct scc_info *si;
   basic_block bb;
   unsigned i;
+  varinfo_t vi;
 
   timevar_push (TV_TREE_PTA);
 
@@ -5447,6 +5507,14 @@ compute_points_to_sets (void)
      points-to solution queries.  */
   cfun->gimple_df->escaped.escaped = 0;
 
+  /* Mark escaped HEAP variables as global.  */
+  for (i = 0; VEC_iterate (varinfo_t, varmap, i, vi); ++i)
+    if (vi->is_heap_var
+       && !vi->is_restrict_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)
     {