From 5c245b956cc455159f9448456eb12b1b7e5b1a88 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Tue, 27 Oct 2009 15:52:44 +0000 Subject: [PATCH] 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 * 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 --- gcc/ChangeLog | 12 ++ gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/torture/ipa-pta-1.c | 26 ++-- gcc/tree-ssa-structalias.c | 221 +++++++++++++++---------------- 4 files changed, 141 insertions(+), 122 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d8518c0..89051c8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2009-10-27 Richard Guenther + + * 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 PR c/41842 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1ded942..54abf12 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2009-10-27 Richard Guenther + + * gcc.dg/torture/ipa-pta-1.c: Adjust testcase. + 2009-10-27 Jakub Jelinek PR c/41842 diff --git a/gcc/testsuite/gcc.dg/torture/ipa-pta-1.c b/gcc/testsuite/gcc.dg/torture/ipa-pta-1.c index 1096397..7df130a 100644 --- a/gcc/testsuite/gcc.dg/torture/ipa-pta-1.c +++ b/gcc/testsuite/gcc.dg/torture/ipa-pta-1.c @@ -4,31 +4,37 @@ 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++; 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++; 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); } -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++; @@ -36,5 +42,5 @@ void test4 (int a, char b, char c, char d, char e, char f, char g, char h) 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" } } */ diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index cc655df..7b33936 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -3663,8 +3663,8 @@ find_func_aliases (gimple origt) pointer passed by address. */ else if (is_gimple_call (t)) { - tree fndecl; - if ((fndecl = gimple_call_fndecl (t)) != NULL_TREE + tree fndecl = gimple_call_fndecl (t); + if (fndecl != NULL_TREE && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) /* ??? All builtins that are handled here need to be handled in the alias-oracle query functions explicitly! */ @@ -3774,7 +3774,9 @@ find_func_aliases (gimple origt) default: /* 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; int flags = gimple_call_flags (t); @@ -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); 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) push_fields_onto_fieldstack (decl_type, &fieldstack, 0); @@ -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. */ static void @@ -5399,44 +5396,12 @@ delete_alias_heapvars (void) heapvar_for_stmt = NULL; } -/* Create points-to sets for the current function. See the comments - at the start of the file for an algorithmic overview. */ +/* Solve the constraint set. */ static void -compute_points_to_sets (void) +solve_constraints (void) { 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) { @@ -5493,6 +5458,48 @@ compute_points_to_sets (void) if (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 call-clobber analysis. */ @@ -5524,8 +5531,6 @@ compute_points_to_sets (void) } timevar_pop (TV_TREE_PTA); - - have_alias_info = true; } @@ -5559,7 +5564,6 @@ delete_points_to_sets (void) VEC_free (varinfo_t, heap, varmap); free_alloc_pool (variable_info_pool); free_alloc_pool (constraint_pool); - have_alias_info = false; } @@ -5658,101 +5662,94 @@ static unsigned int ipa_pta_execute (void) { struct cgraph_node *node; - struct scc_info *si; in_ipa_mode = 1; + init_alias_heapvars (); init_alias_vars (); + /* Build the constraints. */ for (node = cgraph_nodes; node; node = node->next) { 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, 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) { - if (node->analyzed) - { - struct function *func = DECL_STRUCT_FUNCTION (node->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; + struct function *func; + basic_block bb; + tree old_func_decl; - FOR_EACH_BB_FN (bb, func) - { - gimple_stmt_iterator gsi; + /* Nodes without a body are not interesting. */ + if (!gimple_has_body_p (node->decl) + || node->clone_of) + continue; - for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); - gsi_next (&gsi)) - { - gimple phi = gsi_stmt (gsi); + if (dump_file) + fprintf (dump_file, + "Generating constraints for %s\n", + cgraph_node_name (node)); - if (is_gimple_reg (gimple_phi_result (phi))) - find_func_aliases (phi); - } + func = DECL_STRUCT_FUNCTION (node->decl); + 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)) - find_func_aliases (gsi_stmt (gsi)); - } - current_function_decl = old_func_decl; - pop_cfun (); - } - else - { - /* Make point to anything. */ - } - } + /* For externally visible functions use local constraints for + their arguments. For local functions we see all callers + and thus do not need initial constraints for parameters. */ + if (node->local.externally_visible) + intra_create_variable_infos (); - if (dump_file) - { - fprintf (dump_file, "Points-to analysis\n\nConstraints:\n\n"); - dump_constraints (dump_file); - } + /* Build constriants for the function body. */ + FOR_EACH_BB_FN (bb, func) + { + gimple_stmt_iterator gsi; - if (dump_file) - fprintf (dump_file, - "\nCollapsing static cycles and doing variable " - "substitution:\n"); + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); + gsi_next (&gsi)) + { + gimple phi = gsi_stmt (gsi); - init_graph (VEC_length (varinfo_t, varmap) * 2); - build_pred_graph (); - si = perform_var_substitution (graph); - rewrite_constraints (graph, si); + if (is_gimple_reg (gimple_phi_result (phi))) + find_func_aliases (phi); + } - build_succ_graph (); - free_var_substitution_info (si); - move_complex_constraints (graph); - unite_pointer_equivalences (graph); - find_indirect_cycles (graph); + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); - /* Implicit nodes and predecessors are no longer necessary at this - point. */ - remove_preds_and_fake_succs (graph); + find_func_aliases (stmt); + } + } - if (dump_file) - fprintf (dump_file, "\nSolving graph\n"); + current_function_decl = old_func_decl; + pop_cfun (); + } - solve_graph (graph); + /* From the constraints compute the points-to sets. */ + solve_constraints (); - if (dump_file) - dump_sa_points_to_info (dump_file); + delete_points_to_sets (); in_ipa_mode = 0; - delete_alias_heapvars (); - delete_points_to_sets (); + return 0; } -- 2.7.4