https://gcc.gnu.org/g:86ef6c04591ed9b8deda7f1c86ff7f88e1efd734
commit 86ef6c04591ed9b8deda7f1c86ff7f88e1efd734 Author: Josef Melcr <melcr...@fit.cvut.cz> Date: Mon Mar 31 20:48:52 2025 +0200 omp-cp: Fix one segfault, introduce a different one gcc/ChangeLog: * attr-callback.h (callback_fetch_fn_position): Rewrite with the new function below. (callback_fetch_attr_by_decl): New function. (callback_remove_callback_edge): New function. * cgraph.cc (cgraph_edge::get_callback_parent_edge): Add lto_stmt_uid check. (cgraph_edge::first_callback_target): Likewise. (cgraph_edge::next_callback_target): Likewise. (cgraph_node::verify_node): Likewise. * ipa-cp.cc (purge_useless_callback_edges): Reformat, use the new remove function. (ipcp_decision_stage): Add back purge function. * ipa-fnsummary.cc (analyze_function_body): Set call stmt size and time to 0 for callback edges. Signed-off-by: Josef Melcr <melcr...@fit.cvut.cz> Diff: --- gcc/attr-callback.h | 58 +++++++++++++++++++++++++++++++++++++++++++--------- gcc/cgraph.cc | 21 +++++++++++-------- gcc/ipa-cp.cc | 34 +++++++++++++++++------------- gcc/ipa-fnsummary.cc | 2 ++ 4 files changed, 82 insertions(+), 33 deletions(-) diff --git a/gcc/attr-callback.h b/gcc/attr-callback.h index b6a1a0c4106c..622949c03ac3 100644 --- a/gcc/attr-callback.h +++ b/gcc/attr-callback.h @@ -86,18 +86,13 @@ callback_get_arg_mapping (tree decl) return res; } -/* Given a call statement of the parent, it's attribute list and - a decl of the callback, returns a 0-based index of the callback - function in the parameters of it's caller function. Arguments - are extracted from the call statement. If kernel_decl is a decl - of a clone, it's parent decl will be considered as well. */ -inline int -callback_fetch_fn_position (gcall *call, tree attr_list, tree kernel_decl) +inline tree +callback_fetch_attr_by_decl(gcall *call, tree attr_list, tree kernel_decl) { tree original_decl = DECL_ORIGIN (kernel_decl); tree cb_attr = lookup_attribute ("callback", attr_list); gcc_checking_assert (cb_attr); - int res = -1; + tree res = NULL_TREE; for (; cb_attr; cb_attr = lookup_attribute ("callback", TREE_CHAIN (cb_attr))) { int idx = callback_get_fn_index (cb_attr); @@ -108,15 +103,27 @@ callback_fetch_fn_position (gcall *call, tree attr_list, tree kernel_decl) if (pointee != NULL_TREE && (pointee == kernel_decl || pointee == original_decl)) { - res = idx; + res = cb_attr; break; } } } - gcc_checking_assert (res != -1); + gcc_checking_assert (res != NULL_TREE); return res; } +/* Given a call statement of the parent, it's attribute list and + a decl of the callback, returns a 0-based index of the callback + function in the parameters of it's caller function. Arguments + are extracted from the call statement. If kernel_decl is a decl + of a clone, it's parent decl will be considered as well. */ +inline int +callback_fetch_fn_position (gcall *call, tree attr_list, tree kernel_decl) +{ + tree attr = callback_fetch_attr_by_decl(call, attr_list, kernel_decl); + return callback_get_fn_index(attr); +} + /* Returns the element at index idx in the list or NULL_TREE if the list isn't long enough. NULL_TREE is used as the endpoint. */ static tree @@ -281,4 +288,35 @@ 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 3bcfe1f2da12..60a4f49014c3 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -1212,7 +1212,8 @@ cgraph_edge::get_callback_parent_edge () cgraph_edge *e; for (e = caller->callees; e; e = e->next_callee) { - if (e->has_callback && e->call_stmt == call_stmt) + if (e->has_callback && e->call_stmt == call_stmt + && e->lto_stmt_uid == lto_stmt_uid) break; } return e; @@ -1225,7 +1226,8 @@ cgraph_edge::first_callback_target () cgraph_edge *e = NULL; for (e = caller->callees; e; e = e->next_callee) { - if (e->callback && e->call_stmt == call_stmt) + if (e->callback && e->call_stmt == call_stmt + && e->lto_stmt_uid == lto_stmt_uid) { break; } @@ -1240,7 +1242,8 @@ cgraph_edge::next_callback_target () cgraph_edge *e = NULL; for (e = next_callee; e; e = e->next_callee) { - if (e->callback && e->call_stmt == call_stmt) + if (e->callback && e->call_stmt == call_stmt + && e->lto_stmt_uid == lto_stmt_uid) { break; } @@ -4099,16 +4102,16 @@ cgraph_node::verify_node (void) ; 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 + && cbe->lto_stmt_uid == e->lto_stmt_uid) + { + 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 mismatch, " diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc index b259e51d8e74..02447da03144 100644 --- a/gcc/ipa-cp.cc +++ b/gcc/ipa-cp.cc @@ -6229,26 +6229,33 @@ purge_useless_callback_edges () DECL_ATTRIBUTES (e->callee->decl))) { if (dump_file) - fprintf (dump_file, - "\t\tPurging children, because the offloading " - "function no longer has any callback attributes.\n"); + fprintf ( + dump_file, + "\t\tPurging children, because the offloading " + "function no longer has any callback attributes.\n"); e->purge_callback_children (); continue; } - cgraph_edge *cbe, *next; - for (cbe = e->first_callback_target(); cbe; cbe = next) { - next = cbe->next_callback_target(); - if (!callback_edge_useful_p(cbe)) { - if (dump_file) - fprintf(dump_file, "\t\tCallback edge %s -> %s not deemed useful, removing.\n", cbe->caller->name(), cbe->callee->name()); - cgraph_edge::remove(cbe); - } + cgraph_edge *cbe, *next; + for (cbe = e->first_callback_target (); cbe; cbe = next) + { + next = cbe->next_callback_target (); + if (!callback_edge_useful_p (cbe)) + { + if (dump_file) + fprintf (dump_file, + "\t\tCallback edge %s -> %s not deemed " + "useful, removing.\n", + cbe->caller->name (), cbe->callee->name ()); + callback_remove_callback_edge (cbe); } + } } } } + if (dump_file) - fprintf(dump_file, "\n"); + fprintf (dump_file, "\n"); } /* The decision stage. Iterate over the topological order of call graph nodes @@ -6281,8 +6288,7 @@ ipcp_decision_stage (class ipa_topo_info *topo) if (change) identify_dead_nodes (node); } - if (0) - purge_useless_callback_edges(); + purge_useless_callback_edges(); } /* Look up all VR and bits information that we have discovered and copy it diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc index 8c7c8e74063d..f5ac4243348c 100644 --- a/gcc/ipa-fnsummary.cc +++ b/gcc/ipa-fnsummary.cc @@ -3117,6 +3117,8 @@ analyze_function_body (struct cgraph_node *node, bool early) continue; es2 = ipa_call_summaries->get_create (child); ipa_call_summaries->duplicate (edge, child, es, es2); + es2->call_stmt_size = 0; + es2->call_stmt_time = 0; } } }