]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ipa/122852: Don't delete unreachable callback edges.
authorJosef Melcr <josef.melcr@suse.com>
Mon, 8 Dec 2025 14:35:33 +0000 (15:35 +0100)
committerJosef Melcr <josef.melcr@suse.com>
Thu, 15 Jan 2026 09:49:22 +0000 (10:49 +0100)
Hi,
previously, callback edges of a carrying edge redirected to
__builtin_unreachable  were deleted, as I thought they would
mess with the callgraph, given that they were no longer correct.
In some cases, the edges would be deleted when duplicating
a fn summary, producing a segfault. This patch changes this
behavior.  It redirects the callback edges to __builtin_unreachable and
adds an exception for such cases in the verifier.  Callback edges are
now also required to point to __builtin_unreachable if their carrying
edge is pointing to __builtin_unreachable.

Bootstrapped and regtested on x86_64-linux, no regressions.

OK for master?

Thanks,
Josef

PR ipa/122852

gcc/ChangeLog:

* cgraph.cc (cgraph_node::verify_node): Verify that callback
edges are unreachable when the carrying edge is unreachable.
* ipa-fnsummary.cc (redirect_to_unreachable): Redirect callback
edges to unreachable when redirecting the carrying edge.

libgomp/ChangeLog:

* testsuite/libgomp.c/pr122852.c: New test.

Signed-off-by: Josef Melcr <josef.melcr@suse.com>
gcc/cgraph.cc
gcc/ipa-fnsummary.cc
libgomp/testsuite/libgomp.c/pr122852.c [new file with mode: 0644]

index b594b0acc318fd0ca3457329b5b29e135ac9a9b0..91ff2775de1359606965dfd9337f4ca000acb93a 100644 (file)
@@ -4404,7 +4404,8 @@ cgraph_node::verify_node (void)
            }
 
          if (e->has_callback
-             && !callback_is_special_cased (e->callee->decl, e->call_stmt))
+             && !callback_is_special_cased (e->callee->decl, e->call_stmt)
+             && !fndecl_built_in_p (e->callee->decl, BUILT_IN_UNREACHABLE))
            {
              int ncallbacks = 0;
              int nfound_edges = 0;
@@ -4431,6 +4432,16 @@ cgraph_node::verify_node (void)
                }
            }
 
+         if (e->has_callback
+             && fndecl_built_in_p (e->callee->decl, BUILT_IN_UNREACHABLE))
+           for (cgraph_edge *cbe = e->first_callback_edge (); cbe;
+                cbe = cbe->next_callback_edge ())
+             if (!fndecl_built_in_p (cbe->callee->decl, BUILT_IN_UNREACHABLE))
+               error ("callback-carrying edge is pointing towards "
+                      "__builtin_unreachable, but its callback edge %s -> %s "
+                      "is not",
+                      cbe->caller->name (), cbe->callee->name ());
+
          if (!e->aux && !e->speculative && !e->callback && !e->has_callback)
            {
              error ("edge %s->%s has no corresponding call_stmt",
index 80b82a9bf7022fb3305f5eba8f4a3c982d3ea9bd..e187231dfb64c6eadb226a7c8de03dac6ac94865 100644 (file)
@@ -272,7 +272,10 @@ redirect_to_unreachable (struct cgraph_edge *e)
   if (callee)
     callee->remove_symbol_and_inline_clones ();
   if (e->has_callback)
-    e->purge_callback_edges ();
+    for (cgraph_edge *cbe = e->first_callback_edge (); cbe;
+        cbe = cbe->next_callback_edge ())
+      /* If the carrying edge is unreachable, so are the callback calls.  */
+      redirect_to_unreachable (cbe);
   return e;
 }
 
diff --git a/libgomp/testsuite/libgomp.c/pr122852.c b/libgomp/testsuite/libgomp.c/pr122852.c
new file mode 100644 (file)
index 0000000..1a36fe9
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target fopenmp } */
+/* { dg-options "-O2 -fopenmp" } */
+
+int a, b, c;
+
+static void
+foo (int g)
+{
+  int f = c ? c : 2;
+  if (c)
+    b = 3;
+  if (!g)
+    for (int d = 0; d < f; ++d)
+#pragma omp parallel
+      while (a)
+       ;
+}
+
+void
+bar (void)
+{
+  foo (1);
+}