OSDN Git Service

PR tree-optimization/32353
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-structalias.c
index 865770a..2b69728 100644 (file)
@@ -250,6 +250,10 @@ struct variable_info
   /* True if this is a heap variable.  */
   unsigned int is_heap_var:1;
 
   /* True if this is a heap variable.  */
   unsigned int is_heap_var:1;
 
+  /* True if we may not use TBAA to prune references to this
+     variable.  This is used for C++ placement new.  */
+  unsigned int no_tbaa_pruning : 1;
+
   /* Points-to set for this variable.  */
   bitmap solution;
 
   /* Points-to set for this variable.  */
   bitmap solution;
 
@@ -328,7 +332,8 @@ heapvar_lookup (tree from)
   struct tree_map *h, in;
   in.base.from = from;
 
   struct tree_map *h, in;
   in.base.from = from;
 
-  h = htab_find_with_hash (heapvar_for_stmt, &in, htab_hash_pointer (from));
+  h = (struct tree_map *) htab_find_with_hash (heapvar_for_stmt, &in,
+                                              htab_hash_pointer (from));
   if (h)
     return h->to;
   return NULL_TREE;
   if (h)
     return h->to;
   return NULL_TREE;
@@ -343,7 +348,7 @@ heapvar_insert (tree from, tree to)
   struct tree_map *h;
   void **loc;
 
   struct tree_map *h;
   void **loc;
 
-  h = ggc_alloc (sizeof (struct tree_map));
+  h = GGC_NEW (struct tree_map);
   h->hash = htab_hash_pointer (from);
   h->base.from = from;
   h->to = to;
   h->hash = htab_hash_pointer (from);
   h->base.from = from;
   h->to = to;
