Hi,

PR 55264 is caused by cgraph machinery thinking it knows all calls to
a virtual method when that is actually not true.  As discussed with
Honza, prior to inlining, we should not assume some virtual functions
(namely those that are neither DECL_COMDAT nor DECL_EXTERNAL) are not
reachable.

DECL_EXTERNAL however still affects the cgraph_node->local.local flag
and so in order to avoid some LTO failures, I had to adjust IPA-CP to
consider such virtual functions non-local so that verification of
lattice propagation does not complain.  I'm a bit puzzled by the value
of the flag in this situation but at least it does not seem to cause
any other problems.

Below is a trunk patch to do all this.  It does not apply to released
versions which also suffer from the same problem so I'll prepare a
special version(s) for them once this gets approved.  Bootstrapped and
tested on x86_64-linux.  OK for trunk?

Thanks,

Martin


2013-01-15  Martin Jambor  <mjam...@suse.cz>

        PR tree-optimizations/55264
        * ipa-inline-transform.c (can_remove_node_now_p_1): Never return true
        for virtual methods.
        * ipa.c (symtab_remove_unreachable_nodes): Never return true for
        virtual methods before inlining is over.
        * ipa-cp.c (initialize_node_lattices): Also consider all virtual
        methods non-local.

testsuite/
        * g++.dg/ipa/pr55264.C: New test.

Index: src/gcc/ipa-inline-transform.c
===================================================================
--- src.orig/gcc/ipa-inline-transform.c
+++ src/gcc/ipa-inline-transform.c
@@ -92,9 +92,7 @@ can_remove_node_now_p_1 (struct cgraph_n
             those only after all devirtualizable virtual calls are processed.
             Lacking may edges in callgraph we just preserve them post
             inlining.  */
-         && (!DECL_VIRTUAL_P (node->symbol.decl)
-             || (!DECL_COMDAT (node->symbol.decl)
-                 && !DECL_EXTERNAL (node->symbol.decl)))
+         && !DECL_VIRTUAL_P (node->symbol.decl)
          /* During early inlining some unanalyzed cgraph nodes might be in the
             callgraph and they might reffer the function in question.  */
          && !cgraph_new_nodes);
Index: src/gcc/ipa.c
===================================================================
--- src.orig/gcc/ipa.c
+++ src/gcc/ipa.c
@@ -241,8 +241,7 @@ symtab_remove_unreachable_nodes (bool be
        && (!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->symbol.decl)
-               && (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL 
(node->symbol.decl)))))
+               && DECL_VIRTUAL_P (node->symbol.decl))))
       {
         gcc_assert (!node->global.inlined_to);
        pointer_set_insert (reachable, node);
Index: src/gcc/testsuite/g++.dg/ipa/pr55264.C
===================================================================
--- /dev/null
+++ src/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 ();
+}
Index: src/gcc/ipa-cp.c
===================================================================
--- src.orig/gcc/ipa-cp.c
+++ src/gcc/ipa-cp.c
@@ -699,7 +699,8 @@ initialize_node_lattices (struct cgraph_
   int i;
 
   gcc_checking_assert (cgraph_function_with_gimple_body_p (node));
-  if (!node->local.local)
+  if (!node->local.local
+      || DECL_VIRTUAL_P (node->symbol.decl))
     {
       /* When cloning is allowed, we can assume that externally visible
         functions are not called.  We will compensate this by cloning

Reply via email to