https://gcc.gnu.org/g:ae4c22ab05501940e345ee799be3aa36ffa7269a

commit r15-9202-gae4c22ab05501940e345ee799be3aa36ffa7269a
Author: Andrew Pinski <quic_apin...@quicinc.com>
Date:   Wed Apr 2 18:18:50 2025 -0700

    always turn return into __builtin_unreachable for noreturn fuctions 
[PR119599]
    
    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.
    
            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>

Diff:
---
 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(-)

diff --git a/gcc/testsuite/gcc.dg/builtin-apply5.c 
b/gcc/testsuite/gcc.dg/builtin-apply5.c
new file mode 100644
index 000000000000..16892f76a8a7
--- /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 000000000000..4fbd228a3590
--- /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 2fa5678051ad..ecf19d280797 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -9799,18 +9799,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);

Reply via email to