https://gcc.gnu.org/g:151e86109841b2aa7464f4132d2fda9d037190e2
commit 151e86109841b2aa7464f4132d2fda9d037190e2 Author: Josef Melcr <melcr...@fit.cvut.cz> Date: Mon Nov 4 22:35:05 2024 +0100 omp-cp: Add jump function copying, omp constants now appear in lattices gcc/ChangeLog: * cgraph.cc (cgraph_edge::maybe_hot_p): Add temporary hardcode for callback edges (cgraph_node::verify_node): Fix some failing cases when not using lto * ipa-prop.cc (ipa_compute_jump_functions_for_edge): Remove recursion, add jump function copying (ipa_copy_ith_jump_func): New function * ipa-prop.h (ipa_copy_ith_jump_func): New function declaration Signed-off-by: Josef Melcr <melcr...@fit.cvut.cz> Diff: --- gcc/cgraph.cc | 5 +- gcc/ipa-prop.cc | 158 ++++++++++++++++++++++++++++++++++++++++++++++---------- gcc/ipa-prop.h | 4 ++ 3 files changed, 137 insertions(+), 30 deletions(-) diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc index 96d95a87c769..78c56dd43ccd 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -3013,6 +3013,7 @@ cgraph_edge::cannot_lead_to_return_p (void) bool cgraph_edge::maybe_hot_p (void) { + if (callback) return true; if (!maybe_hot_count_p (NULL, count.ipa ())) return false; if (caller->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED @@ -3886,7 +3887,7 @@ cgraph_node::verify_node (void) } if (!e->indirect_unknown_callee) { - if (e->verify_corresponds_to_fndecl (decl)) + if (!e->callback && e->verify_corresponds_to_fndecl (decl)) { error ("edge points to wrong declaration:"); debug_tree (e->callee->decl); @@ -3928,7 +3929,7 @@ cgraph_node::verify_node (void) for (e = callees; e; e = e->next_callee) { - if (!e->aux && !e->speculative && !e->callback) + if (!e->aux && !e->speculative && !e->callback && !e->has_callback) { error ("edge %s->%s has no corresponding call_stmt", identifier_to_locale (e->caller->name ()), diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index 1d131f338004..bc5b7933a75c 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -2330,9 +2330,6 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, ipa_edge_args *args = ipa_edge_args_sum->get_create (cs); gcall *call = cs->call_stmt; int n, arg_num = gimple_call_num_args (call); - if (cs->callback) { - arg_num = args->callback_args->length(); - } bool useful_context = false; if (arg_num == 0 || args->jump_functions) @@ -2346,21 +2343,11 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, if (ipa_func_spec_opts_forbid_analysis_p (cs->caller)) return; - int n_ = 0; - bool recurse = false; cgraph_edge * callback_edge = NULL; - for (n = 0; n < arg_num && n_ < arg_num; n_++, n++) + for (n = 0; n < arg_num; n++) { - if (cs->callback) - { - n_ = (*args->callback_args)[n].idx; - } - else - { - n_ = n; - } struct ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, n); - tree arg = gimple_call_arg (call, n_); + tree arg = gimple_call_arg (call, n); tree param_type = ipa_get_callee_param_type (cs, n); if (flag_devirtualize && POINTER_TYPE_P (TREE_TYPE (arg))) { @@ -2448,10 +2435,9 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, && !cs->callback) { cgraph_node *kernel_node = cgraph_node::get_create (pointee); - gcc_checking_assert (!recurse && !callback_edge); + gcc_checking_assert (!callback_edge); callback_edge = cs->make_callback (kernel_node); calc_callback_args_idx (callback_edge); - recurse = true; } } } @@ -2495,14 +2481,6 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, } } - if (cs->callback && (*args->callback_args)[n].is_data_arg) - { - ipa_set_jf_simple_pass_through (jfunc, 0, true); - } - if (cs->has_callback && n == 1) - { - ipa_set_jf_simple_pass_through (jfunc, 1, true); - } /* If ARG is pointer, we cannot use its type to determine the type of aggregate passed (because type conversions are ignored in gimple). Usually we can safely get type from function declaration, but in case of K&R prototypes or @@ -2521,9 +2499,28 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, determine_known_aggregate_parts (fbi, call, arg, param_type, jfunc); } - if (recurse) { - ipa_compute_jump_functions_for_edge (fbi, callback_edge); - } + if (callback_edge) + { + class ipa_edge_args *cb_summary = ipa_edge_args_sum->get (callback_edge); + unsigned i; + for (i = 0; i < cb_summary->callback_args->length (); i++) + { + cb_arg_info cb = (*cb_summary->callback_args)[i]; + ipa_copy_ith_jump_func (cs, cb.idx, callback_edge, i); + if (cb.is_data_arg) + { + class ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, cb.idx); + unsigned j; + for (j = 0; jfunc->agg.items && (j < jfunc->agg.items->length ()); + j++) + { + if ((*jfunc->agg.items)[j].jftype == IPA_JF_PASS_THROUGH) + (*jfunc->agg.items)[j].value.pass_through.agg_preserved + = true; + } + } + } + } if (!useful_context) vec_free (args->polymorphic_call_contexts); } @@ -4550,6 +4547,111 @@ ipa_edge_args_sum_t::remove (cgraph_edge *cs, ipa_edge_args *args) } } +void +ipa_copy_ith_jump_func (class cgraph_edge *src, unsigned src_idx, + class cgraph_edge *dst, unsigned dst_idx) +{ + class ipa_edge_args *src_args = ipa_edge_args_sum->get (src); + class ipa_edge_args *dst_args = ipa_edge_args_sum->get (dst); + + + if (dst_idx >= vec_safe_length (dst_args->jump_functions)) + { + vec_safe_grow_cleared (dst_args->jump_functions, dst_idx + 1, true); + } + + struct ipa_jump_func *src_jf = ipa_get_ith_jump_func (src_args, src_idx); + struct ipa_jump_func *dst_jf = ipa_get_ith_jump_func (dst_args, dst_idx); + + ::new (dst_jf) ipa_jump_func (*src_jf); + + dst_jf->agg.items = vec_safe_copy (src_jf->agg.items); + dst_jf->m_vr = src_jf->m_vr; + + if (src_jf->type == IPA_JF_CONST) + { + struct ipa_cst_ref_desc *src_rdesc = jfunc_rdesc_usable (src_jf); + + if (!src_rdesc) + dst_jf->value.constant.rdesc = NULL; + else if (src->caller == dst->caller) + { + /* Creation of a speculative edge. If the source edge is the one + grabbing a reference, we must create a new (duplicate) + reference description. Otherwise they refer to the same + description corresponding to a reference taken in a function + src->caller is inlined to. In that case we just must + increment the refcount. */ + if (src_rdesc->cs == src) + { + symtab_node *n = symtab_node_for_jfunc (src_jf); + gcc_checking_assert (n); + ipa_ref *ref + = src->caller->find_reference (n, src->call_stmt, + src->lto_stmt_uid, IPA_REF_ADDR); + gcc_checking_assert (ref); + dst->caller->clone_reference (ref, ref->stmt); + + ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate (); + dst_rdesc->cs = dst; + dst_rdesc->refcount = src_rdesc->refcount; + dst_rdesc->next_duplicate = NULL; + dst_jf->value.constant.rdesc = dst_rdesc; + } + else + { + src_rdesc->refcount++; + dst_jf->value.constant.rdesc = src_rdesc; + } + } + else if (src_rdesc->cs == src) + { + struct ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate (); + dst_rdesc->cs = dst; + dst_rdesc->refcount = src_rdesc->refcount; + dst_rdesc->next_duplicate = src_rdesc->next_duplicate; + src_rdesc->next_duplicate = dst_rdesc; + dst_jf->value.constant.rdesc = dst_rdesc; + } + else + { + struct ipa_cst_ref_desc *dst_rdesc; + /* This can happen during inlining, when a JFUNC can refer to a + reference taken in a function up in the tree of inline clones. + We need to find the duplicate that refers to our tree of + inline clones. */ + + gcc_assert (dst->caller->inlined_to); + for (dst_rdesc = src_rdesc->next_duplicate; dst_rdesc; + dst_rdesc = dst_rdesc->next_duplicate) + { + struct cgraph_node *top; + top = dst_rdesc->cs->caller->inlined_to + ? dst_rdesc->cs->caller->inlined_to + : dst_rdesc->cs->caller; + if (dst->caller->inlined_to == top) + break; + } + gcc_assert (dst_rdesc); + dst_jf->value.constant.rdesc = dst_rdesc; + } + } + else if (dst_jf->type == IPA_JF_PASS_THROUGH && src->caller == dst->caller) + { + struct cgraph_node *inline_root + = dst->caller->inlined_to ? dst->caller->inlined_to : dst->caller; + ipa_node_params *root_info = ipa_node_params_sum->get (inline_root); + int idx = ipa_get_jf_pass_through_formal_id (dst_jf); + + int c = ipa_get_controlled_uses (root_info, idx); + if (c != IPA_UNDESCRIBED_USE) + { + c++; + ipa_set_controlled_uses (root_info, idx, c); + } + } +} + /* Method invoked when an edge is duplicated. Copy ipa_edge_args and adjust reference count data strucutres accordingly. */ diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 7c6324ffb554..4bf263070a8e 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -1062,6 +1062,10 @@ ipa_get_ith_jump_func (class ipa_edge_args *args, int i) return &(*args->jump_functions)[i]; } +void +ipa_copy_ith_jump_func (class cgraph_edge *src, unsigned src_idx, + class cgraph_edge *dst, unsigned dst_idx); + /* Returns a pointer to the polymorphic call context for the ith argument. NULL if contexts are not computed. */ inline class ipa_polymorphic_call_context *