optimize StringPiece memcmp for RISC-V with RVV#3390
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces RISC-V Vector (RVV) accelerated byte-wise comparison/search routines intended to speed up butil::StringPiece operations on RVV-capable RISC-V platforms, and wires RVV memcmp into StringPiece’s internal comparison path.
Changes:
- Added RVV implementations
rvv_memcmpandrvv_memchrin a new source file. - Added RVV dispatch in
BasicStringPiece::wordmemcmpfor byte strings (N ≥ 16). - Updated build files to compile the new RVV source.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| src/butil/strings/string_piece.h | Adds RVV function declarations and dispatches wordmemcmp to rvv_memcmp under RVV guards. |
| src/butil/string_compare_rvv.cc | New RVV-accelerated memcmp/memchr implementations using RVV intrinsics. |
| CMakeLists.txt | Adds string_compare_rvv.cc to butil sources for CMake builds. |
| BUILD.bazel | Adds string_compare_rvv.cc to BUTIL_SRCS (but also adds a missing/unrelated RVV source entry). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "src/butil/third_party/icu/icu_utf.cc", | ||
| "src/butil/third_party/superfasthash/superfasthash.c", | ||
| "src/butil/third_party/modp_b64/modp_b64.cc", | ||
| "src/butil/third_party/modp_b64/modp_b64_rvv.cc", |
There was a problem hiding this comment.
Fixed. Removed modp_b64_rvv.cc from BUTIL_SRCS — it was inadvertently included from a prior PR (#3388) and doesn't belong in this change.
| // RVV-accelerated byte comparison and search (implemented in string_compare_rvv.cc) | ||
| #if defined(__riscv) && defined(__riscv_vector) | ||
| int rvv_memcmp(const void* p1, const void* p2, size_t n); | ||
| const void* rvv_memchr(const void* s, int c, size_t n); | ||
| #endif |
There was a problem hiding this comment.
Fixed. Added BUTIL_EXPORT to the rvv_memcmp declaration to ensure proper symbol visibility in shared library builds.
| if (first >= 0) { | ||
| uint8_t b1 = src1[first]; | ||
| uint8_t b2 = src2[first]; | ||
| return (b1 < b2) ? -1 : 1; | ||
| } |
There was a problem hiding this comment.
Fixed. Changed to return static_cast(src1[first]) - static_cast(src2[first]); which matches glibc memcmp semantics and preserves the byte-difference contract expected by traits_type::compare.
| * rvv_memchr - RVV-accelerated byte search following glibc pattern. | ||
| * | ||
| * Searches for the first occurrence of byte 'c' in buffer 's' of length 'n'. | ||
| * Returns pointer to first match, or NULL if not found. | ||
| * | ||
| * Uses RVV m8 with hardware-adaptive VL for maximum throughput. |
There was a problem hiding this comment.
Fixed. rvv_memchr has been removed from this PR and will be added in a follow-up PR with proper StringPiece::find dispatch. The doc comment and implementation will be aligned in that PR.
| const void* rvv_memchr(const void* s, int c, size_t n) { | ||
| const uint8_t* src = static_cast<const uint8_t*>(s); | ||
| uint8_t ch = static_cast<uint8_t>(c); | ||
| size_t remaining = n; | ||
|
|
||
| while (remaining > 0) { | ||
| size_t vl = __riscv_vsetvl_e8m8(remaining); | ||
| vuint8m8_t v = __riscv_vle8_v_u8m8(src, vl); | ||
| vbool1_t eq = __riscv_vmseq_vx_u8m8_b1(v, ch, vl); | ||
| long first = __riscv_vfirst_m_b1(eq, vl); | ||
|
|
||
| if (first >= 0) { | ||
| return src + first; | ||
| } |
There was a problem hiding this comment.
Agreed. rvv_memchr has been removed from this PR. It will be reintroduced in a follow-up PR that also wires the dispatch into StringPiece::find(char) via internal::find in string_piece.cc.
3902e7e to
24d0b81
Compare
This patch adds RVV-accelerated memcmp for StringPiece operations
on RISC-V 64-bit platforms.
The implementation follows glibc's official RVV pattern:
- e8m8 LMUL for maximum throughput
- Hardware-adaptive vector length via vsetvl
- vfirst.m for early-out on first difference
Performance on SOPHGO SG2044 (RVV 1.0, VLEN >= 128, GCC 15.1):
glibc 2.38 scalar memcmp (no RVV acceleration) as baseline.
memcmp (worst-case full scan, 50000 iterations):
64 B: 20 ns -> 6 ns (3.4x)
256 B: 54 ns -> 15 ns (3.6x)
1 KB: 120 ns -> 55 ns (2.2x)
4 KB: 435 ns -> 225 ns (1.9x)
16 KB: 1968 ns -> 1258 ns (1.6x)
64 KB: 10962 ns -> 9044 ns (1.2x)
256 KB: 46893 ns -> 43108 ns (1.1x)
1 MB: 446161 ns -> 454717 ns (1.01x)
Correctness:
- 59/59 expanded correctness tests passed (64B - 1MB)
- string_piece_unittest: 24/24 passed
- test_butil: 724/725 passed (1 pre-existing StackTrace failure)
- test_bvar: 64/64 passed
Files changed:
- src/butil/string_compare_rvv.cc (new): RVV memcmp implementation
- src/butil/strings/string_piece.h: RVV dispatch in wordmemcmp (N >= 16)
- BUILD.bazel: added string_compare_rvv.cc to BUTIL_SRCS
- CMakeLists.txt: added string_compare_rvv.cc
Signed-off-by: Xiaofei Gong <gongxiaofei24@iscas.ac.cn>
Signed-off-by: YuanSheng <yuansheng@isrc.iscas.ac.cn>
This patch adds RVV-accelerated memcmp for StringPiece operations
on RISC-V 64-bit platforms.
The implementation follows glibc's official RVV pattern:
- e8m8 LMUL for maximum throughput
- Hardware-adaptive vector length via vsetvl
- vfirst.m for early-out on first difference
Performance on SOPHGO SG2044 (RVV 1.0, VLEN >= 128, GCC 15.1):
glibc 2.38 scalar memcmp (no RVV acceleration) as baseline.
memcmp (worst-case full scan, 50000 iterations):
64 B: 20 ns -> 6 ns (3.4x)
256 B: 54 ns -> 15 ns (3.6x)
1 KB: 120 ns -> 55 ns (2.2x)
4 KB: 435 ns -> 225 ns (1.9x)
16 KB: 1968 ns -> 1258 ns (1.6x)
64 KB: 10962 ns -> 9044 ns (1.2x)
256 KB: 46893 ns -> 43108 ns (1.1x)
1 MB: 446161 ns -> 454717 ns (1.01x)
Correctness:
- 59/59 expanded correctness tests passed (64B - 1MB)
- string_piece_unittest: 24/24 passed
- test_butil: 724/725 passed (1 pre-existing StackTrace failure)
- test_bvar: 64/64 passed
Files changed:
- src/butil/string_compare_rvv.cc (new): RVV memcmp implementation
- src/butil/strings/string_piece.h: RVV dispatch in wordmemcmp (N >= 16)
- BUILD.bazel: added string_compare_rvv.cc to BUTIL_SRCS
- CMakeLists.txt: added string_compare_rvv.cc
Signed-off-by: Xiaofei Gong <gongxiaofei24@iscas.ac.cn>
Signed-off-by: YuanSheng <yuansheng@isrc.iscas.ac.cn>
24d0b81 to
5fb665e
Compare
Summary
This patch adds RVV-accelerated
memcmpforStringPieceoperations on RISC-V 64-bit platforms.The implementation follows glibc's official RVV pattern:
vsetvlvfirst.mfor early-out on first differencePerformance
Test environment: SOPHGO SG2044 (RVV 1.0, VLEN >= 128, GCC 15.1)
Baseline: glibc 2.38 scalar memcmp (no RVV acceleration)
memcmp (worst-case full scan, 50000 iterations)
Correctness
string_piece_unittesttest_butiltest_bvarFiles Changed
src/butil/string_compare_rvv.cc(new): RVV memcmp implementationsrc/butil/strings/string_piece.h: RVV dispatch inwordmemcmp(N >= 16), addedBUTIL_EXPORTBUILD.bazel: addedstring_compare_rvv.cctoBUTIL_SRCSCMakeLists.txt: addedstring_compare_rvv.ccBuild
RISC-V optimization for butil StringPiece operations.