[lto] Handle extern inline functions properly

Diego Novillo dnovillo@google.com
Tue Nov 18 16:35:00 GMT 2008


This patch from Rafael handles extern inline functions by making
sure that they disappear properly before LGEN.

Otherwise, during WPA extern inline functions generate duplicate
cgraph nodes for the same function which conflict with each other
and with the cgraph node for the offline version.

The fix is to simply to call cgraph_remove_unreachable_nodes
before LGEN and properly clearing the inlinability indicator
(disregard_inline_limits).

The third change was not completely necessary but caters to some
testsuite cases that assume that early inline handles every
extern inline function even at -O0.  This forced the move of the
second call to pass_early_inline out of
pass_all_early_optimizations.  Jan, maybe there is a better way
of handling this?

Bootstrapped and tested on x86_64.


Diego.

2008-11-18  Rafael Espindola  <espindola@google.com>
	    Diego Novillo  <dnovillo@google.com>

	* cgraphunit.c (ipa_passes): Move from... 
	(cgraph_optimize): ... here.
	* lto-cgraph.c (output_node): Write out node->lowered
	and node->analyzed.
	(input_overwrite_node): Read in node->lowered and
	node->analyzed.
	* ipa.c (cgraph_remove_unreachable_nodes): Clear
	node->local.disregard_inline_limits when removing a
	node.
	* passes.c (init_optimization_passes): Schedule
	pass_rebuild_cgraph_edges and pass_early_inline outside
	of pass_all_early_optimizations.  Document reason.

testsuite/ChangeLog.lto

2008-11-18  Diego Novillo  <dnovillo@google.com>

	* gcc.dg/lto/20081115_0.c: New.
	* gcc.dg/lto/20081115_1.c: New.
	* gcc.dg/lto/20081115_2.c: New.
	* gcc.dg/lto/20080924_0.c: Brace dg-options properly.
	* gcc.dg/lto/20080917_0.c: Likewise.
	* gcc.dg/lto/20081111_0.c: Likewise.
	* gcc.dg/lto/20081112_0.c: Likewise.

Index: cgraphunit.c
===================================================================
--- cgraphunit.c	(revision 141948)
+++ cgraphunit.c	(working copy)
@@ -1249,6 +1249,10 @@ ipa_passes (void)
   bitmap_obstack_initialize (NULL);
   execute_ipa_pass_list (all_small_ipa_passes);
 
+  /* This pass removes bodies of extern inline functions that we never
+     inlined.  */
+  cgraph_remove_unreachable_nodes (false, dump_file);
+
   execute_ipa_summary_passes ((struct ipa_opt_pass *) all_regular_ipa_passes);
   execute_ipa_summary_passes ((struct ipa_opt_pass *) all_lto_gen_passes);
 
@@ -1294,9 +1298,6 @@ cgraph_optimize (void)
   if (errorcount == 0 && sorrycount == 0)
     ipa_passes ();
 
