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