params.def (PARAM_SALIAS_MAX_IMPLICIT_FIELDS): New

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.

From-SVN: r97746
This commit is contained in:
Daniel Berlin 2005-04-06 20:03:15 +00:00 committed by Daniel Berlin
parent 4e9944320f
commit 31617ef157
5 changed files with 115 additions and 9 deletions

View 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.

View 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

View 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

View 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 \

View 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));
currfotype = TREE_TYPE (fo->field);
if ((fo->offset <= up->minused
&& fo->offset + fosize <= up->minused)
|| fo->offset >= up->maxused)
/* 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;