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