In this PR graphite scop detection ends up doing make_forwarder_block on a block with incoming abnormal edges but doesn't want those "stay" on the forwarder. In the end it is an implementation detail of make_forwarder_block that fails (because what graphite wants would be possible - just not using make_forwarder_block).
Rather than changing make_forwarder_block I chose to avoid the situation from GRAPHITE (also makes backporting obvious). Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2014-04-28 Richard Biener <rguent...@suse.de> PR tree-optimization/60979 * graphite-scop-detection.c (scopdet_basic_block_info): Reject SCOPs that end in a block with a successor with abnormal predecessors. * gcc.dg/graphite/pr60979.c: New testcase. Index: gcc/graphite-scop-detection.c =================================================================== *** gcc/graphite-scop-detection.c (revision 209849) --- gcc/graphite-scop-detection.c (working copy) *************** scopdet_basic_block_info (basic_block bb *** 474,481 **** result.exits = false; /* Mark bbs terminating a SESE region difficult, if they start ! a condition. */ ! if (!single_succ_p (bb)) result.difficult = true; else result.exit = single_succ (bb); --- 474,483 ---- result.exits = false; /* Mark bbs terminating a SESE region difficult, if they start ! a condition or if the block it exits to cannot be split ! with make_forwarder_block. */ ! if (!single_succ_p (bb) ! || bb_has_abnormal_pred (single_succ (bb))) result.difficult = true; else result.exit = single_succ (bb); Index: gcc/testsuite/gcc.dg/graphite/pr60979.c =================================================================== *** gcc/testsuite/gcc.dg/graphite/pr60979.c (revision 0) --- gcc/testsuite/gcc.dg/graphite/pr60979.c (working copy) *************** *** 0 **** --- 1,37 ---- + /* { dg-options "-O -fgraphite-identity" } */ + + #include <setjmp.h> + + struct x; + + typedef struct x **(*a)(struct x *); + + struct x { + union { + struct { + union { + a *i; + } l; + int s; + } y; + } e; + }; + + jmp_buf c; + + void + b(struct x *r) + { + int f; + static int w = 0; + volatile jmp_buf m; + f = (*(((struct x *)r)->e.y.l.i[2]((struct x *)r)))->e.y.s; + if (w++ != 0) + __builtin_memcpy((char *)m, (const char *)c, sizeof(jmp_buf)); + if (setjmp (c) == 0) { + int z; + for (z = 0; z < 0; ++z) + ; + } + d((const char *)m); + }