Thread View: gnu.gcc.bug
1 messages
1 total messages
Started by trm
Thu, 29 Oct 1992 13:53
gcc/i860 bug report
Author: trm
Date: Thu, 29 Oct 1992 13:53
Date: Thu, 29 Oct 1992 13:53
134 lines
4288 bytes
4288 bytes
These bug reports are for GCC version 2.2.2 compiled as a cross compiler
for an i860/SVR4 target on a SPARCstation host. I have two bugs to report.
The configure command had arguments i860-sysv4 and --host sun4. The
i860.h file was changed to define BYTES_BIG_ENDING and WORDS_BIG_ENDIAN to
one because this target machine uses the i860 that way.
1) GCC has a bug in the common subexpression elimination optimization
step. It is too optimistic about the use of varying addresses to
access memory. The note_mem_written procedure in cse.c was changed to
fix the bug. Here is an example program:
void bar(void *val)
{
printf("%x\n", (unsigned long)val);
}
void foo(void *addr, long *val)
{
unsigned long lval = 42;
((char *)&lval)[(unsigned long)addr & 3] = 6;
bar((void *)lval);
}
main()
{
unsigned long x = 3;
foo(0, (void*)x);
}
When this program is compiled with just the -O option, the change to the
local variable lval is lost when lval is passed to the bar function so
2a is printed rather than 600002A. To fix the bug, I commented out some
lines in cse.c, the note_mem_written function as shown below:
else if (cse_rtx_addr_varies_p (written))
{
/* A varying address that is a sum indicates an array element,
and that's just as good as a structure element
in implying that we need not invalidate scalar variables. */
/*
* if (!(MEM_IN_STRUCT_P (written)
* || GET_CODE (XEXP (written, 0)) == PLUS))
*/
writes_ptr->all = 1;
writes_ptr->nonscalar = 1;
}
There's probably a better way to fix this problem but it seems to be working
for me.
2) There is a bug in final.c, alter_subreg() due to the WORD_BIG_ENDIAN
change that I made. This caused multiplies to work incorrectly when the
number of local variables spilled over from registers into memory.
Here is an example program to demonstrate the bug:
bar()
{
char x[10000];
memset(x, 'z', 10000);
}
foo(int z)
{
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
int a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
int x;
a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = a10 = z;
a11 = a12 = a13 = a14 = a15 = a16 = a17 = a18 = a19 = a20 = z;
x = a1 * a2 * a3 * a4 * a5 * a6 * a7 * a8 * a9 * a10*
a11 * a12 * a13 * a14 * a15 * a16 * a17 * a18 * a19 * a20;
printf("x = %d (should be 1)\n", x);
}
main()
{
bar();
foo(1);
}
When this program is compiled with the -O option, it prints a garbage value
rather than 1.
To fix the bug, I changed alter_subreg as follows:
rtx
alter_subreg (x)
register rtx x;
{
register rtx y = SUBREG_REG (x);
if (GET_CODE (y) == SUBREG)
y = alter_subreg (y);
if (GET_CODE (y) == REG)
{
/* If the containing reg really gets a hard reg, so do we. */
PUT_CODE (x, REG);
REGNO (x) = REGNO (y) + SUBREG_WORD (x);
}
else if (GET_CODE (y) == MEM)
{
#if WORDS_BIG_ENDIAN
register int offset =
GET_MODE_SIZE (GET_MODE (y)) - (SUBREG_WORD (x) + 1) * UNITS_PER_WORD;
#else
register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
#endif
/*
* printf("alter_subreg: offset=%d, word=%d, y mode size=%d\n",
* offset, SUBREG_WORD(x), GET_MODE_SIZE (GET_MODE (y)));
*/
#if BYTES_BIG_ENDIAN
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
#endif
PUT_CODE (x, MEM);
MEM_VOLATILE_P (x) = MEM_VOLATILE_P (y);
XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
}
return x;
}
The #if WORDS_BIG_ENDIAN statement was added. Again, there may be a better
way to fix the problem but this is working for me.
Tom Mueller AT&T Bell Laboratories (CBE 64E-327)
(614) 860-5287 6400 East Broad Street
trm@cblpn.cb.att.com Columbus, OH 43213
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads