From 6cf67b62c8cda035dccaca2ae6ff94d560b37a6f Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Sun, 10 Nov 2019 12:25:38 +0100 Subject: [PATCH] cgraph.h (struct cgraph_node): Add ipcp_clone flag. * cgraph.h (struct cgraph_node): Add ipcp_clone flag. (cgraph_node::create_virtual_clone): Copy it. * ipa-cp.c (ipcp_versionable_function_p): Watch for missing summaries. (ignore_edge_p): If caller has ipa-cp disabled, skip the edge, too. (ipcp_verify_propagated_values): Do not verify nodes where ipcp is disabled. (propagate_constants_across_call): If callee is not analyzed, give up. (propagate_constants_topo): Lower to bottom latties of all callees of functions with ipa-cp disabled. (ipcp_propagate_stage): Skip functions with ipa-cp disabled. (cgraph_edge_brings_value_p): Check for availability first. (create_specialized_node): Set ipcp_clone. (ipcp_store_bits_results): Check that info is present. * ipa-fnsummary.c (evaluate_properties_for_edge): Do not analyze thunks. (ipa_call_context::duplicate_from, ipa_call_context::equal_to): Be conservative when callee summary is missing. (remap_edge_summaries): Lookup call summary only when needed. * ipa-icf.c (sem_function::param_used_p): Be ready for missing summary. * ipa-prpo.c (ipa_alloc_node_params, ipa_initialize_node_params): Use get_create. (ipa_analyze_node): Use get_create. (propagate_controlled_uses): Do not propagate when function is not analyzed. (ipa_propagate_indirect_call_infos): Remove summary of inline clone. (ipa_read_node_info): Use get_create. * ipa-prop.h (IPA_NODE_REF): Use get. (IPA_NODE_REF_GET_CREATE): New. From-SVN: r278016 --- gcc/ChangeLog | 32 ++++++++++++++++++++ gcc/cgraph.h | 2 ++ gcc/cgraphclones.c | 1 + gcc/ipa-cp.c | 42 ++++++++++++++++++-------- gcc/ipa-fnsummary.c | 73 ++++++++++++++++++++++++--------------------- gcc/ipa-icf.c | 2 +- gcc/ipa-prop.c | 17 +++++++---- gcc/ipa-prop.h | 3 +- 8 files changed, 118 insertions(+), 54 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eb80b71668d..280f8780434 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +2019-11-09 Jan Hubicka + + * cgraph.h (struct cgraph_node): Add ipcp_clone flag. + (cgraph_node::create_virtual_clone): Copy it. + * ipa-cp.c (ipcp_versionable_function_p): Watch for missing + summaries. + (ignore_edge_p): If caller has ipa-cp disabled, skip the edge, too. + (ipcp_verify_propagated_values): Do not verify nodes where ipcp + is disabled. + (propagate_constants_across_call): If callee is not analyzed, give up. + (propagate_constants_topo): Lower to bottom latties of all callees of + functions with ipa-cp disabled. + (ipcp_propagate_stage): Skip functions with ipa-cp disabled. + (cgraph_edge_brings_value_p): Check for availability first. + (create_specialized_node): Set ipcp_clone. + (ipcp_store_bits_results): Check that info is present. + * ipa-fnsummary.c (evaluate_properties_for_edge): Do not analyze + thunks. + (ipa_call_context::duplicate_from, ipa_call_context::equal_to): Be + conservative when callee summary is missing. + (remap_edge_summaries): Lookup call summary only when needed. + * ipa-icf.c (sem_function::param_used_p): Be ready for missing summary. + * ipa-prpo.c (ipa_alloc_node_params, ipa_initialize_node_params): + Use get_create. + (ipa_analyze_node): Use get_create. + (propagate_controlled_uses): Do not propagate when function is not + analyzed. + (ipa_propagate_indirect_call_infos): Remove summary of inline clone. + (ipa_read_node_info): Use get_create. + * ipa-prop.h (IPA_NODE_REF): Use get. + (IPA_NODE_REF_GET_CREATE): New. + 2019-11-09 Jan Hubicka * ipa-fnsummary.c (evaluate_properties_for_edge): Call IPA_NODE_REF diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 0abde3d8f91..a4f14743f00 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1484,6 +1484,8 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node unsigned redefined_extern_inline : 1; /* True if the function may enter serial irrevocable mode. */ unsigned tm_may_enter_irr : 1; + /* True if this was a clone created by ipa-cp. */ + unsigned ipcp_clone : 1; private: /* Unique id of the node. */ diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c index 41a600e64a5..bfcebb20495 100644 --- a/gcc/cgraphclones.c +++ b/gcc/cgraphclones.c @@ -570,6 +570,7 @@ cgraph_node::create_virtual_clone (vec redirect_callers, ??? We cannot use COMDAT linkage because there is no ABI support for this. */ set_new_clone_decl_and_node_flags (new_node); + new_node->ipcp_clone = ipcp_clone; new_node->clone.tree_map = tree_map; if (!implicit_section) new_node->set_section (get_section ()); diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index c6bd265f593..b1d899976e8 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -656,7 +656,7 @@ determine_versionability (struct cgraph_node *node, static bool ipcp_versionable_function_p (struct cgraph_node *node) { - return IPA_NODE_REF (node)->versionable; + return IPA_NODE_REF (node) && IPA_NODE_REF (node)->versionable; } /* Structure holding accumulated information about callers of a node. */ @@ -817,6 +817,7 @@ ignore_edge_p (cgraph_edge *e) = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller); return (avail <= AVAIL_INTERPOSABLE + || !opt_for_fn (e->caller->decl, flag_ipa_cp) || !opt_for_fn (ultimate_target->decl, flag_ipa_cp)); } @@ -1471,6 +1472,8 @@ ipcp_verify_propagated_values (void) FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) { class ipa_node_params *info = IPA_NODE_REF (node); + if (!opt_for_fn (node->decl, flag_ipa_cp)) + continue; int i, count = ipa_get_param_count (info); for (i = 0; i < count; i++) @@ -2307,6 +2310,8 @@ propagate_constants_across_call (struct cgraph_edge *cs) return false; gcc_checking_assert (callee->has_gimple_body_p ()); callee_info = IPA_NODE_REF (callee); + if (!callee_info) + return false; args = IPA_EDGE_REF (cs); parms_count = ipa_get_param_count (callee_info); @@ -3233,7 +3238,17 @@ propagate_constants_topo (class ipa_topo_info *topo) until all lattices stabilize. */ FOR_EACH_VEC_ELT (cycle_nodes, j, v) if (v->has_gimple_body_p ()) - push_node_to_stack (topo, v); + { + if (opt_for_fn (v->decl, flag_ipa_cp)) + push_node_to_stack (topo, v); + /* When V is not optimized, we can not push it to stac, but + still we need to set all its callees lattices to bottom. */ + else + { + for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee) + propagate_constants_across_call (cs); + } + } v = pop_node_from_stack (topo); while (v) @@ -3254,7 +3269,8 @@ propagate_constants_topo (class ipa_topo_info *topo) the local effects of the discovered constants and all valid values to their topological sort. */ FOR_EACH_VEC_ELT (cycle_nodes, j, v) - if (v->has_gimple_body_p ()) + if (v->has_gimple_body_p () + && opt_for_fn (v->decl, flag_ipa_cp)) { struct cgraph_edge *cs; @@ -3333,11 +3349,10 @@ ipcp_propagate_stage (class ipa_topo_info *topo) FOR_EACH_DEFINED_FUNCTION (node) { - class ipa_node_params *info = IPA_NODE_REF (node); - - determine_versionability (node, info); - if (node->has_gimple_body_p ()) + if (node->has_gimple_body_p () && opt_for_fn (node->decl, flag_ipa_cp)) { + class ipa_node_params *info = IPA_NODE_REF (node); + determine_versionability (node, info); info->lattices = XCNEWVEC (class ipcp_param_lattices, ipa_get_param_count (info)); initialize_node_lattices (node); @@ -3526,8 +3541,8 @@ cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source *src, enum availability availability; cgraph_node *real_dest = cs->callee->function_symbol (&availability); - if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) - || availability <= AVAIL_INTERPOSABLE + if (availability <= AVAIL_INTERPOSABLE + || !same_node_or_its_all_contexts_clone_p (real_dest, dest) || caller_info->node_dead) return false; @@ -3583,9 +3598,11 @@ cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value *) { class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); - cgraph_node *real_dest = cs->callee->function_symbol (); + enum availability avail; + cgraph_node *real_dest = cs->callee->function_symbol (&avail); - if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) + if (avail <= AVAIL_INTERPOSABLE + || !same_node_or_its_all_contexts_clone_p (real_dest, dest) || caller_info->node_dead) return false; if (!src->val) @@ -4018,6 +4035,7 @@ create_specialized_node (struct cgraph_node *node, update_profiling_info (node, new_node); new_info = IPA_NODE_REF (new_node); new_info->ipcp_orig_node = node; + new_node->ipcp_clone = true; new_info->known_csts = known_csts; new_info->known_contexts = known_contexts; @@ -5053,7 +5071,7 @@ ipcp_store_bits_results (void) bool dumped_sth = false; bool found_useful_result = false; - if (!opt_for_fn (node->decl, flag_ipa_bit_cp)) + if (!opt_for_fn (node->decl, flag_ipa_bit_cp) || !info) { if (dump_file) fprintf (dump_file, "Not considering %s for ipa bitwise propagation " diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index 7b8182766ee..686d960f75b 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -483,36 +483,39 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, if (count && known_contexts_ptr) known_contexts_ptr->safe_grow_cleared (count); - 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)) - { - 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.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); - /* TODO: When IPA-CP starts propagating and merging aggregate jump - functions, use its knowledge of the caller too, just like the - scalar case above. */ - known_aggs[i] = &jf->agg; - } + 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)) + { + 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.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); + /* TODO: When IPA-CP starts propagating and merging aggregate jump + functions, use its knowledge of the caller too, just like the + scalar case above. */ + known_aggs[i] = &jf->agg; + } + else + gcc_assert (callee->thunk.thunk_p); } else if (e->call_stmt && !e->call_stmt_cannot_inline_p && ((clause_ptr && info->conds) || known_vals_ptr)) @@ -3004,7 +3007,8 @@ ipa_call_context::duplicate_from (const ipa_call_context &ctx) 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); + unsigned int nargs = params_summary + ? ipa_get_param_count (params_summary) : 0; m_inline_param_summary = vNULL; /* Copy the info only if there is at least one useful entry. */ @@ -3093,7 +3097,8 @@ ipa_call_context::equal_to (const ipa_call_context &ctx) return false; class ipa_node_params *params_summary = IPA_NODE_REF (m_node); - unsigned int nargs = ipa_get_param_count (params_summary); + unsigned int nargs = params_summary + ? ipa_get_param_count (params_summary) : 0; if (m_inline_param_summary.exists () || ctx.m_inline_param_summary.exists ()) { @@ -3404,7 +3409,7 @@ inline_update_callee_summaries (struct cgraph_node *node, int depth) } /* Update change_prob of EDGE after INLINED_EDGE has been inlined. - When functoin A is inlined in B and A calls C with parameter that + When function A is inlined in B and A calls C with parameter that changes with probability PROB1 and C is known to be passthroug of argument if B that change with probability PROB2, the probability of change is now PROB1*PROB2. */ @@ -3472,12 +3477,12 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, struct cgraph_edge *e, *next; for (e = node->callees; e; e = next) { - class ipa_call_summary *es = ipa_call_summaries->get (e); predicate p; next = e->next_callee; if (e->inline_failed) { + class ipa_call_summary *es = ipa_call_summaries->get (e); remap_edge_change_prob (inlined_edge, e); if (es->predicate) diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c index 67dd56f3f17..10aa4b76463 100644 --- a/gcc/ipa-icf.c +++ b/gcc/ipa-icf.c @@ -484,7 +484,7 @@ sem_function::param_used_p (unsigned int i) class ipa_node_params *parms_info = IPA_NODE_REF (get_node ()); - if (vec_safe_length (parms_info->descriptors) <= i) + if (!parms_info || vec_safe_length (parms_info->descriptors) <= i) return true; return ipa_is_param_used (IPA_NODE_REF (get_node ()), i); diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index ff6f25a94ea..eb783e66926 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -271,7 +271,7 @@ ipa_dump_param (FILE *file, class ipa_node_params *info, int i) static bool ipa_alloc_node_params (struct cgraph_node *node, int param_count) { - class ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF_GET_CREATE (node); if (!info->descriptors && param_count) { @@ -289,7 +289,7 @@ ipa_alloc_node_params (struct cgraph_node *node, int param_count) void ipa_initialize_node_params (struct cgraph_node *node) { - class ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF_GET_CREATE (node); if (!info->descriptors && ipa_alloc_node_params (node, count_formal_params (node->decl))) @@ -2605,7 +2605,7 @@ ipa_analyze_node (struct cgraph_node *node) ipa_check_create_node_params (); ipa_check_create_edge_args (); - info = IPA_NODE_REF (node); + info = IPA_NODE_REF_GET_CREATE (node); if (info->analysis_done) return; @@ -3601,6 +3601,9 @@ propagate_controlled_uses (struct cgraph_edge *cs) class ipa_node_params *old_root_info = IPA_NODE_REF (cs->callee); int count, i; + if (!old_root_info) + return; + count = MIN (ipa_get_cs_argument_count (args), ipa_get_param_count (old_root_info)); for (i = 0; i < count; i++) @@ -3662,8 +3665,8 @@ propagate_controlled_uses (struct cgraph_edge *cs) clone = cs->caller; while (clone->inlined_to - && clone != rdesc->cs->caller - && IPA_NODE_REF (clone)->ipcp_orig_node) + && clone->ipcp_clone + && clone != rdesc->cs->caller) { struct ipa_ref *ref; ref = clone->find_reference (n, NULL, 0); @@ -3722,6 +3725,7 @@ ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, propagate_controlled_uses (cs); changed = propagate_info_to_inlined_callees (cs, cs->callee, new_edges); + ipa_node_params_sum->remove (cs->callee); return changed; } @@ -4507,7 +4511,8 @@ ipa_read_node_info (class lto_input_block *ib, struct cgraph_node *node, struct cgraph_edge *e; struct bitpack_d bp; bool prevails = node->prevailing_p (); - class ipa_node_params *info = prevails ? IPA_NODE_REF (node) : NULL; + class ipa_node_params *info = prevails + ? IPA_NODE_REF_GET_CREATE (node) : NULL; int param_count = streamer_read_uhwi (ib); if (prevails) diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 7a9e4bc5916..952c01209f5 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -766,7 +766,8 @@ extern GTY(()) function_summary *ipcp_transformation_sum /* Return the associated parameter/argument info corresponding to the given node/edge. */ -#define IPA_NODE_REF(NODE) (ipa_node_params_sum->get_create (NODE)) +#define IPA_NODE_REF(NODE) (ipa_node_params_sum->get (NODE)) +#define IPA_NODE_REF_GET_CREATE(NODE) (ipa_node_params_sum->get_create (NODE)) #define IPA_EDGE_REF(EDGE) (ipa_edge_args_sum->get (EDGE)) #define IPA_EDGE_REF_GET_CREATE(EDGE) (ipa_edge_args_sum->get_create (EDGE)) /* This macro checks validity of index returned by -- 2.30.2