On Sun, Apr 27, 2025 at 1:07 AM Andrew Pinski <quic_apin...@quicinc.com> wrote:
>
> 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.

Doing this at RTL expansion is a bit of an awkward spot since it never
appears in any dump.
We have pass_cleanup_cfg_post_optimizing aka ".optimized", so I wonder
if we could do
this there instead?

>From a QOI perspective we'd really want to turn any unreachable() that
falls off the function
into a trap (also consider hot/cold partitioning here).  ISTR we
talked about all this in detail
somewhen back, but I don't remember the issues with doing this after BB reorder.

Richard.

> 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