minor problems in loop.c for c4x target

Herman ten Brugge Haj.Ten.Brugge@net.HCC.nl
Mon Oct 5 12:31:00 GMT 1998


Hello,

I noticed a small problem in loop.c in move_movables. The insn_count was
multiplied by two when a register was moved_once. This also means that
any register in the movables chain after this register uses also this
higher threshold. I noticed this problem in the test program:

void fzero2(float *foo, int xsize, int ysize)
{
  int i, j;

  for (i = 0; i < ysize; i++)
    for (j = 0; j < xsize; j++)
      foo[i * xsize + j] = 0.0;
}

void fzero2t(float *foo, int xsize, int ysize)
{
  int i, j;

  for (j = 0; j < xsize; j++)
    for (i = 0; i < ysize; i++)
      foo[i * xsize + j] = 0.0;
}

In the first function the constant 0.0 was not moved out of the loop in the
second function it was. This was on the c4x target where you cannot store
immediate values into memory. You have to put the value first in a register.

1998-10-05 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>

        * loop.c (move_movables): Corrected threshold calculation for
	moved_once registers.

--- loop.c.org	Fri Oct  2 23:03:27 1998
+++ loop.c	Mon Oct  5 20:52:07 1998
@@ -1827,13 +1827,8 @@ move_movables (movables, threshold, insn
 	  if (loop_dump_stream)
 	    fprintf (loop_dump_stream, "savings %d ", savings);
 
-	  if (moved_once[regno])
-	    {
-	      insn_count *= 2;
-
-	      if (loop_dump_stream)
-		fprintf (loop_dump_stream, "halved since already moved ");
-	    }
+	  if (moved_once[regno] && loop_dump_stream)
+	    fprintf (loop_dump_stream, "halved since already moved ");
 
 	  /* An insn MUST be moved if we already moved something else
 	     which is safe only if this one is moved too: that is,
@@ -1850,7 +1845,8 @@ move_movables (movables, threshold, insn
 
 	  if (already_moved[regno]
 	      || flag_move_all_movables
-	      || (threshold * savings * m->lifetime) >= insn_count
+	      || (threshold * savings * m->lifetime) >=
+		 (moved_once[regno] ? insn_count * 2 : insn_count)
 	      || (m->forces && m->forces->done
 		  && VARRAY_INT (n_times_used, m->forces->regno) == 1))
 	    {



I also found another problem in loop.c. The torture test loop-2d.c failed
for the c4x 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 assembly code 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 probably only shows on this target because
it has no 32*32 multiply instruction. The best it can do is a 24*24 bit
multiply. Gcc tries to move this multiply (shift and add) out of the loop
with the above result.

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-patches mailing list