aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2014-02-01 09:40:31 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2014-02-01 09:40:31 +0100
commit021293cb5abbe2a03c36bb5324ef2ebebcc98c9d (patch)
tree22ced0be1f1d48fca4a1b793689fd1f9bffc18f7 /gcc
parentb49e41743c3343f32642a4fbb2dd3c2bc4ccb838 (diff)
downloadgcc-021293cb5abbe2a03c36bb5324ef2ebebcc98c9d.zip
gcc-021293cb5abbe2a03c36bb5324ef2ebebcc98c9d.tar.gz
gcc-021293cb5abbe2a03c36bb5324ef2ebebcc98c9d.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/gimple-low.c6
-rw-r--r--gcc/profile.c6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr60003.c48
-rw-r--r--gcc/tree-inline.c7
6 files changed, 69 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 32eb882..6b6add6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2014-02-01 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <vmakarov@redhat.com>
PR bootstrap/59985
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index c60e817..5fbcf3f3 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 752d89f..83cbc07 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 b1a657a..3024259 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-02-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/60003
+ * gcc.c-torture/execute/pr60003.c: New test.
+
2014-01-31 Vladimir Makarov <vmakarov@redhat.com>
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 0000000..94d9cf8
--- /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 79a39bc..439ef4c 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,