Xref: utzoo comp.lang.c:15713 comp.emacs:5134 Path: utzoo!utgpu!attcan!uunet!tank!ncar!noao!arizona!modular!olson From: olson@modular.UUCP (Jon Olson) Newsgroups: comp.lang.c,comp.emacs Subject: Optimization bug in GCC V1.32 on BIG_ENDIAN machines Message-ID: <642@modular.UUCP> Date: 22 Jan 89 04:36:26 GMT Distribution: comp Organization: Modular Mining Systems, Tucson, AZ Lines: 76 I am sending out this GCC bug-report out to a couple likely newsgroups since I have no luck reaching the gcc-bug account of gcc-bug@prep.ai.mit.edu. Hopefully someone will see this who knows to forward to its appropriate destination. I tracked down a rather annoying bug in GCC V1.32 on SUNOS 4.0 the other day. The small test program below demonstrates this bug: struct TEST { unsigned char c; unsigned short s; int i; } r1, r2, r3; main() { foo( &r1, 1, 2, 3 ); printf( "c = %d, s = %d, i = %d\n", r1.c, r1.s, r1.i ); } foo( p, i1, i2, i3 ) struct TEST *p; int i1, i2, i3; { p->c = i1; /* Here, GCC generates moveb a6@(12),a0@ */ p->s = i2; p->i = i3; } After a bit of digging I found the problem lied in some missing logic in `combine.c' with respect to big-endian machines. During optimization, this code forgot to add in the extra 3-bytes required to extract the low byte of `i1' instead of the high byte. Below are the context diffs for the change I made to fix the bug. Maybe somebody should go through GCC carefully to make sure that there are no other such big-endian machine problems??? *** combine.c.save Sat Jan 21 20:45:51 1989 --- combine.c Sat Jan 21 21:02:39 1989 *************** *** 878,891 **** paradoxical case where gen_lowpart_for_combine makes them. */ 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 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; --- 878,895 ---- paradoxical case where gen_lowpart_for_combine makes them. */ if (SUBREG_REG (x) == to && GET_CODE (to) == MEM) ! {/****** JPO: Fixed this for BIG-ENDIAN machines*****/ ! register int offset = SUBREG_WORD (x) * UNITS_PER_WORD; ! #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 if (!undobuf.storage) 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), offset)); } break;