v14-0005-Add-runtime-support-for-AVX-512-CRC.patch

text/x-patch

Filename: v14-0005-Add-runtime-support-for-AVX-512-CRC.patch
Type: text/x-patch
Part: 3
Message: Re: Improve CRC32C performance on SSE4.2

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 v14-0005
Subject: Add runtime support for AVX-512 CRC
File+
src/port/pg_crc32c_sse42_choose.c 50 9
From 85970737d58d3fb46e954f4b056a8411c0870882 Mon Sep 17 00:00:00 2001
From: John Naylor <john.naylor@postgresql.org>
Date: Tue, 11 Mar 2025 13:07:01 +0700
Subject: [PATCH v14 5/8] Add runtime support for AVX-512 CRC

---
 src/port/pg_crc32c_sse42_choose.c | 59 ++++++++++++++++++++++++++-----
 1 file changed, 50 insertions(+), 9 deletions(-)

diff --git a/src/port/pg_crc32c_sse42_choose.c b/src/port/pg_crc32c_sse42_choose.c
index 89a48c76894..c2d25253c2c 100644
--- a/src/port/pg_crc32c_sse42_choose.c
+++ b/src/port/pg_crc32c_sse42_choose.c
@@ -20,16 +20,37 @@
 
 #include "c.h"
 
-#ifdef HAVE__GET_CPUID
+#if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT)
 #include <cpuid.h>
 #endif
 
-#ifdef HAVE__CPUID
+#include <immintrin.h>
+
+#if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX)
 #include <intrin.h>
 #endif
 
 #include "port/pg_crc32c.h"
 
+/*
+ * Does XGETBV say the ZMM registers are enabled?
+ *
+ * NB: Caller is responsible for verifying that osxsave is available
+ * before calling this.
+ */
+#ifdef HAVE_XSAVE_INTRINSICS
+pg_attribute_target("xsave")
+#endif
+static inline bool
+zmm_regs_available(void)
+{
+#ifdef HAVE_XSAVE_INTRINSICS
+	return (_xgetbv(0) & 0xe6) == 0xe6;
+#else
+	return false;
+#endif
+}
+
 /*
  * This gets called on the first call. It replaces the function pointer
  * so that subsequent calls are routed directly to the chosen implementation.
@@ -39,6 +60,15 @@ pg_comp_crc32c_choose(pg_crc32c crc, const void *data, size_t len)
 {
 	unsigned int exx[4] = {0, 0, 0, 0};
 
+#ifdef USE_SSE42_CRC32C_WITH_RUNTIME_CHECK
+
+	/*
+	 * Set fallback. We must guard since slicing-by-8 is not visible
+	 * everywhere.
+	 */
+	pg_comp_crc32c = pg_comp_crc32c_sb8;
+#endif
+
 #if defined(HAVE__GET_CPUID)
 	__get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
 #elif defined(HAVE__CPUID)
@@ -50,15 +80,26 @@ pg_comp_crc32c_choose(pg_crc32c crc, const void *data, size_t len)
 	if ((exx[2] & (1 << 20)) != 0)	/* SSE 4.2 */
 	{
 		pg_comp_crc32c = pg_comp_crc32c_sse42;
-#ifdef USE_PCLMUL_WITH_RUNTIME_CHECK
-		if ((exx[2] & (1 << 1)) != 0)	/* PCLMUL */
-			pg_comp_crc32c = pg_comp_crc32c_pclmul;
+
+		if (exx[2] & (1 << 27) &&	/* OSXSAVE */
+			zmm_regs_available())
+		{
+#ifdef USE_AVX512_CRC32C_WITH_RUNTIME_CHECK
+			/* second cpuid call on leaf 7 to check extended avx512 support */
+
+			memset(exx, 0, 4 * sizeof(exx[0]));
+
+#if defined(HAVE__GET_CPUID_COUNT)
+			__get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]);
+#elif defined(HAVE__CPUIDEX)
+			__cpuidex(exx, 7, 0);
 #endif
-	}
-#ifdef USE_SSE42_CRC32C_WITH_RUNTIME_CHECK
-	else
-		pg_comp_crc32c = pg_comp_crc32c_sb8;
+			if (exx[2] & (1 << 10) &&	/* VPCLMULQDQ */
+				exx[1] & (1 << 31)) /* AVX512-VL */
+				pg_comp_crc32c = pg_comp_crc32c_pclmul;
 #endif
+		}
+	}
 
 	return pg_comp_crc32c(crc, data, len);
 }
-- 
2.48.1