This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Slightly optimize noreturn functions (PR target/82158)
- From: Richard Biener <rguenther at suse dot de>
- To: Jakub Jelinek <jakub at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 20 Oct 2017 08:28:08 +0200
- Subject: Re: [PATCH] Slightly optimize noreturn functions (PR target/82158)
- Authentication-results: sourceware.org; auth=none
- References: <20171019192510.GS14653@tucnak>
On October 19, 2017 9:25:10 PM GMT+02:00, Jakub Jelinek <jakub@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 <jakub@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