Fix PR 32772 Fix PR 32716 Fix PR 32328 Fix PR 32303

2007-08-19  Daniel Berlin  <dberlin@dberlin.org>

	Fix PR 32772
	Fix PR 32716
	Fix PR 32328
	Fix PR 32303

	* tree-flow.h (struct stmt_ann_d): Remove makes_clobbering_call.
	* tree-ssa-alias.c (init_transitive_clobber_worklist): Add
	on_worklist argument and avoid adding things to worklist multiple
	times.
	(add_to_worklist): Ditto.
	(mark_aliases_call_clobbered): Mark entire structure clobbered if
	single SFT is clobbered.
	(set_initial_properties): Ditto.
	(compute_call_clobbered): Update for changes to function
	arguments.
	(create_overlap_variables_for): Always create SFT for offset 0.
	(create_structure_vars): Handle PHI's, since we are in SSA form at
	this point.
	* tree-ssa-loop-ivopts.c (get_ref_tag): Don't return subvars.
	* tree-ssa-operands.c (access_can_touch_variable): Don't handle
	TARGET_MEM_REF.
	(add_vars_for_offset): Figure out aliases from access + points-to.
	(add_virtual_operand): Use add_vars-for_offset.
	(get_tmr_operands): Update for NMT changes, rewrite to be correct.
	(add_call_clobber_ops): Remove makes_clobbering_call set.
	(get_expr_operands): Always pass through the INDIRECT_REF
	reference.
	* tree-ssa-structalias.c (struct constraint_graph): Remove
	variables member.
	Add pe, pe_rep, pointer_label, loc_label, pointed_by, points_to,
	address_taken, pt_used, number_incoming.
	(FIRST_ADDR_NODE): Removed.
	(merge_graph_nodes): Remove broken code for the moment.
	(init_graph): New function.
	(build_pred_graph): Remove code to init_graph.
	Add location equivalence support.
	(struct scc_info): Rename roots to deleted.
	(scc_visit): Ditto.
	(init_scc_info): Ditto
	(init_topo_info): Use graph->size.
	(compute_topo_order): Ditto.
	(do_da_constraint): Removed.
	(do_sd_constraint): Remove calls to find().
	set_union_with_increment should always get 0 as last arg here.
	(do_complex_constraint): Replace do_da_constraint with assert.
	Stop calling find.
	(struct equiv_class_label): New.
	(pointer_equiv_class_table): Ditto.
	(location_equiv_class_table): Ditto.
	(equiv_class_label_hash): Ditto.
	(equiv_class_label_eq): Ditto
	(equiv_class_lookup): Ditto.
	(equiv_class_ladd): Ditto.
	(pointer_equiv_class): Ditto.
	(location_equiv_class): Ditto.
	(condense_visit): Rename and rewrite from label_visit to do only
	SCC related stuff for HU.
	(label_visit): Do HU work for HU.
	(perform_var_substitution): Update to do HU and location
	equivalence.
	(free_var_substitution_info): Update to free HU and location
	equivalence structures.  */
	(find_equivalent_node): Update for pointer but not location
	equivalence.
	(unite_pointer_equivalences): New function.
	(move_complex_constraints): Rewrite to only do moving.
	(rewrite_constraints): Split out of move_complex_constraints.
	(solve_graph): Use graph->size.
	(process_constraint_1): Add from_call argument, use it.
	Split *a = &b into two constraints.
	(process_constraint): Use new process_constraint_1.
	(get_constraint_for_component_ref): Handle bitmaxsize == -1 case.
	(get_constraint_for): Handle non-pointer integers properly.
	Remove code that used to handle structures.
	(handle_ptr_arith): Fix a few bugs in pointer arithmetic handling
	with unknown addends.
	(handle_rhs_call): New function.
	(find_func_aliases): Use handle_rhs_call.
	(set_uids_in_ptset): Add an assert.
	(set_used_smts): Fix bug in not considering unified vars.
	(compute_tbaa_pruning): Stop initing useless iteration_obstack.
	(compute_points_to_sets): Update for other function changes.
	(delete_points_to_sets): Ditto.
	(ipa_pta_execute): Ditto.
	(pass_ipa_pta): We need to update SSA after ipa_pta.

