#include "tree-ssa-structalias.h"
#include "convert.h"
#include "params.h"
+#include "ipa-type-escape.h"
#include "vec.h"
#include "bitmap.h"
unsigned int simple_resolved;
unsigned int tbaa_queries;
unsigned int tbaa_resolved;
+ unsigned int structnoaddress_queries;
+ unsigned int structnoaddress_resolved;
};
/* Local functions. */
static void compute_flow_insensitive_aliasing (struct alias_info *);
static void dump_alias_stats (FILE *);
-static bool may_alias_p (tree, HOST_WIDE_INT, tree, HOST_WIDE_INT);
+static bool may_alias_p (tree, HOST_WIDE_INT, tree, HOST_WIDE_INT, bool);
static tree create_memory_tag (tree type, bool is_type_tag);
static tree get_tmt_for (tree, struct alias_info *);
static tree get_nmt_for (tree);
(ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA. */
static tree
-count_ptr_derefs (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
+count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
{
struct count_ptr_d *count_p = (struct count_ptr_d *) data;
+ /* Do not walk inside ADDR_EXPR nodes. In the expression &ptr->fld,
+ pointer 'ptr' is *not* dereferenced, it is simply used to compute
+ the address of 'fld' as 'ptr + offsetof(fld)'. */
+ if (TREE_CODE (*tp) == ADDR_EXPR)
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
count_p->count++;
gcc_assert (*num_uses_p >= *num_derefs_p);
}
-
/* Initialize the data structures used for alias analysis. */
static struct alias_info *
tree var;
bitmap_obstack_initialize (&alias_obstack);
- ai = xcalloc (1, sizeof (struct alias_info));
+ ai = XCNEW (struct alias_info);
ai->ssa_names_visited = sbitmap_alloc (num_ssa_names);
sbitmap_zero (ai->ssa_names_visited);
VARRAY_TREE_INIT (ai->processed_ptrs, 50, "processed_ptrs");
a global variable, so we *don't* clear their call clobberedness
just because they are tags, though we will clear it if they
aren't for global variables. */
- if (ann->mem_tag_kind == NAME_TAG
- || ann->mem_tag_kind == TYPE_TAG
+ if (TREE_CODE (var) == NAME_MEMORY_TAG
+ || TREE_CODE (var) == TYPE_MEMORY_TAG
|| !is_global_var (var))
clear_call_clobbered (var);
}
delete_points_to_sets ();
}
-
/* Create name tags for all the pointers that have been dereferenced.
We only create a name tag for a pointer P if P is found to point to
a set of variables (so that we can alias them to *P) or if it is
create_name_tags (void)
{
size_t i;
+ VEC (tree, heap) *with_ptvars = NULL;
+ tree ptr;
+ /* Collect the list of pointers with a non-empty points to set. */
for (i = 1; i < num_ssa_names; i++)
{
tree ptr = ssa_name (i);
continue;
}
- if (pi->pt_vars && !bitmap_empty_p (pi->pt_vars))
+ /* Set pt_anything on the pointers without pt_vars filled in so
+ that they are assigned a type tag. */
+
+ if (pi->pt_vars && !bitmap_empty_p (pi->pt_vars))
+ VEC_safe_push (tree, heap, with_ptvars, ptr);
+ else
+ set_pt_anything (ptr);
+ }
+
+ /* If we didn't find any pointers with pt_vars set, we're done. */
+ if (!with_ptvars)
+ return;
+
+ /* Now go through the pointers with pt_vars, and find a name tag
+ with the same pt_vars as this pointer, or create one if one
+ doesn't exist. */
+ for (i = 0; VEC_iterate (tree, with_ptvars, i, ptr); i++)
+ {
+ struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
+ size_t j;
+ tree ptr2;
+ tree old_name_tag = pi->name_mem_tag;
+
+ /* If PTR points to a set of variables, check if we don't
+ have another pointer Q with the same points-to set before
+ creating a tag. If so, use Q's tag instead of creating a
+ new one.
+
+ This is important for not creating unnecessary symbols
+ and also for copy propagation. If we ever need to
+ propagate PTR into Q or vice-versa, we would run into
+ problems if they both had different name tags because
+ they would have different SSA version numbers (which
+ would force us to take the name tags in and out of SSA). */
+ for (j = 0; j < i && VEC_iterate (tree, with_ptvars, j, ptr2); j++)
{
- size_t j;
- tree old_name_tag = pi->name_mem_tag;
-
- /* If PTR points to a set of variables, check if we don't
- have another pointer Q with the same points-to set before
- creating a tag. If so, use Q's tag instead of creating a
- new one.
-
- This is important for not creating unnecessary symbols
- and also for copy propagation. If we ever need to
- propagate PTR into Q or vice-versa, we would run into
- problems if they both had different name tags because
- they would have different SSA version numbers (which
- would force us to take the name tags in and out of SSA). */
- for (j = 1; j < i; j++)
+ struct ptr_info_def *qi = SSA_NAME_PTR_INFO (ptr2);
+
+ if (bitmap_equal_p (pi->pt_vars, qi->pt_vars))
{
- tree q = ssa_name (j);
- struct ptr_info_def *qi;
-
- if (!q || !POINTER_TYPE_P (TREE_TYPE (q)))
- continue;
-
- qi = SSA_NAME_PTR_INFO (q);
-
- if (qi
- && qi->pt_vars
- && qi->name_mem_tag
- && bitmap_equal_p (pi->pt_vars, qi->pt_vars))
- {
- pi->name_mem_tag = qi->name_mem_tag;
- break;
- }
+ pi->name_mem_tag = qi->name_mem_tag;
+ break;
}
-
- /* If we didn't find a pointer with the same points-to set
- as PTR, create a new name tag if needed. */
- if (pi->name_mem_tag == NULL_TREE)
- pi->name_mem_tag = get_nmt_for (ptr);
-
- /* If the new name tag computed for PTR is different than
- the old name tag that it used to have, then the old tag
- needs to be removed from the IL, so we mark it for
- renaming. */
- if (old_name_tag && old_name_tag != pi->name_mem_tag)
- mark_sym_for_renaming (old_name_tag);
- }
- else
- {
- /* If the pointer does not point to a known spot, we should
- use type tags. */
- set_pt_anything (ptr);
- continue;
}
-
+
+ /* If we didn't find a pointer with the same points-to set
+ as PTR, create a new name tag if needed. */
+ if (pi->name_mem_tag == NULL_TREE)
+ pi->name_mem_tag = get_nmt_for (ptr);
+
+ /* If the new name tag computed for PTR is different than
+ the old name tag that it used to have, then the old tag
+ needs to be removed from the IL, so we mark it for
+ renaming. */
+ if (old_name_tag && old_name_tag != pi->name_mem_tag)
+ mark_sym_for_renaming (old_name_tag);
+
TREE_THIS_VOLATILE (pi->name_mem_tag)
- |= TREE_THIS_VOLATILE (TREE_TYPE (TREE_TYPE (ptr)));
-
+ |= TREE_THIS_VOLATILE (TREE_TYPE (TREE_TYPE (ptr)));
+
/* Mark the new name tag for renaming. */
mark_sym_for_renaming (pi->name_mem_tag);
}
+
+ VEC_free (tree, heap, with_ptvars);
}
|| bitmap_bit_p (ai->written_vars, DECL_UID (var));
if (!tag_stored_p && !var_stored_p)
continue;
-
- if (may_alias_p (p_map->var, p_map->set, var, v_map->set))
+
+ if (may_alias_p (p_map->var, p_map->set, var, v_map->set, false))
{
- subvar_t svars;
size_t num_tag_refs, num_var_refs;
num_tag_refs = NUM_REFERENCES (tag_ann);
/* Add VAR to TAG's may-aliases set. */
- /* If this is an aggregate, we may have subvariables for it
- that need to be pointed to. */
- if (var_can_have_subvars (var)
- && (svars = get_subvars_for_var (var)))
- {
- subvar_t sv;
+ /* We should never have a var with subvars here, because
+ they shouldn't get into the set of addressable vars */
+ gcc_assert (!var_can_have_subvars (var)
+ || get_subvars_for_var (var) == NULL);
- for (sv = svars; sv; sv = sv->next)
- {
- add_may_alias (tag, sv->var);
- /* Update the bitmap used to represent TAG's alias set
- in case we need to group aliases. */
- bitmap_set_bit (p_map->may_aliases, DECL_UID (sv->var));
- }
- }
- else
- {
- add_may_alias (tag, var);
- /* Update the bitmap used to represent TAG's alias set
- in case we need to group aliases. */
- bitmap_set_bit (p_map->may_aliases, DECL_UID (var));
- }
+ add_may_alias (tag, var);
+ /* Update the bitmap used to represent TAG's alias set
+ in case we need to group aliases. */
+ bitmap_set_bit (p_map->may_aliases, DECL_UID (var));
/* Update the total number of virtual operands due to
aliasing. Since we are adding one more alias to TAG's
bitmap may_aliases2 = p_map2->may_aliases;
/* If the pointers may not point to each other, do nothing. */
- if (!may_alias_p (p_map1->var, p_map1->set, tag2, p_map2->set))
+ if (!may_alias_p (p_map1->var, p_map1->set, tag2, p_map2->set, true))
continue;
/* The two pointers may alias each other. If they already have
size_t j;
tree ptr = VARRAY_TREE (ai->processed_ptrs, i);
tree name_tag = SSA_NAME_PTR_INFO (ptr)->name_mem_tag;
- varray_type aliases;
+ VEC(tree,gc) *aliases;
+ tree alias;
if (name_tag == NULL_TREE)
continue;
aliases = var_ann (name_tag)->may_aliases;
- for (j = 0; aliases && j < VARRAY_ACTIVE_SIZE (aliases); j++)
+ for (j = 0; VEC_iterate (tree, aliases, j, alias); j++)
{
- tree alias = VARRAY_TREE (aliases, j);
var_ann_t ann = var_ann (alias);
- if ((ann->mem_tag_kind == NOT_A_TAG
- || ann->mem_tag_kind == STRUCT_FIELD)
+ if ((!MTAG_P (alias)
+ || TREE_CODE (alias) == STRUCT_FIELD_TAG)
&& ann->may_aliases)
{
tree new_alias;
- gcc_assert (VARRAY_ACTIVE_SIZE (ann->may_aliases) == 1);
+ gcc_assert (VEC_length (tree, ann->may_aliases) == 1);
- new_alias = VARRAY_TREE (ann->may_aliases, 0);
+ new_alias = VEC_index (tree, ann->may_aliases, 0);
replace_may_alias (name_tag, j, new_alias);
}
}
create_alias_map_for (tree var, struct alias_info *ai)
{
struct alias_map_d *alias_map;
- alias_map = xcalloc (1, sizeof (*alias_map));
+ alias_map = XCNEW (struct alias_map_d);
alias_map->var = var;
alias_map->set = get_alias_set (var);
ai->addressable_vars[ai->num_addressable_vars++] = alias_map;
size_t n_vars, num_addressable_vars, num_pointers;
referenced_var_iterator rvi;
tree var;
+ VEC (tree, heap) *varvec = NULL;
+ safe_referenced_var_iterator srvi;
/* Size up the arrays ADDRESSABLE_VARS and POINTERS. */
num_addressable_vars = num_pointers = 0;
because some TREE_ADDRESSABLE variables will be marked
non-addressable below and only pointers with unique type tags are
going to be added to POINTERS. */
- ai->addressable_vars = xcalloc (num_addressable_vars,
- sizeof (struct alias_map_d *));
- ai->pointers = xcalloc (num_pointers, sizeof (struct alias_map_d *));
+ ai->addressable_vars = XCNEWVEC (struct alias_map_d *, num_addressable_vars);
+ ai->pointers = XCNEWVEC (struct alias_map_d *, num_pointers);
ai->num_addressable_vars = 0;
ai->num_pointers = 0;
unnecessarily. */
n_vars = num_referenced_vars;
- FOR_EACH_REFERENCED_VAR (var, rvi)
+ FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, srvi)
{
var_ann_t v_ann = var_ann (var);
subvar_t svars;
Structure fields, on the other hand, have to have some of this
information processed for them, but it's pointless to mark them
non-addressable (since they are fake variables anyway). */
- if (v_ann->mem_tag_kind != NOT_A_TAG
- && v_ann->mem_tag_kind != STRUCT_FIELD)
+ if (MTAG_P (var) && TREE_CODE (var) != STRUCT_FIELD_TAG)
continue;
/* Remove the ADDRESSABLE flag from every addressable variable whose
/* Global variables and addressable locals may be aliased. Create an
entry in ADDRESSABLE_VARS for VAR. */
- if (may_be_aliased (var))
+ if (may_be_aliased (var)
+ && (!var_can_have_subvars (var)
+ || get_subvars_for_var (var) == NULL))
{
create_alias_map_for (var, ai);
mark_sym_for_renaming (var);
}
}
}
+ VEC_free (tree, heap, varvec);
}
static bool
may_alias_p (tree ptr, HOST_WIDE_INT mem_alias_set,
- tree var, HOST_WIDE_INT var_alias_set)
+ tree var, HOST_WIDE_INT var_alias_set,
+ bool alias_set_only)
{
tree mem;
- var_ann_t m_ann;
alias_stats.alias_queries++;
alias_stats.simple_queries++;
return false;
}
- m_ann = var_ann (mem);
-
- gcc_assert (m_ann->mem_tag_kind == TYPE_TAG);
+ gcc_assert (TREE_CODE (mem) == TYPE_MEMORY_TAG);
alias_stats.tbaa_queries++;
- /* If VAR is a pointer with the same alias set as PTR, then dereferencing
- PTR can't possibly affect VAR. Note, that we are specifically testing
- for PTR's alias set here, not its pointed-to type. We also can't
- do this check with relaxed aliasing enabled. */
- if (POINTER_TYPE_P (TREE_TYPE (var))
- && var_alias_set != 0
- && mem_alias_set != 0)
- {
- HOST_WIDE_INT ptr_alias_set = get_alias_set (ptr);
- if (ptr_alias_set == var_alias_set)
- {
- alias_stats.alias_noalias++;
- alias_stats.tbaa_resolved++;
- return false;
- }
- }
-
/* If the alias sets don't conflict then MEM cannot alias VAR. */
if (!alias_sets_conflict_p (mem_alias_set, var_alias_set))
{
alias_stats.tbaa_resolved++;
return false;
}
+
+ /* If var is a record or union type, ptr cannot point into var
+ unless there is some operation explicit address operation in the
+ program that can reference a field of the ptr's dereferenced
+ type. This also assumes that the types of both var and ptr are
+ contained within the compilation unit, and that there is no fancy
+ addressing arithmetic associated with any of the types
+ involved. */
+
+ if ((mem_alias_set != 0) && (var_alias_set != 0))
+ {
+ tree ptr_type = TREE_TYPE (ptr);
+ tree var_type = TREE_TYPE (var);
+
+ /* The star count is -1 if the type at the end of the pointer_to
+ chain is not a record or union type. */
+ if ((!alias_set_only) &&
+ ipa_type_escape_star_count_of_interesting_type (var_type) >= 0)
+ {
+ int ptr_star_count = 0;
+
+ /* Ipa_type_escape_star_count_of_interesting_type is a little to
+ restrictive for the pointer type, need to allow pointers to
+ primitive types as long as those types cannot be pointers
+ to everything. */
+ while (POINTER_TYPE_P (ptr_type))
+ /* Strip the *'s off. */
+ {
+ ptr_type = TREE_TYPE (ptr_type);
+ ptr_star_count++;
+ }
+
+ /* There does not appear to be a better test to see if the
+ pointer type was one of the pointer to everything
+ types. */
+
+ if (ptr_star_count > 0)
+ {
+ alias_stats.structnoaddress_queries++;
+ if (ipa_type_escape_field_does_not_clobber_p (var_type,
+ TREE_TYPE (ptr)))
+ {
+ alias_stats.structnoaddress_resolved++;
+ alias_stats.alias_noalias++;
+ return false;
+ }
+ }
+ else if (ptr_star_count == 0)
+ {
+ /* If ptr_type was not really a pointer to type, it cannot
+ alias. */
+ alias_stats.structnoaddress_queries++;
+ alias_stats.structnoaddress_resolved++;
+ alias_stats.alias_noalias++;
+ return false;
+ }
+ }
+ }
+
alias_stats.alias_mayalias++;
return true;
}
size_t i;
var_ann_t v_ann = get_var_ann (var);
var_ann_t a_ann = get_var_ann (alias);
+ tree al;
/* Don't allow self-referential aliases. */
gcc_assert (var != alias);
#endif
if (v_ann->may_aliases == NULL)
- VARRAY_TREE_INIT (v_ann->may_aliases, 2, "aliases");
+ v_ann->may_aliases = VEC_alloc (tree, gc, 2);
/* Avoid adding duplicates. */
- for (i = 0; i < VARRAY_ACTIVE_SIZE (v_ann->may_aliases); i++)
- if (alias == VARRAY_TREE (v_ann->may_aliases, i))
+ for (i = 0; VEC_iterate (tree, v_ann->may_aliases, i, al); i++)
+ if (alias == al)
return;
/* If VAR is a call-clobbered variable, so is its new ALIAS.
else if (is_call_clobbered (alias))
mark_call_clobbered (var);
- VARRAY_PUSH_TREE (v_ann->may_aliases, alias);
+ VEC_safe_push (tree, gc, v_ann->may_aliases, alias);
a_ann->is_alias_tag = 1;
}
replace_may_alias (tree var, size_t i, tree new_alias)
{
var_ann_t v_ann = var_ann (var);
- VARRAY_TREE (v_ann->may_aliases, i) = new_alias;
+ VEC_replace (tree, v_ann->may_aliases, i, new_alias);
/* If VAR is a call-clobbered variable, so is NEW_ALIAS.
FIXME, call-clobbering should only depend on whether an address
return false;
}
+/* Create a new memory tag of type TYPE.
+ Does NOT push it into the current binding. */
+
+static tree
+create_tag_raw (enum tree_code code, tree type, const char *prefix)
+{
+ tree tmp_var;
+ tree new_type;
+
+ /* Make the type of the variable writable. */
+ new_type = build_type_variant (type, 0, 0);
+ TYPE_ATTRIBUTES (new_type) = TYPE_ATTRIBUTES (type);
+
+ tmp_var = build_decl (code, create_tmp_var_name (prefix),
+ type);
+ /* Make the variable writable. */
+ TREE_READONLY (tmp_var) = 0;
+
+ /* It doesn't start out global. */
+ MTAG_GLOBAL (tmp_var) = 0;
+ TREE_STATIC (tmp_var) = 0;
+ TREE_USED (tmp_var) = 1;
+
+ return tmp_var;
+}
/* Create a new memory tag of type TYPE. If IS_TYPE_TAG is true, the tag
is considered to represent all the pointers whose pointed-to types are
create_memory_tag (tree type, bool is_type_tag)
{
var_ann_t ann;
- tree tag = create_tmp_var_raw (type, (is_type_tag) ? "TMT" : "NMT");
+ tree tag = create_tag_raw (is_type_tag ? TYPE_MEMORY_TAG : NAME_MEMORY_TAG,
+ type, (is_type_tag) ? "TMT" : "NMT");
/* By default, memory tags are local variables. Alias analysis will
determine whether they should be considered globals. */
TREE_ADDRESSABLE (tag) = 1;
ann = get_var_ann (tag);
- ann->mem_tag_kind = (is_type_tag) ? TYPE_TAG : NAME_TAG;
ann->type_mem_tag = NULL_TREE;
/* Add the tag to the symbol table. */
/* Add PTR to the POINTERS array. Note that we are not interested in
PTR's alias set. Instead, we cache the alias set for the memory that
PTR points to. */
- alias_map = xcalloc (1, sizeof (*alias_map));
+ alias_map = XCNEW (struct alias_map_d);
alias_map->var = ptr;
alias_map->set = tag_set;
ai->pointers[ai->num_pointers++] = alias_map;
alias_stats.tbaa_queries);
fprintf (file, "Total TBAA resolved:\t%u\n",
alias_stats.tbaa_resolved);
+ fprintf (file, "Total non-addressable structure type queries:\t%u\n",
+ alias_stats.structnoaddress_queries);
+ fprintf (file, "Total non-addressable structure type resolved:\t%u\n",
+ alias_stats.structnoaddress_resolved);
}
FOR_EACH_REFERENCED_VAR (var, rvi)
{
- var_ann_t ann = var_ann (var);
- if (ann->mem_tag_kind == TYPE_TAG)
+ if (TREE_CODE (var) == TYPE_MEMORY_TAG)
dump_variable (file, var);
}
FOR_EACH_REFERENCED_VAR (var, rvi)
{
- var_ann_t ann = var_ann (var);
- if (ann->mem_tag_kind == NAME_TAG)
+ if (TREE_CODE (var) == NAME_MEMORY_TAG)
dump_variable (file, var);
}
pi = SSA_NAME_PTR_INFO (t);
if (pi == NULL)
{
- pi = ggc_alloc (sizeof (*pi));
+ pi = GGC_NEW (struct ptr_info_def);
memset ((void *)pi, 0, sizeof (*pi));
SSA_NAME_PTR_INFO (t) = pi;
}
{
if (POINTER_TYPE_P (TREE_TYPE (var)))
{
- var_ann_t ann = var_ann (var);
- if (ann->default_def)
- dump_points_to_info_for (file, ann->default_def);
+ tree def = default_def (var);
+ if (def)
+ dump_points_to_info_for (file, def);
}
}
}
-/* Dump points-to info pointed by PTO into STDERR. */
+/* Dump points-to info pointed to by PTO into STDERR. */
void
debug_points_to_info (void)
void
dump_may_aliases_for (FILE *file, tree var)
{
- varray_type aliases;
+ VEC(tree, gc) *aliases;
if (TREE_CODE (var) == SSA_NAME)
var = SSA_NAME_VAR (var);
if (aliases)
{
size_t i;
+ tree al;
fprintf (file, "{ ");
- for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
+ for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
{
- print_generic_expr (file, VARRAY_TREE (aliases, i), dump_flags);
+ print_generic_expr (file, al, dump_flags);
fprintf (file, " ");
}
fprintf (file, "}");
/* Globally visible variables can have their addresses taken by other
translation units. */
- if (DECL_EXTERNAL (var) || TREE_PUBLIC (var))
+
+ if (MTAG_P (var)
+ && (MTAG_GLOBAL (var) || TREE_PUBLIC (var)))
+ return true;
+ else if (!MTAG_P (var)
+ && (DECL_EXTERNAL (var) || TREE_PUBLIC (var)))
return true;
/* Automatic variables can't have their addresses escape any other way.
}
+/* Given two symbols return TRUE if one is in the alias set of the other. */
+bool
+is_aliased_with (tree tag, tree sym)
+{
+ size_t i;
+ VEC(tree,gc) *aliases;
+ tree al;
+
+ if (var_ann (sym)->is_alias_tag)
+ {
+ aliases = var_ann (tag)->may_aliases;
+
+ if (aliases == NULL)
+ return false;
+
+ for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
+ if (al == sym)
+ return true;
+ }
+ else
+ {
+ aliases = var_ann (sym)->may_aliases;
+
+ if (aliases == NULL)
+ return false;
+
+ for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
+ if (al == tag)
+ return true;
+ }
+
+ return false;
+}
+
+
/* Add VAR to the list of may-aliases of PTR's type tag. If PTR
doesn't already have a type tag, create one. */
void
add_type_alias (tree ptr, tree var)
{
- varray_type aliases;
- tree tag;
+ VEC(tree, gc) *aliases;
+ tree tag, al;
var_ann_t ann = var_ann (ptr);
subvar_t svars;
-
+ VEC (tree, heap) *varvec = NULL;
+ unsigned i;
if (ann->type_mem_tag == NULL_TREE)
{
tree q = NULL_TREE;
tree tag_type = TREE_TYPE (TREE_TYPE (ptr));
HOST_WIDE_INT tag_set = get_alias_set (tag_type);
- referenced_var_iterator rvi;
+ safe_referenced_var_iterator rvi;
/* PTR doesn't have a type tag, create a new one and add VAR to
the new tag's alias set.
whether there is another pointer Q with the same alias set as
PTR. This could be sped up by having type tags associated
with types. */
- FOR_EACH_REFERENCED_VAR (q, rvi)
+ FOR_EACH_REFERENCED_VAR_SAFE (q, varvec, rvi)
{
if (POINTER_TYPE_P (TREE_TYPE (q))
&& tag_set == get_alias_set (TREE_TYPE (TREE_TYPE (q))))
found_tag:
/* If VAR is not already PTR's type tag, add it to the may-alias set
for PTR's type tag. */
- gcc_assert (var_ann (var)->type_mem_tag == NOT_A_TAG);
+ gcc_assert (!MTAG_P (var_ann (var)->type_mem_tag));
tag = ann->type_mem_tag;
/* If VAR has subvars, add the subvars to the tag instead of the
mark_sym_for_renaming (tag);
if ((aliases = var_ann (tag)->may_aliases) != NULL)
{
- size_t i;
- for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
- mark_sym_for_renaming (VARRAY_TREE (aliases, i));
+ for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
+ mark_sym_for_renaming (al);
}
/* If we had grouped aliases, VAR may have aliases of its own. Mark
aliases of VAR will need to be updated. */
if ((aliases = var_ann (var)->may_aliases) != NULL)
{
- size_t i;
- for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
- mark_sym_for_renaming (VARRAY_TREE (aliases, i));
+ for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
+ mark_sym_for_renaming (al);
}
+ VEC_free (tree, heap, varvec);
}
subvar_t svars;
gcc_assert (p_ann->type_mem_tag == NULL_TREE);
- gcc_assert (v_ann->mem_tag_kind == NOT_A_TAG);
+ gcc_assert (!MTAG_P (var));
/* Add VAR to the may-alias set of PTR's new type tag. If VAR has
subvars, add the subvars to the tag instead of the actual var. */
same defs/uses/vdefs/vuses will be found after replacing a reference
to var (or ARRAY_REF to var) with an INDIRECT_REF to ptr whose value
is the address of var. */
- varray_type aliases = v_ann->may_aliases;
+ VEC(tree, gc) *aliases = v_ann->may_aliases;
if ((aliases != NULL)
- && (VARRAY_ACTIVE_SIZE (aliases) == 1))
+ && (VEC_length (tree, aliases) == 1))
{
- tree ali = VARRAY_TREE (aliases, 0);
+ tree ali = VEC_index (tree, aliases, 0);
- if (get_var_ann (ali)->mem_tag_kind == TYPE_TAG)
+ if (TREE_CODE (ali) == TYPE_MEMORY_TAG)
{
p_ann->type_mem_tag = ali;
return;
add_may_alias (tag, var);
else
{
- size_t i;
+ unsigned i;
+ tree al;
- for (i = 0; i < VARRAY_ACTIVE_SIZE (aliases); i++)
- add_may_alias (tag, VARRAY_TREE (aliases, i));
+ for (i = 0; VEC_iterate (tree, aliases, i, al); i++)
+ add_may_alias (tag, al);
}
}
}
static int
used_part_map_eq (const void *va, const void *vb)
{
- const struct used_part_map *a = va, *b = vb;
+ const struct used_part_map *a = (const struct used_part_map *) va;
+ const struct used_part_map *b = (const struct used_part_map *) vb;
return (a->uid == b->uid);
}
free_used_part_map (void *item)
{
free (((struct used_part_map *)item)->to);
+ free (item);
}
/* Lookup a used_part structure for a UID. */
{
struct used_part_map *h, in;
in.uid = uid;
- h = htab_find_with_hash (used_portions, &in, uid);
+ h = (struct used_part_map *) htab_find_with_hash (used_portions, &in, uid);
if (!h)
return NULL;
return h->to;
struct used_part_map *h;
void **loc;
- h = xmalloc (sizeof (struct used_part_map));
+ h = XNEW (struct used_part_map);
h->uid = uid;
h->to = to;
loc = htab_find_slot_with_hash (used_portions, h,
uid, INSERT);
+ if (*loc != NULL)
+ free (*loc);
*(struct used_part_map **) loc = h;
}
used_part_t up;
if ((up = up_lookup (uid)) == NULL)
{
- up = xcalloc (1, sizeof (struct used_part));
+ up = XCNEW (struct used_part);
up->minused = INT_MAX;
up->maxused = 0;
up->explicit_uses = false;
create_sft (tree var, tree field)
{
var_ann_t ann;
- tree subvar = create_tmp_var_raw (TREE_TYPE (field), "SFT");
+ tree subvar = create_tag_raw (STRUCT_FIELD_TAG, TREE_TYPE (field), "SFT");
/* We need to copy the various flags from VAR to SUBVAR, so that
they are is_global_var iff the original variable was. */
DECL_CONTEXT (subvar) = DECL_CONTEXT (var);
- DECL_EXTERNAL (subvar) = DECL_EXTERNAL (var);
+ MTAG_GLOBAL (subvar) = DECL_EXTERNAL (var);
TREE_PUBLIC (subvar) = TREE_PUBLIC (var);
TREE_STATIC (subvar) = TREE_STATIC (var);
TREE_READONLY (subvar) = TREE_READONLY (var);
/* Add the new variable to REFERENCED_VARS. */
ann = get_var_ann (subvar);
- ann->mem_tag_kind = STRUCT_FIELD;
ann->type_mem_tag = NULL;
add_referenced_tmp_var (subvar);
&& fosize == lastfosize
&& currfotype == lastfotype))
continue;
- sv = ggc_alloc (sizeof (struct subvar));
+ sv = GGC_NEW (struct subvar);
sv->offset = fo->offset;
sv->size = fosize;
sv->next = *subvars;
case COMPONENT_REF:
{
HOST_WIDE_INT bitsize;
+ HOST_WIDE_INT bitmaxsize;
HOST_WIDE_INT bitpos;
- tree offset;
- enum machine_mode mode;
- int unsignedp;
- int volatilep;
tree ref;
- ref = get_inner_reference (*tp, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
- if (DECL_P (ref) && offset == NULL && bitsize != -1)
- {
+ ref = get_ref_base_and_extent (*tp, &bitpos, &bitsize, &bitmaxsize);
+ if (DECL_P (ref)
+ && var_can_have_subvars (ref)
+ && bitmaxsize != -1)
+ {
size_t uid = DECL_UID (ref);
used_part_t up;
if (bitpos <= up->minused)
up->minused = bitpos;
- if ((bitpos + bitsize >= up->maxused))
- up->maxused = bitpos + bitsize;
+ if ((bitpos + bitmaxsize >= up->maxused))
+ up->maxused = bitpos + bitmaxsize;
- up->explicit_uses = true;
+ if (bitsize == bitmaxsize)
+ up->explicit_uses = true;
+ else
+ up->implicit_uses = true;
up_insert (uid, up);
*walk_subtrees = 0;
return NULL_TREE;
}
- else if (DECL_P (ref))
- {
- if (DECL_SIZE (ref)
- && var_can_have_subvars (ref)
- && TREE_CODE (DECL_SIZE (ref)) == INTEGER_CST)
- {
- used_part_t up;
- size_t uid = DECL_UID (ref);
-
- up = get_or_create_used_part_for (uid);
-
- up->minused = 0;
- up->maxused = TREE_INT_CST_LOW (DECL_SIZE (ref));
-
- up->implicit_uses = true;
-
- up_insert (uid, up);
-
- *walk_subtrees = 0;
- return NULL_TREE;
- }
- }
}
break;
/* This is here to make sure we mark the entire base variable as used
break;
case VAR_DECL:
case PARM_DECL:
+ case RESULT_DECL:
{
tree var = *tp;
if (DECL_SIZE (var)
create_structure_vars (void)
{
basic_block bb;
- referenced_var_iterator rvi;
+ safe_referenced_var_iterator rvi;
+ VEC (tree, heap) *varvec = NULL;
tree var;
used_portions = htab_create (10, used_part_map_hash, used_part_map_eq,
NULL);
}
}
- FOR_EACH_REFERENCED_VAR (var, rvi)
+ FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, rvi)
{
/* The C++ FE creates vars without DECL_SIZE set, for some reason. */
if (var
&& DECL_SIZE (var)
&& var_can_have_subvars (var)
- && var_ann (var)->mem_tag_kind == NOT_A_TAG
+ && !MTAG_P (var)
&& TREE_CODE (DECL_SIZE (var)) == INTEGER_CST)
create_overlap_variables_for (var);
}
htab_delete (used_portions);
+ VEC_free (tree, heap, varvec);
}