diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-14 17:36:22 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-14 17:36:22 +0300 |
| commit | 13bf7edad251df9943bd75665a3510535849b0ac (patch) | |
| tree | 4597aae71940edac0b7d8b416c4803cd72ac5345 /src/kernels.h | |
| parent | 513bf031a589d9e2a1a2730adf56f95e5e316a06 (diff) | |
Deduplicate scroll and SIMD paths while preserving performance
Diffstat (limited to 'src/kernels.h')
| -rw-r--r-- | src/kernels.h | 151 |
1 files changed, 61 insertions, 90 deletions
diff --git a/src/kernels.h b/src/kernels.h index 57066c0..5cf0d93 100644 --- a/src/kernels.h +++ b/src/kernels.h @@ -197,23 +197,14 @@ static inline TERM_ALWAYS_INLINE void bytes_copy_small(uint8_t *restrict dst, if (k < n) memcpy(dst + n - 16, src + n - 16, 16); } else if (n >= 8) { - uint64_t a, b; - memcpy(&a, src, 8); - memcpy(&b, src + n - 8, 8); - memcpy(dst, &a, 8); - memcpy(dst + n - 8, &b, 8); + memcpy(dst, src, 8); + memcpy(dst + n - 8, src + n - 8, 8); } else if (n >= 4) { - uint32_t a, b; - memcpy(&a, src, 4); - memcpy(&b, src + n - 4, 4); - memcpy(dst, &a, 4); - memcpy(dst + n - 4, &b, 4); + memcpy(dst, src, 4); + memcpy(dst + n - 4, src + n - 4, 4); } else if (n >= 2) { - uint16_t a, b; - memcpy(&a, src, 2); - memcpy(&b, src + n - 2, 2); - memcpy(dst, &a, 2); - memcpy(dst + n - 2, &b, 2); + memcpy(dst, src, 2); + memcpy(dst + n - 2, src + n - 2, 2); } else if (n == 1) { dst[0] = (uint8_t)src[0]; } @@ -365,6 +356,26 @@ static inline int scan_ascii_lf_tail(const char *buf, int i, int len, uint16_t * } #if defined(TERM_KERNEL_AVX512) +TERM_TARGET_AVX512 +static inline int store_lf_offsets_avx512(uint16_t *ends, uint64_t nl, + __m512i lanes, __m128i block) +{ + unsigned n = (unsigned)term_popcount64(nl); + __m512i packed = _mm512_maskz_compress_epi8(nl, lanes); + __m128i offsets = _mm_add_epi16(_mm_cvtepu8_epi16(_mm512_castsi512_si128(packed)), block); + _mm_storeu_si128((__m128i *)ends, offsets); + if (TERM_EXPECT(n > 8, 0)) { + __m512i base = _mm512_broadcast_i32x4(block); + __m512i wide = _mm512_add_epi16(_mm512_cvtepu8_epi16(_mm512_castsi512_si256(packed)), base); + _mm512_storeu_si512(ends, wide); + if (n > 32) { + wide = _mm512_add_epi16(_mm512_cvtepu8_epi16(_mm512_extracti64x4_epi64(packed, 1)), base); + _mm512_storeu_si512(ends + 32, wide); + } + } + return (int)n; +} + TERM_TARGET_AVX512 TERM_MAYBE_UNUSED static int scan_ascii_lf_avx512(const char *buf, int len, uint16_t *ends) { @@ -388,20 +399,7 @@ static int scan_ascii_lf_avx512(const char *buf, int len, uint16_t *ends) } if (bad) break; for (int q = 0; q < 4; q++) { - unsigned n = (unsigned)term_popcount64(nl[q]); - __m512i packed = _mm512_maskz_compress_epi8(nl[q], lanes); - __m128i offsets = _mm_add_epi16(_mm_cvtepu8_epi16(_mm512_castsi512_si128(packed)), block); - _mm_storeu_si128((__m128i *)(ends + count + 1), offsets); - if (TERM_EXPECT(n > 8, 0)) { - __m512i base = _mm512_broadcast_i32x4(block); - __m512i wide = _mm512_add_epi16(_mm512_cvtepu8_epi16(_mm512_castsi512_si256(packed)), base); - _mm512_storeu_si512(ends + count + 1, wide); - if (n > 32) { - wide = _mm512_add_epi16(_mm512_cvtepu8_epi16(_mm512_extracti64x4_epi64(packed, 1)), base); - _mm512_storeu_si512(ends + count + 33, wide); - } - } - count += (int)n; + count += store_lf_offsets_avx512(ends + count + 1, nl[q], lanes, block); block = _mm_add_epi16(block, _mm_set1_epi16(64)); } } @@ -411,20 +409,7 @@ static int scan_ascii_lf_avx512(const char *buf, int len, uint16_t *ends) uint64_t bad = _mm512_cmpge_epu8_mask( _mm512_sub_epi8(v, _mm512_set1_epi8(0x20)), _mm512_set1_epi8(0x5f)) & ~nl; if (bad) break; - unsigned n = (unsigned)term_popcount64(nl); - __m512i packed = _mm512_maskz_compress_epi8(nl, lanes); - __m128i offsets = _mm_add_epi16(_mm_cvtepu8_epi16(_mm512_castsi512_si128(packed)), block); - _mm_storeu_si128((__m128i *)(ends + count + 1), offsets); - if (TERM_EXPECT(n > 8, 0)) { - __m512i base = _mm512_broadcast_i32x4(block); - __m512i wide = _mm512_add_epi16(_mm512_cvtepu8_epi16(_mm512_castsi512_si256(packed)), base); - _mm512_storeu_si512(ends + count + 1, wide); - if (n > 32) { - wide = _mm512_add_epi16(_mm512_cvtepu8_epi16(_mm512_extracti64x4_epi64(packed, 1)), base); - _mm512_storeu_si512(ends + count + 33, wide); - } - } - count += (int)n; + count += store_lf_offsets_avx512(ends + count + 1, nl, lanes, block); block = _mm_add_epi16(block, _mm_set1_epi16(64)); } return scan_ascii_lf_tail(buf, i, len, ends, count); @@ -672,6 +657,32 @@ static inline void put_ascii_chunk_avx2(struct cell * restrict dst, const char * } #endif +#if defined(__aarch64__) +static inline void store_ascii_quad_neon(struct cell *dst, uint32x4_t cps, + uint32x4_t fg, uint32x4_t bg_flags) +{ + uint64x2_t lo = vreinterpretq_u64_u32(vzip1q_u32(cps, fg)); + uint64x2_t hi = vreinterpretq_u64_u32(vzip2q_u32(cps, fg)); + uint64x2_t tail = vreinterpretq_u64_u32(bg_flags); + uint32x4x4_t cells = {{ + vreinterpretq_u32_u64(vzip1q_u64(lo, tail)), + vreinterpretq_u32_u64(vzip2q_u64(lo, tail)), + vreinterpretq_u32_u64(vzip1q_u64(hi, tail)), + vreinterpretq_u32_u64(vzip2q_u64(hi, tail)), + }}; + vst1q_u32_x4((uint32_t *)(void *)dst, cells); +} + +static inline void put_ascii_quad_neon(struct cell *dst, const char *src, + uint32x4_t fg, uint32x4_t bg_flags) +{ + uint32_t bytes; + memcpy(&bytes, src, sizeof(bytes)); + uint16x4_t cps = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vdup_n_u32(bytes)))); + store_ascii_quad_neon(dst, vmovl_u16(cps), fg, bg_flags); +} +#endif + TERM_ALWAYS_INLINE static inline void put_ascii_chunk(struct cell * restrict dst, const char * restrict src, int n, uint32_t fg, uint32_t bg, uint32_t flags) @@ -696,55 +707,15 @@ static inline void put_ascii_chunk(struct cell * restrict dst, const char * rest vcreate_u32(((uint64_t)flags << 32) | bg)); for (; k + 8 <= n; k += 8) { uint16x8_t cp16 = vmovl_u8(vld1_u8((const uint8_t *)src + k)); - uint32x4_t cp_lo = vmovl_u16(vget_low_u16(cp16)); - uint32x4_t cp_hi = vmovl_u16(vget_high_u16(cp16)); - - uint32x4_t c_fg_01 = vzip1q_u32(cp_lo, fg4); - uint32x4_t c_fg_23 = vzip2q_u32(cp_lo, fg4); - uint32x4_t c_fg_45 = vzip1q_u32(cp_hi, fg4); - uint32x4_t c_fg_67 = vzip2q_u32(cp_hi, fg4); - - uint32x4_t cell0 = (uint32x4_t)vzip1q_u64((uint64x2_t)c_fg_01, (uint64x2_t)bg_flags); - uint32x4_t cell1 = (uint32x4_t)vzip2q_u64((uint64x2_t)c_fg_01, (uint64x2_t)bg_flags); - uint32x4_t cell2 = (uint32x4_t)vzip1q_u64((uint64x2_t)c_fg_23, (uint64x2_t)bg_flags); - uint32x4_t cell3 = (uint32x4_t)vzip2q_u64((uint64x2_t)c_fg_23, (uint64x2_t)bg_flags); - uint32x4_t cell4 = (uint32x4_t)vzip1q_u64((uint64x2_t)c_fg_45, (uint64x2_t)bg_flags); - uint32x4_t cell5 = (uint32x4_t)vzip2q_u64((uint64x2_t)c_fg_45, (uint64x2_t)bg_flags); - uint32x4_t cell6 = (uint32x4_t)vzip1q_u64((uint64x2_t)c_fg_67, (uint64x2_t)bg_flags); - uint32x4_t cell7 = (uint32x4_t)vzip2q_u64((uint64x2_t)c_fg_67, (uint64x2_t)bg_flags); - - uint32x4x4_t q0 = {{ cell0, cell1, cell2, cell3 }}; - uint32x4x4_t q1 = {{ cell4, cell5, cell6, cell7 }}; - vst1q_u32_x4((uint32_t *)(void *)(dst + k + 0), q0); - vst1q_u32_x4((uint32_t *)(void *)(dst + k + 4), q1); - } - for (; k + 4 <= n; k += 4) { - uint32_t bytes; - memcpy(&bytes, src + k, sizeof(bytes)); - uint16x4_t cp16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vdup_n_u32(bytes)))); - uint32x4_t cp_lo = vmovl_u16(cp16); - uint32x4_t c_fg_01 = vzip1q_u32(cp_lo, fg4); - uint32x4_t c_fg_23 = vzip2q_u32(cp_lo, fg4); - uint32x4_t cell0 = (uint32x4_t)vzip1q_u64((uint64x2_t)c_fg_01, (uint64x2_t)bg_flags); - uint32x4_t cell1 = (uint32x4_t)vzip2q_u64((uint64x2_t)c_fg_01, (uint64x2_t)bg_flags); - uint32x4_t cell2 = (uint32x4_t)vzip1q_u64((uint64x2_t)c_fg_23, (uint64x2_t)bg_flags); - uint32x4_t cell3 = (uint32x4_t)vzip2q_u64((uint64x2_t)c_fg_23, (uint64x2_t)bg_flags); - uint32x4x4_t q0 = {{ cell0, cell1, cell2, cell3 }}; - vst1q_u32_x4((uint32_t *)(void *)(dst + k + 0), q0); + store_ascii_quad_neon(dst + k, vmovl_u16(vget_low_u16(cp16)), fg4, bg_flags); + store_ascii_quad_neon(dst + k + 4, vmovl_u16(vget_high_u16(cp16)), fg4, bg_flags); + } + if (k + 4 <= n) { + put_ascii_quad_neon(dst + k, src + k, fg4, bg_flags); + k += 4; } if (k < n && n >= 4) { - uint32_t bytes; - memcpy(&bytes, src + n - 4, sizeof(bytes)); - uint16x4_t cp16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vdup_n_u32(bytes)))); - uint32x4_t cp_lo = vmovl_u16(cp16); - uint32x4_t c_fg_01 = vzip1q_u32(cp_lo, fg4); - uint32x4_t c_fg_23 = vzip2q_u32(cp_lo, fg4); - uint32x4_t cell0 = (uint32x4_t)vzip1q_u64((uint64x2_t)c_fg_01, (uint64x2_t)bg_flags); - uint32x4_t cell1 = (uint32x4_t)vzip2q_u64((uint64x2_t)c_fg_01, (uint64x2_t)bg_flags); - uint32x4_t cell2 = (uint32x4_t)vzip1q_u64((uint64x2_t)c_fg_23, (uint64x2_t)bg_flags); - uint32x4_t cell3 = (uint32x4_t)vzip2q_u64((uint64x2_t)c_fg_23, (uint64x2_t)bg_flags); - uint32x4x4_t q0 = {{ cell0, cell1, cell2, cell3 }}; - vst1q_u32_x4((uint32_t *)(void *)(dst + n - 4), q0); + put_ascii_quad_neon(dst + n - 4, src + n - 4, fg4, bg_flags); k = n; } #elif defined(__x86_64__) |
