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;
                    }
                }
            }

Reply via email to