diff options
author | Matt Turner <mattst88@gmail.com> | 2019-09-04 21:48:56 -0700 |
---|---|---|
committer | Tony Cook <tony@develop-help.com> | 2019-10-08 09:27:43 +1100 |
commit | e8864dba80952684bf3afe83438d4eee0c3939a9 (patch) | |
tree | ef39f361559ca7cabef294085a643c3742e6d4f5 /hv_macro.h | |
parent | ee9ac1cd8eb988fea70841eae211b11355711416 (diff) | |
download | perl-e8864dba80952684bf3afe83438d4eee0c3939a9.tar.gz |
Clean up U8TO*_LE macro implementations
The code guarded by #ifndef U32_ALIGNMENT_REQUIRED attempts to optimize
byte-swapping by doing unaligned loads, but accessing data through
unaligned pointers is undefined behavior in C. Moreover, compilers are
more than capable of recognizing these open-coded byte-swap patterns and
emitting a bswap instruction, or an unaligned load instruction, or a
combined load, etc. There's no need for multiple paths to attain the
desired result.
See https://rt.perl.org/Ticket/Display.html?id=133495
Diffstat (limited to 'hv_macro.h')
-rw-r--r-- | hv_macro.h | 31 |
1 files changed, 12 insertions, 19 deletions
diff --git a/hv_macro.h b/hv_macro.h index 77a4c84896..02c0baad08 100644 --- a/hv_macro.h +++ b/hv_macro.h @@ -6,7 +6,7 @@ #endif /*----------------------------------------------------------------------------- - * Endianess, misalignment capabilities and util macros + * Endianess and util macros * * The following 3 macros are defined in this section. The other macros defined * are only needed to help derive these 3. @@ -20,29 +20,22 @@ * ROTR64(x,r) Rotate x right by r bits */ -#ifndef U32_ALIGNMENT_REQUIRED +#ifndef U8TO16_LE #if (BYTEORDER == 0x1234 || BYTEORDER == 0x12345678) - #define U8TO16_LE(ptr) (*((const U16*)(ptr))) - #define U8TO32_LE(ptr) (*((const U32*)(ptr))) - #define U8TO64_LE(ptr) (*((const U64*)(ptr))) + #define U8TO16_LE(ptr) ((U32)(ptr)[1]|(U32)(ptr)[0]<<8) + #define U8TO32_LE(ptr) ((U32)(ptr)[3]|(U32)(ptr)[2]<<8|(U32)(ptr)[1]<<16|(U32)(ptr)[0]<<24) + #define U8TO64_LE(ptr) ((U64)(ptr)[7]|(U64)(ptr)[6]<<8|(U64)(ptr)[5]<<16|(U64)(ptr)[4]<<24|\ + (U64)(ptr)[3]<<32|(U64)(ptr)[4]<<40|\ + (U64)(ptr)[1]<<48|(U64)(ptr)[0]<<56) #elif (BYTEORDER == 0x4321 || BYTEORDER == 0x87654321) - #if defined(__GNUC__) && (__GNUC__>4 || (__GNUC__==4 && __GNUC_MINOR__>=3)) - #define U8TO16_LE(ptr) (__builtin_bswap16(*((U16*)(ptr)))) - #define U8TO32_LE(ptr) (__builtin_bswap32(*((U32*)(ptr)))) - #define U8TO64_LE(ptr) (__builtin_bswap64(*((U64*)(ptr)))) - #endif + #define U8TO16_LE(ptr) ((U32)(ptr)[0]|(U32)(ptr)[1]<<8) + #define U8TO32_LE(ptr) ((U32)(ptr)[0]|(U32)(ptr)[1]<<8|(U32)(ptr)[2]<<16|(U32)(ptr)[3]<<24) + #define U8TO64_LE(ptr) ((U64)(ptr)[0]|(U64)(ptr)[1]<<8|(U64)(ptr)[2]<<16|(U64)(ptr)[3]<<24|\ + (U64)(ptr)[4]<<32|(U64)(ptr)[5]<<40|\ + (U64)(ptr)[6]<<48|(U64)(ptr)[7]<<56) #endif #endif -#ifndef U8TO16_LE - /* Without a known fast bswap32 we're just as well off doing this */ - #define U8TO16_LE(ptr) ((U32)(ptr)[0]|(U32)(ptr)[1]<<8) - #define U8TO32_LE(ptr) ((U32)(ptr)[0]|(U32)(ptr)[1]<<8|(U32)(ptr)[2]<<16|(U32)(ptr)[3]<<24) - #define U8TO64_LE(ptr) ((U64)(ptr)[0]|(U64)(ptr)[1]<<8|(U64)(ptr)[2]<<16|(U64)(ptr)[3]<<24|\ - (U64)(ptr)[4]<<32|(U64)(ptr)[5]<<40|\ - (U64)(ptr)[6]<<48|(U64)(ptr)[7]<<56) -#endif - #ifdef CAN64BITHASH #ifndef U64TYPE /* This probably isn't going to work, but failing with a compiler error due to |