aboutsummaryrefslogtreecommitdiff
path: root/gcc/doloop.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2002-06-24 02:16:42 +0000
committerAlan Modra <amodra@gcc.gnu.org>2002-06-24 11:46:42 +0930
commit0228d06bca95f3605ab1a1558a6ca9e3aa88c028 (patch)
tree01411c204559a7b25819c92b3f56e0a36f0233e8 /gcc/doloop.c
parent17ba19fe451119f57fc499b06bff45c53251a7db (diff)
downloadgcc-0228d06bca95f3605ab1a1558a6ca9e3aa88c028.zip
gcc-0228d06bca95f3605ab1a1558a6ca9e3aa88c028.tar.gz
gcc-0228d06bca95f3605ab1a1558a6ca9e3aa88c028.tar.bz2
doloop.c (doloop_valid_p): Correct comment.
* doloop.c (doloop_valid_p): Correct comment. (doloop_modify_runtime <abs_inc != 1>): Simplify. (doloop_modify_runtime <do-while>): Don't emit code when NE. From-SVN: r54938
Diffstat (limited to 'gcc/doloop.c')
-rw-r--r--gcc/doloop.c69
1 files changed, 24 insertions, 45 deletions
diff --git a/gcc/doloop.c b/gcc/doloop.c
index de59562..ee5b788 100644
--- a/gcc/doloop.c
+++ b/gcc/doloop.c
@@ -361,8 +361,8 @@ doloop_valid_p (loop, jump_insn)
{
/* If the comparison is LEU and the comparison value is UINT_MAX
then the loop will not terminate. Similarly, if the
- comparison code is GEU and the initial value is 0, the loop
- will not terminate.
+ comparison code is GEU and the comparison value is 0, the
+ loop will not terminate.
If the absolute increment is not 1, the loop can be infinite
even with LTU/GTU, e.g. for (i = 3; i > 0; i -= 2)
@@ -591,6 +591,10 @@ doloop_modify_runtime (loop, iterations_max,
n = abs (final - initial) / abs_inc;
n += (abs (final - initial) % abs_inc) != 0;
+ But when abs_inc is a power of two, the summation won't overflow
+ 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
@@ -666,50 +670,22 @@ doloop_modify_runtime (loop, iterations_max,
if (abs_inc * loop_info->unroll_number != 1)
{
int shift_count;
- rtx extra;
- rtx label;
- unsigned HOST_WIDE_INT limit;
shift_count = exact_log2 (abs_inc * loop_info->unroll_number);
if (shift_count < 0)
abort ();
- /* abs (final - initial) / (abs_inc * unroll_number) */
- iterations = expand_simple_binop (GET_MODE (diff), LSHIFTRT,
- diff, GEN_INT (shift_count),
- NULL_RTX, 1,
- OPTAB_LIB_WIDEN);
-
if (abs_inc != 1)
- {
- /* abs (final - initial) % (abs_inc * unroll_number) */
- rtx count = GEN_INT (abs_inc * loop_info->unroll_number - 1);
- extra = expand_simple_binop (GET_MODE (iterations), AND,
- diff, count, NULL_RTX, 1,
- OPTAB_LIB_WIDEN);
-
- /* If (abs (final - initial) % (abs_inc * unroll_number)
- <= abs_inc * (unroll - 1)),
- jump past following increment instruction. */
- label = gen_label_rtx ();
- limit = abs_inc * (loop_info->unroll_number - 1);
- emit_cmp_and_jump_insns (extra, GEN_INT (limit),
- limit == 0 ? EQ : LEU, NULL_RTX,
- GET_MODE (extra), 0, label);
- JUMP_LABEL (get_last_insn ()) = label;
- LABEL_NUSES (label)++;
-
- /* Increment the iteration count by one. */
- iterations = expand_simple_binop (GET_MODE (iterations), PLUS,
- iterations, GEN_INT (1),
- iterations, 1,
- OPTAB_LIB_WIDEN);
-
- emit_label (label);
- }
+ diff = expand_simple_binop (GET_MODE (diff), PLUS,
+ diff, GEN_INT (abs_inc - 1),
+ diff, 1, OPTAB_LIB_WIDEN);
+
+ /* (abs (final - initial) + abs_inc - 1) / (abs_inc * unroll_number) */
+ diff = expand_simple_binop (GET_MODE (diff), LSHIFTRT,
+ diff, GEN_INT (shift_count),
+ diff, 1, OPTAB_LIB_WIDEN);
}
- else
- iterations = diff;
+ iterations = diff;
/* If there is a NOTE_INSN_LOOP_VTOP, we have a `for' or `while'
style loop, with a loop exit test at the start. Thus, we can
@@ -722,17 +698,20 @@ doloop_modify_runtime (loop, iterations_max,
iteration count to one if necessary. */
if (! loop->vtop)
{
- rtx label;
-
if (loop_dump_stream)
fprintf (loop_dump_stream, "Doloop: Do-while loop.\n");
- /* A `do-while' loop must iterate at least once. If the
- iteration count is bogus, we set the iteration count to 1.
+ /* A `do-while' loop must iterate at least once. For code like
+ i = initial; do { ... } while (++i < final);
+ we will calculate a bogus iteration count if initial > final.
+ So detect this and set the iteration count to 1.
Note that if the loop has been unrolled, then the loop body
- is guaranteed to execute at least once. */
- if (loop_info->unroll_number == 1)
+ is guaranteed to execute at least once. Also, when the
+ comparison is NE, our calculated count will be OK. */
+ if (loop_info->unroll_number == 1 && comparison_code != NE)
{
+ rtx label;
+
/* Emit insns to test if the loop will immediately
terminate and to set the iteration count to 1 if true. */
label = gen_label_rtx();