@@ -357,7 +362,8 @@ heapvar_insert (tree from, tree to)
 static varinfo_t
 new_var_info (tree t, unsigned int id, const char *name)
 {
 static varinfo_t
 new_var_info (tree t, unsigned int id, const char *name)
 {
-  varinfo_t ret = pool_alloc (variable_info_pool);
+  varinfo_t ret = (varinfo_t) pool_alloc (variable_info_pool);
+  tree var;
 
   ret->id = id;
   ret->name = name;
 
   ret->id = id;
   ret->name = name;
@@ -368,6 +374,12 @@ new_var_info (tree t, unsigned int id, const char *name)
   ret->is_special_var = false;
   ret->is_unknown_size_var = false;
   ret->has_union = false;
   ret->is_special_var = false;
   ret->is_unknown_size_var = false;
   ret->has_union = false;
+  var = t;
+  if (TREE_CODE (var) == SSA_NAME)
+    var = SSA_NAME_VAR (var);
+  ret->no_tbaa_pruning = (DECL_P (var)
+                         && POINTER_TYPE_P (TREE_TYPE (var))
+                         && DECL_NO_TBAA_P (var));
   ret->solution = BITMAP_ALLOC (&pta_obstack);
   ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
   ret->next = NULL;
   ret->solution = BITMAP_ALLOC (&pta_obstack);
   ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
   ret->next = NULL;
@@ -513,7 +525,7 @@ static constraint_t
 new_constraint (const struct constraint_expr lhs,
                const struct constraint_expr rhs)
 {
 new_constraint (const struct constraint_expr lhs,
                const struct constraint_expr rhs)
 {
-  constraint_t ret = pool_alloc (constraint_pool);
+  constraint_t ret = (constraint_t) pool_alloc (constraint_pool);
   ret->lhs = lhs;
   ret->rhs = rhs;
   return ret;
   ret->lhs = lhs;
   ret->rhs = rhs;
   return ret;
@@ -1194,6 +1206,9 @@ unify_nodes (constraint_graph_t graph, unsigned int to, unsigned int from,
   merge_graph_nodes (graph, to, from);
   merge_node_constraints (graph, to, from);
 
   merge_graph_nodes (graph, to, from);
   merge_node_constraints (graph, to, from);
 
+  if (get_varinfo (from)->no_tbaa_pruning)
+    get_varinfo (to)->no_tbaa_pruning = true;
+
   if (update_changed && TEST_BIT (changed, from))
     {
       RESET_BIT (changed, from);
   if (update_changed && TEST_BIT (changed, from))
     {
       RESET_BIT (changed, from);
@@ -2808,7 +2823,7 @@ do_rhs_deref_structure_copy (const struct constraint_expr lhs,
 }
 
 /* Handle the structure copy case where we have a structure copy
 }
 
 /* Handle the structure copy case where we have a structure copy
-   between a aggregate on the RHS and a dereference of a pointer on
+   between an aggregate on the RHS and a dereference of a pointer on
    the LHS that is of SIZE (in bits)
 
    For each field of the rhs variable (rhsfield)
    the LHS that is of SIZE (in bits)
 
    For each field of the rhs variable (rhsfield)
@@ -3226,7 +3241,7 @@ update_alias_info (tree stmt, struct alias_info *ai)
         combination of direct symbol references and pointer
         dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has
         memory symbols in its argument list, but these cases do not
         combination of direct symbol references and pointer
         dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has
         memory symbols in its argument list, but these cases do not
-        occur so frequently as to constitue a serious problem.  */
+        occur so frequently as to constitute a serious problem.  */
       if (STORED_SYMS (stmt))
        EXECUTE_IF_SET_IN_BITMAP (STORED_SYMS (stmt), 0, i, bi)
          {
       if (STORED_SYMS (stmt))
        EXECUTE_IF_SET_IN_BITMAP (STORED_SYMS (stmt), 0, i, bi)
          {
@@ -3278,23 +3293,17 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
   VEC (ce_s, heap) *temp = NULL;
   unsigned int rhsoffset = 0;
 
   VEC (ce_s, heap) *temp = NULL;
   unsigned int rhsoffset = 0;
 
-  if (TREE_CODE (expr) != PLUS_EXPR
-      && TREE_CODE (expr) != MINUS_EXPR)
+  if (TREE_CODE (expr) != POINTER_PLUS_EXPR)
     return false;
 
   op0 = TREE_OPERAND (expr, 0);
   op1 = TREE_OPERAND (expr, 1);
     return false;
 
   op0 = TREE_OPERAND (expr, 0);
   op1 = TREE_OPERAND (expr, 1);
+  gcc_assert (POINTER_TYPE_P (TREE_TYPE (op0)));
 
   get_constraint_for (op0, &temp);
 
   get_constraint_for (op0, &temp);
-  if (POINTER_TYPE_P (TREE_TYPE (op0))
-      && TREE_CODE (op1) == INTEGER_CST
-      && TREE_CODE (expr) == PLUS_EXPR)
-    {
-      rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
-    }
-  else
-    return false;
 
 
+  if (TREE_CODE (op1) == INTEGER_CST)
+    rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
 
   for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++)
     for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++)
 
   for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++)
     for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++)
@@ -3562,6 +3571,14 @@ find_func_aliases (tree origt)
            }
        }
     }
            }
        }
     }
+  else if (TREE_CODE (t) == CHANGE_DYNAMIC_TYPE_EXPR)
+    {
+      unsigned int j;
+
+      get_constraint_for (CHANGE_DYNAMIC_TYPE_LOCATION (t), &lhsc);
+      for (j = 0; VEC_iterate (ce_s, lhsc, j, c); ++j)
+       get_varinfo (c->var)->no_tbaa_pruning = true;
+    }
 
   /* After promoting variables and computing aliasing we will
      need to re-scan most statements.  FIXME: Try to minimize the
 
   /* After promoting variables and computing aliasing we will
      need to re-scan most statements.  FIXME: Try to minimize the
@@ -4129,7 +4146,10 @@ dump_solution_for_var (FILE *file, unsigned int var)
        {
          fprintf (file, "%s ", get_varinfo (i)->name);
        }
        {
          fprintf (file, "%s ", get_varinfo (i)->name);
        }
-      fprintf (file, "}\n");
+      fprintf (file, "}");
+      if (vi->no_tbaa_pruning)
+       fprintf (file, " no-tbaa-pruning");
+      fprintf (file, "\n");
     }
 }
 
     }
 }
 
@@ -4289,10 +4309,15 @@ shared_bitmap_add (bitmap pt_vars)
 /* Set bits in INTO corresponding to the variable uids in solution set
    FROM, which came from variable PTR.
    For variables that are actually dereferenced, we also use type
 /* Set bits in INTO corresponding to the variable uids in solution set
    FROM, which came from variable PTR.
    For variables that are actually dereferenced, we also use type
-   based alias analysis to prune the points-to sets.  */
+   based alias analysis to prune the points-to sets.
+   IS_DEREFED is true if PTR was directly dereferenced, which we use to
+   help determine whether we are we are allowed to prune using TBAA.
+   If NO_TBAA_PRUNING is true, we do not perform any TBAA pruning of
+   the from set.  */
 
 static void
 
 static void
