Patchwork Drop V1 plugin API hack

login
register
mail settings
Submitter Jan Hubicka
Date Oct. 6, 2012, 4:46 p.m.
Message ID <20121006164644.GB5193@kam.mff.cuni.cz>
Download mbox | patch
Permalink /patch/189746/
State New
Headers show

Comments

Jan Hubicka - Oct. 6, 2012, 4:46 p.m.
Hi,
this patch removes V1 API hack, making us to require V2 plugin api aware linker
to get sane code quality on anything using COMDAT.  Given that the V1 API
linkers are quite old now, I think it is safe.  I added a testcase that should
fail with old linker and will update changes.html.

The patch also cleans up the code for new symbol table APIs.  Nice effect is
that inliner is now more aggressive about inlining comdats and thus tramp3d
scoes are improved with -flto once again.

lto-bootstrapped/regtested x86_64, comitted.

Honza
	PR lto/53831
	PR lto/54776
	* g++.dg/lto/v1-plugin-api-not-supported.C: New testcase.
	* lto-streamer-out.c (produce_symtab): Cleanup; drop v1 API hack.

Patch

Index: testsuite/g++.dg/lto/v1-plugin-api-not-supported.C
===================================================================
--- testsuite/g++.dg/lto/v1-plugin-api-not-supported.C	(revision 0)
+++ testsuite/g++.dg/lto/v1-plugin-api-not-supported.C	(revision 0)
@@ -0,0 +1,59 @@ 
+// { dg-lto-do run }
+// { dg-require-linker-plugin "" }
+// { dg-lto-options {{-O2 -fuse-linker-plugin -fno-early-inlining}}
+
+extern "C" void abort (void);
+extern "C" void linker_error ();
+
+class A
+{
+public:
+  int data;
+  virtual int foo (int i)
+    {
+      return i + 1;
+    }
+};
+
+class B : public A
+{
+public:
+  virtual int foo (int i)
+    {
+      return i + 2;
+    }
+};
+
+class C : public A
+{
+public:
+  virtual int foo (int i)
+    {
+      linker_error ();
+      return i + 3;
+    }
+};
+
+
+static int middleman (class A *obj, int i)
+{
+  return obj->foo (i);
+}
+
+int __attribute__ ((noinline,noclone)) get_input(void)
+{
+  return 1;
+}
+
+int main (int argc, char *argv[])
+{
+  class B b;
+  if (middleman (&b, get_input ()) != 3)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target.*B::foo"  "cp"  } } */
+/* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "optimized"} } */
+/* { dg-final { cleanup-ipa-dump "cp" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
Index: lto-streamer-out.c
===================================================================
--- lto-streamer-out.c	(revision 192154)
+++ lto-streamer-out.c	(working copy)
@@ -1285,11 +1287,9 @@  produce_symtab (struct output_block *ob)
   struct streamer_tree_cache_d *cache = ob->writer_cache;
   char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
   struct pointer_set_t *seen;
-  struct cgraph_node *node;
-  struct varpool_node *vnode;
   struct lto_output_stream stream;
   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
-  int i;
+  lto_symtab_encoder_iterator lsei;
 
   lto_begin_section (section_name, false);
   free (section_name);
@@ -1297,78 +1297,26 @@  produce_symtab (struct output_block *ob)
   seen = pointer_set_create ();
   memset (&stream, 0, sizeof (stream));
 
-  /* Write all functions. 
-     First write all defined functions and then write all used functions.
-     This is done so only to handle duplicated symbols in cgraph.  */
-  for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
+  /* Write the symbol table.
+     First write everything defined and then all declarations.
+     This is neccesary to handle cases where we have duplicated symbols.  */
+  for (lsei = lsei_start (encoder);
+       !lsei_end_p (lsei); lsei_next (&lsei))
     {
-      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
-	continue;
-      node = cgraph (lto_symtab_encoder_deref (encoder, i));
-      if (DECL_EXTERNAL (node->symbol.decl))
-	continue;
-      if (DECL_COMDAT (node->symbol.decl)
-	  && cgraph_comdat_can_be_unshared_p (node))
-	continue;
-      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
+      symtab_node node = lsei_node (lsei);
+
+      if (!symtab_real_symbol_p (node) || DECL_EXTERNAL (node->symbol.decl))
 	continue;
       write_symbol (cache, &stream, node->symbol.decl, seen, false);
     }
-  for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
+  for (lsei = lsei_start (encoder);
+       !lsei_end_p (lsei); lsei_next (&lsei))
     {
-      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
-	continue;
-      node = cgraph (lto_symtab_encoder_deref (encoder, i));
-      if (!DECL_EXTERNAL (node->symbol.decl))
-	continue;
-      /* We keep around unused extern inlines in order to be able to inline
-	 them indirectly or via vtables.  Do not output them to symbol
-	 table: they end up being undefined and just consume space.  */
-      if (!node->symbol.address_taken && !node->callers)
-	continue;
-      if (DECL_COMDAT (node->symbol.decl)
-	  && cgraph_comdat_can_be_unshared_p (node))
-	continue;
-      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
-	continue;
-      write_symbol (cache, &stream, node->symbol.decl, seen, false);
-    }
+      symtab_node node = lsei_node (lsei);
 
-  /* Write all variables.  */
-  for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
-    {
-      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
-	continue;
-      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
-      if (DECL_EXTERNAL (vnode->symbol.decl))
-	continue;
-      /* COMDAT virtual tables can be unshared.  Do not declare them
-	 in the LTO symbol table to prevent linker from forcing them
-	 into the output. */
-      if (DECL_COMDAT (vnode->symbol.decl)
-	  && !vnode->symbol.force_output
-	  && vnode->finalized 
-	  && DECL_VIRTUAL_P (vnode->symbol.decl))
-	continue;
-      if (vnode->alias && !vnode->alias_of)
-	continue;
-      write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
-    }
-  for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
-    {
-      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
-	continue;
-      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
-      if (!DECL_EXTERNAL (vnode->symbol.decl))
+      if (!symtab_real_symbol_p (node) || !DECL_EXTERNAL (node->symbol.decl))
 	continue;
-      if (DECL_COMDAT (vnode->symbol.decl)
-	  && !vnode->symbol.force_output
-	  && vnode->finalized 
-	  && DECL_VIRTUAL_P (vnode->symbol.decl))
-	continue;
-      if (vnode->alias && !vnode->alias_of)
-	continue;
-      write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
+      write_symbol (cache, &stream, node->symbol.decl, seen, false);
     }
 
   lto_write_stream (&stream);