loop.c overflow problem

Herman ten Brugge Haj.Ten.Brugge@net.HCC.nl
Mon Oct 19 22:17:00 GMT 1998


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 compare)
        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.

--- loop.c.org	Fri Oct  2 23:03:27 1998
+++ loop.c	Mon Oct  5 20:52:07 1998
@@ -7398,7 +7394,8 @@ maybe_eliminate_biv_1 (x, insn, bl, elim
 		&& (GET_CODE (v->add_val) == SYMBOL_REF
 		    || GET_CODE (v->add_val) == LABEL_REF
 		    || GET_CODE (v->add_val) == CONST
-		    || (GET_CODE (v->add_val) == REG
+	     		/* Turn this off due to possible overflow.  */
+		    || (0 && GET_CODE (v->add_val) == REG
 			&& REGNO_POINTER_FLAG (REGNO (v->add_val))))
 		&& ! v->ignore && ! v->maybe_dead && v->always_computable
 		&& v->mode == mode)


-- 
-------------------------------------------------------------------------
Herman ten Brugge			Email:	Haj.Ten.Brugge@net.HCC.nl



More information about the Gcc-bugs mailing list