Commit d6d305fe by Richard Biener Committed by Richard Biener

tree-ssa-structalias.c (struct variable_info): Add pointer to the first field of…

tree-ssa-structalias.c (struct variable_info): Add pointer to the first field of an aggregate with sub-vars.

2013-03-20  Richard Biener  <rguenther@suse.de>

	* tree-ssa-structalias.c (struct variable_info): Add pointer
	to the first field of an aggregate with sub-vars.  Make
	this and the pointer to the next subfield its ID.
	(vi_next): New function.
	(nothing_id, anything_id, readonly_id, escaped_id, nonlocal_id,
	storedanything_id, integer_id): Increment by one.
	(new_var_info, get_call_vi, lookup_call_clobber_vi,
	get_call_clobber_vi): Adjust.
	(solution_set_expand): Simplify and speedup.
	(solution_set_add): Inline into ...
	(set_union_with_increment): ... this.  Adjust accordingly.
	(do_sd_constraint): Likewise.
	(do_ds_constraint): Likewise.
	(do_complex_constraint): Simplify.
	(build_pred_graph): Adjust.
	(solve_graph): Likewise.  Simplify and speedup.
	(get_constraint_for_ssa_var, get_constraint_for_ptr_offset,
	get_constraint_for_component_ref, get_constraint_for_1,
	first_vi_for_offset, first_or_preceding_vi_for_offset,
	create_function_info_for, create_variable_info_for_1,
	create_variable_info_for, intra_create_variable_infos): Adjust.
	(init_base_vars): Push NULL for ID zero.
	(compute_points_to_sets): Adjust.

