Applies the changes done in SSE implementation to AVX512 implementation.
Specifically includes the following:
1) Consolidate the <16 len cases and removes len 31 to 16 special handling.
2) Replace byte_len_to_mask_table lookup with equivalent C expression.
3) Replace mask, mask2, mask3 arrays with equivalent SIMD expression.
4) Use SSE barrett_reduction logic with same fold constants.
5) Use SSE logic for partial bytes handling in last_two_xmm function.

Signed-off-by: Shreesh Adiga <[email protected]>
---
 lib/net/net_crc_avx512.c | 86 ++++++++++------------------------------
 1 file changed, 22 insertions(+), 64 deletions(-)

diff --git a/lib/net/net_crc_avx512.c b/lib/net/net_crc_avx512.c
index 7cd681b1cd..b1a00324e8 100644
--- a/lib/net/net_crc_avx512.c
+++ b/lib/net/net_crc_avx512.c
@@ -23,27 +23,20 @@ struct crc_vpclmulqdq_ctx {
 static alignas(64) struct crc_vpclmulqdq_ctx crc32_eth;
 static alignas(64) struct crc_vpclmulqdq_ctx crc16_ccitt;
 
-static uint16_t byte_len_to_mask_table[] = {
-       0x0000, 0x0001, 0x0003, 0x0007,
-       0x000f, 0x001f, 0x003f, 0x007f,
-       0x00ff, 0x01ff, 0x03ff, 0x07ff,
-       0x0fff, 0x1fff, 0x3fff, 0x7fff,
-       0xffff};
-
 static const alignas(16) uint8_t shf_table[32] = {
-       0x00, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+       0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+       0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
 };
 
-static const alignas(16) uint32_t mask[4] = {
-       0xffffffff, 0xffffffff, 0x00000000, 0x00000000
-};
+static __rte_always_inline __m128i
+xmm_shift_left(__m128i reg, const unsigned int num)
+{
+       const __m128i *p = (const __m128i *)(shf_table + 16 - num);
 
-static const alignas(16) uint32_t mask2[4] = {
-       0x00000000, 0xffffffff, 0xffffffff, 0xffffffff
-};
+       return _mm_shuffle_epi8(reg, _mm_loadu_si128(p));
+}
 
 static __rte_always_inline __m512i
 crcr32_folding_round(__m512i data_block, __m512i precomp, __m512i fold)
@@ -93,10 +86,6 @@ last_two_xmm(const uint8_t *data, uint32_t data_len, 
uint32_t n, __m128i res,
        uint32_t offset;
        __m128i res2, res3, res4, pshufb_shf;
 
-       const alignas(16) uint32_t mask3[4] = {
-                  0x80808080, 0x80808080, 0x80808080, 0x80808080
-       };
-
        res2 = res;
        offset = data_len - n;
        res3 = _mm_loadu_si128((const __m128i *)&data[n+offset-16]);
@@ -105,8 +94,7 @@ last_two_xmm(const uint8_t *data, uint32_t data_len, 
uint32_t n, __m128i res,
                        (shf_table + (data_len-n)));
 
        res = _mm_shuffle_epi8(res, pshufb_shf);
-       pshufb_shf = _mm_xor_si128(pshufb_shf,
-                       _mm_load_si128((const __m128i *) mask3));
+       pshufb_shf = _mm_xor_si128(pshufb_shf, _mm_set1_epi8(0xff));
        res2 = _mm_shuffle_epi8(res2, pshufb_shf);
 
        res2 = _mm_blendv_epi8(res2, res3, pshufb_shf);
@@ -140,19 +128,16 @@ done_128(__m128i res, const struct crc_vpclmulqdq_ctx 
*params)
 static __rte_always_inline uint32_t
 barrett_reduction(__m128i data64, const struct crc_vpclmulqdq_ctx *params)
 {
-       __m128i tmp0, tmp1;
+       __m128i tmp0;
 
-       data64 =  _mm_and_si128(data64, *(const __m128i *)mask2);
+       data64 = _mm_blend_epi16(data64, _mm_setzero_si128(), 0x3);
        tmp0 = data64;
-       tmp1 = data64;
 
-       data64 = _mm_clmulepi64_si128(tmp0, params->rk7_rk8, 0x0);
-       data64 = _mm_ternarylogic_epi64(data64, tmp1, *(const __m128i *)mask,
-                       0x28);
+       data64 = _mm_clmulepi64_si128(data64, params->rk7_rk8, 0x0);
+       data64 = _mm_xor_si128(data64, tmp0);
 
-       tmp1 = data64;
        data64 = _mm_clmulepi64_si128(data64, params->rk7_rk8, 0x10);
-       data64 = _mm_ternarylogic_epi64(data64, tmp1, tmp0, 0x96);
+       data64 = _mm_xor_si128(data64, tmp0);
 
        return _mm_extract_epi32(data64, 2);
 }
@@ -165,9 +150,8 @@ reduction_loop(__m128i *fold, int *len, const uint8_t 
*data, uint32_t *n,
 
        tmp = _mm_clmulepi64_si128(*fold, params->fold_1x128b, 0x1);
        *fold = _mm_clmulepi64_si128(*fold, params->fold_1x128b, 0x10);
-       *fold = _mm_xor_si128(*fold, tmp);
        tmp1 = _mm_loadu_si128((const __m128i *)&data[*n]);
-       *fold = _mm_xor_si128(*fold, tmp1);
+       *fold = _mm_ternarylogic_epi64(*fold, tmp, tmp1, 0x96);
        *n += 16;
        *len -= 16;
 }
@@ -229,7 +213,7 @@ crc32_eth_calc_vpclmulqdq(const uint8_t *data, uint32_t 
data_len, uint32_t crc,
                        res = last_two_xmm(data, data_len, n, res,
                                        params);
        } else {
-               if (data_len > 31) {
+               if (data_len >= 16) {
                        res = _mm_cvtsi32_si128(crc);
                        d = _mm_loadu_si128((const __m128i *)data);
                        res = _mm_xor_si128(res, d);
@@ -244,41 +228,15 @@ crc32_eth_calc_vpclmulqdq(const uint8_t *data, uint32_t 
data_len, uint32_t crc,
                        if (n != data_len)
                                res = last_two_xmm(data, data_len, n, res,
                                                params);
-               } else if (data_len > 16) {
-                       res = _mm_cvtsi32_si128(crc);
-                       d = _mm_loadu_si128((const __m128i *)data);
-                       res = _mm_xor_si128(res, d);
-                       n += 16;
-
-                       if (n != data_len)
-                               res = last_two_xmm(data, data_len, n, res,
-                                               params);
-               } else if (data_len == 16) {
-                       res = _mm_cvtsi32_si128(crc);
-                       d = _mm_loadu_si128((const __m128i *)data);
-                       res = _mm_xor_si128(res, d);
                } else {
                        res = _mm_cvtsi32_si128(crc);
-                       d = 
_mm_maskz_loadu_epi8(byte_len_to_mask_table[data_len], data);
+                       d = _mm_maskz_loadu_epi8((1 << data_len) - 1, data);
                        res = _mm_xor_si128(res, d);
-
-                       if (data_len > 3) {
-                               d = _mm_loadu_si128((const __m128i *)
-                                               &shf_table[data_len]);
-                               res = _mm_shuffle_epi8(res, d);
-                       } else if (data_len > 2) {
-                               res = _mm_slli_si128(res, 5);
-                               goto do_barrett_reduction;
-                       } else if (data_len > 1) {
-                               res = _mm_slli_si128(res, 6);
-                               goto do_barrett_reduction;
-                       } else if (data_len > 0) {
-                               res = _mm_slli_si128(res, 7);
+                       if (data_len < 4) {
+                               res = xmm_shift_left(res, 8 - data_len);
                                goto do_barrett_reduction;
-                       } else {
-                               /* zero length case */
-                               return crc;
                        }
+                       res = xmm_shift_left(res, 16 - data_len);
                }
        }
 
@@ -316,7 +274,7 @@ crc32_load_init_constants(void)
        uint64_t c18 = 0x00000000ccaa009e;
        uint64_t c19 = 0x00000000b8bc6765;
        uint64_t c20 = 0x00000001f7011640;
-       uint64_t c21 = 0x00000001db710640;
+       uint64_t c21 = 0x00000001db710641;
 
        a = _mm_set_epi64x(c1, c0);
        crc32_eth.rk1_rk2 = _mm512_broadcast_i32x4(a);
@@ -360,7 +318,7 @@ crc16_load_init_constants(void)
        uint64_t c18 = 0x00000000000081bf;
        uint64_t c19 = 0x0000000000001cbb;
        uint64_t c20 = 0x000000011c581910;
-       uint64_t c21 = 0x0000000000010810;
+       uint64_t c21 = 0x0000000000010811;
 
        a = _mm_set_epi64x(c1, c0);
        crc16_ccitt.rk1_rk2 = _mm512_broadcast_i32x4(a);
-- 
2.54.0

Reply via email to