From-SVN: r127629
This commit is contained in:
Daniel Berlin 2007-08-19 23:23:29 +00:00 committed by Daniel Berlin
parent 73f486583f
commit 7b765bedc0
6 changed files with 1008 additions and 440 deletions

View file

@ -1,3 +1,91 @@
2007-08-19 Daniel Berlin <dberlin@dberlin.org>
Fix PR 32772
Fix PR 32716
Fix PR 32328
Fix PR 32303
* tree-flow.h (struct stmt_ann_d): Remove makes_clobbering_call.
* tree-ssa-alias.c (init_transitive_clobber_worklist): Add
on_worklist argument and avoid adding things to worklist multiple
times.
(add_to_worklist): Ditto.
(mark_aliases_call_clobbered): Mark entire structure clobbered if
single SFT is clobbered.
(set_initial_properties): Ditto.
(compute_call_clobbered): Update for changes to function
arguments.
(create_overlap_variables_for): Always create SFT for offset 0.
(create_structure_vars): Handle PHI's, since we are in SSA form at
this point.
* tree-ssa-loop-ivopts.c (get_ref_tag): Don't return subvars.
* tree-ssa-operands.c (access_can_touch_variable): Don't handle
TARGET_MEM_REF.
(add_vars_for_offset): Figure out aliases from access + points-to.
(add_virtual_operand): Use add_vars-for_offset.
(get_tmr_operands): Update for NMT changes, rewrite to be correct.
(add_call_clobber_ops): Remove makes_clobbering_call set.
(get_expr_operands): Always pass through the INDIRECT_REF
reference.
* tree-ssa-structalias.c (struct constraint_graph): Remove
variables member.
Add pe, pe_rep, pointer_label, loc_label, pointed_by, points_to,
address_taken, pt_used, number_incoming.
(FIRST_ADDR_NODE): Removed.
(merge_graph_nodes): Remove broken code for the moment.
(init_graph): New function.
(build_pred_graph): Remove code to init_graph.
Add location equivalence support.
(struct scc_info): Rename roots to deleted.
(scc_visit): Ditto.
(init_scc_info): Ditto
(init_topo_info): Use graph->size.
(compute_topo_order): Ditto.
(do_da_constraint): Removed.
(do_sd_constraint): Remove calls to find().
set_union_with_increment should always get 0 as last arg here.
(do_complex_constraint): Replace do_da_constraint with assert.
Stop calling find.
(struct equiv_class_label): New.
(pointer_equiv_class_table): Ditto.
(location_equiv_class_table): Ditto.
(equiv_class_label_hash): Ditto.
(equiv_class_label_eq): Ditto
(equiv_class_lookup): Ditto.
(equiv_class_ladd): Ditto.
(pointer_equiv_class): Ditto.
(location_equiv_class): Ditto.
(condense_visit): Rename and rewrite from label_visit to do only
SCC related stuff for HU.
(label_visit): Do HU work for HU.
(perform_var_substitution): Update to do HU and location
equivalence.
(free_var_substitution_info): Update to free HU and location
equivalence structures. */
(find_equivalent_node): Update for pointer but not location
equivalence.
(unite_pointer_equivalences): New function.
(move_complex_constraints): Rewrite to only do moving.
(rewrite_constraints): Split out of move_complex_constraints.
(solve_graph): Use graph->size.
(process_constraint_1): Add from_call argument, use it.
Split *a = &b into two constraints.
(process_constraint): Use new process_constraint_1.
(get_constraint_for_component_ref): Handle bitmaxsize == -1 case.
(get_constraint_for): Handle non-pointer integers properly.
Remove code that used to handle structures.
(handle_ptr_arith): Fix a few bugs in pointer arithmetic handling
with unknown addends.
(handle_rhs_call): New function.
(find_func_aliases): Use handle_rhs_call.
(set_uids_in_ptset): Add an assert.
(set_used_smts): Fix bug in not considering unified vars.
(compute_tbaa_pruning): Stop initing useless iteration_obstack.
(compute_points_to_sets): Update for other function changes.
(delete_points_to_sets): Ditto.
(ipa_pta_execute): Ditto.
(pass_ipa_pta): We need to update SSA after ipa_pta.
2007-08-19 Jan Hubicka <jh@suse.cz>
* i386.md: Replace "rim" and "mri" constraints by "g".

