98770cff7c0631e351bfa5c0545529c6e85d1603
[vpp.git] / src / vppinfra / vector / count_equal.h
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright(c) 2021 Cisco Systems, Inc.
3  */
4
5 #ifndef included_vector_count_equal_h
6 #define included_vector_count_equal_h
7 #include <vppinfra/clib.h>
8
9 static_always_inline uword
10 clib_count_equal_u64 (u64 *data, uword max_count)
11 {
12   uword count;
13   u64 first;
14
15   if (max_count <= 1)
16     return max_count;
17   if (data[0] != data[1])
18     return 1;
19
20   count = 0;
21   first = data[0];
22
23 #if defined(CLIB_HAVE_VEC256)
24   u64x4 splat = u64x4_splat (first);
25   while (count + 3 < max_count)
26     {
27       u64 bmp;
28       bmp = u8x32_msb_mask ((u8x32) (u64x4_load_unaligned (data) == splat));
29       if (bmp != 0xffffffff)
30         {
31           count += count_trailing_zeros (~bmp) / 8;
32           return count;
33         }
34
35       data += 4;
36       count += 4;
37     }
38 #else
39   count += 2;
40   data += 2;
41   while (count + 3 < max_count && ((data[0] ^ first) | (data[1] ^ first) |
42                                    (data[2] ^ first) | (data[3] ^ first)) == 0)
43     {
44       data += 4;
45       count += 4;
46     }
47 #endif
48   while (count < max_count && (data[0] == first))
49     {
50       data += 1;
51       count += 1;
52     }
53   return count;
54 }
55
56 static_always_inline uword
57 clib_count_equal_u32 (u32 *data, uword max_count)
58 {
59   uword count;
60   u32 first;
61
62   if (max_count <= 1)
63     return max_count;
64   if (data[0] != data[1])
65     return 1;
66
67   count = 0;
68   first = data[0];
69
70 #if defined(CLIB_HAVE_VEC256)
71   u32x8 splat = u32x8_splat (first);
72   while (count + 7 < max_count)
73     {
74       u64 bmp;
75       bmp = u8x32_msb_mask ((u8x32) (u32x8_load_unaligned (data) == splat));
76       if (bmp != 0xffffffff)
77         {
78           count += count_trailing_zeros (~bmp) / 4;
79           return count;
80         }
81
82       data += 8;
83       count += 8;
84     }
85 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK)
86   u32x4 splat = u32x4_splat (first);
87   while (count + 3 < max_count)
88     {
89       u64 bmp;
90       bmp = u8x16_msb_mask ((u8x16) (u32x4_load_unaligned (data) == splat));
91       if (bmp != 0xffff)
92         {
93           count += count_trailing_zeros (~bmp) / 4;
94           return count;
95         }
96
97       data += 4;
98       count += 4;
99     }
100 #else
101   count += 2;
102   data += 2;
103   while (count + 3 < max_count && ((data[0] ^ first) | (data[1] ^ first) |
104                                    (data[2] ^ first) | (data[3] ^ first)) == 0)
105     {
106       data += 4;
107       count += 4;
108     }
109 #endif
110   while (count < max_count && (data[0] == first))
111     {
112       data += 1;
113       count += 1;
114     }
115   return count;
116 }
117
118 static_always_inline uword
119 clib_count_equal_u16 (u16 *data, uword max_count)
120 {
121   uword count;
122   u16 first;
123
124   if (max_count <= 1)
125     return max_count;
126   if (data[0] != data[1])
127     return 1;
128
129   count = 0;
130   first = data[0];
131
132 #if defined(CLIB_HAVE_VEC256)
133   u16x16 splat = u16x16_splat (first);
134   while (count + 15 < max_count)
135     {
136       u64 bmp;
137       bmp = u8x32_msb_mask ((u8x32) (u16x16_load_unaligned (data) == splat));
138       if (bmp != 0xffffffff)
139         {
140           count += count_trailing_zeros (~bmp) / 2;
141           return count;
142         }
143
144       data += 16;
145       count += 16;
146     }
147 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK)
148   u16x8 splat = u16x8_splat (first);
149   while (count + 7 < max_count)
150     {
151       u64 bmp;
152       bmp = u8x16_msb_mask ((u8x16) (u16x8_load_unaligned (data) == splat));
153       if (bmp != 0xffff)
154         {
155           count += count_trailing_zeros (~bmp) / 2;
156           return count;
157         }
158
159       data += 8;
160       count += 8;
161     }
162 #else
163   count += 2;
164   data += 2;
165   while (count + 3 < max_count && ((data[0] ^ first) | (data[1] ^ first) |
166                                    (data[2] ^ first) | (data[3] ^ first)) == 0)
167     {
168       data += 4;
169       count += 4;
170     }
171 #endif
172   while (count < max_count && (data[0] == first))
173     {
174       data += 1;
175       count += 1;
176     }
177   return count;
178 }
179
180 static_always_inline uword
181 clib_count_equal_u8 (u8 *data, uword max_count)
182 {
183   uword count;
184   u8 first;
185
186   if (max_count <= 1)
187     return max_count;
188   if (data[0] != data[1])
189     return 1;
190
191   count = 0;
192   first = data[0];
193
194 #if defined(CLIB_HAVE_VEC256)
195   u8x32 splat = u8x32_splat (first);
196   while (count + 31 < max_count)
197     {
198       u64 bmp;
199       bmp = u8x32_msb_mask ((u8x32) (u8x32_load_unaligned (data) == splat));
200       if (bmp != 0xffffffff)
201         return max_count;
202
203       data += 32;
204       count += 32;
205     }
206 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK)
207   u8x16 splat = u8x16_splat (first);
208   while (count + 15 < max_count)
209     {
210       u64 bmp;
211       bmp = u8x16_msb_mask ((u8x16) (u8x16_load_unaligned (data) == splat));
212       if (bmp != 0xffff)
213         {
214           count += count_trailing_zeros (~bmp);
215           return count;
216         }
217
218       data += 16;
219       count += 16;
220     }
221 #else
222   count += 2;
223   data += 2;
224   while (count + 3 < max_count && ((data[0] ^ first) | (data[1] ^ first) |
225                                    (data[2] ^ first) | (data[3] ^ first)) == 0)
226     {
227       data += 4;
228       count += 4;
229     }
230 #endif
231   while (count < max_count && (data[0] == first))
232     {
233       data += 1;
234       count += 1;
235     }
236   return count;
237 }
238 #endif