]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Speed up crc32_[v]pclmulqdq on small strings.
authorHans Kristian Rosbach <hk-git@circlestorm.org>
Thu, 25 Jan 2024 12:28:10 +0000 (13:28 +0100)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Fri, 2 Feb 2024 13:00:18 +0000 (14:00 +0100)
arch/generic/crc32_braid_c.c
arch/x86/crc32_pclmulqdq_tpl.h
crc32_braid_p.h

index 7bf83f17ab251b82d300286ef2bae66aa7da54f1..7d8028f6d705559ee9a29436cd6b1dcde0605a08 100644 (file)
@@ -11,8 +11,6 @@
 #include "crc32_braid_p.h"
 #include "crc32_braid_tbl.h"
 
-/* ========================================================================= */
-
 /*
   A CRC of a message is computed on N braids of words in the message, where
   each word consists of W bytes (4 or 8). If N is 3, for example, then three
   level. Your mileage may vary.
 */
 
-/* ========================================================================= */
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-#  define ZSWAPWORD(word) (word)
-#  define BRAID_TABLE crc_braid_table
-#elif BYTE_ORDER == BIG_ENDIAN
-#  if W == 8
-#    define ZSWAPWORD(word) ZSWAP64(word)
-#  elif W == 4
-#    define ZSWAPWORD(word) ZSWAP32(word)
-#  endif
-#  define BRAID_TABLE crc_braid_big_table
-#else
-#  error "No endian defined"
-#endif
-#define DO1 c = crc_table[(c ^ *buf++) & 0xff] ^ (c >> 8)
-#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
-
 /* ========================================================================= */
 #ifdef W
 /*
@@ -80,7 +60,7 @@ static z_word_t crc_word(z_word_t data) {
 
 /* ========================================================================= */
 Z_INTERNAL uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, size_t len) {
-    Z_REGISTER uint32_t c;
+    uint32_t c;
 
     /* Pre-condition the CRC */
     c = (~crc) & 0xffffffff;
index 8c06a60ef462f9fe59973fc10ff137f07d42f4ee..80a35b035706f7c1c55591cd33aba7b7d8921483 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "crc32.h"
 #include "crc32_braid_p.h"
+#include "crc32_braid_tbl.h"
 #include "x86_intrins.h"
 #include <assert.h>
 
@@ -350,11 +351,22 @@ Z_INTERNAL uint32_t CRC32_FOLD_FINAL(crc32_fold *crc) {
     return crc->value;
 }
 
+static inline uint32_t crc32_small(uint32_t crc, const uint8_t *buf, size_t len) {
+    uint32_t c = (~crc) & 0xffffffff;
+
+    while (len) {
+        len--;
+        DO1;
+    }
+
+    return c ^ 0xffffffff;
+}
+
 Z_INTERNAL uint32_t CRC32(uint32_t crc32, const uint8_t *buf, size_t len) {
-    /* For lens < 64, crc32_braid method is faster. The CRC32 instruction for
-     * these short lengths might also prove to be effective */
-    if (len < 64)
-        return PREFIX(crc32_braid)(crc32, buf, len);
+    /* For lens smaller than ~12, crc32_small method is faster.
+     * But there are also minimum requirements for the pclmul functions due to alignment */
+    if (len < 32)
+        return crc32_small(crc32, buf, len);
 
     crc32_fold ALIGNED_(16) crc_state;
     CRC32_FOLD_RESET(&crc_state);
index 65a535dc2000d6508ebcbb444dce2dbffa1e8760..4bfe37f5f6088b860b7780ce7857177d11aa9121 100644 (file)
 #  endif
 #endif
 
+#if BYTE_ORDER == LITTLE_ENDIAN
+#  define ZSWAPWORD(word) (word)
+#  define BRAID_TABLE crc_braid_table
+#elif BYTE_ORDER == BIG_ENDIAN
+#  if W == 8
+#    define ZSWAPWORD(word) ZSWAP64(word)
+#  elif W == 4
+#    define ZSWAPWORD(word) ZSWAP32(word)
+#  endif
+#  define BRAID_TABLE crc_braid_big_table
+#else
+#  error "No endian defined"
+#endif
+
+#define DO1 c = crc_table[(c ^ *buf++) & 0xff] ^ (c >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
 /* CRC polynomial. */
 #define POLY 0xedb88320         /* p(x) reflected, with x^32 implied */