diff options
author | dberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-04-06 20:03:15 +0000 |
---|---|---|
committer | dberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-04-06 20:03:15 +0000 |
commit | 726e114ce3badf8d02ba54e38ade3dda51039831 (patch) | |
tree | 6a06c9e86888c19907695323e00a5fc66d7d3ed5 /gcc | |
parent | 98b93ebbf48d3a2d9cfaa36b6c8ab35aad923be4 (diff) | |
download | gcc-726e114ce3badf8d02ba54e38ade3dda51039831.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@97746 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 5 | ||||
-rw-r--r-- | gcc/params.def | 8 | ||||
-rw-r--r-- | gcc/params.h | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 97 |
5 files changed, 116 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3d884469dcd..aa8bcc5d20d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index b018b2750bb..e36aa3a2e04 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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 diff --git a/gcc/params.def b/gcc/params.def index 2dbc19758e0..6a90a02bae6 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -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 diff --git a/gcc/params.h b/gcc/params.h index 1f57a0f91a0..0f872d031d0 100644 --- a/gcc/params.h +++ b/gcc/params.h @@ -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 \ diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 8e1b63265f8..17bf8c5cb76 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -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; |