summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-alias.c
diff options
context:
space:
mode:
authordberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>2005-04-06 20:03:15 +0000
committerdberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>2005-04-06 20:03:15 +0000
commit726e114ce3badf8d02ba54e38ade3dda51039831 (patch)
tree6a06c9e86888c19907695323e00a5fc66d7d3ed5 /gcc/tree-ssa-alias.c
parent98b93ebbf48d3a2d9cfaa36b6c8ab35aad923be4 (diff)
downloadgcc-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/tree-ssa-alias.c')
-rw-r--r--gcc/tree-ssa-alias.c97
1 files changed, 87 insertions, 10 deletions
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;