From 40a777e840f74dd5c19ea26c55d1248a335fd11b Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Sun, 3 Nov 2019 23:32:56 +0100 Subject: [PATCH] Improve effectivity of ipa_polymorphi_context cache. * ipa-fnsummary.c (set_cond_stmt_execution_predicate, set_switch_stmt_execution_predicate, compute_bb_predicates, will_be_nonconstant_expr_predicate, phi_result_unknown_predicate, analyze_function_body): Pass arround params summary. (ipa_call_context::duplicate_from): New comment; only duplicate useful values. (ipa_call_context::equal_to): Only compare useful values. (remap_edge_summaries): Pass params_summary. (remap_hint_predicate): Likewise. (ipa_merge_fn_summary_after_inlining): Likewise. (inline_read_section): Initialize params summary used flags. * ipa-predicate.c (predicate::remap_after_inlining): Pass around param_summary. (add_condition): Initialized used params summary flags. * ipa-predicate.h (inline_param_summary::equals_to): Make const. (inline_param_summary::useless_p): New predicate. (remap_after_inlining, add_condition): Update prototype * ipa-prop.c (ipa_populate_param_decls): Watch overflow in move_cost. (ipa_note_param_call): Add parameter POLYMORPHIC; update params summaries. (ipa_analyze_indirect_call_uses): Update use of ipa_note_param_call. (ipa_analyze_virtual_call_uses): Likewise. (update_indirect_edges_after_inlining): Update param summaries. (ipa_print_node_params): Print used flags. (ipa_read_indirect_edge_info): Update param summareis. * ipa-prop.h (ipa_param_descriptor): Add used_by_ipa_predicates, used_by_indirect_call and used_by_polymorphic_call. (ipa_set_param_used_by_ipa_predicates, ipa_set_param_used_by_indirect_call, ipa_set_param_used_by_polymorphic_call, ipa_is_param_used_by_ipa_predicates, ipa_is_param_used_by_indirect_call, ipa_is_param_used_by_polymorphic_call): New inline functions. From-SVN: r277759 --- gcc/ChangeLog | 39 ++++++ gcc/ipa-fnsummary.c | 301 ++++++++++++++++++++++++++++++++------------ gcc/ipa-predicate.c | 10 +- gcc/ipa-predicate.h | 11 +- gcc/ipa-prop.c | 51 ++++++-- gcc/ipa-prop.h | 65 +++++++++- 6 files changed, 383 insertions(+), 94 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fdac1b2ca09..c108ac2108d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,42 @@ +2019-11-02 Jan Hubicka + + * ipa-fnsummary.c (set_cond_stmt_execution_predicate, + set_switch_stmt_execution_predicate, compute_bb_predicates, + will_be_nonconstant_expr_predicate, + phi_result_unknown_predicate, + analyze_function_body): Pass arround params summary. + (ipa_call_context::duplicate_from): New comment; + only duplicate useful values. + (ipa_call_context::equal_to): Only compare useful values. + (remap_edge_summaries): Pass params_summary. + (remap_hint_predicate): Likewise. + (ipa_merge_fn_summary_after_inlining): Likewise. + (inline_read_section): Initialize params summary used flags. + * ipa-predicate.c (predicate::remap_after_inlining): Pass + around param_summary. + (add_condition): Initialized used params summary flags. + * ipa-predicate.h (inline_param_summary::equals_to): Make const. + (inline_param_summary::useless_p): New predicate. + (remap_after_inlining, add_condition): Update prototype + * ipa-prop.c (ipa_populate_param_decls): Watch overflow in + move_cost. + (ipa_note_param_call): Add parameter POLYMORPHIC; update params + summaries. + (ipa_analyze_indirect_call_uses): Update use of ipa_note_param_call. + (ipa_analyze_virtual_call_uses): Likewise. + (update_indirect_edges_after_inlining): Update param summaries. + (ipa_print_node_params): Print used flags. + (ipa_read_indirect_edge_info): Update param summareis. + * ipa-prop.h (ipa_param_descriptor): Add + used_by_ipa_predicates, used_by_indirect_call + and used_by_polymorphic_call. + (ipa_set_param_used_by_ipa_predicates, + ipa_set_param_used_by_indirect_call, + ipa_set_param_used_by_polymorphic_call, + ipa_is_param_used_by_ipa_predicates, + ipa_is_param_used_by_indirect_call, + ipa_is_param_used_by_polymorphic_call): New inline functions. + 2019-11-02 Jan Hubicka * ipa-fnsummary.c (ipa_call_context::duplicate_from): New diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index eaf904cd401..4a3cb760a26 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -1312,6 +1312,7 @@ fail: static void set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, class ipa_fn_summary *summary, + class ipa_node_params *params_summary, basic_block bb) { gimple *last; @@ -1354,7 +1355,8 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, && !dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest)) { predicate p - = add_condition (summary, index, param_type, &aggpos, + = add_condition (summary, params_summary, index, + param_type, &aggpos, this_code, gimple_cond_rhs (last), param_ops); e->aux = edge_predicate_pool.allocate (); *(predicate *) e->aux = p; @@ -1387,7 +1389,8 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, return; FOR_EACH_EDGE (e, ei, bb->succs) if (e->flags & EDGE_FALSE_VALUE) { - predicate p = add_condition (summary, index, param_type, &aggpos, + predicate p = add_condition (summary, params_summary, index, + param_type, &aggpos, predicate::is_not_constant, NULL_TREE); e->aux = edge_predicate_pool.allocate (); *(predicate *) e->aux = p; @@ -1401,6 +1404,7 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, static void set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, class ipa_fn_summary *summary, + class ipa_node_params *params_summary, basic_block bb) { gimple *lastg; @@ -1470,15 +1474,15 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, if (dominated_by_p (CDI_POST_DOMINATORS, bb, e->dest)) p = true; else if (min == max) - p = add_condition (summary, index, param_type, &aggpos, EQ_EXPR, - min, param_ops); + p = add_condition (summary, params_summary, index, param_type, + &aggpos, EQ_EXPR, min, param_ops); else { predicate p1, p2; - p1 = add_condition (summary, index, param_type, &aggpos, GE_EXPR, - min, param_ops); - p2 = add_condition (summary, index, param_type, &aggpos, LE_EXPR, - max, param_ops); + p1 = add_condition (summary, params_summary, index, param_type, + &aggpos, GE_EXPR, min, param_ops); + p2 = add_condition (summary, params_summary,index, param_type, + &aggpos, LE_EXPR, max, param_ops); p = p1 & p2; } *(class predicate *) e->aux @@ -1559,7 +1563,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, tree max = ranges[i].second; if (min == max) - p_seg &= add_condition (summary, index, param_type, &aggpos, NE_EXPR, + p_seg &= add_condition (summary, params_summary, index, + param_type, &aggpos, NE_EXPR, min, param_ops); else { @@ -1567,7 +1572,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, of switch index. */ if (wi::lt_p (vr_wmin, wi::to_wide (min), TYPE_SIGN (type))) { - p_seg &= add_condition (summary, index, param_type, &aggpos, + p_seg &= add_condition (summary, params_summary, index, + param_type, &aggpos, LT_EXPR, min, param_ops); p_all = p_all.or_with (summary->conds, p_seg); } @@ -1580,7 +1586,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, break; } - p_seg = add_condition (summary, index, param_type, &aggpos, GT_EXPR, + p_seg = add_condition (summary, params_summary, index, + param_type, &aggpos, GT_EXPR, max, param_ops); } } @@ -1599,7 +1606,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, static void compute_bb_predicates (struct ipa_func_body_info *fbi, struct cgraph_node *node, - class ipa_fn_summary *summary) + class ipa_fn_summary *summary, + class ipa_node_params *params_summary) { struct function *my_function = DECL_STRUCT_FUNCTION (node->decl); bool done = false; @@ -1607,8 +1615,8 @@ compute_bb_predicates (struct ipa_func_body_info *fbi, FOR_EACH_BB_FN (bb, my_function) { - set_cond_stmt_execution_predicate (fbi, summary, bb); - set_switch_stmt_execution_predicate (fbi, summary, bb); + set_cond_stmt_execution_predicate (fbi, summary, params_summary, bb); + set_switch_stmt_execution_predicate (fbi, summary, params_summary, bb); } /* Entry block is always executable. */ @@ -1701,6 +1709,7 @@ compute_bb_predicates (struct ipa_func_body_info *fbi, static predicate will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, class ipa_fn_summary *summary, + class ipa_node_params *params_summary, tree expr, vec nonconstant_names) { @@ -1712,7 +1721,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, parm = unmodified_parm (fbi, NULL, expr, NULL); if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0) - return add_condition (summary, index, TREE_TYPE (parm), NULL, + return add_condition (summary, params_summary, index, TREE_TYPE (parm), NULL, predicate::changed, NULL_TREE); if (is_gimple_min_invariant (expr)) return false; @@ -1722,6 +1731,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, { predicate p1 = will_be_nonconstant_expr_predicate (fbi, summary, + params_summary, TREE_OPERAND (expr, 0), nonconstant_names); if (p1 == true) @@ -1729,6 +1739,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, predicate p2 = will_be_nonconstant_expr_predicate (fbi, summary, + params_summary, TREE_OPERAND (expr, 1), nonconstant_names); return p1.or_with (summary->conds, p2); @@ -1737,6 +1748,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, { predicate p1 = will_be_nonconstant_expr_predicate (fbi, summary, + params_summary, TREE_OPERAND (expr, 0), nonconstant_names); if (p1 == true) @@ -1744,12 +1756,14 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, predicate p2 = will_be_nonconstant_expr_predicate (fbi, summary, + params_summary, TREE_OPERAND (expr, 1), nonconstant_names); if (p2 == true) return p2; p1 = p1.or_with (summary->conds, p2); p2 = will_be_nonconstant_expr_predicate (fbi, summary, + params_summary, TREE_OPERAND (expr, 2), nonconstant_names); return p2.or_with (summary->conds, p1); @@ -1771,6 +1785,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, static predicate will_be_nonconstant_predicate (struct ipa_func_body_info *fbi, class ipa_fn_summary *summary, + class ipa_node_params *params_summary, gimple *stmt, vec nonconstant_names) { @@ -1828,7 +1843,8 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi, if (is_load) op_non_const = - add_condition (summary, base_index, param_type, &aggpos, + add_condition (summary, params_summary, + base_index, param_type, &aggpos, predicate::changed, NULL_TREE); else op_non_const = false; @@ -1840,7 +1856,8 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi, if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0) { if (index != base_index) - p = add_condition (summary, index, TREE_TYPE (parm), NULL, + p = add_condition (summary, params_summary, index, + TREE_TYPE (parm), NULL, predicate::changed, NULL_TREE); else continue; @@ -2027,7 +2044,9 @@ param_change_prob (ipa_func_body_info *fbi, gimple *stmt, int i) static bool phi_result_unknown_predicate (ipa_func_body_info *fbi, - ipa_fn_summary *summary, basic_block bb, + ipa_fn_summary *summary, + class ipa_node_params *params_summary, + basic_block bb, predicate *p, vec nonconstant_names) { @@ -2071,7 +2090,7 @@ phi_result_unknown_predicate (ipa_func_body_info *fbi, || !is_gimple_ip_invariant (gimple_cond_rhs (stmt))) return false; - *p = will_be_nonconstant_expr_predicate (fbi, summary, + *p = will_be_nonconstant_expr_predicate (fbi, summary, params_summary, gimple_cond_lhs (stmt), nonconstant_names); if (*p == true) @@ -2264,6 +2283,7 @@ analyze_function_body (struct cgraph_node *node, bool early) struct function *my_function = DECL_STRUCT_FUNCTION (node->decl); sreal freq; class ipa_fn_summary *info = ipa_fn_summaries->get_create (node); + class ipa_node_params *params_summary = early ? NULL : IPA_NODE_REF (node); predicate bb_predicate; struct ipa_func_body_info fbi; vec nonconstant_names = vNULL; @@ -2329,7 +2349,7 @@ analyze_function_body (struct cgraph_node *node, bool early) bb_predicate); if (fbi.info) - compute_bb_predicates (&fbi, node, info); + compute_bb_predicates (&fbi, node, info, params_summary); order = XNEWVEC (int, n_basic_blocks_for_fn (cfun)); nblocks = pre_and_rev_post_order_compute (NULL, order, false); for (n = 0; n < nblocks; n++) @@ -2371,7 +2391,9 @@ analyze_function_body (struct cgraph_node *node, bool early) gsi_next (&bsi)) { if (first_phi - && !phi_result_unknown_predicate (&fbi, info, bb, + && !phi_result_unknown_predicate (&fbi, info, + params_summary, + bb, &phi_predicate, nonconstant_names)) break; @@ -2469,7 +2491,7 @@ analyze_function_body (struct cgraph_node *node, bool early) just maximum of the possible paths. */ if (fbi.info) will_be_nonconstant - = will_be_nonconstant_predicate (&fbi, info, + = will_be_nonconstant_predicate (&fbi, info, params_summary, stmt, nonconstant_names); else will_be_nonconstant = true; @@ -2536,7 +2558,8 @@ analyze_function_body (struct cgraph_node *node, bool early) predicate p = bb_predicate; if (fbi.info) p = p & will_be_nonconstant_expr_predicate - (&fbi, info, TREE_OPERAND (op, 1), + (&fbi, info, params_summary, + TREE_OPERAND (op, 1), nonconstant_names); if (p != false) { @@ -2581,6 +2604,7 @@ analyze_function_body (struct cgraph_node *node, bool early) { predicate will_be_nonconstant = will_be_nonconstant_expr_predicate (&fbi, info, + params_summary, niter_desc.niter, nonconstant_names); if (will_be_nonconstant != true) @@ -2625,7 +2649,9 @@ analyze_function_body (struct cgraph_node *node, bool early) continue; predicate will_be_nonconstant - = will_be_nonconstant_expr_predicate (&fbi, info, iv.step, + = will_be_nonconstant_expr_predicate (&fbi, info, + params_summary, + iv.step, nonconstant_names); if (will_be_nonconstant != true) will_be_nonconstant = bb_predicate & will_be_nonconstant; @@ -2964,29 +2990,73 @@ ipa_call_context::ipa_call_context (cgraph_node *node, { } +/* Set THIS to be a duplicate of CTX. Copy all relevant info. */ + void ipa_call_context::duplicate_from (const ipa_call_context &ctx) { m_node = ctx.m_node; m_possible_truths = ctx.m_possible_truths; m_nonspec_possible_truths = ctx.m_nonspec_possible_truths; + class ipa_node_params *params_summary = IPA_NODE_REF (m_node); + unsigned int nargs = ipa_get_param_count (params_summary); + m_inline_param_summary = vNULL; + /* Copy the info only if there is at least one useful entry. */ if (ctx.m_inline_param_summary.exists ()) - m_inline_param_summary = ctx.m_inline_param_summary.copy (); - else - m_inline_param_summary = vNULL; + { + unsigned int n = MIN (ctx.m_inline_param_summary.length (), nargs); + + for (unsigned int i = 0; i < n; i++) + if (ipa_is_param_used_by_ipa_predicates (params_summary, i) + && !ctx.m_inline_param_summary[i].useless_p ()) + { + m_inline_param_summary + = ctx.m_inline_param_summary.copy (); + break; + } + } + m_known_vals = vNULL; if (ctx.m_known_vals.exists ()) - m_known_vals = ctx.m_known_vals.copy (); - else - m_known_vals = vNULL; + { + unsigned int n = MIN (ctx.m_known_vals.length (), nargs); + + for (unsigned int i = 0; i < n; i++) + if (ipa_is_param_used_by_indirect_call (params_summary, i) + && ctx.m_known_vals[i]) + { + m_known_vals = ctx.m_known_vals.copy (); + break; + } + } + + m_known_contexts = vNULL; if (ctx.m_known_contexts.exists ()) - m_known_contexts = ctx.m_known_contexts.copy (); - else - m_known_contexts = vNULL; + { + unsigned int n = MIN (ctx.m_known_contexts.length (), nargs); + + for (unsigned int i = 0; i < n; i++) + if (ipa_is_param_used_by_polymorphic_call (params_summary, i) + && !ctx.m_known_contexts[i].useless_p ()) + { + m_known_contexts = ctx.m_known_contexts.copy (); + break; + } + } + + m_known_aggs = vNULL; if (ctx.m_known_aggs.exists ()) - m_known_aggs = ctx.m_known_aggs.copy (); - else - m_known_aggs = vNULL; + { + unsigned int n = MIN (ctx.m_known_aggs.length (), nargs); + + for (unsigned int i = 0; i < n; i++) + if (ipa_is_param_used_by_indirect_call (params_summary, i) + && ctx.m_known_aggs[i]) + { + m_known_aggs = ctx.m_known_aggs.copy (); + break; + } + } } /* Release memory used by known_vals/contexts/aggs vectors. @@ -3016,49 +3086,107 @@ ipa_call_context::equal_to (const ipa_call_context &ctx) || m_possible_truths != ctx.m_possible_truths || m_nonspec_possible_truths != ctx.m_nonspec_possible_truths) return false; - if (m_inline_param_summary.exists () != ctx.m_inline_param_summary.exists () - || m_known_vals.exists () != ctx.m_known_vals.exists() - || m_known_contexts.exists () != ctx.m_known_contexts.exists () - || m_known_aggs.exists () != ctx.m_known_aggs.exists ()) - return false; - if (m_inline_param_summary.exists ()) + + class ipa_node_params *params_summary = IPA_NODE_REF (m_node); + unsigned int nargs = ipa_get_param_count (params_summary); + + if (m_inline_param_summary.exists () || ctx.m_inline_param_summary.exists ()) { - if (m_inline_param_summary.length () != ctx.m_inline_param_summary.length ()) - return false; - for (unsigned int i = 0; i < m_inline_param_summary.length (); i++) - if (!m_inline_param_summary[i].equal_to (ctx.m_inline_param_summary[i])) - return false; + for (unsigned int i = 0; i < nargs; i++) + { + if (!ipa_is_param_used_by_ipa_predicates (params_summary, i)) + continue; + if (i >= m_inline_param_summary.length () + || m_inline_param_summary[i].useless_p ()) + { + if (i < ctx.m_inline_param_summary.length () + && !ctx.m_inline_param_summary[i].useless_p ()) + return false; + continue; + } + if (i >= ctx.m_inline_param_summary.length () + || ctx.m_inline_param_summary[i].useless_p ()) + { + if (i < m_inline_param_summary.length () + && !m_inline_param_summary[i].useless_p ()) + return false; + continue; + } + if (!m_inline_param_summary[i].equal_to + (ctx.m_inline_param_summary[i])) + return false; + } } - if (m_known_vals.exists ()) + if (m_known_vals.exists () || ctx.m_known_vals.exists ()) { - if (m_known_vals.length () != ctx.m_known_vals.length ()) - return false; - for (unsigned int i = 0; i < m_known_vals.length (); i++) + for (unsigned int i = 0; i < nargs; i++) { - tree t1 = m_known_vals[i]; - tree t2 = ctx.m_known_vals[i]; - - if (t1 != t2 - && (!t1 || !t2 || !operand_equal_p (m_known_vals[i], - ctx.m_known_vals[i], 0))) + if (!ipa_is_param_used_by_indirect_call (params_summary, i)) + continue; + if (i >= m_known_vals.length () || !m_known_vals[i]) + { + if (i < ctx.m_known_vals.length () && ctx.m_known_vals[i]) + return false; + continue; + } + if (i >= ctx.m_known_vals.length () || !ctx.m_known_vals[i]) + { + if (i < m_known_vals.length () && m_known_vals[i]) + return false; + continue; + } + if (m_known_vals[i] != ctx.m_known_vals[i]) return false; } } - if (m_known_contexts.exists ()) + if (m_known_contexts.exists () || ctx.m_known_contexts.exists ()) { - if (m_known_contexts.length () != ctx.m_known_contexts.length ()) - return false; - for (unsigned int i = 0; i < m_known_contexts.length (); i++) - if (!m_known_contexts[i].equal_to (ctx.m_known_contexts[i])) - return false; + for (unsigned int i = 0; i < nargs; i++) + { + if (!ipa_is_param_used_by_polymorphic_call (params_summary, i)) + continue; + if (i >= m_known_contexts.length () + || m_known_contexts[i].useless_p ()) + { + if (i < ctx.m_known_contexts.length () + && !ctx.m_known_contexts[i].useless_p ()) + return false; + continue; + } + if (i >= ctx.m_known_contexts.length () + || ctx.m_known_contexts[i].useless_p ()) + { + if (i < m_known_contexts.length () + && !m_known_contexts[i].useless_p ()) + return false; + continue; + } + if (!m_known_contexts[i].equal_to + (ctx.m_known_contexts[i])) + return false; + } } - if (m_known_aggs.exists ()) + if (m_known_aggs.exists () || ctx.m_known_aggs.exists ()) { - if (m_known_aggs.length () != ctx.m_known_aggs.length ()) - return false; - for (unsigned int i = 0; i < m_known_aggs.length (); i++) - if (!m_known_aggs[i]->equal_to (*ctx.m_known_aggs[i])) - return false; + for (unsigned int i = 0; i < nargs; i++) + { + if (!ipa_is_param_used_by_indirect_call (params_summary, i)) + continue; + if (i >= m_known_aggs.length () || !m_known_aggs[i]) + { + if (i < ctx.m_known_aggs.length () && ctx.m_known_aggs[i]) + return false; + continue; + } + if (i >= ctx.m_known_aggs.length () || !ctx.m_known_aggs[i]) + { + if (i < m_known_aggs.length () && m_known_aggs[i]) + return false; + continue; + } + if (m_known_aggs[i] != ctx.m_known_aggs[i]) + return false; + } } return true; } @@ -3319,6 +3447,7 @@ static void remap_edge_summaries (struct cgraph_edge *inlined_edge, struct cgraph_node *node, class ipa_fn_summary *info, + class ipa_node_params *params_summary, class ipa_fn_summary *callee_info, vec operand_map, vec offset_map, @@ -3339,7 +3468,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, if (es->predicate) { p = es->predicate->remap_after_inlining - (info, callee_info, operand_map, + (info, params_summary, + callee_info, operand_map, offset_map, possible_truths, *toplev_predicate); edge_set_predicate (e, &p); @@ -3348,7 +3478,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, edge_set_predicate (e, toplev_predicate); } else - remap_edge_summaries (inlined_edge, e->callee, info, callee_info, + remap_edge_summaries (inlined_edge, e->callee, info, + params_summary, callee_info, operand_map, offset_map, possible_truths, toplev_predicate); } @@ -3362,7 +3493,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, if (es->predicate) { p = es->predicate->remap_after_inlining - (info, callee_info, operand_map, offset_map, + (info, params_summary, + callee_info, operand_map, offset_map, possible_truths, *toplev_predicate); edge_set_predicate (e, &p); } @@ -3375,6 +3507,7 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, static void remap_hint_predicate (class ipa_fn_summary *info, + class ipa_node_params *params_summary, class ipa_fn_summary *callee_info, predicate **hint, vec operand_map, @@ -3387,7 +3520,7 @@ remap_hint_predicate (class ipa_fn_summary *info, if (!*hint) return; p = (*hint)->remap_after_inlining - (info, callee_info, + (info, params_summary, callee_info, operand_map, offset_map, possible_truths, *toplev_predicate); if (p != false && p != true) @@ -3415,6 +3548,8 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) int i; predicate toplev_predicate; class ipa_call_summary *es = ipa_call_summaries->get (edge); + class ipa_node_params *params_summary = (ipa_node_params_sum + ? IPA_NODE_REF (to) : NULL); if (es->predicate) toplev_predicate = *es->predicate; @@ -3461,19 +3596,21 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) } } operand_map[i] = map; - gcc_assert (map < ipa_get_param_count (IPA_NODE_REF (to))); + gcc_assert (map < ipa_get_param_count (params_summary)); } } for (i = 0; vec_safe_iterate (callee_info->size_time_table, i, &e); i++) { predicate p; p = e->exec_predicate.remap_after_inlining - (info, callee_info, operand_map, + (info, params_summary, + callee_info, operand_map, offset_map, clause, toplev_predicate); predicate nonconstp; nonconstp = e->nonconst_predicate.remap_after_inlining - (info, callee_info, operand_map, + (info, params_summary, + callee_info, operand_map, offset_map, clause, toplev_predicate); if (p != false && nonconstp != false) @@ -3491,12 +3628,13 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) info->account_size_time (e->size, add_time, p, nonconstp); } } - remap_edge_summaries (edge, edge->callee, info, callee_info, operand_map, + remap_edge_summaries (edge, edge->callee, info, params_summary, + callee_info, operand_map, offset_map, clause, &toplev_predicate); - remap_hint_predicate (info, callee_info, + remap_hint_predicate (info, params_summary, callee_info, &callee_info->loop_iterations, operand_map, offset_map, clause, &toplev_predicate); - remap_hint_predicate (info, callee_info, + remap_hint_predicate (info, params_summary, callee_info, &callee_info->loop_stride, operand_map, offset_map, clause, &toplev_predicate); @@ -3687,6 +3825,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, unsigned int index; struct cgraph_node *node; class ipa_fn_summary *info; + class ipa_node_params *params_summary; class ipa_size_summary *size_info; lto_symtab_encoder_t encoder; struct bitpack_d bp; @@ -3698,6 +3837,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, node = dyn_cast (lto_symtab_encoder_deref (encoder, index)); info = node->prevailing_p () ? ipa_fn_summaries->get_create (node) : NULL; + params_summary = node->prevailing_p () ? IPA_NODE_REF (node) : NULL; size_info = node->prevailing_p () ? ipa_size_summaries->get_create (node) : NULL; @@ -3746,6 +3886,9 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, c.param_ops = NULL; if (info) vec_safe_reserve_exact (c.param_ops, count3); + if (params_summary) + ipa_set_param_used_by_ipa_predicates + (params_summary, c.operand_num, true); for (k = 0; k < count3; k++) { struct expr_eval_op op; diff --git a/gcc/ipa-predicate.c b/gcc/ipa-predicate.c index b5e3cf44323..721f0957f9f 100644 --- a/gcc/ipa-predicate.c +++ b/gcc/ipa-predicate.c @@ -505,6 +505,7 @@ predicate::remap_after_duplication (clause_t possible_truths) predicate predicate::remap_after_inlining (class ipa_fn_summary *info, + class ipa_node_params *params_summary, class ipa_fn_summary *callee_info, vec operand_map, vec offset_map, @@ -566,7 +567,7 @@ predicate::remap_after_inlining (class ipa_fn_summary *info, ap.offset = c->offset + offset_delta; ap.agg_contents = c->agg_contents; ap.by_ref = c->by_ref; - cond_predicate = add_condition (info, + cond_predicate = add_condition (info, params_summary, operand_map[c->operand_num], c->type, &ap, c->code, c->val, c->param_ops); @@ -629,7 +630,9 @@ predicate::stream_out (struct output_block *ob) aggregate. */ predicate -add_condition (class ipa_fn_summary *summary, int operand_num, +add_condition (class ipa_fn_summary *summary, + class ipa_node_params *params_summary, + int operand_num, tree type, struct agg_position_info *aggpos, enum tree_code code, tree val, expr_eval_ops param_ops) { @@ -640,6 +643,9 @@ add_condition (class ipa_fn_summary *summary, int operand_num, bool agg_contents, by_ref; expr_eval_op *op; + if (params_summary) + ipa_set_param_used_by_ipa_predicates (params_summary, operand_num, true); + if (aggpos) { offset = aggpos->offset; diff --git a/gcc/ipa-predicate.h b/gcc/ipa-predicate.h index 2509b1e5162..25cd5f2797d 100644 --- a/gcc/ipa-predicate.h +++ b/gcc/ipa-predicate.h @@ -77,10 +77,14 @@ struct inline_param_summary Value 0 is reserved for compile time invariants. */ int change_prob; - bool equal_to (const inline_param_summary &other) + bool equal_to (const inline_param_summary &other) const { return change_prob == other.change_prob; } + bool useless_p (void) const + { + return change_prob == REG_BR_PROB_BASE; + } }; typedef vec *conditions; @@ -233,6 +237,7 @@ public: /* Return predicate equal to THIS after inlining. */ predicate remap_after_inlining (class ipa_fn_summary *, + class ipa_node_params *params_summary, class ipa_fn_summary *, vec, vec, clause_t, const predicate &); @@ -254,7 +259,9 @@ private: }; void dump_condition (FILE *f, conditions conditions, int cond); -predicate add_condition (class ipa_fn_summary *summary, int operand_num, +predicate add_condition (class ipa_fn_summary *summary, + class ipa_node_params *params_summary, + int operand_num, tree type, struct agg_position_info *aggpos, enum tree_code code, tree val, expr_eval_ops param_ops = NULL); diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 5491aee2fc6..83cf4d1c7ba 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -227,8 +227,10 @@ ipa_populate_param_decls (struct cgraph_node *node, for (parm = fnargs; parm; parm = DECL_CHAIN (parm)) { descriptors[param_num].decl_or_type = parm; - descriptors[param_num].move_cost = estimate_move_cost (TREE_TYPE (parm), - true); + unsigned int cost = estimate_move_cost (TREE_TYPE (parm), true); + descriptors[param_num].move_cost = cost; + /* Watch overflow, move_cost is a bitfield. */ + gcc_checking_assert (cost == descriptors[param_num].move_cost); param_num++; } } @@ -2116,11 +2118,12 @@ ipa_is_ssa_with_stmt_def (tree t) /* Find the indirect call graph edge corresponding to STMT and mark it as a call to a parameter number PARAM_INDEX. NODE is the caller. Return the - indirect call graph edge. */ + indirect call graph edge. + If POLYMORPHIC is true record is as a destination of polymorphic call. */ static struct cgraph_edge * ipa_note_param_call (struct cgraph_node *node, int param_index, - gcall *stmt) + gcall *stmt, bool polymorphic) { struct cgraph_edge *cs; @@ -2129,6 +2132,11 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, cs->indirect_info->agg_contents = 0; cs->indirect_info->member_ptr = 0; cs->indirect_info->guaranteed_unmodified = 0; + ipa_set_param_used_by_indirect_call (IPA_NODE_REF (node), + param_index, true); + if (cs->indirect_info->polymorphic || polymorphic) + ipa_set_param_used_by_polymorphic_call + (IPA_NODE_REF (node), param_index, true); return cs; } @@ -2204,7 +2212,7 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call, tree var = SSA_NAME_VAR (target); int index = ipa_get_param_decl_index (info, var); if (index >= 0) - ipa_note_param_call (fbi->node, index, call); + ipa_note_param_call (fbi->node, index, call, false); return; } @@ -2216,7 +2224,8 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call, gimple_assign_rhs1 (def), &index, &offset, NULL, &by_ref, &guaranteed_unmodified)) { - struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call); + struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, + call, false); cs->indirect_info->offset = offset; cs->indirect_info->agg_contents = 1; cs->indirect_info->by_ref = by_ref; @@ -2317,7 +2326,8 @@ ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call, if (index >= 0 && parm_preserved_before_stmt_p (fbi, index, call, rec)) { - struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call); + struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, + call, false); cs->indirect_info->offset = offset; cs->indirect_info->agg_contents = 1; cs->indirect_info->member_ptr = 1; @@ -2377,7 +2387,8 @@ ipa_analyze_virtual_call_uses (struct ipa_func_body_info *fbi, return; } - struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call); + struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, + call, true); class cgraph_indirect_call_info *ii = cs->indirect_info; ii->offset = anc_offset; ii->otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target)); @@ -3510,6 +3521,11 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs, if (ici->polymorphic && !ipa_get_jf_pass_through_type_preserved (jfunc)) ici->vptr_changed = true; + ipa_set_param_used_by_indirect_call (new_root_info, + ici->param_index, true); + if (ici->polymorphic) + ipa_set_param_used_by_polymorphic_call (new_root_info, + ici->param_index, true); } } else if (jfunc->type == IPA_JF_ANCESTOR) @@ -4055,6 +4071,12 @@ ipa_print_node_params (FILE *f, struct cgraph_node *node) ipa_dump_param (f, info, i); if (ipa_is_param_used (info, i)) fprintf (f, " used"); + if (ipa_is_param_used_by_ipa_predicates (info, i)) + fprintf (f, " used_by_ipa_predicates"); + if (ipa_is_param_used_by_indirect_call (info, i)) + fprintf (f, " used_by_indirect_call"); + if (ipa_is_param_used_by_polymorphic_call (info, i)) + fprintf (f, " used_by_polymorphic_call"); c = ipa_get_controlled_uses (info, i); if (c == IPA_UNDESCRIBED_USE) fprintf (f, " undescribed_use"); @@ -4331,7 +4353,8 @@ ipa_write_indirect_edge_info (struct output_block *ob, static void ipa_read_indirect_edge_info (class lto_input_block *ib, class data_in *data_in, - struct cgraph_edge *cs) + struct cgraph_edge *cs, + class ipa_node_params *info) { class cgraph_indirect_call_info *ii = cs->indirect_info; struct bitpack_d bp; @@ -4354,6 +4377,14 @@ ipa_read_indirect_edge_info (class lto_input_block *ib, ii->otr_type = stream_read_tree (ib, data_in); ii->context.stream_in (ib, data_in); } + if (info && ii->param_index >= 0) + { + if (ii->polymorphic) + ipa_set_param_used_by_polymorphic_call (info, + ii->param_index , true); + ipa_set_param_used_by_indirect_call (info, + ii->param_index, true); + } } /* Stream out NODE info to OB. */ @@ -4523,7 +4554,7 @@ ipa_read_node_info (class lto_input_block *ib, struct cgraph_node *node, for (e = node->indirect_calls; e; e = e->next_callee) { ipa_read_edge_info (ib, data_in, e, prevails); - ipa_read_indirect_edge_info (ib, data_in, e); + ipa_read_indirect_edge_info (ib, data_in, e, info); } } diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 121d0f647b1..9f2479e7fdc 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -333,9 +333,12 @@ struct GTY(()) ipa_param_descriptor says how many there are. If any use could not be described by means of ipa-prop structures, this is IPA_UNDESCRIBED_USE. */ int controlled_uses; - unsigned int move_cost : 31; + unsigned int move_cost : 28; /* The parameter is used. */ unsigned used : 1; + unsigned used_by_ipa_predicates : 1; + unsigned used_by_indirect_call : 1; + unsigned used_by_polymorphic_call : 1; }; /* ipa_node_params stores information related to formal parameters of functions @@ -519,6 +522,36 @@ ipa_set_param_used (class ipa_node_params *info, int i, bool val) (*info->descriptors)[i].used = val; } +/* Set the used_by_ipa_predicates flag corresponding to the Ith formal + parameter of the function associated with INFO to VAL. */ + +static inline void +ipa_set_param_used_by_ipa_predicates (class ipa_node_params *info, int i, bool val) +{ + gcc_checking_assert (info->descriptors); + (*info->descriptors)[i].used_by_ipa_predicates = val; +} + +/* Set the used_by_indirect_call flag corresponding to the Ith formal + parameter of the function associated with INFO to VAL. */ + +static inline void +ipa_set_param_used_by_indirect_call (class ipa_node_params *info, int i, bool val) +{ + gcc_checking_assert (info->descriptors); + (*info->descriptors)[i].used_by_indirect_call = val; +} + +/* Set the .used_by_polymorphic_call flag corresponding to the Ith formal + parameter of the function associated with INFO to VAL. */ + +static inline void +ipa_set_param_used_by_polymorphic_call (class ipa_node_params *info, int i, bool val) +{ + gcc_checking_assert (info->descriptors); + (*info->descriptors)[i].used_by_polymorphic_call = val; +} + /* Return how many uses described by ipa-prop a parameter has or IPA_UNDESCRIBED_USE if there is a use that is not described by these structures. */ @@ -550,6 +583,36 @@ ipa_is_param_used (class ipa_node_params *info, int i) return (*info->descriptors)[i].used; } +/* Return the used_by_ipa_predicates flag corresponding to the Ith formal + parameter of the function associated with INFO. */ + +static inline bool +ipa_is_param_used_by_ipa_predicates (class ipa_node_params *info, int i) +{ + gcc_checking_assert (info->descriptors); + return (*info->descriptors)[i].used_by_ipa_predicates; +} + +/* Return the used_by_indirect_call flag corresponding to the Ith formal + parameter of the function associated with INFO. */ + +static inline bool +ipa_is_param_used_by_indirect_call (class ipa_node_params *info, int i) +{ + gcc_checking_assert (info->descriptors); + return (*info->descriptors)[i].used_by_indirect_call; +} + +/* Return the used_by_polymorphic_call flag corresponding to the Ith formal + parameter of the function associated with INFO. */ + +static inline bool +ipa_is_param_used_by_polymorphic_call (class ipa_node_params *info, int i) +{ + gcc_checking_assert (info->descriptors); + return (*info->descriptors)[i].used_by_polymorphic_call; +} + /* Information about replacements done in aggregates for a given node (each node has its linked list). */ struct GTY(()) ipa_agg_replacement_value -- 2.30.2