This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: loop.c overflow problem
- To: Herman ten Brugge <Haj dot Ten dot Brugge at net dot HCC dot nl>
- Subject: Re: loop.c overflow problem
- From: Jeffrey A Law <law at cygnus dot com>
- Date: Thu, 29 Oct 1998 10:41:42 -0700
- cc: egcs-bugs at cygnus dot com
- Reply-To: law at cygnus dot com
In message <199810200616.HAA00974@htbrug.net.HCC.nl>you write:
> Hello,
>
> I found a problem in loop.c. The torture test loop-2d.c failed for the
> c4x and m68k target. This test program looks like:
>
> int a[2];
>
> f (b)
> {
> unsigned int i;
> int *p;
> for (p = &a[b], i = b; --i < ~0; )
> *--p = i * 3 + (int)a;
> }
>
> main ()
> {
> a[0] = a[1] = 0;
> f (2);
> if (a[0] != (int)a || a[1] != (int)a + 3)
> abort ();
> exit (0);
> }
>
> When compiled for the c4x target with '-m30 -O2' options the function f is
> compiled wrong. The same problem is present on the m68k target when compiling
> with -O2 -m68000. Perhaps more targets are effected.
> The assembly code for the c4x is below.
>
> .sect ".const"
> LC0:
> .word _a
> LC1:
> .word _a-6 ; 0081cd508h
> .text
> .global _f
> _f:
> ldiu ar2,r0 - ar2 = input value = b
> ldp @LC0
> ldiu @LC0,r2 - r2 = _a
> addi3 r2,r0,ar0 - ar0 = _a + b
> ldiu r0,r1 - r1 = b
> addi -1,r1 - r1 = b-1
> cmpi -2,r1 - correct test for exit loop
> retshi (~Carry and ~Zero=unsigned com
> pare)
> ldiu r1,r0 - r0 = b-1
> ash 1,r0 - r0 = (b-1) << 1
> addi3 r1,r0,r1 - r0 = (b-1)*3
> addi3 r2,r1,r0 - r0 = _a + (b-1)*3
> ldp @LC1
> ldiu @LC1,r1 - load _a-6 into r1
> L5:
> sti r0,*--ar0 - store value r0 into --ar0
> addi -3,r0 - r0 = r0 - 3
> cmpi3 r1,r0 - test for end
> retshi - incorrect test for exit loop
> br L5
>
> The loop is optimized by eliminating i out of the loop. Instead the
> variable a is used as exit test. The problem is that the compare
> instruction does not work correctly now. The loop is only executed once
> instead of twice. The problem starts when the final compare instruction:
>
> cmp -2,biv->regno
>
> is replaced by:
>
> cmp -2*3+_a,biv->new_reg
>
> -2 = arg
> 3 = mult_val
> _a = add_val
>
> This is not correct because the -2 is an unsigned value. It should read
> 0xfffffffe. This causes an overflow. I found the location of the problem
> in loop.c. I just turned it off with the patch below.
> Some one with more knoledge off biv/giv stuff can probably do a better job.
>
> 1998-10-05 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
>
> * loop.c (maybe_eliminate_biv_1): Disable constant mulval plus
> register addval due to possible overflow.
I would rather see a more selective patch than continuing to just disable
this stuff. Every time we do this we have to climb the optimization hill
again just to get back where we were.
The loop* tests were all written to trigger obscure bugs in the loop optimizer
and we have not considered them a high priority to fix yet.
jeff