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 ();
+}

Reply via email to