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,

Reply via email to