Hi, On Wed, Jan 16, 2013 at 10:24:10PM +0100, Jan Hubicka wrote: > > On Wed, Jan 16, 2013 at 01:44:20PM +0100, Jan Hubicka wrote: > > > > Perhaps could you first change cgraph_non_local_node_p_1 and try to > > > > check some code > > > > if codegen differs significantly? It should not at all. > > > > ipa-cp is the sole user of this flag in IPA passes, so you should know > > > > what it does. > > > > > > Thinking deeper of ipa-cp and local virtuals, I think this is all > > > slipperly. > > > Local means that all calls to the functions are explicit and known. > > > Obviously > > > if function is virutal and new calls may appear by devirtualization, the > > > local > > > flag is bogus. I guess the external functions are the only that may be > > > local > > > and virtual because somewhere there must be a vtable reference, but to > > > play > > > safe, I would suggest marking all virtuals non-local. > > > > > > > Right, as discussed on IRC, the patch below therfore modifies > > cgraph_only_called_directly_or_aliased_p to return false for virtual > > functions (which translates into cleared local flag) and the cloning > > machinery to clear that flag. > > > > Bootstrapped and tested on x86_64-linux without any problems. OK for > > trunk? > OK, thanks! > > Honza
Great, thanks. I will therefore also commit the following equivalent to the 4.7 branch on Monday unless someone objects. It passes bootstrap and testsuite without any issues. Thanks, Martin 2013-01-17 Martin Jambor <mjam...@suse.cz> PR tree-optimizations/55264 * cgraph.c (cgraph_create_virtual_clone): Mark clones as non-virtual. * cgraph.h (cgraph_only_called_directly_p_or_aliased_p): Return false for virtual functions. * ipa-inline-transform.c (can_remove_node_now_p_1): Never return true for virtual methods. * ipa.c (cgraph_remove_unreachable_nodes): Never return true for virtual methods before inlining is over. testsuite/ * g++.dg/ipa/pr55264.C: New test. diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 9cc3690..78e131b 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2269,6 +2269,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, TREE_PUBLIC (new_node->decl) = 0; DECL_COMDAT (new_node->decl) = 0; DECL_WEAK (new_node->decl) = 0; + DECL_VIRTUAL_P (new_node->decl) = 0; DECL_STATIC_CONSTRUCTOR (new_node->decl) = 0; DECL_STATIC_DESTRUCTOR (new_node->decl) = 0; new_node->clone.tree_map = tree_map; diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 122a44c..7abfb8a 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -935,6 +935,7 @@ cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node) gcc_assert (!node->global.inlined_to); return (!node->needed && !node->address_taken && !node->reachable_from_other_partition + && !DECL_VIRTUAL_P (node->decl) && !DECL_STATIC_CONSTRUCTOR (node->decl) && !DECL_STATIC_DESTRUCTOR (node->decl) && !node->local.externally_visible); diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index 75b8e9d..ce1bc6e 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -95,9 +95,7 @@ can_remove_node_now_p_1 (struct cgraph_node *node) those only after all devirtualizable virtual calls are processed. Lacking may edges in callgraph we just preserve them post inlining. */ - && (!DECL_VIRTUAL_P (node->decl) - || (!DECL_COMDAT (node->decl) - && !DECL_EXTERNAL (node->decl))) + && !DECL_VIRTUAL_P (node->decl) /* During early inlining some unanalyzed cgraph nodes might be in the callgraph and they might reffer the function in question. */ && !cgraph_new_nodes); diff --git a/gcc/ipa.c b/gcc/ipa.c index 388291a..8c2b3bd 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -194,9 +194,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) if (node->analyzed && !node->global.inlined_to && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node) /* Keep around virtual functions for possible devirtualization. */ - || (before_inlining_p - && DECL_VIRTUAL_P (node->decl) - && (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))))) + || (before_inlining_p && DECL_VIRTUAL_P (node->decl)))) { gcc_assert (!node->global.inlined_to); enqueue_cgraph_node (node, &first); diff --git a/gcc/testsuite/g++.dg/ipa/pr55264.C b/gcc/testsuite/g++.dg/ipa/pr55264.C new file mode 100644 index 0000000..cf54d6a --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr55264.C @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-early-inlining -fno-weak" } */ + +struct S +{ + S(); + virtual inline void foo () + { + foo(); + } +}; + +void +B () +{ + S().foo (); +}