re PR target/82158 (_Noreturn functions that do return clobber caller's registers on ARM32 (but not other arches))

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.

From-SVN: r253926
This commit is contained in:
Jakub Jelinek 2017-10-20 09:35:48 +02:00 committed by Jakub Jelinek
parent 9a45ffbd12
commit 356fcc67fb
4 changed files with 68 additions and 2 deletions

View File

@ -1,5 +1,10 @@
2017-10-20 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 ().
PR sanitizer/82595
* config/gnu-user.h (LIBTSAN_EARLY_SPEC): Add libtsan_preinit.o
for -fsanitize=thread link of executables.

View File

@ -1,5 +1,8 @@
2017-10-20 Jakub Jelinek <jakub@redhat.com>
PR target/82158
* gcc.dg/tree-ssa/noreturn-1.c: New test.
PR target/82370
* gcc.target/i386/avx-pr82370.c: New test.
* gcc.target/i386/avx2-pr82370.c: New test.

View File

@ -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" } */

View File

@ -9077,13 +9077,29 @@ pass_warn_function_return::execute (function *fun)
&& 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;