re PR rtl-optimization/7130 (miscompiled code for gcc-3.1 on powerpc-unknown-linux...
authorAlan Modra <amodra@bigpond.net.au>
Sat, 20 Jul 2002 00:31:15 +0000 (00:31 +0000)
committerAlan Modra <amodra@gcc.gnu.org>
Sat, 20 Jul 2002 00:31:15 +0000 (10:01 +0930)
PR optimization/7130
* loop.h (struct loop_info): Add "preconditioned".
* unroll.c (unroll_loop): Set it.
* doloop.c (doloop_modify_runtime): Correct count for unrolled loops.

From-SVN: r55598

gcc/ChangeLog
gcc/doloop.c
gcc/loop.h
gcc/unroll.c

index 69403e0b4db6729081d718e9018a0363047cee98..8fd107b810741389c0e8ef9955744826f745560d 100644 (file)
@@ -1,3 +1,10 @@
+2002-07-20  Alan Modra  <amodra@bigpond.net.au>
+
+       PR optimization/7130
+       * loop.h (struct loop_info): Add "preconditioned".
+       * unroll.c (unroll_loop): Set it.
+       * doloop.c (doloop_modify_runtime): Correct count for unrolled loops.
+
 2002-07-19  Zack Weinberg  <zack@codesourcery.com>
 
        * rtl.def (CODE_LABEL): Remove slot 8.
index ee5b788a911c6507f02dd0013eb563e9029968b2..9bddb92ed23d11c4efb0fa369b561aff0662149a 100644 (file)
@@ -552,6 +552,7 @@ doloop_modify_runtime (loop, iterations_max,
 {
   const struct loop_info *loop_info = LOOP_INFO (loop);
   HOST_WIDE_INT abs_inc;
+  HOST_WIDE_INT abs_loop_inc;
   int neg_inc;
   rtx diff;
   rtx sequence;
@@ -595,13 +596,18 @@ doloop_modify_runtime (loop, iterations_max,
      except in cases where the loop never terminates.  So we don't
      need to use this more costly calculation.
 
-     If the loop has been unrolled, then the loop body has been
-     preconditioned to iterate a multiple of unroll_number times.  If
-     abs_inc is != 1, the full calculation is
+     If the loop has been unrolled, the full calculation is
 
-       t1 = abs_inc * unroll_number;
-       n = abs (final - initial) / t1;
-       n += (abs (final - initial) % t1) > t1 - abs_inc;
+       t1 = abs_inc * unroll_number;           increment per loop
+       n = abs (final - initial) / t1;         full loops
+       n += (abs (final - initial) % t1) != 0; partial loop
+
+     However, in certain cases the unrolled loop will be preconditioned
+     by emitting copies of the loop body with conditional branches,
+     so that the unrolled loop is always a full loop and thus needs
+     no exit tests.  In this case we don't want to add the partial
+     loop count.  As above, when t1 is a power of two we don't need to
+     worry about overflow.
 
      The division and modulo operations can be avoided by requiring
      that the increment is a power of 2 (precondition_loop_p enforces
@@ -667,20 +673,22 @@ doloop_modify_runtime (loop, iterations_max,
        }
     }
 
-  if (abs_inc * loop_info->unroll_number != 1)
+  abs_loop_inc = abs_inc * loop_info->unroll_number;
+  if (abs_loop_inc != 1)
     {
       int shift_count;
 
-      shift_count = exact_log2 (abs_inc * loop_info->unroll_number);
+      shift_count = exact_log2 (abs_loop_inc);
       if (shift_count < 0)
        abort ();
 
-      if (abs_inc != 1)
+      if (!loop_info->preconditioned)
        diff = expand_simple_binop (GET_MODE (diff), PLUS,
-                                   diff, GEN_INT (abs_inc - 1),
+                                   diff, GEN_INT (abs_loop_inc - 1),
                                    diff, 1, OPTAB_LIB_WIDEN);
 
-      /* (abs (final - initial) + abs_inc - 1) / (abs_inc * unroll_number)  */
+      /* (abs (final - initial) + abs_inc * unroll_number - 1)
+        / (abs_inc * unroll_number)  */
       diff = expand_simple_binop (GET_MODE (diff), LSHIFTRT,
                                  diff, GEN_INT (shift_count),
                                  diff, 1, OPTAB_LIB_WIDEN);
index 4f4dc4160c16a002218b27a6c1a49670295bd793..631352fee6d23861b3642e57c18ea713e84d9c7a 100644 (file)
@@ -316,6 +316,9 @@ struct loop_info
   int has_multiple_exit_targets;
   /* Nonzero if there is an indirect jump in the current function.  */
   int has_indirect_jump;
+  /* Whether loop unrolling has emitted copies of the loop body so
+     that the main loop needs no exit tests.  */
+  int preconditioned;
   /* Register or constant initial loop value.  */
   rtx initial_value;
   /* Register or constant value used for comparison test.  */
index e0b0d36579d109b723cf8ab555c82f7c4c9298c8..c8201ed6336361b153f76f80a250b61efc89ef5d 100644 (file)
@@ -1135,6 +1135,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
   /* Keep track of the unroll factor for the loop.  */
   loop_info->unroll_number = unroll_number;
 
+  /* And whether the loop has been preconditioned.  */
+  loop_info->preconditioned = loop_preconditioned;
+
   /* For each biv and giv, determine whether it can be safely split into
      a different variable for each unrolled copy of the loop body.
      We precalculate and save this info here, since computing it is