summaryrefslogtreecommitdiff
path: root/gcc/cgraphclones.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cgraphclones.c')
-rw-r--r--gcc/cgraphclones.c55
1 files changed, 45 insertions, 10 deletions
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 04cb990cc86..54b97b91c78 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -147,6 +147,7 @@ cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
/* Clone flags that depend on call_stmt availability manually. */
new_edge->can_throw_external = e->can_throw_external;
new_edge->call_stmt_cannot_inline_p = e->call_stmt_cannot_inline_p;
+ new_edge->speculative = e->speculative;
if (update_original)
{
e->count -= new_edge->count;
@@ -251,7 +252,7 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq,
return new_node;
}
-/* Create a new name for clone of DECL, add SUFFIX. Returns an identifier. */
+/* Return a new assembler name for a clone of DECL with SUFFIX. */
static GTY(()) unsigned int clone_fn_id_num;
@@ -292,10 +293,11 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
tree old_decl = old_node->symbol.decl;
struct cgraph_node *new_node = NULL;
tree new_decl;
- size_t i;
+ size_t len, i;
struct ipa_replace_map *map;
+ char *name;
- if (!flag_wpa)
+ if (!in_lto_p)
gcc_checking_assert (tree_versionable_function_p (old_decl));
gcc_assert (old_node->local.can_change_signature || !args_to_skip);
@@ -317,8 +319,13 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
sometimes storing only clone decl instead of original. */
/* Generate a new name for the new version. */
- DECL_NAME (new_decl) = clone_function_name (old_decl, suffix);
- SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
+ len = IDENTIFIER_LENGTH (DECL_NAME (old_decl));
+ name = XALLOCAVEC (char, len + strlen (suffix) + 2);
+ memcpy (name, IDENTIFIER_POINTER (DECL_NAME (old_decl)), len);
+ strcpy (name + len + 1, suffix);
+ name[len] = '.';
+ DECL_NAME (new_decl) = get_identifier (name);
+ SET_DECL_ASSEMBLER_NAME (new_decl, clone_function_name (old_decl, suffix));
SET_DECL_RTL (new_decl, NULL);
new_node = cgraph_clone_node (old_node, new_decl, old_node->count,
@@ -474,17 +481,21 @@ cgraph_find_replacement_node (struct cgraph_node *node)
}
/* Like cgraph_set_call_stmt but walk the clone tree and update all
- clones sharing the same function body. */
+ clones sharing the same function body.
+ When WHOLE_SPECULATIVE_EDGES is true, all three components of
+ speculative edge gets updated. Otherwise we update only direct
+ call. */
void
cgraph_set_call_stmt_including_clones (struct cgraph_node *orig,
- gimple old_stmt, gimple new_stmt)
+ gimple old_stmt, gimple new_stmt,
+ bool update_speculative)
{
struct cgraph_node *node;
struct cgraph_edge *edge = cgraph_edge (orig, old_stmt);
if (edge)
- cgraph_set_call_stmt (edge, new_stmt);
+ cgraph_set_call_stmt (edge, new_stmt, update_speculative);
node = orig->clones;
if (node)
@@ -492,7 +503,23 @@ cgraph_set_call_stmt_including_clones (struct cgraph_node *orig,
{
struct cgraph_edge *edge = cgraph_edge (node, old_stmt);
if (edge)
- cgraph_set_call_stmt (edge, new_stmt);
+ {
+ cgraph_set_call_stmt (edge, new_stmt, update_speculative);
+ /* If UPDATE_SPECULATIVE is false, it means that we are turning
+ speculative call into a real code sequence. Update the
+ callgraph edges. */
+ if (edge->speculative && !update_speculative)
+ {
+ struct cgraph_edge *direct, *indirect;
+ struct ipa_ref *ref;
+
+ gcc_assert (!edge->indirect_unknown_callee);
+ cgraph_speculative_call_info (edge, direct, indirect, ref);
+ direct->speculative = false;
+ indirect->speculative = false;
+ ref->speculative = false;
+ }
+ }
if (node->clones)
node = node->clones;
else if (node->next_sibling_clone)
@@ -811,6 +838,7 @@ cgraph_materialize_all_clones (void)
{
struct cgraph_node *node;
bool stabilized = false;
+
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "Materializing clones\n");
@@ -829,6 +857,8 @@ cgraph_materialize_all_clones (void)
if (node->clone_of && node->symbol.decl != node->clone_of->symbol.decl
&& !gimple_has_body_p (node->symbol.decl))
{
+ if (!node->clone_of->clone_of)
+ cgraph_get_body (node->clone_of);
if (gimple_has_body_p (node->clone_of->symbol.decl))
{
if (cgraph_dump_file)
@@ -874,7 +904,12 @@ cgraph_materialize_all_clones (void)
}
FOR_EACH_FUNCTION (node)
if (!node->symbol.analyzed && node->callees)
- cgraph_node_remove_callees (node);
+ {
+ cgraph_node_remove_callees (node);
+ ipa_remove_all_references (&node->symbol.ref_list);
+ }
+ else
+ ipa_clear_stmts_in_references ((symtab_node)node);
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
#ifdef ENABLE_CHECKING