tree-ssa-structalias.c (struct variable_info): Remove has_union.
authorRichard Guenther <rguenther@suse.de>
Sun, 6 Jul 2008 18:38:15 +0000 (18:38 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sun, 6 Jul 2008 18:38:15 +0000 (18:38 +0000)
2008-07-06  Richard Guenther  <rguenther@suse.de>

* tree-ssa-structalias.c (struct variable_info): Remove has_union.
(new_var_info): Deal with it.
(solution_set_add): Likewise.
(bitpos_of_field): Make signed, fix.
(struct fieldoff): Remove type and decl fields.  Make size field
unsigned HOST_WIDE_INT.  Add has_unknown_size and may_have_pointers
flags.
(fieldoff_compare): Deal with it.
(push_fields_onto_fieldstack): Remove has_union argument, glob
adjacent non-pointer fields together.
(create_function_info_for): Do not set has_union.
(create_variable_info_for): Simplify.

* gcc.dg/tree-ssa/pta-callused.c: Adjust testcase.

From-SVN: r137530

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c
gcc/tree-ssa-structalias.c

index 9ee6347..3dd4618 100644 (file)
@@ -1,3 +1,18 @@
+2008-07-06  Richard Guenther  <rguenther@suse.de>
+
+       * tree-ssa-structalias.c (struct variable_info): Remove has_union.
+       (new_var_info): Deal with it.
+       (solution_set_add): Likewise.
+       (bitpos_of_field): Make signed, fix.
+       (struct fieldoff): Remove type and decl fields.  Make size field
+       unsigned HOST_WIDE_INT.  Add has_unknown_size and may_have_pointers
+       flags.
+       (fieldoff_compare): Deal with it.
+       (push_fields_onto_fieldstack): Remove has_union argument, glob
+       adjacent non-pointer fields together.
+       (create_function_info_for): Do not set has_union.
+       (create_variable_info_for): Simplify.
+
 2008-07-06  Kai Tietz  <kai.tietz@onevision.com>
 
        * config.gcc (extra_headers): Add cross-stdarg.h for target
index cf6ba6b..25c118e 100644 (file)
@@ -1,3 +1,7 @@
+2008-07-06  Richard Guenther  <rguenther@suse.de>
+
+       * gcc.dg/tree-ssa/pta-callused.c: Adjust testcase.
+
 2008-07-06  Kai Tietz  <kai.tietz@onevision.com>
 
        * gcc.dg/callabi/callabi.h: New.
index 44d095a..c2b512a 100644 (file)
@@ -22,6 +22,6 @@ int bar (int b)
   return foo (&q);
 }
 
-/* { dg-final { scan-tree-dump "CALLUSED = { f f.q i q }" "alias" } } */
+/* { dg-final { scan-tree-dump "CALLUSED = { f.* i q }" "alias" } } */
 /* { dg-final { cleanup-tree-dump "alias" } } */
 
index 0b68b84..266538c 100644 (file)
@@ -220,9 +220,6 @@ struct variable_info
   /* True for variables whose size is not known or variable.  */
   unsigned int is_unknown_size_var:1;
 
-  /* True for variables that have unions somewhere in them.  */
-  unsigned int has_union:1;
-
   /* True if this is a heap variable.  */
   unsigned int is_heap_var:1;
 
@@ -376,7 +373,6 @@ new_var_info (tree t, unsigned int id, const char *name)
   ret->is_heap_var = 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);
@@ -769,7 +765,6 @@ solution_set_add (bitmap set, unsigned HOST_WIDE_INT offset)
          bitmap_set_bit (result, v->id);
        }
       else if (get_varinfo (i)->is_artificial_var
-              || get_varinfo (i)->has_union
               || get_varinfo (i)->is_unknown_size_var)
        {
          bitmap_set_bit (result, i);
@@ -2670,16 +2665,16 @@ could_have_pointers (tree t)
 /* Return the position, in bits, of FIELD_DECL from the beginning of its
    structure.  */
 
-static unsigned HOST_WIDE_INT
+static HOST_WIDE_INT
 bitpos_of_field (const tree fdecl)
 {
 
-  if (TREE_CODE (DECL_FIELD_OFFSET (fdecl)) != INTEGER_CST
-      || TREE_CODE (DECL_FIELD_BIT_OFFSET (fdecl)) != INTEGER_CST)
+  if (!host_integerp (DECL_FIELD_OFFSET (fdecl), 0)
+      || !host_integerp (DECL_FIELD_BIT_OFFSET (fdecl), 0))
     return -1;
 
-  return (tree_low_cst (DECL_FIELD_OFFSET (fdecl), 1) * 8)
-        + tree_low_cst (DECL_FIELD_BIT_OFFSET (fdecl), 1);
+  return (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (fdecl)) * 8
+         + TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (fdecl)));
 }
 
 
