re PR rtl-optimization/7130 (miscompiled code for gcc-3.1 on powerpc-unknown-linux-gnu with -funroll-all-loops)

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
This commit is contained in:
Alan Modra 2002-07-20 00:31:15 +00:00 committed by Alan Modra
parent 0dc36574af
commit 8b583747ad
4 changed files with 32 additions and 11 deletions

View 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.

View 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);

View 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. */

View 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