[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