OSDN Git Service

2004-12-05 Daniel Berlin <dberlin@dberlin.org>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-alias.c
index 4640f1f..b321d26 100644 (file)
@@ -195,7 +195,8 @@ tree global_var;
    The concept of 'escaping' is the same one used in the Java world.  When
    a pointer or an ADDR_EXPR escapes, it means that it has been exposed
    outside of the current function.  So, assignment to global variables,
-   function arguments and returning a pointer are all escape sites.
+   function arguments and returning a pointer are all escape sites, as are
+   conversions between pointers and integers.
 
    This is where we are currently limited.  Since not everything is renamed
    into SSA, we lose track of escape properties when a pointer is stashed
@@ -357,6 +358,62 @@ struct tree_opt_pass pass_may_alias =
   0                                    /* letter */
 };
 
+/* Count the number of calls in the function and conditionally
+   create GLOBAL_VAR.   This is performed before translation
+   into SSA (and thus before alias analysis) to avoid compile time
+   and memory utilization explosions in functions with many
+   of calls and call clobbered variables.  */
+
+static void
+count_calls_and_maybe_create_global_var (void)
+{
+  struct alias_info ai;
+  basic_block bb;
+  bool temp;
+
+  memset (&ai, 0, sizeof (struct alias_info));
+
+  /* First count the number of calls in the IL.  */
+  FOR_EACH_BB (bb)
+    {
+      block_stmt_iterator si;
+
+      for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+        {
+          tree stmt = bsi_stmt (si);
+
+         if (get_call_expr_in (stmt) != NULL_TREE)
+           ai.num_calls_found++;
+       }
+    }
+
+  /* If there are no call clobbered variables, then maybe_create_global_var
+     will always create a GLOBAL_VAR.  At this point we do not want that
+     behavior.  So we turn on one bit in CALL_CLOBBERED_VARs, call
+     maybe_create_global_var, then reset the bit to its original state.  */
+  temp = bitmap_bit_p (call_clobbered_vars, 0);
+  bitmap_set_bit (call_clobbered_vars, 0);
+  maybe_create_global_var (&ai);
+  if (!temp)
+    bitmap_clear_bit (call_clobbered_vars, 0);
+}
+
+struct tree_opt_pass pass_maybe_create_global_var = 
+{
+  "maybe_create_global_var",           /* name */
+  NULL,                                        /* gate */
+  count_calls_and_maybe_create_global_var, /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_TREE_MAY_ALIAS,                   /* tv_id */
+  PROP_cfg,                            /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  0,                                   /* todo_flags_finish */
+  0                                    /* letter */
+};
 
 /* Initialize the data structures used for alias analysis.  */
 
