Fallback for when we need to copy while extending the pattern, for example copying 10 bytes from 3 positions back abc -> abcabcabcabca. REQUIRES: [dst - offset, dst + 64) is a valid address range.
| 360 | // |
| 361 | // REQUIRES: [dst - offset, dst + 64) is a valid address range. |
| 362 | SNAPPY_ATTRIBUTE_ALWAYS_INLINE |
| 363 | static inline bool Copy64BytesWithPatternExtension(char* dst, size_t offset) { |
| 364 | #if SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE |
| 365 | if (SNAPPY_PREDICT_TRUE(offset <= 16)) { |
| 366 | switch (offset) { |
| 367 | case 0: |
| 368 | return false; |
| 369 | case 1: { |
| 370 | // TODO: Ideally we should memset, move back once the |
| 371 | // codegen issues are fixed. |
| 372 | V128 pattern = V128_DupChar(dst[-1]); |
| 373 | for (int i = 0; i < 4; i++) { |
| 374 | V128_StoreU(reinterpret_cast<V128*>(dst + 16 * i), pattern); |
| 375 | } |
| 376 | return true; |
| 377 | } |
| 378 | case 2: |
| 379 | case 4: |
| 380 | case 8: |
| 381 | case 16: { |
| 382 | V128 pattern = LoadPattern(dst - offset, offset); |
| 383 | for (int i = 0; i < 4; i++) { |
| 384 | V128_StoreU(reinterpret_cast<V128*>(dst + 16 * i), pattern); |
| 385 | } |
| 386 | return true; |
| 387 | } |
| 388 | default: { |
| 389 | auto pattern_and_reshuffle_mask = |
| 390 | LoadPatternAndReshuffleMask(dst - offset, offset); |
| 391 | V128 pattern = pattern_and_reshuffle_mask.first; |
| 392 | V128 reshuffle_mask = pattern_and_reshuffle_mask.second; |
| 393 | for (int i = 0; i < 4; i++) { |
| 394 | V128_StoreU(reinterpret_cast<V128*>(dst + 16 * i), pattern); |
| 395 | pattern = V128_Shuffle(pattern, reshuffle_mask); |
| 396 | } |
| 397 | return true; |
| 398 | } |
| 399 | } |
| 400 | } |
| 401 | #else |
| 402 | if (SNAPPY_PREDICT_TRUE(offset < 16)) { |
| 403 | if (SNAPPY_PREDICT_FALSE(offset == 0)) return false; |
| 404 | // Extend the pattern to the first 16 bytes. |
| 405 | // The simpler formulation of `dst[i - offset]` induces undefined behavior. |
| 406 | for (int i = 0; i < 16; i++) dst[i] = (dst - offset)[i]; |
| 407 | // Find a multiple of pattern >= 16. |
| 408 | static std::array<uint8_t, 16> pattern_sizes = []() { |
| 409 | std::array<uint8_t, 16> res; |
| 410 | for (int i = 1; i < 16; i++) res[i] = (16 / i + 1) * i; |
| 411 | return res; |
| 412 | }(); |
| 413 | offset = pattern_sizes[offset]; |
| 414 | for (int i = 1; i < 4; i++) { |
| 415 | std::memcpy(dst + i * 16, dst + i * 16 - offset, 16); |
| 416 | } |
| 417 | return true; |
| 418 | } |
| 419 | #endif // SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE |
no test coverage detected