On Mon, Apr 28, 2025 at 1:23 AM Richard Biener <richard.guent...@gmail.com> wrote: > > 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?
Yes that might be a good place to put this. > > 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. That would be a good idea too. Let me think about it for a week to see if it is an easy way of implementing that. The only issue is not all targets have a trap instruction. E.g. avr, bpf, c6x, epiphany, fr30, frv, ft32, h8300, lm32, m32c, m32r, mcore, mmix, mn10300, moxie, msp430, or1k, pdp11, pru, rl78, rx, (and some others) don't have a trap instruction defined. I am thinking I should only do this conversion in the first place if there is a trap instruction. E.g. for BPF some code will be rejected as abort is not really callable. Anyways let me think about this some more. Thanks, Andrew . > > 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 > >