Commit ec6a1e35 by Jan Hubicka Committed by Jan Hubicka

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
parent df8b0a11
2016-05-17 Jan Hubicka <hubicka@ucw.cz>
* 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 <kuganv@linaro.org>
PR middle-end/63586
......
......@@ -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.
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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)
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment