piet@ruuinf (Piet van Oostrum) (02/16/89)
------------------------------------------------------------------------
combine.c tries to optimize (SUBREG:m (MEM:n ...) k) RTL's and does not
take into account the BIG-endianness of the computer.
(This is on gcc version 1.32).
This generates wrong addresses when m<n (e.g. m=QI and n=SI).
This strikes the tahoe/hcx when a shift instruction is used with a
parameter as the shift count and the count is not loaded in a register.
e.g.
test(i,j)
unsigned i, j[];
{
j[0] |= (1<<i);
}
A patch for updating addresses in combine.c follows.
------------------------------------------------------------------------
*** combine.c.~1~ Tue Jan 17 13:49:03 1989
--- combine.c Wed Feb 15 16:33:38 1989
***************
*** 879,884
if (SUBREG_REG (x) == to
&& GET_CODE (to) == MEM)
{
if (!undobuf.storage)
undobuf.storage = (char *) oballoc (0);
/* Note if the plus_constant doesn't make a valid address
--- 879,885 -----
if (SUBREG_REG (x) == to
&& GET_CODE (to) == MEM)
{
+ register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
if (!undobuf.storage)
undobuf.storage = (char *) oballoc (0);
/* Note if the plus_constant doesn't make a valid address
***************
*** 883,888
undobuf.storage = (char *) oballoc (0);
/* Note if the plus_constant doesn't make a valid address
then this combination won't be accepted. */
return gen_rtx (MEM, GET_MODE (x),
plus_constant (XEXP (to, 0),
SUBREG_WORD (x) * UNITS_PER_WORD));
--- 884,893 -----
undobuf.storage = (char *) oballoc (0);
/* Note if the plus_constant doesn't make a valid address
then this combination won't be accepted. */
+ #ifdef BYTES_BIG_ENDIAN
+ offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
+ - min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (to))));
+ #endif
return gen_rtx (MEM, GET_MODE (x),
plus_constant (XEXP (to, 0), offset));
}
***************
*** 884,891
/* Note if the plus_constant doesn't make a valid address
then this combination won't be accepted. */
return gen_rtx (MEM, GET_MODE (x),
! plus_constant (XEXP (to, 0),
! SUBREG_WORD (x) * UNITS_PER_WORD));
}
break;
--- 889,895 -----
- min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (to))));
#endif
return gen_rtx (MEM, GET_MODE (x),
! plus_constant (XEXP (to, 0), offset));
}
break;
------------------------------------------------------------------------
Another thing which I wouldn't call a bug (maybe it was on purpose) is that
combine.c does not try to combine a binary operation with its two operands.
(it only tries to distribute the operation)
There is code in it for a special case but that is disabled.
Here is a patch to enable the code. Alternatively it could be integrated in
the distribution loop.
------------------------------------------------------------------------
***************
*** 325,330
|| GET_CODE (SET_DEST (PATTERN (insn))) == SIGN_EXTRACT
|| GET_CODE (SET_SRC (PATTERN (insn))) == ZERO_EXTRACT
|| GET_CODE (SET_SRC (PATTERN (insn))) == SIGN_EXTRACT))
{
for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
if (GET_CODE (XEXP (links, 0)) != NOTE)
--- 325,331 -----
|| GET_CODE (SET_DEST (PATTERN (insn))) == SIGN_EXTRACT
|| GET_CODE (SET_SRC (PATTERN (insn))) == ZERO_EXTRACT
|| GET_CODE (SET_SRC (PATTERN (insn))) == SIGN_EXTRACT))
+ #endif
{
for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
if (GET_CODE (XEXP (links, 0)) != NOTE)
***************
*** 333,339
if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0)))
goto retry;
}
- #endif
record_dead_and_set_regs (insn);
prev = insn;
}
--- 334,339 -----
if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0)))
goto retry;
}
record_dead_and_set_regs (insn);
prev = insn;
}
--
Piet van Oostrum, Dept of Computer Science, University of Utrecht
Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands
Telephone: +31-30-531806. piet@cs.ruu.nl (mcvax!hp4nl!ruuinf!piet)