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]