In the same way that abs, rol and ror are recognized, bswap(int x)
could be identified from:
( x << 24 ) | ( x << 8 ) & 0xff0000 | ( x >> 8 ) & 0xff00 | ( x >> 24 );
and this would be completely portable.
Comment #1 by bearophile_hugs — 2011-12-29T04:21:37Z
(In reply to comment #0)
> In the same way that abs, rol and ror are recognized, bswap(int x)
> could be identified from:
>
> ( x << 24 ) | ( x << 8 ) & 0xff0000 | ( x >> 8 ) & 0xff00 | ( x >> 24 );
>
> and this would be completely portable.
Even if this pattern gets recognized and optimized, I suggest to keep a bswap function in Phobos, to avoid writing all that bug-prone stuff (I'd like a rol/ror function pair too in Phobos).
Comment #2 by clugdbug — 2011-12-29T09:29:47Z
(In reply to comment #1)
> (In reply to comment #0)
> > In the same way that abs, rol and ror are recognized, bswap(int x)
> > could be identified from:
> >
> > ( x << 24 ) | ( x << 8 ) & 0xff0000 | ( x >> 8 ) & 0xff00 | ( x >> 24 );
> >
> > and this would be completely portable.
>
> Even if this pattern gets recognized and optimized, I suggest to keep a bswap
> function in Phobos, to avoid writing all that bug-prone stuff (I'd like a
> rol/ror function pair too in Phobos).
Definitely. It would just change from:
int bswap(int); /* intrinsic */
into
int bswap(int x)
{
return ( x << 24 ) | ( x << 8 ) & 0xff0000 | ( x >> 8 ) & 0xff00 | ( x >> 24 );
}
Comment #3 by andrei — 2011-12-29T12:23:38Z
Wonder if other patterns would need to be figured as well, e.g.
auto p1 = cast(char*) &x;
int y = void;
auto p2 = cast(char*) &y;
p2[0] = p1[3];
p2[1] = p1[2];
p2[2] = p1[1];
p2[3] = p1[0];
Or (probably more realistically) patterns involving temporaries and 2 expressions:
auto y = ( x << 24 ) | ( x << 8 ) & 0xff0000;
y |= ( x >> 8 ) & 0xff00 | ( x >> 24 );
Comment #4 by andrei — 2011-12-29T12:25:27Z
(In reply to comment #2)
> (In reply to comment #1)
> > (In reply to comment #0)
> > > In the same way that abs, rol and ror are recognized, bswap(int x)
> > > could be identified from:
> > >
> > > ( x << 24 ) | ( x << 8 ) & 0xff0000 | ( x >> 8 ) & 0xff00 | ( x >> 24 );
> > >
> > > and this would be completely portable.
> >
> > Even if this pattern gets recognized and optimized, I suggest to keep a bswap
> > function in Phobos, to avoid writing all that bug-prone stuff (I'd like a
> > rol/ror function pair too in Phobos).
>
> Definitely. It would just change from:
>
> int bswap(int); /* intrinsic */
>
> into
>
> int bswap(int x)
> {
> return ( x << 24 ) | ( x << 8 ) & 0xff0000 | ( x >> 8 ) & 0xff00 | ( x >>
> 24 );
> }
I only now realized the meaning of this remark... took me some 10 minutes. Clever.
Comment #5 by bugzilla — 2012-04-16T02:17:30Z
The following is now recognized and replaced with bswap:
(p[0]<<24)|(p[1]<<16)|(p[2]<<8)|(p[3]<<0)
where p is a pointer to a ubyte. I realize that there are many, many ways to write bswap, but this is the recognized one. (The operands to | can at least appear in any order.)
Also,
(p[3]<<24)|(p[2]<<16)|(p[1]<<8)|(p[0]<<0)
is now recognized and replaced with *cast(uint*)p, at least for x86 byte ordering.
What remains to be done is to provide such a body for core.bitop.bswap() and remove bswap from the compiler intrinsics.
For reference:
http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
Comment #6 by robert.schadek — 2024-12-13T17:57:24Z