When we have an empty function, things can go wrong with 
cfi_startproc/cfi_endproc and a few other
things like exceptions. So if the only thing the function does is a call to 
__builtin_unreachable,
let's expand that to a __builtin_trap instead. For most targets that is one 
instruction wide so it
won't hurt things that much and we get correct behavior for exceptions and some 
linkers will be better
for it.

Bootstrapped and tested on x86_64-linux-gnu.

        PR middle-end/109267

gcc/ChangeLog:

        * cfgexpand.cc (expand_gimple_basic_block): If the first non debug 
statement in the
        first (and only) basic block is a call to __builtin_unreachable change 
it to a call
        to __builtin_trap.

gcc/testsuite/ChangeLog:

        * gcc.dg/pr109267-1.c: New test.
        * gcc.dg/pr109267-2.c: New test.

Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
---
 gcc/cfgexpand.cc                  |  8 ++++++++
 gcc/testsuite/gcc.dg/pr109267-1.c | 14 ++++++++++++++
 gcc/testsuite/gcc.dg/pr109267-2.c | 13 +++++++++++++
 3 files changed, 35 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/pr109267-1.c
 create mode 100644 gcc/testsuite/gcc.dg/pr109267-2.c

diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index e84f12a5e93..e14df760b7a 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -6206,6 +6206,14 @@ expand_gimple_basic_block (basic_block bb, bool 
disable_tail_calls)
       basic_block new_bb;
 
       stmt = gsi_stmt (gsi);
+
+      /* If we are expanding the first (and only) bb and the only non debug
+        statement is __builtin_unreachable call, then replace it with a trap
+        so the function is at least one instruction in size.  */
+      if (!nondebug_stmt_seen && bb->index == NUM_FIXED_BLOCKS
+          && gimple_call_builtin_p (stmt, BUILT_IN_UNREACHABLE))
+       gimple_call_set_fndecl(stmt, builtin_decl_implicit (BUILT_IN_TRAP));
+
       if (!is_gimple_debug (stmt))
        nondebug_stmt_seen = true;
 
diff --git a/gcc/testsuite/gcc.dg/pr109267-1.c 
b/gcc/testsuite/gcc.dg/pr109267-1.c
new file mode 100644
index 00000000000..4f1da8b41e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr109267-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-expand-details" } */
+
+/* PR middle-end/109267 */
+
+int f(void)
+{
+  __builtin_unreachable();
+}
+
+/* This unreachable should expand as trap. */
+
+/* { dg-final { scan-rtl-dump-times "__builtin_trap " 1 "expand"} } */
+/* { dg-final { scan-rtl-dump-times "__builtin_unreachable " 1 "expand"} } */
diff --git a/gcc/testsuite/gcc.dg/pr109267-2.c 
b/gcc/testsuite/gcc.dg/pr109267-2.c
new file mode 100644
index 00000000000..e6da4860998
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr109267-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-expand-details" } */
+
+/* PR middle-end/109267 */
+void g(void);
+int f(int *t)
+{
+  g();
+  __builtin_unreachable();
+}
+
+/* This should be expanded to unreachable so it should show up twice. */
+/* { dg-final { scan-rtl-dump-times "__builtin_unreachable " 2 "expand"} } */
-- 
2.43.0

Reply via email to