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