The following fixes PR82276 and PR82244 in a slightly different way to ensure VRP is able to fully propagate out asserts on abnormals to restore valid SSA form.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2017-09-21 Richard Biener <rguent...@suse.de> PR tree-optimization/82276 PR tree-optimization/82244 * tree-vrp.c (build_assert_expr_for): Set SSA_NAME_OCCURS_IN_ABNORMAL_PHI if the variable we assert on has it set. (remove_range_assertions): Revert earlier change. * gcc.dg/torture/pr82276.c: New testcase. Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 253050) +++ gcc/tree-vrp.c (working copy) @@ -4518,7 +4518,12 @@ build_assert_expr_for (tree cond, tree v operand of the ASSERT_EXPR. Create it so the new name and the old one are registered in the replacement table so that we can fix the SSA web after adding all the ASSERT_EXPRs. */ - create_new_def_for (v, assertion, NULL); + tree new_def = create_new_def_for (v, assertion, NULL); + /* Make sure we preserve abnormalness throughout an ASSERT_EXPR chain + given we have to be able to fully propagate those out to re-create + valid SSA when removing the asserts. */ + if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (v)) + SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_def) = 1; return assertion; } @@ -7039,14 +7044,6 @@ remove_range_assertions (void) FOR_EACH_IMM_USE_ON_STMT (use_p, iter) SET_USE (use_p, var); } - /* But do not propagate constants as that is invalid. */ - else if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) - { - gassign *ass = gimple_build_assign (lhs, var); - gsi_replace (&si, ass, true); - gsi_next (&si); - continue; - } else replace_uses_by (lhs, var); Index: gcc/testsuite/gcc.dg/torture/pr82276.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr82276.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr82276.c (working copy) @@ -0,0 +1,32 @@ +/* { dg-do compile } */ + +typedef struct a { + struct a *b; +} a; + +extern int d(void); +extern int g(void); +extern int h(void); +extern int _setjmp(); +extern int i(void); + +void c(void) { + 1 ? d() : 0; + a *e; + while (e) { + e = (e == (a *) c) ? 0 : e->b; + while (e) { + unsigned int f = 0; + g(); + _setjmp(f); + if (f & 6) { + ; + } else if (f & 2) { + ; + } else { + h(); + } + i(); + } + } +}