This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: loop.c overflow problem



  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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]