re PR tree-optimization/36400 (points-to results wrong)

2008-06-27  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/36400
	PR tree-optimization/36373
	PR tree-optimization/36344
	* tree-ssa-structalias.c (var_escaped, escaped_tree, escaped_id,
	var_nonlocal, nonlocal_tree, nonlocal_id): New globals
	(update_alias_info): Remove call clobbering code.
	(make_constraint_to): New helper function.
	(make_escape_constraint): Likewise.
	(handle_rhs_call): Use it on all pointer containing arguments.
	Also mark the static chain escaped.
	(handle_lhs_call): Make constraints from NONLOCAL and ESCAPED
	instead of ANYTHING.
	(make_constraint_from): New helper split out from ...
	(make_constraint_from_anything): ... here.
	(find_func_aliases): Add constraints for escape sites.
	(intra_create_variable_infos): Make constraints from NONLOCAL
	for parameters.
	(find_what_p_points_to): Interpret NONLOCAL and ESCAPED the same
	as ANYTHING.
	(clobber_what_p_points_to): Remove.
	(clobber_what_escaped): New function.
	(init_base_vars): Init NONLOCAL and ESCAPED.
	(do_sd_constraint): Do not propagate the solution from ESCAPED
	but use ESCAPED as a placeholder.
	(solve_graph): Likewise.
	* tree-flow.h (clobber_what_p_points_to): Remove.
	(clobber_what_escaped): Declare.
	* tree-ssa-alias.c (set_initial_properties): Call it.
	Remove code clobbering escaped pointers.

	* gcc.dg/torture/pr36373-1.c: New testcase.
	* gcc.dg/torture/pr36373-2.c: Likewise.
	* gcc.dg/torture/pr36373-3.c: Likewise.
	* gcc.dg/torture/pr36373-4.c: Likewise.
	* gcc.dg/torture/pr36373-5.c: Likewise.
	* gcc.dg/torture/pr36373-6.c: Likewise.
	* gcc.dg/torture/pr36373-7.c: Likewise.
	* gcc.dg/torture/pr36373-8.c: Likewise.
	* gcc.dg/torture/pr36373-9.c: Likewise.
	* gcc.dg/torture/pr36373-10.c: Likewise.
	* gcc.dg/torture/pr36400.c: Likewise.
	* gcc.c-torture/execute/pta-field-1.c: Likewise.
	* gcc.c-torture/execute/pta-field-2.c: Likewise.
	* gcc.dg/tree-ssa/loadpre8.c: Remove XFAIL.
	* gcc.dg/tree-ssa/pr24287.c: XFAIL.

From-SVN: r137197
This commit is contained in:
Richard Guenther 2008-06-27 18:53:43 +00:00 committed by Richard Biener
parent 04dbd89190
commit b7091901cd
7 changed files with 353 additions and 113 deletions

View File

@ -1,3 +1,35 @@
2008-06-27 Richard Guenther <rguenther@suse.de>
PR tree-optimization/36400
PR tree-optimization/36373
PR tree-optimization/36344
* tree-ssa-structalias.c (var_escaped, escaped_tree, escaped_id,
var_nonlocal, nonlocal_tree, nonlocal_id): New globals
(update_alias_info): Remove call clobbering code.
(make_constraint_to): New helper function.
(make_escape_constraint): Likewise.
(handle_rhs_call): Use it on all pointer containing arguments.
Also mark the static chain escaped.
(handle_lhs_call): Make constraints from NONLOCAL and ESCAPED
instead of ANYTHING.
(make_constraint_from): New helper split out from ...
(make_constraint_from_anything): ... here.
(find_func_aliases): Add constraints for escape sites.
(intra_create_variable_infos): Make constraints from NONLOCAL
for parameters.
(find_what_p_points_to): Interpret NONLOCAL and ESCAPED the same
as ANYTHING.
(clobber_what_p_points_to): Remove.
(clobber_what_escaped): New function.
(init_base_vars): Init NONLOCAL and ESCAPED.
(do_sd_constraint): Do not propagate the solution from ESCAPED
but use ESCAPED as a placeholder.
(solve_graph): Likewise.
* tree-flow.h (clobber_what_p_points_to): Remove.
(clobber_what_escaped): Declare.
* tree-ssa-alias.c (set_initial_properties): Call it.
Remove code clobbering escaped pointers.
2008-06-27 Richard Sandiford <rdsandiford@googlemail.com>
* function.c (allocate_struct_function): Only allocate a unique

