Add RISC-V Zbc clmul CRC-32C implementation

Started by joshuaabout 3 hours ago1 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

never appliedCI history
Jump to latest
#1joshua
cooper.joshua@linux.alibaba.com

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

Attachments:

0001-Add-RISC-V-Zbc-clmul-CRC-32C-implementation.patchapplication/octet-streamDownload+244-8