hash: add local variable
[vpp.git] / src / vppinfra / vector / array_mask.h
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright(c) 2021 Cisco Systems, Inc.
3  */
4
5 #ifndef included_vector_array_mask_h
6 #define included_vector_array_mask_h
7 #include <vppinfra/clib.h>
8
9 /** \brief Mask array of 32-bit elemments
10
11     @param src source array of u32 elements
12     @param mask use to mask the values of source array
13     @param n_elts number of elements in the source array
14     @return masked values are return in source array
15 */
16
17 static_always_inline void
18 clib_array_mask_u32 (u32 *src, u32 mask, u32 n_elts)
19 {
20 #if defined(CLIB_HAVE_VEC512)
21   u32x16 mask16 = u32x16_splat (mask);
22   if (n_elts <= 16)
23     {
24       u32 m = pow2_mask (n_elts);
25       u32x16 r = u32x16_mask_load_zero (src, m);
26       u32x16_mask_store (r & mask16, src, m);
27       return;
28     }
29   for (int i = 0; i < n_elts; i += 16)
30     *((u32x16u *) (src + i)) &= mask16;
31   *((u32x16u *) (src + n_elts - 16)) &= mask16;
32 #elif defined(CLIB_HAVE_VEC256)
33   u32x8 mask8 = u32x8_splat (mask);
34 #if defined(CLIB_HAVE_VEC256_MASK_LOAD_STORE)
35   if (n_elts <= 8)
36     {
37       u32 m = pow2_mask (n_elts);
38       u32x8 r = u32x8_mask_load_zero (src, m);
39       u32x8_mask_store (r & mask8, src, m);
40       return;
41     }
42 #else
43   if (PREDICT_FALSE (n_elts < 4))
44     {
45       if (n_elts & 2)
46         {
47           src[0] &= mask;
48           src[1] &= mask;
49           src += 2;
50         }
51       if (n_elts & 1)
52         src[0] &= mask;
53       return;
54     }
55   if (n_elts <= 8)
56     {
57       u32x4 mask4 = u32x4_splat (mask);
58       *(u32x4u *) src &= mask4;
59       *(u32x4u *) (src + n_elts - 4) &= mask4;
60     }
61 #endif
62
63   for (int i = 0; i < n_elts; i += 8)
64     *((u32x8u *) (src + i)) &= mask8;
65   *((u32x8u *) (src + n_elts - 8)) &= mask8;
66 #elif defined(CLIB_HAVE_VEC128)
67   u32x4 mask4 = u32x4_splat (mask);
68
69   if (PREDICT_FALSE (n_elts < 4))
70     {
71       if (n_elts & 2)
72         {
73           src[0] &= mask;
74           src[1] &= mask;
75           src += 2;
76         }
77       if (n_elts & 1)
78         src[0] &= mask;
79       return;
80     }
81
82   for (int i = 0; i < n_elts; i += 4)
83     *((u32x4u *) (src + i)) &= mask4;
84   *((u32x4u *) (src + n_elts - 4)) &= mask4;
85   return;
86 #else
87   while (n_elts > 0)
88     {
89       src[0] &= mask;
90       src++;
91       n_elts--;
92     }
93 #endif
94 }
95
96 static_always_inline void
97 clib_array_mask_set_u32_x64 (u32 *a, u32 v, uword bmp, int n_elts)
98 {
99 #if defined(CLIB_HAVE_VEC512_MASK_LOAD_STORE)
100   u32x16 r = u32x16_splat (v);
101   for (; n_elts > 0; n_elts -= 16, a += 16, bmp >>= 16)
102     u32x16_mask_store (r, a, bmp);
103 #elif defined(CLIB_HAVE_VEC256_MASK_LOAD_STORE)
104   u32x8 r = u32x8_splat (v);
105   for (; n_elts > 0; n_elts -= 8, a += 8, bmp >>= 8)
106     u32x8_mask_store (r, a, bmp);
107 #else
108   while (bmp)
109     {
110       a[get_lowest_set_bit_index (bmp)] = v;
111       bmp = clear_lowest_set_bit (bmp);
112     }
113 #endif
114 }
115
116 static_always_inline void
117 clib_array_mask_set_u32 (u32 *a, u32 v, uword *bmp, u32 n_elts)
118 {
119   while (n_elts >= uword_bits)
120     {
121       clib_array_mask_set_u32_x64 (a, v, bmp++[0], uword_bits);
122       a += uword_bits;
123       n_elts -= uword_bits;
124     }
125
126   clib_array_mask_set_u32_x64 (a, v, bmp[0] & pow2_mask (n_elts), n_elts);
127 }
128
129 #endif