From 231b4916bf2636a02ede685b996b2bfb7773d639 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Mon, 17 Nov 2014 23:04:36 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 9 ++++++ gcc/ipa-cp.c | 64 ++++++++++++++++++++++++++++----------- gcc/ipa-inline-analysis.c | 5 +-- gcc/ipa-prop.h | 3 +- 4 files changed, 60 insertions(+), 21 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5e2e1a19f79..366be84ad34 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2014-11-17 Jan Hubicka + + * 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 * tree.c (free_lang_data_in_decl): Set DECL_FUNCTION_SPECIFIC_OPTIMIZATION diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 375b49e5f91..e598241c01d 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 known_csts, vec known_contexts, vec 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 known_csts, vec known_contexts, - vec known_aggs) + vec 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) diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 69e06123fee..dace2fc78be 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -2986,6 +2986,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, struct cgraph_node *callee; struct inline_summary *isummary; enum availability avail; + bool speculative; if (!known_vals.exists () && !known_contexts.exists ()) return false; @@ -2993,8 +2994,8 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, return false; target = ipa_get_indirect_edge_target (ie, known_vals, known_contexts, - known_aggs); - if (!target) + known_aggs, &speculative); + if (!target || speculative) return false; /* Account for difference in cost between indirect and direct calls. */ diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 9e0ce359983..6adb8d4d9c7 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -529,7 +529,8 @@ bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, tree ipa_get_indirect_edge_target (struct cgraph_edge *ie, vec , vec, - vec ); + vec, + bool *); struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree, bool speculative = false); tree ipa_impossible_devirt_target (struct cgraph_edge *, tree); -- 2.30.2