@@ -1244,24 +1244,21 @@ void MemCopy64(char* dst, const void* src, size_t size) {
12441244 _mm256_storeu_si256 (reinterpret_cast <__m256i *>(dst) + 1 , data);
12451245 }
12461246 // RVV acceleration available on RISC-V when compiled with -march=rv64gcv
1247+ // RVV: mirror the AVX path — first 32 B, then another 32 B if size > 32.
1248+ // e8m1 may need two segments per 32 B when VLEN < 256 (e.g. vl=16 on VLEN=128).
12471249#elif defined(__riscv) && SNAPPY_HAVE_RVV
1248- // Cast pointers to the type we will operate on.
1249- unsigned char * dst_ptr = reinterpret_cast <unsigned char *>(dst);
1250- const unsigned char * src_ptr = reinterpret_cast <const unsigned char *>(src);
1251- size_t remaining_bytes = size;
1252- // Loop as long as there are bytes remaining to be copied.
1253- while (remaining_bytes > 0 ) {
1254- // Set vector configuration: e8 (8-bit elements), m2 (LMUL=2).
1255- // Use e8m2 configuration to maximize throughput.
1256- size_t vl = VSETVL_E8M2 (remaining_bytes);
1257- // Load data from the current source pointer.
1258- vuint8m2_t vec = VLE8_V_U8M2 (src_ptr, vl);
1259- // Store data to the current destination pointer.
1260- VSE8_V_U8M2 (dst_ptr, vec, vl);
1261- // Update pointers and the remaining count.
1262- src_ptr += vl;
1263- dst_ptr += vl;
1264- remaining_bytes -= vl;
1250+ assert (kShortMemCopy <= 32 );
1251+ const size_t vl = VSETVL_E8M2 (32 );
1252+ unsigned char * d = reinterpret_cast <unsigned char *>(dst);
1253+ const unsigned char * s = reinterpret_cast <const unsigned char *>(src);
1254+ vuint8m2_t v0 = VLE8_V_U8M2 (s, vl);
1255+ VSE8_V_U8M2 (d, v0, vl);
1256+ // Profiling shows that nearly all copies are short.
1257+ if (SNAPPY_PREDICT_FALSE (size > kShortMemCopy )) {
1258+ const unsigned char * s2 = s + kShortMemCopy ;
1259+ unsigned char * d2 = d + kShortMemCopy ;
1260+ vuint8m2_t v2 = VLE8_V_U8M2 (s2, vl);
1261+ VSE8_V_U8M2 (d2, v2, vl);
12651262 }
12661263
12671264#else
0 commit comments