summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-alias.c
diff options
context:
space:
mode:
authordnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>2007-11-13 15:20:40 +0000
committerdnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>2007-11-13 15:20:40 +0000
commit18346ecd861dc66e71dafe48ff216cfa4dc95a21 (patch)
treeb04ec56bade931807b6ed40c6d251c05aa588f0b /gcc/tree-ssa-alias.c
parent62e369b3a7e2a62037d4b22f55f96530b76bb9f8 (diff)
downloadgcc-18346ecd861dc66e71dafe48ff216cfa4dc95a21.tar.gz
pr 33870
* tree.h (strcut tree_memory_tag): add field unpartitionable. remove field in_nested_struct. (struct tree_struct_field_tag): add field nesting_level. (sft_in_nested_struct): remove. (sft_nesting_level): define. (sft_unpartitionable_p): define. * tree-ssa-alias.c (mem_sym_score): if mp->var is not partitionable, return long_max. (compute_memory_partitions): do not partition sfts marked unpartitionable. (create_sft): add argument nesting_level. set sft_nesting_level with it. update all users. (create_overlap_variables_for): show nesting level. * tree-dfa.c (dump_subvars_for): likewise. (dump_variable): likewise. show whether the sft is partitionable or not. * tree-flow.h (struct fieldoff): remove field in_nested_struct. add field nesting_level. * tree-ssa-structalias.c (struct variable_info): remove field in_nested_struct. (push_fields_onto_fieldstack): add argument nesting_level. update all users. update documentation. update pair->nesting_level with nesting_level. make recursive calls with nesting_level + 1. (set_uids_in_ptset): if an sft is added to the points-to set, mark it as unpartitionable. * tree-ssa-operands.c (ref_nesting_level): new. (add_vars_for_offset): call it. add argument full_ref. update callers. if var is inside a nested structure and the nesting level of full_ref is lower than the nesting level of var, adjust offset by the offset of var. testsuite/ChangeLog PR 33870 * gcc.c-torture/execute/pr33870-1.c: New test. * gcc.dg/tree-ssa/alias-16.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@130141 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-alias.c')
-rw-r--r--gcc/tree-ssa-alias.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index f2e30646d4c..31e04bcca29 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -828,6 +828,13 @@ count_mem_refs (long *num_vuses_p, long *num_vdefs_p,
static inline long
mem_sym_score (mem_sym_stats_t mp)
{
+ /* Unpartitionable SFTs are automatically thrown to the bottom of
+ the list. They are not stored in partitions, but they are used
+ for computing overall statistics. */
+ if (TREE_CODE (mp->var) == STRUCT_FIELD_TAG
+ && SFT_UNPARTITIONABLE_P (mp->var))
+ return LONG_MAX;
+
return mp->frequency_writes * 64 + mp->frequency_reads * 32
+ mp->num_direct_writes * 16 + mp->num_direct_reads * 8
+ mp->num_indirect_writes * 4 + mp->num_indirect_reads * 2
@@ -1392,8 +1399,8 @@ update_reference_counts (struct mem_ref_stats_d *mem_ref_stats)
static void
build_mp_info (struct mem_ref_stats_d *mem_ref_stats,
- VEC(mem_sym_stats_t,heap) **mp_info_p,
- VEC(tree,heap) **tags_p)
+ VEC(mem_sym_stats_t,heap) **mp_info_p,
+ VEC(tree,heap) **tags_p)
{
tree var;
referenced_var_iterator rvi;
@@ -1591,6 +1598,15 @@ compute_memory_partitions (void)
if (!need_to_partition_p (mem_ref_stats))
break;
+ /* SFTs that are marked unpartitionable should not be added to
+ partitions. These SFTs are special because they mark the
+ first SFT into a structure where a pointer is pointing to.
+ This is needed by the operand scanner to find adjacent
+ fields. See add_vars_for_offset for details. */
+ if (TREE_CODE (mp_p->var) == STRUCT_FIELD_TAG
+ && SFT_UNPARTITIONABLE_P (mp_p->var))
+ continue;
+
mpt = find_partition_for (mp_p);
estimate_vop_reduction (mem_ref_stats, mp_p, mpt);
}
@@ -3774,7 +3790,8 @@ get_or_create_used_part_for (size_t uid)
static tree
create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
- unsigned HOST_WIDE_INT size, alias_set_type alias_set)
+ unsigned HOST_WIDE_INT size, alias_set_type alias_set,
+ unsigned nesting_level)
{
tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT");
@@ -3794,6 +3811,8 @@ create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
SFT_OFFSET (subvar) = offset;
SFT_SIZE (subvar) = size;
SFT_ALIAS_SET (subvar) = alias_set;
+ SFT_NESTING_LEVEL (subvar) = nesting_level;
+
return subvar;
}
@@ -3814,7 +3833,7 @@ create_overlap_variables_for (tree var)
return;
push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL,
- TREE_TYPE (var));
+ TREE_TYPE (var), 0);
if (VEC_length (fieldoff_s, fieldstack) != 0)
{
subvar_t *subvars;
@@ -3897,7 +3916,6 @@ create_overlap_variables_for (tree var)
field, skip it. Note that we always need the field at
offset 0 so we can properly handle pointers to the
structure. */
-
if ((fo->offset != 0
&& ((fo->offset <= up->minused
&& fo->offset + fosize <= up->minused)
@@ -3906,8 +3924,9 @@ create_overlap_variables_for (tree var)
&& fosize == lastfosize
&& currfotype == lastfotype))
continue;
- subvar = create_sft (var, fo->type, fo->offset,
- fosize, fo->alias_set);
+
+ subvar = create_sft (var, fo->type, fo->offset, fosize,
+ fo->alias_set, fo->nesting_level);
VEC_quick_push (tree, *subvars, subvar);
if (dump_file)
@@ -3918,7 +3937,8 @@ create_overlap_variables_for (tree var)
SFT_OFFSET (subvar));
fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC,
SFT_SIZE (subvar));
- fprintf (dump_file, "\n");
+ fprintf (dump_file, " nesting level %d\n",
+ SFT_NESTING_LEVEL (subvar));
}
lastfotype = currfotype;