View file

@ -498,10 +498,6 @@ struct stmt_ann_d GTY(())
/* Nonzero if the statement makes references to volatile storage. */
unsigned has_volatile_ops : 1;
/* Nonzero if the statement makes a function call that may clobber global
and local addressable variables. */
unsigned makes_clobbering_call : 1;
};
union tree_ann_d GTY((desc ("ann_type ((tree_ann_t)&%h)")))

View file

@ -322,7 +322,8 @@ sort_tags_by_id (const void *pa, const void *pb)
static void
init_transitive_clobber_worklist (VEC (tree, heap) **worklist,
VEC (int, heap) **worklist2)
VEC (int, heap) **worklist2,
bitmap on_worklist)
{
referenced_var_iterator rvi;
tree curr;
@ -332,7 +333,9 @@ init_transitive_clobber_worklist (VEC (tree, heap) **worklist,
if (MTAG_P (curr) && is_call_clobbered (curr))
{
VEC_safe_push (tree, heap, *worklist, curr);
VEC_safe_push (int, heap, *worklist2, var_ann (curr)->escape_mask);
VEC_safe_push (int, heap, *worklist2,
var_ann (curr)->escape_mask);
bitmap_set_bit (on_worklist, DECL_UID (curr));
}
}
}
@ -343,13 +346,15 @@ init_transitive_clobber_worklist (VEC (tree, heap) **worklist,
static void
add_to_worklist (tree alias, VEC (tree, heap) **worklist,
VEC (int, heap) **worklist2,
int reason)
VEC (int, heap) **worklist2, int reason,
bitmap on_worklist)
{
if (MTAG_P (alias) && !is_call_clobbered (alias))
if (MTAG_P (alias) && !is_call_clobbered (alias)
&& !bitmap_bit_p (on_worklist, DECL_UID (alias)))
{
VEC_safe_push (tree, heap, *worklist, alias);
VEC_safe_push (int, heap, *worklist2, reason);
bitmap_set_bit (on_worklist, DECL_UID (alias));
}
}
@ -358,7 +363,8 @@ add_to_worklist (tree alias, VEC (tree, heap) **worklist,
static void
mark_aliases_call_clobbered (tree tag, VEC (tree, heap) **worklist,
VEC (int, heap) **worklist2)
VEC (int, heap) **worklist2,
bitmap on_worklist)
{
bitmap aliases;
bitmap_iterator bi;
@ -375,9 +381,23 @@ mark_aliases_call_clobbered (tree tag, VEC (tree, heap) **worklist,
EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
{
entry = referenced_var (i);
if (!unmodifiable_var_p (entry))
/* If you clobber one part of a structure, you
clobber the entire thing. While this does not make
the world a particularly nice place, it is necessary
in order to allow C/C++ tricks that involve
pointer arithmetic to work. */
if (TREE_CODE (entry) == STRUCT_FIELD_TAG)
{
add_to_worklist (entry, worklist, worklist2, ta->escape_mask);
subvar_t svars;
svars = get_subvars_for_var (SFT_PARENT_VAR (entry));
for (; svars; svars = svars->next)
if (!unmodifiable_var_p (entry))
mark_call_clobbered (svars->var, ta->escape_mask);
}
else if (!unmodifiable_var_p (entry))
{
add_to_worklist (entry, worklist, worklist2, ta->escape_mask,
on_worklist);
mark_call_clobbered (entry, ta->escape_mask);
}
}
@ -528,8 +548,25 @@ set_initial_properties (struct alias_info *ai)
bitmap_iterator bi;
unsigned int j;
EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j, bi)
if (!unmodifiable_var_p (referenced_var (j)))
mark_call_clobbered (referenced_var (j), pi->escape_mask);
{
tree alias = referenced_var (j);
/* If you clobber one part of a structure, you
clobber the entire thing. While this does not make
the world a particularly nice place, it is necessary
in order to allow C/C++ tricks that involve
pointer arithmetic to work. */
if (TREE_CODE (alias) == STRUCT_FIELD_TAG)
{
subvar_t svars;
svars = get_subvars_for_var (SFT_PARENT_VAR (alias));
for (; svars; svars = svars->next)
if (!unmodifiable_var_p (alias))
mark_call_clobbered (svars->var, pi->escape_mask);
}
else if (!unmodifiable_var_p (alias))
mark_call_clobbered (alias, pi->escape_mask);
}
}
}
@ -573,21 +610,27 @@ static void
compute_call_clobbered (struct alias_info *ai)
{
VEC (tree, heap) *worklist = NULL;
VEC(int,heap) *worklist2 = NULL;
VEC (int,heap) *worklist2 = NULL;
bitmap on_worklist;
timevar_push (TV_CALL_CLOBBER);
on_worklist = BITMAP_ALLOC (NULL);
set_initial_properties (ai);
init_transitive_clobber_worklist (&worklist, &worklist2);
init_transitive_clobber_worklist (&worklist, &worklist2, on_worklist);
while (VEC_length (tree, worklist) != 0)
{
tree curr = VEC_pop (tree, worklist);
int reason = VEC_pop (int, worklist2);
bitmap_clear_bit (on_worklist, DECL_UID (curr));
mark_call_clobbered (curr, reason);
mark_aliases_call_clobbered (curr, &worklist, &worklist2);
mark_aliases_call_clobbered (curr, &worklist, &worklist2,
on_worklist);
}
VEC_free (tree, heap, worklist);
VEC_free (int, heap, worklist2);
BITMAP_FREE (on_worklist);
compute_tag_properties ();
timevar_pop (TV_CALL_CLOBBER);
}
@ -3783,11 +3826,14 @@ create_overlap_variables_for (tree var)
/* If this field isn't in the used portion,
or it has the exact same offset and size as the last
field, skip it. */
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 <= up->minused
&& fo->offset + fosize <= up->minused)
|| fo->offset >= up->maxused)
if ((fo->offset != 0
&& ((fo->offset <= up->minused
&& fo->offset + fosize <= up->minused)
|| fo->offset >= up->maxused))
|| (fo->offset == lastfooffset
&& fosize == lastfosize
&& currfotype == lastfotype))
@ -3975,6 +4021,21 @@ create_structure_vars (void)
FOR_EACH_BB (bb)
{
block_stmt_iterator bsi;
tree phi;
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
use_operand_p use;
ssa_op_iter iter;
FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
{
tree op = USE_FROM_PTR (use);
walk_tree_without_duplicates (&op, find_used_portions,
NULL);
}
}
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
walk_tree_without_duplicates (bsi_stmt_ptr (bsi),
@ -4013,7 +4074,7 @@ create_structure_vars (void)
tree sym = referenced_var_lookup (i);
if (get_subvars_for_var (sym))
{
update=true;
update = true;
break;
}
}
@ -4024,7 +4085,7 @@ create_structure_vars (void)
tree sym = referenced_var_lookup (i);
if (get_subvars_for_var (sym))
{
update=true;
update = true;
break;
}
}
@ -4036,7 +4097,7 @@ create_structure_vars (void)
tree sym = referenced_var_lookup (i);
if (get_subvars_for_var (sym))
{
update=true;
update = true;
break;
}
}

