OSDN Git Service

2010-04-06 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-structalias.c
index 74dc6d2..1ea7afc 100644 (file)
@@ -1,5 +1,6 @@
 /* Tree based points-to analysis
-   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
    Contributed by Daniel Berlin <dberlin@dberlin.org>
 
    This file is part of GCC.
@@ -1269,13 +1270,18 @@ build_succ_graph (void)
        }
     }
 
-  /* Add edges from STOREDANYTHING to all non-direct nodes.  */
+  /* Add edges from STOREDANYTHING to all non-direct nodes that can
+     receive pointers.  */
   t = find (storedanything_id);
   for (i = integer_id + 1; i < FIRST_REF_NODE; ++i)
     {
-      if (!TEST_BIT (graph->direct_nodes, i))
+      if (!TEST_BIT (graph->direct_nodes, i)
+         && get_varinfo (i)->may_have_pointers)
        add_graph_edge (graph, find (i), t);
     }
+
+  /* Everything stored to ANYTHING also potentially escapes.  */
+  add_graph_edge (graph, find (escaped_id), t);
 }
 
 
@@ -1349,7 +1355,6 @@ scc_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
          && si->dfs[VEC_last (unsigned, si->scc_stack)] >= my_dfs)
        {
          bitmap scc = BITMAP_ALLOC (NULL);
-         bool have_ref_node = n >= FIRST_REF_NODE;
          unsigned int lowest_node;
          bitmap_iterator bi;
 
@@ -1361,8 +1366,6 @@ scc_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
              unsigned int w = VEC_pop (unsigned, si->scc_stack);
 
              bitmap_set_bit (scc, w);
-             if (w >= FIRST_REF_NODE)
-               have_ref_node = true;
            }
 
          lowest_node = bitmap_first_set_bit (scc);
@@ -1439,10 +1442,10 @@ unify_nodes (constraint_graph_t graph, unsigned int to, unsigned int from,
              changed_count++;
            }
        }
-      
+
       BITMAP_FREE (get_varinfo (from)->solution);
       BITMAP_FREE (get_varinfo (from)->oldsolution);
-      
+
       if (stats.iterations > 0)
        {
          BITMAP_FREE (get_varinfo (to)->oldsolution);
@@ -2283,10 +2286,10 @@ unite_pointer_equivalences (constraint_graph_t graph)
       if (label)
        {
          int label_rep = graph->pe_rep[label];
-         
+
          if (label_rep == -1)
            continue;
-         
+
          label_rep = find (label_rep);
          if (label_rep >= 0 && unite (label_rep, find (i)))
            unify_nodes (graph, label_rep, i, false);
@@ -2363,7 +2366,7 @@ rewrite_constraints (constraint_graph_t graph,
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
-             
+
              fprintf (dump_file, "%s is a non-pointer variable,"
                       "ignoring constraint:",
                       get_varinfo (lhs.var)->name);
@@ -2377,7 +2380,7 @@ rewrite_constraints (constraint_graph_t graph,
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
-             
+
              fprintf (dump_file, "%s is a non-pointer variable,"
                       "ignoring constraint:",
                       get_varinfo (rhs.var)->name);
@@ -2720,7 +2723,8 @@ get_constraint_for_ssa_var (tree t, VEC(ce_s, heap) **results, bool address_p)
 
   /* If we are not taking the address of the constraint expr, add all
      sub-fiels of the variable as well.  */
-  if (!address_p)
+  if (!address_p
+      && !vi->is_full_var)
     {
       for (; vi; vi = vi->next)
        {
@@ -3277,14 +3281,11 @@ do_structure_copy (tree lhsop, tree rhsop)
           && (rhsp->type == SCALAR
               || rhsp->type == ADDRESSOF))
     {
-      tree lhsbase, rhsbase;
       HOST_WIDE_INT lhssize, lhsmaxsize, lhsoffset;
       HOST_WIDE_INT rhssize, rhsmaxsize, rhsoffset;
       unsigned k = 0;
-      lhsbase = get_ref_base_and_extent (lhsop, &lhsoffset,
-                                        &lhssize, &lhsmaxsize);
-      rhsbase = get_ref_base_and_extent (rhsop, &rhsoffset,
-                                        &rhssize, &rhsmaxsize);
+      get_ref_base_and_extent (lhsop, &lhsoffset, &lhssize, &lhsmaxsize);
+      get_ref_base_and_extent (rhsop, &rhsoffset, &rhssize, &rhsmaxsize);
       for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp);)
        {
          varinfo_t lhsv, rhsv;
@@ -3482,7 +3483,7 @@ 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)
+handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc, tree fndecl)
 {
   VEC(ce_s, heap) *lhsc = NULL;
 
@@ -3496,6 +3497,12 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
          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
+        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);
     }
   else if (VEC_length (ce_s, rhsc) > 0)
     {
@@ -3634,11 +3641,9 @@ find_func_aliases (gimple origt)
          get_constraint_for (gimple_phi_result (t), &lhsc);
          for (i = 0; i < gimple_phi_num_args (t); i++)
            {
-             tree rhstype;
              tree strippedrhs = PHI_ARG_DEF (t, i);
 
              STRIP_NOPS (strippedrhs);
-             rhstype = TREE_TYPE (strippedrhs);
              get_constraint_for (gimple_phi_arg_def (t, i), &rhsc);
 
              for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
@@ -3800,7 +3805,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);
+           handle_lhs_call (gimple_call_lhs (t), flags, rhsc, fndecl);
          VEC_free (ce_s, heap, rhsc);
        }
       else
@@ -4032,7 +4037,7 @@ first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset)
         In that case, however, offset should still be within the size
         of the variable. */
       if (offset >= start->offset
-         && offset < (start->offset + start->size))
+         && (offset - start->offset) < start->size)
        return start;
 
       start= start->next;
