[PATCH xserver 3/2] Rewrite the byte swapping macros.

Eric Anholt eric at anholt.net
Tue Mar 28 19:52:47 UTC 2017


Peter Hutterer <peter.hutterer at who-t.net> writes:

> On Mon, Mar 27, 2017 at 03:11:03PM -0700, Eric Anholt wrote:
>> The clever pointer tricks were actually not working, and we were doing
>> the byte-by-byte moves in general.  By just doing the memcpy and
>> obvious byte swap code, we end up generating actual byte swap
>> instructions, thanks to optimizing compilers.
>> 
>>          text	   data	    bss	    dec	    hex	filename
>> before: 2241932	  51584	 132016	2425532	 2502bc	hw/xfree86/Xorg
>> after:  2216276	  51584	 132016	2399876	 249e84	hw/xfree86/Xorg
>> ---
>>  doc/Xserver-spec.xml |  2 +-
>>  glx/glxbyteorder.h   | 21 ------------
>>  include/misc.h       | 97 ++++++++++++++++++----------------------------------
>>  os/io.c              |  4 +--
>>  4 files changed, 37 insertions(+), 87 deletions(-)
>> 
>> diff --git a/doc/Xserver-spec.xml b/doc/Xserver-spec.xml
>> index 7867544e48a9..3dde65178b7f 100644
>> --- a/doc/Xserver-spec.xml
>> +++ b/doc/Xserver-spec.xml
>> @@ -600,7 +600,7 @@ are: REQUEST, REQUEST_SIZE_MATCH, REQUEST_AT_LEAST_SIZE,
>>  REQUEST_FIXED_SIZE, LEGAL_NEW_RESOURCE, and
>>  VALIDATE_DRAWABLE_AND_GC. Useful byte swapping macros can be found
>>  in Xserver/include/dix.h: WriteReplyToClient and WriteSwappedDataToClient; and
>> -in Xserver/include/misc.h: lswapl, lswaps, LengthRestB, LengthRestS,
>> +in Xserver/include/misc.h: bswap_64, bswap_32, bswap_16, LengthRestB, LengthRestS,
>>  LengthRestL, SwapRestS, SwapRestL, swapl, swaps, cpswapl, and cpswaps.</para>
>>  </section>
>>  </section>
>> diff --git a/glx/glxbyteorder.h b/glx/glxbyteorder.h
>> index 5e94e8626e66..8f0cd8a4b0d7 100644
>> --- a/glx/glxbyteorder.h
>> +++ b/glx/glxbyteorder.h
>> @@ -37,25 +37,4 @@
>>  
>>  #include "misc.h"
>>  
>> -static inline uint16_t
>> -bswap_16(uint16_t val)
>> -{
>> -    swap_uint16(&val);
>> -    return val;
>> -}
>> -
>> -static inline uint32_t
>> -bswap_32(uint32_t val)
>> -{
>> -    swap_uint32(&val);
>> -    return val;
>> -}
>> -
>> -static inline uint64_t
>> -bswap_64(uint64_t val)
>> -{
>> -    swap_uint64(&val);
>> -    return val;
>> -}
>> -
>>  #endif                          /* !defined(__GLXBYTEORDER_H__) */
>> diff --git a/include/misc.h b/include/misc.h
>> index 01747fd38339..a75eb617c642 100644
>> --- a/include/misc.h
>> +++ b/include/misc.h
>> @@ -128,21 +128,6 @@ typedef struct _xReq *xReqPtr;
>>  #define USE_BACKGROUND_PIXEL 3
>>  #define USE_BORDER_PIXEL 3
>>  
>> -/* byte swap a 32-bit literal */
>> -static inline uint32_t
>> -lswapl(uint32_t x)
>> -{
>> -    return ((x & 0xff) << 24) |
>> -        ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x >> 24) & 0xff);
>> -}
>> -
>> -/* byte swap a 16-bit literal */
>> -static inline uint16_t
>> -lswaps(uint16_t x)
>> -{
>> -    return (uint16_t)((x & 0xff) << 8) | ((x >> 8) & 0xff);
>> -}
>> -
>>  #undef min
>>  #undef max
>>  
>> @@ -311,88 +296,74 @@ __builtin_constant_p(int x)
>>  }
>>  #endif
>>  
>> -/* byte swap a 64-bit value */
>> -static inline void
>> -swap_uint64(uint64_t *x)
>> +static inline uint64_t
>> +bswap_64(uint64_t x)
>>  {
>> -    char n;
>> -
>> -    n = ((char *) x)[0];
>> -    ((char *) x)[0] = ((char *) x)[7];
>> -    ((char *) x)[7] = n;
>> -
>> -    n = ((char *) x)[1];
>> -    ((char *) x)[1] = ((char *) x)[6];
>> -    ((char *) x)[6] = n;
>> -
>> -    n = ((char *) x)[2];
>> -    ((char *) x)[2] = ((char *) x)[5];
>> -    ((char *) x)[5] = n;
>> -
>> -    n = ((char *) x)[3];
>> -    ((char *) x)[3] = ((char *) x)[4];
>> -    ((char *) x)[4] = n;
>> +    return (((x & 0xFF00000000000000ull) >> 56) |
>> +            ((x & 0x00FF000000000000ull) >> 40) |
>> +            ((x & 0x0000FF0000000000ull) >> 24) |
>> +            ((x & 0x000000FF00000000ull) >>  8) |
>> +            ((x & 0x00000000FF000000ull) <<  8) |
>> +            ((x & 0x0000000000FF0000ull) << 24) |
>> +            ((x & 0x000000000000FF00ull) << 40) |
>> +            ((x & 0x00000000000000FFull) << 56));
>>  }
>>  
>>  #define swapll(x) do { \
>> +		uint64_t temp; \
>>  		if (sizeof(*(x)) != 8) \
>>  			wrong_size(); \
>> -                swap_uint64((uint64_t *)(x));   \
>> +		memcpy(&temp, x, 8); \
>> +		temp = bswap_64(temp); \
>> +		memcpy(x, &temp, 8); \
>
> is the memcpy really needed here? am I missing something? We're passing by
> value into bswap_64() now, so we get the copy for free anyway. Same in the
> swapl below.
>
> fwiww, test/misc.c would be trivially amended to test all of these macros
> for correctness :)

Unaligned accesses trap on some platforms, and I don't think we're
guaranteed that the caller has the pointer aligned (at least, the
previous code seemed pretty clearly to be trying to work around that, as
well).

I do like the unit test plan, though.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <https://lists.x.org/archives/xorg-devel/attachments/20170328/26d04891/attachment.sig>


More information about the xorg-devel mailing list