Hi, our kernel guys saw this problem when they used an asm goto to implement a conditional where the then-block was empty. RTL ifcvt happily goes on and removes the whole block and the jump instruction, even though it has side-effects (as marked with the volatility). Patch below fixes it by checking that it's really just a jump. Regstrapped on trunk. Okay for trunk, 4.9, 4.8?
Ciao, Michael. PR rtl-optimization/61772 * ifcvt.c (dead_or_predicable): Check jump to be free of side effects. testsuite/ PR rtl-optimization/61772 * gcc.dg/torture/pr61772.c: New test. Index: ifcvt.c =================================================================== --- ifcvt.c (revision 212430) +++ ifcvt.c (working copy) @@ -4138,6 +4138,8 @@ dead_or_predicable (basic_block test_bb, if (JUMP_P (end)) { + if (!onlyjump_p (end)) + return FALSE; if (head == end) { head = end = NULL_RTX; Index: testsuite/gcc.dg/torture/pr61772.c =================================================================== --- testsuite/gcc.dg/torture/pr61772.c (revision 0) +++ testsuite/gcc.dg/torture/pr61772.c (working copy) @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-final { scan-assembler-times "XXX" 2 } } */ + +static inline __attribute__((always_inline)) int dec_and_test (int *i) +{ + asm volatile goto ("XXX %0, %l[cc_label]" + : : "m" (*i) : "memory" : cc_label); + return 0; +cc_label: + return 1; +} +extern int getit (int *); +int f (int *i, int cond) +{ + if (cond) { + getit (0); + if (dec_and_test (i)) + getit (i); + return 42; + } + if (dec_and_test (i)) + (void)1; + return getit (i); +}