OSDN Git Service

2008-05-01 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-structalias.c
index 479145a..ddcf498 100644 (file)
@@ -1428,9 +1428,6 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
          else if (add_graph_edge (graph, lhs, t))
            flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
        }
-      else if (0 && dump_file && !(get_varinfo (j)->is_special_var))
-       fprintf (dump_file, "Untypesafe usage in do_sd_constraint\n");
-
     }
 
 done:
@@ -1514,8 +1511,6 @@ do_ds_constraint (constraint_t c, bitmap delta)
                }
            }
        }
-      else if (0 && dump_file && !(get_varinfo (j)->is_special_var))
-       fprintf (dump_file, "Untypesafe usage in do_ds_constraint\n");
     }
 }
 
@@ -2630,25 +2625,6 @@ bitpos_of_field (const tree fdecl)
 }
 
 
-/* Return true if an access to [ACCESSPOS, ACCESSSIZE]
-   overlaps with a field at [FIELDPOS, FIELDSIZE] */
-
-static bool
-offset_overlaps_with_access (const unsigned HOST_WIDE_INT fieldpos,
-                            const unsigned HOST_WIDE_INT fieldsize,
-                            const unsigned HOST_WIDE_INT accesspos,
-                            const unsigned HOST_WIDE_INT accesssize)
-{
-  if (fieldpos == accesspos && fieldsize == accesssize)
-    return true;
-  if (accesspos >= fieldpos && accesspos < (fieldpos + fieldsize))
-    return true;
-  if (accesspos < fieldpos && (accesspos + accesssize > fieldpos))
-    return true;
-
-  return false;
-}
-
 /* Given a COMPONENT_REF T, return the constraint_expr for it.  */
 
 static void
@@ -2681,11 +2657,6 @@ get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results)
 
   t = get_ref_base_and_extent (t, &bitpos, &bitsize, &bitmaxsize);
 
-  /* String constants are readonly, so there is nothing to really do
-     here.  */
-  if (TREE_CODE (t) == STRING_CST)
-    return;
-
   get_constraint_for (t, results);
   result = VEC_last (ce_s, *results);
   result->offset = bitpos;
@@ -2713,8 +2684,8 @@ get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results)
          varinfo_t curr;
          for (curr = get_varinfo (result->var); curr; curr = curr->next)
            {
-             if (offset_overlaps_with_access (curr->offset, curr->size,
-                                              result->offset, bitmaxsize))
+             if (ranges_overlap_p (curr->offset, curr->size,
+                                   result->offset, bitmaxsize))
                {
                  result->var = curr->id;
                  break;
@@ -2803,6 +2774,16 @@ get_constraint_for (tree t, VEC (ce_s, heap) **results)
       return;
     }
 
+  /* String constants are read-only.  */
+  if (TREE_CODE (t) == STRING_CST)
+    {
+      temp.var = readonly_id;
+      temp.type = SCALAR;
+      temp.offset = 0;
+      VEC_safe_push (ce_s, heap, *results, &temp);
+      return;
+    }
+
   switch (TREE_CODE_CLASS (TREE_CODE (t)))
     {
     case tcc_expression:
@@ -2932,7 +2913,6 @@ get_constraint_for (tree t, VEC (ce_s, heap) **results)
          {
          case NOP_EXPR:
          case CONVERT_EXPR:
-         case NON_LVALUE_EXPR:
            {
              tree op = TREE_OPERAND (t, 0);
 
@@ -4053,19 +4033,22 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
    TYPE.
 
    ADDRESSABLE_TYPE is the type of the outermost object that could
-   have its address taken.
-
-   NESTING_LEVEL indicates whether TYPE is a structure nested inside
-   another, it starts at 0 and it is incremented by one on every
-   structure recursed into.  */
+   have its address taken.  */
 
 int
 push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
                             HOST_WIDE_INT offset, bool *has_union,
-                            tree addressable_type, unsigned nesting_level)
+                            tree addressable_type)
 {
   tree field;
   int count = 0;
+  unsigned int first_element = VEC_length (fieldoff_s, *fieldstack);
+
+  /* If the vector of fields is growing too big, bail out early.
+     Callers check for VEC_length <= MAX_FIELDS_FOR_FIELD_SENSITIVE, make
+     sure this fails.  */
+  if (first_element > MAX_FIELDS_FOR_FIELD_SENSITIVE)
+    return 0;
 
   if (TREE_CODE (type) == COMPLEX_TYPE)
     {
@@ -4076,6 +4059,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
       real_part->offset = offset;
       real_part->decl = NULL_TREE;
       real_part->alias_set = -1;
+      real_part->base_for_components = false;
 
       img_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
       img_part->type = TREE_TYPE (type);
@@ -4083,11 +4067,12 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
       img_part->offset = offset + TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (type)));
       img_part->decl = NULL_TREE;
       img_part->alias_set = -1;
+      img_part->base_for_components = false;
 
-      return 2;
+      count = 2;
     }
 
-  if (TREE_CODE (type) == ARRAY_TYPE)
+  else if (TREE_CODE (type) == ARRAY_TYPE)
     {
       tree sz = TYPE_SIZE (type);
       tree elsz = TYPE_SIZE (TREE_TYPE (type));
@@ -4125,8 +4110,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
                      has_union,
                      (TYPE_NONALIASED_COMPONENT (type)
                       ? addressable_type
-                      : TREE_TYPE (type)),
-                     nesting_level + 1)))
+                      : TREE_TYPE (type)))))
            /* Empty structures may have actual size, like in C++. So
               see if we didn't push any subfields and the size is
               nonzero, push the field onto the stack */
