From: Jan Hubicka Date: Thu, 21 Nov 2019 14:58:08 +0000 (+0100) Subject: ipa-fnsummary.c (evaluate_conditions_for_known_args): Be ready for some vectors to... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b0d5547612f08d7112d9284a7b5a862df3373570;p=gcc.git ipa-fnsummary.c (evaluate_conditions_for_known_args): Be ready for some vectors to not be allocated. * ipa-fnsummary.c (evaluate_conditions_for_known_args): Be ready for some vectors to not be allocated. (evaluate_properties_for_edge): Document better; make known_vals and known_aggs caller allocated; avoid determining values of parameters which are not used. (ipa_merge_fn_summary_after_inlining): Pre allocate known_vals and known_aggs. * ipa-inline-analysis.c (do_estimate_edge_time): Likewise. (do_estimate_edge_size): Likewise. (do_estimate_edge_hints): Likewise. * ipa-cp.c (ipa_get_indirect_edge_target_1): Do not early exit when values are not known. (ipa_release_agg_values): Add option to not release vector itself. From-SVN: r278553 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8bb076320ff..34820c33d2d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2019-11-21 Jan Hubicka + + * ipa-fnsummary.c (evaluate_conditions_for_known_args): Be + ready for some vectors to not be allocated. + (evaluate_properties_for_edge): Document better; make + known_vals and known_aggs caller allocated; avoid determining + values of parameters which are not used. + (ipa_merge_fn_summary_after_inlining): Pre allocate known_vals and + known_aggs. + * ipa-inline-analysis.c (do_estimate_edge_time): Likewise. + (do_estimate_edge_size): Likewise. + (do_estimate_edge_hints): Likewise. + * ipa-cp.c (ipa_get_indirect_edge_target_1): Do not early exit when + values are not known. + (ipa_release_agg_values): Add option to not release vector itself. + 2019-11-21 Richard Biener * cfgloop.h (loop_iterator::~loop_iterator): Remove. diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 8372dfaa771..31a98a3d98a 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -2744,18 +2744,17 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, { int param_index = ie->indirect_info->param_index; HOST_WIDE_INT anc_offset; - tree t; + tree t = NULL; tree target = NULL; *speculative = false; - if (param_index == -1 - || known_csts.length () <= (unsigned int) param_index) + if (param_index == -1) return NULL_TREE; if (!ie->indirect_info->polymorphic) { - tree t; + tree t = NULL; if (ie->indirect_info->agg_contents) { @@ -2782,7 +2781,11 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, else agg = NULL; bool from_global_constant; - t = ipa_find_agg_cst_for_param (agg, known_csts[param_index], + t = ipa_find_agg_cst_for_param (agg, + (unsigned) param_index + < known_csts.length () + ? known_csts[param_index] + : NULL, ie->indirect_info->offset, ie->indirect_info->by_ref, &from_global_constant); @@ -2792,7 +2795,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, t = NULL_TREE; } } - else + else if ((unsigned) param_index < known_csts.length ()) t = known_csts[param_index]; if (t @@ -2833,7 +2836,10 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, && !ie->indirect_info->by_ref) { struct ipa_agg_value_set *agg = &known_aggs[param_index]; - t = ipa_find_agg_cst_for_param (agg, known_csts[param_index], + t = ipa_find_agg_cst_for_param (agg, + (unsigned) param_index + < known_csts.length () + ? known_csts[param_index] : NULL, ie->indirect_info->offset, true); } @@ -2867,7 +2873,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, } /* Do we know the constant value of pointer? */ - if (!t) + if (!t && (unsigned) param_index < known_csts.length ()) t = known_csts[param_index]; gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO); diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index d0bbe71c979..9ac998482b5 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -342,7 +342,7 @@ evaluate_conditions_for_known_args (struct cgraph_node *node, for (i = 0; vec_safe_iterate (info->conds, i, &c); i++) { - tree val; + tree val = NULL; tree res; int j; struct expr_eval_op *op; @@ -351,14 +351,8 @@ evaluate_conditions_for_known_args (struct cgraph_node *node, (especially for K&R style programs). So bound check here (we assume known_aggs vector, if non-NULL, has the same length as known_vals). */ - gcc_checking_assert (!known_aggs.exists () + gcc_checking_assert (!known_aggs.length () || !known_vals.length () || (known_vals.length () == known_aggs.length ())); - if (c->operand_num >= (int) known_vals.length ()) - { - clause |= 1 << (i + predicate::first_dynamic_condition); - nonspec_clause |= 1 << (i + predicate::first_dynamic_condition); - continue; - } if (c->agg_contents) { @@ -366,19 +360,24 @@ evaluate_conditions_for_known_args (struct cgraph_node *node, if (c->code == predicate::changed && !c->by_ref + && c->operand_num < (int)known_vals.length () && (known_vals[c->operand_num] == error_mark_node)) continue; - if (known_aggs.exists ()) + if (c->operand_num < (int)known_aggs.length ()) { agg = &known_aggs[c->operand_num]; - val = ipa_find_agg_cst_for_param (agg, known_vals[c->operand_num], + val = ipa_find_agg_cst_for_param (agg, + c->operand_num + < (int) known_vals.length () + ? known_vals[c->operand_num] + : NULL, c->offset, c->by_ref); } else val = NULL_TREE; } - else + else if (c->operand_num < (int) known_vals.length ()) { val = known_vals[c->operand_num]; if (val == error_mark_node && c->code != predicate::changed) @@ -504,7 +503,18 @@ evaluate_conditions_for_known_args (struct cgraph_node *node, } -/* Work out what conditions might be true at invocation of E. */ +/* Work out what conditions might be true at invocation of E. + Compute costs for inlined edge if INLINE_P is true. + + Return in CLAUSE_PTR the evaluated condistions and in NONSPEC_CLAUSE_PTR + (if non-NULL) conditions evaluated for nonspecialized clone called + in a given context. + + KNOWN_VALS_PTR and KNOWN_AGGS_PTR must be non-NULL and will be filled by + known canstant and aggregate values of parameters. + + KNOWN_CONTEXT_PTR, if non-NULL, will be filled by polymorphic call contexts + of parameter used by a polymorphic call. */ void evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, @@ -517,113 +527,141 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, { struct cgraph_node *callee = e->callee->ultimate_alias_target (); class ipa_fn_summary *info = ipa_fn_summaries->get (callee); - vec known_vals = vNULL; auto_vec known_value_ranges; - vec known_aggs = vNULL; class ipa_edge_args *args; if (clause_ptr) *clause_ptr = inline_p ? 0 : 1 << predicate::not_inlined_condition; - if (known_vals_ptr) - known_vals_ptr->create (0); - if (known_contexts_ptr) - known_contexts_ptr->create (0); if (ipa_node_params_sum && !e->call_stmt_cannot_inline_p - && ((clause_ptr && info->conds) || known_vals_ptr || known_contexts_ptr) + && (info->conds || known_contexts_ptr) && (args = IPA_EDGE_REF (e)) != NULL) { struct cgraph_node *caller; - class ipa_node_params *caller_parms_info, *callee_pi; + class ipa_node_params *caller_parms_info, *callee_pi = NULL; class ipa_call_summary *es = ipa_call_summaries->get (e); int i, count = ipa_get_cs_argument_count (args); - if (e->caller->inlined_to) - caller = e->caller->inlined_to; - else - caller = e->caller; - caller_parms_info = IPA_NODE_REF (caller); - callee_pi = IPA_NODE_REF (callee); - - if (count && (info->conds || known_vals_ptr)) - known_vals.safe_grow_cleared (count); - if (count && info->conds) - known_value_ranges.safe_grow_cleared (count); - if (count && (info->conds || known_aggs_ptr)) - known_aggs.safe_grow_cleared (count); - if (count && known_contexts_ptr) - known_contexts_ptr->safe_grow_cleared (count); + if (count) + { + if (e->caller->inlined_to) + caller = e->caller->inlined_to; + else + caller = e->caller; + caller_parms_info = IPA_NODE_REF (caller); + callee_pi = IPA_NODE_REF (callee); + + /* Watch for thunks. */ + if (callee_pi) + /* Watch for variadic functions. */ + count = MIN (count, ipa_get_param_count (callee_pi)); + } if (callee_pi) for (i = 0; i < count; i++) { struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, i); - tree cst = ipa_value_from_jfunc (caller_parms_info, jf, - ipa_get_type (callee_pi, i)); - if (!cst && e->call_stmt - && i < (int)gimple_call_num_args (e->call_stmt)) + if (ipa_is_param_used_by_indirect_call (callee_pi, i) + || ipa_is_param_used_by_ipa_predicates (callee_pi, i)) { - cst = gimple_call_arg (e->call_stmt, i); - if (!is_gimple_min_invariant (cst)) - cst = NULL; + /* Determine if we know constant value of the parameter. */ + tree cst = ipa_value_from_jfunc (caller_parms_info, jf, + ipa_get_type (callee_pi, i)); + + if (!cst && e->call_stmt + && i < (int)gimple_call_num_args (e->call_stmt)) + { + cst = gimple_call_arg (e->call_stmt, i); + if (!is_gimple_min_invariant (cst)) + cst = NULL; + } + if (cst) + { + gcc_checking_assert (TREE_CODE (cst) != TREE_BINFO); + if (!known_vals_ptr->length ()) + vec_safe_grow_cleared (known_vals_ptr, count); + (*known_vals_ptr)[i] = cst; + } + else if (inline_p && !es->param[i].change_prob) + { + if (!known_vals_ptr->length ()) + vec_safe_grow_cleared (known_vals_ptr, count); + (*known_vals_ptr)[i] = error_mark_node; + } + + /* If we failed to get simple constant, try value range. */ + if ((!cst || TREE_CODE (cst) != INTEGER_CST) + && ipa_is_param_used_by_ipa_predicates (callee_pi, i)) + { + value_range vr + = ipa_value_range_from_jfunc (caller_parms_info, e, jf, + ipa_get_type (callee_pi, + i)); + if (!vr.undefined_p () && !vr.varying_p ()) + { + if (!known_value_ranges.length ()) + known_value_ranges.safe_grow_cleared (count); + known_value_ranges[i] = vr; + } + } + + /* Determine known aggregate values. */ + ipa_agg_value_set agg + = ipa_agg_value_set_from_jfunc (caller_parms_info, + caller, &jf->agg); + if (agg.items.length ()) + { + if (!known_aggs_ptr->length ()) + vec_safe_grow_cleared (known_aggs_ptr, count); + (*known_aggs_ptr)[i] = agg; + } } - if (cst) + + /* For calls used in polymorphic calls we further determine + polymorphic call context. */ + if (known_contexts_ptr + && ipa_is_param_used_by_polymorphic_call (callee_pi, i)) { - gcc_checking_assert (TREE_CODE (cst) != TREE_BINFO); - if (known_vals.exists ()) - known_vals[i] = cst; - } - else if (inline_p && !es->param[i].change_prob) - known_vals[i] = error_mark_node; - - if (known_contexts_ptr) - (*known_contexts_ptr)[i] - = ipa_context_from_jfunc (caller_parms_info, e, i, jf); - - known_aggs[i] = ipa_agg_value_set_from_jfunc (caller_parms_info, - caller, &jf->agg); - if (info->conds) - known_value_ranges[i] - = ipa_value_range_from_jfunc (caller_parms_info, e, jf, - ipa_get_type (callee_pi, i)); + ipa_polymorphic_call_context + ctx = ipa_context_from_jfunc (caller_parms_info, e, i, jf); + if (!ctx.useless_p ()) + { + if (!known_contexts_ptr->length ()) + known_contexts_ptr->safe_grow_cleared (count); + (*known_contexts_ptr)[i] + = ipa_context_from_jfunc (caller_parms_info, e, i, jf); + } + } } else - gcc_assert (callee->thunk.thunk_p); + gcc_assert (!count || callee->thunk.thunk_p); } - else if (e->call_stmt && !e->call_stmt_cannot_inline_p - && ((clause_ptr && info->conds) || known_vals_ptr)) + else if (e->call_stmt && !e->call_stmt_cannot_inline_p && info->conds) { int i, count = (int)gimple_call_num_args (e->call_stmt); - if (count && (info->conds || known_vals_ptr)) - known_vals.safe_grow_cleared (count); for (i = 0; i < count; i++) { tree cst = gimple_call_arg (e->call_stmt, i); if (!is_gimple_min_invariant (cst)) cst = NULL; if (cst) - known_vals[i] = cst; + { + if (!known_vals_ptr->length ()) + vec_safe_grow_cleared (known_vals_ptr, count); + (*known_vals_ptr)[i] = cst; + } } } evaluate_conditions_for_known_args (callee, inline_p, - known_vals, + *known_vals_ptr, known_value_ranges, - known_aggs, clause_ptr, + *known_aggs_ptr, + clause_ptr, nonspec_clause_ptr); - - if (known_vals_ptr) - *known_vals_ptr = known_vals; - else - known_vals.release (); - - if (known_aggs_ptr) - *known_aggs_ptr = known_aggs; - else - ipa_release_agg_values (known_aggs); } @@ -2926,7 +2964,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, enum availability avail; bool speculative; - if (!known_vals.exists () && !known_contexts.exists ()) + if (!known_vals.length () && !known_contexts.length ()) return false; if (!opt_for_fn (ie->caller->decl, flag_indirect_inlining)) return false; @@ -3305,11 +3343,13 @@ ipa_call_context::release (bool all) /* See if context is initialized at first place. */ if (!m_node) return; - m_known_vals.release (); - m_known_contexts.release (); - ipa_release_agg_values (m_known_aggs); + ipa_release_agg_values (m_known_aggs, all); if (all) - m_inline_param_summary.release (); + { + m_known_vals.release (); + m_known_contexts.release (); + m_inline_param_summary.release (); + } } /* Return true if CTX describes the same call context as THIS. */ @@ -3813,8 +3853,12 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) info->fp_expressions |= callee_info->fp_expressions; if (callee_info->conds) - evaluate_properties_for_edge (edge, true, &clause, - NULL, NULL, NULL, NULL); + { + auto_vec known_vals; + auto_vec known_aggs; + evaluate_properties_for_edge (edge, true, &clause, NULL, + &known_vals, NULL, &known_aggs); + } if (ipa_node_params_sum && callee_info->conds) { class ipa_edge_args *args = IPA_EDGE_REF (edge); diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index b5a55a71d5a..e36902073f5 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -186,9 +186,9 @@ do_estimate_edge_time (struct cgraph_edge *edge, sreal *ret_nonspec_time) ipa_hints hints; struct cgraph_node *callee; clause_t clause, nonspec_clause; - vec known_vals; - vec known_contexts; - vec known_aggs; + auto_vec known_vals; + auto_vec known_contexts; + auto_vec known_aggs; class ipa_call_summary *es = ipa_call_summaries->get (edge); int min_size = -1; @@ -308,9 +308,9 @@ do_estimate_edge_size (struct cgraph_edge *edge) int size; struct cgraph_node *callee; clause_t clause, nonspec_clause; - vec known_vals; - vec known_contexts; - vec known_aggs; + auto_vec known_vals; + auto_vec known_contexts; + auto_vec known_aggs; /* When we do caching, use do_estimate_edge_time to populate the entry. */ @@ -347,9 +347,9 @@ do_estimate_edge_hints (struct cgraph_edge *edge) ipa_hints hints; struct cgraph_node *callee; clause_t clause, nonspec_clause; - vec known_vals; - vec known_contexts; - vec known_aggs; + auto_vec known_vals; + auto_vec known_contexts; + auto_vec known_aggs; /* When we do caching, use do_estimate_edge_time to populate the entry. */