Repository: ClickHouse/ClickHouse
File: src/Compression/LZ4_decompress_faster.cpp (C++)

Code before:
        2,  3,  4,  5,  6,  0,  1,  2,  3,  4,  5,  6,  0,  1,  2,  3,
        0,  1,  2,  3,  4,  5,  6,  7,  0,  1,  2,  3,  4,  5,  6,  7,
        7,  8,  0,  1,  2,  3,  4,  5,  6,  7,  8,  0,  1,  2,  3,  4,
        6,  7,  8,  9,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0,  1,
        5,  6,  7,  8,  9, 10,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
        4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,
        3,  4,  5,  6,  7,  8,  9, 10, 11, 12,  0,  1,  2,  3,  4,  5,
        2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,  0,  1,  2,  3,
        1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  0,  1,
    };

    static constexpr UInt8 shifts[]
        = {0, 1, 2, 2, 4, 2, 2, 4, 8, 5, 2, 10, 8, 6, 4, 2, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};

    if (offset >= 16)
    {
        unalignedStore<uint8x16_t>(op,
            unalignedLoad<uint8x16_t>(match));

        unalignedStore<uint8x16_t>(op + 16,
            unalignedLoad<uint8x16_t>(match + 16));
    }
    else
    {
        unalignedStore<uint8x8_t>(op,
            vtbl2_u8(unalignedLoad<uint8x8x2_t>(match), unalignedLoad<uint8x8_t>(masks_lo + 16 * offset)));

        unalignedStore<uint8x8_t>(op + 8,
            vtbl2_u8(unalignedLoad<uint8x8x2_t>(match), unalignedLoad<uint8x8_t>(masks_lo + 16 * offset + 8)));

        unalignedStore<uint8x8_t>(op + 16,
            vtbl2_u8(unalignedLoad<uint8x8x2_t>(match), unalignedLoad<uint8x8_t>(masks_hi + 16 * offset)));

        unalignedStore<uint8x8_t>(op + 24,
            vtbl2_u8(unalignedLoad<uint8x8x2_t>(match), unalignedLoad<uint8x8_t>(masks_hi + 16 * offset + 8)));
    }

    match += shifts[offset];

#else
    /// 4 % n
    static constexpr UInt8 shift1[] = {0, 1, 2, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};

    /// 8 % n
    static constexpr UInt8 shift2[] = {0, 1, 2, 2, 4, 3, 2, 1, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};

    /// 16 % n
    static constexpr UInt8 shift3[]
        = {0, 1, 2, 1, 4, 1, 4, 2, 8, 7, 6, 5, 4, 3, 2, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};

    /// 32 % n

Review comment (suggestion):
Given that you use the arrays in this way, why not just define them as: `masks_hi[16][16]`. For `constexpr` the compiler will do this computation for you. 

Or, why not just: `&masks_lo[16 * offset]`? In old times this used to make the compiler more happy for vectorization.

Code after:
    /// For offset>=4: shift1[n]=4, so we read the next 4 fresh bytes.
    static constexpr UInt8 shift1[] = {0, 1, 2, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};

    /// Where to read from for the next 8 bytes (positions 8-15): equals (8 % offset) when that's non-zero, else 8.
    /// For offset=2: shift2[2]=2, wrapping the 2-byte pattern.
    /// For offset=3: shift2[3]=2, because 8%3=2, continuing from the 2nd byte of the pattern.
    /// For offset=5: shift2[5]=3, because 8%5=3, continuing from the 3rd byte of the pattern.
    /// For offset>=8: shift2[n]=8 or (8%n), reading fresh or wrapped bytes as appropriate.
    static constexpr UInt8 shift2[] = {0, 1, 2, 2, 4, 3, 2, 1, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};

    /// Where to read from for the next 16 bytes (positions 16-31): equals (16 % offset) when that's non-zero, else 16.
    /// For offset=3: shift3[3]=1, because 16%3=1.
    /// For offset=5: shift3[5]=1, because 16%5=1.
    /// For offset=9: shift3[9]=7, because 16%9=7.
    /// For offset>=16: shift3[n]=16, reading the next fresh 16 bytes without wrapping.
    static constexpr UInt8 shift3[]
        = {0, 1, 2, 1, 4, 1, 4, 2, 8, 7, 6, 5, 4, 3, 2, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};

    /// How far to advance match pointer after copying all 32 bytes: equals (32 % offset).
    /// This determines the final position after all four copy stages complete.
    /// Same values as the SSSE3 shifts table.
    static constexpr UInt8 shift4[]
        = {0, 1, 2, 2, 4, 2, 2, 4, 8, 5, 2, 10, 8, 6, 4, 2, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};

    /// Copy the first 4 bytes directly.
    op[0] = match[0];
    op[1] = match[1];
    op[2] = match[2];
    op[3] = match[3];

    /// Copy in stages, each reading from a position that maintains the repeating pattern.
    memcpy(op + 4, match + shift1[offset], 4);
    memcpy(op + 8, match + shift2[offset], 8);
    memcpy(op + 16, match + shift3[offset], 16);
    match += shift4[offset];
#endif
}


template <size_t copy_amount>
bool NO_INLINE decompressImpl(const char * const source, char * const dest, size_t source_size, size_t dest_size)
{
    const UInt8 * ip = reinterpret_cast<const UInt8 *>(source);
    UInt8 * op = reinterpret_cast<UInt8 *>(dest);
    const UInt8 * const input_end = ip + source_size;
    UInt8 * const output_begin = op;
    UInt8 * const output_end = op + dest_size;

    while (true)
    {
        size_t length;