In this PR we run into the issue that releasing SSA names from FRE/PRE elimination corrupts the VN lattice and thus the VN lookup we perform for removing redudnant stores ICEs. The patch works around the particular case by making unreachable code detection in SCCVN more optimistic by ignoring backedges during reachability computation and by not doing any elimination on unreachable blocks.
I still have to think about a "proper" fix to the underlying issue (propagate_value_into_stmt updating stmts on our back). Bootstrap and regtest running on x86_64-unknown-linux-gnu. Richard. 2014-05-19 Richard Biener <rguent...@suse.de> PR tree-optimization/61221 * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Do nothing for unreachable blocks. * tree-ssa-sccvn.c (cond_dom_walker::before_dom_children): Improve unreachability detection. * gcc.dg/torture/pr61221.c: New testcase. Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 210608) --- gcc/tree-ssa-pre.c (working copy) *************** eliminate_dom_walker::before_dom_childre *** 4010,4015 **** --- 4010,4024 ---- /* Mark new bb. */ el_avail_stack.safe_push (NULL_TREE); + /* If this block is not reachable do nothing. */ + edge_iterator ei; + edge e; + FOR_EACH_EDGE (e, ei, b->preds) + if (e->flags & EDGE_EXECUTABLE) + break; + if (!e) + return; + for (gsi = gsi_start_phis (b); !gsi_end_p (gsi);) { gimple stmt, phi = gsi_stmt (gsi); Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c (revision 210608) --- gcc/tree-ssa-sccvn.c (working copy) *************** cond_dom_walker::before_dom_children (ba *** 4175,4185 **** if (fail) return; ! /* If any of the predecessor edges are still marked as possibly ! executable consider this block reachable. */ bool reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (cfun); FOR_EACH_EDGE (e, ei, bb->preds) ! reachable |= (e->flags & EDGE_EXECUTABLE); /* If the block is not reachable all outgoing edges are not executable. */ --- 4175,4187 ---- if (fail) return; ! /* If any of the predecessor edges that do not come from blocks dominated ! by us are still marked as possibly executable consider this block ! reachable. */ bool reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (cfun); FOR_EACH_EDGE (e, ei, bb->preds) ! if (!dominated_by_p (CDI_DOMINATORS, e->src, bb)) ! reachable |= (e->flags & EDGE_EXECUTABLE); /* If the block is not reachable all outgoing edges are not executable. */ Index: gcc/testsuite/gcc.dg/torture/pr61221.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr61221.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr61221.c (working copy) *************** *** 0 **** --- 1,32 ---- + /* { dg-do compile } */ + + void __assert_fail (void); + + int **a, b, c, e, *j; + short *d, **f; + + int * + foo () + { + *a = j; + if (!(1 & e)) + __assert_fail (); + return 0; + } + + void + bar () + { + int *g = &b; + short **h = &d; + if ((f = &d) != h) + for (; b;) + { + int i = 1; + if (i) + g = foo (); + c = 0; + } + if (!g) + __assert_fail (); + }