v1-0001-Inline-CRC-computation-for-small-fixed-length-inp.patch
application/x-patch
Filename: v1-0001-Inline-CRC-computation-for-small-fixed-length-inp.patch
Type: application/x-patch
Part: 0
Message:
vectorized CRC on ARM64
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v1-0001
Subject: Inline CRC computation for small fixed-length input on Arm
| File | + | − |
|---|---|---|
| src/include/port/pg_crc32c.h | 43 | 1 |
From 9f3096da8fbed3f1457e7d52dfd91e6b29557239 Mon Sep 17 00:00:00 2001
From: John Naylor <john.naylor@postgresql.org>
Date: Sun, 27 Apr 2025 04:04:28 +0700
Subject: [PATCH v1 1/3] Inline CRC computation for small fixed-length input on
Arm
Similar vein to e2809e3a1. One difference is that the dispatch
function requires 4-byte alignment to prevent unnecessary branching
in the preamble. This corresponds to the alignment of WAL records.
---
src/include/port/pg_crc32c.h | 44 +++++++++++++++++++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/src/include/port/pg_crc32c.h b/src/include/port/pg_crc32c.h
index 82313bb7fcf..9f021db83b2 100644
--- a/src/include/port/pg_crc32c.h
+++ b/src/include/port/pg_crc32c.h
@@ -114,11 +114,53 @@ extern pg_crc32c pg_comp_crc32c_avx512(pg_crc32c crc, const void *data, size_t l
/* Use ARMv8 CRC Extension instructions. */
#define COMP_CRC32C(crc, data, len) \
- ((crc) = pg_comp_crc32c_armv8((crc), (data), (len)))
+ ((crc) = pg_comp_crc32c_dispatch((crc), (data), (len)))
#define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF)
extern pg_crc32c pg_comp_crc32c_armv8(pg_crc32c crc, const void *data, size_t len);
+static inline
+pg_crc32c
+pg_comp_crc32c_dispatch(pg_crc32c crc, const void *data, size_t len)
+{
+ /* require 4-byte alignment to avoid a long preamble */
+ if (__builtin_constant_p(len) &&
+ PointerIsAligned(data, uint32) &&
+ len < 32)
+ {
+ const unsigned char *p = data;
+
+ /*
+ * For small constant inputs, inline the computation to avoid a
+ * function call and allow the compiler to unroll loops.
+ */
+#if 1
+
+ /*
+ * WIP: is it better to avoid branching by unrolling the loop and
+ * processing only 4-bytes per iteration?
+ */
+ if (!PointerIsAligned(p, uint64) && len > 4)
+ {
+ crc = __crc32cw(crc, *(uint32 *) p);
+ p += 4;
+ len -= 4;
+ }
+#if SIZEOF_VOID_P >= 8
+ for (; len >= 8; p += 8, len -= 8)
+ crc = __crc32cd(crc, *(const uint64 *) p);
+#endif
+#endif
+ for (; len >= 4; p += 4, len -= 4)
+ crc = __crc32cw(crc, *(const uint32 *) p);
+ for (; len > 0; --len)
+ crc = __crc32cb(crc, *p++);
+ return crc;
+ }
+ else
+ return pg_comp_crc32c_armv8(crc, data, len);
+}
+
#elif defined(USE_LOONGARCH_CRC32C)
/* Use LoongArch CRCC instructions. */
--
2.49.0