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)