andrew@frip.WV.TEK.COM (Andrew Klossner) (09/09/89)
At the end of this note is a program which was whittled down from libg++/src/BitStream.cc. It illustrates a problem which causes G++ to generate a fullword store to an address that is not fullword aligned. GCC does not share this problem. This is from GCC 1.35 and G++ 1.35.1-, with m88k back-end work from Michael Meissner (meissner@dg-rtp.DG.COM). qq() is an inline function which returns an unsigned short. e is a local variable, declared unsigned short. The statement unsigned short e = qq(p, b, 0, 0); compiles to code which, on the 88k, ends with st r24,r30,0x2a {write r24 to offset 0x2a from the FP} which is improper because 0x2a is not a multiple of 4. I have observed similar bad code from a 68k G++ compiler. While expanding the inline function, integrate.c does this: /* If function's value was promoted before return, avoid machine mode mismatch when we substitute INLINE_TARGET. But TARGET is what we will return to the caller. */ if (arriving_mode != departing_mode) inline_target = gen_rtx (SUBREG, arriving_mode, target, 0); and so builds this insn: (insn/i 37 36 38 (set (subreg:SI (reg/v:HI 37) 0) (reg:SI 56)) -1 (nil) (nil)) then, while spilling registers, reload changes it to (insn 217 221 41 (set (subreg:SI (mem:HI (plus:SI (reg:SI 30) (const_int 44))) 0) (reg:SI 24)) -1 (nil) (nil)) Then final calls alter_subreg to replace the (subreg ...) with (mem:SI (plus:SI (reg:SI 30) (const_int 42))) My gut feel is that the (set (subreg ...)) shouldn't have been built in the first place, but I'm not fluent in GCC/G++ internals. I would be grateful for any suggestions. ============================== the program ============================== static inline unsigned short pp(int a) { return a; } static inline unsigned short qq(unsigned short a[], int b, int c, int d) { if (b < c) return (a[b] >> 1) | (a[b+1] << (16 - d)); else return (a[b] >> d); } int search(unsigned short* p) { int a; int b; int c; int d; int x; unsigned short e = qq(p, b, 0, 0); unsigned short g; unsigned short h; for (;;) { if (a == e) { int f = b; for (;;) { if (++f > d || ++d > c) return 0; g = qq(0, 0, c, c); h = qq(p, 0, a, a); x += h; g &= pp(2 - a); if (g != h) break; } } } } ======================================================================== -=- Andrew Klossner (uunet!tektronix!frip.WV.TEK!andrew) [UUCP] (andrew%frip.wv.tek.com@relay.cs.net) [ARPA]