This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Clean up U8TO*_LE macro implementations
authorMatt Turner <mattst88@gmail.com>
Thu, 5 Sep 2019 04:48:56 +0000 (21:48 -0700)
committerTony Cook <tony@develop-help.com>
Mon, 7 Oct 2019 22:27:43 +0000 (09:27 +1100)
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

hv_macro.h
stadtx_hash.h
zaphod32_hash.h

index 77a4c84..02c0baa 100644 (file)
@@ -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.
  * 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
index bd09c2f..5ee8794 100644 (file)
 #define STMT_END while(0)
 #endif
 
-#ifndef STADTX_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN
-/* STADTX_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN only matters if nothing has defined U8TO64_LE etc,
- * and when built with Perl these should be defined before this file is loaded.
- */
-#ifdef U32_ALIGNMENT_REQUIRED
-#define STADTX_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN 0
-#else
-#define STADTX_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN 1
-#endif
-#endif
-
-#ifndef U8TO64_LE
-#if STADTX_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN
-#define U8TO64_LE(ptr)  (*((const U64 *)(ptr)))
-#else
-#define U8TO64_LE(ptr)  (\
-    (U64)(ptr)[7] << 56 | \
-    (U64)(ptr)[6] << 48 | \
-    (U64)(ptr)[5] << 40 | \
-    (U64)(ptr)[4] << 32 | \
-    (U64)(ptr)[3] << 24 | \
-    (U64)(ptr)[2] << 16 | \
-    (U64)(ptr)[1] << 8  | \
-    (U64)(ptr)[0]         \
-)
-#endif
-#endif
-
-#ifndef U8TO32_LE
-#if STADTX_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN
-#define U8TO32_LE(ptr)  (*((const U32 *)(ptr)))
-#else
-#define U8TO32_LE(ptr)  (\
-    (U32)(ptr)[3] << 24 | \
-    (U32)(ptr)[2] << 16 | \
-    (U32)(ptr)[1] << 8  | \
-    (U32)(ptr)[0]         \
-)
-#endif
-#endif
-
-#ifndef U8TO16_LE
-#if STADTX_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN
-#define U8TO16_LE(ptr)  (*((const U16 *)(ptr)))
-#else
-#define U8TO16_LE(ptr)  (\
-    (U16)(ptr)[1] << 8  | \
-    (U16)(ptr)[0]         \
-)
-#endif
-#endif
-
 /* Find best way to ROTL32/ROTL64 */
 #if defined(_MSC_VER)
   #include <stdlib.h>  /* Microsoft put _rotl declaration in here */
index c9b60cc..2fb391a 100644 (file)
 #define STMT_END while(0)
 #endif
 
-#ifndef ZAPHOD32_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN
-/* ZAPHOD32_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN only matters if nothing has defined U8TO64_LE etc,
- * and when built with Perl these should be defined before this file is loaded.
- */
-#ifdef U32_ALIGNMENT_REQUIRED
-#define ZAPHOD32_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN 0
-#else
-#define ZAPHOD32_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN 1
-#endif
-#endif
-
-#ifndef U8TO32_LE
-#if ZAPHOD32_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN
-#define U8TO32_LE(ptr)  (*((const U32 *)(ptr)))
-#else
-#define U8TO32_LE(ptr)  (\
-    (U32)(ptr)[3] << 24 | \
-    (U32)(ptr)[2] << 16 | \
-    (U32)(ptr)[1] << 8  | \
-    (U32)(ptr)[0]         \
-)
-#endif
-#endif
-
-#ifndef U8TO16_LE
-#if ZAPHOD32_ALLOW_UNALIGNED_AND_LITTLE_ENDIAN
-#define U8TO16_LE(ptr)  (*((const U16 *)(ptr)))
-#else
-#define U8TO16_LE(ptr)  (\
-    (U16)(ptr)[1] << 8  | \
-    (U16)(ptr)[0]         \
-)
-#endif
-#endif
-
 /* This is two marsaglia xor-shift permutes, with a prime-multiple
  * sandwiched inside. The end result of doing this twice with different
  * primes is a completely avalanched v.  */