Commit 5c245b95 by Richard Guenther Committed by Richard Biener

tree-ssa-structalias.c (find_func_aliases): In IPA mode handle calls to…

tree-ssa-structalias.c (find_func_aliases): In IPA mode handle calls to externally visible functions like in regular mode.

2009-10-27  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-structalias.c (find_func_aliases): In IPA mode
	handle calls to externally visible functions like in regular mode.
	(create_variable_info_for): Do not create function infos here.
	(have_alias_info): Remove write-only variable.
	(solve_constraints): New function split out from common code
	in compute_points_to_sets and ipa_pta_execute.
	(compute_points_to_sets): Adjust.
	(ipa_pta_execute): Likewise.  Handle clones and externally visible
	functions like in non-IPA mode.

	* gcc.dg/torture/ipa-pta-1.c: Adjust testcase.

From-SVN: r153600
parent 06302a02
2009-10-27 Richard Guenther <rguenther@suse.de>
* tree-ssa-structalias.c (find_func_aliases): In IPA mode
handle calls to externally visible functions like in regular mode.
(create_variable_info_for): Do not create function infos here.
(have_alias_info): Remove write-only variable.
(solve_constraints): New function split out from common code
in compute_points_to_sets and ipa_pta_execute.
(compute_points_to_sets): Adjust.
(ipa_pta_execute): Likewise. Handle clones and externally visible
functions like in non-IPA mode.
2009-10-27 Jakub Jelinek <jakub@redhat.com> 2009-10-27 Jakub Jelinek <jakub@redhat.com>
PR c/41842 PR c/41842
2009-10-27 Richard Guenther <rguenther@suse.de>
* gcc.dg/torture/ipa-pta-1.c: Adjust testcase.
2009-10-27 Jakub Jelinek <jakub@redhat.com> 2009-10-27 Jakub Jelinek <jakub@redhat.com>
PR c/41842 PR c/41842
......
...@@ -4,31 +4,37 @@ ...@@ -4,31 +4,37 @@
struct X { char x; char y; }; struct X { char x; char y; };
void bar (char *p); char *q;
void test1 (char a, char b, char c, char d, char e, char f, char g, char h) static void __attribute__((noinline))
bar (char *p)
{ {
char *p = &a; q = p;
}
void test1 (char a1, char b, char c, char d, char e, char f, char g, char h)
{
char *p = &a1;
p++; p++;
bar (p); bar (p);
} }
void test2 (struct X a, char b, char c, char d, char e, char f, char g, char h) void test2 (struct X a2, char b, char c, char d, char e, char f, char g, char h)
{ {
char *p = &a.x; char *p = &a2.x;
p++; p++;
bar (p); bar (p);
} }
void test3 (struct X a, char b, char c, char d, char e, char f, char g, char h) void test3 (struct X a3, char b, char c, char d, char e, char f, char g, char h)
{ {
char *p = &a.y; char *p = &a3.y;
bar (p); bar (p);
} }
void test4 (int a, char b, char c, char d, char e, char f, char g, char h) void test4 (int a4, char b, char c, char d, char e, char f, char g, char h)
{ {
char *p = (char *)&a; char *p = (char *)&a4;
p++; p++;
p++; p++;
p++; p++;
...@@ -36,5 +42,5 @@ void test4 (int a, char b, char c, char d, char e, char f, char g, char h) ...@@ -36,5 +42,5 @@ void test4 (int a, char b, char c, char d, char e, char f, char g, char h)
bar (p); bar (p);
} }
/* { dg-final { scan-ipa-dump "bar.arg0 = { test4.arg0 test3.arg0 test2.arg0 test1.arg0 }" "pta" } } */ /* { dg-final { scan-ipa-dump "bar.arg0 = { a4 a3 a2 a1 }" "pta" } } */
/* { dg-final { cleanup-ipa-dump "pta" } } */ /* { dg-final { cleanup-ipa-dump "pta" } } */
...@@ -3663,8 +3663,8 @@ find_func_aliases (gimple origt) ...@@ -3663,8 +3663,8 @@ find_func_aliases (gimple origt)
pointer passed by address. */ pointer passed by address. */
else if (is_gimple_call (t)) else if (is_gimple_call (t))
{ {
tree fndecl; tree fndecl = gimple_call_fndecl (t);
if ((fndecl = gimple_call_fndecl (t)) != NULL_TREE if (fndecl != NULL_TREE
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
/* ??? All builtins that are handled here need to be handled /* ??? All builtins that are handled here need to be handled
in the alias-oracle query functions explicitly! */ in the alias-oracle query functions explicitly! */
...@@ -3774,7 +3774,9 @@ find_func_aliases (gimple origt) ...@@ -3774,7 +3774,9 @@ find_func_aliases (gimple origt)
default: default:
/* Fallthru to general call handling. */; /* Fallthru to general call handling. */;
} }
if (!in_ipa_mode) if (!in_ipa_mode
|| (fndecl
&& !lookup_vi_for_tree (fndecl)))
{ {
VEC(ce_s, heap) *rhsc = NULL; VEC(ce_s, heap) *rhsc = NULL;
int flags = gimple_call_flags (t); int flags = gimple_call_flags (t);
...@@ -4425,9 +4427,6 @@ create_variable_info_for (tree decl, const char *name) ...@@ -4425,9 +4427,6 @@ create_variable_info_for (tree decl, const char *name)
tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decl_type); tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decl_type);
VEC (fieldoff_s,heap) *fieldstack = NULL; VEC (fieldoff_s,heap) *fieldstack = NULL;
if (TREE_CODE (decl) == FUNCTION_DECL && in_ipa_mode)
return create_function_info_for (decl, name);
if (var_can_have_subvars (decl) && use_field_sensitive) if (var_can_have_subvars (decl) && use_field_sensitive)
push_fields_onto_fieldstack (decl_type, &fieldstack, 0); push_fields_onto_fieldstack (decl_type, &fieldstack, 0);
...@@ -4773,8 +4772,6 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt) ...@@ -4773,8 +4772,6 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
} }
static bool have_alias_info = false;
/* Compute the points-to solution *PT for the variable VI. */ /* Compute the points-to solution *PT for the variable VI. */
static void static void
...@@ -5399,44 +5396,12 @@ delete_alias_heapvars (void) ...@@ -5399,44 +5396,12 @@ delete_alias_heapvars (void)
heapvar_for_stmt = NULL; heapvar_for_stmt = NULL;
} }
/* Create points-to sets for the current function. See the comments /* Solve the constraint set. */
at the start of the file for an algorithmic overview. */
static void static void
compute_points_to_sets (void) solve_constraints (void)
{ {
struct scc_info *si; struct scc_info *si;
basic_block bb;
unsigned i;
varinfo_t vi;
timevar_push (TV_TREE_PTA);
init_alias_vars ();
init_alias_heapvars ();
intra_create_variable_infos ();
/* Now walk all statements and derive aliases. */
FOR_EACH_BB (bb)
{
gimple_stmt_iterator gsi;
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple phi = gsi_stmt (gsi);
if (is_gimple_reg (gimple_phi_result (phi)))
find_func_aliases (phi);
}
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple stmt = gsi_stmt (gsi);
find_func_aliases (stmt);
}
}
if (dump_file) if (dump_file)
{ {
...@@ -5493,6 +5458,48 @@ compute_points_to_sets (void) ...@@ -5493,6 +5458,48 @@ compute_points_to_sets (void)
if (dump_file) if (dump_file)
dump_sa_points_to_info (dump_file); dump_sa_points_to_info (dump_file);
}
/* Create points-to sets for the current function. See the comments
at the start of the file for an algorithmic overview. */
static void
compute_points_to_sets (void)
{
basic_block bb;
unsigned i;
varinfo_t vi;
timevar_push (TV_TREE_PTA);
init_alias_vars ();
init_alias_heapvars ();
intra_create_variable_infos ();
/* Now walk all statements and derive aliases. */
FOR_EACH_BB (bb)
{
gimple_stmt_iterator gsi;
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple phi = gsi_stmt (gsi);
if (is_gimple_reg (gimple_phi_result (phi)))
find_func_aliases (phi);
}
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple stmt = gsi_stmt (gsi);
find_func_aliases (stmt);
}
}
/* From the constraints compute the points-to sets. */
solve_constraints ();
/* Compute the points-to sets for ESCAPED and CALLUSED used for /* Compute the points-to sets for ESCAPED and CALLUSED used for
call-clobber analysis. */ call-clobber analysis. */
...@@ -5524,8 +5531,6 @@ compute_points_to_sets (void) ...@@ -5524,8 +5531,6 @@ compute_points_to_sets (void)
} }
timevar_pop (TV_TREE_PTA); timevar_pop (TV_TREE_PTA);
have_alias_info = true;
} }
...@@ -5559,7 +5564,6 @@ delete_points_to_sets (void) ...@@ -5559,7 +5564,6 @@ delete_points_to_sets (void)
VEC_free (varinfo_t, heap, varmap); VEC_free (varinfo_t, heap, varmap);
free_alloc_pool (variable_info_pool); free_alloc_pool (variable_info_pool);
free_alloc_pool (constraint_pool); free_alloc_pool (constraint_pool);
have_alias_info = false;
} }
...@@ -5658,101 +5662,94 @@ static unsigned int ...@@ -5658,101 +5662,94 @@ static unsigned int
ipa_pta_execute (void) ipa_pta_execute (void)
{ {
struct cgraph_node *node; struct cgraph_node *node;
struct scc_info *si;
in_ipa_mode = 1; in_ipa_mode = 1;
init_alias_heapvars (); init_alias_heapvars ();
init_alias_vars (); init_alias_vars ();
/* Build the constraints. */
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
{ {
unsigned int varid; unsigned int varid;
/* Nodes without a body are not interesting. Especially do not
visit clones at this point for now - we get duplicate decls
there for inline clones at least. */
if (!gimple_has_body_p (node->decl)
|| node->clone_of)
continue;
/* It does not make sense to have graph edges into or out of
externally visible functions. There is no extra information
we can gather from them. */
if (node->local.externally_visible)
continue;
varid = create_function_info_for (node->decl, varid = create_function_info_for (node->decl,
cgraph_node_name (node)); cgraph_node_name (node));
if (node->local.externally_visible)
{
varinfo_t fi = get_varinfo (varid);
for (; fi; fi = fi->next)
make_constraint_from (fi, anything_id);
}
} }
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
{ {
if (node->analyzed) struct function *func;
{ basic_block bb;
struct function *func = DECL_STRUCT_FUNCTION (node->decl); tree old_func_decl;
basic_block bb;
tree old_func_decl = current_function_decl;
if (dump_file)
fprintf (dump_file,
"Generating constraints for %s\n",
cgraph_node_name (node));
push_cfun (func);
current_function_decl = node->decl;
FOR_EACH_BB_FN (bb, func) /* Nodes without a body are not interesting. */
{ if (!gimple_has_body_p (node->decl)
gimple_stmt_iterator gsi; || node->clone_of)
continue;
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); if (dump_file)
gsi_next (&gsi)) fprintf (dump_file,
{ "Generating constraints for %s\n",
gimple phi = gsi_stmt (gsi); cgraph_node_name (node));
if (is_gimple_reg (gimple_phi_result (phi))) func = DECL_STRUCT_FUNCTION (node->decl);
find_func_aliases (phi); old_func_decl = current_function_decl;
} push_cfun (func);
current_function_decl = node->decl;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) /* For externally visible functions use local constraints for
find_func_aliases (gsi_stmt (gsi)); their arguments. For local functions we see all callers
} and thus do not need initial constraints for parameters. */
current_function_decl = old_func_decl; if (node->local.externally_visible)
pop_cfun (); intra_create_variable_infos ();
}
else
{
/* Make point to anything. */
}
}
if (dump_file) /* Build constriants for the function body. */
{ FOR_EACH_BB_FN (bb, func)
fprintf (dump_file, "Points-to analysis\n\nConstraints:\n\n"); {
dump_constraints (dump_file); gimple_stmt_iterator gsi;
}
if (dump_file) for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
fprintf (dump_file, gsi_next (&gsi))
"\nCollapsing static cycles and doing variable " {
"substitution:\n"); gimple phi = gsi_stmt (gsi);
init_graph (VEC_length (varinfo_t, varmap) * 2); if (is_gimple_reg (gimple_phi_result (phi)))
build_pred_graph (); find_func_aliases (phi);
si = perform_var_substitution (graph); }
rewrite_constraints (graph, si);
build_succ_graph (); for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
free_var_substitution_info (si); {
move_complex_constraints (graph); gimple stmt = gsi_stmt (gsi);
unite_pointer_equivalences (graph);
find_indirect_cycles (graph);
/* Implicit nodes and predecessors are no longer necessary at this find_func_aliases (stmt);
point. */ }
remove_preds_and_fake_succs (graph); }
if (dump_file) current_function_decl = old_func_decl;
fprintf (dump_file, "\nSolving graph\n"); pop_cfun ();
}
solve_graph (graph); /* From the constraints compute the points-to sets. */
solve_constraints ();
if (dump_file) delete_points_to_sets ();
dump_sa_points_to_info (dump_file);
in_ipa_mode = 0; in_ipa_mode = 0;
delete_alias_heapvars ();
delete_points_to_sets ();
return 0; return 0;
} }
......
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