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; 
+ }

Reply via email to