View file

@ -5020,7 +5020,7 @@ get_ref_tag (tree ref, tree orig)
}
if (aref && SSA_VAR_P (aref) && get_subvars_for_var (aref))
return unshare_expr (sv);
return aref;
if (!var)
return NULL_TREE;

View file

@ -1181,7 +1181,9 @@ append_vuse (tree var)
/* REF is a tree that contains the entire pointer dereference
expression, if available, or NULL otherwise. ALIAS is the variable
we are asking if REF can access. OFFSET and SIZE come from the
memory access expression that generated this virtual operand. */
memory access expression that generated this virtual operand.
XXX: We should handle the NO_ALIAS attributes here. */
static bool
access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset,
@ -1197,6 +1199,11 @@ access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset,
if (alias == gimple_global_var (cfun))
return true;
/* If ref is a TARGET_MEM_REF, just return true, as we can't really
disambiguate them right now. */
if (ref && TREE_CODE (ref) == TARGET_MEM_REF)
return true;
/* If ALIAS is an SFT, it can't be touched if the offset
and size of the access is not overlapping with the SFT offset and
size. This is only true if we are accessing through a pointer
@ -1290,6 +1297,7 @@ access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset,
&& flag_strict_aliasing
&& TREE_CODE (ref) != INDIRECT_REF
&& !MTAG_P (alias)
&& base
&& (TREE_CODE (base) != INDIRECT_REF
|| TREE_CODE (TREE_TYPE (base)) != UNION_TYPE)
&& !AGGREGATE_TYPE_P (TREE_TYPE (alias))
@ -1335,6 +1343,106 @@ access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset,
return true;
}
/* Add the actual variables FULL_REF can access, given a member of
full_ref's points-to set VAR, where FULL_REF is an access of SIZE at
OFFSET from var. IS_CALL_SITE is true if this is a call, and IS_DEF
is true if this is supposed to be a vdef, and false if this should
be a VUSE.
The real purpose of this function is to take a points-to set for a
pointer to a structure, say
struct s {
int a;
int b;
} foo, *foop = &foo;
and discover which variables an access, such as foop->b, can alias.
This is necessary because foop only actually points to foo's first
member, so that is all the points-to set contains. However, an access
to foop->a may be touching some single SFT if we have created some
SFT's for a structure. */
static bool
add_vars_for_offset (tree full_ref, tree var, HOST_WIDE_INT offset,
HOST_WIDE_INT size, bool is_call_site, bool is_def)
{
/* Call-clobbered tags may have non-call-clobbered
symbols in their alias sets. Ignore them if we are
adding VOPs for a call site. */
if (is_call_site && !is_call_clobbered (var))
return false;
/* For offset 0, we already have the right variable. If there is no
full_ref, this is not a place we care about (All component
related accesses that go through pointers will have full_ref not
NULL).
Any var for which we didn't create SFT's can't be
distinguished. */
if (!full_ref || (offset == 0 && size != -1)
|| (TREE_CODE (var) != STRUCT_FIELD_TAG
&& (!var_can_have_subvars (var) || !get_subvars_for_var (var))))
{
if (!access_can_touch_variable (full_ref, var, offset, size))
return false;
if (is_def)
append_vdef (var);
else
append_vuse (var);
return true;
}
else if (TREE_CODE (var) == STRUCT_FIELD_TAG)
{
if (size == -1)
{
bool added = false;
subvar_t sv = get_subvars_for_var (SFT_PARENT_VAR (var));
for (; sv; sv = sv->next)
{
if (overlap_subvar (SFT_OFFSET (var) + offset, size,
sv->var, NULL)
&& access_can_touch_variable (full_ref, sv->var,
offset, size))
{
added = true;
if (is_def)
append_vdef (sv->var);
else
append_vuse (sv->var);
}
}
return added;
}
else
{
bool added = false;
subvar_t sv = get_subvars_for_var (SFT_PARENT_VAR (var));
for (; sv; sv = sv->next)
{
/* Once we hit the end of the parts that could touch,
stop looking. */
if (SFT_OFFSET (var) + offset + size <= SFT_OFFSET (sv->var))
break;
if (overlap_subvar (SFT_OFFSET (var) + offset, size,
sv->var, NULL)
&& access_can_touch_variable (full_ref, sv->var, offset,
size))
{
added = true;
if (is_def)
append_vdef (sv->var);
else
append_vuse (sv->var);
}
}
return added;
}
}
return false;
}
/* Add VAR to the virtual operands array. FLAGS is as in
get_expr_operands. FULL_REF is a tree that contains the entire
@ -1343,7 +1451,7 @@ access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset,
generated this virtual operand. IS_CALL_SITE is true if the
affected statement is a call site. */
static void
static void
add_virtual_operand (tree var, stmt_ann_t s_ann, int flags,
tree full_ref, HOST_WIDE_INT offset,
HOST_WIDE_INT size, bool is_call_site)
@ -1416,17 +1524,8 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags,
EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
{
al = referenced_var (i);
if (!access_can_touch_variable (full_ref, al, offset, size))
continue;
/* Call-clobbered tags may have non-call-clobbered
symbols in their alias sets. Ignore them if we are
adding VOPs for a call site. */
if (is_call_site && !is_call_clobbered (al))
continue;
none_added = false;
append_vdef (al);
none_added &= !add_vars_for_offset (full_ref, al, offset, size,
is_call_site, true);
}
/* If the variable is also an alias tag, add a virtual
@ -1443,9 +1542,7 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags,
if (none_added
|| (TREE_CODE (var) == SYMBOL_MEMORY_TAG
&& is_call_site))
{
append_vdef (var);
}
append_vdef (var);
}
else
{
@ -1453,17 +1550,9 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags,
EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi)
{
al = referenced_var (i);
if (!access_can_touch_variable (full_ref, al, offset, size))
continue;
/* Call-clobbered tags may have non-call-clobbered
symbols in their alias sets. Ignore them if we are
adding VOPs for a call site. */
if (is_call_site && !is_call_clobbered (al))
continue;
none_added = false;
append_vuse (al);
none_added &= !add_vars_for_offset (full_ref, al, offset, size,
is_call_site, false);
}
/* Even if no aliases have been added, we still need to
@ -1620,9 +1709,7 @@ get_indirect_ref_operands (tree stmt, tree expr, int flags,
static void
get_tmr_operands (tree stmt, tree expr, int flags)
{
tree tag, ref;
HOST_WIDE_INT offset, size, maxsize;
subvar_t svars, sv;
tree tag;
stmt_ann_t s_ann = stmt_ann (stmt);
/* This statement references memory. */
@ -1642,23 +1729,13 @@ get_tmr_operands (tree stmt, tree expr, int flags)
s_ann->has_volatile_ops = true;
return;
}
if (DECL_P (tag))
if (!MTAG_P (tag))
{
get_expr_operands (stmt, &tag, flags);
return;
}
ref = get_ref_base_and_extent (tag, &offset, &size, &maxsize);
gcc_assert (ref != NULL_TREE);
svars = get_subvars_for_var (ref);
for (sv = svars; sv; sv = sv->next)
{
bool exact;
if (overlap_subvar (offset, maxsize, sv->var, &exact))
add_stmt_operand (&sv->var, s_ann, flags);
}
add_virtual_operand (tag, s_ann, flags, expr, 0, -1, false);
}
@ -1673,11 +1750,6 @@ add_call_clobber_ops (tree stmt, tree callee)
stmt_ann_t s_ann = stmt_ann (stmt);
bitmap not_read_b, not_written_b;
/* Functions that are not const, pure or never return may clobber
call-clobbered variables. */
if (s_ann)
s_ann->makes_clobbering_call = true;
/* If we created .GLOBAL_VAR earlier, just use it. */
if (gimple_global_var (cfun))
{
@ -2032,7 +2104,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
case ALIGN_INDIRECT_REF:
case INDIRECT_REF:
get_indirect_ref_operands (stmt, expr, flags, NULL_TREE, 0, -1, true);
get_indirect_ref_operands (stmt, expr, flags, expr, 0, -1, true);
return;
case TARGET_MEM_REF:

File diff suppressed because it is too large Load diff