https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123226
Jan Hubicka <hubicka at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |hubicka at gcc dot gnu.org
--- Comment #5 from Jan Hubicka <hubicka at gcc dot gnu.org> ---
Resolving of this calles happens in:
0 cgraph_edge::resolve_speculation (edge=0x7ffff72c4618,
callee_decl=0x7ffff72af300) at ../../gcc/cgraph.cc:1539
#1 0x00000000010d269d in cgraph_update_edges_for_call_stmt_node
(node=0x7ffff72c6110, old_stmt=0x7ffff7303da8, old_call=0x0,
new_stmt=0x7ffff7303da8)
at ../../gcc/cgraph.cc:2017
#2 0x00000000010d2965 in cgraph_update_edges_for_call_stmt
(old_stmt=0x7ffff7303da8, old_decl=0x0, new_stmt=0x7ffff7303da8) at
../../gcc/cgraph.cc:2091
#3 0x000000000193e7fd in fold_marked_statements (first=0,
statements=0x4911d60) at ../../gcc/tree-inline.cc:5575
#4 0x0000000001942133 in tree_function_versioning (old_decl=0x7ffff729f000,
new_decl=0x7ffff72b6c00, tree_map=0x7ffff72c3578,
param_adjustments=0x7ffff72c14e0,
update_clones=true, blocks_to_copy=0x0, new_entry=0x0) at
../../gcc/tree-inline.cc:6555
#5 0x00000000010ef6b1 in cgraph_node::materialize_clone (this=0x7ffff72c6110)
at ../../gcc/cgraphclones.cc:1249
#6 0x00000000016e2411 in execute_all_ipa_transforms (do_not_collect=false) at
../../gcc/passes.cc:2373
#7 0x00000000010e84f6 in cgraph_node::expand (this=0x7ffff72b9000) at
../../gcc/cgraphunit.cc:1864
#8 0x00000000010e8d6e in expand_all_functions () at
../../gcc/cgraphunit.cc:2054
#9 0x00000000010e98ae in symbol_table::compile (this=0x7ffff7406000) at
../../gcc/cgraphunit.cc:2432
#10 0x0000000000fa3b0d in lto_main () at ../../gcc/lto/lto.cc:694
#11 0x000000000186daa6 in compile_file () at ../../gcc/toplev.cc:455
#12 0x0000000001871027 in do_compile () at ../../gcc/toplev.cc:2225
#13 0x000000000187148e in toplev::main (this=0x7fffffffda5a, argc=29,
argv=0x4839c10) at ../../gcc/toplev.cc:2390
#14 0x00000000036f9a7e in main (argc=26, argv=0x7fffffffdb88) at
../../gcc/main.cc:39
stmt originally is
# .MEM = VDEF <.MEM>
D.5907 = OBJ_TYPE_REF(_2;(struct generic_parser_base)&MEM <struct n> [(void
*)&j + 16B]->3B) (&MEM <struct n> [(void *)&j + 16B]);
and folding turns it to
# .MEM = VDEF <.MEM>
D.5907 = _ZThn8_N4llvm14PassNameParserD0Ev (&MEM <struct n> [(void *)&j +
16B]);
We have
ZN4llvm2cl19generic_parser_base10findOptionENS_9StringRefE.constprop.0/69
(findOption.constprop)
Type: function definition analyzed
Visibility: artificial
References:
_ZNK4llvm2cl19generic_parser_base14getOptionWidthERKNS0_6OptionE/2 (addr)
(speculative) _ZThn8_N4llvm14PassNameParserD0Ev/42 (addr) (speculative) j/14
(addr)
Referring:
Read from file: a-CommandLine.o
Function findOption.constprop/69 is inline copy in _GLOBAL__sub_I_j/16
Clone of _ZN4llvm2cl19generic_parser_base10findOptionENS_9StringRefE/1
Availability: local
Unit id: 1
Function flags: count:6950038029 (estimated locally) body local
only_called_at_startup executed_once
Called by: _ZN4llvm14PassNameParser1bEPKi.constprop.0/68 (inlined)
(6950038029 (estimated locally),6.47 per call) (can throw external)
Calls: _ZN4llvmeqENS_9StringRefES0_/4 (701953785967 (estimated
locally),653.75 per call) (can throw external)
_ZNK4llvm2cl19generic_parser_base14getOptionWidthERKNS0_6OptionE.constprop.0/70
(speculative) (inlined) (280781514649 (estimated locally),261.50 per call) (can
throw external) _ZThn8_N4llvm14PassNameParserD0Ev/74 (speculative) (inlined)
(168468908786 (estimated locally),156.90 per call) (can throw external)
indirect polymorphic callsite, vptr_changed, calling param -1, offset
64otr_token 3, otr_type struct generic_parser_base, context Outer type
(dynamic):struct generic_parser_base (or a derived type) offset 0, flags 0, num
speculative call targets: 2
So the edge is speculate twice and the speculation to
_ZThn8_N4llvm14PassNameParserD0Ev is inlined
Now we do
/* If call was devirtualized during cloning, mark edge
as resolved. */
if (e->speculative)
{
if (new_stmt && is_gimple_call (new_stmt))
{
tree decl = gimple_call_fndecl (new_stmt);
if (decl)
e = cgraph_edge::resolve_speculation (e, decl);
}
else
e = cgraph_edge::resolve_speculation (e, NULL);
}
this resolves one edge but is supposed to do all of them as documented in
resolve_speculation.
This fixes it
diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index 91ff2775de1..571b3cbf3ba 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -2014,10 +2014,10 @@ cgraph_update_edges_for_call_stmt_node (cgraph_node
*node,
{
tree decl = gimple_call_fndecl (new_stmt);
if (decl)
- e = cgraph_edge::resolve_speculation (e, decl);
+ e = cgraph_edge::make_direct (e, cgraph_node::get_create
(decl));
}
else
- e = cgraph_edge::resolve_speculation (e, NULL);
+ gcc_unreachable ();
}
/* Keep calls marked as dead dead. */
if (new_stmt && is_gimple_call (new_stmt) && e->callee
The problem really traces back to the original multi-target speculation support
rf1ba88b1b20cb579b3b7ce6ce65470205742be7e
I will test the patch above
However I think there is another problem. In case we redirect edge to a clone
of original function, both make_direct and resolve_speculation will interpret
it as a failed speculation since callees won't match
cgraph_edge *
cgraph_edge::resolve_speculation (cgraph_edge *edge, tree callee_decl)
{
cgraph_edge *e2;
ipa_ref *ref;
gcc_assert (edge->speculative && (!callee_decl || edge->callee));
if (!edge->callee)
e2 = edge->first_speculative_call_target ();
else
e2 = edge;
ref = e2->speculative_call_target_ref ();
edge = edge->speculative_call_indirect_edge ();
symtab_node *callee;
if (!callee_decl
|| !(callee = symtab_node::get (callee_decl))
|| !ref->referred->semantically_equivalent_p (callee))
{
if (dump_file)
{
if (callee_decl)
{
fprintf (dump_file, "Speculative indirect call %s => %s has "
"turned out to have contradicting known target ",
edge->caller->dump_name (),
e2->callee->dump_name ());
...
I will try to craft a testcase.