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