Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ BUTIL_SRCS = [
"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",
"src/butil/third_party/symbolize/demangle.cc",
"src/butil/third_party/symbolize/symbolize.cc",
"src/butil/third_party/snappy/snappy-sinksource.cc",
Expand Down
28 changes: 24 additions & 4 deletions src/butil/string_compare_rvv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@
// specific language governing permissions and limitations
// under the License.

// RVV-accelerated memcmp for StringPiece operations.
// Algorithm follows glibc's RVV memcmp pattern:
// - e8m8 LMUL with hardware-adaptive VL via vsetvl
// - vfirst.m for early-out on first mismatch
// RVV-accelerated memcmp and memchr for StringPiece operations.
// memcmp: follows glibc's RVV memcmp pattern (e8m8 LMUL, vfirst.m early-out).
// memchr: uses vmseq + vfirst.m to locate first matching byte.

#include "butil/strings/string_piece.h"

Expand Down Expand Up @@ -50,6 +49,27 @@ int rvv_memcmp(const void* p1, const void* p2, size_t n) {
return 0;
}

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;
}

src += vl;
remaining -= vl;
}
return nullptr;
}

} // namespace butil

#endif // __riscv && __riscv_vector
11 changes: 11 additions & 0 deletions src/butil/strings/string_piece.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,18 @@ size_t findT(const BasicStringPiece<STR>& self,
}

size_t find(const StringPiece& self, char c, size_t pos) {
#if defined(__riscv) && defined(__riscv_vector)
if (pos < self.size()) {
const void* result = butil::rvv_memchr(self.data() + pos, c, self.size() - pos);
if (result != nullptr) {
return static_cast<size_t>(static_cast<const char*>(result) - self.data());
}
return BasicStringPiece<std::string>::npos;
}
return BasicStringPiece<std::string>::npos;
#else
return findT(self, c, pos);
#endif
}

size_t find(const StringPiece16& self, char16 c, size_t pos) {
Expand Down
3 changes: 2 additions & 1 deletion src/butil/strings/string_piece.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@

namespace butil {

// RVV-accelerated byte comparison (implemented in string_compare_rvv.cc)
// RVV-accelerated byte comparison and search (implemented in string_compare_rvv.cc)
#if defined(__riscv) && defined(__riscv_vector)
BUTIL_EXPORT int rvv_memcmp(const void* p1, const void* p2, size_t n);
BUTIL_EXPORT const void* rvv_memchr(const void* s, int c, size_t n);
#endif

template <typename STRING_TYPE> class BasicStringPiece;
Expand Down
Loading