diff options
author | kan <kan@FreeBSD.org> | 2002-10-10 04:40:18 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2002-10-10 04:40:18 +0000 |
commit | 92318bc515d223b2eeebb665f76e131dd2318b2b (patch) | |
tree | f505e08c93c8d3d8e51f5dac050b459cce4d4ae2 /contrib/gcc/doloop.c | |
parent | 48f00f4c43af857e09b5f961c806a8811c504a3c (diff) | |
download | FreeBSD-src-92318bc515d223b2eeebb665f76e131dd2318b2b.zip FreeBSD-src-92318bc515d223b2eeebb665f76e131dd2318b2b.tar.gz |
Gcc 3.2.1-prerelease from the FSF anoncvs repo gcc-3_2-branch on October 9th 2002 20:15 EST.
Diffstat (limited to 'contrib/gcc/doloop.c')
-rw-r--r-- | contrib/gcc/doloop.c | 93 |
1 files changed, 40 insertions, 53 deletions
diff --git a/contrib/gcc/doloop.c b/contrib/gcc/doloop.c index 6c0185c..06d8d57 100644 --- a/contrib/gcc/doloop.c +++ b/contrib/gcc/doloop.c @@ -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; @@ -591,13 +592,22 @@ doloop_modify_runtime (loop, iterations_max, n = abs (final - initial) / abs_inc; n += (abs (final - initial) % abs_inc) != 0; - 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 + 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. - t1 = abs_inc * unroll_number; - n = abs (final - initial) / t1; - n += (abs (final - initial) % t1) > t1 - abs_inc; + If the loop has been unrolled, the full calculation is + + 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 @@ -658,58 +668,32 @@ doloop_modify_runtime (loop, iterations_max, fprintf (loop_dump_stream, "Doloop: Basic induction var skips initial incr.\n"); - diff = expand_simple_binop (mode, PLUS, diff, increment, diff, - unsigned_p, OPTAB_LIB_WIDEN); + diff = expand_simple_binop (mode, PLUS, diff, GEN_INT (abs_inc), + diff, unsigned_p, OPTAB_LIB_WIDEN); } } - 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; - rtx extra; - rtx label; - unsigned HOST_WIDE_INT limit; - shift_count = exact_log2 (abs_inc * loop_info->unroll_number); + shift_count = exact_log2 (abs_loop_inc); 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); + if (!loop_info->preconditioned) + diff = expand_simple_binop (GET_MODE (diff), PLUS, + diff, GEN_INT (abs_loop_inc - 1), + diff, 1, OPTAB_LIB_WIDEN); - emit_label (label); - } + /* (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); } - 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 +706,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(); |