OSDN Git Service

2005-04-06 Daniel Berlin <dberlin@dberlin.org>
authordberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Apr 2005 20:03:15 +0000 (20:03 +0000)
committerdberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Apr 2005 20:03:15 +0000 (20:03 +0000)
* params.def (PARAM_SALIAS_MAX_IMPLICIT_FIELDS): New
* params.h (SALIAS_MAX_IMPLICIT_FIELDS): New
* doc/invoke.texi: Documnet salias-max-implicit-fields.
* tree-ssa-alias.c (struct used_part): Add implicit_uses and
explicit_uses members.
(get_or_create_used_part_for): Initialize new fields.
(fieldoff_compare): New function.
(create_overlap_variables_for): Count number of fields, use
heuristic to determine whether to create subvars for vars with
only implicit uses.
Sort the field list by offset and avoid creating duplicate SFT's.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@97746 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/doc/invoke.texi
gcc/params.def
gcc/params.h
gcc/tree-ssa-alias.c

index 3d88446..aa8bcc5 100644 (file)
@@ -1,3 +1,17 @@
+2005-04-06  Daniel Berlin  <dberlin@dberlin.org>
+
+       * params.def (PARAM_SALIAS_MAX_IMPLICIT_FIELDS): New
+       * params.h (SALIAS_MAX_IMPLICIT_FIELDS): New
+       * doc/invoke.texi: Documnet salias-max-implicit-fields.
+       * tree-ssa-alias.c (struct used_part): Add implicit_uses and
+       explicit_uses members.
+       (get_or_create_used_part_for): Initialize new fields.
+       (fieldoff_compare): New function.
+       (create_overlap_variables_for): Count number of fields, use
+       heuristic to determine whether to create subvars for vars with
+       only implicit uses.
+       Sort the field list by offset and avoid creating duplicate SFT's.
+
 2005-04-06  Richard Sandiford  <rsandifo@redhat.com>
 
        * c.opt (-F): Remove trailing whitespace from help string.
index b018b27..e36aa3a 100644 (file)
@@ -5445,6 +5445,11 @@ In each case, the @var{value} is an integer.  The allowable choices for
 @var{name} are given in the following table:
 
 @table @gcctabopt
+@item salias-max-implicit-fields
+The maximum number of fields in a variable without direct
+structure accesses for which structure aliasing will consider trying 
+to track each field.  The default is 5
+
 @item sra-max-structure-size
 The maximum structure size, in bytes, at which the scalar replacement
 of aggregates (SRA) optimization will perform block copies.  The
index 2dbc197..6a90a02 100644 (file)
@@ -35,6 +35,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
    Be sure to add an entry to invoke.texi summarizing the parameter.  */
 
+/* The maximum number of fields in a variable with only implicit uses
+   for which structure aliasing will consider trying to track each
+   field.  The default is 5.  */
+DEFPARAM (PARAM_SALIAS_MAX_IMPLICIT_FIELDS,
+         "salias-max-implicit-fields",
+         "The maximum number of fields in a structure variable without direct structure accesses that GCC will attempt to track separately",
+         5, 0, 0)
+   
 /* The maximum structure size at which the scalar replacement of
    aggregates (SRA) pass will perform block copies.  The default
    value, 0, implies that GCC will select the most appropriate size
index 1f57a0f..0f872d0 100644 (file)
@@ -89,6 +89,8 @@ typedef enum compiler_param
   (compiler_params[(int) ENUM].value)
 
 /* Macros for the various parameters.  */
+#define SALIAS_MAX_IMPLICIT_FIELDS \
+  PARAM_VALUE (PARAM_SALIAS_MAX_IMPLICIT_FIELDS)
 #define SRA_MAX_STRUCTURE_SIZE \
   PARAM_VALUE (PARAM_SRA_MAX_STRUCTURE_SIZE)
 #define SRA_FIELD_STRUCTURE_RATIO \
index 8e1b632..17bf8c5 100644 (file)
@@ -2780,6 +2780,13 @@ typedef struct used_part
 {
   HOST_WIDE_INT minused;
   HOST_WIDE_INT maxused;
+  /* True if we have an explicit use/def of some portion of this variable,
+     even if it is all of it. i.e. a.b = 5 or temp = a.b.  */
+  bool explicit_uses;
+  /* True if we have an implicit use/def of some portion of this
+     variable.  Implicit uses occur when we can't tell what part we
+     are referencing, and have to make conservative assumptions.  */
+  bool implicit_uses;
 } *used_part_t;
 
 /* An array of used_part structures, indexed by variable uid.  */
@@ -2798,14 +2805,32 @@ get_or_create_used_part_for (size_t uid)
       up = xcalloc (1, sizeof (struct used_part));
       up->minused = INT_MAX;
       up->maxused = 0;
+      up->explicit_uses = false;
+      up->implicit_uses = false;
     }
   else
     up = used_portions[uid];
   return up;
 }
 
