diff options
author | amodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-07-20 00:31:15 +0000 |
---|---|---|
committer | amodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-07-20 00:31:15 +0000 |
commit | 4db1469f863b2b9d82eff8d112a9471a4c94b079 (patch) | |
tree | 94eedd6796f702b3e750b75344a9180da4a76c79 | |
parent | a7ae1e597777179c8b1545a3b56518781f1de909 (diff) | |
download | gcc-4db1469f863b2b9d82eff8d112a9471a4c94b079.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@55598 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/doloop.c | 30 | ||||
-rw-r--r-- | gcc/loop.h | 3 | ||||
-rw-r--r-- | gcc/unroll.c | 3 |
4 files changed, 32 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 69403e0b4db..8fd107b8107 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/doloop.c b/gcc/doloop.c index ee5b788a911..9bddb92ed23 100644 --- a/gcc/doloop.c +++ b/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; @@ -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); diff --git a/gcc/loop.h b/gcc/loop.h index 4f4dc4160c1..631352fee6d 100644 --- a/gcc/loop.h +++ b/gcc/loop.h @@ -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. */ diff --git a/gcc/unroll.c b/gcc/unroll.c index e0b0d36579d..c8201ed6336 100644 --- a/gcc/unroll.c +++ b/gcc/unroll.c @@ -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 |