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 <[email protected]>
---
 gcc/cgraph.cc                          | 13 ++++++++++++-
 gcc/ipa-fnsummary.cc                   |  5 ++++-
 libgomp/testsuite/libgomp.c/pr122852.c | 24 ++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 2 deletions(-)
 create mode 100644 libgomp/testsuite/libgomp.c/pr122852.c

diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index 3c21e174943..2d4925230f8 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -4348,7 +4348,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;
@@ -4375,6 +4376,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",
diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc
index bf98a449584..d7451e76ed2 100644
--- a/gcc/ipa-fnsummary.cc
+++ b/gcc/ipa-fnsummary.cc
@@ -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
index 00000000000..1a36fe9c0fc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pr122852.c
@@ -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);
+}
-- 
2.52.0

Reply via email to