@@ -282,18 +282,6 @@ inline char* IncrementalCopySlow(const char* src, char* op,
282282// calling MakePatternMaskBytes(0, 6, index_sequence<16>()) and
283283// MakePatternMaskBytes(16, 6, index_sequence<16>()) respectively.
284284
285- // Selects the appropriate vector size based on the current architecture
286- // vuint8m1_t, RISC-V vector type with fixed 128-bit size
287- // (sizeof not used due to variable-length vector register in RVV)
288- #if defined(__SSE2__) || defined(SNAPPY_HAVE_SSSE3)
289- constexpr size_t kVectorSize = sizeof (V128 ); // __m128i
290- #elif defined(__ARM_NEON) || defined(SNAPPY_HAVE_NEON)
291- constexpr size_t kVectorSize = sizeof (uint8x16_t ); // uint8x16_t
292- #elif defined(SNAPPY_HAVE_RVV) || defined(__riscv_vector)
293- constexpr size_t kVectorSize = 16 ; // vuint8m1_t
294- #else
295- #error "Unsupported architecture. Please define __SSE2__, __ARM_NEON, or SNAPPY_HAVE_RVV/__riscv_vector."
296- #endif
297285
298286template <size_t ... indexes>
299287inline constexpr std::array<char , sizeof ...(indexes)> MakePatternMaskBytes (
@@ -342,20 +330,14 @@ static inline V128 LoadPattern(const char* src, const size_t pattern_size) {
342330 generation_mask);
343331}
344332// vuint8m1_t cannot be used as an element of std::pair
345- #if SNAPPY_HAVE_RVV
346- #define LoadPatternAndReshuffleMask (src, pattern_size ) \
347- V128 pattern = LoadPattern(src, pattern_size);\
348- V128 reshuffle_mask = V128_Load(reinterpret_cast <const V128 *>(\
349- pattern_reshuffle_masks[pattern_size - 1 ].data()));
350- #else
351333
352334// Suppress -Wignored-attributes warning for __m128i in x86 SSE2 environment
353335// warning: ignoring attributes on template argument 'snappy::internal::V128' {aka '__vector(2) long long int'} [-Wignored-attributes]
354336// This occurs because __m128i has vector attributes (e.g., __attribute__((vector_size(16)))) that are ignored in template parameters.
355337#ifdef __SSE2__
356338#pragma GCC diagnostic push
357339#pragma GCC diagnostic ignored "-Wignored-attributes"
358- # endif
340+
359341
360342SNAPPY_ATTRIBUTE_ALWAYS_INLINE
361343static inline std::pair<V128 /* pattern */ , V128 /* reshuffle_mask */ >
@@ -411,14 +393,10 @@ static inline bool Copy64BytesWithPatternExtension(char* dst, size_t offset) {
411393 return true ;
412394 }
413395 default : {
414- #if SNAPPY_HAVE_RVV
415- LoadPatternAndReshuffleMask (dst - offset, offset)
416- #else
417396 auto pattern_and_reshuffle_mask =
418397 LoadPatternAndReshuffleMask (dst - offset, offset);
419398 V128 pattern = pattern_and_reshuffle_mask.first ;
420399 V128 reshuffle_mask = pattern_and_reshuffle_mask.second ;
421- #endif
422400 for (int i = 0 ; i < 4 ; i++) {
423401 V128_StoreU (reinterpret_cast <V128 *>(dst + 16 * i), pattern);
424402 pattern = V128_Shuffle (pattern, reshuffle_mask);
@@ -526,14 +504,10 @@ inline char* IncrementalCopy(const char* src, char* op, char* const op_limit,
526504 // Typically, the op_limit is the gating factor so try to simplify the loop
527505 // based on that.
528506 if (SNAPPY_PREDICT_TRUE (op_limit <= buf_limit - 15 )) {
529- #if SNAPPY_HAVE_RVV
530- LoadPatternAndReshuffleMask (src, pattern_size);
531- #else
532507 auto pattern_and_reshuffle_mask =
533508 LoadPatternAndReshuffleMask (src, pattern_size);
534509 V128 pattern = pattern_and_reshuffle_mask.first ;
535510 V128 reshuffle_mask = pattern_and_reshuffle_mask.second ;
536- #endif
537511 // There is at least one, and at most four 16-byte blocks. Writing four
538512 // conditionals instead of a loop allows FDO to layout the code with
539513 // respect to the actual probabilities of each length.
@@ -556,14 +530,10 @@ inline char* IncrementalCopy(const char* src, char* op, char* const op_limit,
556530 }
557531 char * const op_end = buf_limit - 15 ;
558532 if (SNAPPY_PREDICT_TRUE (op < op_end)) {
559- #if SNAPPY_HAVE_RVV
560- LoadPatternAndReshuffleMask (src, pattern_size);
561- #else
562533 auto pattern_and_reshuffle_mask =
563534 LoadPatternAndReshuffleMask (src, pattern_size);
564535 V128 pattern = pattern_and_reshuffle_mask.first ;
565536 V128 reshuffle_mask = pattern_and_reshuffle_mask.second ;
566- #endif
567537 // This code path is relatively cold however so we save code size
568538 // by avoiding unrolling and vectorizing.
569539 //
@@ -1288,36 +1258,27 @@ void MemCopy64(char* dst, const void* src, size_t size) {
12881258 data = _mm256_lddqu_si256 (static_cast <const __m256i *>(src) + 1 );
12891259 _mm256_storeu_si256 (reinterpret_cast <__m256i *>(dst) + 1 , data);
12901260 }
1291- // RVV acceleration available on RISC-V when compiled with -march=rv64gcv
1292- #elif defined(__riscv) & SNAPPY_HAVE_RVV
1293- uint8_t * dst_u8 = (uint8_t *)dst;
1294- const uint8_t * src_u8 = (const uint8_t *)src;
1295- // overlap bwd copy
1296- if (src_u8 < dst_u8 && dst_u8 < src_u8 + size) {
1297- size_t offset = size;
1298- while (offset > 0 ) {
1299- size_t vl = VSETVL_E8M1 (offset);
1300- offset -= vl;
1301- vuint8m1_t vec = VLE8_V_U8M1 (src_u8 + offset, vl);
1302- VSE8_V_U8M1 (dst_u8 + offset, vec, vl);
1303- }
1304- } else {
1305- size_t vl = VSETVL_E8M1 (size);
1306- // if size >vl,use the max_vlen copy
1307- if (vl < size) {
1308- size_t offset = 0 ;
1309- while (offset < size) {
1310- vl = VSETVL_E8M1 (size - offset);
1311- vuint8m1_t vec = VLE8_V_U8M1 (src_u8 + offset, vl);
1312- VSE8_V_U8M1 (dst_u8 + offset, vec, vl);
1313- offset += vl;
1314- }
1315- } else {
1316- // Copy the rest
1317- vuint8m1_t vec = VLE8_V_U8M1 (src_u8, vl);
1318- VSE8_V_U8M1 (dst_u8, vec, vl);
1319- }
1320- }
1261+ // RVV acceleration available on RISC-V when compiled with -march=rv64gcv
1262+ #elif defined(__riscv) && SNAPPY_HAVE_RVV
1263+ // Cast pointers to the type we will operate on.
1264+ unsigned char * dst_ptr = (unsigned char *)dst;
1265+ const unsigned char * src_ptr = (const unsigned char *)src;
1266+ size_t remaining_bytes = size;
1267+ // Loop as long as there are bytes remaining to be copied.
1268+ while (remaining_bytes > 0 ) {
1269+ // Set vector configuration: e8 (8-bit elements), m2 (LMUL=2).
1270+ // Use e8m2 configuration to maximize throughput.
1271+ size_t vl = VSETVL_E8M2 (remaining_bytes);
1272+ // Load data from the current source pointer.
1273+ vuint8m2_t vec = VLE8_V_U8M2 (src_ptr, vl);
1274+ // Store data to the current destination pointer.
1275+ VSE8_V_U8M2 (dst_ptr, vec, vl);
1276+ // Update pointers and the remaining count.
1277+ src_ptr += vl;
1278+ dst_ptr += vl;
1279+ remaining_bytes -= vl;
1280+ }
1281+
13211282#else
13221283 std::memmove (dst, src, kShortMemCopy );
13231284 // Profiling shows that nearly all copies are short.
0 commit comments