@@ -4005,17 +4000,15 @@ insert_into_field_list_sorted (varinfo_t base, varinfo_t field)
 
 struct fieldoff
 {
-  /* Type of the field.  */
-  tree type;
+  /* Offset from the base of the base containing object to this field.  */
+  HOST_WIDE_INT offset;
 
   /* Size, in bits, of the field.  */
-  tree size;
+  unsigned HOST_WIDE_INT size;
 
-  /* Field.  */
-  tree decl;
+  unsigned has_unknown_size : 1;
 
-  /* Offset from the base of the base containing object to this field.  */
-  HOST_WIDE_INT offset;  
+  unsigned may_have_pointers : 1;
 };
 typedef struct fieldoff fieldoff_s;
 
@@ -4036,10 +4029,10 @@ fieldoff_compare (const void *pa, const void *pb)
   else if (foa->offset > fob->offset)
     return 1;
 
-  foasize = TREE_INT_CST_LOW (foa->size);
-  fobsize = TREE_INT_CST_LOW (fob->size);
+  foasize = foa->size;
+  fobsize = fob->size;
   if (foasize < fobsize)
-    return - 1;
+    return -1;
   else if (foasize > fobsize)
     return 1;
   return 0;
@@ -4083,14 +4076,11 @@ var_can_have_subvars (const_tree v)
 
    OFFSET is used to keep track of the offset in this entire
    structure, rather than just the immediately containing structure.
-   Returns the number of fields pushed.
-
-   HAS_UNION is set to true if we find a union type as a field of
-   TYPE.  */
+   Returns the number of fields pushed.  */
 
 static int
 push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
-                            HOST_WIDE_INT offset, bool *has_union)
+                            HOST_WIDE_INT offset)
 {
   tree field;
   int count = 0;
@@ -4109,19 +4099,14 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
       {
        bool push = false;
        int pushed = 0;
+       HOST_WIDE_INT foff = bitpos_of_field (field);
 
-       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))
+       if (!var_can_have_subvars (field)
+           || TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
+           || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
          push = true;
        else if (!(pushed = push_fields_onto_fieldstack
-                  (TREE_TYPE (field),
-                   fieldstack,
-                   offset + bitpos_of_field (field),
-                   has_union))
+                  (TREE_TYPE (field), fieldstack, offset + foff))
                 && (DECL_SIZE (field)
                     && !integer_zerop (DECL_SIZE (field))))
          /* Empty structures may have actual size, like in C++.  So
@@ -4131,14 +4116,39 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
 
        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);
-           count++;
+           fieldoff_s *pair = NULL;
+           bool has_unknown_size = false;
+
+           if (!VEC_empty (fieldoff_s, *fieldstack))
+             pair = VEC_last (fieldoff_s, *fieldstack);
+
+           if (!DECL_SIZE (field)
+               || !host_integerp (DECL_SIZE (field), 1))
+             has_unknown_size = true;
+
+           /* If adjacent fields do not contain pointers merge them.  */
+           if (pair
+               && !pair->may_have_pointers
+               && !could_have_pointers (field)
+               && !pair->has_unknown_size
+               && !has_unknown_size
+               && pair->offset + (HOST_WIDE_INT)pair->size == offset + foff)
+             {
+               pair = VEC_last (fieldoff_s, *fieldstack);
+               pair->size += TREE_INT_CST_LOW (DECL_SIZE (field));
+             }
+           else
+             {
+               pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
+               pair->offset = offset + foff;
+               pair->has_unknown_size = has_unknown_size;
+               if (!has_unknown_size)
+                 pair->size = TREE_INT_CST_LOW (DECL_SIZE (field));
+               else
+                 pair->size = -1;
+               pair->may_have_pointers = could_have_pointers (field);
+               count++;
+             }
          }
        else
          count += pushed;
@@ -4204,7 +4214,6 @@ create_function_info_for (tree decl, const char *name)
   vi = new_var_info (decl, index, name);
   vi->decl = decl;
   vi->offset = 0;
-  vi->has_union = 0;
   vi->size = 1;
   vi->fullsize = count_num_arguments (decl, &is_varargs) + 1;
   insert_vi_for_tree (vi->decl, vi);
@@ -4249,7 +4258,6 @@ create_function_info_for (tree decl, const char *name)
       argvi->offset = i;
       argvi->size = 1;
       argvi->fullsize = vi->fullsize;
