re PR middle-end/68878 (471.omnetpp in SPEC CPU 2006 is miscompiled with LTO)
authorJan Hubicka <hubicka@ucw.cz>
Wed, 16 Dec 2015 04:58:13 +0000 (05:58 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 16 Dec 2015 04:58:13 +0000 (04:58 +0000)
PR lto/68878
* lto-symtab.c (lto_symtab_prevailing_virtual_decl): New function.
* lto-symtab.h (lto_symtab_prevailing_virtual_decl): Declare.
(lto_symtab_prevailing_decl): Use it.

From-SVN: r231671

gcc/lto/ChangeLog
gcc/lto/lto-symtab.c
gcc/lto/lto-symtab.h

index ac20a3f2dde4baddc26a4a24abc345f679984a6c..1e509b1c7a9fe36a8464871b3fb0d0618160a439 100644 (file)
@@ -1,3 +1,10 @@
+2015-12-10  Jan Hubicka  <hubicka@ucw.cz>
+
+       PR lto/68878
+       * lto-symtab.c (lto_symtab_prevailing_virtual_decl): New function.
+       * lto-symtab.h (lto_symtab_prevailing_virtual_decl): Declare.
+       (lto_symtab_prevailing_decl): Use it.
+
 2015-12-15  Ilya Verbin  <ilya.verbin@intel.com>
 
        * lto.c: Include stringpool.h and fold-const.h.
index 35c690ae41a117ecb83b5f786b3a3ad01e63eca9..957fbf6a6b103c8c5e12f08e996f1914106fc044 100644 (file)
@@ -517,6 +517,8 @@ lto_symtab_merge_p (tree prevailing, tree decl)
                 "TREE_CODE mismatch\n");
       return false;
     }
+  gcc_checking_assert (TREE_CHAIN (prevailing) == TREE_CHAIN (decl));
+  
   if (TREE_CODE (prevailing) == FUNCTION_DECL)
     {
       if (DECL_BUILT_IN (prevailing) != DECL_BUILT_IN (decl))
@@ -883,6 +885,11 @@ lto_symtab_merge_symbols_1 (symtab_node *prevailing)
          else
            {
              DECL_INITIAL (e->decl) = error_mark_node;
+             if (e->lto_file_data)
+               {
+                 lto_free_function_in_decl_state_for_node (e);
+                 e->lto_file_data = NULL;
+               }
              symtab->call_varpool_removal_hooks (dyn_cast<varpool_node *> (e));
            }
          e->remove_all_references ();
@@ -968,3 +975,33 @@ lto_symtab_merge_symbols (void)
        }
     }
 }
+
+/* Virtual tables may matter for code generation even if they are not
+   directly refernced by the code because they may be used for devirtualizaiton.
+   For this reason it is important to merge even virtual tables that have no
+   associated symbol table entries.  Without doing so we lose optimization
+   oppurtunities by losing track of the vtable constructor.
+   FIXME: we probably ought to introduce explicit symbol table entries for
+   those before streaming.  */
+
+tree
+lto_symtab_prevailing_virtual_decl (tree decl)
+{
+  gcc_checking_assert (!type_in_anonymous_namespace_p (DECL_CONTEXT (decl))
+                      && DECL_ASSEMBLER_NAME_SET_P (decl));
+
+  symtab_node *n = symtab_node::get_for_asmname
+                    (DECL_ASSEMBLER_NAME (decl));
+  while (n && ((!DECL_EXTERNAL (n->decl) && !TREE_PUBLIC (n->decl))
+              || !DECL_VIRTUAL_P (n->decl)))
+    n = n->next_sharing_asm_name;
+  if (n)
+    {
+      lto_symtab_prevail_decl (n->decl, decl);
+      decl = n->decl;
+    }
+  else
+    symtab_node::get_create (decl);
+
+  return decl;
+}
index c6b68b6001e3a52e0a1091b24ed2e558f1c80006..4c446312cfb587423c370218367c77cb565b28b4 100644 (file)
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 extern void lto_symtab_merge_decls (void);
 extern void lto_symtab_merge_symbols (void);
 extern tree lto_symtab_prevailing_decl (tree decl);
+extern tree lto_symtab_prevailing_virtual_decl (tree decl);
 
 /* Mark DECL to be previailed by PREVAILING.
    Use DECL_ABSTRACT_ORIGIN and DECL_CHAIN as special markers; those do not
@@ -31,6 +32,7 @@ inline void
 lto_symtab_prevail_decl (tree prevailing, tree decl)
 {
   gcc_checking_assert (DECL_ABSTRACT_ORIGIN (decl) != error_mark_node);
+  gcc_assert (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl));
   DECL_CHAIN (decl) = prevailing;
   DECL_ABSTRACT_ORIGIN (decl) = error_mark_node;
 }
@@ -43,5 +45,12 @@ lto_symtab_prevailing_decl (tree decl)
   if (DECL_ABSTRACT_ORIGIN (decl) == error_mark_node)
     return DECL_CHAIN (decl);
   else
-    return decl;
+    {
+      if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
+         && DECL_VIRTUAL_P (decl)
+         && (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
+         && !symtab_node::get (decl))
+       return lto_symtab_prevailing_virtual_decl (decl);
+      return decl;
+    }
 }