Commit 231b4916 by Jan Hubicka Committed by Jan Hubicka

ipa-cp.c (ipa_get_indirect_edge_target_1): Handle speculation.


	* ipa-cp.c (ipa_get_indirect_edge_target_1): Handle speculation.
	(ipa_get_indirect_edge_target): Add SPECULATIVE argument.
	(devirtualization_time_bonus): Use it.
	(ipcp_discover_new_direct_edges): Likewise.
	* ipa-inline-analysis.c (estimate_edge_devirt_benefit): Update.
	* ipa-prop.h (ipa_get_indirect_edge_target): Update prototype.

From-SVN: r217675
parent a19faae3
2014-11-17 Jan Hubicka <hubicka@ucw.cz> 2014-11-17 Jan Hubicka <hubicka@ucw.cz>
* ipa-cp.c (ipa_get_indirect_edge_target_1): Handle speculation.
(ipa_get_indirect_edge_target): Add SPECULATIVE argument.
(devirtualization_time_bonus): Use it.
(ipcp_discover_new_direct_edges): Likewise.
* ipa-inline-analysis.c (estimate_edge_devirt_benefit): Update.
* ipa-prop.h (ipa_get_indirect_edge_target): Update prototype.
2014-11-17 Jan Hubicka <hubicka@ucw.cz>
* tree.c (free_lang_data_in_decl): Set DECL_FUNCTION_SPECIFIC_OPTIMIZATION * tree.c (free_lang_data_in_decl): Set DECL_FUNCTION_SPECIFIC_OPTIMIZATION
to optimization_default_node. to optimization_default_node.
...@@ -1730,13 +1730,16 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, ...@@ -1730,13 +1730,16 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
vec<tree> known_csts, vec<tree> known_csts,
vec<ipa_polymorphic_call_context> known_contexts, vec<ipa_polymorphic_call_context> known_contexts,
vec<ipa_agg_jump_function_p> known_aggs, vec<ipa_agg_jump_function_p> known_aggs,
struct ipa_agg_replacement_value *agg_reps) struct ipa_agg_replacement_value *agg_reps,
bool *speculative)
{ {
int param_index = ie->indirect_info->param_index; int param_index = ie->indirect_info->param_index;
HOST_WIDE_INT anc_offset; HOST_WIDE_INT anc_offset;
tree t; tree t;
tree target = NULL; tree target = NULL;
*speculative = false;
if (param_index == -1 if (param_index == -1
|| known_csts.length () <= (unsigned int) param_index) || known_csts.length () <= (unsigned int) param_index)
return NULL_TREE; return NULL_TREE;
...@@ -1792,8 +1795,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, ...@@ -1792,8 +1795,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
t = NULL; t = NULL;
/* Try to work out value of virtual table pointer value in replacemnets. */ /* Try to work out value of virtual table pointer value in replacemnets. */
if (!t && agg_reps && !ie->indirect_info->by_ref if (!t && agg_reps && !ie->indirect_info->by_ref)
&& !ie->indirect_info->vptr_changed)
{ {
while (agg_reps) while (agg_reps)
{ {
...@@ -1811,8 +1813,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, ...@@ -1811,8 +1813,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
/* Try to work out value of virtual table pointer value in known /* Try to work out value of virtual table pointer value in known
aggregate values. */ aggregate values. */
if (!t && known_aggs.length () > (unsigned int) param_index if (!t && known_aggs.length () > (unsigned int) param_index
&& !ie->indirect_info->by_ref && !ie->indirect_info->by_ref)
&& !ie->indirect_info->vptr_changed)
{ {
struct ipa_agg_jump_function *agg; struct ipa_agg_jump_function *agg;
agg = known_aggs[param_index]; agg = known_aggs[param_index];
...@@ -1836,7 +1837,9 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, ...@@ -1836,7 +1837,9 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
|| !possible_polymorphic_call_target_p || !possible_polymorphic_call_target_p
(ie, cgraph_node::get (target))) (ie, cgraph_node::get (target)))
target = ipa_impossible_devirt_target (ie, target); target = ipa_impossible_devirt_target (ie, target);
return target; *speculative = ie->indirect_info->vptr_changed;
if (!*speculative)
return target;
} }
} }
} }
...@@ -1877,11 +1880,32 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, ...@@ -1877,11 +1880,32 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
ie->indirect_info->otr_token, ie->indirect_info->otr_token,
context, &final); context, &final);
if (!final || targets.length () > 1) if (!final || targets.length () > 1)
return NULL_TREE; {
if (targets.length () == 1) struct cgraph_node *node;
target = targets[0]->decl; if (*speculative)
return target;
if (!flag_devirtualize_speculatively || ie->speculative
|| !ie->maybe_hot_p ())
return NULL;
node = try_speculative_devirtualization (ie->indirect_info->otr_type,
ie->indirect_info->otr_token,
context);
if (node)
{
*speculative = true;
target = node->decl;
}
else
return NULL;
}
else else
target = ipa_impossible_devirt_target (ie, NULL_TREE); {
*speculative = false;
if (targets.length () == 1)
target = targets[0]->decl;
else
target = ipa_impossible_devirt_target (ie, NULL_TREE);
}
if (target && !possible_polymorphic_call_target_p (ie, if (target && !possible_polymorphic_call_target_p (ie,
cgraph_node::get (target))) cgraph_node::get (target)))
...@@ -1899,10 +1923,11 @@ tree ...@@ -1899,10 +1923,11 @@ tree
ipa_get_indirect_edge_target (struct cgraph_edge *ie, ipa_get_indirect_edge_target (struct cgraph_edge *ie,
vec<tree> known_csts, vec<tree> known_csts,
vec<ipa_polymorphic_call_context> known_contexts, vec<ipa_polymorphic_call_context> known_contexts,
vec<ipa_agg_jump_function_p> known_aggs) vec<ipa_agg_jump_function_p> known_aggs,
bool *speculative)
{ {
return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts, return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
known_aggs, NULL); known_aggs, NULL, speculative);
} }
/* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
...@@ -1923,9 +1948,10 @@ devirtualization_time_bonus (struct cgraph_node *node, ...@@ -1923,9 +1948,10 @@ devirtualization_time_bonus (struct cgraph_node *node,
struct inline_summary *isummary; struct inline_summary *isummary;
enum availability avail; enum availability avail;
tree target; tree target;
bool speculative;
target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts, target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
known_aggs); known_aggs, &speculative);
if (!target) if (!target)
continue; continue;
...@@ -1944,12 +1970,12 @@ devirtualization_time_bonus (struct cgraph_node *node, ...@@ -1944,12 +1970,12 @@ devirtualization_time_bonus (struct cgraph_node *node,
/* FIXME: The values below need re-considering and perhaps also /* FIXME: The values below need re-considering and perhaps also
integrating into the cost metrics, at lest in some very basic way. */ integrating into the cost metrics, at lest in some very basic way. */
if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4) if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
res += 31; res += 31 / ((int)speculative + 1);
else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2) else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
res += 15; res += 15 / ((int)speculative + 1);
else if (isummary->size <= MAX_INLINE_INSNS_AUTO else if (isummary->size <= MAX_INLINE_INSNS_AUTO
|| DECL_DECLARED_INLINE_P (callee->decl)) || DECL_DECLARED_INLINE_P (callee->decl))
res += 7; res += 7 / ((int)speculative + 1);
} }
return res; return res;
...@@ -2645,16 +2671,18 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node, ...@@ -2645,16 +2671,18 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node,
for (ie = node->indirect_calls; ie; ie = next_ie) for (ie = node->indirect_calls; ie; ie = next_ie)
{ {
tree target; tree target;
bool speculative;
next_ie = ie->next_callee; next_ie = ie->next_callee;
target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts, target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
vNULL, aggvals); vNULL, aggvals, &speculative);
if (target) if (target)
{ {
bool agg_contents = ie->indirect_info->agg_contents; bool agg_contents = ie->indirect_info->agg_contents;
bool polymorphic = ie->indirect_info->polymorphic; bool polymorphic = ie->indirect_info->polymorphic;
int param_index = ie->indirect_info->param_index; int param_index = ie->indirect_info->param_index;
struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target); struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target,
speculative);
found = true; found = true;
if (cs && !agg_contents && !polymorphic) if (cs && !agg_contents && !polymorphic)
......
...@@ -2986,6 +2986,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, ...@@ -2986,6 +2986,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
struct cgraph_node *callee; struct cgraph_node *callee;
struct inline_summary *isummary; struct inline_summary *isummary;
enum availability avail; enum availability avail;
bool speculative;
if (!known_vals.exists () && !known_contexts.exists ()) if (!known_vals.exists () && !known_contexts.exists ())
return false; return false;
...@@ -2993,8 +2994,8 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, ...@@ -2993,8 +2994,8 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
return false; return false;
target = ipa_get_indirect_edge_target (ie, known_vals, known_contexts, target = ipa_get_indirect_edge_target (ie, known_vals, known_contexts,
known_aggs); known_aggs, &speculative);
if (!target) if (!target || speculative)
return false; return false;
/* Account for difference in cost between indirect and direct calls. */ /* Account for difference in cost between indirect and direct calls. */
......
...@@ -529,7 +529,8 @@ bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, ...@@ -529,7 +529,8 @@ bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
tree ipa_get_indirect_edge_target (struct cgraph_edge *ie, tree ipa_get_indirect_edge_target (struct cgraph_edge *ie,
vec<tree> , vec<tree> ,
vec<ipa_polymorphic_call_context>, vec<ipa_polymorphic_call_context>,
vec<ipa_agg_jump_function_p> ); vec<ipa_agg_jump_function_p>,
bool *);
struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree, struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree,
bool speculative = false); bool speculative = false);
tree ipa_impossible_devirt_target (struct cgraph_edge *, tree); tree ipa_impossible_devirt_target (struct cgraph_edge *, tree);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment