Hi all,
PostgreSQL currently has hardware-accelerated CRC-32C on x86_64 (SSE 4.2 / 
AVX-512), ARMv8 and LoongArch, but on RISC-V we always fall back to the 
software slicing-by-8 implementation.
Some RISC-V CPUs implement the Zbc extension, which adds carry-less 
multiplication instructions (clmul/clmulh). CRC-32C can be computed with a 
folding algorithm built on carry-less multiplication, so these CPUs can get 
hardware acceleration too, which should help in IO-heavy workloads.
Attached is a patch that adds RISC-V Zbc support for CRC-32C, following roughly 
the same structure as the existing ARMv8 implementation (commit f044d71e331d):
src/port/pg_crc32c_zbc.c does the folding algorithm using the 
__builtin_rev_crc32_data8/16/32() compiler intrinsics. These landed in GCC 15 
and compile down to clmul-based sequences when targeting Zbc. As in the ARMv8 
version, we process leading bytes one at a time until the pointer is 8-byte 
aligned, run the main loop eight bytes at a time, then handle the trailing 0-7 
bytes.
src/port/pg_crc32c_zbc_choose.c does the runtime check. Zbc has no 
corresponding bit in the auxiliary vector, so we probe for it by running the 
clmul code and catching SIGILL — same approach as pg_crc32c_armv8_choose.c. If 
that fails we fall back to slicing-by-8.
configure checks for the intrinsics first with the default compiler flags, then 
with "-march=rv64gc_zbc" if that fails. We build with the runtime-check path 
whenever the compiler supports the intrinsics at all, since compilers generally 
don't target Zbc by default. The hardware-specific code lives behind #if 
defined USE_ZBC_CRC32C_WITH_RUNTIME_CHECK.
I benchmarked this with pgbench TPC-B (scale 4000) under QEMU (qemu-riscv64, 
CPU model xt-c9501fdvkt), using the QEMU hotblocks plugin to count instructions 
over the same workload:
 baseline (SB8) Zbc clmul
 total instructions 1,787,477,187 1,721,911,819 (-3.67%)
 XLogRecordAssemble 168,329,617 50,044,718
 pg_comp_crc32c_zbc N/A 85,984,082
Most of the reduction comes from the CRC32C computation itself — compared to 
the ARMv8 hardware path on the same workload (76.6M instructions), this closes 
85.7% of the gap.
I checked correctness against slicing-by-8 on 584 test vectors (all input 
lengths 0-72 at every alignment offset, two different initial CRC values), and 
ran the full pgbench workload with WAL CRC validation enabled, which passed.
The patch applies against master's current CRC-32C layout and also applies 
cleanly to REL_17. I'll add it to the next CommitFest. 
Feedback welcome.
Regards,
Jun Sha

Attachment: 0001-Add-RISC-V-Zbc-clmul-CRC-32C-implementation.patch
Description: Binary data



Reply via email to