From 021293cb5abbe2a03c36bb5324ef2ebebcc98c9d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 1 Feb 2014 09:40:31 +0100 Subject: [PATCH] re PR tree-optimization/60003 (wrong code with __builtin_setjmp/__builtin_longjmp and inlining) PR tree-optimization/60003 * gimple-low.c (lower_builtin_setjmp): Set cfun->has_nonlocal_label. * profile.c (branch_prob): Use gimple_call_builtin_p to check for BUILT_IN_SETJMP_RECEIVER. * tree-inline.c (copy_bb): Call notice_special_calls. * gcc.c-torture/execute/pr60003.c: New test. From-SVN: r207382 --- gcc/ChangeLog | 8 ++++ gcc/gimple-low.c | 6 +++ gcc/profile.c | 6 +-- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.c-torture/execute/pr60003.c | 48 +++++++++++++++++++ gcc/tree-inline.c | 7 +-- 6 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr60003.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 32eb882f40e..6b6add62651 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2014-02-01 Jakub Jelinek + + PR tree-optimization/60003 + * gimple-low.c (lower_builtin_setjmp): Set cfun->has_nonlocal_label. + * profile.c (branch_prob): Use gimple_call_builtin_p + to check for BUILT_IN_SETJMP_RECEIVER. + * tree-inline.c (copy_bb): Call notice_special_calls. + 2014-01-31 Vladimir Makarov PR bootstrap/59985 diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index c60e8177d38..5fbcf3f34ac 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -709,6 +709,12 @@ lower_builtin_setjmp (gimple_stmt_iterator *gsi) tree dest, t, arg; gimple g; + /* __builtin_setjmp_{setup,receiver} aren't ECF_RETURNS_TWICE and for RTL + these builtins are modelled as non-local label jumps to the label + that is passed to these two builtins, so pretend we have a non-local + label during GIMPLE passes too. See PR60003. */ + cfun->has_nonlocal_label = true; + /* NEXT_LABEL is the label __builtin_longjmp will jump to. Its address is passed to both __builtin_setjmp_setup and __builtin_setjmp_receiver. */ FORCED_LABEL (next_label) = 1; diff --git a/gcc/profile.c b/gcc/profile.c index 752d89fc3d8..83cbc07967b 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -1104,7 +1104,6 @@ branch_prob (void) { gimple_stmt_iterator gsi; gimple first; - tree fndecl; gsi = gsi_start_nondebug_after_labels_bb (bb); gcc_checking_assert (!gsi_end_p (gsi)); @@ -1114,10 +1113,7 @@ branch_prob (void) special and don't expect anything to be inserted before them. */ if (is_gimple_call (first) - && (((fndecl = gimple_call_fndecl (first)) != NULL - && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL - && (DECL_FUNCTION_CODE (fndecl) - == BUILT_IN_SETJMP_RECEIVER)) + && (gimple_call_builtin_p (first, BUILT_IN_SETJMP_RECEIVER) || (gimple_call_flags (first) & ECF_RETURNS_TWICE) || (gimple_call_internal_p (first) && (gimple_call_internal_fn (first) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b1a657aea92..302425935df 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-02-01 Jakub Jelinek + + PR tree-optimization/60003 + * gcc.c-torture/execute/pr60003.c: New test. + 2014-01-31 Vladimir Makarov PR bootstrap/59985 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr60003.c b/gcc/testsuite/gcc.c-torture/execute/pr60003.c new file mode 100644 index 00000000000..94d9cf88698 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr60003.c @@ -0,0 +1,48 @@ +/* PR tree-optimization/60003 */ + +extern void abort (void); + +unsigned long long jmp_buf[5]; + +__attribute__((noinline, noclone)) void +baz (void) +{ + __builtin_longjmp (&jmp_buf, 1); +} + +void +bar (void) +{ + baz (); +} + +__attribute__((noinline, noclone)) int +foo (int x) +{ + int a = 0; + + if (__builtin_setjmp (&jmp_buf) == 0) + { + while (1) + { + a = 1; + bar (); /* OK if baz () instead */ + } + } + else + { + if (a == 0) + return 0; + else + return x; + } +} + +int +main () +{ + if (foo (1) == 0) + abort (); + + return 0; +} diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 79a39bca136..439ef4c2933 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1745,7 +1745,6 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, if (is_gimple_call (stmt)) { struct cgraph_edge *edge; - int flags; switch (id->transform_call_graph_edges) { @@ -1868,11 +1867,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, } } - flags = gimple_call_flags (stmt); - if (flags & ECF_MAY_BE_ALLOCA) - cfun->calls_alloca = true; - if (flags & ECF_RETURNS_TWICE) - cfun->calls_setjmp = true; + notice_special_calls (stmt); } maybe_duplicate_eh_stmt_fn (cfun, stmt, id->src_cfun, orig_stmt,