From: Jan Hubicka Date: Wed, 18 May 2016 07:12:46 +0000 (+0200) Subject: ipa-inline-transform.c (preserve_function_body_p): Look for first non-thunk clone. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ec6a1e35322a8b9b008c5fef7a8effdbf17b68eb;p=gcc.git ipa-inline-transform.c (preserve_function_body_p): Look for first non-thunk clone. * ipa-inline-transform.c (preserve_function_body_p): Look for first non-thunk clone. (save_function_body): Save into first non-thunk. * lto-cgraph.c (lto_output_edge): When streaming thunk do not look up call stmt id. (lto_output_node): Inline thunks don't need body in every partition. * lto-streamer-in.c: Do not fixup thunk clones. * cgraphclones.c (cgraph_node::create_edge_including_clone): Skip thunks. * tree-inline.c (copy_bb): Be prepared for target node to be new after folding suceeds. From-SVN: r236357 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2f294c89fdf..40d723b2b17 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2016-05-17 Jan Hubicka + + * ipa-inline-transform.c (preserve_function_body_p): Look for + first non-thunk clone. + (save_function_body): Save into first non-thunk. + * lto-cgraph.c (lto_output_edge): When streaming thunk do not look + up call stmt id. + (lto_output_node): Inline thunks don't need body in every + partition. + * lto-streamer-in.c: Do not fixup thunk clones. + * cgraphclones.c (cgraph_node::create_edge_including_clone): Skip + thunks. + * tree-inline.c (copy_bb): Be prepared for target node to be new after + folding suceeds. + 2016-05-17 Kugan Vivekanandarajah PR middle-end/63586 diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c index 97eb927c01b..686c2890021 100644 --- a/gcc/cgraphclones.c +++ b/gcc/cgraphclones.c @@ -771,33 +771,35 @@ cgraph_node::create_edge_including_clones (cgraph_node *callee, node = clones; if (node) while (node != this) - { - cgraph_edge *edge = node->get_edge (old_stmt); - - /* It is possible that clones already contain the edge while - master didn't. Either we promoted indirect call into direct - call in the clone or we are processing clones of unreachable - master where edges has been removed. */ - if (edge) - edge->set_call_stmt (stmt); - else if (! node->get_edge (stmt)) - { - edge = node->create_edge (callee, stmt, count, freq); - edge->inline_failed = reason; - } + /* Thunk clones do not get updated while copying inline function body. */ + if (!node->thunk.thunk_p) + { + cgraph_edge *edge = node->get_edge (old_stmt); + + /* It is possible that clones already contain the edge while + master didn't. Either we promoted indirect call into direct + call in the clone or we are processing clones of unreachable + master where edges has been removed. */ + if (edge) + edge->set_call_stmt (stmt); + else if (! node->get_edge (stmt)) + { + edge = node->create_edge (callee, stmt, count, freq); + edge->inline_failed = reason; + } - if (node->clones) - node = node->clones; - else if (node->next_sibling_clone) - node = node->next_sibling_clone; - else - { - while (node != this && !node->next_sibling_clone) - node = node->clone_of; - if (node != this) - node = node->next_sibling_clone; - } - } + if (node->clones) + node = node->clones; + else if (node->next_sibling_clone) + node = node->next_sibling_clone; + else + { + while (node != this && !node->next_sibling_clone) + node = node->clone_of; + if (node != this) + node = node->next_sibling_clone; + } + } } /* Remove the node from cgraph and all inline clones inlined into it. diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index 1e6e108b9db..90a0d7ebbb7 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -506,6 +506,22 @@ save_inline_function_body (struct cgraph_node *node) /* first_clone will be turned into real function. */ first_clone = node->clones; + + /* Arrange first clone to not be thunk as those do not have bodies. */ + if (first_clone->thunk.thunk_p) + { + while (first_clone->thunk.thunk_p) + first_clone = first_clone->next_sibling_clone; + first_clone->prev_sibling_clone->next_sibling_clone + = first_clone->next_sibling_clone; + if (first_clone->next_sibling_clone) + first_clone->next_sibling_clone->prev_sibling_clone + = first_clone->prev_sibling_clone; + first_clone->next_sibling_clone = node->clones; + first_clone->prev_sibling_clone = NULL; + node->clones->prev_sibling_clone = first_clone; + node->clones = first_clone; + } first_clone->decl = copy_node (node->decl); first_clone->decl->decl_with_vis.symtab_node = first_clone; gcc_assert (first_clone == cgraph_node::get (first_clone->decl)); @@ -514,7 +530,8 @@ save_inline_function_body (struct cgraph_node *node) first_clone. */ if (first_clone->next_sibling_clone) { - for (n = first_clone->next_sibling_clone; n->next_sibling_clone; n = n->next_sibling_clone) + for (n = first_clone->next_sibling_clone; n->next_sibling_clone; + n = n->next_sibling_clone) n->clone_of = first_clone; n->clone_of = first_clone; n->next_sibling_clone = first_clone->clones; @@ -587,9 +604,10 @@ preserve_function_body_p (struct cgraph_node *node) gcc_assert (symtab->global_info_ready); gcc_assert (!node->alias && !node->thunk.thunk_p); - /* Look if there is any clone around. */ - if (node->clones && !node->clones->thunk.thunk_p) - return true; + /* Look if there is any non-thunk clone around. */ + for (node = node->clones; node; node = node->next_sibling_clone) + if (!node->thunk.thunk_p) + return true; return false; } diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 11d440b7b74..5cef2bae159 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -259,7 +259,7 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge, streamer_write_gcov_count_stream (ob->main_stream, edge->count); bp = bitpack_create (ob->main_stream); - uid = (!gimple_has_body_p (edge->caller->decl) + uid = (!gimple_has_body_p (edge->caller->decl) || edge->caller->thunk.thunk_p ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt) + 1); bp_pack_enum (&bp, cgraph_inline_failed_t, CIF_N_REASONS, edge->inline_failed); @@ -398,7 +398,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node); - if (node->analyzed && (!boundary_p || node->alias || node->thunk.thunk_p)) + if (node->analyzed && (!boundary_p || node->alias + || (node->thunk.thunk_p && !node->global.inlined_to))) tag = LTO_symtab_analyzed_node; else tag = LTO_symtab_unavail_node; diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 1970d45ee86..3a353cd0437 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -953,7 +953,8 @@ fixup_call_stmt_edges (struct cgraph_node *orig, gimple **stmts) if (orig->clones) for (node = orig->clones; node != orig;) { - fixup_call_stmt_edges_1 (node, stmts, fn); + if (!node->thunk.thunk_p) + fixup_call_stmt_edges_1 (node, stmts, fn); if (node->clones) node = node->clones; else if (node->next_sibling_clone) diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 954dac30487..4eb8d200411 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -2063,7 +2063,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, && id->dst_node->definition && (fn = gimple_call_fndecl (stmt)) != NULL) { - struct cgraph_node *dest = cgraph_node::get (fn); + struct cgraph_node *dest = cgraph_node::get_create (fn); /* We have missing edge in the callgraph. This can happen when previous inlining turned an indirect call into a