re PR rtl-optimization/20290 (Miscompilation on ppc/arm with -Os)
authorAlexandre Oliva <aoliva@redhat.com>
Sat, 2 Apr 2005 16:53:44 +0000 (16:53 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Sat, 2 Apr 2005 16:53:44 +0000 (16:53 +0000)
gcc/ChangeLog:
PR rtl-optimization/20290
* loop.c (for_each_insn_in_loop): Don't assume the loop body runs
in every iteration if the entry point is the exit test.
gcc/testsuite/ChangeLog:
PR rtl-optimization/20290
* gcc.c-torture/execute/loop-ivopts-2.c: New.

From-SVN: r97441

gcc/ChangeLog
gcc/loop.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/loop-ivopts-2.c [new file with mode: 0644]

index 86086934cbb974e3488887b347f67b8310522d87..f9f53e008cf2f2521a4cc88d5edf41101b6b6c29 100644 (file)
@@ -1,3 +1,9 @@
+2005-04-02  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR rtl-optimization/20290
+       * loop.c (for_each_insn_in_loop): Don't assume the loop body runs
+       in every iteration if the entry point is the exit test.
+
 2005-04-02  Hans-Peter Nilsson  <hp@axis.com>
 
        * config/cris/cris.md (attribute "length"): Define.
index 6a99e97d38f948b33fa03ff6f3a28d4deaed8c58..e2e6074ccc47dffcb1e38b217b7950066b3d9307 100644 (file)
@@ -4654,12 +4654,18 @@ for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall)
   int not_every_iteration = 0;
   int maybe_multiple = 0;
   int past_loop_latch = 0;
+  bool exit_test_is_entry = false;
   rtx p;
 
-  /* If loop_scan_start points to the loop exit test, we have to be wary of
-     subversive use of gotos inside expression statements.  */
+  /* If loop_scan_start points to the loop exit test, the loop body
+     cannot be counted on running on every iteration, and we have to
+     be wary of subversive use of gotos inside expression
+     statements.  */
   if (prev_nonnote_insn (loop->scan_start) != prev_nonnote_insn (loop->start))
-    maybe_multiple = back_branch_in_range_p (loop, loop->scan_start);
+    {
+      exit_test_is_entry = true;
+      maybe_multiple = back_branch_in_range_p (loop, loop->scan_start);
+    }
 
   /* Scan through loop and update NOT_EVERY_ITERATION and MAYBE_MULTIPLE.  */
   for (p = next_insn_in_loop (loop, loop->scan_start);
@@ -4717,10 +4723,12 @@ for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall)
          beginning, don't set not_every_iteration for that.
          This can be any kind of jump, since we want to know if insns
          will be executed if the loop is executed.  */
-         && !(JUMP_LABEL (p) == loop->top
-              && ((NEXT_INSN (NEXT_INSN (p)) == loop->end
-                   && any_uncondjump_p (p))
-                  || (NEXT_INSN (p) == loop->end && any_condjump_p (p)))))
+         && (exit_test_is_entry
+             || !(JUMP_LABEL (p) == loop->top
+                  && ((NEXT_INSN (NEXT_INSN (p)) == loop->end
+                       && any_uncondjump_p (p))
+                      || (NEXT_INSN (p) == loop->end
+                          && any_condjump_p (p))))))
        {
          rtx label = 0;
 
index b8c472441313f17be27121797c04c24ea7a35abc..c2a49280c1448fc69e2a4cd50ee98659d96356f1 100644 (file)
@@ -1,3 +1,8 @@
+2005-04-02  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR rtl-optimization/20290
+       * gcc.c-torture/execute/loop-ivopts-2.c: New.
+
 2005-04-02  Geoffrey Keating  <geoffk@apple.com>
 
        * gcc.dg/rs6000-fpint.c: New.
diff --git a/gcc/testsuite/gcc.c-torture/execute/loop-ivopts-2.c b/gcc/testsuite/gcc.c-torture/execute/loop-ivopts-2.c
new file mode 100644 (file)
index 0000000..737640b
--- /dev/null
@@ -0,0 +1,50 @@
+/* PR rtl-optimization/20290  */
+   
+/* We used to mis-optimize the second loop in main on at least ppc and
+   arm, because tree loop would change the loop to something like:
+
+  ivtmp.65 = &l[i];
+  ivtmp.16 = 113;
+  goto <bb 4> (<L4>);
+
+<L3>:;
+  *(ivtmp.65 + 4294967292B) = 9;
+  i = i + 1;
+
+<L4>:;
+  ivtmp.16 = ivtmp.16 - 1;
+  ivtmp.65 = ivtmp.65 + 4B;
+  if (ivtmp.16 != 0) goto <L3>; 
+
+  We used to consider the increment of i as executed in every
+  iteration, so we'd miscompute the final value.  */
+
+extern void abort (void);
+
+void
+check (unsigned int *l)
+{
+  int i;
+  for (i = 0; i < 288; i++)
+    if (l[i] != 7 + (i < 256 || i >= 280) + (i >= 144 && i < 256))
+      abort ();
+}
+
+int
+main (void)
+{
+  int i;
+  unsigned int l[288];
+
+  for (i = 0; i < 144; i++)
+    l[i] = 8;
+  for (; i < 256; i++)
+    l[i] = 9;
+  for (; i < 280; i++)
+    l[i] = 7;
+  for (; i < 288; i++)
+    l[i] = 8;
+  check (l);
+  return 0;
+}
+