This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Loop reversal code misses a check
- To: gcc-patches at gcc dot gnu dot org
- Subject: [PATCH] Loop reversal code misses a check
- From: Franz Sirl <Franz dot Sirl-kernel at lauterbach dot com>
- Date: Sat, 24 Feb 2001 19:20:42 +0100
Hi,
the attached testcase fails on powerpc-linux-gnu if compiled with -O2. We end
up with 2 BIVs reg83 and reg84, where reg84 is set from reg83. reg83 is the
loop count register and is considered for inc->dec conversion in
check_dbra_loop. In there we end up reverting the loop, cause
no_use_except_counting remains at 1. The BIV replacing code then ends up
incorrectly replacing uses of reg84, causing access of the wrong array member
in &psd[j] in the testcase.
My solution is to check for the loop reg in the init_set of all BIVs too and
clearing no_use_except_counting accordingly, this fixes the testcase.
OK to commit patch and testcase to mainline and branch if the bootstrap (PPC
and x86) succeeds?
Franz.
* loop.c (check_dbra_loop): A biv has uses besides counting if it is
used to set another biv.
extern void abort (void);
typedef signed short int16_t;
typedef unsigned short uint16_t;
int16_t logadd (int16_t *a, int16_t *b);
void ba_compute_psd (int16_t start);
int16_t masktab[6] = { 1, 2, 3, 4, 5};
int16_t psd[6] = { 50, 40, 30, 20, 10};
int16_t bndpsd[6] = { 1, 2, 3, 4, 5};
void ba_compute_psd (int16_t start)
{
int i,j,k;
int16_t lastbin = 4;
j = start;
k = masktab[start];
bndpsd[k] = psd[j];
j++;
for (i = j; i < lastbin; i++) {
bndpsd[k] = logadd(&bndpsd[k], &psd[j]);
j++;
}
}
int16_t logadd (int16_t *a, int16_t *b)
{
return *a + *b;
}
int main (void)
{
int i;
ba_compute_psd (0);
if (bndpsd[1] != 140) abort ();
return 0;
}
Index: gcc/loop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop.c,v
retrieving revision 1.322
diff -u -p -r1.322 loop.c
--- gcc/loop.c 2001/01/26 22:06:41 1.322
+++ gcc/loop.c 2001/02/24 18:14:29
@@ -7259,6 +7259,7 @@ check_dbra_loop (loop, insn_count)
if (bl->giv_count == 0 && ! loop->exit_count)
{
rtx bivreg = regno_reg_rtx[bl->regno];
+ struct iv_class *blt;
/* If there are no givs for this biv, and the only exit is the
fall through at the end of the loop, then
@@ -7294,6 +7295,14 @@ check_dbra_loop (loop, insn_count)
no_use_except_counting = 0;
break;
}
+ }
+
+ /* A biv has uses besides counting if it is used to set another biv. */
+ for (blt = ivs->list; blt; blt = blt->next)
+ if (blt->init_set && reg_mentioned_p (bivreg, SET_SRC (blt->init_set)))
+ {
+ no_use_except_counting = 0;
+ break;
}
}