@@ -2596,4 +2596,47 @@ verify_cgraph (void)
FOR_EACH_FUNCTION (node)
verify_cgraph_node (node);
}
+
+/* Create external decl node for DECL.
+ The difference i nbetween cgraph_get_create_node and
+ cgraph_get_create_real_symbol_node is that cgraph_get_create_node
+ may return inline clone, while cgraph_get_create_real_symbol_node
+ will create a new node in this case.
+ FIXME: This function should be removed once clones are put out of decl
+ hash. */
+
+struct cgraph_node *
+cgraph_get_create_real_symbol_node (tree decl)
+{
+ struct cgraph_node *first_clone = cgraph_get_node (decl);
+ struct cgraph_node *node;
+ /* create symbol table node. even if inline clone exists, we can not take
+ it as a target of non-inlined call. */
+ node = cgraph_get_node (decl);
+ if (node && !node->global.inlined_to)
+ return node;
+
+ node = cgraph_create_node (decl);
+
+ /* ok, we previously inlined the function, then removed the offline copy and
+ now we want it back for external call. this can happen when devirtualizing
+ while inlining function called once that happens after extern inlined and
+ virtuals are already removed. in this case introduce the external node
+ and make it available for call. */
+ if (first_clone)
+ {
+ first_clone->clone_of = node;
+ node->clones = first_clone;
+ symtab_prevail_in_asm_name_hash ((symtab_node) node);
+ symtab_insert_node_to_hashtable ((symtab_node) node);
+ if (dump_file)
+ fprintf (dump_file, "Introduced new external node "
+ "(%s/%i) and turned into root of the clone tree.\n",
+ xstrdup (cgraph_node_name (node)), node->uid);
+ }
+ else if (dump_file)
+ fprintf (dump_file, "Introduced new external node "
+ "(%s/%i).\n", xstrdup (cgraph_node_name (node)), node->uid);
+ return node;
+}
#include "gt-cgraph.h"
@@ -575,6 +575,7 @@ struct cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void);
struct cgraph_node * cgraph_create_node (tree);
struct cgraph_node * cgraph_create_empty_node (void);
struct cgraph_node * cgraph_get_create_node (tree);
+struct cgraph_node * cgraph_get_create_real_symbol_node (tree);
struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree);
struct cgraph_node * cgraph_add_thunk (struct cgraph_node *, tree, tree, bool, HOST_WIDE_INT,
HOST_WIDE_INT, tree, tree);
@@ -73,7 +73,7 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
decl = get_base_var (*tp);
if (TREE_CODE (decl) == FUNCTION_DECL)
{
- struct cgraph_node *node = cgraph_get_create_node (decl);
+ struct cgraph_node *node = cgraph_get_create_real_symbol_node (decl);
if (!ctx->only_vars)
cgraph_mark_address_taken_node (node);
ipa_record_reference ((symtab_node)ctx->varpool_node,
@@ -143,7 +143,7 @@ record_eh_tables (struct cgraph_node *node, struct function *fun)
{
struct cgraph_node *per_node;
- per_node = cgraph_get_create_node (DECL_FUNCTION_PERSONALITY (node->symbol.decl));
+ per_node = cgraph_get_create_real_symbol_node (DECL_FUNCTION_PERSONALITY (node->symbol.decl));
ipa_record_reference ((symtab_node)node, (symtab_node)per_node, IPA_REF_ADDR, NULL);
cgraph_mark_address_taken_node (per_node);
}
@@ -223,7 +223,7 @@ mark_address (gimple stmt, tree addr, void *data)
addr = get_base_address (addr);
if (TREE_CODE (addr) == FUNCTION_DECL)
{
- struct cgraph_node *node = cgraph_get_create_node (addr);
+ struct cgraph_node *node = cgraph_get_create_real_symbol_node (addr);
cgraph_mark_address_taken_node (node);
ipa_record_reference ((symtab_node)data,
(symtab_node)node,
@@ -252,7 +252,7 @@ mark_load (gimple stmt, tree t, void *data)
{
/* ??? This can happen on platforms with descriptors when these are
directly manipulated in the code. Pretend that it's an address. */
- struct cgraph_node *node = cgraph_get_create_node (t);
+ struct cgraph_node *node = cgraph_get_create_real_symbol_node (t);
cgraph_mark_address_taken_node (node);
ipa_record_reference ((symtab_node)data,
(symtab_node)node,
@@ -330,7 +330,7 @@ build_cgraph_edges (void)
{
tree fn = gimple_omp_parallel_child_fn (stmt);
ipa_record_reference ((symtab_node)node,
- (symtab_node)cgraph_get_create_node (fn),
+ (symtab_node)cgraph_get_create_real_symbol_node (fn),
IPA_REF_ADDR, stmt);
}
if (gimple_code (stmt) == GIMPLE_OMP_TASK)
@@ -338,12 +338,12 @@ build_cgraph_edges (void)
tree fn = gimple_omp_task_child_fn (stmt);
if (fn)
ipa_record_reference ((symtab_node)node,
- (symtab_node) cgraph_get_create_node (fn),
+ (symtab_node) cgraph_get_create_real_symbol_node (fn),
IPA_REF_ADDR, stmt);
fn = gimple_omp_task_copy_fn (stmt);
if (fn)
ipa_record_reference ((symtab_node)node,
- (symtab_node)cgraph_get_create_node (fn),
+ (symtab_node)cgraph_get_create_real_symbol_node (fn),
IPA_REF_ADDR, stmt);
}
}
@@ -178,7 +178,7 @@ canonicalize_constructor_val (tree cval, tree from_decl)
/* Make sure we create a cgraph node for functions we'll reference.
They can be non-existent if the reference comes from an entry
of an external vtable for example. */
- cgraph_get_create_node (base);
+ cgraph_get_create_real_symbol_node (base);
}
/* Fixup types in global initializers. */
if (TREE_TYPE (TREE_TYPE (cval)) != TREE_TYPE (TREE_OPERAND (cval, 0)))
@@ -2126,7 +2126,6 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
we may create the first reference to the object in the unit. */
if (!callee || callee->global.inlined_to)
{
- struct cgraph_node *first_clone = callee;
/* We are better to ensure we can refer to it.
In the case of static functions we are out of luck, since we already
@@ -2142,31 +2141,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
xstrdup (cgraph_node_name (ie->callee)), ie->callee->uid);
return NULL;
}
-
- /* Create symbol table node. Even if inline clone exists, we can not take
- it as a target of non-inlined call. */
- callee = cgraph_create_node (target);
-
- /* OK, we previously inlined the function, then removed the offline copy and
- now we want it back for external call. This can happen when devirtualizing
- while inlining function called once that happens after extern inlined and
- virtuals are already removed. In this case introduce the external node
- and make it available for call. */
- if (first_clone)
- {
- first_clone->clone_of = callee;
- callee->clones = first_clone;
- symtab_prevail_in_asm_name_hash ((symtab_node)callee);
- symtab_insert_node_to_hashtable ((symtab_node)callee);
- if (dump_file)
- fprintf (dump_file, "ipa-prop: Introduced new external node "
- "(%s/%i) and turned into root of the clone tree.\n",
- xstrdup (cgraph_node_name (callee)), callee->uid);
- }
- else if (dump_file)
- fprintf (dump_file, "ipa-prop: Introduced new external node "
- "(%s/%i).\n",
- xstrdup (cgraph_node_name (callee)), callee->uid);
+ callee = cgraph_get_create_real_symbol_node (target);
}
ipa_check_create_node_params ();