The following fixes PR60912 - a bug with IPA PTA computing the use/clobber sets for direct calls where it "optimized" walking using the cgraph nodes caller list. But that can be incomplete in the face of aliases. Luckily that optimization is no longer necessary because we now cache the outcome of find_what_var_points_to, thus removing it fixes the issue.
Bootstrap and regtest ongoing on x86_64-unknown-linux-gnu, will apply to trunk and 4.9 branch. Thanks, Richard. 2014-04-24 Richard Biener <rguent...@suse.de> PR ipa/60912 * tree-ssa-structalias.c (ipa_pta_execute): Compute direct call stmt use/clobber sets during stmt walk instead of walking the possibly incomplete set of caller edges. * g++.dg/opt/pr60912.C: New testcase. Index: gcc/tree-ssa-structalias.c =================================================================== *** gcc/tree-ssa-structalias.c (revision 209744) --- gcc/tree-ssa-structalias.c (working copy) *************** ipa_pta_execute (void) *** 7244,7253 **** tree ptr; struct function *fn; unsigned i; - varinfo_t fi; basic_block bb; - struct pt_solution uses, clobbers; - struct cgraph_edge *e; /* Nodes without a body are not interesting. */ if (!cgraph_function_with_gimple_body_p (node) || node->clone_of) --- 7244,7250 ---- *************** ipa_pta_execute (void) *** 7263,7283 **** find_what_p_points_to (ptr); } - /* Compute the call-use and call-clobber sets for all direct calls. */ - fi = lookup_vi_for_tree (node->decl); - gcc_assert (fi->is_fn_info); - clobbers - = find_what_var_points_to (first_vi_for_offset (fi, fi_clobbers)); - uses = find_what_var_points_to (first_vi_for_offset (fi, fi_uses)); - for (e = node->callers; e; e = e->next_caller) - { - if (!e->call_stmt) - continue; - - *gimple_call_clobber_set (e->call_stmt) = clobbers; - *gimple_call_use_set (e->call_stmt) = uses; - } - /* Compute the call-use and call-clobber sets for indirect calls and calls to external functions. */ FOR_EACH_BB_FN (bb, fn) --- 7260,7265 ---- *************** ipa_pta_execute (void) *** 7288,7304 **** { gimple stmt = gsi_stmt (gsi); struct pt_solution *pt; ! varinfo_t vi; tree decl; if (!is_gimple_call (stmt)) continue; ! /* Handle direct calls to external functions. */ decl = gimple_call_fndecl (stmt); if (decl ! && (!(fi = lookup_vi_for_tree (decl)) ! || !fi->is_fn_info)) { pt = gimple_call_use_set (stmt); if (gimple_call_flags (stmt) & ECF_CONST) --- 7270,7296 ---- { gimple stmt = gsi_stmt (gsi); struct pt_solution *pt; ! varinfo_t vi, fi; tree decl; if (!is_gimple_call (stmt)) continue; ! /* Handle direct calls to functions with body. */ decl = gimple_call_fndecl (stmt); if (decl ! && (fi = lookup_vi_for_tree (decl)) ! && fi->is_fn_info) ! { ! *gimple_call_clobber_set (stmt) ! = find_what_var_points_to ! (first_vi_for_offset (fi, fi_clobbers)); ! *gimple_call_use_set (stmt) ! = find_what_var_points_to ! (first_vi_for_offset (fi, fi_uses)); ! } ! /* Handle direct calls to external functions. */ ! else if (decl) { pt = gimple_call_use_set (stmt); if (gimple_call_flags (stmt) & ECF_CONST) *************** ipa_pta_execute (void) *** 7342,7351 **** pt->nonlocal = 1; } } - /* Handle indirect calls. */ ! if (!decl ! && (fi = get_fi_for_callee (stmt))) { /* We need to accumulate all clobbers/uses of all possible callees. */ --- 7334,7342 ---- pt->nonlocal = 1; } } /* Handle indirect calls. */ ! else if (!decl ! && (fi = get_fi_for_callee (stmt))) { /* We need to accumulate all clobbers/uses of all possible callees. */ Index: gcc/testsuite/g++.dg/opt/pr60912.C =================================================================== *** gcc/testsuite/g++.dg/opt/pr60912.C (revision 0) --- gcc/testsuite/g++.dg/opt/pr60912.C (working copy) *************** *** 0 **** --- 1,18 ---- + // { dg-do run } + // { dg-options "-O -fno-inline -fipa-pta" } + + struct IFoo + { + virtual void Foo () = 0; + }; + + struct Bar:IFoo + { + void Foo () {} + }; + + int main () + { + (new Bar ())->Foo (); + return 0; + }