https://gcc.gnu.org/g:307ba5b392678330c44b9a43215856eef5befc60
commit 307ba5b392678330c44b9a43215856eef5befc60 Author: Josef Melcr <melcr...@fit.cvut.cz> Date: Fri Mar 14 15:13:42 2025 +0100 omp-cp: fix info copying in fn-summary, fix callback edge inlining gcc/ChangeLog: * cgraph.cc (cgraph_add_edge_to_call_site_hash): Exclude callback edges. (cgraph_node::get_edge): Return parent edge if callback is found first. (cgraph_edge::set_call_stmt): Fix callback edges. (cgraph_edge::first_callback_target): New function. (cgraph_edge::next_callback_target): New function. (cgraph_node::remove_callers): Remove callback edges when removing their parent. (cgraph_node::verify_node): Fix type. * cgraph.h: Add declarations. * ipa-fnsummary.cc (analyze_function_body): Fix summary copying when dealing with callback edges. * ipa-inline-transform.cc (inline_transform): Set child call stmts when setting their parent. * ipa-prop.cc (ipa_compute_jump_functions_for_edge): Fix segfault when dealing with indirect edges. * tree-inline.cc (copy_bb): Add callback edge copying. Signed-off-by: Josef Melcr <melcr...@fit.cvut.cz> Diff: --- gcc/cgraph.cc | 63 ++++++++++++++++++++++++++++++++++++++++++--- gcc/cgraph.h | 6 +++++ gcc/ipa-fnsummary.cc | 16 ++++++++---- gcc/ipa-inline-transform.cc | 12 ++++++++- gcc/ipa-prop.cc | 2 +- gcc/tree-inline.cc | 13 ++++++++++ 6 files changed, 101 insertions(+), 11 deletions(-) diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc index eabba370aa1f..e032cc0b4864 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -721,6 +721,8 @@ cgraph_add_edge_to_call_site_hash (cgraph_edge *e) one indirect); always hash the direct one. */ if (e->speculative && e->indirect_unknown_callee) return; + if (e->callback) + return; cgraph_edge **slot = e->caller->call_site_hash->find_slot_with_hash (e->call_stmt, cgraph_edge_hasher::hash (e->call_stmt), INSERT); if (*slot) @@ -769,6 +771,9 @@ cgraph_node::get_edge (gimple *call_stmt) n++; } + if (e && e->callback) + e = e->get_callback_parent_edge (); + if (n > 100) { call_site_hash = hash_table<cgraph_edge_hasher>::create_ggc (120); @@ -845,7 +850,7 @@ cgraph_edge::set_call_stmt (cgraph_edge *e, gcall *new_stmt, { cgraph_edge *current, *next; - current = e; + current = e->first_callback_target (); gcall *old_stmt = current->call_stmt; for (cgraph_edge *d = current; d; d = next) { @@ -1213,6 +1218,36 @@ cgraph_edge::get_callback_parent_edge () return e; } +cgraph_edge * +cgraph_edge::first_callback_target () +{ + gcc_checking_assert (has_callback || callback); + cgraph_edge *e = NULL; + for (e = caller->callees; e; e = e->next_callee) + { + if (e->callback && e->call_stmt == call_stmt) + { + break; + } + } + return e; +} + +cgraph_edge * +cgraph_edge::next_callback_target () +{ + gcc_checking_assert (has_callback || callback); + cgraph_edge *e = NULL; + for (e = next_callee; e; e = e->next_callee) + { + if (e->callback && e->call_stmt == call_stmt) + { + break; + } + } + return e; +} + /* Speculative call consists of an indirect edge and one or more direct edge+ref pairs. @@ -1867,6 +1902,17 @@ cgraph_node::remove_callers (void) for (e = callers; e; e = f) { f = e->next_caller; + if (e->has_callback) + { + cgraph_edge *cbe, *next_cbe = NULL; + for (cbe = e->first_callback_target (); cbe; cbe = next_cbe) + { + next_cbe = cbe->next_callback_target (); + symtab->call_edge_removal_hooks (cbe); + cbe->remove_caller (); + symtab->free_edge (cbe); + } + } symtab->call_edge_removal_hooks (e); e->remove_caller (); symtab->free_edge (e); @@ -4032,11 +4078,20 @@ cgraph_node::verify_node (void) ncallbacks++) ; for (cgraph_edge *cbe = callees; cbe; cbe = cbe->next_callee) - if (cbe->callback && cbe->call_stmt == e->call_stmt) - nfound_edges++; + { + if (cbe->callback && cbe->call_stmt == e->call_stmt) { + + nfound_edges++; + + } + else if (cbe->callback) { + fprintf (stderr, "sus verify %s -> %s\n", + cbe->caller->name (), cbe->callee->name ()); + } + } if (ncallbacks != nfound_edges) { - error ("callback edge %s->%s child edge count mismach, " + error ("callback edge %s->%s child edge count mismatch, " "expected %d, found %d", identifier_to_locale (e->caller->name ()), identifier_to_locale (e->callee->name ()), ncallbacks, diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 00d2285671ed..044639793486 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1747,6 +1747,12 @@ public: this method is caled on. */ cgraph_edge *get_callback_parent_edge (); + /* TODO DOCS */ + cgraph_edge *first_callback_target (); + + /* TODO DOCS */ + cgraph_edge *next_callback_target (); + /* Speculative call consists of an indirect edge and one or more direct edge+ref pairs. Speculative will expand to the following sequence: diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc index 7a44ad1c5f2f..8c7c8e74063d 100644 --- a/gcc/ipa-fnsummary.cc +++ b/gcc/ipa-fnsummary.cc @@ -3106,12 +3106,18 @@ analyze_function_body (struct cgraph_node *node, bool early) /* Treat callback edges the same way we treat speculative edges. */ - if (edge->callback) + if (edge->has_callback) { - cgraph_edge *parent = edge->get_callback_parent_edge (); - ipa_call_summary *es2 - = ipa_call_summaries->get_create (parent); - ipa_call_summaries->duplicate (edge, parent, es, es2); + cgraph_edge *child; + for (child = edge->first_callback_target (); child; + child = child->next_callback_target ()) + { + ipa_call_summary *es2 = ipa_call_summaries->get (child); + if (es2) + continue; + es2 = ipa_call_summaries->get_create (child); + ipa_call_summaries->duplicate (edge, child, es, es2); + } } } diff --git a/gcc/ipa-inline-transform.cc b/gcc/ipa-inline-transform.cc index cfa902b4dd3f..a991cfd0c743 100644 --- a/gcc/ipa-inline-transform.cc +++ b/gcc/ipa-inline-transform.cc @@ -798,7 +798,17 @@ inline_transform (struct cgraph_node *node) if (!e->inline_failed) has_inline = true; next = e->next_callee; - cgraph_edge::redirect_call_stmt_to_callee (e); + if (e->has_callback) + { + 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); + } + else + cgraph_edge::redirect_call_stmt_to_callee (e); } node->remove_all_references (); diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index 4a086ad19745..450d0065c424 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -2443,7 +2443,7 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, if (TREE_CODE (arg) == ADDR_EXPR) { tree pointee = TREE_OPERAND (arg, 0); - if (TREE_CODE (pointee) == FUNCTION_DECL && !cs->callback) + if (TREE_CODE (pointee) == FUNCTION_DECL && !cs->callback && cs->callee) { /* Argument is a pointer to a function. Look for a callback attribute describing this argument. */ diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 8f86fb723288..1ef6e5c34daf 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -2340,6 +2340,19 @@ copy_bb (copy_body_data *id, basic_block bb, indirect->count = copy_basic_block->count.apply_probability (prob); } + /* If edge is a callback parent edge, copy all its + * children as well */ + else if (edge->has_callback) + { + edge + = edge->clone (id->dst_node, call_stmt, + gimple_uid (stmt), num, den, true); + cgraph_edge *e; + for (e = old_edge->first_callback_target (); e; + e = e->next_callback_target ()) + edge = e->clone (id->dst_node, call_stmt, + gimple_uid (stmt), num, den, true); + } else { edge = edge->clone (id->dst_node, call_stmt,