{
EXECUTE_IF_SET_IN_BITMAP (queued, 0, i, bi)
{
- subvar_t svars;
- svars = get_subvars_for_var (referenced_var (i));
- for (; svars; svars = svars->next)
- if (!unmodifiable_var_p (svars->var))
- mark_call_clobbered (svars->var, ta->escape_mask);
+ subvar_t svars = get_subvars_for_var (referenced_var (i));
+ unsigned int i;
+ tree subvar;
+
+ for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
+ if (!unmodifiable_var_p (subvar))
+ mark_call_clobbered (subvar, ta->escape_mask);
}
bitmap_clear (queued);
}
{
EXECUTE_IF_SET_IN_BITMAP (queued, 0, j, bi)
{
- subvar_t svars;
- svars = get_subvars_for_var (referenced_var (j));
- for (; svars; svars = svars->next)
- if (!unmodifiable_var_p (svars->var))
- mark_call_clobbered (svars->var, pi->escape_mask);
+ subvar_t svars = get_subvars_for_var (referenced_var (j));
+ unsigned int i;
+ tree subvar;
+
+ for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
+ if (!unmodifiable_var_p (subvar))
+ mark_call_clobbered (subvar, pi->escape_mask);
}
bitmap_clear (queued);
}
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
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;
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);
}
if (var_can_have_subvars (var)
&& (svars = get_subvars_for_var (var)))
{
- subvar_t sv;
+ unsigned int i;
+ tree subvar;
- for (sv = svars; sv; sv = sv->next)
+ for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
{
if (bitmap_bit_p (gimple_addressable_vars (cfun),
- DECL_UID (sv->var)))
+ DECL_UID (subvar)))
okay_to_mark = false;
- mark_sym_for_renaming (sv->var);
+ mark_sym_for_renaming (subvar);
}
}
So, if we have some pure/const and some regular calls in the
program we create .GLOBAL_VAR to avoid missing these
relations. */
- if (bitmap_count_bits (gimple_call_clobbered_vars (cfun)) == 0
+ if (bitmap_empty_p (gimple_call_clobbered_vars (cfun))
&& stats->num_call_sites > 0
&& stats->num_pure_const_call_sites > 0
&& stats->num_call_sites > stats->num_pure_const_call_sites)
aliases = may_aliases (var);
/* Case 1: |aliases| == 1 */
- if (aliases && bitmap_count_bits (aliases) == 1)
+ if (aliases
+ && bitmap_single_bit_set_p (aliases))
{
tree ali = referenced_var (bitmap_first_set_bit (aliases));
if (TREE_CODE (ali) == SYMBOL_MEMORY_TAG)
HOST_WIDE_INT offset, size, maxsize;
tree ref;
VEC (tree, heap) *overlaps = NULL;
- subvar_t sv;
- unsigned int len;
+ unsigned int len, i;
+ tree subvar;
+
gcc_assert (symbol_mem_tag (ptr) == NULL_TREE);
gcc_assert (!MTAG_P (var));
if (var_can_have_subvars (ref)
&& (svars = get_subvars_for_var (ref)))
{
- for (sv = svars; sv; sv = sv->next)
+ for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
{
bool exact;
- if (overlap_subvar (offset, maxsize, sv->var, &exact))
- VEC_safe_push (tree, heap, overlaps, sv->var);
+ if (overlap_subvar (offset, maxsize, subvar, &exact))
+ VEC_safe_push (tree, heap, overlaps, subvar);
}
gcc_assert (overlaps != NULL);
}
On mem-ssa branch, the scanning for virtual operands have been
split from the rest of tree-ssa-operands, so it should be much
easier to fix this problem correctly once mem-ssa is merged. */
- for (sv = svars; sv; sv = sv->next)
- VEC_safe_push (tree, heap, overlaps, sv->var);
+ for (i = 0; VEC_iterate (tree, svars, i, subvar); ++i)
+ VEC_safe_push (tree, heap, overlaps, subvar);
gcc_assert (overlaps != NULL);
}
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,
+ bool base_for_components)
{
tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT");
SFT_OFFSET (subvar) = offset;
SFT_SIZE (subvar) = size;
SFT_ALIAS_SET (subvar) = alias_set;
+ SFT_BASE_FOR_COMPONENTS_P (subvar) = base_for_components;
+ SFT_UNPARTITIONABLE_P (subvar) = false;
+
return subvar;
}
push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL,
TREE_TYPE (var));
- if (VEC_length (fieldoff_s, fieldstack) != 0)
+ /* Make sure to not create SFTs for structs we won't generate variable
+ infos for. See tree-ssa-structalias.c:create_variable_info_for (). */
+ if (VEC_length (fieldoff_s, fieldstack) > 1
+ && VEC_length (fieldoff_s, fieldstack) <= MAX_FIELDS_FOR_FIELD_SENSITIVE)
{
subvar_t *subvars;
fieldoff_s *fo;
/* Otherwise, create the variables. */
subvars = lookup_subvars_for_var (var);
-
+ *subvars = VEC_alloc (tree, gc, VEC_length (fieldoff_s, fieldstack));
+
sort_fieldstack (fieldstack);
- for (i = VEC_length (fieldoff_s, fieldstack);
- VEC_iterate (fieldoff_s, fieldstack, --i, fo);)
+ for (i = 0; VEC_iterate (fieldoff_s, fieldstack, i, fo); ++i)
{
- subvar_t sv;
HOST_WIDE_INT fosize;
- tree currfotype;
+ tree currfotype, subvar;
fosize = TREE_INT_CST_LOW (fo->size);
currfotype = fo->type;
&& fosize == lastfosize
&& currfotype == lastfotype))
continue;
- sv = GGC_NEW (struct subvar);
- sv->next = *subvars;
- sv->var =
- create_sft (var, fo->type, fo->offset, fosize, fo->alias_set);
+ subvar = create_sft (var, fo->type, fo->offset,
+ fosize, fo->alias_set, fo->base_for_components);
+ VEC_quick_push (tree, *subvars, subvar);
if (dump_file)
{
fprintf (dump_file, "structure field tag %s created for var %s",
- get_name (sv->var), get_name (var));
+ get_name (subvar), get_name (var));
fprintf (dump_file, " offset " HOST_WIDE_INT_PRINT_DEC,
- SFT_OFFSET (sv->var));
+ SFT_OFFSET (subvar));
fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC,
- SFT_SIZE (sv->var));
+ SFT_SIZE (subvar));
fprintf (dump_file, "\n");
}
lastfotype = currfotype;
lastfooffset = fo->offset;
lastfosize = fosize;
- *subvars = sv;
}
/* Once we have created subvars, the original is no longer call