If the loop has been unrolled, the full calculation is
- t1 = abs_inc * unroll_number; increment per loop
- n = (abs (final - initial) + abs_inc - 1) / t1; full loops
- n += (abs (final - initial) + abs_inc - 1) % t1) >= abs_inc;
- partial loop
- which works out to be equivalent to
+ t1 = abs_inc * unroll_number; increment per loop
+ n = abs (final - initial) / t1; full loops
+ n += (abs (final - initial) % t1) != 0; partial loop
- n = (abs (final - initial) + t1 - 1) / t1;
-
- In the case where the loop was preconditioned, a few iterations
- may have been executed earlier; but 'initial' was adjusted as they
- were executed, so we don't need anything special for that case here.
- As above, when t1 is a power of two we don't need to worry about
- overflow.
+ 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
if (shift_count < 0)
abort ();
- /* (abs (final - initial) + abs_inc * unroll_number - 1) */
- diff = expand_simple_binop (GET_MODE (diff), PLUS,
- diff, GEN_INT (abs_loop_inc - 1),
- diff, 1, OPTAB_LIB_WIDEN);
+ if (!loop_info->preconditioned)
+ diff = expand_simple_binop (GET_MODE (diff), PLUS,
+ diff, GEN_INT (abs_loop_inc - 1),
+ diff, 1, OPTAB_LIB_WIDEN);
/* (abs (final - initial) + abs_inc * unroll_number - 1)
/ (abs_inc * unroll_number) */
&& REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)])
return 0;
- /* Out-of-range regs can occur when we are called from unrolling.
- These have always been created by the unroller and are set in
- the loop, hence are never invariant. */
-
- if (REGNO (x) >= regs->num)
- return 0;
-
if (regs->array[REGNO (x)].set_in_loop < 0)
return 2;
--- /dev/null
+/* PR optimization/8599 */
+/* { dg-do run } */
+/* { dg-options "-O2 -funroll-loops" } */
+/* { dg-options "-mcpu=k6 -O2 -funroll-loops" { target i?86-*-* } } */
+
+extern void abort (void);
+
+int array[6] = { 1,2,3,4,5,6 };
+
+void foo()
+{
+ int i;
+
+ for (i = 0; i < 5; i++)
+ array[i] = 0;
+}
+
+int main()
+{
+ foo();
+ if (array[0] || array [1] || array[2] || array[3] || array[4])
+ abort ();
+ if (array[5] != 6)
+ abort ();
+ return 0;
+}