OSDN Git Service

2009-10-21 Jack Howarth <howarth@bromo.med.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-structalias.c
index 303bd1f..e5f4a29 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
@@ -402,10 +425,6 @@ struct constraint
 static VEC(constraint_t,heap) *constraints;
 static alloc_pool constraint_pool;
 
-
-DEF_VEC_I(int);
-DEF_VEC_ALLOC_I(int, heap);
-
 /* The constraint graph is represented as an array of bitmaps
    containing successor nodes.  */
 
@@ -1264,10 +1283,6 @@ build_succ_graph (void)
 static unsigned int changed_count;
 static sbitmap changed;
 
-DEF_VEC_I(unsigned);
-DEF_VEC_ALLOC_I(unsigned,heap);
-
-
 /* Strongly Connected Component visitation info.  */
 
 struct scc_info
@@ -3365,7 +3380,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)
     {
@@ -3373,7 +3388,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;
@@ -3388,6 +3403,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;
@@ -4495,6 +4511,13 @@ create_variable_info_for (tree decl, const char *name)
       vi->size = fo->size;
       vi->offset = fo->offset;
       vi->may_have_pointers = fo->may_have_pointers;
+      if (vi->is_global_var
+         && (!flag_whole_program || !in_ipa_mode)
+         && vi->may_have_pointers)
+       {
+         if (fo->only_restrict_pointers)
+           make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
+       }
       for (i = VEC_length (fieldoff_s, fieldstack) - 1;
           i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo);
           i--)
@@ -4517,13 +4540,13 @@ create_variable_info_for (tree decl, const char *name)
          newvi->fullsize = vi->fullsize;
          newvi->may_have_pointers = fo->may_have_pointers;
          insert_into_field_list (vi, newvi);
-         if (newvi->is_global_var
-             && (!flag_whole_program || !in_ipa_mode)
+         if ((newvi->is_global_var || TREE_CODE (decl) == PARM_DECL)
              && newvi->may_have_pointers)
            {
               if (fo->only_restrict_pointers)
                 make_constraint_from_restrict (newvi, "GLOBAL_RESTRICT");
-              make_copy_constraint (newvi, nonlocal_id);
+              if (newvi->is_global_var && !in_ipa_mode)
+                make_copy_constraint (newvi, nonlocal_id);
            }
 
          stats.total_vars++;
@@ -4587,43 +4610,41 @@ intra_create_variable_infos (void)
       if (!could_have_pointers (t))
        continue;
 
-      /* If flag_argument_noalias is set, then function pointer
-        arguments are guaranteed not to point to each other.  In that
-        case, create an artificial variable PARM_NOALIAS and the
-        constraint ARG = &PARM_NOALIAS.  */
-      if (POINTER_TYPE_P (TREE_TYPE (t)) && flag_argument_noalias > 0)
+      /* For restrict qualified pointers to objects passed by
+         reference build a real representative for the pointed-to object.  */
+      if (DECL_BY_REFERENCE (t)
+         && POINTER_TYPE_P (TREE_TYPE (t))
+         && TYPE_RESTRICT (TREE_TYPE (t)))
        {
+         struct constraint_expr lhsc, rhsc;
          varinfo_t vi;
-         var_ann_t ann;
-
-         vi = make_constraint_from_heapvar (get_vi_for_tree (t),
-                                            "PARM_NOALIAS");
-         ann = get_var_ann (vi->decl);
-         if (flag_argument_noalias == 1)
-           {
-             ann->noalias_state = NO_ALIAS;
-             make_copy_constraint (vi, nonlocal_id);
-           }
-         else if (flag_argument_noalias == 2)
-           {
-             ann->noalias_state = NO_ALIAS_GLOBAL;
-             make_constraint_from (vi, vi->id);
-           }
-         else if (flag_argument_noalias == 3)
+         tree heapvar = heapvar_lookup (t, 0);
+         if (heapvar == NULL_TREE)
            {
-             ann->noalias_state = NO_ALIAS_ANYTHING;
-             make_constraint_from (vi, vi->id);
+             var_ann_t ann;
+             heapvar = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (t)),
+                                           "PARM_NOALIAS");
+             DECL_EXTERNAL (heapvar) = 1;
+             heapvar_insert (t, 0, heapvar);
+             ann = get_var_ann (heapvar);
+             ann->is_heapvar = 1;
            }
-         else
-           gcc_unreachable ();
+         if (gimple_referenced_vars (cfun))
+           add_referenced_var (heapvar);
+         lhsc.var = get_vi_for_tree (t)->id;
+         lhsc.type = SCALAR;
+         lhsc.offset = 0;
+         rhsc.var = (vi = get_vi_for_tree (heapvar))->id;
+         rhsc.type = ADDRESSOF;
+         rhsc.offset = 0;
+         process_constraint (new_constraint (lhsc, rhsc));
+         vi->is_restrict_var = 1;
+         continue;
        }
-      else
-       {
-         varinfo_t arg_vi = get_vi_for_tree (t);
 
-         for (p = arg_vi; p; p = p->next)
-           make_constraint_from (p, nonlocal_id);
-       }
+      for (p = get_vi_for_tree (t); p; p = p->next)
+       if (p->may_have_pointers)
+         make_constraint_from (p, nonlocal_id);
       if (POINTER_TYPE_P (TREE_TYPE (t))
          && TYPE_RESTRICT (TREE_TYPE (t)))
        make_constraint_from_restrict (get_vi_for_tree (t), "PARM_RESTRICT");
@@ -4886,6 +4907,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
@@ -5340,7 +5383,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);
 }