OSDN Git Service

PR optimization/10171
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Mar 2003 20:24:42 +0000 (20:24 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Mar 2003 20:24:42 +0000 (20:24 +0000)
        * unroll.c (unroll_loop): Don't delete the jump at the end unless
        we also delete a jump at the beginning.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@64863 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/gcc.dg/loop-2.c [new file with mode: 0644]
gcc/unroll.c

index b5f7edc..791d08c 100644 (file)
@@ -1,3 +1,9 @@
+2003-03-21  Jason Merrill  <jason@redhat.com>
+
+       PR optimization/10171
+       * unroll.c (unroll_loop): Don't delete the jump at the end unless
+       we also delete a jump at the beginning.
+
 2003-03-25  Stephane Carrez  <stcarrez@nerim.fr>
 
        * doc/contrib.texi (Contributors): Mention self as 68HC11/68HC12
diff --git a/gcc/testsuite/gcc.dg/loop-2.c b/gcc/testsuite/gcc.dg/loop-2.c
new file mode 100644 (file)
index 0000000..e939f32
--- /dev/null
@@ -0,0 +1,20 @@
+/* PR optimization/10171 */
+/* Bug: unroll_loop misoptimized the function so that we got
+   0 iterations of the loop rather than the correct 1.  */
+/* { dg-do run } */
+
+inline int tag() { return 0; }
+
+void f ();
+
+int main() {
+  int i;
+  for (i = 0; i < (tag() ? 2 : 1); i++)
+    f();
+  abort ();
+}
+
+void f ()
+{
+  exit (0);
+}
index 3b5dd7c..9db9975 100644 (file)
@@ -305,9 +305,11 @@ unroll_loop (loop, insn_count, strength_reduce_p)
         jump to the loop condition.  Make sure to delete the jump
         insn, otherwise the loop body will never execute.  */
 
+      /* FIXME this actually checks for a jump to the continue point, which
+        is not the same as the condition in a for loop.  As a result, this
+        optimization fails for most for loops.  We should really use flow
+        information rather than instruction pattern matching.  */
       rtx ujump = ujump_to_loop_cont (loop->start, loop->cont);
-      if (ujump)
-       delete_related_insns (ujump);
 
       /* If number of iterations is exactly 1, then eliminate the compare and
         branch at the end of the loop since they will never be taken.
@@ -319,9 +321,10 @@ unroll_loop (loop, insn_count, strength_reduce_p)
       if (GET_CODE (last_loop_insn) == BARRIER)
        {
          /* Delete the jump insn.  This will delete the barrier also.  */
-         delete_related_insns (PREV_INSN (last_loop_insn));
+         last_loop_insn = PREV_INSN (last_loop_insn);
        }
-      else if (GET_CODE (last_loop_insn) == JUMP_INSN)
+
+      if (ujump && GET_CODE (last_loop_insn) == JUMP_INSN)
        {
 #ifdef HAVE_cc0
          rtx prev = PREV_INSN (last_loop_insn);
@@ -333,24 +336,27 @@ unroll_loop (loop, insn_count, strength_reduce_p)
          if (only_sets_cc0_p (prev))
            delete_related_insns (prev);
 #endif
-       }
 
-      /* Remove the loop notes since this is no longer a loop.  */
-      if (loop->vtop)
-       delete_related_insns (loop->vtop);
-      if (loop->cont)
-       delete_related_insns (loop->cont);
-      if (loop_start)
-       delete_related_insns (loop_start);
-      if (loop_end)
-       delete_related_insns (loop_end);
+         delete_related_insns (ujump);
 
-      return;
+         /* Remove the loop notes since this is no longer a loop.  */
+         if (loop->vtop)
+           delete_related_insns (loop->vtop);
+         if (loop->cont)
+           delete_related_insns (loop->cont);
+         if (loop_start)
+           delete_related_insns (loop_start);
+         if (loop_end)
+           delete_related_insns (loop_end);
+
+         return;
+       }
     }
-  else if (loop_info->n_iterations > 0
-          /* Avoid overflow in the next expression.  */
-          && loop_info->n_iterations < (unsigned) MAX_UNROLLED_INSNS
-          && loop_info->n_iterations * insn_count < (unsigned) MAX_UNROLLED_INSNS)
+
+  if (loop_info->n_iterations > 0
+      /* Avoid overflow in the next expression.  */
+      && loop_info->n_iterations < (unsigned) MAX_UNROLLED_INSNS
+      && loop_info->n_iterations * insn_count < (unsigned) MAX_UNROLLED_INSNS)
     {
       unroll_number = loop_info->n_iterations;
       unroll_type = UNROLL_COMPLETELY;