-set_uids_in_ptset (tree ptr, bitmap into, bitmap from)
+set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
+                  bool no_tbaa_pruning)
 {
   unsigned int i;
   bitmap_iterator bi;
 {
   unsigned int i;
   bitmap_iterator bi;
@@ -4317,7 +4342,8 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from)
            bitmap_set_bit (into, DECL_UID (sv->var));
        }
       else if (TREE_CODE (vi->decl) == VAR_DECL
            bitmap_set_bit (into, DECL_UID (sv->var));
        }
       else if (TREE_CODE (vi->decl) == VAR_DECL
-              || TREE_CODE (vi->decl) == PARM_DECL)
+              || TREE_CODE (vi->decl) == PARM_DECL
+              || TREE_CODE (vi->decl) == RESULT_DECL)
        {
          if (var_can_have_subvars (vi->decl)
              && get_subvars_for_var (vi->decl))
        {
          if (var_can_have_subvars (vi->decl)
              && get_subvars_for_var (vi->decl))
@@ -4328,7 +4354,8 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from)
              if (sft)
                {
                  var_alias_set = get_alias_set (sft);
              if (sft)
                {
                  var_alias_set = get_alias_set (sft);
-                 if (!vi->directly_dereferenced
+                 if (no_tbaa_pruning
+                     || (!is_derefed && !vi->directly_dereferenced)
                      || alias_sets_conflict_p (ptr_alias_set, var_alias_set))
                    bitmap_set_bit (into, DECL_UID (sft));
                }
                      || alias_sets_conflict_p (ptr_alias_set, var_alias_set))
                    bitmap_set_bit (into, DECL_UID (sft));
                }
@@ -4342,7 +4369,8 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from)
              else
                {
                  var_alias_set = get_alias_set (vi->decl);
              else
                {
                  var_alias_set = get_alias_set (vi->decl);
-                 if (!vi->directly_dereferenced
+                 if (no_tbaa_pruning
+                     || (!is_derefed && !vi->directly_dereferenced)
                      || alias_sets_conflict_p (ptr_alias_set, var_alias_set))
                    bitmap_set_bit (into, DECL_UID (vi->decl));
                }
                      || alias_sets_conflict_p (ptr_alias_set, var_alias_set))
                    bitmap_set_bit (into, DECL_UID (vi->decl));
                }
@@ -4537,15 +4565,26 @@ find_what_p_points_to (tree p)
          finished_solution = BITMAP_GGC_ALLOC ();
          stats.points_to_sets_created++;
          
          finished_solution = BITMAP_GGC_ALLOC ();
          stats.points_to_sets_created++;
          
-         /* Instead of using pt_anything, we instead merge in the SMT
-            aliases for the underlying SMT.  */
+         /* Instead of using pt_anything, we merge in the SMT aliases
+            for the underlying SMT.  In addition, if they could have
+            pointed to anything, they could point to global memory.
+            But we cannot do that for ref-all pointers because these
+            aliases have not been computed yet.  */
          if (was_pt_anything)
            {
          if (was_pt_anything)
            {
+             if (PTR_IS_REF_ALL (p))
+               {
+                 pi->pt_anything = 1;
+                 return false;
+               }
+
              merge_smts_into (p, finished_solution);
              pi->pt_global_mem = 1;
            }
          
              merge_smts_into (p, finished_solution);
              pi->pt_global_mem = 1;
            }
          
