Hi!

The following testcase FAILs with -fcompare-debug, because reassociate_bb
mishandles the case when the last stmt in a bb has zero uses.  In that case
reassoc_remove_stmt (like gsi_remove) moves the iterator to the next stmt,
i.e. gsi_end_p is true, which means the code sets the iterator back to
gsi_last_bb.  The problem is that the for loop does gsi_prev on that before
handling the next statement, which means the former penultimate stmt, now
last one, is not processed by reassociate_bb.
Now, with -g, if there is at least one debug stmt at the end of the bb,
reassoc_remove_stmt moves the iterator to that following debug stmt and we
just do gsi_prev and continue with the former penultimate non-debug stmt,
now last non-debug stmt.

The following patch fixes that by not doing the gsi_prev in this case; there
are too many continue; cases, so I didn't want to copy over the gsi_prev to
all of them, so this patch uses a bool for that instead.  The second
gsi_end_p check isn't needed anymore, because when we don't do the
undesirable gsi_prev after gsi = gsi_last_bb, the loop !gsi_end_p (gsi)
condition will catch the removal of the very last stmt from a bb.

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

2020-03-28  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/94329
        * tree-ssa-reassoc.c (reassociate_bb): When calling reassoc_remove_stmt
        on the last stmt in a bb, make sure gsi_prev isn't done immediately
        after gsi_last_bb.

        * gfortran.dg/pr94329.f90: New test.

--- gcc/tree-ssa-reassoc.c.jj   2020-03-17 13:50:52.319942549 +0100
+++ gcc/tree-ssa-reassoc.c      2020-03-27 15:49:14.323217631 +0100
@@ -6224,8 +6224,11 @@ reassociate_bb (basic_block bb)
   if (stmt && !gimple_visited_p (stmt))
     cfg_cleanup_needed |= maybe_optimize_range_tests (stmt);
 
-  for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
+  bool do_prev = false;
+  for (gsi = gsi_last_bb (bb);
+       !gsi_end_p (gsi); do_prev ? gsi_prev (&gsi) : (void) 0)
     {
+      do_prev = true;
       stmt = gsi_stmt (gsi);
 
       if (is_gimple_assign (stmt)
@@ -6246,15 +6249,12 @@ reassociate_bb (basic_block bb)
                  release_defs (stmt);
                  /* We might end up removing the last stmt above which
                     places the iterator to the end of the sequence.
-                    Reset it to the last stmt in this case which might
-                    be the end of the sequence as well if we removed
-                    the last statement of the sequence.  In which case
-                    we need to bail out.  */
+                    Reset it to the last stmt in this case and make sure
+                    we don't do gsi_prev in that case.  */
                  if (gsi_end_p (gsi))
                    {
                      gsi = gsi_last_bb (bb);
-                     if (gsi_end_p (gsi))
-                       break;
+                     do_prev = false;
                    }
                }
              continue;
--- gcc/testsuite/gfortran.dg/pr94329.f90.jj    2020-03-27 15:54:46.453249143 
+0100
+++ gcc/testsuite/gfortran.dg/pr94329.f90       2020-03-27 15:54:23.474592894 
+0100
@@ -0,0 +1,12 @@
+! PR tree-optimization/94329
+! { dg-do compile }
+! { dg-options "-O1 -fno-tree-loop-optimize -fwrapv -fcompare-debug" }
+
+subroutine pr94329 (s, t)
+  real :: s, t(:,:)
+  do i = 1,3
+    do j = 1,3
+      s = t(i,j)
+    end do
+  end do
+end

        Jakub

Reply via email to