From: Al Viro <[EMAIL PROTECTED]>
Date: Sat, 7 Jan 2006 09:39:10 +0000
> BTW, is there any reason why
> static inline void ip_eth_mc_map(u32 addr, char *buf)
> {
> addr=ntohl(addr);
> buf[0]=0x01;
> buf[1]=0x00;
> buf[2]=0x5e;
> buf[5]=addr&0xFF;
> addr>>=8;
> buf[4]=addr&0xFF;
> addr>>=8;
> buf[3]=addr&0x7F;
> }
> is not doing just
> unsigned char *p = &addr;
> buf[0]=0x01;
> buf[1]=0x00;
> buf[2]=0x5e;
> buf[3]=p[1]&0x7F;
> buf[4]=p[2];
> buf[5]=p[3];
Because GCC can't make anything reasonable with it.
And besides wouldn't that need to be:
buf[3]=p[3]&0x7F;
buf[4]=p[2];
buf[5]=p[1];
on big-endian? :-)
GCC isn't (currently) smart enough to avoid tossing addr onto the
stack when you do the pointer games like that. With gcc-4.0.2 on
sparc I get:
mov 1, %g1
st %o0, [%sp+68]
mov 94, %g2
stb %g1, [%o1]
ldub [%sp+69], %g1
and %g1, 127, %g1
stb %g2, [%o1+2]
stb %g1, [%o1+3]
ldub [%sp+70], %g2
ldub [%sp+71], %g1
stb %g0, [%o1+1]
stb %g2, [%o1+4]
jmp %o7+8
stb %g1, [%o1+5]
That's with -O2, 32-bit.
Even when inlined and working with constant 'addr', gcc still sticks
it onto the stack.
For some reason it's scalar optimizations aren't transforming this.
Probably because we're changing the type with that cast, thus breaking
strict aliasing rules and all bets are off.
I hacked it to use a union, and it did the right thing in all cases
when inlining, but when not inlined on 32-bit sparc it still used the
stack because all aggregates are passed by reference on 32-bit sparc.
So, it's probably fine the way it is :-)
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html