https://gcc.gnu.org/g:060374f2294e5df3bf1c96e2051a06b8f7051ba6
commit 060374f2294e5df3bf1c96e2051a06b8f7051ba6 Author: Josef Melcr <melcr...@fit.cvut.cz> Date: Wed Apr 2 11:06:35 2025 +0200 omp-cp: Fix redirections, callback edge deletion gcc/ChangeLog: * attr-callback.h (callback_remove_callback_edge): Remove function. * cgraph.cc (cgraph_edge::set_call_stmt): Add null check. (cgraph_node::verify_node): Change verifying logic to account for CB edge deletion. * ipa-cp.cc (purge_useless_callback_edges): Change deletion function, more logging. * ipa-fnsummary.cc (ipa_call_summary_t::duplicate): Exclude callback edges when subtracting size and time. * ipa-inline-analysis.cc (do_estimate_growth_1): Skip callback edges when calculating inlining cost. * ipa-inline-transform.cc (inline_transform): Add callback edge redirection. * tree-inline.cc (redirect_all_calls): Likewise. Signed-off-by: Josef Melcr <melcr...@fit.cvut.cz> Diff: --- gcc/attr-callback.h | 31 ------------------------------- gcc/cgraph.cc | 32 ++++++++++++++++---------------- gcc/ipa-cp.cc | 10 +++++++++- gcc/ipa-fnsummary.cc | 3 ++- gcc/ipa-inline-analysis.cc | 3 +++ gcc/ipa-inline-transform.cc | 7 ++++++- gcc/tree-inline.cc | 12 ++++++++++-- 7 files changed, 46 insertions(+), 52 deletions(-) diff --git a/gcc/attr-callback.h b/gcc/attr-callback.h index 622949c03ac3..cf22808c9b8b 100644 --- a/gcc/attr-callback.h +++ b/gcc/attr-callback.h @@ -288,35 +288,4 @@ callback_edge_useful_p (cgraph_edge *e) return true; } -inline void -callback_remove_callback_edge (cgraph_edge *e) -{ - gcc_checking_assert (e->callback); - cgraph_edge *parent = e->get_callback_parent_edge (); - tree offload_decl = parent->callee->decl; - if (parent->call_stmt) - { - tree attr = callback_fetch_attr_by_decl (parent->call_stmt, - DECL_ATTRIBUTES (offload_decl), - e->callee->decl); - - tree *p; - tree list = DECL_ATTRIBUTES (offload_decl); - for (p = &list; *p;) - { - tree l = *p; - - if (l == attr) - { - *p = TREE_CHAIN (l); - continue; - } - p = &TREE_CHAIN (l); - } - - DECL_ATTRIBUTES (offload_decl) = list; - } - cgraph_edge::remove (e); -} - #endif /* ATTR_CALLBACK_H */ diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc index 60a4f49014c3..a1bb366265e7 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -851,19 +851,22 @@ cgraph_edge::set_call_stmt (cgraph_edge *e, gcall *new_stmt, cgraph_edge *current, *next; current = e->first_callback_target (); - gcall *old_stmt = current->call_stmt; - for (cgraph_edge *d = current; d; d = next) + if (current) { - next = d->next_callee; - for (; next; next = next->next_callee) + gcall *old_stmt = current->call_stmt; + for (cgraph_edge *d = current; d; d = next) { - /* has_callback doesn't need to checked, as their - call statements wouldn't match */ - if (next->callback && old_stmt == next->call_stmt) - break; + next = d->next_callee; + for (; next; next = next->next_callee) + { + /* has_callback doesn't need to checked, as their + call statements wouldn't match */ + if (next->callback && old_stmt == next->call_stmt) + break; + } + cgraph_edge *d2 = set_call_stmt (d, new_stmt, false); + gcc_assert (d2 == d); } - cgraph_edge *d2 = set_call_stmt (d, new_stmt, false); - gcc_assert (d2 == d); } } @@ -3824,6 +3827,7 @@ cgraph_node::verify_node (void) && !e->caller->inlined_to && !e->speculative && !e->callback + && !e->has_callback /* Optimized out calls are redirected to __builtin_unreachable. */ && (e->count.nonzero_p () || ! e->callee->decl @@ -4107,15 +4111,11 @@ cgraph_node::verify_node (void) { nfound_edges++; } - else if (cbe->callback) { - fprintf (stderr, "sus verify %s -> %s\n", - cbe->caller->name (), cbe->callee->name ()); - } } - if (ncallbacks != nfound_edges) + if (ncallbacks < nfound_edges) { error ("callback edge %s->%s child edge count mismatch, " - "expected %d, found %d", + "expected at most %d, found %d", identifier_to_locale (e->caller->name ()), identifier_to_locale (e->callee->name ()), ncallbacks, nfound_edges); diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc index 02447da03144..4ce08f96fae0 100644 --- a/gcc/ipa-cp.cc +++ b/gcc/ipa-cp.cc @@ -6247,7 +6247,15 @@ purge_useless_callback_edges () "\t\tCallback edge %s -> %s not deemed " "useful, removing.\n", cbe->caller->name (), cbe->callee->name ()); - callback_remove_callback_edge (cbe); + cgraph_edge::remove (cbe); + } + else + { + if (dump_file) + fprintf (dump_file, + "\t\tNot considering callback edge %s -> %s " + "for deletion.\n", + cbe->caller->name (), cbe->callee->name ()); } } } diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc index f5ac4243348c..90228c4259f5 100644 --- a/gcc/ipa-fnsummary.cc +++ b/gcc/ipa-fnsummary.cc @@ -987,7 +987,8 @@ ipa_call_summary_t::duplicate (struct cgraph_edge *src, info->predicate = NULL; edge_set_predicate (dst, srcinfo->predicate); info->param = srcinfo->param.copy (); - if (!dst->indirect_unknown_callee && src->indirect_unknown_callee) + if (!dst->indirect_unknown_callee && src->indirect_unknown_callee + && !src->has_callback && !dst->callback) { info->call_stmt_size -= (eni_size_weights.indirect_call_cost - eni_size_weights.call_cost); diff --git a/gcc/ipa-inline-analysis.cc b/gcc/ipa-inline-analysis.cc index a190cb6501b8..f35941908304 100644 --- a/gcc/ipa-inline-analysis.cc +++ b/gcc/ipa-inline-analysis.cc @@ -417,6 +417,9 @@ do_estimate_growth_1 (struct cgraph_node *node, void *data) { gcc_checking_assert (e->inline_failed); + if (e->callback) + continue; + if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR || !opt_for_fn (e->caller->decl, optimize)) { diff --git a/gcc/ipa-inline-transform.cc b/gcc/ipa-inline-transform.cc index a991cfd0c743..6d4b080474df 100644 --- a/gcc/ipa-inline-transform.cc +++ b/gcc/ipa-inline-transform.cc @@ -800,12 +800,17 @@ inline_transform (struct cgraph_node *node) next = e->next_callee; if (e->has_callback) { + /* Call statement might change, so we must set it to all child edges + as well, otherwise their pairing would fall apart. */ gcall *old_stmt = e->call_stmt; cgraph_edge *cbe; cgraph_edge::redirect_call_stmt_to_callee (e); for (cbe = node->callees; cbe; cbe = cbe->next_callee) if (cbe->callback && cbe->call_stmt == old_stmt) - cgraph_edge::set_call_stmt (cbe, e->call_stmt, false); + { + cgraph_edge::set_call_stmt (cbe, e->call_stmt, false); + cgraph_edge::redirect_call_stmt_to_callee (cbe); + } } else cgraph_edge::redirect_call_stmt_to_callee (e); diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 1ef6e5c34daf..e2d23578e52e 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -3045,8 +3045,16 @@ redirect_all_calls (copy_body_data * id, basic_block bb) { if (!id->killed_new_ssa_names) id->killed_new_ssa_names = new hash_set<tree> (16); - cgraph_edge::redirect_call_stmt_to_callee (edge, - id->killed_new_ssa_names); + cgraph_edge::redirect_call_stmt_to_callee ( + edge, id->killed_new_ssa_names); + if (edge->has_callback) + { + cgraph_edge *cbe; + for (cbe = edge->first_callback_target (); cbe; + cbe = cbe->next_callback_target ()) + cgraph_edge::redirect_call_stmt_to_callee ( + cbe, id->killed_new_ssa_names); + } if (stmt == last && id->call_stmt && maybe_clean_eh_stmt (stmt)) gimple_purge_dead_eh_edges (bb);