-         set_uids_in_ptset (vi->decl, finished_solution, vi->solution);
+         set_uids_in_ptset (vi->decl, finished_solution, vi->solution,
+                            vi->directly_dereferenced,
+                            vi->no_tbaa_pruning);
          result = shared_bitmap_lookup (finished_solution);
 
          if (!result)
          result = shared_bitmap_lookup (finished_solution);
 
          if (!result)
@@ -4762,7 +4801,7 @@ remove_preds_and_fake_succs (constraint_graph_t graph)
   /* Now reallocate the size of the successor list as, and blow away
      the predecessor bitmaps.  */
   graph->size = VEC_length (varinfo_t, varmap);
   /* Now reallocate the size of the successor list as, and blow away
      the predecessor bitmaps.  */
   graph->size = VEC_length (varinfo_t, varmap);
-  graph->succs = xrealloc (graph->succs, graph->size * sizeof (bitmap));
+  graph->succs = XRESIZEVEC (bitmap, graph->succs, graph->size);
 
   free (graph->implicit_preds);
   graph->implicit_preds = NULL;
 
   free (graph->implicit_preds);
   graph->implicit_preds = NULL;
@@ -4771,6 +4810,142 @@ remove_preds_and_fake_succs (constraint_graph_t graph)
   bitmap_obstack_release (&predbitmap_obstack);
 }
 
   bitmap_obstack_release (&predbitmap_obstack);
 }
 
+/* Compute the set of variables we can't TBAA prune.  */
+
+static void
+compute_tbaa_pruning (void)
+{
+  unsigned int size = VEC_length (varinfo_t, varmap);
+  unsigned int i;
+  bool any;
+
+  changed_count = 0;
+  changed = sbitmap_alloc (size);
+  sbitmap_zero (changed);
+
+  /* Mark all initial no_tbaa_pruning nodes as changed.  */
+  any = false;
+  for (i = 0; i < size; ++i)
+    {
+      varinfo_t ivi = get_varinfo (i);
+
+      if (find (i) == i && ivi->no_tbaa_pruning)
+       {
+         any = true;
+         if ((graph->succs[i] && !bitmap_empty_p (graph->succs[i]))
+             || VEC_length (constraint_t, graph->complex[i]) > 0)
+           {
+             SET_BIT (changed, i);
+             ++changed_count;
+           }
+       }
+    }
+
+  while (changed_count > 0)
+    {
+      struct topo_info *ti = init_topo_info ();
+      ++stats.iterations;
+
+      bitmap_obstack_initialize (&iteration_obstack);
+
+      compute_topo_order (graph, ti);
+
+      while (VEC_length (unsigned, ti->topo_order) != 0)
+       {
+         bitmap_iterator bi;
+
+         i = VEC_pop (unsigned, ti->topo_order);
+
+         /* If this variable is not a representative, skip it.  */
+         if (find (i) != i)
+           continue;
+
+         /* If the node has changed, we need to process the complex
+            constraints and outgoing edges again.  */
+         if (TEST_BIT (changed, i))
+           {
+             unsigned int j;
+             constraint_t c;
+             VEC(constraint_t,heap) *complex = graph->complex[i];
+
+             RESET_BIT (changed, i);
+             --changed_count;
+
+             /* Process the complex copy constraints.  */
+             for (j = 0; VEC_iterate (constraint_t, complex, j, c); ++j)
+               {
+                 if (c->lhs.type == SCALAR && c->rhs.type == SCALAR)
+                   {
+                     varinfo_t lhsvi = get_varinfo (find (c->lhs.var));
+
+                     if (!lhsvi->no_tbaa_pruning)
+                       {
+                         lhsvi->no_tbaa_pruning = true;
+                         if (!TEST_BIT (changed, lhsvi->id))
+                           {
+                             SET_BIT (changed, lhsvi->id);
+                             ++changed_count;
+                           }
+                       }
+                   }
+               }
+
+             /* Propagate to all successors.  */
+             EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i], 0, j, bi)
+               {
+                 unsigned int to = find (j);
+                 varinfo_t tovi = get_varinfo (to);
+
+                 /* Don't propagate to ourselves.  */
+                 if (to == i)
+                   continue;
+
+                 if (!tovi->no_tbaa_pruning)
+                   {
+                     tovi->no_tbaa_pruning = true;
+                     if (!TEST_BIT (changed, to))
+                       {
+                         SET_BIT (changed, to);
+                         ++changed_count;
+                       }
+                   }
+               }
+           }
+       }
+
+      free_topo_info (ti);
+      bitmap_obstack_release (&iteration_obstack);
+    }
+
+  sbitmap_free (changed);
+
+  if (any)
+    {
+      for (i = 0; i < size; ++i)
+       {
+         varinfo_t ivi = get_varinfo (i);
+         varinfo_t ivip = get_varinfo (find (i));
+
+         if (ivip->no_tbaa_pruning)
+           {
+             tree var = ivi->decl;
+
+             if (TREE_CODE (var) == SSA_NAME)
+               var = SSA_NAME_VAR (var);
+
+             if (POINTER_TYPE_P (TREE_TYPE (var)))
+               {
+                 DECL_NO_TBAA_P (var) = 1;
+
+                 /* Tell the RTL layer that this pointer can alias
+                    anything.  */
+                 DECL_POINTER_ALIAS_SET (var) = 0;
+               }
+           }
+       }
+    }
+}
+
 /* Create points-to sets for the current function.  See the comments
    at the start of the file for an algorithmic overview.  */
 
 /* Create points-to sets for the current function.  See the comments
    at the start of the file for an algorithmic overview.  */
 
