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

Reply via email to