aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2013-05-06 11:27:29 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2013-05-06 11:27:29 +0000
commit0107dca2adf82db79c54d6da9707035533d474d6 (patch)
tree08393bb2ffe3daf1347d560e6951600839f91db7
parente5123d087ed24066c03c97c92a15d255c8d318dd (diff)
downloadgcc-0107dca2adf82db79c54d6da9707035533d474d6.zip
gcc-0107dca2adf82db79c54d6da9707035533d474d6.tar.gz
gcc-0107dca2adf82db79c54d6da9707035533d474d6.tar.bz2
re PR middle-end/57147 (setjmp call and if body wrongly elided (function runs off early end))
2013-05-06 Richard Biener <rguenther@suse.de> PR middle-end/57147 * tree-cfg.c (gimple_purge_dead_abnormal_call_edges): If the edge is also fallthru, preserve it and just clear the abnormal flag. * tree-cfgcleanup.c (remove_fallthru_edge): If the edge is also complex, preserve that and just clear the fallthru flag. * tree-inline.c (update_ssa_across_abnormal_edges): Also update virtual operands. * gcc.dg/torture/pr57147-1.c: New testcase. * gcc.dg/torture/pr57147-2.c: Likewise. * gcc.dg/torture/pr57147-3.c: Likewise. From-SVN: r198625
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57147-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57147-2.c22
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57147-3.c20
-rw-r--r--gcc/tree-cfg.c5
-rw-r--r--gcc/tree-cfgcleanup.c5
-rw-r--r--gcc/tree-inline.c8
8 files changed, 90 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1a448c7..ddcdb19 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2013-05-06 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/57147
+ * tree-cfg.c (gimple_purge_dead_abnormal_call_edges): If
+ the edge is also fallthru, preserve it and just clear the
+ abnormal flag.
+ * tree-cfgcleanup.c (remove_fallthru_edge): If the edge is
+ also complex, preserve that and just clear the fallthru flag.
+ * tree-inline.c (update_ssa_across_abnormal_edges): Also
+ update virtual operands.
+
2013-05-06 Alan Modra <amodra@gmail.com>
* config/rs6000/linux.h (DEFAULT_ASM_ENDIAN): Define.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 745ed0dc..b4e0479 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2013-05-06 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/57147
+ * gcc.dg/torture/pr57147-1.c: New testcase.
+ * gcc.dg/torture/pr57147-2.c: Likewise.
+ * gcc.dg/torture/pr57147-3.c: Likewise.
+
2013-05-06 Oleg Endo <olegendo@gcc.gnu.org>
PR target/55303
diff --git a/gcc/testsuite/gcc.dg/torture/pr57147-1.c b/gcc/testsuite/gcc.dg/torture/pr57147-1.c
new file mode 100644
index 0000000..e5ad544
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57147-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+struct __jmp_buf_tag {};
+typedef struct __jmp_buf_tag jmp_buf[1];
+extern int _setjmp (struct __jmp_buf_tag __env[1]);
+
+jmp_buf g_return_jmp_buf;
+
+void SetNaClSwitchExpectations (void)
+{
+}
+void TestSyscall(void)
+{
+ SetNaClSwitchExpectations();
+ _setjmp (g_return_jmp_buf);
+}
+
+/* { dg-final { scan-tree-dump-not "builtin_unreachable" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr57147-2.c b/gcc/testsuite/gcc.dg/torture/pr57147-2.c
new file mode 100644
index 0000000..521d126
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57147-2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+struct __jmp_buf_tag {};
+typedef struct __jmp_buf_tag jmp_buf[1];
+extern int _setjmp (struct __jmp_buf_tag __env[1]);
+
+jmp_buf g_return_jmp_buf;
+
+void SetNaClSwitchExpectations (void)
+{
+ __builtin_longjmp (g_return_jmp_buf, 1);
+}
+void TestSyscall(void)
+{
+ SetNaClSwitchExpectations();
+ _setjmp (g_return_jmp_buf);
+}
+
+/* { dg-final { scan-tree-dump "setjmp" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr57147-3.c b/gcc/testsuite/gcc.dg/torture/pr57147-3.c
new file mode 100644
index 0000000..c64e5ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57147-3.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+typedef char * ptr_t;
+struct __jmp_buf_tag {
+};
+typedef struct __jmp_buf_tag sigjmp_buf[1];
+sigjmp_buf GC_jmp_buf;
+void GC_fault_handler(int sig)
+{
+}
+void GC_setup_temporary_fault_handler() {
+ GC_set_and_save_fault_handler(GC_fault_handler);
+}
+ptr_t GC_find_limit(ptr_t p)
+{
+ GC_setup_temporary_fault_handler();
+ if (__sigsetjmp (GC_jmp_buf, 1) == 0)
+ for (;;)
+ ;
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 798a2f7..a08a737 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -7628,7 +7628,10 @@ gimple_purge_dead_abnormal_call_edges (basic_block bb)
{
if (e->flags & EDGE_ABNORMAL)
{
- remove_edge_and_dominated_blocks (e);
+ if (e->flags & EDGE_FALLTHRU)
+ e->flags &= ~EDGE_ABNORMAL;
+ else
+ remove_edge_and_dominated_blocks (e);
changed = true;
}
else
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index 3c69a7d..9b314f7 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -57,7 +57,10 @@ remove_fallthru_edge (vec<edge, va_gc> *ev)
FOR_EACH_EDGE (e, ei, ev)
if ((e->flags & EDGE_FALLTHRU) != 0)
{
- remove_edge_and_dominated_blocks (e);
+ if (e->flags & EDGE_COMPLEX)
+ e->flags &= ~EDGE_FALLTHRU;
+ else
+ remove_edge_and_dominated_blocks (e);
return true;
}
return false;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index b5339c4..83b41b1 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1841,14 +1841,8 @@ update_ssa_across_abnormal_edges (basic_block bb, basic_block ret_bb,
gcc_assert ((e->flags & EDGE_EH)
|| SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)));
- if (virtual_operand_p (PHI_RESULT (phi)))
- {
- mark_virtual_operands_for_renaming (cfun);
- continue;
- }
-
re = find_edge (ret_bb, e->dest);
- gcc_assert (re);
+ gcc_checking_assert (re);
gcc_assert ((re->flags & (EDGE_EH | EDGE_ABNORMAL))
== (e->flags & (EDGE_EH | EDGE_ABNORMAL)));