-      argvi->has_union = false;
       insert_into_field_list_sorted (vi, argvi);
       stats.total_vars ++;
       if (arg)
@@ -4285,7 +4293,6 @@ create_function_info_for (tree decl, const char *name)
       resultvi->offset = i;
       resultvi->size = 1;
       resultvi->fullsize = vi->fullsize;
-      resultvi->has_union = false;
       insert_into_field_list_sorted (vi, resultvi);
       stats.total_vars ++;
       if (DECL_RESULT (decl))
@@ -4325,25 +4332,14 @@ create_variable_info_for (tree decl, const char *name)
   varinfo_t vi;
   tree decltype = TREE_TYPE (decl);
   tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decltype);
-  bool notokay = false;
-  bool hasunion;
   bool is_global = DECL_P (decl) ? is_global_var (decl) : false;
   VEC (fieldoff_s,heap) *fieldstack = NULL;
 
   if (TREE_CODE (decl) == FUNCTION_DECL && in_ipa_mode)
     return create_function_info_for (decl, name);
 
-  hasunion = TREE_CODE (decltype) == UNION_TYPE
-            || TREE_CODE (decltype) == QUAL_UNION_TYPE;
-  if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion)
-    {
-      push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion);
-      if (hasunion)
-       {
-         VEC_free (fieldoff_s, heap, fieldstack);
-         notokay = true;
-       }
-    }
+  if (var_can_have_subvars (decl) && use_field_sensitive)
+    push_fields_onto_fieldstack (decltype, &fieldstack, 0);
 
   /* If the variable doesn't have subvars, we may end up needing to
      sort the field list and create fake variables for all the
@@ -4351,11 +4347,8 @@ create_variable_info_for (tree decl, const char *name)
   vi = new_var_info (decl, index, name);
   vi->decl = decl;
   vi->offset = 0;
-  vi->has_union = hasunion;
   if (!declsize
-      || TREE_CODE (declsize) != INTEGER_CST
-      || TREE_CODE (decltype) == UNION_TYPE
-      || TREE_CODE (decltype) == QUAL_UNION_TYPE)
+      || !host_integerp (declsize, 1))
     {
       vi->is_unknown_size_var = true;
       vi->fullsize = ~0;
@@ -4375,7 +4368,6 @@ create_variable_info_for (tree decl, const char *name)
 
   stats.total_vars++;
   if (use_field_sensitive
-      && !notokay
       && !vi->is_unknown_size_var
       && var_can_have_subvars (decl)
       && VEC_length (fieldoff_s, fieldstack) > 1
@@ -4383,12 +4375,12 @@ create_variable_info_for (tree decl, const char *name)
     {
       unsigned int newindex = VEC_length (varinfo_t, varmap);
       fieldoff_s *fo = NULL;
+      bool notokay = false;
       unsigned int i;
 
       for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
        {
-         if (! fo->size
-             || TREE_CODE (fo->size) != INTEGER_CST
+         if (fo->has_unknown_size
              || fo->offset < 0)
            {
              notokay = true;
@@ -4423,7 +4415,7 @@ create_variable_info_for (tree decl, const char *name)
          return index;
        }
 
-      vi->size = TREE_INT_CST_LOW (fo->size);
+      vi->size = fo->size;
       vi->offset = fo->offset;
       for (i = VEC_length (fieldoff_s, fieldstack) - 1;
           i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo);
@@ -4436,23 +4428,20 @@ create_variable_info_for (tree decl, const char *name)
          newindex = VEC_length (varinfo_t, varmap);
          if (dump_file)
            {
-             if (fo->decl)
-               asprintf (&tempname, "%s.%s",
-                         vi->name, alias_get_name (fo->decl));
-             else
-               asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC,
-                         vi->name, fo->offset);
+             asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC
+                       "+" HOST_WIDE_INT_PRINT_DEC,
+                       vi->name, fo->offset, fo->size);
              newname = ggc_strdup (tempname);
              free (tempname);
            }
          newvi = new_var_info (decl, newindex, newname);
          newvi->offset = fo->offset;
-         newvi->size = TREE_INT_CST_LOW (fo->size);
+         newvi->size = fo->size;
          newvi->fullsize = vi->fullsize;
          insert_into_field_list (vi, newvi);
          VEC_safe_push (varinfo_t, heap, varmap, newvi);
          if (is_global && (!flag_whole_program || !in_ipa_mode)
-             && (!fo->decl || could_have_pointers (fo->decl)))
+             && fo->may_have_pointers)
            make_constraint_from (newvi, escaped_id);
 
          stats.total_vars++;