aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-cp.c
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2014-11-17 23:04:36 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2014-11-17 22:04:36 +0000
commit231b4916bf2636a02ede685b996b2bfb7773d639 (patch)
treea0d20c604d54f9af5b113f166f5c11a470e4b182 /gcc/ipa-cp.c
parenta19faae31ea866598ad4738a511ed81b01e3d58e (diff)
downloadgcc-231b4916bf2636a02ede685b996b2bfb7773d639.zip
gcc-231b4916bf2636a02ede685b996b2bfb7773d639.tar.gz
gcc-231b4916bf2636a02ede685b996b2bfb7773d639.tar.bz2
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
Diffstat (limited to 'gcc/ipa-cp.c')
-rw-r--r--gcc/ipa-cp.c64
1 files changed, 46 insertions, 18 deletions
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 375b49e..e598241 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -1730,13 +1730,16 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
vec<tree> known_csts,
vec<ipa_polymorphic_call_context> known_contexts,
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;
HOST_WIDE_INT anc_offset;
tree t;
tree target = NULL;
+ *speculative = false;
+
if (param_index == -1
|| known_csts.length () <= (unsigned int) param_index)
return NULL_TREE;
@@ -1792,8 +1795,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
t = NULL;
/* Try to work out value of virtual table pointer value in replacemnets. */
- if (!t && agg_reps && !ie->indirect_info->by_ref
- && !ie->indirect_info->vptr_changed)
+ if (!t && agg_reps && !ie->indirect_info->by_ref)
{
while (agg_reps)
{
@@ -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
aggregate values. */
if (!t && known_aggs.length () > (unsigned int) param_index
- && !ie->indirect_info->by_ref
- && !ie->indirect_info->vptr_changed)
+ && !ie->indirect_info->by_ref)
{
struct ipa_agg_jump_function *agg;
agg = known_aggs[param_index];
@@ -1836,7 +1837,9 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
|| !possible_polymorphic_call_target_p
(ie, cgraph_node::get (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,
ie->indirect_info->otr_token,
context, &final);
if (!final || targets.length () > 1)
- return NULL_TREE;
- if (targets.length () == 1)
- target = targets[0]->decl;
+ {
+ struct cgraph_node *node;
+ 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
- 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,
cgraph_node::get (target)))
@@ -1899,10 +1923,11 @@ tree
ipa_get_indirect_edge_target (struct cgraph_edge *ie,
vec<tree> known_csts,
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,
- known_aggs, NULL);
+ known_aggs, NULL, speculative);
}
/* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
@@ -1923,9 +1948,10 @@ devirtualization_time_bonus (struct cgraph_node *node,
struct inline_summary *isummary;
enum availability avail;
tree target;
+ bool speculative;
target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts,
- known_aggs);
+ known_aggs, &speculative);
if (!target)
continue;
@@ -1944,12 +1970,12 @@ devirtualization_time_bonus (struct cgraph_node *node,
/* FIXME: The values below need re-considering and perhaps also
integrating into the cost metrics, at lest in some very basic way. */
if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4)
- res += 31;
+ res += 31 / ((int)speculative + 1);
else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
- res += 15;
+ res += 15 / ((int)speculative + 1);
else if (isummary->size <= MAX_INLINE_INSNS_AUTO
|| DECL_DECLARED_INLINE_P (callee->decl))
- res += 7;
+ res += 7 / ((int)speculative + 1);
}
return res;
@@ -2645,16 +2671,18 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node,
for (ie = node->indirect_calls; ie; ie = next_ie)
{
tree target;
+ bool speculative;
next_ie = ie->next_callee;
target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts,
- vNULL, aggvals);
+ vNULL, aggvals, &speculative);
if (target)
{
bool agg_contents = ie->indirect_info->agg_contents;
bool polymorphic = ie->indirect_info->polymorphic;
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;
if (cs && !agg_contents && !polymorphic)