Felix-Gong commented on code in PR #3388: URL: https://github.com/apache/brpc/pull/3388#discussion_r3585891911
########## src/butil/third_party/modp_b64/modp_b64_rvv.h: ########## @@ -0,0 +1,23 @@ +/* ... Apache 2.0 license header ... */ Review Comment: Fixed. Replaced the placeholder with the full Apache-2.0 license header matching the style used in other modp_b64 files. ########## src/butil/third_party/modp_b64/modp_b64_rvv.cc: ########## @@ -0,0 +1,244 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ +/* vi: set expandtab shiftwidth=4 tabstop=4: */ +/** + * \file + * RISC-V Vector (RVV) accelerated base64 encoder/decoder implementation + * + * Optimizes table lookup using RVV vrgather (encode) and vectorized + * range comparisons (decode) for significant speedup on rv64gcv hardware. + * + * 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. + */ + +#include "modp_b64_rvv.h" + +#if defined(__riscv) && defined(__riscv_vector) +#include <riscv_vector.h> +#include <stdint.h> +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* 64-entry base64 alphabet (A-Z, a-z, 0-9, +, /) */ +static const uint8_t s_rvv_alphabet[64] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' +}; + +/** + * rvv_modp_b64_encode - RVV-accelerated base64 encode + * + * Processes 12 input bytes at a time (producing 16 output bytes): + * 1. Compute 16 6-bit indices from 4 input triplets via scalar bit manipulation + * 2. Vectorized vrgather lookup from 64-entry alphabet (LMUL=4) + * 3. Vectorized store of 16 bytes + * + * The alphabet (64 bytes) is preloaded into LMUL=4 register group. + */ +size_t rvv_modp_b64_encode(char* dest, const char* str, size_t len) +{ + size_t i = 0; + uint8_t* p = (uint8_t*)dest; + + /* Preload 64-byte alphabet into LMUL=4 register group */ + size_t vl_alpha = __riscv_vsetvl_e8m4(64); + vuint8m4_t v_alpha = __riscv_vle8_v_u8m4(s_rvv_alphabet, vl_alpha); + + /* Process 12 bytes (4 triplets -> 16 output) per iteration */ + while (i + 12 <= len) { + uint8_t idx_buf[16] __attribute__((aligned(16))); + + /* Compute 16 6-bit indices from 4 input triplets (scalar) */ + for (int j = 0; j < 4; j++) { + uint8_t b0 = (uint8_t)str[i + j*3]; + uint8_t b1 = (uint8_t)str[i + j*3 + 1]; + uint8_t b2 = (uint8_t)str[i + j*3 + 2]; + idx_buf[j*4] = b0 >> 2; + idx_buf[j*4 + 1] = ((b0 & 0x03) << 4) | (b1 >> 4); + idx_buf[j*4 + 2] = ((b1 & 0x0F) << 2) | (b2 >> 6); + idx_buf[j*4 + 3] = b2 & 0x3F; + } + + /* Vectorized lookup: alphabet[idx[i]] via vrgather */ + size_t vl = __riscv_vsetvl_e8m4(16); + vuint8m4_t v_idx = __riscv_vle8_v_u8m4(idx_buf, vl); + vuint8m4_t v_out = __riscv_vrgather_vv_u8m4(v_alpha, v_idx, vl); + __riscv_vse8_v_u8m4(p, v_out, vl); + + p += 16; + i += 12; + } + + /* Tail processing: remaining bytes (0-11) handled via scalar fallback */ + { + size_t remaining = len - i; + const uint8_t* s = (const uint8_t*)(str + i); + uint8_t* d = p; + + uint8_t t1, t2, t3; + size_t ti = 0; + + if (remaining > 2) { + for (; ti < remaining - 2; ti += 3) { + t1 = s[ti]; t2 = s[ti+1]; t3 = s[ti+2]; + *d++ = s_rvv_alphabet[t1 >> 2]; + *d++ = s_rvv_alphabet[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)]; + *d++ = s_rvv_alphabet[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)]; + *d++ = s_rvv_alphabet[t3 & 0x3F]; + } + } + + switch (remaining - ti) { + case 1: + t1 = s[ti]; + *d++ = s_rvv_alphabet[t1 >> 2]; + *d++ = s_rvv_alphabet[(t1 & 0x03) << 4]; + *d++ = '='; + *d++ = '='; + break; + case 2: + t1 = s[ti]; t2 = s[ti+1]; + *d++ = s_rvv_alphabet[t1 >> 2]; + *d++ = s_rvv_alphabet[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)]; + *d++ = s_rvv_alphabet[(t2 & 0x0F) << 2]; + *d++ = '='; + break; + default: + break; + } + + return (size_t)(d - (uint8_t*)dest); Review Comment: Fixed. Added `*d = '\0'` before return in both the RVV fast path and scalar tail, matching modp_b64_encode() behavior. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