@@ -381,6 +438,20 @@ init_alias_info (void)
     {
       unsigned i;
       bitmap_iterator bi;
+      basic_block bb;
+  
+     /* Make sure that every statement has a valid set of operands.
+       If a statement needs to be scanned for operands while we
+       compute aliases, it may get erroneous operands because all
+       the alias relations are not built at that point.
+       FIXME: This code will become obsolete when operands are not
+       lazily updated.  */
+      FOR_EACH_BB (bb)
+       {
+         block_stmt_iterator si;
+         for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+           get_stmt_operands (bsi_stmt (si));
+       }
 
       /* Clear the call-clobbered set.  We are going to re-discover
          call-clobbered variables.  */
@@ -606,22 +677,6 @@ compute_points_to_and_addr_escape (struct alias_info *ai)
          if (stmt_escapes_p)
            block_ann->has_escape_site = 1;
 
-         /* Special case for silly ADDR_EXPR tricks
-            (gcc.c-torture/unsorted/pass.c).  If this statement is an
-            assignment to a non-pointer variable and the RHS takes the
-            address of a variable, assume that the variable on the RHS is
-            call-clobbered.  We could add the LHS to the list of
-            "pointers" and follow it to see if it really escapes, but it's
-            not worth the pain.  */
-         if (addr_taken
-             && TREE_CODE (stmt) == MODIFY_EXPR
-             && !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (stmt, 0))))
-           EXECUTE_IF_SET_IN_BITMAP (addr_taken, 0, i, bi)
-             {
-               tree var = referenced_var (i);
-               mark_call_clobbered (var);
-             }
-
          FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
            {
              var_ann_t v_ann = var_ann (SSA_NAME_VAR (op));
@@ -886,7 +941,6 @@ static void
 compute_flow_insensitive_aliasing (struct alias_info *ai)
 {
   size_t i;
-  sbitmap res;
 
   /* Initialize counter for the total number of virtual operands that
      aliasing will introduce.  When AI->TOTAL_ALIAS_VOPS goes beyond the
@@ -980,8 +1034,6 @@ compute_flow_insensitive_aliasing (struct alias_info *ai)
      To avoid this problem, we do a final traversal of AI->POINTERS
      looking for pairs of pointers that have no aliased symbols in
      common and yet have conflicting alias set numbers.  */
-  res = sbitmap_alloc (num_referenced_vars);
-
   for (i = 0; i < ai->num_pointers; i++)
     {
       size_t j;
@@ -1001,8 +1053,7 @@ compute_flow_insensitive_aliasing (struct alias_info *ai)
 
          /* The two pointers may alias each other.  If they already have
             symbols in common, do nothing.  */
-         sbitmap_a_and_b (res, may_aliases1, may_aliases2);
-         if (sbitmap_first_set_bit (res) >= 0)
+         if (sbitmap_any_common_bits (may_aliases1, may_aliases2))
            continue;
 
          if (sbitmap_first_set_bit (may_aliases2) >= 0)
@@ -1024,8 +1075,6 @@ compute_flow_insensitive_aliasing (struct alias_info *ai)
        }
     }
 
-  sbitmap_free (res);
-
   if (dump_file)
     fprintf (dump_file, "%s: Total number of aliased vops: %ld\n",
             get_name (current_function_decl),
@@ -1168,15 +1217,12 @@ static void
 group_aliases (struct alias_info *ai)
 {
   size_t i;
-  sbitmap res;
 
   /* Sort the POINTERS array in descending order of contributed
      virtual operands.  */
   qsort (ai->pointers, ai->num_pointers, sizeof (struct alias_map_d *),
          total_alias_vops_cmp);
 
-  res = sbitmap_alloc (num_referenced_vars);
-
   /* For every pointer in AI->POINTERS, reverse the roles of its tag
      and the tag's may-aliases set.  */
   for (i = 0; i < ai->num_pointers; i++)
@@ -1196,8 +1242,7 @@ group_aliases (struct alias_info *ai)
        {
          sbitmap tag2_aliases = ai->pointers[j]->may_aliases;
 
-         sbitmap_a_and_b (res, tag1_aliases, tag2_aliases);
-         if (sbitmap_first_set_bit (res) >= 0)
+          if (sbitmap_any_common_bits (tag1_aliases, tag2_aliases))
            {
              tree tag2 = var_ann (ai->pointers[j]->var)->type_mem_tag;
 
@@ -1267,8 +1312,6 @@ group_aliases (struct alias_info *ai)
        }
     }
 
-  sbitmap_free (res);
-
   if (dump_file)
     fprintf (dump_file,
             "%s: Total number of aliased vops after grouping: %ld%s\n",
@@ -1993,6 +2036,16 @@ is_escape_site (tree stmt, size_t *num_calls_p)
       if (lhs == NULL_TREE)
        return true;
 
+      /* If the RHS is a conversion between a pointer and an integer, the
+        pointer escapes since we can't track the integer.  */
+      if ((TREE_CODE (TREE_OPERAND (stmt, 1)) == NOP_EXPR
+          || TREE_CODE (TREE_OPERAND (stmt, 1)) == CONVERT_EXPR
+          || TREE_CODE (TREE_OPERAND (stmt, 1)) == VIEW_CONVERT_EXPR)
+         && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND
+                                       (TREE_OPERAND (stmt, 1), 0)))
+         && !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (stmt, 1))))
+       return true;
+
       /* If the LHS is an SSA name, it can't possibly represent a non-local
         memory store.  */
       if (TREE_CODE (lhs) == SSA_NAME)
@@ -2148,7 +2201,7 @@ static void
 create_global_var (void)
 {
   global_var = build_decl (VAR_DECL, get_identifier (".GLOBAL_VAR"),
-                           size_type_node);
+                           void_type_node);
   DECL_ARTIFICIAL (global_var) = 1;
   TREE_READONLY (global_var) = 0;
   DECL_EXTERNAL (global_var) = 1;