Commit 3e8542ca by Richard Guenther Committed by Richard Biener

tree-ssa-structalias.c (callused_id): Remove.

2010-04-13  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-structalias.c (callused_id): Remove.
	(call_stmt_vars): New.
	(get_call_vi): Likewise.
	(lookup_call_use_vi): Likewise.
	(lookup_call_clobber_vi): Likewise.
	(get_call_use_vi): Likewise.
	(get_call_clobber_vi): Likewise.
	(make_transitive_closure_constraints): Likewise.
	(handle_const_call): Adjust to do per-call call-used handling.
	(handle_pure_call): Likewise.
	(find_what_var_points_to): Remove general callused handling.
	(init_base_vars): Likewise.
	(init_alias_vars): Initialize call_stmt_vars.
	(compute_points_to_sets): Process call-used and call-clobbered
	vars for call statements.
	(delete_points_to_sets): Free call_stmt_vars.

From-SVN: r158260
parent 777e1f09
2010-04-13 Richard Guenther <rguenther@suse.de> 2010-04-13 Richard Guenther <rguenther@suse.de>
* tree-ssa-structalias.c (callused_id): Remove.
(call_stmt_vars): New.
(get_call_vi): Likewise.
(lookup_call_use_vi): Likewise.
(lookup_call_clobber_vi): Likewise.
(get_call_use_vi): Likewise.
(get_call_clobber_vi): Likewise.
(make_transitive_closure_constraints): Likewise.
(handle_const_call): Adjust to do per-call call-used handling.
(handle_pure_call): Likewise.
(find_what_var_points_to): Remove general callused handling.
(init_base_vars): Likewise.
(init_alias_vars): Initialize call_stmt_vars.
(compute_points_to_sets): Process call-used and call-clobbered
vars for call statements.
(delete_points_to_sets): Free call_stmt_vars.
2010-04-13 Richard Guenther <rguenther@suse.de>
* tree-vect-data-refs.c (vect_analyze_data_ref_dependence): * tree-vect-data-refs.c (vect_analyze_data_ref_dependence):
Only add RW dependence for dependence distance zero. Only add RW dependence for dependence distance zero.
Adjust maximal vectorization factor according to dependences. Adjust maximal vectorization factor according to dependences.
......
...@@ -288,8 +288,8 @@ get_varinfo (unsigned int n) ...@@ -288,8 +288,8 @@ get_varinfo (unsigned int n)
/* Static IDs for the special variables. */ /* Static IDs for the special variables. */
enum { nothing_id = 0, anything_id = 1, readonly_id = 2, enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
escaped_id = 3, nonlocal_id = 4, callused_id = 5, escaped_id = 3, nonlocal_id = 4,
storedanything_id = 6, integer_id = 7 }; storedanything_id = 5, integer_id = 6 };
struct GTY(()) heapvar_map { struct GTY(()) heapvar_map {
struct tree_map map; struct tree_map map;
...@@ -379,6 +379,86 @@ new_var_info (tree t, const char *name) ...@@ -379,6 +379,86 @@ new_var_info (tree t, const char *name)
return ret; return ret;
} }
/* A map mapping call statements to per-stmt variables for uses
and clobbers specific to the call. */
struct pointer_map_t *call_stmt_vars;
/* Lookup or create the variable for the call statement CALL. */
static varinfo_t
get_call_vi (gimple call)
{
void **slot_p;
varinfo_t vi, vi2;
slot_p = pointer_map_insert (call_stmt_vars, call);
if (*slot_p)
return (varinfo_t) *slot_p;
vi = new_var_info (NULL_TREE, "CALLUSED");
vi->offset = 0;
vi->size = 1;
vi->fullsize = 2;
vi->is_full_var = true;
vi->next = vi2 = new_var_info (NULL_TREE, "CALLCLOBBERED");
vi2->offset = 1;
vi2->size = 1;
vi2->fullsize = 2;
vi2->is_full_var = true;
*slot_p = (void *) vi;
return vi;
}
/* Lookup the variable for the call statement CALL representing
the uses. Returns NULL if there is nothing special about this call. */
static varinfo_t
lookup_call_use_vi (gimple call)
{
void **slot_p;
slot_p = pointer_map_contains (call_stmt_vars, call);
if (slot_p)
return (varinfo_t) *slot_p;
return NULL;
}
/* Lookup the variable for the call statement CALL representing
the clobbers. Returns NULL if there is nothing special about this call. */
static varinfo_t
lookup_call_clobber_vi (gimple call)
{
varinfo_t uses = lookup_call_use_vi (call);
if (!uses)
return NULL;
return uses->next;
}
/* Lookup or create the variable for the call statement CALL representing
the uses. */
static varinfo_t
get_call_use_vi (gimple call)
{
return get_call_vi (call);
}
/* Lookup or create the variable for the call statement CALL representing
the clobbers. */
static varinfo_t ATTRIBUTE_UNUSED
get_call_clobber_vi (gimple call)
{
return get_call_vi (call)->next;
}
typedef enum {SCALAR, DEREF, ADDRESSOF} constraint_expr_type; typedef enum {SCALAR, DEREF, ADDRESSOF} constraint_expr_type;
/* An expression that appears in a constraint. */ /* An expression that appears in a constraint. */
...@@ -3377,6 +3457,32 @@ make_escape_constraint (tree op) ...@@ -3377,6 +3457,32 @@ make_escape_constraint (tree op)
make_constraint_to (escaped_id, op); make_constraint_to (escaped_id, op);
} }
/* Add constraints to that the solution of VI is transitively closed. */
static void
make_transitive_closure_constraints (varinfo_t vi)
{
struct constraint_expr lhs, rhs;
/* VAR = *VAR; */
lhs.type = SCALAR;
lhs.var = vi->id;
lhs.offset = 0;
rhs.type = DEREF;
rhs.var = vi->id;
rhs.offset = 0;
process_constraint (new_constraint (lhs, rhs));
/* VAR = VAR + UNKNOWN; */
lhs.type = SCALAR;
lhs.var = vi->id;
lhs.offset = 0;
rhs.type = SCALAR;
rhs.var = vi->id;
rhs.offset = UNKNOWN_OFFSET;
process_constraint (new_constraint (lhs, rhs));
}
/* Create a new artificial heap variable with NAME and make a /* Create a new artificial heap variable with NAME and make a
constraint from it to LHS. Return the created variable. */ constraint from it to LHS. Return the created variable. */
...@@ -3538,8 +3644,10 @@ handle_const_call (gimple stmt, VEC(ce_s, heap) **results) ...@@ -3538,8 +3644,10 @@ handle_const_call (gimple stmt, VEC(ce_s, heap) **results)
as the static chain is concerned. */ as the static chain is concerned. */
if (gimple_call_chain (stmt)) if (gimple_call_chain (stmt))
{ {
make_constraint_to (callused_id, gimple_call_chain (stmt)); varinfo_t uses = get_call_use_vi (stmt);
rhsc.var = callused_id; make_transitive_closure_constraints (uses);
make_constraint_to (uses->id, gimple_call_chain (stmt));
rhsc.var = uses->id;
rhsc.offset = 0; rhsc.offset = 0;
rhsc.type = SCALAR; rhsc.type = SCALAR;
VEC_safe_push (ce_s, heap, *results, &rhsc); VEC_safe_push (ce_s, heap, *results, &rhsc);
...@@ -3577,7 +3685,7 @@ handle_pure_call (gimple stmt, VEC(ce_s, heap) **results) ...@@ -3577,7 +3685,7 @@ handle_pure_call (gimple stmt, VEC(ce_s, heap) **results)
{ {
struct constraint_expr rhsc; struct constraint_expr rhsc;
unsigned i; unsigned i;
bool need_callused = false; varinfo_t uses = NULL;
/* Memory reached from pointer arguments is call-used. */ /* Memory reached from pointer arguments is call-used. */
for (i = 0; i < gimple_call_num_args (stmt); ++i) for (i = 0; i < gimple_call_num_args (stmt); ++i)
...@@ -3586,22 +3694,30 @@ handle_pure_call (gimple stmt, VEC(ce_s, heap) **results) ...@@ -3586,22 +3694,30 @@ handle_pure_call (gimple stmt, VEC(ce_s, heap) **results)
if (could_have_pointers (arg)) if (could_have_pointers (arg))
{ {
make_constraint_to (callused_id, arg); if (!uses)
need_callused = true; {
uses = get_call_use_vi (stmt);
make_transitive_closure_constraints (uses);
}
make_constraint_to (uses->id, arg);
} }
} }
/* The static chain is used as well. */ /* The static chain is used as well. */
if (gimple_call_chain (stmt)) if (gimple_call_chain (stmt))
{ {
make_constraint_to (callused_id, gimple_call_chain (stmt)); if (!uses)
need_callused = true; {
uses = get_call_use_vi (stmt);
make_transitive_closure_constraints (uses);
}
make_constraint_to (uses->id, gimple_call_chain (stmt));
} }
/* Pure functions may return callused and nonlocal memory. */ /* Pure functions may return call-used and nonlocal memory. */
if (need_callused) if (uses)
{ {
rhsc.var = callused_id; rhsc.var = uses->id;
rhsc.offset = 0; rhsc.offset = 0;
rhsc.type = SCALAR; rhsc.type = SCALAR;
VEC_safe_push (ce_s, heap, *results, &rhsc); VEC_safe_push (ce_s, heap, *results, &rhsc);
...@@ -4004,8 +4120,8 @@ find_func_aliases (gimple origt) ...@@ -4004,8 +4120,8 @@ find_func_aliases (gimple origt)
if (!allows_reg && allows_mem) if (!allows_reg && allows_mem)
make_escape_constraint (build_fold_addr_expr (op)); make_escape_constraint (build_fold_addr_expr (op));
/* Strictly we'd only need the constraint to ESCAPED if /* Strictly we'd only need the constraint to ESCAPED if
the asm clobbers memory, otherwise using CALLUSED the asm clobbers memory, otherwise using something
would be enough. */ along the lines of per-call clobbers/uses would be enough. */
else if (op && could_have_pointers (op)) else if (op && could_have_pointers (op))
make_escape_constraint (op); make_escape_constraint (op);
} }
...@@ -4811,8 +4927,6 @@ find_what_var_points_to (varinfo_t orig_vi, struct pt_solution *pt) ...@@ -4811,8 +4927,6 @@ find_what_var_points_to (varinfo_t orig_vi, struct pt_solution *pt)
pt->null = 1; pt->null = 1;
else if (vi->id == escaped_id) else if (vi->id == escaped_id)
pt->escaped = 1; pt->escaped = 1;
else if (vi->id == callused_id)
gcc_unreachable ();
else if (vi->id == nonlocal_id) else if (vi->id == nonlocal_id)
pt->nonlocal = 1; pt->nonlocal = 1;
else if (vi->is_heap_var) else if (vi->is_heap_var)
...@@ -5138,7 +5252,6 @@ init_base_vars (void) ...@@ -5138,7 +5252,6 @@ init_base_vars (void)
varinfo_t var_readonly; varinfo_t var_readonly;
varinfo_t var_escaped; varinfo_t var_escaped;
varinfo_t var_nonlocal; varinfo_t var_nonlocal;
varinfo_t var_callused;
varinfo_t var_storedanything; varinfo_t var_storedanything;
varinfo_t var_integer; varinfo_t var_integer;
...@@ -5265,35 +5378,6 @@ init_base_vars (void) ...@@ -5265,35 +5378,6 @@ init_base_vars (void)
rhs.offset = 0; rhs.offset = 0;
process_constraint (new_constraint (lhs, rhs)); process_constraint (new_constraint (lhs, rhs));
/* Create the CALLUSED variable, used to represent the set of call-used
memory. */
var_callused = new_var_info (NULL_TREE, "CALLUSED");
gcc_assert (var_callused->id == callused_id);
var_callused->is_artificial_var = 1;
var_callused->offset = 0;
var_callused->size = ~0;
var_callused->fullsize = ~0;
var_callused->is_special_var = 0;
/* CALLUSED = *CALLUSED, because call-used is may-deref'd at calls, etc. */
lhs.type = SCALAR;
lhs.var = callused_id;
lhs.offset = 0;
rhs.type = DEREF;
rhs.var = callused_id;
rhs.offset = 0;
process_constraint (new_constraint (lhs, rhs));
/* CALLUSED = CALLUSED + UNKNOWN, because if a sub-field is call-used the
whole variable is call-used. */
lhs.type = SCALAR;
lhs.var = callused_id;
lhs.offset = 0;
rhs.type = SCALAR;
rhs.var = callused_id;
rhs.offset = UNKNOWN_OFFSET;
process_constraint (new_constraint (lhs, rhs));
/* Create the STOREDANYTHING variable, used to represent the set of /* Create the STOREDANYTHING variable, used to represent the set of
variables stored to *ANYTHING. */ variables stored to *ANYTHING. */
var_storedanything = new_var_info (NULL_TREE, "STOREDANYTHING"); var_storedanything = new_var_info (NULL_TREE, "STOREDANYTHING");
...@@ -5344,6 +5428,7 @@ init_alias_vars (void) ...@@ -5344,6 +5428,7 @@ init_alias_vars (void)
constraints = VEC_alloc (constraint_t, heap, 8); constraints = VEC_alloc (constraint_t, heap, 8);
varmap = VEC_alloc (varinfo_t, heap, 8); varmap = VEC_alloc (varinfo_t, heap, 8);
vi_for_tree = pointer_map_create (); vi_for_tree = pointer_map_create ();
call_stmt_vars = pointer_map_create ();
memset (&stats, 0, sizeof (stats)); memset (&stats, 0, sizeof (stats));
shared_bitmap_table = htab_create (511, shared_bitmap_hash, shared_bitmap_table = htab_create (511, shared_bitmap_hash,
...@@ -5480,7 +5565,6 @@ compute_points_to_sets (void) ...@@ -5480,7 +5565,6 @@ compute_points_to_sets (void)
basic_block bb; basic_block bb;
unsigned i; unsigned i;
varinfo_t vi; varinfo_t vi;
struct pt_solution callused;
timevar_push (TV_TREE_PTA); timevar_push (TV_TREE_PTA);
...@@ -5513,11 +5597,9 @@ compute_points_to_sets (void) ...@@ -5513,11 +5597,9 @@ compute_points_to_sets (void)
/* From the constraints compute the points-to sets. */ /* From the constraints compute the points-to sets. */
solve_constraints (); solve_constraints ();
/* Compute the points-to sets for ESCAPED and CALLUSED used for /* Compute the points-to set for ESCAPED used for call-clobber analysis. */
call-clobber analysis. */
find_what_var_points_to (get_varinfo (escaped_id), find_what_var_points_to (get_varinfo (escaped_id),
&cfun->gimple_df->escaped); &cfun->gimple_df->escaped);
find_what_var_points_to (get_varinfo (callused_id), &callused);
/* Make sure the ESCAPED solution (which is used as placeholder in /* Make sure the ESCAPED solution (which is used as placeholder in
other solutions) does not reference itself. This simplifies other solutions) does not reference itself. This simplifies
...@@ -5556,11 +5638,11 @@ compute_points_to_sets (void) ...@@ -5556,11 +5638,11 @@ compute_points_to_sets (void)
pt = gimple_call_use_set (stmt); pt = gimple_call_use_set (stmt);
if (gimple_call_flags (stmt) & ECF_CONST) if (gimple_call_flags (stmt) & ECF_CONST)
memset (pt, 0, sizeof (struct pt_solution)); memset (pt, 0, sizeof (struct pt_solution));
else if (gimple_call_flags (stmt) & ECF_PURE) else if ((vi = lookup_call_use_vi (stmt)) != NULL)
{ {
/* For const calls we should now be able to compute the find_what_var_points_to (vi, pt);
call-used set per function. */ /* Escaped (and thus nonlocal) variables are always
*pt = callused; implicitly used by calls. */
/* ??? ESCAPED can be empty even though NONLOCAL /* ??? ESCAPED can be empty even though NONLOCAL
always escaped. */ always escaped. */
pt->nonlocal = 1; pt->nonlocal = 1;
...@@ -5568,6 +5650,8 @@ compute_points_to_sets (void) ...@@ -5568,6 +5650,8 @@ compute_points_to_sets (void)
} }
else else
{ {
/* If there is nothing special about this call then
we have made everything that is used also escape. */
*pt = cfun->gimple_df->escaped; *pt = cfun->gimple_df->escaped;
pt->nonlocal = 1; pt->nonlocal = 1;
} }
...@@ -5575,8 +5659,20 @@ compute_points_to_sets (void) ...@@ -5575,8 +5659,20 @@ compute_points_to_sets (void)
pt = gimple_call_clobber_set (stmt); pt = gimple_call_clobber_set (stmt);
if (gimple_call_flags (stmt) & (ECF_CONST|ECF_PURE|ECF_NOVOPS)) if (gimple_call_flags (stmt) & (ECF_CONST|ECF_PURE|ECF_NOVOPS))
memset (pt, 0, sizeof (struct pt_solution)); memset (pt, 0, sizeof (struct pt_solution));
else if ((vi = lookup_call_clobber_vi (stmt)) != NULL)
{
find_what_var_points_to (vi, pt);
/* Escaped (and thus nonlocal) variables are always
implicitly clobbered by calls. */
/* ??? ESCAPED can be empty even though NONLOCAL
always escaped. */
pt->nonlocal = 1;
pt->escaped = 1;
}
else else
{ {
/* If there is nothing special about this call then
we have made everything that is used also escape. */
*pt = cfun->gimple_df->escaped; *pt = cfun->gimple_df->escaped;
pt->nonlocal = 1; pt->nonlocal = 1;
} }
...@@ -5600,6 +5696,7 @@ delete_points_to_sets (void) ...@@ -5600,6 +5696,7 @@ delete_points_to_sets (void)
stats.points_to_sets_created); stats.points_to_sets_created);
pointer_map_destroy (vi_for_tree); pointer_map_destroy (vi_for_tree);
pointer_map_destroy (call_stmt_vars);
bitmap_obstack_release (&pta_obstack); bitmap_obstack_release (&pta_obstack);
VEC_free (constraint_t, heap, constraints); VEC_free (constraint_t, heap, constraints);
......
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