Hi, this modifies the decision making stage of IPA-CP in two ways:
Previously, local effects of the cloning were estimated only for the constant that was being considered, even though the calls which bring it also carry other constants. With this patch, all knowsn constants for the given subset of caller edges are considered and the heuritics should therefore have more information and generally work better. Also, when evaluating the opportunities for a given node, IPA-CP previously just iterate over the parameters starting with the first one and if any opportunity looked profitable, it was carried out and associated calling edges were redirected, even if this precludes some even better opportunity. The patch tries to mitigate this by first using the initial estimates to sort all cloning candidates and then iterate in that order. Bootstrapped, LTO-bootstrapped and tested on x86_64, OK for master? Thanks, Martin gcc/ChangeLog: 2025-11-16 Martin Jambor <[email protected]> * ipa-cp.cc (good_cloning_opportunity_p): Dump a message when bailing out early too. (find_more_scalar_values_for_callers_subset): Rename to find_scalar_values_for_callers_subset, collect constants regardless of what is already in the vector. Remove dumping. (find_more_contexts_for_caller_subset): Rename to find_contexts_for_caller_subset, collect contexts regardless of what is already in the vector. Remove dumping. (find_aggregate_values_for_callers_subset): Rename to find_aggregate_values_for_callers_subset_gc, implement using new functions. (find_aggregate_values_for_callers_subset_1): New function. (find_aggregate_values_for_callers_subset): Likewise. (copy_known_vectors_add_val): Removed. (dump_reestimation_message): New function. (decide_about_value): Remove formal parameter avals, compute it independently, and use it to estimate local cloning effects. (struct cloning_opportunity_ranking): New type. (compare_cloning_opportunities): New function. (cloning_opportunity_ranking_evaluation): Likewise. (decide_whether_version_node): Pre-sort candidates for cloning before really evaluating them. Calculate context independent values only when considering versioning for all contexts. gcc/testsuite/ChangeLog: 2025-11-16 Martin Jambor <[email protected]> * gcc.dg/ipa/ipcp-agg-2.c: Adjust dump test. * gcc.dg/ipa/ipcp-agg-3.c: Likewise. * gcc.dg/ipa/ipcp-agg-4.c: Likewise. * gcc.dg/vect/pr101145_1.c: Compile with -fno-ipa-cp. * gcc.dg/vect/pr101145_2.c: Likewise. * gcc.dg/vect/pr101145_3.c: Likewise. --- gcc/ipa-cp.cc | 455 +++++++++++++++++-------- gcc/testsuite/gcc.dg/ipa/ipcp-agg-2.c | 2 +- gcc/testsuite/gcc.dg/ipa/ipcp-agg-3.c | 4 +- gcc/testsuite/gcc.dg/ipa/ipcp-agg-4.c | 2 +- gcc/testsuite/gcc.dg/vect/pr101145_1.c | 2 +- gcc/testsuite/gcc.dg/vect/pr101145_2.c | 2 +- gcc/testsuite/gcc.dg/vect/pr101145_3.c | 2 +- 7 files changed, 316 insertions(+), 153 deletions(-) diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc index f4959178321..d611b39e253 100644 --- a/gcc/ipa-cp.cc +++ b/gcc/ipa-cp.cc @@ -3403,7 +3403,13 @@ good_cloning_opportunity_p (struct cgraph_node *node, sreal time_benefit, /* If there is no call which was executed in profiling or where profile is missing, we do not want to clone. */ || (!called_without_ipa_profile && !count_sum.nonzero_p ())) - return false; + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " good_cloning_opportunity_p (time: %g, " + "size: %i): Definitely not good or prohibited.\n", + time_benefit.to_double (), size_cost); + return false; + } gcc_assert (size_cost > 0); @@ -5244,24 +5250,29 @@ self_recursive_agg_pass_through_p (const cgraph_edge *cs, KNOWN_CSTS with constants that are also known for all of the CALLERS. */ static void -find_more_scalar_values_for_callers_subset (struct cgraph_node *node, - vec<tree> &known_csts, - const vec<cgraph_edge *> &callers) +find_scalar_values_for_callers_subset (vec<tree> &known_csts, + ipa_node_params *info, + const vec<cgraph_edge *> &callers) { - ipa_node_params *info = ipa_node_params_sum->get (node); int i, count = ipa_get_param_count (info); for (i = 0; i < count; i++) { + ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i); + if (lat->bottom) + continue; + if (lat->is_single_const ()) + { + known_csts[i] = lat->values->value; + continue; + } + struct cgraph_edge *cs; tree newval = NULL_TREE; int j; bool first = true; tree type = ipa_get_type (info, i); - if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i]) - continue; - FOR_EACH_VEC_ELT (callers, j, cs) { struct ipa_jump_func *jump_func; @@ -5318,18 +5329,7 @@ find_more_scalar_values_for_callers_subset (struct cgraph_node *node, } if (newval) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, " adding an extra known scalar value "); - print_ipcp_constant_value (dump_file, newval); - fprintf (dump_file, " for "); - ipa_dump_param (dump_file, info, i); - fprintf (dump_file, "\n"); - } - - known_csts[i] = newval; - } + known_csts[i] = newval; } } @@ -5338,23 +5338,34 @@ find_more_scalar_values_for_callers_subset (struct cgraph_node *node, CALLERS. */ static void -find_more_contexts_for_caller_subset (cgraph_node *node, - vec<ipa_polymorphic_call_context> - *known_contexts, - const vec<cgraph_edge *> &callers) +find_contexts_for_caller_subset (vec<ipa_polymorphic_call_context> + &known_contexts, + ipa_node_params *info, + const vec<cgraph_edge *> &callers) { - ipa_node_params *info = ipa_node_params_sum->get (node); int i, count = ipa_get_param_count (info); for (i = 0; i < count; i++) { - cgraph_edge *cs; + if (!ipa_is_param_used (info, i)) + continue; - if (ipa_get_poly_ctx_lat (info, i)->bottom - || (known_contexts->exists () - && !(*known_contexts)[i].useless_p ())) + ipcp_lattice<ipa_polymorphic_call_context> *ctxlat + = ipa_get_poly_ctx_lat (info, i); + if (ctxlat->bottom) continue; + if (ctxlat->is_single_const ()) + { + if (!ctxlat->values->value.useless_p ()) + { + if (known_contexts.is_empty ()) + known_contexts.safe_grow_cleared (count, true); + known_contexts[i] = ctxlat->values->value; + } + continue; + } + cgraph_edge *cs; ipa_polymorphic_call_context newval; bool first = true; int j; @@ -5382,20 +5393,9 @@ find_more_contexts_for_caller_subset (cgraph_node *node, if (!newval.useless_p ()) { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, " adding an extra known polymorphic " - "context "); - print_ipcp_constant_value (dump_file, newval); - fprintf (dump_file, " for "); - ipa_dump_param (dump_file, info, i); - fprintf (dump_file, "\n"); - } - - if (!known_contexts->exists ()) - known_contexts->safe_grow_cleared (ipa_get_param_count (info), - true); - (*known_contexts)[i] = newval; + if (known_contexts.is_empty ()) + known_contexts.safe_grow_cleared (count, true); + known_contexts[i] = newval; } } @@ -5582,11 +5582,12 @@ push_agg_values_from_edge (struct cgraph_edge *cs, /* Look at edges in CALLERS and collect all known aggregate values that arrive - from all of them. Return nullptr if there are none. */ + from all of them into INTERIM. Return how many there are. */ -static struct vec<ipa_argagg_value, va_gc> * -find_aggregate_values_for_callers_subset (struct cgraph_node *node, - const vec<cgraph_edge *> &callers) +static unsigned int +find_aggregate_values_for_callers_subset_1 (vec<ipa_argagg_value> &interim, + struct cgraph_node *node, + const vec<cgraph_edge *> &callers) { ipa_node_params *dest_info = ipa_node_params_sum->get (node); if (dest_info->ipcp_orig_node) @@ -5594,12 +5595,11 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node, /* gather_edges_for_value puts a non-recursive call into the first element of callers if it can. */ - auto_vec<ipa_argagg_value, 32> interim; push_agg_values_from_edge (callers[0], dest_info, &interim, NULL, true); unsigned valid_entries = interim.length (); if (!valid_entries) - return nullptr; + return 0; unsigned caller_count = callers.length(); for (unsigned i = 1; i < caller_count; i++) @@ -5610,9 +5610,47 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node, valid_entries = intersect_argaggs_with (interim, last); if (!valid_entries) - return nullptr; + return 0; } + return valid_entries; +} + +/* Look at edges in CALLERS and collect all known aggregate values that arrive + from all of them and return them in a garbage-collected vector. Return + nullptr if there are none. */ + +static void +find_aggregate_values_for_callers_subset (vec<ipa_argagg_value> &res, + struct cgraph_node *node, + const vec<cgraph_edge *> &callers) +{ + auto_vec<ipa_argagg_value, 32> interim; + unsigned valid_entries + = find_aggregate_values_for_callers_subset_1 (interim, node, callers); + if (!valid_entries) + return; + + for (const ipa_argagg_value &av : interim) + if (av.value) + res.safe_push(av); + return; +} + +/* Look at edges in CALLERS and collect all known aggregate values that arrive + from all of them and return them in a garbage-collected vector. Return + nullptr if there are none. */ + +static struct vec<ipa_argagg_value, va_gc> * +find_aggregate_values_for_callers_subset_gc (struct cgraph_node *node, + const vec<cgraph_edge *> &callers) +{ + auto_vec<ipa_argagg_value, 32> interim; + unsigned valid_entries + = find_aggregate_values_for_callers_subset_1 (interim, node, callers); + if (!valid_entries) + return nullptr; + vec<ipa_argagg_value, va_gc> *res = NULL; vec_safe_reserve_exact (res, valid_entries); for (const ipa_argagg_value &av : interim) @@ -5743,37 +5781,6 @@ copy_useful_known_contexts (const vec<ipa_polymorphic_call_context> &known_conte return vNULL; } -/* Copy known scalar values from AVALS into KNOWN_CSTS and modify the copy - according to VAL and INDEX. If non-empty, replace KNOWN_CONTEXTS with its - copy too. */ - -static void -copy_known_vectors_add_val (ipa_auto_call_arg_values *avals, - vec<tree> *known_csts, - vec<ipa_polymorphic_call_context> *known_contexts, - ipcp_value<tree> *val, int index) -{ - *known_csts = avals->m_known_vals.copy (); - *known_contexts = copy_useful_known_contexts (avals->m_known_contexts); - (*known_csts)[index] = val->value; -} - -/* Copy known scalar values from AVALS into KNOWN_CSTS. Similarly, copy - contexts to KNOWN_CONTEXTS and modify the copy according to VAL and - INDEX. */ - -static void -copy_known_vectors_add_val (ipa_auto_call_arg_values *avals, - vec<tree> *known_csts, - vec<ipa_polymorphic_call_context> *known_contexts, - ipcp_value<ipa_polymorphic_call_context> *val, - int index) -{ - *known_csts = avals->m_known_vals.copy (); - *known_contexts = avals->m_known_contexts.copy (); - (*known_contexts)[index] = val->value; -} - /* Return true if OFFSET indicates this was not an aggregate value or there is a replacement equivalent to VALUE, INDEX and OFFSET among those in the AGGVALS list. */ @@ -5790,6 +5797,42 @@ ipcp_val_agg_replacement_ok_p (vec<ipa_argagg_value, va_gc> *aggvals, return v && values_equal_for_ipcp_p (v, value); } +/* Dump to F all the values in AVALS for which we are re-evaluating the effects + on the function represented b INFO. */ + +DEBUG_FUNCTION void +dump_reestimation_message (FILE *f, ipa_node_params *info, + const ipa_auto_call_arg_values &avals) +{ + fprintf (f, " Re-estimating effects with\n" + " Scalar constants:"); + int param_count = ipa_get_param_count (info); + for (int i = 0; i < param_count; i++) + if (avals.m_known_vals[i]) + { + fprintf (f, " %i:", i); + print_ipcp_constant_value (f, avals.m_known_vals[i]); + } + fprintf (f, "\n"); + if (!avals.m_known_contexts.is_empty ()) + { + fprintf (f, " Pol. contexts:"); + for (int i = 0; i < param_count; i++) + if (!avals.m_known_contexts[i].useless_p ()) + { + fprintf (f, " %i:", i); + avals.m_known_contexts[i].dump (f); + } + fprintf (f, "\n"); + } + if (!avals.m_known_aggs.is_empty ()) + { + fprintf (f, " Aggregate replacements:"); + ipa_argagg_value_list avs (&avals); + avs.dump (f); + } +} + /* Return true if offset is minus one because source of a polymorphic context cannot be an aggregate value. */ @@ -5812,13 +5855,12 @@ ipcp_val_agg_replacement_ok_p (vec<ipa_argagg_value, va_gc> *, template <typename valtype> static bool decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset, - ipcp_value<valtype> *val, ipa_auto_call_arg_values *avals, + ipcp_value<valtype> *val, vec<cgraph_node *> *self_gen_clones, int cur_sweep) { int caller_count; sreal freq_sum; profile_count count_sum, rec_count_sum; - vec<cgraph_edge *> callers; bool called_without_ipa_profile; if (val->spec_node) @@ -5872,34 +5914,75 @@ decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset, fprintf (dump_file, " (caller_count: %i)\n", caller_count); } - if (!good_cloning_opportunity_p (node, val->local_time_benefit, - freq_sum, count_sum, - val->local_size_cost, - called_without_ipa_profile, cur_sweep) - && !good_cloning_opportunity_p (node, val->prop_time_benefit, - freq_sum, count_sum, val->prop_size_cost, - called_without_ipa_profile, cur_sweep)) - return false; + vec<cgraph_edge *> callers; + callers = gather_edges_for_value (val, node, caller_count); + ipa_node_params *info = ipa_node_params_sum->get (node); + ipa_auto_call_arg_values avals; + avals.m_known_vals.safe_grow_cleared (ipa_get_param_count (info), true); + find_scalar_values_for_callers_subset (avals.m_known_vals, info, callers); + find_contexts_for_caller_subset (avals.m_known_contexts, info, callers); + find_aggregate_values_for_callers_subset (avals.m_known_aggs, node, callers); + + + if (good_cloning_opportunity_p (node, val->prop_time_benefit, + freq_sum, count_sum, val->prop_size_cost, + called_without_ipa_profile, cur_sweep)) + ; + else + { + /* Extern inline functions are only meaningful to clione to propagate + values to their callees. */ + if (DECL_EXTERNAL (node->decl) && DECL_DECLARED_INLINE_P (node->decl)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " Skipping extern inline.\n"); + return false; + } + if (dump_file && (dump_flags & TDF_DETAILS)) + dump_reestimation_message (dump_file, info, avals); + + ipa_call_estimates estimates; + estimate_ipcp_clone_size_and_time (node, &avals, &estimates); + int removable_params_cost = 0; + for (tree t : avals.m_known_vals) + if (t) + removable_params_cost += estimate_move_cost (TREE_TYPE (t), true); + + int size = estimates.size - caller_count * removable_params_cost; + + if (size <= 0) + { + if (dump_file) + fprintf (dump_file, " Code not going to grow.\n"); + } + else + { + sreal time_benefit + = ((estimates.nonspecialized_time - estimates.time) + + hint_time_bonus (node, estimates) + + (devirtualization_time_bonus (node, &avals) + + removable_params_cost)); + + if (!good_cloning_opportunity_p (node, time_benefit, freq_sum, + count_sum, size, + called_without_ipa_profile, + cur_sweep)) + return false; + } + } if (dump_file) fprintf (dump_file, " Creating a specialized node of %s.\n", node->dump_name ()); - vec<tree> known_csts; - vec<ipa_polymorphic_call_context> known_contexts; + vec<tree> known_csts = avals.m_known_vals.copy (); + vec<ipa_polymorphic_call_context> known_contexts + = copy_useful_known_contexts (avals.m_known_contexts); - callers = gather_edges_for_value (val, node, caller_count); - if (offset == -1) - copy_known_vectors_add_val (avals, &known_csts, &known_contexts, val, index); - else - { - known_csts = avals->m_known_vals.copy (); - known_contexts = copy_useful_known_contexts (avals->m_known_contexts); - } - find_more_scalar_values_for_callers_subset (node, known_csts, callers); - find_more_contexts_for_caller_subset (node, &known_contexts, callers); - vec<ipa_argagg_value, va_gc> *aggvals - = find_aggregate_values_for_callers_subset (node, callers); + vec<ipa_argagg_value, va_gc> *aggvals = NULL; + vec_safe_reserve_exact (aggvals, avals.m_known_aggs.length ()); + for (const ipa_argagg_value &av : avals.m_known_aggs) + aggvals->quick_push (av); gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index, offset, val->value)); val->spec_node = create_specialized_node (node, known_csts, known_contexts, @@ -5939,6 +6022,52 @@ ipa_range_contains_p (const vrange &r, tree val) return r.contains_p (val); } +/* Structure holding opportunitties so that they can be pre-sorted. */ + +struct cloning_opportunity_ranking +{ + /* A very rough evaluation of likely benefit. */ + sreal eval; + /* In the case of aggregate constants, a non-negative offset within their + aggregates. -1 for scalar constants, -2 for polymorphic contexts. */ + HOST_WIDE_INT offset; + /* The value being considered for evaluation for cloning. */ + ipcp_value_base *val; + /* Index of the formal parameter the value is coming in. */ + int index; +}; + +/* Helper function to qsort a vecotr of cloning opportunities. */ + +static int +compare_cloning_opportunities (const void *a, const void *b) +{ + const cloning_opportunity_ranking *o1 + = (const cloning_opportunity_ranking *) a; + const cloning_opportunity_ranking *o2 + = (const cloning_opportunity_ranking *) b; + if (o1->eval < o2->eval) + return 1; + if (o1->eval > o2->eval) + return -1; + return 0; +} + +/* Use the estimations in VAL to determine how good a candidate it represents + for the purposes of ordering real evaluation of opportunities (which + includes information about incoming edges, among other things). */ + +static sreal +cloning_opportunity_ranking_evaluation (const ipcp_value_base *val) +{ + sreal e1 = (val->local_time_benefit * 1000) / MAX (val->local_size_cost, 1); + sreal e2 = (val->prop_time_benefit * 1000) / MAX (val->prop_size_cost, 1); + if (e2 > e1) + return e2; + else + return e1; +} + /* Decide whether and what specialized clones of NODE should be created. CUR_SWEEP is the number of the current sweep of the call-graph during the decision stage. */ @@ -5947,7 +6076,7 @@ static bool decide_whether_version_node (struct cgraph_node *node, int cur_sweep) { ipa_node_params *info = ipa_node_params_sum->get (node); - int i, count = ipa_get_param_count (info); + int count = ipa_get_param_count (info); bool ret = false; if (info->node_dead || count == 0) @@ -5957,13 +6086,8 @@ decide_whether_version_node (struct cgraph_node *node, int cur_sweep) fprintf (dump_file, "\nEvaluating opportunities for %s.\n", node->dump_name ()); - auto_vec <cgraph_node *, 9> self_gen_clones; - ipa_auto_call_arg_values avals; - int removable_params_cost; - bool ctx_independent_const - = gather_context_independent_values (info, &avals, &removable_params_cost); - - for (i = 0; i < count;i++) + auto_vec <cloning_opportunity_ranking, 32> opp_ranking; + for (int i = 0; i < count;i++) { if (!ipa_is_param_used (info, i)) continue; @@ -5973,7 +6097,7 @@ decide_whether_version_node (struct cgraph_node *node, int cur_sweep) ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; if (!lat->bottom - && !avals.m_known_vals[i]) + && !lat->is_single_const ()) { ipcp_value<tree> *val; for (val = lat->values; val; val = val->next) @@ -6000,8 +6124,12 @@ decide_whether_version_node (struct cgraph_node *node, int cur_sweep) } continue; } - ret |= decide_about_value (node, i, -1, val, &avals, - &self_gen_clones, cur_sweep); + cloning_opportunity_ranking opp; + opp.eval = cloning_opportunity_ranking_evaluation (val); + opp.offset = -1; + opp.val = val; + opp.index = i; + opp_ranking.safe_push (opp); } } @@ -6016,37 +6144,83 @@ decide_whether_version_node (struct cgraph_node *node, int cur_sweep) && (plats->aggs_contain_variable || !aglat->is_single_const ())) for (val = aglat->values; val; val = val->next) - ret |= decide_about_value (node, i, aglat->offset, val, &avals, - &self_gen_clones, cur_sweep); + { + cloning_opportunity_ranking opp; + opp.eval = cloning_opportunity_ranking_evaluation (val); + opp.offset = aglat->offset; + opp.val = val; + opp.index = i; + opp_ranking.safe_push (opp); + } } if (!ctxlat->bottom - && avals.m_known_contexts[i].useless_p ()) + && !ctxlat->is_single_const ()) { ipcp_value<ipa_polymorphic_call_context> *val; for (val = ctxlat->values; val; val = val->next) - ret |= decide_about_value (node, i, -1, val, &avals, + if (!val->value.useless_p ()) + { + cloning_opportunity_ranking opp; + opp.eval = cloning_opportunity_ranking_evaluation (val); + opp.offset = -2; + opp.val = val; + opp.index = i; + opp_ranking.safe_push (opp); + } + } + } + + if (!opp_ranking.is_empty ()) + { + opp_ranking.qsort (compare_cloning_opportunities); + auto_vec <cgraph_node *, 9> self_gen_clones; + for (const cloning_opportunity_ranking &opp : opp_ranking) + if (opp.offset == -2) + { + ipcp_value<ipa_polymorphic_call_context> *val + = static_cast <ipcp_value<ipa_polymorphic_call_context> *> + (opp.val); + ret |= decide_about_value (node, opp.index, -1, val, &self_gen_clones, cur_sweep); + } + else + { + ipcp_value<tree> *val = static_cast<ipcp_value<tree> *> (opp.val); + ret |= decide_about_value (node, opp.index, opp.offset, val, + &self_gen_clones, cur_sweep); + } + + if (!self_gen_clones.is_empty ()) + { + self_gen_clones.safe_push (node); + update_counts_for_self_gen_clones (node, self_gen_clones); } } - if (!self_gen_clones.is_empty ()) + struct caller_statistics stats; + init_caller_stats (&stats); + node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, + false); + if (!stats.n_calls) { - self_gen_clones.safe_push (node); - update_counts_for_self_gen_clones (node, self_gen_clones); + if (dump_file) + fprintf (dump_file, " Not cloning for all contexts because " + "there are no callers of the original node (any more).\n"); + return ret; } bool do_clone_for_all_contexts = false; + ipa_auto_call_arg_values avals; + int removable_params_cost; + bool ctx_independent_const + = gather_context_independent_values (info, &avals, &removable_params_cost); sreal devirt_bonus = devirtualization_time_bonus (node, &avals); if (ctx_independent_const || devirt_bonus > 0 || (removable_params_cost && clone_for_param_removal_p (node))) { - struct caller_statistics stats; - ipa_call_estimates estimates; + ipa_call_estimates estimates; - init_caller_stats (&stats); - node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, - false); estimate_ipcp_clone_size_and_time (node, &avals, &estimates); sreal time = estimates.nonspecialized_time - estimates.time; time += devirt_bonus; @@ -6058,13 +6232,7 @@ decide_whether_version_node (struct cgraph_node *node, int cur_sweep) fprintf (dump_file, " - context independent values, size: %i, " "time_benefit: %f\n", size, (time).to_double ()); - if (!stats.n_calls) - { - if (dump_file) - fprintf (dump_file, " Not cloning for all contexts because " - "there are no callers of the original node left.\n"); - } - else if (size <= 0 || node->local) + if (size <= 0 || node->local) { if (!dbg_cnt (ipa_cp_values)) return ret; @@ -6124,19 +6292,14 @@ decide_whether_version_node (struct cgraph_node *node, int cur_sweep) fprintf (dump_file, " Creating a specialized node of %s " "for all known contexts.\n", node->dump_name ()); - vec<tree> known_csts = avals.m_known_vals.copy (); - vec<ipa_polymorphic_call_context> known_contexts - = copy_useful_known_contexts (avals.m_known_contexts); - find_more_scalar_values_for_callers_subset (node, known_csts, callers); - find_more_contexts_for_caller_subset (node, &known_contexts, callers); + vec<tree> known_csts = vNULL; + known_csts.safe_grow_cleared (count, true); + find_scalar_values_for_callers_subset (known_csts, info, callers); + vec<ipa_polymorphic_call_context> known_contexts = vNULL; + find_contexts_for_caller_subset (known_contexts, info, callers); vec<ipa_argagg_value, va_gc> *aggvals - = find_aggregate_values_for_callers_subset (node, callers); + = find_aggregate_values_for_callers_subset_gc (node, callers); - if (!known_contexts_useful_p (known_contexts)) - { - known_contexts.release (); - known_contexts = vNULL; - } struct cgraph_node *clone = create_specialized_node (node, known_csts, known_contexts, aggvals, callers); diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-agg-2.c b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-2.c index d142e2a95d3..0afc011909a 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipcp-agg-2.c +++ b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-2.c @@ -37,5 +37,5 @@ entry (int c) foo (&s); } /* { dg-final { scan-ipa-dump-times "Creating a specialized node of foo/\[0-9\]*\\." 2 "cp" } } */ -/* { dg-final { scan-ipa-dump-times "Aggregate replacements:" 4 "cp" } } */ +/* { dg-final { scan-ipa-dump "Aggregate replacements:" "cp" } } */ /* { dg-final { scan-tree-dump-not "->c;" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-agg-3.c b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-3.c index 98e0ee03ff6..0fa56a1acfc 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipcp-agg-3.c +++ b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-3.c @@ -37,6 +37,6 @@ entry (int c) foo (0, &s); } /* { dg-final { scan-ipa-dump-times "Creating a specialized node of foo/\[0-9\]*\\." 2 "cp" } } */ -/* { dg-final { scan-ipa-dump-times "Aggregate replacements: 1" 2 "cp" } } */ -/* { dg-final { scan-ipa-dump-times "Aggregate replacements: 0" 2 "cp" } } */ +/* { dg-final { scan-ipa-dump "Aggregate replacements: 1" "cp" } } */ +/* { dg-final { scan-ipa-dump "Aggregate replacements: 0" "cp" } } */ /* { dg-final { scan-tree-dump-not "->c;" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-agg-4.c b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-4.c index 5b0d6916654..47bcfecaba8 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipcp-agg-4.c +++ b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-4.c @@ -56,5 +56,5 @@ entry2 (int c) } /* { dg-final { scan-ipa-dump-times "Creating a specialized node of foo/\[0-9\]*\\." 2 "cp" } } */ -/* { dg-final { scan-ipa-dump-times "Aggregate replacements:" 4 "cp" } } */ +/* { dg-final { scan-ipa-dump "Aggregate replacements:" "cp" } } */ /* { dg-final { scan-tree-dump-not "->c;" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr101145_1.c b/gcc/testsuite/gcc.dg/vect/pr101145_1.c index 24a9da63e88..bd35e8c4be1 100644 --- a/gcc/testsuite/gcc.dg/vect/pr101145_1.c +++ b/gcc/testsuite/gcc.dg/vect/pr101145_1.c @@ -1,5 +1,5 @@ /* { dg-require-effective-target vect_char_add } */ -/* { dg-additional-options "-O3" } */ +/* { dg-additional-options "-O3 -fno-ipa-cp" } */ #define TYPE signed char #define MIN -128 #define MAX 127 diff --git a/gcc/testsuite/gcc.dg/vect/pr101145_2.c b/gcc/testsuite/gcc.dg/vect/pr101145_2.c index 9091f606066..a0e9472ecb7 100644 --- a/gcc/testsuite/gcc.dg/vect/pr101145_2.c +++ b/gcc/testsuite/gcc.dg/vect/pr101145_2.c @@ -1,5 +1,5 @@ /* { dg-require-effective-target vect_char_add } */ -/* { dg-additional-options "-O3" } */ +/* { dg-additional-options "-O3 -fno-ipa-cp" } */ #define TYPE unsigned char #define MIN 0 #define MAX 255 diff --git a/gcc/testsuite/gcc.dg/vect/pr101145_3.c b/gcc/testsuite/gcc.dg/vect/pr101145_3.c index 001e5f38a46..0d809635dd8 100644 --- a/gcc/testsuite/gcc.dg/vect/pr101145_3.c +++ b/gcc/testsuite/gcc.dg/vect/pr101145_3.c @@ -1,5 +1,5 @@ /* { dg-require-effective-target vect_long_long } */ -/* { dg-additional-options "-O3" } */ +/* { dg-additional-options "-O3 -fno-ipa-cp" } */ #define TYPE int * #define MIN ((TYPE)0) #define MAX ((TYPE)((long long)-1)) -- 2.51.1