-           
-  
+/* qsort comparison function for two fieldoff_t's PA and PB */
+
+static int 
+fieldoff_compare (const void *pa, const void *pb)
+{
+  const fieldoff_t foa = *(fieldoff_t *)pa;
+  const fieldoff_t fob = *(fieldoff_t *)pb;
+  HOST_WIDE_INT foasize, fobsize;
+  if (foa->offset != fob->offset)
+    return foa->offset - fob->offset;
+
+  foasize = TREE_INT_CST_LOW (DECL_SIZE (foa->field));
+  fobsize = TREE_INT_CST_LOW (DECL_SIZE (fob->field));
+  if (foasize != fobsize)
+    return foasize - fobsize;
+  return 0;
+}
+
 /* Given an aggregate VAR, create the subvariables that represent its
    fields.  */
 
@@ -2819,13 +2844,18 @@ create_overlap_variables_for (tree var)
   if (used_portions[uid] == NULL)
     return;
 
+  up = used_portions[uid];
   push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0);
   if (VEC_length (fieldoff_t, fieldstack) != 0)
     {
       subvar_t *subvars;
       fieldoff_t fo;
       bool notokay = false;
+      int fieldcount = 0;
       int i;
+      HOST_WIDE_INT lastfooffset = -1;
+      HOST_WIDE_INT lastfosize = -1;
+      tree lastfotype = NULL_TREE;
 
       /* Not all fields have DECL_SIZE set, and those that don't, we don't
         know their size, and thus, can't handle.
@@ -2846,7 +2876,34 @@ create_overlap_variables_for (tree var)
              notokay = true;
              break;
            }
+          fieldcount++;
        }
+
+      /* The current heuristic we use is as follows:
+        If the variable has no used portions in this function, no
+        structure vars are created for it.
+        Otherwise,
+         If the variable has less than SALIAS_MAX_IMPLICIT_FIELDS,
+        we always create structure vars for them.
+        If the variable has more than SALIAS_MAX_IMPLICIT_FIELDS, and
+        some explicit uses, we create structure vars for them.
+        If the variable has more than SALIAS_MAX_IMPLICIT_FIELDS, and
+        no explicit uses, we do not create structure vars for them.
+      */
+      
+      if (fieldcount >= SALIAS_MAX_IMPLICIT_FIELDS
+         && !up->explicit_uses)
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "Variable ");
+             print_generic_expr (dump_file, var, 0);
+             fprintf (dump_file, " has no explicit uses in this function, and is > SALIAS_MAX_IMPLICIT_FIELDS, so skipping\n");
+           }
+         notokay = true;
+       }
+      
+    
       /* Cleanup after ourselves if we can't create overlap variables.  */
       if (notokay)
        {
@@ -2860,25 +2917,38 @@ create_overlap_variables_for (tree var)
        }
       /* Otherwise, create the variables.  */
       subvars = lookup_subvars_for_var (var);
-      up = used_portions[uid];
       
+      qsort (VEC_address (fieldoff_t, fieldstack), 
+            VEC_length (fieldoff_t, fieldstack), 
+            sizeof (fieldoff_t),
+            fieldoff_compare);
+
       while (VEC_length (fieldoff_t, fieldstack) != 0)
        {
-         subvar_t sv = ggc_alloc (sizeof (struct subvar));
+         subvar_t sv;
          HOST_WIDE_INT fosize;
          var_ann_t ann;
+         tree currfotype;
 
          fo = VEC_pop (fieldoff_t, fieldstack);          
          fosize = TREE_INT_CST_LOW (DECL_SIZE (fo->field));
-
-         if ((fo->offset <= up->minused
-              && fo->offset + fosize <= up->minused)
-             || fo->offset >= up->maxused)
+         currfotype = TREE_TYPE (fo->field);
+
+         /* If this field isn't in the used portion,
+            or it has the exact same offset and size as the last
+            field, skip it.  */
+
+         if (((fo->offset <= up->minused
+               && fo->offset + fosize <= up->minused)
+              || fo->offset >= up->maxused)
+             || (fo->offset == lastfooffset
+                 && fosize == lastfosize
+                 && currfotype == lastfotype))
            {
              free (fo);
              continue;
            }
-
+         sv = ggc_alloc (sizeof (struct subvar));
          sv->offset = fo->offset;
          sv->size = fosize;
          sv->next = *subvars;
@@ -2913,7 +2983,10 @@ create_overlap_variables_for (tree var)
          ann->mem_tag_kind = STRUCT_FIELD; 
          ann->type_mem_tag = NULL;     
          add_referenced_tmp_var (sv->var);
-           
+         
+         lastfotype = currfotype;
+         lastfooffset = fo->offset;
+         lastfosize = fosize;
          *subvars = sv;
          free (fo);
        }
@@ -2968,6 +3041,7 @@ find_used_portions (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
            if ((bitpos + bitsize >= up->maxused))
              up->maxused = bitpos + bitsize;       
 
+           up->explicit_uses = true;
            used_portions[uid] = up;
 
            *walk_subtrees = 0;
@@ -2987,6 +3061,8 @@ find_used_portions (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
                up->minused = 0;
                up->maxused = TREE_INT_CST_LOW (DECL_SIZE (ref));
 
+               up->implicit_uses = true;
+
                used_portions[uid] = up;
 
                *walk_subtrees = 0;
@@ -3010,6 +3086,7 @@ find_used_portions (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
  
            up->minused = 0;
            up->maxused = TREE_INT_CST_LOW (DECL_SIZE (var));
+           up->implicit_uses = true;
 
            used_portions[uid] = up;
            *walk_subtrees = 0;