PRE in prune_clobbered_mems iterates over a bitmap, eventually removing the current bit. That's not safe in case the current element gets removed (that will terminate the iteration as the next element is then NULL).
The following fixes this by keeping a queue of size one (it's safe to remove all but the current bit). Bootstrap and regtest running on x86_64-unknown-linux-gnu. Richard. 2016-10-06 Richard Biener <rguent...@suse.de> PR tree-optimization/77855 * tree-ssa-pre.c (prune_clobbered_mems): Queue exprs to remove instead of removing the current item while iterating over the set which is not safe. * gcc.dg/torture/pr77855.c: New testcase. Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 240828) --- gcc/tree-ssa-pre.c (working copy) *************** prune_clobbered_mems (bitmap_set_t set, *** 2025,2033 **** --- 2025,2041 ---- { bitmap_iterator bi; unsigned i; + pre_expr to_remove = NULL; FOR_EACH_EXPR_ID_IN_SET (set, i, bi) { + /* Remove queued expr. */ + if (to_remove) + { + bitmap_remove_from_set (set, to_remove); + to_remove = NULL; + } + pre_expr expr = expression_for_id (i); if (expr->kind == REFERENCE) { *************** prune_clobbered_mems (bitmap_set_t set, *** 2041,2047 **** block, gimple_bb (def_stmt))) || (gimple_bb (def_stmt) == block && value_dies_in_block_x (expr, block)))) ! bitmap_remove_from_set (set, expr); } } else if (expr->kind == NARY) --- 2049,2055 ---- block, gimple_bb (def_stmt))) || (gimple_bb (def_stmt) == block && value_dies_in_block_x (expr, block)))) ! to_remove = expr; } } else if (expr->kind == NARY) *************** prune_clobbered_mems (bitmap_set_t set, *** 2053,2061 **** as the available expression might be after the exit point. */ if (BB_MAY_NOTRETURN (block) && vn_nary_may_trap (nary)) ! bitmap_remove_from_set (set, expr); } } } static sbitmap has_abnormal_preds; --- 2061,2073 ---- as the available expression might be after the exit point. */ if (BB_MAY_NOTRETURN (block) && vn_nary_may_trap (nary)) ! to_remove = expr; } } + + /* Remove queued expr. */ + if (to_remove) + bitmap_remove_from_set (set, to_remove); } static sbitmap has_abnormal_preds; Index: gcc/testsuite/gcc.dg/torture/pr77855.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr77855.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr77855.c (working copy) *************** *** 0 **** --- 1,48 ---- + /* { dg-do run } */ + + int a, b = 1, c, e, f, g, k, m, n, o; + char d, h, i, j, l; + char res[2]; + + void __attribute__ ((noinline,noclone)) fn2 () + { + d = 2; + } + + void fn3 () + { + for (;;) + { + for (; b; b--) + { + fn2 (); + if (e) + j = 1; + if (f) + L1: + k = j | (a & l); + for (;;) + { + __builtin_snprintf (res, 2, "%d\n", d); + if (d) + break; + for (; o; o--) + for (; n;) + for (; m; m++) + ; + goto L1; + } + } + g = h; + c = i; + break; + } + } + + int main () + { + fn3 (); + if (res[0] != '2') + __builtin_abort (); + return 0; + }