View File

@ -1,3 +1,24 @@
2008-06-27 Richard Guenther <rguenther@suse.de>
PR tree-optimization/36400
PR tree-optimization/36373
PR tree-optimization/36344
* gcc.dg/torture/pr36373-1.c: New testcase.
* gcc.dg/torture/pr36373-2.c: Likewise.
* gcc.dg/torture/pr36373-3.c: Likewise.
* gcc.dg/torture/pr36373-4.c: Likewise.
* gcc.dg/torture/pr36373-5.c: Likewise.
* gcc.dg/torture/pr36373-6.c: Likewise.
* gcc.dg/torture/pr36373-7.c: Likewise.
* gcc.dg/torture/pr36373-8.c: Likewise.
* gcc.dg/torture/pr36373-9.c: Likewise.
* gcc.dg/torture/pr36373-10.c: Likewise.
* gcc.dg/torture/pr36400.c: Likewise.
* gcc.c-torture/execute/pta-field-1.c: Likewise.
* gcc.c-torture/execute/pta-field-2.c: Likewise.
* gcc.dg/tree-ssa/loadpre8.c: Remove XFAIL.
* gcc.dg/tree-ssa/pr24287.c: XFAIL.
2008-06-27 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/aggr9.ad[sb]: New test.

View File

@ -93,5 +93,5 @@ rewrite_add_phi_arguments (basic_block bb)
get_reaching_def ((get_def_from_ptr (get_phi_result_ptr (phi)))->ssa_name.var);
}
}
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -21,5 +21,5 @@ int g(void)
link_error ();
return t2 == 2;
}
/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */
/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail *-*-* } } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -1173,7 +1173,7 @@ tree gimple_fold_indirect_ref (tree);
/* In tree-ssa-structalias.c */
bool find_what_p_points_to (tree);
bool clobber_what_p_points_to (tree);
bool clobber_what_escaped (void);
/* In tree-ssa-live.c */
extern void remove_unused_locals (void);

View File

