[PATCH][LTO] Fix ICE in output_node of lto-cgraph.c
Doug Kwan (關振德)
dougkwan@google.com
Tue Dec 2 08:59:00 GMT 2008
Hi Diego,
This patch fixes an ICE in output_node of lto-cgraph.c. When we
add the master clone of an inlined function F to a cgraph node set S,
F itself may contain other inlined functions. The inlines of F may
not be in S. We redirect all such inlines to their master clones and
make the edges appear non-inlined. This is done so that we don't have
boundary nodes that are (non-master) clones. Essentially we disable
any inlining across the boundary of the set S. We only care about
inlining inside S.
This is a tested on i686-unknown-linux-gnu.
-Doug
2008-12-01 Doug Kwan <dougkwan@google.com>
ChangeLog.lto:
* lto-cgraph.c (maybe_redirect_inlined_node): New.
(output_edge): Add new parameter SET. Redirect an inlined callee
which is outside of SET to its master clone. Fix-up INLINE_FAILED
if callee is redirected.
(output_cgraph): Redirect an inlined callee which is outside of SET to
its master clone. Adjust call to output_edge for new parameter.
testsuite/ChangeLog.lto:
* gcc.dg/lto/20081201-1_0.c: New.
* gcc.dg/lto/20081201-1_1.c: New.
* gcc.dg/lto/20081201-1_2.c: New.
* gcc.dg/lto/20081201-2_0.c: New.
* gcc.dg/lto/20081201-2_1.c: New.
-------------- next part --------------
Index: gcc/gcc/testsuite/gcc.dg/lto/20081201-1_0.c
===================================================================
--- gcc/gcc/testsuite/gcc.dg/lto/20081201-1_0.c (revision 0)
+++ gcc/gcc/testsuite/gcc.dg/lto/20081201-1_0.c (revision 0)
@@ -0,0 +1,33 @@
+/* { 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: gcc/gcc/testsuite/gcc.dg/lto/20081201-1_1.c
===================================================================
--- gcc/gcc/testsuite/gcc.dg/lto/20081201-1_1.c (revision 0)
+++ gcc/gcc/testsuite/gcc.dg/lto/20081201-1_1.c (revision 0)
@@ -0,0 +1,13 @@
+extern int f (void);
+
+extern inline int
+e_inline_baz (void)
+{
+ return 2 + f ();
+}
+
+int
+foo (void)
+{
+ return e_inline_baz ();
+}
Index: gcc/gcc/testsuite/gcc.dg/lto/20081201-2_0.c
===================================================================
--- gcc/gcc/testsuite/gcc.dg/lto/20081201-2_0.c (revision 0)
+++ gcc/gcc/testsuite/gcc.dg/lto/20081201-2_0.c (revision 0)
@@ -0,0 +1,16 @@
+/* { dg-options "{-O3 -fwhopr}" } */
+
+/* Test that cross-TU inlining works. */
+
+extern void abort ();
+extern void exit (int);
+extern void *foo (void);
+
+int
+main ()
+{
+ if (foo () != __builtin_return_address (0))
+ abort ();
+
+ exit (0);
+}
Index: gcc/gcc/testsuite/gcc.dg/lto/20081201-2_1.c
===================================================================
--- gcc/gcc/testsuite/gcc.dg/lto/20081201-2_1.c (revision 0)
+++ gcc/gcc/testsuite/gcc.dg/lto/20081201-2_1.c (revision 0)
@@ -0,0 +1,5 @@
+void *
+foo (void)
+{
+ return __builtin_return_address (0);
+}
Index: gcc/gcc/testsuite/gcc.dg/lto/20081201-1_2.c
===================================================================
--- gcc/gcc/testsuite/gcc.dg/lto/20081201-1_2.c (revision 0)
+++ gcc/gcc/testsuite/gcc.dg/lto/20081201-1_2.c (revision 0)
@@ -0,0 +1,7 @@
+int
+e_inline_baz (void)
+{
+ return 0;
+}
+
+
Index: gcc/gcc/lto-cgraph.c
===================================================================
--- gcc/gcc/lto-cgraph.c (revision 142345)
+++ gcc/gcc/lto-cgraph.c (working copy)
@@ -157,16 +157,35 @@ const char * LTO_cgraph_tag_names[LTO_cg
{"", "avail", "overwrite", "unavail", "edge"};
#endif
+/* Redirect inlined NODE to its master clone if it is not in SET.
+ Return NODE itself if it is in SET or it is not inlined. */
+
+static struct cgraph_node *
+maybe_redirect_inlined_node (struct cgraph_node *node, cgraph_node_set set)
+{
+ struct cgraph_node *master_clone;
+
+ if (!cgraph_node_in_set_p (node, set) && node->global.inlined_to != NULL)
+ {
+ master_clone = node->master_clone;
+ gcc_assert (master_clone && master_clone != node);
+ return master_clone;
+ }
+ else
+ return node;
+}
/* Output the cgraph EDGE to OB using ENCODER. */
static void
output_edge (struct lto_simple_output_block *ob,
- struct cgraph_edge *edge, lto_cgraph_encoder_t encoder)
+ struct cgraph_edge *edge, lto_cgraph_encoder_t encoder,
+ cgraph_node_set set)
{
unsigned int uid;
intptr_t ref;
unsigned HOST_WIDEST_INT flags = 0;
+ struct cgraph_node *callee;
lto_output_uleb128_stream (ob->main_stream, LTO_cgraph_edge);
LTO_DEBUG_INDENT (LTO_cgraph_edge);
@@ -177,15 +196,23 @@ output_edge (struct lto_simple_output_bl
lto_output_sleb128_stream (ob->main_stream, ref);
LTO_DEBUG_TOKEN ("callee");
- ref = lto_cgraph_encoder_lookup (encoder, edge->callee);
+ callee = maybe_redirect_inlined_node (edge->callee, set);
+ ref = lto_cgraph_encoder_lookup (encoder, callee);
gcc_assert (ref != LCC_NOT_FOUND);
lto_output_sleb128_stream (ob->main_stream, ref);
LTO_DEBUG_TOKEN ("stmt");
uid = flag_wpa ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt);
lto_output_uleb128_stream (ob->main_stream, uid);
+
+ /* If we have redirected an inlined callee outside SET to its master
+ clone, mark edge as not inlined. */
LTO_DEBUG_TOKEN ("inline_failed");
- lto_output_uleb128_stream (ob->main_stream, edge->inline_failed);
+ if (callee != edge->callee)
+ lto_output_uleb128_stream (ob->main_stream, CIF_UNSPECIFIED);
+ else
+ lto_output_uleb128_stream (ob->main_stream, edge->inline_failed);
+
LTO_DEBUG_TOKEN ("count");
lto_output_uleb128_stream (ob->main_stream, edge->count);
LTO_DEBUG_TOKEN ("frequency");
@@ -392,7 +419,7 @@ output_cgraph_verify_node (cgraph_node_s
static void
output_cgraph (cgraph_node_set set)
{
- struct cgraph_node *node, *master_clone;
+ struct cgraph_node *node, *callee, *master_clone;
struct lto_simple_output_block *ob
= lto_create_simple_output_block (LTO_section_cgraph);
cgraph_node_set_iterator csi;
@@ -419,12 +446,17 @@ output_cgraph (cgraph_node_set set)
lto_cgraph_encoder_encode (encoder, node);
}
- /* Go over all the nodes again to include callees that are not in SET. */
+ /* Go over all the nodes again to include callees that are not in SET.
+ For inlined callee that are not in the set, redirect the edge to
+ its master clone. */
for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
{
node = csi_node (csi);
for (edge = node->callees; edge; edge = edge->next_callee)
- lto_cgraph_encoder_encode (encoder, edge->callee);
+ {
+ callee = maybe_redirect_inlined_node (edge->callee, set);
+ lto_cgraph_encoder_encode (encoder, callee);
+ }
}
/* Write out the nodes */
@@ -443,7 +475,7 @@ output_cgraph (cgraph_node_set set)
{
node = csi_node (csi);
for (edge = node->callees; edge; edge = edge->next_callee)
- output_edge (ob, edge, encoder);
+ output_edge (ob, edge, encoder, set);
}
lto_output_uleb128_stream (ob->main_stream, 0);
More information about the Gcc-patches
mailing list