aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/cgraphclones.c54
-rw-r--r--gcc/ipa-inline-transform.c26
-rw-r--r--gcc/lto-cgraph.c5
-rw-r--r--gcc/lto-streamer-in.c3
-rw-r--r--gcc/tree-inline.c2
6 files changed, 71 insertions, 34 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2f294c8..40d723b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+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
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 97eb927..686c2890 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 1e6e108..90a0d7e 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 11d440b..5cef2ba 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 1970d45..3a353cd 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 954dac3..4eb8d20 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