@@ -4145,64 +4129,69 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
                pair->alias_set = get_alias_set (addressable_type);
              else
                pair->alias_set = -1;
-             pair->nesting_level = nesting_level;
+             pair->base_for_components = false;
              count++;
            }
          else
            count += pushed;
        }
-
-      return count;
     }
 
-  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
-    if (TREE_CODE (field) == FIELD_DECL)
-      {
-       bool push = false;
-       int pushed = 0;
-
-       if (has_union
-           && (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
-               || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
-         *has_union = true;
-
-       if (!var_can_have_subvars (field))
-         push = true;
-       else if (!(pushed = push_fields_onto_fieldstack
-                  (TREE_TYPE (field),
-                   fieldstack,
-                   offset + bitpos_of_field (field),
-                   has_union,
-                   (DECL_NONADDRESSABLE_P (field)
-                    ? addressable_type
-                    : TREE_TYPE (field)),
-                   nesting_level + 1))
-                && DECL_SIZE (field)
-                && !integer_zerop (DECL_SIZE (field)))
-         /* Empty structures may have actual size, like in C++. So
-            see if we didn't push any subfields and the size is
-            nonzero, push the field onto the stack */
-         push = true;
-
-       if (push)
+  else
+    {
+      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+       if (TREE_CODE (field) == FIELD_DECL)
          {
-           fieldoff_s *pair;
-
-           pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
-           pair->type = TREE_TYPE (field);
-           pair->size = DECL_SIZE (field);
-           pair->decl = field;
-           pair->offset = offset + bitpos_of_field (field);
-           if (DECL_NONADDRESSABLE_P (field))
-             pair->alias_set = get_alias_set (addressable_type);
+           bool push = false;
+           int pushed = 0;
+
+           if (has_union
+               && (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
+                   || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
+             *has_union = true;
+
+           if (!var_can_have_subvars (field))
+             push = true;
+           else if (!(pushed = push_fields_onto_fieldstack
+                      (TREE_TYPE (field),
+                       fieldstack,
+                       offset + bitpos_of_field (field),
+                       has_union,
+                       (DECL_NONADDRESSABLE_P (field)
+                        ? addressable_type
+                        : TREE_TYPE (field))))
+                    && DECL_SIZE (field)
+                    && !integer_zerop (DECL_SIZE (field)))
+             /* Empty structures may have actual size, like in C++. So
+                see if we didn't push any subfields and the size is
+                nonzero, push the field onto the stack */
+             push = true;
+
+           if (push)
+             {
+               fieldoff_s *pair;
+
+               pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
+               pair->type = TREE_TYPE (field);
+               pair->size = DECL_SIZE (field);
+               pair->decl = field;
+               pair->offset = offset + bitpos_of_field (field);
+               if (DECL_NONADDRESSABLE_P (field))
+                 pair->alias_set = get_alias_set (addressable_type);
+               else
+                 pair->alias_set = -1;
+               pair->base_for_components = false;
+               count++;
+             }
            else
-             pair->alias_set = -1;
-           pair->nesting_level = nesting_level;
-           count++;
-         }
-       else
-         count += pushed;
-      }
+             count += pushed;
+          }
+    }
+
+  /* Make sure the first pushed field is marked as eligible for
+     being a base for component references.  */
+  if (count > 0)
+    VEC_index (fieldoff_s, *fieldstack, first_element)->base_for_components = true;
 
   return count;
 }
@@ -4397,7 +4386,7 @@ create_variable_info_for (tree decl, const char *name)
   if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion)
     {
       push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion,
-                                  decltype, 0);
+                                  decltype);
       if (hasunion)
        {
          VEC_free (fieldoff_s, heap, fieldstack);
@@ -4438,6 +4427,7 @@ create_variable_info_for (tree decl, const char *name)
       && !notokay
       && !vi->is_unknown_size_var
       && var_can_have_subvars (decl)
+      && VEC_length (fieldoff_s, fieldstack) > 1
       && VEC_length (fieldoff_s, fieldstack) <= MAX_FIELDS_FOR_FIELD_SENSITIVE)
     {
       unsigned int newindex = VEC_length (varinfo_t, varmap);
@@ -4719,7 +4709,10 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
 {
   unsigned int i;
   bitmap_iterator bi;
-  alias_set_type ptr_alias_set = get_alias_set (TREE_TYPE (ptr));
+  alias_set_type ptr_alias_set;
+
+  gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
+  ptr_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
 
   EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
     {
@@ -4746,15 +4739,24 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
               || TREE_CODE (vi->decl) == PARM_DECL
               || TREE_CODE (vi->decl) == RESULT_DECL)
        {
+         subvar_t sv;
          if (var_can_have_subvars (vi->decl)
-             && get_subvars_for_var (vi->decl))
+             && (sv = get_subvars_for_var (vi->decl)))
            {
              /* If VI->DECL is an aggregate for which we created
-                SFTs, add the SFT corresponding to VI->OFFSET.  */
-             tree sft = get_subvar_at (vi->decl, vi->offset);
+                SFTs, add the SFT corresponding to VI->OFFSET.
+                If we didn't do field-sensitive PTA we need to to
+                add all overlapping SFTs.  */
+             unsigned int j;
+             tree sft = get_first_overlapping_subvar (sv, vi->offset,
+                                                      vi->size, &j);
              gcc_assert (sft);
-             if (sft)
+             for (; VEC_iterate (tree, sv, j, sft); ++j)
                {
+                 if (SFT_OFFSET (sft) > vi->offset
+                     && vi->size <= SFT_OFFSET (sft) - vi->offset)
+                   break;
+
                  var_alias_set = get_alias_set (sft);
                  if (no_tbaa_pruning
                      || (!is_derefed && !vi->directly_dereferenced)
@@ -4762,15 +4764,15 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
                    {
                      bitmap_set_bit (into, DECL_UID (sft));
                      
-                     /* If SFT is inside a nested structure, it will
-                        be needed by the operand scanner to adjust
-                        offsets when adding operands to memory
+                     /* Pointed-to SFTs are needed by the operand scanner
+                        to adjust offsets when adding operands to memory
                         expressions that dereference PTR.  This means
                         that memory partitioning may not partition
                         this SFT because the operand scanner will not
                         be able to find the other SFTs next to this
-                        one.  */
-                     if (SFT_NESTING_LEVEL (sft) > 0)
+                        one.  But we only need to do this if the pointed
+                        to type is aggregate.  */
+                     if (SFT_BASE_FOR_COMPONENTS_P (sft))
                        SFT_UNPARTITIONABLE_P (sft) = true;
                    }
                }
@@ -4859,8 +4861,6 @@ set_used_smts (void)
 static void
 merge_smts_into (tree p, bitmap solution)
 {
-  unsigned int i;
-  bitmap_iterator bi;
   tree smt;
   bitmap aliases;
   tree var = p;
@@ -4871,20 +4871,8 @@ merge_smts_into (tree p, bitmap solution)
   smt = var_ann (var)->symbol_mem_tag;
   if (smt)
     {
-      alias_set_type smtset = get_alias_set (TREE_TYPE (smt));
-
-      /* Need to set the SMT subsets first before this
-        will work properly.  */
+      /* The smt itself isn't included in its aliases.  */
       bitmap_set_bit (solution, DECL_UID (smt));
-      EXECUTE_IF_SET_IN_BITMAP (used_smts, 0, i, bi)
-       {
-         tree newsmt = referenced_var (i);
-         tree newsmttype = TREE_TYPE (newsmt);
-
-         if (alias_set_subset_of (get_alias_set (newsmttype),
-                                  smtset))
-           bitmap_set_bit (solution, i);
-       }
 
       aliases = MTAG_ALIASES (smt);
       if (aliases)
@@ -4981,22 +4969,14 @@ find_what_p_points_to (tree p)
 
          /* 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.  */
+            pointed to anything, they could point to global memory.  */
          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;
            }
 
-         set_uids_in_ptset (vi->decl, finished_solution, vi->solution,
+         set_uids_in_ptset (p, finished_solution, vi->solution,
                             vi->directly_dereferenced,
                             vi->no_tbaa_pruning);
          result = shared_bitmap_lookup (finished_solution);
@@ -5549,17 +5529,17 @@ ipa_pta_execute (void)
     {
       if (node->analyzed && cgraph_is_master_clone (node))
        {
-         struct function *cfun = DECL_STRUCT_FUNCTION (node->decl);
+         struct function *func = DECL_STRUCT_FUNCTION (node->decl);
          basic_block bb;
          tree old_func_decl = current_function_decl;
          if (dump_file)
            fprintf (dump_file,
                     "Generating constraints for %s\n",
                     cgraph_node_name (node));
-         push_cfun (cfun);
+         push_cfun (func);
          current_function_decl = node->decl;
 
-         FOR_EACH_BB_FN (bb, cfun)
+         FOR_EACH_BB_FN (bb, func)
            {
              block_stmt_iterator bsi;
              tree phi;
@@ -5627,8 +5607,10 @@ ipa_pta_execute (void)
   return 0;
 }
 
-struct tree_opt_pass pass_ipa_pta =
+struct simple_ipa_opt_pass pass_ipa_pta =
 {
+ {
+  SIMPLE_IPA_PASS,
   "pta",                               /* name */
   gate_ipa_pta,                        /* gate */
   ipa_pta_execute,                     /* execute */
@@ -5640,8 +5622,8 @@ struct tree_opt_pass pass_ipa_pta =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_update_ssa,                      /* todo_flags_finish */
-  0                                    /* letter */
+  TODO_update_ssa                       /* todo_flags_finish */
+ }
 };
 
 /* Initialize the heapvar for statement mapping.  */