From-SVN: r196812
parent a271b42d
2013-03-20 Richard Biener <rguenther@suse.de> 2013-03-20 Richard Biener <rguenther@suse.de>
* tree-ssa-structalias.c (struct variable_info): Add pointer
to the first field of an aggregate with sub-vars. Make
this and the pointer to the next subfield its ID.
(vi_next): New function.
(nothing_id, anything_id, readonly_id, escaped_id, nonlocal_id,
storedanything_id, integer_id): Increment by one.
(new_var_info, get_call_vi, lookup_call_clobber_vi,
get_call_clobber_vi): Adjust.
(solution_set_expand): Simplify and speedup.
(solution_set_add): Inline into ...
(set_union_with_increment): ... this. Adjust accordingly.
(do_sd_constraint): Likewise.
(do_ds_constraint): Likewise.
(do_complex_constraint): Simplify.
(build_pred_graph): Adjust.
(solve_graph): Likewise. Simplify and speedup.
(get_constraint_for_ssa_var, get_constraint_for_ptr_offset,
get_constraint_for_component_ref, get_constraint_for_1,
first_vi_for_offset, first_or_preceding_vi_for_offset,
create_function_info_for, create_variable_info_for_1,
create_variable_info_for, intra_create_variable_infos): Adjust.
(init_base_vars): Push NULL for ID zero.
(compute_points_to_sets): Adjust.
2013-03-20 Richard Biener <rguenther@suse.de>
* cfgloop.c (verify_loop_structure): Streamline and avoid * cfgloop.c (verify_loop_structure): Streamline and avoid
ICEing on corrupt loop tree. ICEing on corrupt loop tree.
* graph.c (draw_cfg_nodes_for_loop): Avoid ICEing on corrupt * graph.c (draw_cfg_nodes_for_loop): Avoid ICEing on corrupt
......
...@@ -268,8 +268,12 @@ struct variable_info ...@@ -268,8 +268,12 @@ struct variable_info
/* True if this represents a IPA function info. */ /* True if this represents a IPA function info. */
unsigned int is_fn_info : 1; unsigned int is_fn_info : 1;
/* A link to the variable for the next field in this structure. */ /* The ID of the variable for the next field in this structure
struct variable_info *next; or zero for the last field in this structure. */
unsigned next;
/* The ID of the variable for the first field in this structure. */
unsigned head;
/* Offset of this variable, in bits, from the base variable */ /* Offset of this variable, in bits, from the base variable */
unsigned HOST_WIDE_INT offset; unsigned HOST_WIDE_INT offset;
...@@ -319,10 +323,20 @@ get_varinfo (unsigned int n) ...@@ -319,10 +323,20 @@ get_varinfo (unsigned int n)
return varmap[n]; return varmap[n];
} }
/* Static IDs for the special variables. */ /* Return the next variable in the list of sub-variables of VI
enum { nothing_id = 0, anything_id = 1, readonly_id = 2, or NULL if VI is the last sub-variable. */
escaped_id = 3, nonlocal_id = 4,
storedanything_id = 5, integer_id = 6 }; static inline varinfo_t
vi_next (varinfo_t vi)
{
return get_varinfo (vi->next);
}
/* Static IDs for the special variables. Variable ID zero is unused
and used as terminator for the sub-variable chain. */
enum { nothing_id = 1, anything_id = 2, readonly_id = 3,
escaped_id = 4, nonlocal_id = 5,
storedanything_id = 6, integer_id = 7 };
/* Return a new variable info structure consisting for a variable /* Return a new variable info structure consisting for a variable
named NAME, and using constraint graph node NODE. Append it named NAME, and using constraint graph node NODE. Append it
...@@ -355,7 +369,8 @@ new_var_info (tree t, const char *name) ...@@ -355,7 +369,8 @@ new_var_info (tree t, const char *name)
&& DECL_HARD_REGISTER (t))); && DECL_HARD_REGISTER (t)));
ret->solution = BITMAP_ALLOC (&pta_obstack); ret->solution = BITMAP_ALLOC (&pta_obstack);
ret->oldsolution = NULL; ret->oldsolution = NULL;
ret->next = NULL; ret->next = 0;
ret->head = ret->id;
stats.total_vars++; stats.total_vars++;
...@@ -387,12 +402,14 @@ get_call_vi (gimple call) ...@@ -387,12 +402,14 @@ get_call_vi (gimple call)
vi->fullsize = 2; vi->fullsize = 2;
vi->is_full_var = true; vi->is_full_var = true;
vi->next = vi2 = new_var_info (NULL_TREE, "CALLCLOBBERED"); vi2 = new_var_info (NULL_TREE, "CALLCLOBBERED");
vi2->offset = 1; vi2->offset = 1;
vi2->size = 1; vi2->size = 1;
vi2->fullsize = 2; vi2->fullsize = 2;
vi2->is_full_var = true; vi2->is_full_var = true;
vi->next = vi2->id;
*slot_p = (void *) vi; *slot_p = (void *) vi;
return vi; return vi;
} }
...@@ -422,7 +439,7 @@ lookup_call_clobber_vi (gimple call) ...@@ -422,7 +439,7 @@ lookup_call_clobber_vi (gimple call)
if (!uses) if (!uses)
return NULL; return NULL;
return uses->next; return vi_next (uses);
} }
/* Lookup or create the variable for the call statement CALL representing /* Lookup or create the variable for the call statement CALL representing
...@@ -440,7 +457,7 @@ get_call_use_vi (gimple call) ...@@ -440,7 +457,7 @@ get_call_use_vi (gimple call)
static varinfo_t ATTRIBUTE_UNUSED static varinfo_t ATTRIBUTE_UNUSED
get_call_clobber_vi (gimple call) get_call_clobber_vi (gimple call)
{ {
return get_call_vi (call)->next; return vi_next (get_call_vi (call));
} }
...@@ -701,8 +718,10 @@ dump_constraint_graph (FILE *file) ...@@ -701,8 +718,10 @@ dump_constraint_graph (FILE *file)
/* The next lines print the nodes in the graph together with the /* The next lines print the nodes in the graph together with the
complex constraints attached to them. */ complex constraints attached to them. */
for (i = 0; i < graph->size; i++) for (i = 1; i < graph->size; i++)
{ {
if (i == FIRST_REF_NODE)
continue;
if (find (i) != i) if (find (i) != i)
continue; continue;
if (i < FIRST_REF_NODE) if (i < FIRST_REF_NODE)
...@@ -726,7 +745,7 @@ dump_constraint_graph (FILE *file) ...@@ -726,7 +745,7 @@ dump_constraint_graph (FILE *file)
/* Go over the edges. */ /* Go over the edges. */
fprintf (file, "\n // Edges in the constraint graph:\n"); fprintf (file, "\n // Edges in the constraint graph:\n");
for (i = 0; i < graph->size; i++) for (i = 1; i < graph->size; i++)
{ {
unsigned j; unsigned j;
bitmap_iterator bi; bitmap_iterator bi;
...@@ -881,63 +900,71 @@ constraint_set_union (vec<constraint_t> *to, ...@@ -881,63 +900,71 @@ constraint_set_union (vec<constraint_t> *to,
} }
} }
/* Expands the solution in SET to all sub-fields of variables included. /* Expands the solution in SET to all sub-fields of variables included. */
Union the expanded result into RESULT. */
static void static void
solution_set_expand (bitmap result, bitmap set) solution_set_expand (bitmap set)
{ {
bitmap_iterator bi; bitmap_iterator bi;
bitmap vars = NULL;
unsigned j; unsigned j;
/* In a first pass record all variables we need to add all /* In a first pass expand to the head of the variables we need to
sub-fields off. This avoids quadratic behavior. */ add all sub-fields off. This avoids quadratic behavior. */
EXECUTE_IF_SET_IN_BITMAP (set, 0, j, bi) EXECUTE_IF_SET_IN_BITMAP (set, 0, j, bi)
{ {
varinfo_t v = get_varinfo (j); varinfo_t v = get_varinfo (j);
if (v->is_artificial_var if (v->is_artificial_var
|| v->is_full_var) || v->is_full_var)
continue; continue;
v = lookup_vi_for_tree (v->decl); bitmap_set_bit (set, v->head);
if (vars == NULL)
vars = BITMAP_ALLOC (NULL);
bitmap_set_bit (vars, v->id);
} }
/* In the second pass now do the addition to the solution and /* In the second pass now expand all head variables with subfields. */
to speed up solving add it to the delta as well. */ EXECUTE_IF_SET_IN_BITMAP (set, 0, j, bi)
if (vars != NULL)
{ {
EXECUTE_IF_SET_IN_BITMAP (vars, 0, j, bi) varinfo_t v = get_varinfo (j);
{ if (v->is_artificial_var
varinfo_t v = get_varinfo (j); || v->is_full_var
for (; v != NULL; v = v->next) || v->head != j)
bitmap_set_bit (result, v->id); continue;
} for (v = vi_next (v); v != NULL; v = vi_next (v))
BITMAP_FREE (vars); bitmap_set_bit (set, v->id);
} }
} }
/* Take a solution set SET, add OFFSET to each member of the set, and /* Union solution sets TO and FROM, and add INC to each member of FROM in the
overwrite SET with the result when done. */ process. */
static void static bool
solution_set_add (bitmap set, HOST_WIDE_INT offset) set_union_with_increment (bitmap to, bitmap from, HOST_WIDE_INT inc)
{ {
bitmap result = BITMAP_ALLOC (&iteration_obstack); bool changed = false;
unsigned int i;
bitmap_iterator bi; bitmap_iterator bi;
unsigned int i;
/* If the solution of FROM contains anything it is good enough to transfer
this to TO. */
if (bitmap_bit_p (from, anything_id))
return bitmap_set_bit (to, anything_id);
/* For zero offset simply union the solution into the destination. */
if (inc == 0)
return bitmap_ior_into (to, from);
/* If the offset is unknown we have to expand the solution to /* If the offset is unknown we have to expand the solution to
all subfields. */ all subfields. */
if (offset == UNKNOWN_OFFSET) if (inc == UNKNOWN_OFFSET)
{ {
solution_set_expand (set, set); bitmap tmp = BITMAP_ALLOC (&iteration_obstack);
return; bitmap_copy (tmp, from);
solution_set_expand (tmp);
changed |= bitmap_ior_into (to, tmp);
BITMAP_FREE (tmp);
return changed;
} }
EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi) /* For non-zero offset union the offsetted solution into the destination. */
EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
{ {
varinfo_t vi = get_varinfo (i); varinfo_t vi = get_varinfo (i);
...@@ -946,54 +973,30 @@ solution_set_add (bitmap set, HOST_WIDE_INT offset) ...@@ -946,54 +973,30 @@ solution_set_add (bitmap set, HOST_WIDE_INT offset)
if (vi->is_artificial_var if (vi->is_artificial_var
|| vi->is_unknown_size_var || vi->is_unknown_size_var
|| vi->is_full_var) || vi->is_full_var)
bitmap_set_bit (result, i); changed |= bitmap_set_bit (to, i);
else else
{ {
unsigned HOST_WIDE_INT fieldoffset = vi->offset + offset; unsigned HOST_WIDE_INT fieldoffset = vi->offset + inc;
/* If the offset makes the pointer point to before the /* If the offset makes the pointer point to before the
variable use offset zero for the field lookup. */ variable use offset zero for the field lookup. */
if (offset < 0 if (inc < 0
&& fieldoffset > vi->offset) && fieldoffset > vi->offset)
fieldoffset = 0; fieldoffset = 0;
if (offset != 0) vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
bitmap_set_bit (result, vi->id); changed |= bitmap_set_bit (to, vi->id);
/* If the result is not exactly at fieldoffset include the next /* If the result is not exactly at fieldoffset include the next
field as well. See get_constraint_for_ptr_offset for more field as well. See get_constraint_for_ptr_offset for more
rationale. */ rationale. */
if (vi->offset != fieldoffset if (vi->offset != fieldoffset
&& vi->next != NULL) && vi->next != 0)
bitmap_set_bit (result, vi->next->id); changed |= bitmap_set_bit (to, vi->next);
} }
} }
bitmap_copy (set, result); return changed;
BITMAP_FREE (result);
}
/* Union solution sets TO and FROM, and add INC to each member of FROM in the
process. */
static bool
set_union_with_increment (bitmap to, bitmap from, HOST_WIDE_INT inc)
{
if (inc == 0)
return bitmap_ior_into (to, from);
else
{
bitmap tmp;
bool res;
tmp = BITMAP_ALLOC (&iteration_obstack);
bitmap_copy (tmp, from);
solution_set_add (tmp, inc);
res = bitmap_ior_into (to, tmp);
BITMAP_FREE (tmp);
return res;
}
} }
/* Insert constraint C into the list of complex constraints for graph /* Insert constraint C into the list of complex constraints for graph
...@@ -1190,7 +1193,7 @@ build_pred_graph (void) ...@@ -1190,7 +1193,7 @@ build_pred_graph (void)
graph->address_taken = BITMAP_ALLOC (&predbitmap_obstack); graph->address_taken = BITMAP_ALLOC (&predbitmap_obstack);
bitmap_clear (graph->direct_nodes); bitmap_clear (graph->direct_nodes);
for (j = 0; j < FIRST_REF_NODE; j++) for (j = 1; j < FIRST_REF_NODE; j++)
{ {
if (!get_varinfo (j)->is_special_var) if (!get_varinfo (j)->is_special_var)
bitmap_set_bit (graph->direct_nodes, j); bitmap_set_bit (graph->direct_nodes, j);
...@@ -1244,11 +1247,11 @@ build_pred_graph (void) ...@@ -1244,11 +1247,11 @@ build_pred_graph (void)
v = get_varinfo (rhsvar); v = get_varinfo (rhsvar);
if (!v->is_full_var) if (!v->is_full_var)
{ {
v = lookup_vi_for_tree (v->decl); v = get_varinfo (v->head);
do do
{ {
bitmap_clear_bit (graph->direct_nodes, v->id); bitmap_clear_bit (graph->direct_nodes, v->id);
v = v->next; v = vi_next (v);
} }
while (v != NULL); while (v != NULL);
} }
...@@ -1578,7 +1581,7 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c, ...@@ -1578,7 +1581,7 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
dereferenced at all valid offsets. */ dereferenced at all valid offsets. */
if (roffset == UNKNOWN_OFFSET) if (roffset == UNKNOWN_OFFSET)
{ {
solution_set_expand (delta, delta); solution_set_expand (delta);
/* No further offset processing is necessary. */ /* No further offset processing is necessary. */
roffset = 0; roffset = 0;
} }
...@@ -1618,10 +1621,10 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c, ...@@ -1618,10 +1621,10 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
/* If the variable is not exactly at the requested offset /* If the variable is not exactly at the requested offset
we have to include the next one. */ we have to include the next one. */
if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset
|| v->next == NULL) || v->next == 0)
break; break;
v = v->next; v = vi_next (v);
fieldoffset = v->offset; fieldoffset = v->offset;
} }
while (1); while (1);
...@@ -1676,7 +1679,7 @@ do_ds_constraint (constraint_t c, bitmap delta) ...@@ -1676,7 +1679,7 @@ do_ds_constraint (constraint_t c, bitmap delta)
dereferenced at all valid offsets. */ dereferenced at all valid offsets. */
if (loff == UNKNOWN_OFFSET) if (loff == UNKNOWN_OFFSET)
{ {
solution_set_expand (delta, delta); solution_set_expand (delta);
loff = 0; loff = 0;
} }
...@@ -1724,10 +1727,10 @@ do_ds_constraint (constraint_t c, bitmap delta) ...@@ -1724,10 +1727,10 @@ do_ds_constraint (constraint_t c, bitmap delta)
/* If the variable is not exactly at the requested offset /* If the variable is not exactly at the requested offset
we have to include the next one. */ we have to include the next one. */
if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset
|| v->next == NULL) || v->next == 0)
break; break;
v = v->next; v = vi_next (v);
fieldoffset = v->offset; fieldoffset = v->offset;
} }
while (1); while (1);
...@@ -1771,10 +1774,7 @@ do_complex_constraint (constraint_graph_t graph, constraint_t c, bitmap delta) ...@@ -1771,10 +1774,7 @@ do_complex_constraint (constraint_graph_t graph, constraint_t c, bitmap delta)
flag = set_union_with_increment (tmp, solution, c->rhs.offset); flag = set_union_with_increment (tmp, solution, c->rhs.offset);
if (flag) if (flag)
{ bitmap_set_bit (changed, c->lhs.var);
get_varinfo (c->lhs.var)->solution = tmp;
bitmap_set_bit (changed, c->lhs.var);
}
} }
} }
...@@ -2160,8 +2160,10 @@ dump_pred_graph (struct scc_info *si, FILE *file) ...@@ -2160,8 +2160,10 @@ dump_pred_graph (struct scc_info *si, FILE *file)
/* The next lines print the nodes in the graph together with the /* The next lines print the nodes in the graph together with the
complex constraints attached to them. */ complex constraints attached to them. */
for (i = 0; i < graph->size; i++) for (i = 1; i < graph->size; i++)
{ {
if (i == FIRST_REF_NODE)
continue;
if (si->node_mapping[i] != i) if (si->node_mapping[i] != i)
continue; continue;
if (i < FIRST_REF_NODE) if (i < FIRST_REF_NODE)
...@@ -2183,7 +2185,7 @@ dump_pred_graph (struct scc_info *si, FILE *file) ...@@ -2183,7 +2185,7 @@ dump_pred_graph (struct scc_info *si, FILE *file)
/* Go over the edges. */ /* Go over the edges. */
fprintf (file, "\n // Edges in the constraint graph:\n"); fprintf (file, "\n // Edges in the constraint graph:\n");
for (i = 0; i < graph->size; i++) for (i = 1; i < graph->size; i++)
{ {
unsigned j; unsigned j;
bitmap_iterator bi; bitmap_iterator bi;
...@@ -2229,7 +2231,7 @@ perform_var_substitution (constraint_graph_t graph) ...@@ -2229,7 +2231,7 @@ perform_var_substitution (constraint_graph_t graph)
/* Condense the nodes, which means to find SCC's, count incoming /* Condense the nodes, which means to find SCC's, count incoming
predecessors, and unite nodes in SCC's. */ predecessors, and unite nodes in SCC's. */
for (i = 0; i < FIRST_REF_NODE; i++) for (i = 1; i < FIRST_REF_NODE; i++)
if (!bitmap_bit_p (si->visited, si->node_mapping[i])) if (!bitmap_bit_p (si->visited, si->node_mapping[i]))
condense_visit (graph, si, si->node_mapping[i]); condense_visit (graph, si, si->node_mapping[i]);
...@@ -2243,12 +2245,12 @@ perform_var_substitution (constraint_graph_t graph) ...@@ -2243,12 +2245,12 @@ perform_var_substitution (constraint_graph_t graph)
bitmap_clear (si->visited); bitmap_clear (si->visited);
/* Actually the label the nodes for pointer equivalences */ /* Actually the label the nodes for pointer equivalences */
for (i = 0; i < FIRST_REF_NODE; i++) for (i = 1; i < FIRST_REF_NODE; i++)
if (!bitmap_bit_p (si->visited, si->node_mapping[i])) if (!bitmap_bit_p (si->visited, si->node_mapping[i]))
label_visit (graph, si, si->node_mapping[i]); label_visit (graph, si, si->node_mapping[i]);
/* Calculate location equivalence labels. */ /* Calculate location equivalence labels. */
for (i = 0; i < FIRST_REF_NODE; i++) for (i = 1; i < FIRST_REF_NODE; i++)
{ {
bitmap pointed_by; bitmap pointed_by;
bitmap_iterator bi; bitmap_iterator bi;
...@@ -2286,7 +2288,7 @@ perform_var_substitution (constraint_graph_t graph) ...@@ -2286,7 +2288,7 @@ perform_var_substitution (constraint_graph_t graph)
} }
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
for (i = 0; i < FIRST_REF_NODE; i++) for (i = 1; i < FIRST_REF_NODE; i++)
{ {
unsigned j = si->node_mapping[i]; unsigned j = si->node_mapping[i];
if (j != i) if (j != i)
...@@ -2306,7 +2308,7 @@ perform_var_substitution (constraint_graph_t graph) ...@@ -2306,7 +2308,7 @@ perform_var_substitution (constraint_graph_t graph)
/* Quickly eliminate our non-pointer variables. */ /* Quickly eliminate our non-pointer variables. */
for (i = 0; i < FIRST_REF_NODE; i++) for (i = 1; i < FIRST_REF_NODE; i++)
{ {
unsigned int node = si->node_mapping[i]; unsigned int node = si->node_mapping[i];
...@@ -2393,7 +2395,7 @@ unite_pointer_equivalences (constraint_graph_t graph) ...@@ -2393,7 +2395,7 @@ unite_pointer_equivalences (constraint_graph_t graph)
/* Go through the pointer equivalences and unite them to their /* Go through the pointer equivalences and unite them to their
representative, if they aren't already. */ representative, if they aren't already. */
for (i = 0; i < FIRST_REF_NODE; i++) for (i = 1; i < FIRST_REF_NODE; i++)
{ {
unsigned int label = graph->pe[i]; unsigned int label = graph->pe[i];
if (label) if (label)
...@@ -2570,7 +2572,7 @@ solve_graph (constraint_graph_t graph) ...@@ -2570,7 +2572,7 @@ solve_graph (constraint_graph_t graph)
changed = BITMAP_ALLOC (NULL); changed = BITMAP_ALLOC (NULL);
/* Mark all initial non-collapsed nodes as changed. */ /* Mark all initial non-collapsed nodes as changed. */
for (i = 0; i < size; i++) for (i = 1; i < size; i++)
{ {
varinfo_t ivi = get_varinfo (i); varinfo_t ivi = get_varinfo (i);
if (find (i) == i && !bitmap_empty_p (ivi->solution) if (find (i) == i && !bitmap_empty_p (ivi->solution)
...@@ -2617,8 +2619,19 @@ solve_graph (constraint_graph_t graph) ...@@ -2617,8 +2619,19 @@ solve_graph (constraint_graph_t graph)
varinfo_t vi = get_varinfo (i); varinfo_t vi = get_varinfo (i);
bool solution_empty; bool solution_empty;
/* Compute the changed set of solution bits. */ /* Compute the changed set of solution bits. If anything
if (vi->oldsolution) is in the solution just propagate that. */
if (bitmap_bit_p (vi->solution, anything_id))
{
/* If anything is also in the old solution there is
nothing to do.
??? But we shouldn't ended up with "changed" set ... */
if (vi->oldsolution
&& bitmap_bit_p (vi->oldsolution, anything_id))
continue;
bitmap_copy (pts, get_varinfo (find (anything_id))->solution);
}
else if (vi->oldsolution)
bitmap_and_compl (pts, vi->solution, vi->oldsolution); bitmap_and_compl (pts, vi->solution, vi->oldsolution);
else else
bitmap_copy (pts, vi->solution); bitmap_copy (pts, vi->solution);
...@@ -2682,13 +2695,10 @@ solve_graph (constraint_graph_t graph) ...@@ -2682,13 +2695,10 @@ solve_graph (constraint_graph_t graph)
if (i == eff_escaped_id) if (i == eff_escaped_id)
flag = bitmap_set_bit (tmp, escaped_id); flag = bitmap_set_bit (tmp, escaped_id);
else else
flag = set_union_with_increment (tmp, pts, 0); flag = bitmap_ior_into (tmp, pts);
if (flag) if (flag)
{ bitmap_set_bit (changed, to);
get_varinfo (to)->solution = tmp;
bitmap_set_bit (changed, to);
}
} }
} }
} }
...@@ -2866,7 +2876,7 @@ get_constraint_for_ssa_var (tree t, vec<ce_s> *results, bool address_p) ...@@ -2866,7 +2876,7 @@ get_constraint_for_ssa_var (tree t, vec<ce_s> *results, bool address_p)
if (!address_p if (!address_p
&& !vi->is_full_var) && !vi->is_full_var)
{ {
for (; vi; vi = vi->next) for (; vi; vi = vi_next (vi))
{ {
cexpr.var = vi->id; cexpr.var = vi->id;
results->safe_push (cexpr); results->safe_push (cexpr);
...@@ -3013,7 +3023,7 @@ get_constraint_for_ptr_offset (tree ptr, tree offset, ...@@ -3013,7 +3023,7 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
/* If we do not know the offset add all subfields. */ /* If we do not know the offset add all subfields. */
&& rhsoffset == UNKNOWN_OFFSET) && rhsoffset == UNKNOWN_OFFSET)
{ {
varinfo_t temp = lookup_vi_for_tree (curr->decl); varinfo_t temp = get_varinfo (curr->head);
do do
{ {
struct constraint_expr c2; struct constraint_expr c2;
...@@ -3022,7 +3032,7 @@ get_constraint_for_ptr_offset (tree ptr, tree offset, ...@@ -3022,7 +3032,7 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
c2.offset = 0; c2.offset = 0;
if (c2.var != c.var) if (c2.var != c.var)
results->safe_push (c2); results->safe_push (c2);
temp = temp->next; temp = vi_next (temp);
} }
while (temp); while (temp);
} }
...@@ -3050,10 +3060,10 @@ get_constraint_for_ptr_offset (tree ptr, tree offset, ...@@ -3050,10 +3060,10 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
do not result in the same or a conservative superset do not result in the same or a conservative superset
solution. */ solution. */
if (temp->offset != offset if (temp->offset != offset
&& temp->next != NULL) && temp->next != 0)
{ {
struct constraint_expr c2; struct constraint_expr c2;
c2.var = temp->next->id; c2.var = temp->next;
c2.type = ADDRESSOF; c2.type = ADDRESSOF;
c2.offset = 0; c2.offset = 0;
results->safe_push (c2); results->safe_push (c2);
...@@ -3156,7 +3166,7 @@ get_constraint_for_component_ref (tree t, vec<ce_s> *results, ...@@ -3156,7 +3166,7 @@ get_constraint_for_component_ref (tree t, vec<ce_s> *results,
varinfo_t curr; varinfo_t curr;
results->pop (); results->pop ();
cexpr.offset = 0; cexpr.offset = 0;
for (curr = get_varinfo (cexpr.var); curr; curr = curr->next) for (curr = get_varinfo (cexpr.var); curr; curr = vi_next (curr))
{ {
if (ranges_overlap_p (curr->offset, curr->size, if (ranges_overlap_p (curr->offset, curr->size,
bitpos, bitmaxsize)) bitpos, bitmaxsize))
...@@ -3173,8 +3183,8 @@ get_constraint_for_component_ref (tree t, vec<ce_s> *results, ...@@ -3173,8 +3183,8 @@ get_constraint_for_component_ref (tree t, vec<ce_s> *results,
if (address_p && results->length () == 0) if (address_p && results->length () == 0)
{ {
curr = get_varinfo (cexpr.var); curr = get_varinfo (cexpr.var);
while (curr->next != NULL) while (curr->next != 0)
curr = curr->next; curr = vi_next (curr);
cexpr.var = curr->id; cexpr.var = curr->id;
results->safe_push (cexpr); results->safe_push (cexpr);
} }
...@@ -3370,7 +3380,7 @@ get_constraint_for_1 (tree t, vec<ce_s> *results, bool address_p, ...@@ -3370,7 +3380,7 @@ get_constraint_for_1 (tree t, vec<ce_s> *results, bool address_p,
return; return;
vi = get_varinfo (cs.var); vi = get_varinfo (cs.var);
curr = vi->next; curr = vi_next (vi);
if (!vi->is_full_var if (!vi->is_full_var
&& curr) && curr)
{ {
...@@ -3379,7 +3389,7 @@ get_constraint_for_1 (tree t, vec<ce_s> *results, bool address_p, ...@@ -3379,7 +3389,7 @@ get_constraint_for_1 (tree t, vec<ce_s> *results, bool address_p,
size = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (t))); size = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (t)));
else else
size = -1; size = -1;
for (; curr; curr = curr->next) for (; curr; curr = vi_next (curr))
{ {
if (curr->offset - vi->offset < size) if (curr->offset - vi->offset < size)
{ {
...@@ -5075,7 +5085,7 @@ first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset) ...@@ -5075,7 +5085,7 @@ first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset)
/* If we cannot reach offset from start, lookup the first field /* If we cannot reach offset from start, lookup the first field
and start from there. */ and start from there. */
if (start->offset > offset) if (start->offset > offset)
start = lookup_vi_for_tree (start->decl); start = get_varinfo (start->head);
while (start) while (start)
{ {
...@@ -5087,7 +5097,7 @@ first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset) ...@@ -5087,7 +5097,7 @@ first_vi_for_offset (varinfo_t start, unsigned HOST_WIDE_INT offset)
&& (offset - start->offset) < start->size) && (offset - start->offset) < start->size)
return start; return start;
start= start->next; start = vi_next (start);
} }
return NULL; return NULL;
...@@ -5104,7 +5114,7 @@ first_or_preceding_vi_for_offset (varinfo_t start, ...@@ -5104,7 +5114,7 @@ first_or_preceding_vi_for_offset (varinfo_t start,
/* If we cannot reach offset from start, lookup the first field /* If we cannot reach offset from start, lookup the first field
and start from there. */ and start from there. */
if (start->offset > offset) if (start->offset > offset)
start = lookup_vi_for_tree (start->decl); start = get_varinfo (start->head);
/* We may not find a variable in the field list with the actual /* We may not find a variable in the field list with the actual
offset when when we have glommed a structure to a variable. offset when when we have glommed a structure to a variable.
...@@ -5115,7 +5125,7 @@ first_or_preceding_vi_for_offset (varinfo_t start, ...@@ -5115,7 +5125,7 @@ first_or_preceding_vi_for_offset (varinfo_t start,
while (start->next while (start->next
&& offset >= start->offset && offset >= start->offset
&& !((offset - start->offset) < start->size)) && !((offset - start->offset) < start->size))
start = start->next; start = vi_next (start);
return start; return start;
} }
...@@ -5398,7 +5408,7 @@ create_function_info_for (tree decl, const char *name) ...@@ -5398,7 +5408,7 @@ create_function_info_for (tree decl, const char *name)
clobbervi->is_full_var = true; clobbervi->is_full_var = true;
clobbervi->is_global_var = false; clobbervi->is_global_var = false;
gcc_assert (prev_vi->offset < clobbervi->offset); gcc_assert (prev_vi->offset < clobbervi->offset);
prev_vi->next = clobbervi; prev_vi->next = clobbervi->id;
prev_vi = clobbervi; prev_vi = clobbervi;
asprintf (&tempname, "%s.use", name); asprintf (&tempname, "%s.use", name);
...@@ -5412,7 +5422,7 @@ create_function_info_for (tree decl, const char *name) ...@@ -5412,7 +5422,7 @@ create_function_info_for (tree decl, const char *name)
usevi->is_full_var = true; usevi->is_full_var = true;
usevi->is_global_var = false; usevi->is_global_var = false;
gcc_assert (prev_vi->offset < usevi->offset); gcc_assert (prev_vi->offset < usevi->offset);
prev_vi->next = usevi; prev_vi->next = usevi->id;
prev_vi = usevi; prev_vi = usevi;
} }
...@@ -5434,7 +5444,7 @@ create_function_info_for (tree decl, const char *name) ...@@ -5434,7 +5444,7 @@ create_function_info_for (tree decl, const char *name)
chainvi->is_full_var = true; chainvi->is_full_var = true;
chainvi->is_global_var = false; chainvi->is_global_var = false;
gcc_assert (prev_vi->offset < chainvi->offset); gcc_assert (prev_vi->offset < chainvi->offset);
prev_vi->next = chainvi; prev_vi->next = chainvi->id;
prev_vi = chainvi; prev_vi = chainvi;
insert_vi_for_tree (fn->static_chain_decl, chainvi); insert_vi_for_tree (fn->static_chain_decl, chainvi);
} }
...@@ -5463,7 +5473,7 @@ create_function_info_for (tree decl, const char *name) ...@@ -5463,7 +5473,7 @@ create_function_info_for (tree decl, const char *name)
if (DECL_RESULT (decl)) if (DECL_RESULT (decl))
resultvi->may_have_pointers = true; resultvi->may_have_pointers = true;
gcc_assert (prev_vi->offset < resultvi->offset); gcc_assert (prev_vi->offset < resultvi->offset);
prev_vi->next = resultvi; prev_vi->next = resultvi->id;
prev_vi = resultvi; prev_vi = resultvi;
if (DECL_RESULT (decl)) if (DECL_RESULT (decl))
insert_vi_for_tree (DECL_RESULT (decl), resultvi); insert_vi_for_tree (DECL_RESULT (decl), resultvi);
...@@ -5493,7 +5503,7 @@ create_function_info_for (tree decl, const char *name) ...@@ -5493,7 +5503,7 @@ create_function_info_for (tree decl, const char *name)
if (arg) if (arg)
argvi->may_have_pointers = true; argvi->may_have_pointers = true;
gcc_assert (prev_vi->offset < argvi->offset); gcc_assert (prev_vi->offset < argvi->offset);
prev_vi->next = argvi; prev_vi->next = argvi->id;
prev_vi = argvi; prev_vi = argvi;
if (arg) if (arg)
{ {
...@@ -5524,7 +5534,7 @@ create_function_info_for (tree decl, const char *name) ...@@ -5524,7 +5534,7 @@ create_function_info_for (tree decl, const char *name)
argvi->is_heap_var = true; argvi->is_heap_var = true;
argvi->fullsize = vi->fullsize; argvi->fullsize = vi->fullsize;
gcc_assert (prev_vi->offset < argvi->offset); gcc_assert (prev_vi->offset < argvi->offset);
prev_vi->next = argvi; prev_vi->next = argvi->id;
prev_vi = argvi; prev_vi = argvi;
} }
...@@ -5638,7 +5648,7 @@ create_variable_info_for_1 (tree decl, const char *name) ...@@ -5638,7 +5648,7 @@ create_variable_info_for_1 (tree decl, const char *name)
vi->fullsize = TREE_INT_CST_LOW (declsize); vi->fullsize = TREE_INT_CST_LOW (declsize);
for (i = 0, newvi = vi; for (i = 0, newvi = vi;
fieldstack.iterate (i, &fo); fieldstack.iterate (i, &fo);
++i, newvi = newvi->next) ++i, newvi = vi_next (newvi))
{ {
const char *newname = "NULL"; const char *newname = "NULL";
char *tempname; char *tempname;
...@@ -5657,7 +5667,11 @@ create_variable_info_for_1 (tree decl, const char *name) ...@@ -5657,7 +5667,11 @@ create_variable_info_for_1 (tree decl, const char *name)
newvi->may_have_pointers = fo->may_have_pointers; newvi->may_have_pointers = fo->may_have_pointers;
newvi->only_restrict_pointers = fo->only_restrict_pointers; newvi->only_restrict_pointers = fo->only_restrict_pointers;
if (i + 1 < fieldstack.length ()) if (i + 1 < fieldstack.length ())
newvi->next = new_var_info (decl, name); {
varinfo_t tem = new_var_info (decl, name);
newvi->next = tem->id;
tem->head = vi->id;
}
} }
fieldstack.release (); fieldstack.release ();
...@@ -5677,7 +5691,7 @@ create_variable_info_for (tree decl, const char *name) ...@@ -5677,7 +5691,7 @@ create_variable_info_for (tree decl, const char *name)
return id; return id;
/* Create initial constraints for globals. */ /* Create initial constraints for globals. */
for (; vi; vi = vi->next) for (; vi; vi = vi_next (vi))
{ {
if (!vi->may_have_pointers if (!vi->may_have_pointers
|| !vi->is_global_var) || !vi->is_global_var)
...@@ -5807,7 +5821,7 @@ intra_create_variable_infos (void) ...@@ -5807,7 +5821,7 @@ intra_create_variable_infos (void)
rhsc.type = ADDRESSOF; rhsc.type = ADDRESSOF;
rhsc.offset = 0; rhsc.offset = 0;
process_constraint (new_constraint (lhsc, rhsc)); process_constraint (new_constraint (lhsc, rhsc));
for (; vi; vi = vi->next) for (; vi; vi = vi_next (vi))
if (vi->may_have_pointers) if (vi->may_have_pointers)
{ {
if (vi->only_restrict_pointers) if (vi->only_restrict_pointers)
...@@ -5823,7 +5837,7 @@ intra_create_variable_infos (void) ...@@ -5823,7 +5837,7 @@ intra_create_variable_infos (void)
make_constraint_from_global_restrict (p, "PARM_RESTRICT"); make_constraint_from_global_restrict (p, "PARM_RESTRICT");
else else
{ {
for (; p; p = p->next) for (; p; p = vi_next (p))
{ {
if (p->only_restrict_pointers) if (p->only_restrict_pointers)
make_constraint_from_global_restrict (p, "PARM_RESTRICT"); make_constraint_from_global_restrict (p, "PARM_RESTRICT");
...@@ -5839,7 +5853,7 @@ intra_create_variable_infos (void) ...@@ -5839,7 +5853,7 @@ intra_create_variable_infos (void)
{ {
varinfo_t p, result_vi = get_vi_for_tree (DECL_RESULT (cfun->decl)); varinfo_t p, result_vi = get_vi_for_tree (DECL_RESULT (cfun->decl));
for (p = result_vi; p; p = p->next) for (p = result_vi; p; p = vi_next (p))
make_constraint_from (p, nonlocal_id); make_constraint_from (p, nonlocal_id);
} }
...@@ -5848,7 +5862,7 @@ intra_create_variable_infos (void) ...@@ -5848,7 +5862,7 @@ intra_create_variable_infos (void)
{ {
varinfo_t p, chain_vi = get_vi_for_tree (cfun->static_chain_decl); varinfo_t p, chain_vi = get_vi_for_tree (cfun->static_chain_decl);
for (p = chain_vi; p; p = p->next) for (p = chain_vi; p; p = vi_next (p))
make_constraint_from (p, nonlocal_id); make_constraint_from (p, nonlocal_id);
} }
} }
...@@ -6363,7 +6377,7 @@ dump_sa_points_to_info (FILE *outfile) ...@@ -6363,7 +6377,7 @@ dump_sa_points_to_info (FILE *outfile)
stats.num_implicit_edges); stats.num_implicit_edges);
} }
for (i = 0; i < varmap.length (); i++) for (i = 1; i < varmap.length (); i++)
{ {
varinfo_t vi = get_varinfo (i); varinfo_t vi = get_varinfo (i);
if (!vi->may_have_pointers) if (!vi->may_have_pointers)
...@@ -6397,6 +6411,9 @@ init_base_vars (void) ...@@ -6397,6 +6411,9 @@ init_base_vars (void)
varinfo_t var_storedanything; varinfo_t var_storedanything;
varinfo_t var_integer; varinfo_t var_integer;
/* Variable ID zero is reserved and should be NULL. */
varmap.safe_push (NULL);
/* Create the NULL variable, used to represent that a variable points /* Create the NULL variable, used to represent that a variable points
to NULL. */ to NULL. */
var_nothing = new_var_info (NULL_TREE, "NULL"); var_nothing = new_var_info (NULL_TREE, "NULL");
...@@ -6416,7 +6433,6 @@ init_base_vars (void) ...@@ -6416,7 +6433,6 @@ init_base_vars (void)
var_anything->is_artificial_var = 1; var_anything->is_artificial_var = 1;
var_anything->size = ~0; var_anything->size = ~0;
var_anything->offset = 0; var_anything->offset = 0;
var_anything->next = NULL;
var_anything->fullsize = ~0; var_anything->fullsize = ~0;
var_anything->is_special_var = 1; var_anything->is_special_var = 1;
...@@ -6443,7 +6459,6 @@ init_base_vars (void) ...@@ -6443,7 +6459,6 @@ init_base_vars (void)
var_readonly->offset = 0; var_readonly->offset = 0;
var_readonly->size = ~0; var_readonly->size = ~0;
var_readonly->fullsize = ~0; var_readonly->fullsize = ~0;
var_readonly->next = NULL;
var_readonly->is_special_var = 1; var_readonly->is_special_var = 1;
/* readonly memory points to anything, in order to make deref /* readonly memory points to anything, in order to make deref
...@@ -6540,7 +6555,6 @@ init_base_vars (void) ...@@ -6540,7 +6555,6 @@ init_base_vars (void)
var_integer->size = ~0; var_integer->size = ~0;
var_integer->fullsize = ~0; var_integer->fullsize = ~0;
var_integer->offset = 0; var_integer->offset = 0;
var_integer->next = NULL;
var_integer->is_special_var = 1; var_integer->is_special_var = 1;
/* INTEGER = ANYTHING, because we don't know where a dereference of /* INTEGER = ANYTHING, because we don't know where a dereference of
...@@ -6595,7 +6609,7 @@ remove_preds_and_fake_succs (constraint_graph_t graph) ...@@ -6595,7 +6609,7 @@ remove_preds_and_fake_succs (constraint_graph_t graph)
/* Clear the implicit ref and address nodes from the successor /* Clear the implicit ref and address nodes from the successor
lists. */ lists. */
for (i = 0; i < FIRST_REF_NODE; i++) for (i = 1; i < FIRST_REF_NODE; i++)
{ {
if (graph->succs[i]) if (graph->succs[i])
bitmap_clear_range (graph->succs[i], FIRST_REF_NODE, bitmap_clear_range (graph->succs[i], FIRST_REF_NODE,
...@@ -6603,7 +6617,7 @@ remove_preds_and_fake_succs (constraint_graph_t graph) ...@@ -6603,7 +6617,7 @@ remove_preds_and_fake_succs (constraint_graph_t graph)
} }
/* Free the successor list for the non-ref nodes. */ /* Free the successor list for the non-ref nodes. */
for (i = FIRST_REF_NODE; i < graph->size; i++) for (i = FIRST_REF_NODE + 1; i < graph->size; i++)
{ {
if (graph->succs[i]) if (graph->succs[i])
BITMAP_FREE (graph->succs[i]); BITMAP_FREE (graph->succs[i]);
...@@ -6750,7 +6764,8 @@ compute_points_to_sets (void) ...@@ -6750,7 +6764,8 @@ compute_points_to_sets (void)
/* Mark escaped HEAP variables as global. */ /* Mark escaped HEAP variables as global. */
FOR_EACH_VEC_ELT (varmap, i, vi) FOR_EACH_VEC_ELT (varmap, i, vi)
if (vi->is_heap_var if (vi
&& vi->is_heap_var
&& !vi->is_global_var) && !vi->is_global_var)
DECL_EXTERNAL (vi->decl) = vi->is_global_var DECL_EXTERNAL (vi->decl) = vi->is_global_var
= pt_solution_includes (&cfun->gimple_df->escaped, vi->decl); = pt_solution_includes (&cfun->gimple_df->escaped, vi->decl);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment