doloop.c fix for PR 6984
Alan Modra
amodra@bigpond.net.au
Sun Jun 23 18:49:00 GMT 2002
On Sun, Jun 23, 2002 at 02:58:38PM -0700, Richard Henderson wrote:
> On Sat, Jun 22, 2002 at 06:04:06PM +0930, Alan Modra wrote:
> > final == initial + j * inc, for some integer j
> > so final - initial == j * inc
>
> I don't see this part of the setup. Seems to me that
>
> final == initial + j * inc + c
> for c < inc.
I was sloppy, and there's a missing step or two.
Let's try again, for positive increment.
inc is greater than one (doloop_modify_runtime)
inc is a power of two, 2**k say (precondition_loop_p)
the loop terminates with <, >, <= or >= test (doloop_valid_p)
in fact, it must be < or <= (doloop_optimize)
assume the loop terminates (**)
then actual_final == initial + j * inc for some positive integer j
actual_final == test_final + c, 0 <= c < inc for < test, 0 < c <= inc for <=
so test_final - initial == j * inc - c
if the loop terminates, then initial + j * inc can't overflow. (*)
so j * inc can't overflow.
and given width of iterator type is n bits
then j < 2**n / 2**k, or jmax is 2**(n-k) - 1
so test_final - initial + inc - 1 <= jmax * inc - c + inc - 1
== (2**(n-k) - 1) * 2**k - c + 2**k - 1
== 2**n - c - 1
which doesn't overflow.
*) There are a few steps to reach this conclusion too, the first being
that if the expression does overflow, then inc being a power of two
guarantees that when the iterator overflows it repeats the same
values. This doesn't hold for a weird loop like
unsigned int i;
for (i = 1; i < 0xFFFFFFFF; i += 3)
where i overflows a number of times before finally reaching 0xFFFFFFFF.
**) Assuming the loop terminates is really bad, but see the comment
near the end of doloop_valid_p
> However, I wasn't able to construct an example for which
> the original wasn't a non-terminating loop. So I guess
> the patch is ok.
Thanks. May I add these comment corrections too?
* doloop.c (doloop_valid_p): Correct comment.
(doloop_modify_runtime): Likewise.
Index: gcc/doloop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doloop.c,v
retrieving revision 1.19
diff -u -p -r1.19 doloop.c
--- gcc/doloop.c 17 Jun 2002 22:45:44 -0000 1.19
+++ gcc/doloop.c 24 Jun 2002 01:33:36 -0000
@@ -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_
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
--
Alan Modra
IBM OzLabs - Linux Technology Centre
More information about the Gcc-patches
mailing list