On Thu, Apr 3, 2025 at 11:56 PM Andrew Pinski <quic_apin...@quicinc.com> wrote:
>
> r8-3988-g356fcc67fba52b added code to turn return statements into 
> __builtin_unreachable
> calls inside noreturn functions but only while optimizing. Since 
> -funreachable-traps
> was added (r13-1204-gd68d3664253696), it is a good idea to move over to using
> __builtin_unreachable (and the trap version with this option which defaults 
> at -O0 and -0g)
> instead of just a follow through even at -O0.
>
> This also fixes a regression when inlining a noreturn function that returns 
> at -O0 (due to always_inline)
> as we would get an empty bb which has no successor edge instead of one with a 
> call to __builtin_unreachable.
>
> I also noticed there was no testcase testing the warning about 
> __builtin_return inside a noreturn function
> so I added a testcase there.
>
> Bootstrapped and tested on x86_64-linux-gnu.

OK.

Thanks,
Richard.

>         PR ipa/119599
>
> gcc/ChangeLog:
>
>         * tree-cfg.cc (pass_warn_function_return::execute): Turn return 
> statements always
>         into __builtin_unreachable calls.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/torture/pr119599-1.c: New test.
>         * gcc.dg/builtin-apply5.c: New test.
>
> Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> ---
>  gcc/testsuite/gcc.dg/builtin-apply5.c     | 23 +++++++++++++++++++
>  gcc/testsuite/gcc.dg/torture/pr119599-1.c | 27 +++++++++++++++++++++++
>  gcc/tree-cfg.cc                           | 20 +++++++++--------
>  3 files changed, 61 insertions(+), 9 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/builtin-apply5.c
>  create mode 100644 gcc/testsuite/gcc.dg/torture/pr119599-1.c
>
> diff --git a/gcc/testsuite/gcc.dg/builtin-apply5.c 
> b/gcc/testsuite/gcc.dg/builtin-apply5.c
> new file mode 100644
> index 00000000000..16892f76a8a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/builtin-apply5.c
> @@ -0,0 +1,23 @@
> +/* { dg-options "-O2 -Wmissing-noreturn -fgnu89-inline" } */
> +/* { dg-additional-options "-mno-mmx" { target { { i?86-*-* x86_64-*-* } && 
> ia32 } } } */
> +/* { dg-do compile } */
> +
> +extern void abort (void);
> +
> +double
> +foo (int arg)
> +{
> +  if (arg != 116)
> +    abort();
> +  return arg + 1;
> +}
> +
> +__attribute__((noreturn))
> +double
> +bar (int arg)
> +{
> +  foo (arg);
> +  __builtin_return (__builtin_apply ((void (*) ()) foo, /* { dg-warning 
> "'noreturn' function does return" } */
> +                                    __builtin_apply_args (), 16));
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/torture/pr119599-1.c 
> b/gcc/testsuite/gcc.dg/torture/pr119599-1.c
> new file mode 100644
> index 00000000000..4fbd228a359
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr119599-1.c
> @@ -0,0 +1,27 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fdump-tree-einline" } */
> +
> +/* PR ipa/119599 */
> +/* inlining a noreturn function which returns
> +   can cause an ICE when dealing finding an unreachable block.
> +   We should get a __builtin_unreachable after the inliing.  */
> +
> +
> +void baz (void);
> +
> +static inline __attribute__((always_inline, noreturn)) void
> +bar (void)
> +{
> +  static volatile int t = 0;
> +  if (t == 0)
> +    baz ();
> +} /* { dg-warning "function does return" } */
> +
> +void
> +foo (void)
> +{
> +  bar ();
> +}
> +
> +/* After inlining, we should have call to __builtin_unreachable now. */
> +/* { dg-final { scan-tree-dump "__builtin_unreachable " "einline" } } */
> diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
> index f25480cf6fc..6a29a56ca9a 100644
> --- a/gcc/tree-cfg.cc
> +++ b/gcc/tree-cfg.cc
> @@ -9808,18 +9808,20 @@ pass_warn_function_return::execute (function *fun)
>            (e = ei_safe_edge (ei)); )
>         {
>           last = *gsi_last_bb (e->src);
> -         if ((gimple_code (last) == GIMPLE_RETURN
> -              || gimple_call_builtin_p (last, BUILT_IN_RETURN))
> -             && location == UNKNOWN_LOCATION
> -             && ((location = LOCATION_LOCUS (gimple_location (last)))
> -                 != UNKNOWN_LOCATION)
> -             && !optimize)
> -           break;
> -         /* When optimizing, replace return stmts in noreturn functions
> +         /* Warn about __builtin_return .*/
> +         if (gimple_call_builtin_p (last, BUILT_IN_RETURN)
> +             && location == UNKNOWN_LOCATION)
> +           {
> +             location = LOCATION_LOCUS (gimple_location (last));
> +             ei_next (&ei);
> +           }
> +         /* Replace return stmts in noreturn functions
>              with __builtin_unreachable () call.  */
> -         if (optimize && gimple_code (last) == GIMPLE_RETURN)
> +         else if (gimple_code (last) == GIMPLE_RETURN)
>             {
>               location_t loc = gimple_location (last);
> +             if (location == UNKNOWN_LOCATION)
> +               location = LOCATION_LOCUS (loc);
>               gimple *new_stmt = gimple_build_builtin_unreachable (loc);
>               gimple_stmt_iterator gsi = gsi_for_stmt (last);
>               gsi_replace (&gsi, new_stmt, true);
> --
> 2.43.0
>

Reply via email to