On October 19, 2017 9:25:10 PM GMT+02:00, Jakub Jelinek <ja...@redhat.com> 
wrote:
>Hi!
>
>The following patch, when optimizing, replaces GIMPLE_RETURN in
>noreturn functions right after warning about them with
>__builtin_unreachable
>().  The advantage of that is that we don't emit unnecessary epilogues
>for
>them and perhaps optimize away some other useless computations if the
>only
>side-effect of those is feeding the return value.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK. 

Richard. 

>2017-10-19  Jakub Jelinek  <ja...@redhat.com>
>
>       PR target/82158
>       * tree-cfg.c (pass_warn_function_return::execute): In noreturn
>       functions when optimizing replace GIMPLE_RETURN stmts with
>       calls to __builtin_unreachable ().
>
>       * gcc.dg/tree-ssa/noreturn-1.c: New test.
>
>--- gcc/tree-cfg.c.jj  2017-10-10 22:04:09.000000000 +0200
>+++ gcc/tree-cfg.c     2017-10-19 18:41:04.843653944 +0200
>@@ -9084,13 +9084,29 @@ pass_warn_function_return::execute (func
>       && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (fun)->preds) > 0)
>     {
>       location = UNKNOWN_LOCATION;
>-      FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (fun)->preds)
>+      for (ei = ei_start (EXIT_BLOCK_PTR_FOR_FN (fun)->preds);
>+         (e = ei_safe_edge (ei)); )
>       {
>         last = last_stmt (e->src);
>         if ((gimple_code (last) == GIMPLE_RETURN
>              || gimple_call_builtin_p (last, BUILT_IN_RETURN))
>-            && (location = gimple_location (last)) != UNKNOWN_LOCATION)
>+            && location == UNKNOWN_LOCATION
>+            && (location = gimple_location (last)) != UNKNOWN_LOCATION
>+            && !optimize)
>           break;
>+        /* When optimizing, replace return stmts in noreturn functions
>+           with __builtin_unreachable () call.  */
>+        if (optimize && gimple_code (last) == GIMPLE_RETURN)
>+          {
>+            tree fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
>+            gimple *new_stmt = gimple_build_call (fndecl, 0);
>+            gimple_set_location (new_stmt, gimple_location (last));
>+            gimple_stmt_iterator gsi = gsi_for_stmt (last);
>+            gsi_replace (&gsi, new_stmt, true);
>+            remove_edge (e);
>+          }
>+        else
>+          ei_next (&ei);
>       }
>       if (location == UNKNOWN_LOCATION)
>       location = cfun->function_end_locus;
>--- gcc/testsuite/gcc.dg/tree-ssa/noreturn-1.c.jj      2017-10-19
>18:50:53.861660409 +0200
>+++ gcc/testsuite/gcc.dg/tree-ssa/noreturn-1.c 2017-10-19
>18:55:32.270354804 +0200
>@@ -0,0 +1,42 @@
>+/* { dg-do compile } *
>+/* { dg-options "-O2 -fdump-tree-ssa -std=gnu11" } */
>+/* { dg-final { scan-tree-dump-times "__builtin_unreachable" 4 "ssa" }
>} */
>+
>+void bar1 (void);
>+void bar2 (void);
>+void bar3 (void);
>+void bar4 (void);
>+
>+_Noreturn void
>+foo1 (int *p, int y)
>+{
>+  bar1 ();
>+  *p = y;
>+  return;     /* { dg-warning "function declared 'noreturn' has a 'return'
>statement" } */
>+}             /* { dg-warning "'noreturn' function does return" "" { target 
>*-*-*
>} .-1 } */
>+
>+_Noreturn void
>+foo2 (int *p, int y)
>+{
>+  bar2 ();
>+  *p = y;
>+}             /* { dg-warning "'noreturn' function does return" } */
>+
>+_Noreturn void
>+foo3 (int *p, int y)
>+{
>+  if (y > 10)
>+    return;   /* { dg-warning "function declared 'noreturn' has a
>'return' statement" } */
>+  bar3 ();
>+  *p = y;
>+  return;     /* { dg-warning "function declared 'noreturn' has a 'return'
>statement" } */
>+}             /* { dg-warning "'noreturn' function does return" } */
>+
>+_Noreturn void
>+foo4 (int *p, int y)
>+{
>+  if (y > 10)
>+    return;   /* { dg-warning "function declared 'noreturn' has a
>'return' statement" } */
>+  bar4 ();
>+  *p = y;
>+}             /* { dg-warning "'noreturn' function does return" } */
>
>       Jakub

Reply via email to