This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
minor problems in loop.c for c4x target
- To: egcs-patches at cygnus dot com
- Subject: minor problems in loop.c for c4x target
- From: Herman ten Brugge <Haj dot Ten dot Brugge at net dot HCC dot nl>
- Date: Mon, 5 Oct 1998 21:31:14 +0100 (WEST)
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