[backport gcc-4.9/trunk r198625, fixes PR57147 regression from PR56982 fix ] gcc/ 2013-05-06 Richard Biener 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/testsuite/ 2013-05-06 Richard Biener 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. --- gcc-4.8.0/gcc/testsuite/gcc.dg/torture/pr57147-1.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.8.0/gcc/testsuite/gcc.dg/torture/pr57147-1.c 2013-05-09 16:37:58.295313649 +0200 @@ -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" } } */ --- gcc-4.8.0/gcc/testsuite/gcc.dg/torture/pr57147-2.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.8.0/gcc/testsuite/gcc.dg/torture/pr57147-2.c 2013-05-09 16:37:58.295313649 +0200 @@ -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" } } */ --- gcc-4.8.0/gcc/testsuite/gcc.dg/torture/pr57147-3.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.8.0/gcc/testsuite/gcc.dg/torture/pr57147-3.c 2013-05-09 16:37:58.295313649 +0200 @@ -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 (;;) + ; +} --- gcc-4.8.0/gcc/tree-cfg.c.~1~ 2013-05-09 16:37:25.555422035 +0200 +++ gcc-4.8.0/gcc/tree-cfg.c 2013-05-09 16:37:58.305313618 +0200 @@ -7493,7 +7493,10 @@ gimple_purge_dead_abnormal_call_edges (b { 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 --- gcc-4.8.0/gcc/tree-cfgcleanup.c.~1~ 2013-02-27 15:01:08.000000000 +0100 +++ gcc-4.8.0/gcc/tree-cfgcleanup.c 2013-05-09 16:37:58.295313649 +0200 @@ -57,7 +57,10 @@ remove_fallthru_edge (vec * 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; --- gcc-4.8.0/gcc/tree-inline.c.~1~ 2013-05-09 16:37:48.635345621 +0200 +++ gcc-4.8.0/gcc/tree-inline.c 2013-05-09 16:37:58.305313618 +0200 @@ -1843,14 +1843,8 @@ update_ssa_across_abnormal_edges (basic_ 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)));