http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56265
--- Comment #4 from Jan Hubicka <hubicka at ucw dot cz> 2013-02-12 17:25:31 UTC
---
Hi,
this patch should make ipa_make_edge_direct_to_target to behave properly when
new symbol
needs to be inserted into the symbol table. We already have
canonicalize_constructor_val
to do the right thing (i.e. check we can refer to the symbol), but we need to
update
symbol table in that case, too.
I also took the chance to add more detailed debug output.
I will give this patch more testing on Mozilla/Qt tomorrow and produce some
statistic.
here is some chance of provoking some latent bug in
canonicalize_constructor_val
since we get bit more devirtualizations tham previously. It however ought not
be
much of issue since all of them can be produced on old tree by adding another
function allowing local devirtualization and inserting the symbol into symtab.
Honza
Index: ipa-prop.c
===================================================================
--- ipa-prop.c (revision 195956)
+++ ipa-prop.c (working copy)
@@ -2100,10 +2100,65 @@ ipa_make_edge_direct_to_target (struct c
if (TREE_CODE (target) == ADDR_EXPR)
target = TREE_OPERAND (target, 0);
if (TREE_CODE (target) != FUNCTION_DECL)
- return NULL;
+ {
+ target = canonicalize_constructor_val (target, NULL);
+ if (!target || TREE_CODE (target) != FUNCTION_DECL)
+ {
+ if (dump_file)
+ fprintf (dump_file, "ipa-prop: Discovered direct call to non-function"
+ " in (%s/%i).\n",
+ cgraph_node_name (ie->caller), ie->caller->uid);
+ return NULL;
+ }
+ }
callee = cgraph_get_node (target);
- if (!callee)
- return NULL;
+
+ /* Because may-edges are not explicitely represented and vtable may be
external,
+ 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
+ removed its body. In the case of public functions we may or may
+ not introduce the reference. */
+ if (!canonicalize_constructor_val (target, NULL)
+ || !TREE_PUBLIC (target))
+ {
+ if (dump_file)
+ fprintf (dump_file, "ipa-prop: Discovered call to a known target "
+ "(%s/%i -> %s/%i) but can not refer to it. Giving up.\n",
+ xstrdup (cgraph_node_name (ie->caller)), ie->caller->uid,
+ 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);
+ }
ipa_check_create_node_params ();
/* We can not make edges to inline clones. It is bug that someone removed