@@ -4062,7 +4067,7 @@ first_or_preceding_vi_for_offset (varinfo_t start,
      directly preceding offset which may be the last field.  */
   while (start->next
         && offset >= start->offset
-        && !(offset < (start->offset + start->size)))
+        && !((offset - start->offset) < start->size))
     start = start->next;
 
   return start;
@@ -4286,21 +4291,22 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
 static unsigned int
 count_num_arguments (tree decl, bool *is_varargs)
 {
-  unsigned int i = 0;
+  unsigned int num = 0;
   tree t;
 
-  for (t = TYPE_ARG_TYPES (TREE_TYPE (decl));
-       t;
-       t = TREE_CHAIN (t))
-    {
-      if (TREE_VALUE (t) == void_type_node)
-       break;
-      i++;
-    }
+  /* Capture named arguments for K&R functions.  They do not
+     have a prototype and thus no TYPE_ARG_TYPES.  */
+  for (t = DECL_ARGUMENTS (decl); t; t = TREE_CHAIN (t))
+    ++num;
 
+  /* Check if the function has variadic arguments.  */
+  for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
+    if (TREE_VALUE (t) == void_type_node)
+      break;
   if (!t)
     *is_varargs = true;
-  return i;
+
+  return num;
 }
 
 /* Creation function node for DECL, using NAME, and return the index
@@ -4745,7 +4751,7 @@ shared_bitmap_add (bitmap pt_vars)
 
 /* Set bits in INTO corresponding to the variable uids in solution set FROM.  */
 
-static void 
+static void
 set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
 {
   unsigned int i;
@@ -4777,18 +4783,19 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
 /* Compute the points-to solution *PT for the variable VI.  */
 
 static void
-find_what_var_points_to (varinfo_t vi, struct pt_solution *pt)
+find_what_var_points_to (varinfo_t orig_vi, struct pt_solution *pt)
 {
   unsigned int i;
   bitmap_iterator bi;
   bitmap finished_solution;
   bitmap result;
+  varinfo_t vi;
 
   memset (pt, 0, sizeof (struct pt_solution));
 
   /* This variable may have been collapsed, let's get the real
      variable.  */
-  vi = get_varinfo (find (vi->id));
+  vi = get_varinfo (find (orig_vi->id));
 
   /* Translate artificial variables into SSA_NAME_PTR_INFO
      attributes.  */
@@ -4823,7 +4830,7 @@ find_what_var_points_to (varinfo_t vi, struct pt_solution *pt)
   /* Instead of doing extra work, simply do not create
      elaborate points-to information for pt_anything pointers.  */
   if (pt->anything
-      && (vi->is_artificial_var
+      && (orig_vi->is_artificial_var
          || !pt->vars_contains_restrict))
     return;
 
@@ -5417,16 +5424,16 @@ solve_constraints (void)
             "substitution\n");
 
   init_graph (VEC_length (varinfo_t, varmap) * 2);
-  
+
   if (dump_file)
     fprintf (dump_file, "Building predecessor graph\n");
   build_pred_graph ();
-  
+
   if (dump_file)
     fprintf (dump_file, "Detecting pointer and location "
             "equivalences\n");
   si = perform_var_substitution (graph);
-  
+
   if (dump_file)
     fprintf (dump_file, "Rewriting constraints and unifying "
             "variables\n");
@@ -5654,7 +5661,8 @@ struct gimple_opt_pass pass_build_ealias =
 static bool
 gate_ipa_pta (void)
 {
-  return (flag_ipa_pta
+  return (optimize
+         && flag_ipa_pta
          /* Don't bother doing anything if the program has errors.  */
          && !(errorcount || sorrycount));
 }
@@ -5673,8 +5681,6 @@ ipa_pta_execute (void)
   /* Build the constraints.  */
   for (node = cgraph_nodes; node; node = node->next)
     {
-      unsigned int varid;
-
       /* 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.  */
@@ -5688,8 +5694,8 @@ ipa_pta_execute (void)
       if (node->local.externally_visible)
        continue;
 
-      varid = create_function_info_for (node->decl,
-                                       cgraph_node_name (node));
+      create_function_info_for (node->decl,
+                               cgraph_node_name (node));
     }
 
   for (node = cgraph_nodes; node; node = node->next)