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:
parent
9a45ffbd12
commit
356fcc67fb
@ -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.
|
||||
|
@ -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.
|
||||
|
42
gcc/testsuite/gcc.dg/tree-ssa/noreturn-1.c
Normal file
42
gcc/testsuite/gcc.dg/tree-ssa/noreturn-1.c
Normal 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" } */
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user