diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5fd5c7a2476..cf7505c41c1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-10-06 Richard Biener + + 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. + 2016-10-06 James Clarke Eric Botcazou diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 085884660fa..e180375cd7c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-10-06 Richard Biener + + PR tree-optimization/77855 + * gcc.dg/torture/pr77855.c: New testcase. + 2016-10-06 James Clarke Eric Botcazou diff --git a/gcc/testsuite/gcc.dg/torture/pr77855.c b/gcc/testsuite/gcc.dg/torture/pr77855.c new file mode 100644 index 00000000000..bec5af32013 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr77855.c @@ -0,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; +} diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 39bc2548c10..4f172005f26 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -2025,9 +2025,17 @@ prune_clobbered_mems (bitmap_set_t set, basic_block block) { 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) { @@ -2041,7 +2049,7 @@ prune_clobbered_mems (bitmap_set_t set, basic_block block) block, gimple_bb (def_stmt))) || (gimple_bb (def_stmt) == block && value_dies_in_block_x (expr, block)))) - bitmap_remove_from_set (set, expr); + to_remove = expr; } } else if (expr->kind == NARY) @@ -2053,9 +2061,13 @@ prune_clobbered_mems (bitmap_set_t set, basic_block block) 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); + to_remove = expr; } } + + /* Remove queued expr. */ + if (to_remove) + bitmap_remove_from_set (set, to_remove); } static sbitmap has_abnormal_preds;