LCOV - code coverage report
Current view: top level - lib/acl - acl_run_avx2.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 62 62 100.0 %
Date: 2025-02-01 18:54:23 Functions: 3 3 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 8 8 100.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2014 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "acl_run_sse.h"
       6                 :            : 
       7                 :            : static const rte_ymm_t ymm_match_mask = {
       8                 :            :         .u32 = {
       9                 :            :                 RTE_ACL_NODE_MATCH,
      10                 :            :                 RTE_ACL_NODE_MATCH,
      11                 :            :                 RTE_ACL_NODE_MATCH,
      12                 :            :                 RTE_ACL_NODE_MATCH,
      13                 :            :                 RTE_ACL_NODE_MATCH,
      14                 :            :                 RTE_ACL_NODE_MATCH,
      15                 :            :                 RTE_ACL_NODE_MATCH,
      16                 :            :                 RTE_ACL_NODE_MATCH,
      17                 :            :         },
      18                 :            : };
      19                 :            : 
      20                 :            : static const rte_ymm_t ymm_index_mask = {
      21                 :            :         .u32 = {
      22                 :            :                 RTE_ACL_NODE_INDEX,
      23                 :            :                 RTE_ACL_NODE_INDEX,
      24                 :            :                 RTE_ACL_NODE_INDEX,
      25                 :            :                 RTE_ACL_NODE_INDEX,
      26                 :            :                 RTE_ACL_NODE_INDEX,
      27                 :            :                 RTE_ACL_NODE_INDEX,
      28                 :            :                 RTE_ACL_NODE_INDEX,
      29                 :            :                 RTE_ACL_NODE_INDEX,
      30                 :            :         },
      31                 :            : };
      32                 :            : 
      33                 :            : static const rte_ymm_t ymm_shuffle_input = {
      34                 :            :         .u32 = {
      35                 :            :                 0x00000000, 0x04040404, 0x08080808, 0x0c0c0c0c,
      36                 :            :                 0x00000000, 0x04040404, 0x08080808, 0x0c0c0c0c,
      37                 :            :         },
      38                 :            : };
      39                 :            : 
      40                 :            : static const rte_ymm_t ymm_ones_16 = {
      41                 :            :         .u16 = {
      42                 :            :                 1, 1, 1, 1, 1, 1, 1, 1,
      43                 :            :                 1, 1, 1, 1, 1, 1, 1, 1,
      44                 :            :         },
      45                 :            : };
      46                 :            : 
      47                 :            : static const rte_ymm_t ymm_range_base = {
      48                 :            :         .u32 = {
      49                 :            :                 0xffffff00, 0xffffff04, 0xffffff08, 0xffffff0c,
      50                 :            :                 0xffffff00, 0xffffff04, 0xffffff08, 0xffffff0c,
      51                 :            :         },
      52                 :            : };
      53                 :            : 
      54                 :            : /*
      55                 :            :  * Process 8 transitions in parallel.
      56                 :            :  * tr_lo contains low 32 bits for 8 transition.
      57                 :            :  * tr_hi contains high 32 bits for 8 transition.
      58                 :            :  * next_input contains up to 4 input bytes for 8 flows.
      59                 :            :  */
      60                 :            : static __rte_always_inline ymm_t
      61                 :            : transition8(ymm_t next_input, const uint64_t *trans, ymm_t *tr_lo, ymm_t *tr_hi)
      62                 :            : {
      63                 :            :         const int32_t *tr;
      64                 :            :         ymm_t addr;
      65                 :            : 
      66                 :            :         tr = (const int32_t *)(uintptr_t)trans;
      67                 :            : 
      68                 :            :         /* Calculate the address (array index) for all 8 transitions. */
      69                 :    1810262 :         ACL_TR_CALC_ADDR(mm256, 256, addr, ymm_index_mask.y, next_input,
      70                 :            :                 ymm_shuffle_input.y, ymm_ones_16.y, ymm_range_base.y,
      71                 :            :                 *tr_lo, *tr_hi);
      72                 :            : 
      73                 :            :         /* load lower 32 bits of 8 transactions at once. */
      74                 :    1810262 :         *tr_lo = _mm256_i32gather_epi32(tr, addr, sizeof(trans[0]));
      75                 :            : 
      76                 :            :         next_input = _mm256_srli_epi32(next_input, CHAR_BIT);
      77                 :            : 
      78                 :            :         /* load high 32 bits of 8 transactions at once. */
      79                 :    1810262 :         *tr_hi = _mm256_i32gather_epi32(tr + 1, addr, sizeof(trans[0]));
      80                 :            : 
      81                 :            :         return next_input;
      82                 :            : }
      83                 :            : 
      84                 :            : /*
      85                 :            :  * Process matches for  8 flows.
      86                 :            :  * tr_lo contains low 32 bits for 8 transition.
      87                 :            :  * tr_hi contains high 32 bits for 8 transition.
      88                 :            :  */
      89                 :            : static inline void
      90                 :    1125534 : acl_process_matches_avx2x8(const struct rte_acl_ctx *ctx,
      91                 :            :         struct parms *parms, struct acl_flow_data *flows, uint32_t slot,
      92                 :            :         ymm_t matches, ymm_t *tr_lo, ymm_t *tr_hi)
      93                 :            : {
      94                 :            :         ymm_t t0, t1;
      95                 :            :         ymm_t lo, hi;
      96                 :            :         xmm_t l0, l1;
      97                 :            :         uint32_t i;
      98                 :            :         uint64_t tr[MAX_SEARCHES_SSE8];
      99                 :            : 
     100                 :    1125534 :         l1 = _mm256_extracti128_si256(*tr_lo, 1);
     101                 :            :         l0 = _mm256_castsi256_si128(*tr_lo);
     102                 :            : 
     103         [ +  + ]:    5627670 :         for (i = 0; i != RTE_DIM(tr) / 2; i++) {
     104                 :            : 
     105                 :            :                 /*
     106                 :            :                  * Extract low 32bits of each transition.
     107                 :            :                  * That's enough to process the match.
     108                 :            :                  */
     109                 :    4502136 :                 tr[i] = (uint32_t)_mm_cvtsi128_si32(l0);
     110                 :    4502136 :                 tr[i + 4] = (uint32_t)_mm_cvtsi128_si32(l1);
     111                 :            : 
     112                 :            :                 l0 = _mm_srli_si128(l0, sizeof(uint32_t));
     113                 :            :                 l1 = _mm_srli_si128(l1, sizeof(uint32_t));
     114                 :            : 
     115                 :    4502136 :                 tr[i] = acl_match_check(tr[i], slot + i,
     116                 :            :                         ctx, parms, flows, resolve_priority_sse);
     117                 :    4502136 :                 tr[i + 4] = acl_match_check(tr[i + 4], slot + i + 4,
     118                 :            :                         ctx, parms, flows, resolve_priority_sse);
     119                 :            :         }
     120                 :            : 
     121                 :            :         /* Collect new transitions into 2 YMM registers. */
     122                 :    1125534 :         t0 = _mm256_set_epi64x(tr[5], tr[4], tr[1], tr[0]);
     123                 :    1125534 :         t1 = _mm256_set_epi64x(tr[7], tr[6], tr[3], tr[2]);
     124                 :            : 
     125                 :            :         /* For each transition: put low 32 into tr_lo and high 32 into tr_hi */
     126                 :    1125534 :         ACL_TR_HILO(mm256, __m256, t0, t1, lo, hi);
     127                 :            : 
     128                 :            :         /* Keep transitions with NOMATCH intact. */
     129                 :    1125534 :         *tr_lo = _mm256_blendv_epi8(*tr_lo, lo, matches);
     130                 :    1125534 :         *tr_hi = _mm256_blendv_epi8(*tr_hi, hi, matches);
     131                 :    1125534 : }
     132                 :            : 
     133                 :            : static inline void
     134                 :    4026904 : acl_match_check_avx2x8(const struct rte_acl_ctx *ctx, struct parms *parms,
     135                 :            :         struct acl_flow_data *flows, uint32_t slot,
     136                 :            :         ymm_t *tr_lo, ymm_t *tr_hi, ymm_t match_mask)
     137                 :            : {
     138                 :            :         uint32_t msk;
     139                 :            :         ymm_t matches, temp;
     140                 :            : 
     141                 :            :         /* test for match node */
     142                 :    4026904 :         temp = _mm256_and_si256(match_mask, *tr_lo);
     143                 :            :         matches = _mm256_cmpeq_epi32(temp, match_mask);
     144                 :    4026904 :         msk = _mm256_movemask_epi8(matches);
     145                 :            : 
     146         [ +  + ]:    5152438 :         while (msk != 0) {
     147                 :            : 
     148                 :    1125534 :                 acl_process_matches_avx2x8(ctx, parms, flows, slot,
     149                 :            :                         matches, tr_lo, tr_hi);
     150                 :    1125534 :                 temp = _mm256_and_si256(match_mask, *tr_lo);
     151                 :            :                 matches = _mm256_cmpeq_epi32(temp, match_mask);
     152                 :    1125534 :                 msk = _mm256_movemask_epi8(matches);
     153                 :            :         }
     154                 :    4026904 : }
     155                 :            : 
     156                 :            : /*
     157                 :            :  * Execute trie traversal for up to 16 flows in parallel.
     158                 :            :  */
     159                 :            : static inline int
     160                 :     203190 : search_avx2x16(const struct rte_acl_ctx *ctx, const uint8_t **data,
     161                 :            :         uint32_t *results, uint32_t total_packets, uint32_t categories)
     162                 :            : {
     163                 :            :         uint32_t n;
     164                 :            :         struct acl_flow_data flows;
     165                 :            :         uint64_t index_array[MAX_SEARCHES_AVX16];
     166                 :            :         struct completion cmplt[MAX_SEARCHES_AVX16];
     167                 :            :         struct parms parms[MAX_SEARCHES_AVX16];
     168                 :            :         ymm_t input[2], tr_lo[2], tr_hi[2];
     169                 :            :         ymm_t t0, t1;
     170                 :            : 
     171                 :            :         acl_set_flow(&flows, cmplt, RTE_DIM(cmplt), data, results,
     172                 :     203190 :                 total_packets, categories, ctx->trans_table);
     173                 :            : 
     174         [ +  + ]:    3454230 :         for (n = 0; n < RTE_DIM(cmplt); n++) {
     175                 :    3251040 :                 cmplt[n].count = 0;
     176                 :    3251040 :                 index_array[n] = acl_start_next_trie(&flows, parms, n, ctx);
     177                 :            :         }
     178                 :            : 
     179                 :     203190 :         t0 = _mm256_set_epi64x(index_array[5], index_array[4],
     180                 :     203190 :                 index_array[1], index_array[0]);
     181                 :     203190 :         t1 = _mm256_set_epi64x(index_array[7], index_array[6],
     182                 :     203190 :                 index_array[3], index_array[2]);
     183                 :            : 
     184                 :     203190 :         ACL_TR_HILO(mm256, __m256, t0, t1, tr_lo[0], tr_hi[0]);
     185                 :            : 
     186                 :     203190 :         t0 = _mm256_set_epi64x(index_array[13], index_array[12],
     187                 :     203190 :                 index_array[9], index_array[8]);
     188                 :     203190 :         t1 = _mm256_set_epi64x(index_array[15], index_array[14],
     189                 :     203190 :                 index_array[11], index_array[10]);
     190                 :            : 
     191                 :     203190 :         ACL_TR_HILO(mm256, __m256, t0, t1, tr_lo[1], tr_hi[1]);
     192                 :            : 
     193                 :            :          /* Check for any matches. */
     194                 :     203190 :         acl_match_check_avx2x8(ctx, parms, &flows, 0, &tr_lo[0], &tr_hi[0],
     195                 :            :                 ymm_match_mask.y);
     196                 :     203190 :         acl_match_check_avx2x8(ctx, parms, &flows, 8, &tr_lo[1], &tr_hi[1],
     197                 :            :                 ymm_match_mask.y);
     198                 :            : 
     199         [ +  + ]:    2013452 :         while (flows.started > 0) {
     200                 :            : 
     201                 :            :                 uint32_t in[MAX_SEARCHES_SSE8];
     202                 :            : 
     203                 :            :                 /* Gather 4 bytes of input data for first 8 flows. */
     204                 :    1810262 :                 in[0] = GET_NEXT_4BYTES(parms, 0);
     205                 :    1810262 :                 in[4] = GET_NEXT_4BYTES(parms, 4);
     206                 :    1810262 :                 in[1] = GET_NEXT_4BYTES(parms, 1);
     207                 :    1810262 :                 in[5] = GET_NEXT_4BYTES(parms, 5);
     208                 :    1810262 :                 in[2] = GET_NEXT_4BYTES(parms, 2);
     209                 :    1810262 :                 in[6] = GET_NEXT_4BYTES(parms, 6);
     210                 :    1810262 :                 in[3] = GET_NEXT_4BYTES(parms, 3);
     211                 :    1810262 :                 in[7] = GET_NEXT_4BYTES(parms, 7);
     212                 :            :                 input[0] = _mm256_set_epi32(in[7], in[6], in[5], in[4],
     213                 :            :                         in[3], in[2], in[1], in[0]);
     214                 :            : 
     215                 :            :                 /* Gather 4 bytes of input data for last 8 flows. */
     216                 :    1810262 :                 in[0] = GET_NEXT_4BYTES(parms, 8);
     217                 :    1810262 :                 in[4] = GET_NEXT_4BYTES(parms, 12);
     218                 :    1810262 :                 in[1] = GET_NEXT_4BYTES(parms, 9);
     219                 :    1810262 :                 in[5] = GET_NEXT_4BYTES(parms, 13);
     220                 :    1810262 :                 in[2] = GET_NEXT_4BYTES(parms, 10);
     221                 :    1810262 :                 in[6] = GET_NEXT_4BYTES(parms, 14);
     222                 :    1810262 :                 in[3] = GET_NEXT_4BYTES(parms, 11);
     223                 :    1810262 :                 in[7] = GET_NEXT_4BYTES(parms, 15);
     224                 :            :                 input[1] = _mm256_set_epi32(in[7], in[6], in[5], in[4],
     225                 :            :                         in[3], in[2], in[1], in[0]);
     226                 :            : 
     227                 :    1810262 :                 input[0] = transition8(input[0], flows.trans,
     228                 :            :                         &tr_lo[0], &tr_hi[0]);
     229                 :            :                 input[1] = transition8(input[1], flows.trans,
     230                 :            :                         &tr_lo[1], &tr_hi[1]);
     231                 :            : 
     232                 :            :                 input[0] = transition8(input[0], flows.trans,
     233                 :            :                         &tr_lo[0], &tr_hi[0]);
     234                 :            :                 input[1] = transition8(input[1], flows.trans,
     235                 :            :                         &tr_lo[1], &tr_hi[1]);
     236                 :            : 
     237                 :            :                 input[0] = transition8(input[0], flows.trans,
     238                 :            :                         &tr_lo[0], &tr_hi[0]);
     239                 :            :                 input[1] = transition8(input[1], flows.trans,
     240                 :            :                         &tr_lo[1], &tr_hi[1]);
     241                 :            : 
     242                 :            :                 input[0] = transition8(input[0], flows.trans,
     243                 :            :                         &tr_lo[0], &tr_hi[0]);
     244                 :            :                 input[1] = transition8(input[1], flows.trans,
     245                 :            :                         &tr_lo[1], &tr_hi[1]);
     246                 :            : 
     247                 :            :                  /* Check for any matches. */
     248                 :    1810262 :                 acl_match_check_avx2x8(ctx, parms, &flows, 0,
     249                 :            :                         &tr_lo[0], &tr_hi[0], ymm_match_mask.y);
     250                 :    1810262 :                 acl_match_check_avx2x8(ctx, parms, &flows, 8,
     251                 :            :                         &tr_lo[1], &tr_hi[1], ymm_match_mask.y);
     252                 :            :         }
     253                 :            : 
     254                 :     203190 :         return 0;
     255                 :            : }

Generated by: LCOV version 1.14