]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Use memcpy instead of memcmp for unaligned memory comparisons.
authorNathan Moinvaziri <nathan@nathanm.com>
Sun, 5 Feb 2023 20:14:18 +0000 (12:14 -0800)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Wed, 8 Feb 2023 21:12:37 +0000 (22:12 +0100)
Use memcpy because it is better supported for compilers that support unaligned
access than memcmp.

compare256.c
deflate_quick.c
match_tpl.h
zbuild.h
zutil_p.h

index b11ac24ee076a03194391f4baebd1d049f9fb133..94b88e756f57b28047f1a2bd07ff8774f5173212 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include "zbuild.h"
+#include "zutil_p.h"
 #include "fallback_builtins.h"
 
 /* ALIGNED, byte comparison */
@@ -61,16 +62,19 @@ static inline uint32_t compare256_unaligned_16_static(const uint8_t *src0, const
     uint32_t len = 0;
 
     do {
-        if (zmemcmp_2(src0, src1) != 0)
+        if (zng_memcmp_2(src0, src1) != 0)
             return len + (*src0 == *src1);
         src0 += 2, src1 += 2, len += 2;
-        if (zmemcmp_2(src0, src1) != 0)
+
+        if (zng_memcmp_2(src0, src1) != 0)
             return len + (*src0 == *src1);
         src0 += 2, src1 += 2, len += 2;
-        if (zmemcmp_2(src0, src1) != 0)
+
+        if (zng_memcmp_2(src0, src1) != 0)
             return len + (*src0 == *src1);
         src0 += 2, src1 += 2, len += 2;
-        if (zmemcmp_2(src0, src1) != 0)
+
+        if (zng_memcmp_2(src0, src1) != 0)
             return len + (*src0 == *src1);
         src0 += 2, src1 += 2, len += 2;
     } while (len < 256);
index 4d8013e71016e3ab2741efdedda389a45bec337f..d616677c5f9138c826c2b78a56bde2c90a4509bb 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include "zbuild.h"
+#include "zutil_p.h"
 #include "deflate.h"
 #include "deflate_p.h"
 #include "functable.h"
@@ -92,7 +93,7 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) {
                 const uint8_t *str_start = s->window + s->strstart;
                 const uint8_t *match_start = s->window + hash_head;
 
-                if (zmemcmp_2(str_start, match_start) == 0) {
+                if (zng_memcmp_2(str_start, match_start) == 0) {
                     match_len = functable.compare256(str_start+2, match_start+2) + 2;
 
                     if (match_len >= WANT_MIN_MATCH) {
index fbd34e58a5a0b4ff841350b5ed959cee10a2e56e..d076798520eeda01d41aa859274ced6e36049325 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include "zbuild.h"
+#include "zutil_p.h"
 #include "deflate.h"
 #include "functable.h"
 
@@ -145,24 +146,24 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) {
 #ifdef UNALIGNED_OK
         if (best_len < sizeof(uint32_t)) {
             for (;;) {
-                if (zmemcmp_2(mbase_end+cur_match, scan_end) == 0 &&
-                    zmemcmp_2(mbase_start+cur_match, scan_start) == 0)
+                if (zng_memcmp_2(mbase_end+cur_match, scan_end) == 0 &&
+                    zng_memcmp_2(mbase_start+cur_match, scan_start) == 0)
                     break;
                 GOTO_NEXT_CHAIN;
             }
 #  ifdef UNALIGNED64_OK
         } else if (best_len >= sizeof(uint64_t)) {
             for (;;) {
-                if (zmemcmp_8(mbase_end+cur_match, scan_end) == 0 &&
-                    zmemcmp_8(mbase_start+cur_match, scan_start) == 0)
+                if (zng_memcmp_8(mbase_end+cur_match, scan_end) == 0 &&
+                    zng_memcmp_8(mbase_start+cur_match, scan_start) == 0)
                     break;
                 GOTO_NEXT_CHAIN;
             }
 #  endif
         } else {
             for (;;) {
-                if (zmemcmp_4(mbase_end+cur_match, scan_end) == 0 &&
-                    zmemcmp_4(mbase_start+cur_match, scan_start) == 0)
+                if (zng_memcmp_4(mbase_end+cur_match, scan_end) == 0 &&
+                    zng_memcmp_4(mbase_start+cur_match, scan_start) == 0)
                     break;
                 GOTO_NEXT_CHAIN;
             }
index 901111cd79910376fa19e6fe2f09c2250ab2eca6..c7df4b1e69d654651b2bcaca2ea2dc266541ee6c 100644 (file)
--- a/zbuild.h
+++ b/zbuild.h
 #  endif
 #endif
 
-/* Force compiler to emit unaligned memory comparisons if unaligned access is supported
-   on the architecture, otherwise don't assume unaligned access is supported. Older
-   compilers don't optimize memcmp calls for all integer types to unaligned access instructions
-   when it is supported on the architecture resulting in significant performance impact. */
-#ifdef UNALIGNED_OK
-#  define zmemcmp_2(str1, str2)   (*((uint16_t *)(str1)) != *((uint16_t *)(str2)))
-#  define zmemcmp_4(str1, str2)   (*((uint32_t *)(str1)) != *((uint32_t *)(str2)))
-#  if defined(UNALIGNED64_OK) && (UINTPTR_MAX == UINT64_MAX)
-#    define zmemcmp_8(str1, str2) (*((uint64_t *)(str1)) != *((uint64_t *)(str2)))
-#  else
-#    define zmemcmp_8(str1, str2) (((uint32_t *)(str1))[0] != ((uint32_t *)(str2))[0] || \
-                                   ((uint32_t *)(str1))[1] != ((uint32_t *)(str2))[1])
-#  endif
-#else
-#  define zmemcmp_2(str1, str2) memcmp(str1, str2, 2)
-#  define zmemcmp_4(str1, str2) memcmp(str1, str2, 4)
-#  define zmemcmp_8(str1, str2) memcmp(str1, str2, 8)
-#endif
-
 #if defined(__has_feature)
 #  if __has_feature(memory_sanitizer)
 #    define Z_MEMORY_SANITIZER 1
index 318b4d9011ed85f89045abd4a38618864e005e73..caec91d50d364c887d5b430d156ff0084377cc11 100644 (file)
--- a/zutil_p.h
+++ b/zutil_p.h
@@ -39,4 +39,33 @@ static inline void zng_free(void *ptr) {
 #endif
 }
 
+/* Use memcpy instead of memcmp to avoid older compilers not converting memcmp calls to
+   unaligned comparisons when unaligned access is supported. */
+static inline int32_t zng_memcmp_2(const void *src0, const void *src1) {
+    uint16_t src0_cmp, src1_cmp;
+
+    memcpy(&src0_cmp, src0, sizeof(src0_cmp));
+    memcpy(&src1_cmp, src1, sizeof(src1_cmp));
+
+    return src0_cmp != src1_cmp;
+}
+
+static inline int32_t zng_memcmp_4(const void *src0, const void *src1) {
+    uint32_t src0_cmp, src1_cmp;
+
+    memcpy(&src0_cmp, src0, sizeof(src0_cmp));
+    memcpy(&src1_cmp, src1, sizeof(src1_cmp));
+
+    return src0_cmp != src1_cmp;
+}
+
+static inline int32_t zng_memcmp_8(const void *src0, const void *src1) {
+    uint64_t src0_cmp, src1_cmp;
+
+    memcpy(&src0_cmp, src0, sizeof(src0_cmp));
+    memcpy(&src1_cmp, src1, sizeof(src1_cmp));
+
+    return src0_cmp != src1_cmp;
+}
+
 #endif