{
tree decl;
+ cgraph_node *new_direct_callee = NULL;
+ if ((e->indirect_unknown_callee || e->speculative)
+ && (decl = gimple_call_fndecl (new_stmt)))
+ {
+ /* Constant propagation and especially inlining can turn an indirect call
+ into a direct one. */
+ new_direct_callee = cgraph_node::get (decl);
+ gcc_checking_assert (new_direct_callee);
+ }
+
/* Speculative edges has three component, update all of them
when asked to. */
- if (update_speculative && e->speculative)
+ if (update_speculative && e->speculative
+ /* If we are about to resolve the speculation by calling make_direct
+ below, do not bother going over all the speculative edges now. */
+ && !new_direct_callee)
{
cgraph_edge *direct, *indirect, *next;
ipa_ref *ref;
return e_indirect ? indirect : direct;
}
+ if (new_direct_callee)
+ e = make_direct (e, new_direct_callee);
+
/* Only direct speculative edges go to call_site_hash. */
if (e->caller->call_site_hash
&& (!e->speculative || !e->indirect_unknown_callee)
(e->call_stmt, cgraph_edge_hasher::hash (e->call_stmt));
e->call_stmt = new_stmt;
- if (e->indirect_unknown_callee
- && (decl = gimple_call_fndecl (new_stmt)))
- {
- /* Constant propagation (and possibly also inlining?) can turn an
- indirect call into a direct one. */
- cgraph_node *new_callee = cgraph_node::get (decl);
-
- gcc_checking_assert (new_callee);
- e = make_direct (e, new_callee);
- }
function *fun = DECL_STRUCT_FUNCTION (e->caller->decl);
e->can_throw_external = stmt_can_throw_external (fun, new_stmt);
return NULL;
}
-/* Make an indirect edge with an unknown callee an ordinary edge leading to
- CALLEE. Speculations can be resolved in the process and EDGE can be removed
- and deallocated. Return the edge that now represents the call. */
+/* Make an indirect or speculative EDGE with an unknown callee an ordinary edge
+ leading to CALLEE. Speculations can be resolved in the process and EDGE can
+ be removed and deallocated. Return the edge that now represents the
+ call. */
cgraph_edge *
cgraph_edge::make_direct (cgraph_edge *edge, cgraph_node *callee)
{
- gcc_assert (edge->indirect_unknown_callee);
+ gcc_assert (edge->indirect_unknown_callee || edge->speculative);
/* If we are redirecting speculative call, make it non-speculative. */
if (edge->speculative)