-  /* This pass remove bodies of extern inline functions we never inlined.
-     Do this later so other IPA passes see what is really going on.  */
-  cgraph_remove_unreachable_nodes (false, dump_file);
   cgraph_global_info_ready = true;
   if (cgraph_dump_file)
     {
Index: testsuite/gcc.dg/lto/20081115_0.c
===================================================================
--- testsuite/gcc.dg/lto/20081115_0.c	(revision 0)
+++ testsuite/gcc.dg/lto/20081115_0.c	(revision 0)
@@ -0,0 +1,32 @@
+/* { dg-options "{-O2 -DOPTIMIZE -fwhopr} {-O0 -fwhopr}" } */
+
+extern void abort (void);
+
+int f (void)
+{
+  return 1;
+}
+
+extern inline int
+e_inline_baz (void)
+{
+  return 1 + f();
+}
+
+int
+bar (void)
+{
+  return e_inline_baz ();
+}
+
+main ()
+{
+#ifdef OPTIMIZE
+  if (bar () != 2 || foo () != 3)
+    abort ();
+#else
+  if (bar () != 0 || foo () != 0)
+    abort ();
+#endif
+  return 0;
+}
Index: testsuite/gcc.dg/lto/20081115_1.c
===================================================================
--- testsuite/gcc.dg/lto/20081115_1.c	(revision 0)
+++ testsuite/gcc.dg/lto/20081115_1.c	(revision 0)
@@ -0,0 +1,11 @@
+extern inline int
+e_inline_baz (void)
+{
+  return 2 + 1;
+}
+
+int
+foo (void)
+{
+  return e_inline_baz ();
+}
Index: testsuite/gcc.dg/lto/20081115_2.c
===================================================================
--- testsuite/gcc.dg/lto/20081115_2.c	(revision 0)
+++ testsuite/gcc.dg/lto/20081115_2.c	(revision 0)
@@ -0,0 +1,5 @@
+int
+e_inline_baz (void)
+{
+  return 0;
+}
Index: testsuite/gcc.dg/lto/20080924_0.c
===================================================================
--- testsuite/gcc.dg/lto/20080924_0.c	(revision 141948)
+++ testsuite/gcc.dg/lto/20080924_0.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile }  */
-/* { dg-options "-O2 -flto-single -funsigned-char" }  */ 
+/* { dg-options "{-O2 -flto-single -funsigned-char}" }  */ 
 typedef unsigned int size_t;
 foo (const char *src, unsigned char *dst, size_t size)
 {
Index: testsuite/gcc.dg/lto/20080917_0.c
===================================================================
--- testsuite/gcc.dg/lto/20080917_0.c	(revision 141948)
+++ testsuite/gcc.dg/lto/20080917_0.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile }  */
-/* { dg-options "-O2 -flto-single -funsigned-char" }  */ 
+/* { dg-options "{-O2 -flto-single -funsigned-char}" }  */ 
 int
 foo (char *s, int flag)
 {
Index: testsuite/gcc.dg/lto/20081111_0.c
===================================================================
--- testsuite/gcc.dg/lto/20081111_0.c	(revision 141948)
+++ testsuite/gcc.dg/lto/20081111_0.c	(working copy)
@@ -1,4 +1,3 @@
-/* { dg-options "-fwhopr" } */
 extern int mumble;
 extern void abort (void);
 extern void exit (int);
Index: testsuite/gcc.dg/lto/20081112_0.c
===================================================================
--- testsuite/gcc.dg/lto/20081112_0.c	(revision 141948)
+++ testsuite/gcc.dg/lto/20081112_0.c	(working copy)
@@ -1,4 +1,3 @@
-/* { dg-options "{-fwhopr -O3}" } */
 extern void exit (int);
 extern void abort (void);
 
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 141948)
+++ lto-cgraph.c	(working copy)
@@ -291,6 +291,8 @@ output_node (struct lto_simple_output_bl
       LTO_DEBUG_FN_NAME (node->decl);
     }
 
+  lto_set_flag (&flags, node->lowered);
+  lto_set_flag (&flags, node->analyzed);
   lto_set_flag (&flags, needed);
   lto_set_flag (&flags, local);
   lto_set_flag (&flags, externally_visible);
@@ -483,8 +485,8 @@ input_overwrite_node (struct lto_file_de
   node->local.externally_visible = lto_get_flag (&flags);
   node->local.local = lto_get_flag (&flags);
   node->needed = lto_get_flag (&flags);
-  node->analyzed = node->local.finalized;
-  node->lowered = node->local.finalized;
+  node->analyzed = lto_get_flag (&flags);
+  node->lowered = lto_get_flag (&flags);
 }
 
 /* Read a node from input_block IB.  TAG is the node's tag just read. 
Index: ipa.c
===================================================================
--- ipa.c	(revision 141948)
+++ ipa.c	(working copy)
@@ -187,6 +187,7 @@ cgraph_remove_unreachable_nodes (bool be
 		  cgraph_node_remove_callees (node);
 		  node->analyzed = false;
 		  node->local.inlinable = false;
+		  node->local.disregard_inline_limits = false;
 		}
 	      else
 		cgraph_remove_node (node);
Index: passes.c
===================================================================
--- passes.c	(revision 141948)
+++ passes.c	(working copy)
@@ -549,11 +549,16 @@ init_optimization_passes (void)
       NEXT_PASS (pass_reset_cc_flags);
       NEXT_PASS (pass_build_ssa);
       NEXT_PASS (pass_early_warn_uninitialized);
+      /* Note that it is not strictly necessary to schedule an early
+	 inline pass here.  However, some test cases (e.g.,
+	 g++.dg/other/p334435.C g++.dg/other/i386-1.C) expect extern
+	 inline functions to be inlined even at -O0.  This does not
+	 happen during the first early inline pass.  */
+      NEXT_PASS (pass_rebuild_cgraph_edges);
+      NEXT_PASS (pass_early_inline);
       NEXT_PASS (pass_all_early_optimizations);
 	{
 	  struct opt_pass **p = &pass_all_early_optimizations.pass.sub;
-	  NEXT_PASS (pass_rebuild_cgraph_edges);
-	  NEXT_PASS (pass_early_inline);
 	  NEXT_PASS (pass_rename_ssa_copies);
 	  NEXT_PASS (pass_ccp);
 	  NEXT_PASS (pass_forwprop);



More information about the Gcc-patches mailing list