Hi!

The attached testcase loops endlessly, using more and more memory.
The problem is that the prev stmt iterator sometimes references stmts that
remove_prop_source_from_use decides to remove, and since Michael's
gimple seq changes that seems to be fatal.

Fixed by not keeping an iterator, but instead marking stmts that don't need
revisiting and restarting with first stmt that needs revisiting.  This
assumes that new stmts will have uid 0, but I believe that is the case.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2012-05-08  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/53226
        * tree-ssa-forwprop.c (ssa_forward_propagate_and_combine): Remove
        prev and prev_initialized vars, gimple_set_uid (stmt, 0) before
        processing it and gimple_set_uid (stmt, 1) if it doesn't need to be
        revisited, look for earliest stmt with uid 0 if something changed.

        * gcc.c-torture/compile/pr53226.c: New test.

--- gcc/tree-ssa-forwprop.c.jj  2012-05-03 08:35:52.000000000 +0200
+++ gcc/tree-ssa-forwprop.c     2012-05-08 18:10:19.662061709 +0200
@@ -2677,8 +2677,7 @@ ssa_forward_propagate_and_combine (void)
 
   FOR_EACH_BB (bb)
     {
-      gimple_stmt_iterator gsi, prev;
-      bool prev_initialized;
+      gimple_stmt_iterator gsi;
 
       /* Apply forward propagation to all stmts in the basic-block.
         Note we update GSI within the loop as necessary.  */
@@ -2771,12 +2770,14 @@ ssa_forward_propagate_and_combine (void)
 
       /* Combine stmts with the stmts defining their operands.
         Note we update GSI within the loop as necessary.  */
-      prev_initialized = false;
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
        {
          gimple stmt = gsi_stmt (gsi);
          bool changed = false;
 
+         /* Mark stmt as potentially needing revisiting.  */
+         gimple_set_uid (stmt, 0);
+
          switch (gimple_code (stmt))
            {
            case GIMPLE_ASSIGN:
@@ -2856,18 +2857,18 @@ ssa_forward_propagate_and_combine (void)
            {
              /* If the stmt changed then re-visit it and the statements
                 inserted before it.  */
-             if (!prev_initialized)
+             for (; !gsi_end_p (gsi); gsi_prev (&gsi))
+               if (gimple_uid (gsi_stmt (gsi)))
+                 break;
+             if (gsi_end_p (gsi))
                gsi = gsi_start_bb (bb);
              else
-               {
-                 gsi = prev;
-                 gsi_next (&gsi);
-               }
+               gsi_next (&gsi);
            }
          else
            {
-             prev = gsi;
-             prev_initialized = true;
+             /* Stmt no longer needs to be revisited.  */
+             gimple_set_uid (stmt, 1);
              gsi_next (&gsi);
            }
        }
--- gcc/testsuite/gcc.c-torture/compile/pr53226.c.jj    2012-05-08 
18:07:40.007000510 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr53226.c       2012-05-08 
18:07:35.071029578 +0200
@@ -0,0 +1,13 @@
+/* PR tree-optimization/53226 */
+
+void
+foo (unsigned long *x, char y, char z)
+{
+  int i;
+  for (i = y; i < z; ++i)
+    {
+      unsigned long a = ((unsigned char) i) & 63UL;
+      unsigned long b = 1ULL << a;
+      *x |= b;
+    }
+}

        Jakub

Reply via email to