@@ -4793,7 +4968,7 @@ compute_points_to_sets (struct alias_info *ai)
       block_stmt_iterator bsi;
       tree phi;
 
       block_stmt_iterator bsi;
       tree phi;
 
-      for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
        {
          if (is_gimple_reg (PHI_RESULT (phi)))
            {
        {
          if (is_gimple_reg (PHI_RESULT (phi)))
            {
@@ -4807,7 +4982,7 @@ compute_points_to_sets (struct alias_info *ai)
            }
        }
 
            }
        }
 
-      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+      for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
        {
          tree stmt = bsi_stmt (bsi);
 
        {
          tree stmt = bsi_stmt (bsi);
 
@@ -4818,6 +4993,13 @@ compute_points_to_sets (struct alias_info *ai)
             This is used when creating name tags and alias
             sets.  */
          update_alias_info (stmt, ai);
             This is used when creating name tags and alias
             sets.  */
          update_alias_info (stmt, ai);
+
+         /* The information in CHANGE_DYNAMIC_TYPE_EXPR nodes has now
+            been captured, and we can remove them.  */
+         if (TREE_CODE (stmt) == CHANGE_DYNAMIC_TYPE_EXPR)
+           bsi_remove (&bsi, true);
+         else
+           bsi_next (&bsi);
        }
     }
 
        }
     }
 
@@ -4849,6 +5031,8 @@ compute_points_to_sets (struct alias_info *ai)
 
   solve_graph (graph);
 
 
   solve_graph (graph);
 
+  compute_tbaa_pruning ();
+
   if (dump_file)
     dump_sa_points_to_info (dump_file);
 
   if (dump_file)
     dump_sa_points_to_info (dump_file);
 
@@ -4877,6 +5061,7 @@ delete_points_to_sets (void)
 
   for (i = 0; VEC_iterate (varinfo_t, varmap, i, v); i++)
     VEC_free (constraint_t, heap, graph->complex[i]);
 
   for (i = 0; VEC_iterate (varinfo_t, varmap, i, v); i++)
     VEC_free (constraint_t, heap, graph->complex[i]);
+  free (graph->complex);
 
   free (graph->rep);
   free (graph->succs);
 
   free (graph->rep);
   free (graph->succs);
@@ -4945,7 +5130,7 @@ ipa_pta_execute (void)
              block_stmt_iterator bsi;
              tree phi;
 
              block_stmt_iterator bsi;
              tree phi;
 
-             for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+             for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
                {
                  if (is_gimple_reg (PHI_RESULT (phi)))
                    {
                {
                  if (is_gimple_reg (PHI_RESULT (phi)))
                    {