@ -537,6 +537,12 @@ set_initial_properties (struct alias_info *ai)
}
}
if (!clobber_what_escaped ())
{
any_pt_anything = true;
pt_anything_mask |= ESCAPE_TO_CALL;
}
for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++)
{
struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
@ -557,18 +563,6 @@ set_initial_properties (struct alias_info *ai)
if (tag)
mark_call_clobbered (tag, pi->escape_mask);
/* Defer to points-to analysis if possible, otherwise
clobber all addressable variables. Parameters cannot
point to local memory though.
??? Properly tracking which pointers point to non-local
memory only would make a big difference here. */
if (!clobber_what_p_points_to (ptr)
&& !(pi->escape_mask & ESCAPE_IS_PARM))
{
any_pt_anything = true;
pt_anything_mask |= pi->escape_mask;
}
}
/* If the name tag is call clobbered, so is the symbol tag
@ -2906,6 +2900,12 @@ is_escape_site (tree stmt)
if (TREE_CODE (lhs) == SSA_NAME)
return NO_ESCAPE;
/* If the LHS is a non-global decl, it isn't a non-local memory store.
If the LHS escapes, the RHS escape is dealt with in the PTA solver. */
if (DECL_P (lhs)
&& !is_global_var (lhs))
return NO_ESCAPE;
/* FIXME: LHS is not an SSA_NAME. Even if it's an assignment to a
local variables we cannot be sure if it will escape, because we
don't have information about objects not in SSA form. Need to

View File

@ -294,26 +294,34 @@ get_varinfo_fc (unsigned int n)
return v;
}
/* Static IDs for the special variables. */
enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
escaped_id = 3, nonlocal_id = 4, integer_id = 5 };
/* Variable that represents the unknown pointer. */
static varinfo_t var_anything;
static tree anything_tree;
static unsigned int anything_id;
/* Variable that represents the NULL pointer. */
static varinfo_t var_nothing;
static tree nothing_tree;
static unsigned int nothing_id;
/* Variable that represents read only memory. */
static varinfo_t var_readonly;
static tree readonly_tree;
static unsigned int readonly_id;
/* Variable that represents escaped memory. */
static varinfo_t var_escaped;
static tree escaped_tree;
/* Variable that represents nonlocal memory. */
static varinfo_t var_nonlocal;
static tree nonlocal_tree;
/* Variable that represents integers. This is used for when people do things
like &0->a.b. */
static varinfo_t var_integer;
static tree integer_tree;
static unsigned int integer_id;
/* Lookup a heap var for FROM, and return it if we find one. */
@ -1399,6 +1407,7 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
bitmap_set_bit (sol, anything_id);
goto done;
}
/* For each variable j in delta (Sol(y)), add
an edge in the graph from j to x, and union Sol(j) into Sol(x). */
EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
@ -1417,8 +1426,16 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
/* Adding edges from the special vars is pointless.
They don't have sets that can change. */
if (get_varinfo (t) ->is_special_var)
if (get_varinfo (t)->is_special_var)
flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
/* Merging the solution from ESCAPED needlessly increases
the set. Use ESCAPED as representative instead. */
else if (get_varinfo (t)->id == escaped_id
&& !bitmap_bit_p (sol, get_varinfo (t)->id))
{
bitmap_set_bit (sol, escaped_id);
flag = true;
}
else if (add_graph_edge (graph, lhs, t))
flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
}
@ -2351,7 +2368,9 @@ solve_graph (constraint_graph_t graph)
solution_empty = bitmap_empty_p (solution);
if (!solution_empty)
if (!solution_empty
/* Do not propagate the ESCAPED solution. */
&& i != escaped_id)
{
bitmap_iterator bi;
@ -3271,24 +3290,7 @@ update_alias_info (tree stmt, struct alias_info *ai)
/* Mark all the variables whose address are taken by the statement. */
addr_taken = addresses_taken (stmt);
if (addr_taken)
{
bitmap_ior_into (gimple_addressable_vars (cfun), addr_taken);
/* If STMT is an escape point, all the addresses taken by it are
call-clobbered. */
if (stmt_escape_type != NO_ESCAPE)
{
bitmap_iterator bi;
unsigned i;
EXECUTE_IF_SET_IN_BITMAP (addr_taken, 0, i, bi)
{
tree rvar = referenced_var (i);
if (!unmodifiable_var_p (rvar))
mark_call_clobbered (rvar, stmt_escape_type);
}
}
}
bitmap_ior_into (gimple_addressable_vars (cfun), addr_taken);
/* Process each operand use. For pointers, determine whether they
are dereferenced by the statement, or whether their value
@ -3573,6 +3575,34 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
return true;
}
/* Create a constraint ID = OP. */
static void
make_constraint_to (unsigned id, tree op)
{
VEC(ce_s, heap) *rhsc = NULL;
struct constraint_expr *c;
struct constraint_expr includes;
unsigned int j;
includes.var = id;
includes.offset = 0;
includes.type = SCALAR;
get_constraint_for (op, &rhsc);
for (j = 0; VEC_iterate (ce_s, rhsc, j, c); j++)
process_constraint_1 (new_constraint (includes, *c), true);
VEC_free (ce_s, heap, rhsc);
}
/* Make constraints necessary to make OP escape. */
static void
make_escape_constraint (tree op)
{
make_constraint_to (escaped_id, op);
}
/* For non-IPA mode, generate constraints necessary for a call on the
RHS. */
@ -3581,35 +3611,21 @@ handle_rhs_call (tree rhs)
{
tree arg;
call_expr_arg_iterator iter;
struct constraint_expr rhsc;
rhsc.var = anything_id;
rhsc.offset = 0;
rhsc.type = ADDRESSOF;
FOR_EACH_CALL_EXPR_ARG (arg, iter, rhs)
{
VEC(ce_s, heap) *lhsc = NULL;
/* Find those pointers being passed, and make sure they end up
pointing to anything. */
if (could_have_pointers (arg))
make_escape_constraint (arg);
/* Find those pointers being passed, and make sure they end up
pointing to anything. */
if (POINTER_TYPE_P (TREE_TYPE (arg)))
{
unsigned int j;
struct constraint_expr *lhsp;
get_constraint_for (arg, &lhsc);
do_deref (&lhsc);
for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
process_constraint_1 (new_constraint (*lhsp, rhsc), true);
VEC_free (ce_s, heap, lhsc);
}
}
/* The static chain escapes as well. */
if (CALL_EXPR_STATIC_CHAIN (rhs))
make_escape_constraint (CALL_EXPR_STATIC_CHAIN (rhs));
}
/* For non-IPA mode, generate constraints necessary for a call
that returns a pointer and assigns it to LHS. This simply makes
the LHS point to anything. */
the LHS point to global and escaped variables. */
static void
handle_lhs_call (tree lhs)
@ -3619,12 +3635,70 @@ handle_lhs_call (tree lhs)
unsigned int j;
struct constraint_expr *lhsp;
rhsc.var = anything_id;
get_constraint_for (lhs, &lhsc);
rhsc.var = nonlocal_id;
rhsc.offset = 0;
rhsc.type = ADDRESSOF;
get_constraint_for (lhs, &lhsc);
for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
process_constraint_1 (new_constraint (*lhsp, rhsc), true);
rhsc.var = escaped_id;
rhsc.offset = 0;
rhsc.type = ADDRESSOF;
for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
process_constraint_1 (new_constraint (*lhsp, rhsc), true);
VEC_free (ce_s, heap, lhsc);
}
/* For non-IPA mode, generate constraints necessary for a call of a
const function that returns a pointer in the statement STMT. */
static void
handle_const_call (tree stmt)
{
tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
tree call = get_call_expr_in (stmt);
VEC(ce_s, heap) *lhsc = NULL;
struct constraint_expr rhsc;
unsigned int j;
struct constraint_expr *lhsp;
tree arg;
call_expr_arg_iterator iter;
get_constraint_for (lhs, &lhsc);
/* If this is a nested function then it can return anything. */
if (CALL_EXPR_STATIC_CHAIN (call))
{
rhsc.var = anything_id;
rhsc.offset = 0;
rhsc.type = ADDRESSOF;
for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
process_constraint_1 (new_constraint (*lhsp, rhsc), true);
VEC_free (ce_s, heap, lhsc);
return;
}
/* May return addresses of globals. */
rhsc.var = nonlocal_id;
rhsc.offset = 0;
rhsc.type = ADDRESSOF;
for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
process_constraint_1 (new_constraint (*lhsp, rhsc), true);
/* May return arguments. */
FOR_EACH_CALL_EXPR_ARG (arg, iter, call)
if (could_have_pointers (arg))
{
VEC(ce_s, heap) *argc = NULL;
struct constraint_expr *argp;
int i;
get_constraint_for (arg, &argc);
for (i = 0; VEC_iterate (ce_s, argc, i, argp); i++)
for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
process_constraint_1 (new_constraint (*lhsp, *argp), true);
VEC_free (ce_s, heap, argc);
}
VEC_free (ce_s, heap, lhsc);
}
@ -3636,10 +3710,12 @@ handle_lhs_call (tree lhs)
static void
find_func_aliases (tree origt)
{
tree t = origt;
tree call, t = origt;
VEC(ce_s, heap) *lhsc = NULL;
VEC(ce_s, heap) *rhsc = NULL;
struct constraint_expr *c;
enum escape_type stmt_escape_type;
int flags;
if (TREE_CODE (t) == RETURN_EXPR && TREE_OPERAND (t, 0))
t = TREE_OPERAND (t, 0);
@ -3688,17 +3764,26 @@ find_func_aliases (tree origt)
In non-ipa mode, we need to generate constraints for each
pointer passed by address. */
else if (((TREE_CODE (t) == GIMPLE_MODIFY_STMT
&& TREE_CODE (GIMPLE_STMT_OPERAND (t, 1)) == CALL_EXPR
&& !(call_expr_flags (GIMPLE_STMT_OPERAND (t, 1))
& (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))
|| (TREE_CODE (t) == CALL_EXPR
&& !(call_expr_flags (t)
& (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))))
else if ((call = get_call_expr_in (t)) != NULL_TREE
&& !((flags = call_expr_flags (call))
& (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))
{
if (!in_ipa_mode)
{
if (TREE_CODE (t) == GIMPLE_MODIFY_STMT)
/* Const functions can return their arguments and addresses
of global memory but not of escaped memory. */
if (flags & ECF_CONST)
{
if (TREE_CODE (t) == GIMPLE_MODIFY_STMT
&& could_have_pointers (GIMPLE_STMT_OPERAND (t, 1)))
handle_const_call (t);
}
/* Pure functions can return addresses in and of memory
reachable from their arguments, but they are not an escape
point for reachable memory of their arguments. But as we
do not compute call-used memory separately we cannot do
something special here. */
else if (TREE_CODE (t) == GIMPLE_MODIFY_STMT)
{
handle_rhs_call (GIMPLE_STMT_OPERAND (t, 1));
if (could_have_pointers (GIMPLE_STMT_OPERAND (t, 1)))
@ -3893,6 +3978,57 @@ find_func_aliases (tree origt)
get_varinfo (c->var)->no_tbaa_pruning = true;
}
stmt_escape_type = is_escape_site (t);
if (stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
{
tree rhs;
gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
rhs = GIMPLE_STMT_OPERAND (t, 1);
if (TREE_CODE (rhs) == ADDR_EXPR)
{
tree base = get_base_address (TREE_OPERAND (rhs, 0));
if (base
&& (!DECL_P (base)
|| !is_global_var (base)))
make_escape_constraint (rhs);
}
else if (TREE_CODE (rhs) == SSA_NAME
&& POINTER_TYPE_P (TREE_TYPE (rhs)))
make_escape_constraint (rhs);
else if (could_have_pointers (rhs))
make_escape_constraint (rhs);
}
else if (stmt_escape_type == ESCAPE_BAD_CAST)
{
tree rhs;
gcc_assert (TREE_CODE (t) == GIMPLE_MODIFY_STMT);
rhs = GIMPLE_STMT_OPERAND (t, 1);
gcc_assert (CONVERT_EXPR_P (rhs)
|| TREE_CODE (rhs) == VIEW_CONVERT_EXPR);
rhs = TREE_OPERAND (rhs, 0);
make_escape_constraint (rhs);
}
else if (stmt_escape_type == ESCAPE_TO_ASM)
{
tree link;
int i;
for (i = 0, link = ASM_OUTPUTS (t); link; i++, link = TREE_CHAIN (link))
{
tree op = TREE_VALUE (link);
if (op && could_have_pointers (op))
/* Strictly we'd only need the constraints from ESCAPED and
NONLOCAL. */
make_escape_constraint (op);
}
for (i = 0, link = ASM_INPUTS (t); link; i++, link = TREE_CHAIN (link))
{
tree op = TREE_VALUE (link);
if (op && could_have_pointers (op))
/* Strictly we'd only need the constraint to ESCAPED. */
make_escape_constraint (op);
}
}
/* After promoting variables and computing aliasing we will
need to re-scan most statements. FIXME: Try to minimize the
number of statements re-scanned. It's not really necessary to
@ -4118,9 +4254,10 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
return count;
}
/* Create a constraint from ANYTHING variable to VI. */
/* Create a constraint ID = &FROM. */
static void
make_constraint_from_anything (varinfo_t vi)
make_constraint_from (varinfo_t vi, int from)
{
struct constraint_expr lhs, rhs;
@ -4128,12 +4265,19 @@ make_constraint_from_anything (varinfo_t vi)
lhs.offset = 0;
lhs.type = SCALAR;
rhs.var = anything_id;
rhs.var = from;
rhs.offset = 0;
rhs.type = ADDRESSOF;
process_constraint (new_constraint (lhs, rhs));
}
/* Create a constraint from ANYTHING variable to VI. */
static void
make_constraint_from_anything (varinfo_t vi)
{
make_constraint_from (vi, anything_id);
}
/* Count the number of arguments DECL has, and set IS_VARARGS to true
if it is a varargs function. */
@ -4478,7 +4622,7 @@ intra_create_variable_infos (void)
struct constraint_expr lhs, rhs;
/* For each incoming pointer argument arg, create the constraint ARG
= ANYTHING or a dummy variable if flag_argument_noalias is set. */
= NONLOCAL or a dummy variable if flag_argument_noalias is set. */
for (t = DECL_ARGUMENTS (current_function_decl); t; t = TREE_CHAIN (t))
{
varinfo_t p;
@ -4539,7 +4683,7 @@ intra_create_variable_infos (void)
varinfo_t arg_vi = get_vi_for_tree (t);
for (p = arg_vi; p; p = p->next)
make_constraint_from_anything (p);
make_constraint_from (p, nonlocal_id);
}
}
}
@ -4794,7 +4938,9 @@ find_what_p_points_to (tree p)
aliases. */
if (vi->id == nothing_id)
pi->pt_null = 1;
else if (vi->id == anything_id)
else if (vi->id == anything_id
|| vi->id == nonlocal_id
|| vi->id == escaped_id)
was_pt_anything = 1;
else if (vi->id == readonly_id)
was_pt_anything = 1;
@ -4843,42 +4989,23 @@ find_what_p_points_to (tree p)
return false;
}
/* Mark everything that p points to as call clobbered. Returns true
if everything is done and false if all addressable variables need to
be clobbered because p points to anything. */
/* Mark the ESCAPED solution as call clobbered. Returns false if
pt_anything escaped which needs all locals that have their address
taken marked call clobbered as well. */
bool
clobber_what_p_points_to (tree p)
clobber_what_escaped (void)
{
tree lookup_p = p;
varinfo_t vi;
struct ptr_info_def *pi;
unsigned int i;
bitmap_iterator bi;
if (!have_alias_info)
return false;
/* For parameters, get at the points-to set for the actual parm
decl. */
if (TREE_CODE (p) == SSA_NAME
&& TREE_CODE (SSA_NAME_VAR (p)) == PARM_DECL
&& SSA_NAME_IS_DEFAULT_DEF (p))
lookup_p = SSA_NAME_VAR (p);
vi = lookup_vi_for_tree (lookup_p);
if (!vi)
return false;
/* We are asking for the points-to solution of pointers. */
gcc_assert (!vi->is_artificial_var
&& vi->size == vi->fullsize);
pi = get_ptr_info (p);
/* This variable may have been collapsed, let's get the real
variable. */
vi = get_varinfo (find (vi->id));
variable for escaped_id. */
vi = get_varinfo (find (escaped_id));
/* Mark variables in the solution call-clobbered. */
EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi)
@ -4903,12 +5030,13 @@ clobber_what_p_points_to (tree p)
|| TREE_CODE (vi->decl) == PARM_DECL
|| TREE_CODE (vi->decl) == RESULT_DECL)
&& !unmodifiable_var_p (vi->decl))
mark_call_clobbered (vi->decl, pi->escape_mask);
mark_call_clobbered (vi->decl, ESCAPE_TO_CALL);
}
return true;
}
/* Dump points-to information to OUTFILE. */
void
@ -4959,20 +5087,19 @@ init_base_vars (void)
/* Create the NULL variable, used to represent that a variable points
to NULL. */
nothing_tree = create_tmp_var_raw (void_type_node, "NULL");
var_nothing = new_var_info (nothing_tree, 0, "NULL");
var_nothing = new_var_info (nothing_tree, nothing_id, "NULL");
insert_vi_for_tree (nothing_tree, var_nothing);
var_nothing->is_artificial_var = 1;
var_nothing->offset = 0;
var_nothing->size = ~0;
var_nothing->fullsize = ~0;
var_nothing->is_special_var = 1;
nothing_id = 0;
VEC_safe_push (varinfo_t, heap, varmap, var_nothing);
/* Create the ANYTHING variable, used to represent that a variable
points to some unknown piece of memory. */
anything_tree = create_tmp_var_raw (void_type_node, "ANYTHING");
var_anything = new_var_info (anything_tree, 1, "ANYTHING");
var_anything = new_var_info (anything_tree, anything_id, "ANYTHING");
insert_vi_for_tree (anything_tree, var_anything);
var_anything->is_artificial_var = 1;
var_anything->size = ~0;
@ -4980,7 +5107,6 @@ init_base_vars (void)
var_anything->next = NULL;
var_anything->fullsize = ~0;
var_anything->is_special_var = 1;
anything_id = 1;
/* Anything points to anything. This makes deref constraints just
work in the presence of linked list and other p = *p type loops,
@ -5001,7 +5127,7 @@ init_base_vars (void)
/* Create the READONLY variable, used to represent that a variable
points to readonly memory. */
readonly_tree = create_tmp_var_raw (void_type_node, "READONLY");
var_readonly = new_var_info (readonly_tree, 2, "READONLY");
var_readonly = new_var_info (readonly_tree, readonly_id, "READONLY");
var_readonly->is_artificial_var = 1;
var_readonly->offset = 0;
var_readonly->size = ~0;
@ -5009,7 +5135,6 @@ init_base_vars (void)
var_readonly->next = NULL;
var_readonly->is_special_var = 1;
insert_vi_for_tree (readonly_tree, var_readonly);
readonly_id = 2;
VEC_safe_push (varinfo_t, heap, varmap, var_readonly);
/* readonly memory points to anything, in order to make deref
@ -5020,15 +5145,58 @@ init_base_vars (void)
lhs.var = readonly_id;
lhs.offset = 0;
rhs.type = ADDRESSOF;
rhs.var = anything_id;
rhs.var = readonly_id; /* FIXME */
rhs.offset = 0;
process_constraint (new_constraint (lhs, rhs));
/* Create the ESCAPED variable, used to represent the set of escaped
memory. */
escaped_tree = create_tmp_var_raw (void_type_node, "ESCAPED");
var_escaped = new_var_info (escaped_tree, escaped_id, "ESCAPED");
insert_vi_for_tree (escaped_tree, var_escaped);
var_escaped->is_artificial_var = 1;
var_escaped->offset = 0;
var_escaped->size = ~0;
var_escaped->fullsize = ~0;
var_escaped->is_special_var = 0;
VEC_safe_push (varinfo_t, heap, varmap, var_escaped);
gcc_assert (VEC_index (varinfo_t, varmap, 3) == var_escaped);
/* ESCAPED = *ESCAPED, because escaped is may-deref'd at calls, etc. */
lhs.type = SCALAR;
lhs.var = escaped_id;
lhs.offset = 0;
rhs.type = DEREF;
rhs.var = escaped_id;
rhs.offset = 0;
process_constraint_1 (new_constraint (lhs, rhs), true);
/* Create the NONLOCAL variable, used to represent the set of nonlocal
memory. */
nonlocal_tree = create_tmp_var_raw (void_type_node, "NONLOCAL");
var_nonlocal = new_var_info (nonlocal_tree, nonlocal_id, "NONLOCAL");
insert_vi_for_tree (nonlocal_tree, var_nonlocal);
var_nonlocal->is_artificial_var = 1;
var_nonlocal->offset = 0;
var_nonlocal->size = ~0;
var_nonlocal->fullsize = ~0;
var_nonlocal->is_special_var = 1;
VEC_safe_push (varinfo_t, heap, varmap, var_nonlocal);
/* Nonlocal memory points to escaped (which includes nonlocal),
in order to make deref easier. */
lhs.type = SCALAR;
lhs.var = nonlocal_id;
lhs.offset = 0;
rhs.type = ADDRESSOF;
rhs.var = escaped_id;
rhs.offset = 0;
process_constraint (new_constraint (lhs, rhs));
/* Create the INTEGER variable, used to represent that a variable points
to an INTEGER. */
integer_tree = create_tmp_var_raw (void_type_node, "INTEGER");
var_integer = new_var_info (integer_tree, 3, "INTEGER");
var_integer = new_var_info (integer_tree, integer_id, "INTEGER");
insert_vi_for_tree (integer_tree, var_integer);
var_integer->is_artificial_var = 1;
var_integer->size = ~0;
@ -5036,7 +5204,6 @@ init_base_vars (void)
var_integer->offset = 0;
var_integer->next = NULL;
var_integer->is_special_var = 1;
integer_id = 3;
VEC_safe_push (varinfo_t, heap, varmap, var_integer);
/* INTEGER = ANYTHING, because we don't know where a dereference of
@ -5048,6 +5215,26 @@ init_base_vars (void)
rhs.var = anything_id;
rhs.offset = 0;
process_constraint (new_constraint (lhs, rhs));
/* *ESCAPED = &ESCAPED. This is true because we have to assume
everything pointed to by escaped can also point to escaped. */
lhs.type = DEREF;
lhs.var = escaped_id;
lhs.offset = 0;
rhs.type = ADDRESSOF;
rhs.var = escaped_id;
rhs.offset = 0;
process_constraint_1 (new_constraint (lhs, rhs), true);
/* *ESCAPED = &NONLOCAL. This is true because we have to assume
everything pointed to by escaped can also point to nonlocal. */
lhs.type = DEREF;
lhs.var = escaped_id;
lhs.offset = 0;
rhs.type = ADDRESSOF;
rhs.var = nonlocal_id;
rhs.offset = 0;
process_constraint_1 (new_constraint (lhs, rhs), true);
}
/* Initialize things necessary to perform PTA */