diff --git a/BUILD.bazel b/BUILD.bazel index 3a5030845a..cf4560b703 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -128,7 +128,6 @@ 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", @@ -189,6 +188,7 @@ BUTIL_SRCS = [ "src/butil/strings/string_number_conversions.cc", "src/butil/strings/string_split.cc", "src/butil/strings/string_piece.cc", + "src/butil/string_compare_rvv.cc", "src/butil/strings/string_util.cc", "src/butil/strings/string_util_constants.cc", "src/butil/strings/stringprintf.cc", diff --git a/CMakeLists.txt b/CMakeLists.txt index bff13e0687..85270acc1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -478,6 +478,7 @@ set(BUTIL_SOURCES ${PROJECT_SOURCE_DIR}/src/butil/strings/string_number_conversions.cc ${PROJECT_SOURCE_DIR}/src/butil/strings/string_split.cc ${PROJECT_SOURCE_DIR}/src/butil/strings/string_piece.cc + ${PROJECT_SOURCE_DIR}/src/butil/string_compare_rvv.cc ${PROJECT_SOURCE_DIR}/src/butil/strings/string_util.cc ${PROJECT_SOURCE_DIR}/src/butil/strings/string_util_constants.cc ${PROJECT_SOURCE_DIR}/src/butil/strings/stringprintf.cc diff --git a/src/butil/string_compare_rvv.cc b/src/butil/string_compare_rvv.cc new file mode 100644 index 0000000000..3f7985e1c8 --- /dev/null +++ b/src/butil/string_compare_rvv.cc @@ -0,0 +1,55 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// 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 + +#include "butil/strings/string_piece.h" + +#if defined(__riscv) && defined(__riscv_vector) +#include + +namespace butil { + +int rvv_memcmp(const void* p1, const void* p2, size_t n) { + const uint8_t* src1 = static_cast(p1); + const uint8_t* src2 = static_cast(p2); + size_t remaining = n; + + while (remaining > 0) { + size_t vl = __riscv_vsetvl_e8m8(remaining); + vuint8m8_t v1 = __riscv_vle8_v_u8m8(src1, vl); + vuint8m8_t v2 = __riscv_vle8_v_u8m8(src2, vl); + vbool1_t neq = __riscv_vmsne_vv_u8m8_b1(v1, v2, vl); + long first = __riscv_vfirst_m_b1(neq, vl); + + if (first >= 0) { + return static_cast(src1[first]) - static_cast(src2[first]); + } + + src1 += vl; + src2 += vl; + remaining -= vl; + } + return 0; +} + +} // namespace butil + +#endif // __riscv && __riscv_vector diff --git a/src/butil/strings/string_piece.h b/src/butil/strings/string_piece.h index dbfd69e6e0..b1a4ed73a5 100644 --- a/src/butil/strings/string_piece.h +++ b/src/butil/strings/string_piece.h @@ -43,6 +43,11 @@ namespace butil { +// RVV-accelerated byte comparison (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); +#endif + template class BasicStringPiece; typedef BasicStringPiece StringPiece; typedef BasicStringPiece StringPiece16; @@ -286,6 +291,11 @@ template class BasicStringPiece { static int wordmemcmp(const value_type* p, const value_type* p2, size_type N) { +#if defined(__riscv) && defined(__riscv_vector) + if (sizeof(value_type) == 1 && N >= 16) { + return rvv_memcmp(p, p2, N); + } +#endif return STRING_TYPE::traits_type::compare(p, p2, N); }