This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH, PR 55264] Do not remove as unreachable any virtual methods before inlining
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 <mjambor@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 ();
+}