Line data Source code
1 : /*
2 : * Copyright(c) 2019 Intel Corporation
3 : * SPDX - License - Identifier: BSD - 2 - Clause - Patent
4 : */
5 :
6 : #include <assert.h>
7 :
8 : #include "EbComputeSAD_AVX2.h"
9 : #include "EbDefinitions.h"
10 : #include "immintrin.h"
11 : #include "EbMemory_AVX2.h"
12 : #include "EbComputeSAD.h"
13 :
14 : #define UPDATE_BEST(s, k, offset) \
15 : temSum1 = _mm_extract_epi32(s, k); \
16 : if (temSum1 < lowSum) { \
17 : lowSum = temSum1; \
18 : xBest = j + offset + k; \
19 : yBest = i; \
20 : }
21 :
22 0 : void ext_sad_calculation_8x8_16x16_avx2_intrin(
23 : uint8_t *src,
24 : uint32_t src_stride,
25 : uint8_t *ref,
26 : uint32_t ref_stride,
27 : uint32_t *p_best_sad8x8,
28 : uint32_t *p_best_sad16x16,
29 : uint32_t *p_best_mv8x8,
30 : uint32_t *p_best_mv16x16,
31 : uint32_t mv,
32 : uint32_t *p_sad16x16,
33 : uint32_t *p_sad8x8,
34 : EbBool sub_sad) {
35 : __m128i xmm_sad16x16, xmm_sad16x16_total, sad8x8_0_3;
36 : __m128i sad8x8_less_than_bitmask, best_mv8x8;
37 : __m128i best_sad8x8, xmm_best_sad8x8, xmm_best_mv8x8;
38 : __m256i sad8x8_0_3_256, src_256, ref_256;
39 0 : __m128i xmm_mv = _mm_set1_epi32(mv);
40 :
41 0 : src_256 = _mm256_setr_m128i(
42 : _mm_loadu_si128((__m128i const*)(src + 0 * src_stride)),
43 : _mm_loadu_si128((__m128i const*)(src + 8 * src_stride)));
44 0 : ref_256 = _mm256_setr_m128i(
45 : _mm_loadu_si128((__m128i const*)(ref + 0 * ref_stride)),
46 : _mm_loadu_si128((__m128i const*)(ref + 8 * ref_stride)));
47 0 : sad8x8_0_3_256 = _mm256_sad_epu8(src_256, ref_256);
48 :
49 0 : src_256 = _mm256_setr_m128i(
50 : _mm_loadu_si128((__m128i const*)(src + 2 * src_stride)),
51 : _mm_loadu_si128((__m128i const*)(src + 10 * src_stride)));
52 0 : ref_256 = _mm256_setr_m128i(
53 : _mm_loadu_si128((__m128i const*)(ref + 2 * ref_stride)),
54 : _mm_loadu_si128((__m128i const*)(ref + 10 * ref_stride)));
55 0 : sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
56 : sad8x8_0_3_256);
57 :
58 0 : src_256 = _mm256_setr_m128i(
59 : _mm_loadu_si128((__m128i const*)(src + 4 * src_stride)),
60 : _mm_loadu_si128((__m128i const*)(src + 12 * src_stride)));
61 0 : ref_256 = _mm256_setr_m128i(
62 : _mm_loadu_si128((__m128i const*)(ref + 4 * ref_stride)),
63 : _mm_loadu_si128((__m128i const*)(ref + 12 * ref_stride)));
64 0 : sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
65 : sad8x8_0_3_256);
66 :
67 0 : src_256 = _mm256_setr_m128i(
68 : _mm_loadu_si128((__m128i const*)(src + 6 * src_stride)),
69 : _mm_loadu_si128((__m128i const*)(src + 14 * src_stride)));
70 0 : ref_256 = _mm256_setr_m128i(
71 : _mm_loadu_si128((__m128i const*)(ref + 6 * ref_stride)),
72 : _mm_loadu_si128((__m128i const*)(ref + 14 * ref_stride)));
73 0 : sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
74 : sad8x8_0_3_256);
75 :
76 0 : if (sub_sad)
77 0 : sad8x8_0_3_256 = _mm256_slli_epi32(sad8x8_0_3_256, 1);
78 : else {
79 0 : src_256 = _mm256_setr_m128i(
80 : _mm_loadu_si128((__m128i const*)(src + 1 * src_stride)),
81 : _mm_loadu_si128((__m128i const*)(src + 9 * src_stride)));
82 0 : ref_256 = _mm256_setr_m128i(
83 : _mm_loadu_si128((__m128i const*)(ref + 1 * ref_stride)),
84 : _mm_loadu_si128((__m128i const*)(ref + 9 * ref_stride)));
85 0 : sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
86 : sad8x8_0_3_256);
87 :
88 0 : src_256 = _mm256_setr_m128i(
89 : _mm_loadu_si128((__m128i const*)(src + 3 * src_stride)),
90 : _mm_loadu_si128((__m128i const*)(src + 11 * src_stride)));
91 0 : ref_256 = _mm256_setr_m128i(
92 : _mm_loadu_si128((__m128i const*)(ref + 3 * ref_stride)),
93 : _mm_loadu_si128((__m128i const*)(ref + 11 * ref_stride)));
94 0 : sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
95 : sad8x8_0_3_256);
96 :
97 0 : src_256 = _mm256_setr_m128i(
98 : _mm_loadu_si128((__m128i const*)(src + 5 * src_stride)),
99 : _mm_loadu_si128((__m128i const*)(src + 13 * src_stride)));
100 0 : ref_256 = _mm256_setr_m128i(
101 : _mm_loadu_si128((__m128i const*)(ref + 5 * ref_stride)),
102 : _mm_loadu_si128((__m128i const*)(ref + 13 * ref_stride)));
103 0 : sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
104 : sad8x8_0_3_256);
105 :
106 0 : src_256 = _mm256_setr_m128i(
107 : _mm_loadu_si128((__m128i const*)(src + 7 * src_stride)),
108 : _mm_loadu_si128((__m128i const*)(src + 15 * src_stride)));
109 0 : ref_256 = _mm256_setr_m128i(
110 : _mm_loadu_si128((__m128i const*)(ref + 7 * ref_stride)),
111 : _mm_loadu_si128((__m128i const*)(ref + 15 * ref_stride)));
112 0 : sad8x8_0_3_256 = _mm256_add_epi32(_mm256_sad_epu8(src_256, ref_256),
113 : sad8x8_0_3_256);
114 : }
115 :
116 0 : sad8x8_0_3 = _mm_packs_epi32(_mm256_castsi256_si128(sad8x8_0_3_256),
117 0 : _mm256_extracti128_si256(sad8x8_0_3_256, 1));
118 : _mm_storeu_si128((__m128i*)p_sad8x8, sad8x8_0_3);
119 :
120 0 : xmm_best_sad8x8 = _mm_loadu_si128((__m128i const*)p_best_sad8x8);
121 0 : xmm_best_mv8x8 = _mm_loadu_si128((__m128i const*)p_best_mv8x8);
122 :
123 : // sad8x8_0 < p_best_sad8x8[0] for 0 to 3
124 0 : sad8x8_less_than_bitmask = _mm_cmplt_epi32(sad8x8_0_3, xmm_best_sad8x8);
125 0 : best_sad8x8 = _mm_blendv_epi8(xmm_best_sad8x8, sad8x8_0_3,
126 : sad8x8_less_than_bitmask);
127 0 : best_mv8x8 = _mm_blendv_epi8(xmm_best_mv8x8, xmm_mv,
128 : sad8x8_less_than_bitmask);
129 : _mm_storeu_si128((__m128i*)p_best_sad8x8, best_sad8x8);
130 : _mm_storeu_si128((__m128i*)p_best_mv8x8, best_mv8x8);
131 :
132 0 : xmm_sad16x16 = _mm_add_epi32(_mm256_castsi256_si128(sad8x8_0_3_256),
133 0 : _mm256_extracti128_si256(sad8x8_0_3_256, 1));
134 0 : xmm_sad16x16_total = _mm_add_epi32(
135 0 : _mm_srli_si128(xmm_sad16x16, 8), xmm_sad16x16);
136 0 : p_sad16x16[0] = _mm_cvtsi128_si32(xmm_sad16x16_total);
137 :
138 0 : if (p_sad16x16[0] < p_best_sad16x16[0]) {
139 0 : p_best_sad16x16[0] = p_sad16x16[0];
140 0 : p_best_mv16x16[0] = mv;
141 : }
142 0 : }
143 :
144 0 : void sad_loop_kernel_sparse_avx2_intrin(
145 : uint8_t *src, // input parameter, source samples Ptr
146 : uint32_t src_stride, // input parameter, source stride
147 : uint8_t *ref, // input parameter, reference samples Ptr
148 : uint32_t ref_stride, // input parameter, reference stride
149 : uint32_t block_height, // input parameter, block height (M)
150 : uint32_t block_width, // input parameter, block width (N)
151 : uint64_t *best_sad,
152 : int16_t *x_search_center,
153 : int16_t *y_search_center,
154 : uint32_t src_stride_raw, // input parameter, source stride (no line skipping)
155 : int16_t search_area_width,
156 : int16_t search_area_height)
157 : {
158 0 : int16_t xBest = *x_search_center, yBest = *y_search_center;
159 0 : uint32_t lowSum = 0xffffff;
160 0 : uint32_t temSum1 = 0;
161 : int16_t i, j;
162 : uint32_t k, l;
163 0 : uint32_t leftover = search_area_width & 7;
164 : const uint8_t *pRef, *pSrc;
165 0 : __m128i s0, s1, s2, s3, s4, s5, s6, s8 = _mm_set1_epi32(-1);
166 : __m256i ss0, ss1, ss2, ss3, ss4, ss5, ss6, ss7, ss8;
167 :
168 0 : if (leftover) {
169 0 : for (k = 0; k < leftover; k++)
170 0 : s8 = _mm_slli_si128(s8, 2);
171 : }
172 :
173 0 : switch (block_width) {
174 0 : case 4:
175 :
176 0 : if (!(block_height % 4)) {
177 0 : uint32_t srcStrideT = 3 * src_stride;
178 0 : uint32_t refStrideT = 3 * ref_stride;
179 0 : for (i = 0; i < search_area_height; i++) {
180 0 : uint32_t startW = (i & 1) << 3;
181 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
182 0 : pSrc = src;
183 0 : pRef = ref + j;
184 0 : ss3 = ss5 = _mm256_setzero_si256();
185 0 : for (k = 0; k < block_height; k += 4) {
186 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
187 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
188 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)pSrc), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)(pSrc + 2 * src_stride)), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + srcStrideT))), 0x1);
189 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
190 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
191 0 : pSrc += src_stride << 2;
192 0 : pRef += ref_stride << 2;
193 : }
194 0 : ss3 = _mm256_adds_epu16(ss3, ss5);
195 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
196 0 : s3 = _mm_minpos_epu16(s3);
197 0 : temSum1 = _mm_extract_epi16(s3, 0);
198 0 : if (temSum1 < lowSum) {
199 0 : lowSum = temSum1;
200 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
201 0 : yBest = i;
202 : }
203 : }
204 :
205 0 : if (leftover && j < search_area_width ) {
206 0 : pSrc = src;
207 0 : pRef = ref + j;
208 0 : ss3 = ss5 = _mm256_setzero_si256();
209 0 : for (k = 0; k < block_height; k += 4) {
210 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
211 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
212 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)pSrc), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)(pSrc + 2 * src_stride)), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + srcStrideT))), 0x1);
213 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
214 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
215 0 : pSrc += src_stride << 2;
216 0 : pRef += ref_stride << 2;
217 : }
218 0 : ss3 = _mm256_adds_epu16(ss3, ss5);
219 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
220 0 : s3 = _mm_or_si128(s3, s8);
221 0 : s3 = _mm_minpos_epu16(s3);
222 0 : temSum1 = _mm_extract_epi16(s3, 0);
223 0 : if (temSum1 < lowSum) {
224 0 : lowSum = temSum1;
225 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
226 0 : yBest = i;
227 : }
228 : }
229 0 : ref += src_stride_raw;
230 : }
231 : }
232 : else {
233 0 : for (i = 0; i < search_area_height; i++) {
234 0 : uint32_t startW = (i & 1) << 3;
235 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
236 0 : pSrc = src;
237 0 : pRef = ref + j;
238 0 : s3 = _mm_setzero_si128();
239 0 : for (k = 0; k < block_height; k += 2) {
240 0 : s0 = _mm_loadu_si128((__m128i*)pRef);
241 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
242 0 : s2 = _mm_cvtsi32_si128(*(uint32_t *)pSrc);
243 0 : s5 = _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride));
244 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
245 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
246 0 : pSrc += src_stride << 1;
247 0 : pRef += ref_stride << 1;
248 : }
249 0 : s3 = _mm_minpos_epu16(s3);
250 0 : temSum1 = _mm_extract_epi16(s3, 0);
251 0 : if (temSum1 < lowSum) {
252 0 : lowSum = temSum1;
253 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
254 0 : yBest = i;
255 : }
256 : }
257 :
258 0 : if (leftover && j < search_area_width ) {
259 0 : pSrc = src;
260 0 : pRef = ref + j;
261 0 : s3 = _mm_setzero_si128();
262 0 : for (k = 0; k < block_height; k += 2) {
263 0 : s0 = _mm_loadu_si128((__m128i*)pRef);
264 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
265 0 : s2 = _mm_cvtsi32_si128(*(uint32_t *)pSrc);
266 0 : s5 = _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride));
267 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
268 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
269 0 : pSrc += src_stride << 1;
270 0 : pRef += ref_stride << 1;
271 : }
272 0 : s3 = _mm_or_si128(s3, s8);
273 0 : s3 = _mm_minpos_epu16(s3);
274 0 : temSum1 = _mm_extract_epi16(s3, 0);
275 0 : if (temSum1 < lowSum) {
276 0 : lowSum = temSum1;
277 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
278 0 : yBest = i;
279 : }
280 : }
281 0 : ref += src_stride_raw;
282 : }
283 : }
284 :
285 0 : break;
286 :
287 0 : case 8:
288 0 : if (!(block_height % 4)) {
289 0 : uint32_t srcStrideT = 3 * src_stride;
290 0 : uint32_t refStrideT = 3 * ref_stride;
291 0 : for (i = 0; i < search_area_height; i++) {
292 0 : uint32_t startW = (i & 1) << 3;
293 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
294 0 : pSrc = src;
295 0 : pRef = ref + j;
296 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
297 0 : for (k = 0; k < block_height; k += 4) {
298 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
299 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
300 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)pSrc), _mm_loadl_epi64((__m128i*)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)(pSrc + 2 * src_stride)), _mm_loadl_epi64((__m128i*)(pSrc + srcStrideT))), 0x1);
301 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
302 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
303 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
304 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
305 0 : pSrc += src_stride << 2;
306 0 : pRef += ref_stride << 2;
307 : }
308 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
309 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
310 0 : s3 = _mm_minpos_epu16(s3);
311 0 : temSum1 = _mm_extract_epi16(s3, 0);
312 0 : if (temSum1 < lowSum) {
313 0 : lowSum = temSum1;
314 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
315 0 : yBest = i;
316 : }
317 : }
318 :
319 0 : if (leftover && j < search_area_width ) {
320 0 : pSrc = src;
321 0 : pRef = ref + j;
322 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
323 0 : for (k = 0; k < block_height; k += 4) {
324 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
325 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
326 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)pSrc), _mm_loadl_epi64((__m128i*)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)(pSrc + 2 * src_stride)), _mm_loadl_epi64((__m128i*)(pSrc + srcStrideT))), 0x1);
327 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
328 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
329 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
330 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
331 0 : pSrc += src_stride << 2;
332 0 : pRef += ref_stride << 2;
333 : }
334 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
335 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
336 0 : s3 = _mm_or_si128(s3, s8);
337 0 : s3 = _mm_minpos_epu16(s3);
338 0 : temSum1 = _mm_extract_epi16(s3, 0);
339 0 : if (temSum1 < lowSum) {
340 0 : lowSum = temSum1;
341 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
342 0 : yBest = i;
343 : }
344 : }
345 0 : ref += src_stride_raw;
346 : }
347 : }
348 : else {
349 0 : for (i = 0; i < search_area_height; i++) {
350 0 : uint32_t startW = (i & 1) << 3;
351 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
352 0 : pSrc = src;
353 0 : pRef = ref + j;
354 0 : s3 = s4 = _mm_setzero_si128();
355 0 : for (k = 0; k < block_height; k += 2) {
356 0 : s0 = _mm_loadu_si128((__m128i*)pRef);
357 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
358 0 : s2 = _mm_loadl_epi64((__m128i*)pSrc);
359 0 : s5 = _mm_loadl_epi64((__m128i*)(pSrc + src_stride));
360 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
361 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
362 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
363 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s1, s5, 5));
364 0 : pSrc += src_stride << 1;
365 0 : pRef += ref_stride << 1;
366 : }
367 0 : s3 = _mm_adds_epu16(s3, s4);
368 0 : s3 = _mm_minpos_epu16(s3);
369 0 : temSum1 = _mm_extract_epi16(s3, 0);
370 0 : if (temSum1 < lowSum) {
371 0 : lowSum = temSum1;
372 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
373 0 : yBest = i;
374 : }
375 : }
376 :
377 0 : if (leftover && j < search_area_width ) {
378 0 : pSrc = src;
379 0 : pRef = ref + j;
380 0 : s3 = s4 = _mm_setzero_si128();
381 0 : for (k = 0; k < block_height; k += 2) {
382 0 : s0 = _mm_loadu_si128((__m128i*)pRef);
383 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
384 0 : s2 = _mm_loadl_epi64((__m128i*)pSrc);
385 0 : s5 = _mm_loadl_epi64((__m128i*)(pSrc + src_stride));
386 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
387 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
388 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
389 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s1, s5, 5));
390 0 : pSrc += src_stride << 1;
391 0 : pRef += ref_stride << 1;
392 : }
393 0 : s3 = _mm_adds_epu16(s3, s4);
394 0 : s3 = _mm_or_si128(s3, s8);
395 0 : s3 = _mm_minpos_epu16(s3);
396 0 : temSum1 = _mm_extract_epi16(s3, 0);
397 0 : if (temSum1 < lowSum) {
398 0 : lowSum = temSum1;
399 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
400 0 : yBest = i;
401 : }
402 : }
403 0 : ref += src_stride_raw;
404 : }
405 : }
406 0 : break;
407 :
408 0 : case 16:
409 0 : if (block_height <= 16) {
410 0 : for (i = 0; i < search_area_height; i++) {
411 0 : uint32_t startW = (i & 1) << 3;
412 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
413 0 : pSrc = src;
414 0 : pRef = ref + j;
415 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
416 0 : for (k = 0; k < block_height; k += 2) {
417 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
418 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
419 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
420 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
421 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
422 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
423 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
424 0 : pSrc += 2 * src_stride;
425 0 : pRef += 2 * ref_stride;
426 : }
427 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
428 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
429 0 : s3 = _mm_minpos_epu16(s3);
430 0 : temSum1 = _mm_extract_epi16(s3, 0);
431 0 : if (temSum1 < lowSum) {
432 0 : lowSum = temSum1;
433 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
434 0 : yBest = i;
435 : }
436 : }
437 :
438 0 : if (leftover && j < search_area_width ) {
439 0 : pSrc = src;
440 0 : pRef = ref + j;
441 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
442 0 : for (k = 0; k < block_height; k += 2) {
443 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
444 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
445 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
446 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
447 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
448 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
449 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
450 0 : pSrc += 2 * src_stride;
451 0 : pRef += 2 * ref_stride;
452 : }
453 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
454 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
455 0 : s3 = _mm_or_si128(s3, s8);
456 0 : s3 = _mm_minpos_epu16(s3);
457 0 : temSum1 = _mm_extract_epi16(s3, 0);
458 0 : if (temSum1 < lowSum) {
459 0 : lowSum = temSum1;
460 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
461 0 : yBest = i;
462 : }
463 : }
464 0 : ref += src_stride_raw;
465 : }
466 : }
467 0 : else if (block_height <= 32) {
468 0 : for (i = 0; i < search_area_height; i++) {
469 0 : uint32_t startW = (i & 1) << 3;
470 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
471 0 : pSrc = src;
472 0 : pRef = ref + j;
473 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
474 0 : for (k = 0; k < block_height; k += 2) {
475 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
476 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
477 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
478 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
479 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
480 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
481 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
482 0 : pSrc += 2 * src_stride;
483 0 : pRef += 2 * ref_stride;
484 : }
485 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
486 0 : s3 = _mm256_castsi256_si128(ss3);
487 0 : s5 = _mm256_extracti128_si256(ss3, 1);
488 0 : s4 = _mm_minpos_epu16(s3);
489 0 : s6 = _mm_minpos_epu16(s5);
490 0 : s4 = _mm_unpacklo_epi16(s4, s4);
491 0 : s4 = _mm_unpacklo_epi32(s4, s4);
492 0 : s4 = _mm_unpacklo_epi64(s4, s4);
493 0 : s6 = _mm_unpacklo_epi16(s6, s6);
494 0 : s6 = _mm_unpacklo_epi32(s6, s6);
495 0 : s6 = _mm_unpacklo_epi64(s6, s6);
496 0 : s3 = _mm_sub_epi16(s3, s4);
497 0 : s5 = _mm_adds_epu16(s5, s3);
498 0 : s5 = _mm_sub_epi16(s5, s6);
499 0 : s5 = _mm_minpos_epu16(s5);
500 0 : temSum1 = _mm_extract_epi16(s5, 0);
501 0 : temSum1 += _mm_extract_epi16(s4, 0);
502 0 : temSum1 += _mm_extract_epi16(s6, 0);
503 0 : if (temSum1 < lowSum) {
504 0 : lowSum = temSum1;
505 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
506 0 : yBest = i;
507 : }
508 : }
509 :
510 0 : if (leftover && j < search_area_width ) {
511 0 : pSrc = src;
512 0 : pRef = ref + j;
513 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
514 0 : for (k = 0; k < block_height; k += 2) {
515 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
516 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
517 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
518 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
519 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
520 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
521 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
522 0 : pSrc += 2 * src_stride;
523 0 : pRef += 2 * ref_stride;
524 : }
525 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
526 0 : s3 = _mm256_castsi256_si128(ss3);
527 0 : s5 = _mm256_extracti128_si256(ss3, 1);
528 0 : s3 = _mm_or_si128(s3, s8);
529 0 : s5 = _mm_or_si128(s5, s8);
530 0 : s4 = _mm_minpos_epu16(s3);
531 0 : s6 = _mm_minpos_epu16(s5);
532 0 : s4 = _mm_unpacklo_epi16(s4, s4);
533 0 : s4 = _mm_unpacklo_epi32(s4, s4);
534 0 : s4 = _mm_unpacklo_epi64(s4, s4);
535 0 : s6 = _mm_unpacklo_epi16(s6, s6);
536 0 : s6 = _mm_unpacklo_epi32(s6, s6);
537 0 : s6 = _mm_unpacklo_epi64(s6, s6);
538 0 : s3 = _mm_sub_epi16(s3, s4);
539 0 : s5 = _mm_adds_epu16(s5, s3);
540 0 : s5 = _mm_sub_epi16(s5, s6);
541 0 : s5 = _mm_minpos_epu16(s5);
542 0 : temSum1 = _mm_extract_epi16(s5, 0);
543 0 : temSum1 += _mm_extract_epi16(s4, 0);
544 0 : temSum1 += _mm_extract_epi16(s6, 0);
545 0 : if (temSum1 < lowSum) {
546 0 : lowSum = temSum1;
547 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
548 0 : yBest = i;
549 : }
550 : }
551 0 : ref += src_stride_raw;
552 : }
553 : }
554 : else {
555 0 : for (i = 0; i < search_area_height; i++) {
556 0 : uint32_t startW = (i & 1) << 3;
557 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
558 0 : pSrc = src;
559 0 : pRef = ref + j;
560 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
561 0 : for (k = 0; k < block_height; k += 2) {
562 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
563 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
564 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
565 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
566 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
567 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
568 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
569 0 : pSrc += 2 * src_stride;
570 0 : pRef += 2 * ref_stride;
571 : }
572 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
573 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
574 0 : ss0 = _mm256_adds_epu16(ss3, ss5);
575 0 : s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
576 0 : s0 = _mm_minpos_epu16(s0);
577 0 : temSum1 = _mm_extract_epi16(s0, 0);
578 0 : if (temSum1 < lowSum) {
579 0 : if (temSum1 != 0xFFFF) { // no overflow
580 0 : lowSum = temSum1;
581 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
582 0 : yBest = i;
583 : }
584 : else {
585 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
586 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
587 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
588 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
589 0 : ss4 = _mm256_add_epi32(ss4, ss6);
590 0 : ss3 = _mm256_add_epi32(ss3, ss5);
591 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
592 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
593 0 : UPDATE_BEST(s0, 0, 0);
594 0 : UPDATE_BEST(s0, 1, 0);
595 0 : UPDATE_BEST(s0, 2, 0);
596 0 : UPDATE_BEST(s0, 3, 0);
597 0 : UPDATE_BEST(s3, 0, 4);
598 0 : UPDATE_BEST(s3, 1, 4);
599 0 : UPDATE_BEST(s3, 2, 4);
600 0 : UPDATE_BEST(s3, 3, 4);
601 : }
602 : }
603 : }
604 :
605 0 : if (leftover && j < search_area_width ) {
606 0 : pSrc = src;
607 0 : pRef = ref + j;
608 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
609 0 : for (k = 0; k < block_height; k += 2) {
610 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
611 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
612 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
613 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
614 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
615 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
616 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
617 0 : pSrc += 2 * src_stride;
618 0 : pRef += 2 * ref_stride;
619 : }
620 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
621 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
622 0 : ss0 = _mm256_adds_epu16(ss3, ss5);
623 0 : s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
624 0 : s0 = _mm_or_si128(s0, s8);
625 0 : s0 = _mm_minpos_epu16(s0);
626 0 : temSum1 = _mm_extract_epi16(s0, 0);
627 0 : if (temSum1 < lowSum) {
628 0 : if (temSum1 != 0xFFFF) { // no overflow
629 0 : lowSum = temSum1;
630 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
631 0 : yBest = i;
632 : }
633 : else {
634 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
635 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
636 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
637 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
638 0 : ss4 = _mm256_add_epi32(ss4, ss6);
639 0 : ss3 = _mm256_add_epi32(ss3, ss5);
640 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
641 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
642 0 : k = leftover;
643 0 : while (k > 0) {
644 0 : for (l = 0; l < 4 && k; l++, k--) {
645 0 : temSum1 = _mm_extract_epi32(s0, 0);
646 0 : s0 = _mm_srli_si128(s0, 4);
647 0 : if (temSum1 < lowSum) {
648 0 : lowSum = temSum1;
649 0 : xBest = (int16_t)(j + leftover - k);
650 0 : yBest = i;
651 : }
652 : }
653 0 : s0 = s3;
654 : }
655 : }
656 : }
657 : }
658 0 : ref += src_stride_raw;
659 : }
660 : }
661 0 : break;
662 :
663 0 : case 24:
664 0 : if (block_height <= 16) {
665 0 : for (i = 0; i < search_area_height; i++) {
666 0 : uint32_t startW = (i & 1) << 3;
667 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
668 0 : pSrc = src;
669 0 : pRef = ref + j;
670 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
671 0 : for (k = 0; k < block_height; k++) {
672 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
673 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
674 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
675 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
676 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
677 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
678 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
679 0 : pSrc += src_stride;
680 0 : pRef += ref_stride;
681 : }
682 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
683 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
684 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
685 0 : s5 = _mm256_castsi256_si128(ss5);
686 0 : s4 = _mm_minpos_epu16(s3);
687 0 : s6 = _mm_minpos_epu16(s5);
688 0 : s4 = _mm_unpacklo_epi16(s4, s4);
689 0 : s4 = _mm_unpacklo_epi32(s4, s4);
690 0 : s4 = _mm_unpacklo_epi64(s4, s4);
691 0 : s6 = _mm_unpacklo_epi16(s6, s6);
692 0 : s6 = _mm_unpacklo_epi32(s6, s6);
693 0 : s6 = _mm_unpacklo_epi64(s6, s6);
694 0 : s3 = _mm_sub_epi16(s3, s4);
695 0 : s5 = _mm_adds_epu16(s5, s3);
696 0 : s5 = _mm_sub_epi16(s5, s6);
697 0 : s5 = _mm_minpos_epu16(s5);
698 0 : temSum1 = _mm_extract_epi16(s5, 0);
699 0 : temSum1 += _mm_extract_epi16(s4, 0);
700 0 : temSum1 += _mm_extract_epi16(s6, 0);
701 0 : if (temSum1 < lowSum) {
702 0 : lowSum = temSum1;
703 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
704 0 : yBest = i;
705 : }
706 : }
707 :
708 0 : if (leftover && j < search_area_width ) {
709 0 : pSrc = src;
710 0 : pRef = ref + j;
711 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
712 0 : for (k = 0; k < block_height; k++) {
713 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
714 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
715 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
716 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
717 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
718 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
719 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
720 0 : pSrc += src_stride;
721 0 : pRef += ref_stride;
722 : }
723 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
724 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
725 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
726 0 : s5 = _mm256_castsi256_si128(ss5);
727 0 : s3 = _mm_or_si128(s3, s8);
728 0 : s5 = _mm_or_si128(s5, s8);
729 0 : s4 = _mm_minpos_epu16(s3);
730 0 : s6 = _mm_minpos_epu16(s5);
731 0 : s4 = _mm_unpacklo_epi16(s4, s4);
732 0 : s4 = _mm_unpacklo_epi32(s4, s4);
733 0 : s4 = _mm_unpacklo_epi64(s4, s4);
734 0 : s6 = _mm_unpacklo_epi16(s6, s6);
735 0 : s6 = _mm_unpacklo_epi32(s6, s6);
736 0 : s6 = _mm_unpacklo_epi64(s6, s6);
737 0 : s3 = _mm_sub_epi16(s3, s4);
738 0 : s5 = _mm_adds_epu16(s5, s3);
739 0 : s5 = _mm_sub_epi16(s5, s6);
740 0 : s5 = _mm_minpos_epu16(s5);
741 0 : temSum1 = _mm_extract_epi16(s5, 0);
742 0 : temSum1 += _mm_extract_epi16(s4, 0);
743 0 : temSum1 += _mm_extract_epi16(s6, 0);
744 0 : if (temSum1 < lowSum) {
745 0 : lowSum = temSum1;
746 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
747 0 : yBest = i;
748 : }
749 : }
750 0 : ref += src_stride_raw;
751 : }
752 : }
753 : else {
754 0 : for (i = 0; i < search_area_height; i++) {
755 0 : uint32_t startW = (i & 1) << 3;
756 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
757 0 : pSrc = src;
758 0 : pRef = ref + j;
759 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
760 0 : for (k = 0; k < block_height; k++) {
761 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
762 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
763 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
764 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
765 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
766 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
767 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
768 0 : pSrc += src_stride;
769 0 : pRef += ref_stride;
770 : }
771 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
772 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
773 0 : s3 = _mm256_castsi256_si128(ss3);
774 0 : s4 = _mm256_extracti128_si256(ss3, 1);
775 0 : s5 = _mm256_castsi256_si128(ss5);
776 0 : s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), s5);
777 0 : s0 = _mm_minpos_epu16(s0);
778 0 : temSum1 = _mm_extract_epi16(s0, 0);
779 0 : if (temSum1 < lowSum) {
780 0 : if (temSum1 != 0xFFFF) { // no overflow
781 0 : lowSum = temSum1;
782 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
783 0 : yBest = i;
784 : }
785 : else {
786 0 : s0 = _mm_unpacklo_epi16(s3, _mm_setzero_si128());
787 0 : s3 = _mm_unpackhi_epi16(s3, _mm_setzero_si128());
788 0 : s1 = _mm_unpacklo_epi16(s4, _mm_setzero_si128());
789 0 : s4 = _mm_unpackhi_epi16(s4, _mm_setzero_si128());
790 0 : s2 = _mm_unpacklo_epi16(s5, _mm_setzero_si128());
791 0 : s5 = _mm_unpackhi_epi16(s5, _mm_setzero_si128());
792 0 : s0 = _mm_add_epi32(_mm_add_epi32(s0, s1), s2);
793 0 : s3 = _mm_add_epi32(_mm_add_epi32(s3, s4), s5);
794 0 : UPDATE_BEST(s0, 0, 0);
795 0 : UPDATE_BEST(s0, 1, 0);
796 0 : UPDATE_BEST(s0, 2, 0);
797 0 : UPDATE_BEST(s0, 3, 0);
798 0 : UPDATE_BEST(s3, 0, 4);
799 0 : UPDATE_BEST(s3, 1, 4);
800 0 : UPDATE_BEST(s3, 2, 4);
801 0 : UPDATE_BEST(s3, 3, 4);
802 : }
803 : }
804 : }
805 :
806 0 : if (leftover && j < search_area_width ) {
807 0 : pSrc = src;
808 0 : pRef = ref + j;
809 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
810 0 : for (k = 0; k < block_height; k++) {
811 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
812 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
813 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
814 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
815 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
816 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
817 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
818 0 : pSrc += src_stride;
819 0 : pRef += ref_stride;
820 : }
821 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
822 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
823 0 : s3 = _mm256_castsi256_si128(ss3);
824 0 : s4 = _mm256_extracti128_si256(ss3, 1);
825 0 : s5 = _mm256_castsi256_si128(ss5);
826 0 : s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), s5);
827 0 : s0 = _mm_or_si128(s0, s8);
828 0 : s0 = _mm_minpos_epu16(s0);
829 0 : temSum1 = _mm_extract_epi16(s0, 0);
830 0 : if (temSum1 < lowSum) {
831 0 : if (temSum1 != 0xFFFF) { // no overflow
832 0 : lowSum = temSum1;
833 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
834 0 : yBest = i;
835 : }
836 : else {
837 0 : s0 = _mm_unpacklo_epi16(s3, _mm_setzero_si128());
838 0 : s3 = _mm_unpackhi_epi16(s3, _mm_setzero_si128());
839 0 : s1 = _mm_unpacklo_epi16(s4, _mm_setzero_si128());
840 0 : s4 = _mm_unpackhi_epi16(s4, _mm_setzero_si128());
841 0 : s2 = _mm_unpacklo_epi16(s5, _mm_setzero_si128());
842 0 : s5 = _mm_unpackhi_epi16(s5, _mm_setzero_si128());
843 0 : s0 = _mm_add_epi32(_mm_add_epi32(s0, s1), s2);
844 0 : s3 = _mm_add_epi32(_mm_add_epi32(s3, s4), s5);
845 0 : k = leftover;
846 0 : while (k > 0) {
847 0 : for (l = 0; l < 4 && k; l++, k--) {
848 0 : temSum1 = _mm_extract_epi32(s0, 0);
849 0 : s0 = _mm_srli_si128(s0, 4);
850 0 : if (temSum1 < lowSum) {
851 0 : lowSum = temSum1;
852 0 : xBest = (int16_t)(j + leftover - k);
853 0 : yBest = i;
854 : }
855 : }
856 0 : s0 = s3;
857 : }
858 : }
859 : }
860 : }
861 0 : ref += src_stride_raw;
862 : }
863 : }
864 0 : break;
865 :
866 0 : case 32:
867 0 : if (block_height <= 16) {
868 0 : for (i = 0; i < search_area_height; i++) {
869 0 : uint32_t startW = (i & 1) << 3;
870 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
871 0 : pSrc = src;
872 0 : pRef = ref + j;
873 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
874 0 : for (k = 0; k < block_height; k++) {
875 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
876 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
877 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
878 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
879 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
880 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
881 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
882 0 : pSrc += src_stride;
883 0 : pRef += ref_stride;
884 : }
885 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
886 0 : s3 = _mm256_castsi256_si128(ss3);
887 0 : s5 = _mm256_extracti128_si256(ss3, 1);
888 0 : s4 = _mm_minpos_epu16(s3);
889 0 : s6 = _mm_minpos_epu16(s5);
890 0 : s4 = _mm_unpacklo_epi16(s4, s4);
891 0 : s4 = _mm_unpacklo_epi32(s4, s4);
892 0 : s4 = _mm_unpacklo_epi64(s4, s4);
893 0 : s6 = _mm_unpacklo_epi16(s6, s6);
894 0 : s6 = _mm_unpacklo_epi32(s6, s6);
895 0 : s6 = _mm_unpacklo_epi64(s6, s6);
896 0 : s3 = _mm_sub_epi16(s3, s4);
897 0 : s5 = _mm_adds_epu16(s5, s3);
898 0 : s5 = _mm_sub_epi16(s5, s6);
899 0 : s5 = _mm_minpos_epu16(s5);
900 0 : temSum1 = _mm_extract_epi16(s5, 0);
901 0 : temSum1 += _mm_extract_epi16(s4, 0);
902 0 : temSum1 += _mm_extract_epi16(s6, 0);
903 0 : if (temSum1 < lowSum) {
904 0 : lowSum = temSum1;
905 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
906 0 : yBest = i;
907 : }
908 : }
909 :
910 0 : if (leftover && j < search_area_width ) {
911 0 : pSrc = src;
912 0 : pRef = ref + j;
913 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
914 0 : for (k = 0; k < block_height; k++) {
915 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
916 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
917 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
918 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
919 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
920 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
921 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
922 0 : pSrc += src_stride;
923 0 : pRef += ref_stride;
924 : }
925 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
926 0 : s3 = _mm256_castsi256_si128(ss3);
927 0 : s5 = _mm256_extracti128_si256(ss3, 1);
928 0 : s3 = _mm_or_si128(s3, s8);
929 0 : s5 = _mm_or_si128(s5, s8);
930 0 : s4 = _mm_minpos_epu16(s3);
931 0 : s6 = _mm_minpos_epu16(s5);
932 0 : s4 = _mm_unpacklo_epi16(s4, s4);
933 0 : s4 = _mm_unpacklo_epi32(s4, s4);
934 0 : s4 = _mm_unpacklo_epi64(s4, s4);
935 0 : s6 = _mm_unpacklo_epi16(s6, s6);
936 0 : s6 = _mm_unpacklo_epi32(s6, s6);
937 0 : s6 = _mm_unpacklo_epi64(s6, s6);
938 0 : s3 = _mm_sub_epi16(s3, s4);
939 0 : s5 = _mm_adds_epu16(s5, s3);
940 0 : s5 = _mm_sub_epi16(s5, s6);
941 0 : s5 = _mm_minpos_epu16(s5);
942 0 : temSum1 = _mm_extract_epi16(s5, 0);
943 0 : temSum1 += _mm_extract_epi16(s4, 0);
944 0 : temSum1 += _mm_extract_epi16(s6, 0);
945 0 : if (temSum1 < lowSum) {
946 0 : lowSum = temSum1;
947 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
948 0 : yBest = i;
949 : }
950 : }
951 0 : ref += src_stride_raw;
952 : }
953 : }
954 0 : else if (block_height <= 32) {
955 0 : for (i = 0; i < search_area_height; i++) {
956 0 : uint32_t startW = (i & 1) << 3;
957 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
958 0 : pSrc = src;
959 0 : pRef = ref + j;
960 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
961 0 : for (k = 0; k < block_height; k++) {
962 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
963 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
964 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
965 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
966 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
967 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
968 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
969 0 : pSrc += src_stride;
970 0 : pRef += ref_stride;
971 : }
972 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
973 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
974 0 : ss6 = _mm256_adds_epu16(ss3, ss5);
975 0 : s3 = _mm256_castsi256_si128(ss6);
976 0 : s4 = _mm256_extracti128_si256(ss6, 1);
977 0 : s0 = _mm_adds_epu16(s3, s4);
978 0 : s0 = _mm_minpos_epu16(s0);
979 0 : temSum1 = _mm_extract_epi16(s0, 0);
980 0 : if (temSum1 < lowSum) {
981 0 : if (temSum1 != 0xFFFF) { // no overflow
982 0 : lowSum = temSum1;
983 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
984 0 : yBest = i;
985 : }
986 : else {
987 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
988 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
989 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
990 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
991 0 : ss4 = _mm256_add_epi32(ss4, ss6);
992 0 : ss3 = _mm256_add_epi32(ss3, ss5);
993 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
994 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
995 0 : UPDATE_BEST(s0, 0, 0);
996 0 : UPDATE_BEST(s0, 1, 0);
997 0 : UPDATE_BEST(s0, 2, 0);
998 0 : UPDATE_BEST(s0, 3, 0);
999 0 : UPDATE_BEST(s3, 0, 4);
1000 0 : UPDATE_BEST(s3, 1, 4);
1001 0 : UPDATE_BEST(s3, 2, 4);
1002 0 : UPDATE_BEST(s3, 3, 4);
1003 : }
1004 : }
1005 : }
1006 :
1007 0 : if (leftover && j < search_area_width ) {
1008 0 : pSrc = src;
1009 0 : pRef = ref + j;
1010 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
1011 0 : for (k = 0; k < block_height; k++) {
1012 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
1013 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
1014 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
1015 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1016 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1017 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1018 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1019 0 : pSrc += src_stride;
1020 0 : pRef += ref_stride;
1021 : }
1022 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
1023 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
1024 0 : ss6 = _mm256_adds_epu16(ss3, ss5);
1025 0 : s3 = _mm256_castsi256_si128(ss6);
1026 0 : s4 = _mm256_extracti128_si256(ss6, 1);
1027 0 : s0 = _mm_adds_epu16(s3, s4);
1028 : //s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
1029 0 : s0 = _mm_or_si128(s0, s8);
1030 0 : s0 = _mm_minpos_epu16(s0);
1031 0 : temSum1 = _mm_extract_epi16(s0, 0);
1032 0 : if (temSum1 < lowSum) {
1033 0 : if (temSum1 != 0xFFFF) { // no overflow
1034 0 : lowSum = temSum1;
1035 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
1036 0 : yBest = i;
1037 : }
1038 : else {
1039 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
1040 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
1041 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
1042 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
1043 0 : ss4 = _mm256_add_epi32(ss4, ss6);
1044 0 : ss3 = _mm256_add_epi32(ss3, ss5);
1045 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
1046 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1047 0 : k = leftover;
1048 0 : while (k > 0) {
1049 0 : for (l = 0; l < 4 && k; l++, k--) {
1050 0 : temSum1 = _mm_extract_epi32(s0, 0);
1051 0 : s0 = _mm_srli_si128(s0, 4);
1052 0 : if (temSum1 < lowSum) {
1053 0 : lowSum = temSum1;
1054 0 : xBest = (int16_t)(j + leftover - k);
1055 0 : yBest = i;
1056 : }
1057 : }
1058 0 : s0 = s3;
1059 : }
1060 : }
1061 : }
1062 : }
1063 0 : ref += src_stride_raw;
1064 : }
1065 : }
1066 : else {
1067 0 : for (i = 0; i < search_area_height; i++) {
1068 0 : uint32_t startW = (i & 1) << 3;
1069 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
1070 0 : pSrc = src;
1071 0 : pRef = ref + j;
1072 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
1073 0 : for (k = 0; k < block_height; k++) {
1074 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
1075 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
1076 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
1077 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1078 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1079 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1080 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1081 0 : pSrc += src_stride;
1082 0 : pRef += ref_stride;
1083 : }
1084 0 : ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
1085 0 : s3 = _mm256_castsi256_si128(ss7);
1086 0 : s4 = _mm256_extracti128_si256(ss7, 1);
1087 0 : s0 = _mm_adds_epu16(s3, s4);
1088 0 : s0 = _mm_minpos_epu16(s0);
1089 0 : temSum1 = _mm_extract_epi16(s0, 0);
1090 0 : if (temSum1 < lowSum) {
1091 0 : if (temSum1 != 0xFFFF) { // no overflow
1092 0 : lowSum = temSum1;
1093 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
1094 0 : yBest = i;
1095 : }
1096 : else {
1097 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
1098 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
1099 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
1100 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
1101 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
1102 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
1103 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
1104 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
1105 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
1106 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
1107 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
1108 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1109 0 : UPDATE_BEST(s0, 0, 0);
1110 0 : UPDATE_BEST(s0, 1, 0);
1111 0 : UPDATE_BEST(s0, 2, 0);
1112 0 : UPDATE_BEST(s0, 3, 0);
1113 0 : UPDATE_BEST(s3, 0, 4);
1114 0 : UPDATE_BEST(s3, 1, 4);
1115 0 : UPDATE_BEST(s3, 2, 4);
1116 0 : UPDATE_BEST(s3, 3, 4);
1117 : }
1118 : }
1119 : }
1120 :
1121 0 : if (leftover && j < search_area_width ) {
1122 0 : pSrc = src;
1123 0 : pRef = ref + j;
1124 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
1125 0 : for (k = 0; k < block_height; k++) {
1126 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
1127 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
1128 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
1129 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1130 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1131 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1132 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1133 0 : pSrc += src_stride;
1134 0 : pRef += ref_stride;
1135 : }
1136 0 : ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
1137 0 : s3 = _mm256_castsi256_si128(ss7);
1138 0 : s4 = _mm256_extracti128_si256(ss7, 1);
1139 0 : s0 = _mm_adds_epu16(s3, s4);
1140 0 : s0 = _mm_minpos_epu16(s0);
1141 0 : temSum1 = _mm_extract_epi16(s0, 0);
1142 0 : if (temSum1 < lowSum) {
1143 0 : if (temSum1 != 0xFFFF) { // no overflow
1144 0 : lowSum = temSum1;
1145 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
1146 0 : yBest = i;
1147 : }
1148 : else {
1149 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
1150 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
1151 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
1152 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
1153 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
1154 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
1155 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
1156 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
1157 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
1158 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
1159 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
1160 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1161 0 : k = leftover;
1162 0 : while (k > 0) {
1163 0 : for (l = 0; l < 4 && k; l++, k--) {
1164 0 : temSum1 = _mm_extract_epi32(s0, 0);
1165 0 : s0 = _mm_srli_si128(s0, 4);
1166 0 : if (temSum1 < lowSum) {
1167 0 : lowSum = temSum1;
1168 0 : xBest = (int16_t)(j + leftover - k);
1169 0 : yBest = i;
1170 : }
1171 : }
1172 0 : s0 = s3;
1173 : }
1174 : }
1175 : }
1176 : }
1177 0 : ref += src_stride_raw;
1178 : }
1179 : }
1180 0 : break;
1181 :
1182 0 : case 48:
1183 0 : if (block_height <= 32) {
1184 0 : for (i = 0; i < search_area_height; i++) {
1185 0 : uint32_t startW = (i & 1) << 3;
1186 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
1187 0 : pSrc = src;
1188 0 : pRef = ref + j;
1189 0 : s3 = s4 = s5 = s6 = _mm_setzero_si128();
1190 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
1191 0 : for (k = 0; k < block_height; k++) {
1192 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
1193 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
1194 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
1195 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1196 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1197 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1198 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1199 0 : s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
1200 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
1201 0 : s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
1202 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
1203 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
1204 0 : s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
1205 0 : s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
1206 0 : pSrc += src_stride;
1207 0 : pRef += ref_stride;
1208 : }
1209 0 : s3 = _mm_adds_epu16(s3, s4);
1210 0 : s5 = _mm_adds_epu16(s5, s6);
1211 0 : s0 = _mm_adds_epu16(s3, s5);
1212 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
1213 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
1214 0 : ss6 = _mm256_adds_epu16(ss3, ss5);
1215 0 : s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss6), _mm256_extracti128_si256(ss6, 1)));
1216 0 : s0 = _mm_minpos_epu16(s0);
1217 0 : temSum1 = _mm_extract_epi16(s0, 0);
1218 0 : if (temSum1 < lowSum) {
1219 0 : if (temSum1 != 0xFFFF) { // no overflow
1220 0 : lowSum = temSum1;
1221 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
1222 0 : yBest = i;
1223 : }
1224 : else {
1225 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
1226 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
1227 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
1228 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
1229 0 : ss4 = _mm256_add_epi32(ss4, ss6);
1230 0 : ss3 = _mm256_add_epi32(ss3, ss5);
1231 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
1232 0 : s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1233 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
1234 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
1235 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
1236 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
1237 0 : UPDATE_BEST(s0, 0, 0);
1238 0 : UPDATE_BEST(s0, 1, 0);
1239 0 : UPDATE_BEST(s0, 2, 0);
1240 0 : UPDATE_BEST(s0, 3, 0);
1241 0 : UPDATE_BEST(s1, 0, 4);
1242 0 : UPDATE_BEST(s1, 1, 4);
1243 0 : UPDATE_BEST(s1, 2, 4);
1244 0 : UPDATE_BEST(s1, 3, 4);
1245 : }
1246 : }
1247 : }
1248 :
1249 0 : if (leftover && j < search_area_width ) {
1250 0 : pSrc = src;
1251 0 : pRef = ref + j;
1252 0 : s3 = s4 = s5 = s6 = _mm_setzero_si128();
1253 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
1254 0 : for (k = 0; k < block_height; k++) {
1255 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
1256 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
1257 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
1258 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1259 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1260 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1261 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1262 0 : s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
1263 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
1264 0 : s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
1265 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
1266 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
1267 0 : s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
1268 0 : s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
1269 0 : pSrc += src_stride;
1270 0 : pRef += ref_stride;
1271 : }
1272 0 : s3 = _mm_adds_epu16(s3, s4);
1273 0 : s5 = _mm_adds_epu16(s5, s6);
1274 0 : s0 = _mm_adds_epu16(s3, s5);
1275 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
1276 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
1277 0 : ss6 = _mm256_adds_epu16(ss3, ss5);
1278 0 : s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss6), _mm256_extracti128_si256(ss6, 1)));
1279 0 : s0 = _mm_or_si128(s0, s8);
1280 0 : s0 = _mm_minpos_epu16(s0);
1281 0 : temSum1 = _mm_extract_epi16(s0, 0);
1282 0 : if (temSum1 < lowSum) {
1283 0 : if (temSum1 != 0xFFFF) { // no overflow
1284 0 : lowSum = temSum1;
1285 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
1286 0 : yBest = i;
1287 : }
1288 : else {
1289 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
1290 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
1291 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
1292 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
1293 0 : ss4 = _mm256_add_epi32(ss4, ss6);
1294 0 : ss3 = _mm256_add_epi32(ss3, ss5);
1295 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
1296 0 : s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1297 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
1298 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
1299 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
1300 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
1301 0 : k = leftover;
1302 0 : while (k > 0) {
1303 0 : for (l = 0; l < 4 && k; l++, k--) {
1304 0 : temSum1 = _mm_extract_epi32(s0, 0);
1305 0 : s0 = _mm_srli_si128(s0, 4);
1306 0 : if (temSum1 < lowSum) {
1307 0 : lowSum = temSum1;
1308 0 : xBest = (int16_t)(j + leftover - k);
1309 0 : yBest = i;
1310 : }
1311 : }
1312 0 : s0 = s1;
1313 : }
1314 : }
1315 : }
1316 : }
1317 0 : ref += src_stride_raw;
1318 : }
1319 : }
1320 : else {
1321 0 : for (i = 0; i < search_area_height; i++) {
1322 0 : uint32_t startW = (i & 1) << 3;
1323 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
1324 0 : pSrc = src;
1325 0 : pRef = ref + j;
1326 0 : s3 = s4 = s5 = s6 = _mm_setzero_si128();
1327 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
1328 0 : for (k = 0; k < block_height; k++) {
1329 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
1330 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
1331 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
1332 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1333 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1334 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1335 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1336 0 : s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
1337 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
1338 0 : s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
1339 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
1340 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
1341 0 : s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
1342 0 : s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
1343 0 : pSrc += src_stride;
1344 0 : pRef += ref_stride;
1345 : }
1346 0 : s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
1347 0 : ss7 = _mm256_adds_epu16(ss3, ss4);
1348 0 : ss8 = _mm256_adds_epu16(ss5, ss6);
1349 0 : ss7 = _mm256_adds_epu16(ss7, ss8);
1350 0 : s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1)));
1351 0 : s0 = _mm_minpos_epu16(s0);
1352 0 : temSum1 = _mm_extract_epi16(s0, 0);
1353 0 : if (temSum1 < lowSum) {
1354 0 : if (temSum1 != 0xFFFF) { // no overflow
1355 0 : lowSum = temSum1;
1356 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
1357 0 : yBest = i;
1358 : }
1359 : else {
1360 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
1361 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
1362 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
1363 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
1364 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
1365 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
1366 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
1367 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
1368 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
1369 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
1370 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
1371 0 : s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1372 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
1373 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s4, _mm_setzero_si128()));
1374 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
1375 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s6, _mm_setzero_si128()));
1376 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
1377 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s4, _mm_setzero_si128()));
1378 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
1379 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s6, _mm_setzero_si128()));
1380 0 : UPDATE_BEST(s0, 0, 0);
1381 0 : UPDATE_BEST(s0, 1, 0);
1382 0 : UPDATE_BEST(s0, 2, 0);
1383 0 : UPDATE_BEST(s0, 3, 0);
1384 0 : UPDATE_BEST(s1, 0, 4);
1385 0 : UPDATE_BEST(s1, 1, 4);
1386 0 : UPDATE_BEST(s1, 2, 4);
1387 0 : UPDATE_BEST(s1, 3, 4);
1388 : }
1389 : }
1390 : }
1391 :
1392 0 : if (leftover && j < search_area_width ) {
1393 0 : pSrc = src;
1394 0 : pRef = ref + j;
1395 0 : s3 = s4 = s5 = s6 = _mm_setzero_si128();
1396 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
1397 0 : for (k = 0; k < block_height; k++) {
1398 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
1399 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
1400 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
1401 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1402 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1403 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1404 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1405 0 : s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
1406 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
1407 0 : s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
1408 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
1409 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
1410 0 : s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
1411 0 : s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
1412 0 : pSrc += src_stride;
1413 0 : pRef += ref_stride;
1414 : }
1415 0 : s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
1416 0 : ss7 = _mm256_adds_epu16(ss3, ss4);
1417 0 : ss8 = _mm256_adds_epu16(ss5, ss6);
1418 0 : ss7 = _mm256_adds_epu16(ss7, ss8);
1419 0 : s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1)));
1420 0 : s0 = _mm_or_si128(s0, s8);
1421 0 : s0 = _mm_minpos_epu16(s0);
1422 0 : temSum1 = _mm_extract_epi16(s0, 0);
1423 0 : if (temSum1 < lowSum) {
1424 0 : if (temSum1 != 0xFFFF) { // no overflow
1425 0 : lowSum = temSum1;
1426 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
1427 0 : yBest = i;
1428 : }
1429 : else {
1430 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
1431 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
1432 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
1433 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
1434 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
1435 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
1436 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
1437 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
1438 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
1439 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
1440 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
1441 0 : s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1442 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
1443 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s4, _mm_setzero_si128()));
1444 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
1445 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s6, _mm_setzero_si128()));
1446 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
1447 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s4, _mm_setzero_si128()));
1448 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
1449 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s6, _mm_setzero_si128()));
1450 0 : k = leftover;
1451 0 : while (k > 0) {
1452 0 : for (l = 0; l < 4 && k; l++, k--) {
1453 0 : temSum1 = _mm_extract_epi32(s0, 0);
1454 0 : s0 = _mm_srli_si128(s0, 4);
1455 0 : if (temSum1 < lowSum) {
1456 0 : lowSum = temSum1;
1457 0 : xBest = (int16_t)(j + leftover - k);
1458 0 : yBest = i;
1459 : }
1460 : }
1461 0 : s0 = s1;
1462 : }
1463 : }
1464 : }
1465 : }
1466 0 : ref += src_stride_raw;
1467 : }
1468 : }
1469 0 : break;
1470 :
1471 0 : case 64:
1472 0 : if (block_height <= 32) {
1473 0 : for (i = 0; i < search_area_height; i++) {
1474 0 : uint32_t startW = (i & 1) << 3;
1475 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
1476 0 : pSrc = src;
1477 0 : pRef = ref + j;
1478 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
1479 0 : for (k = 0; k < block_height; k++) {
1480 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
1481 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
1482 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
1483 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1484 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1485 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1486 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1487 0 : ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
1488 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
1489 0 : ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
1490 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1491 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1492 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1493 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1494 0 : pSrc += src_stride;
1495 0 : pRef += ref_stride;
1496 : }
1497 0 : ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
1498 0 : s3 = _mm256_castsi256_si128(ss7);
1499 0 : s4 = _mm256_extracti128_si256(ss7, 1);
1500 0 : s0 = _mm_adds_epu16(s3, s4);
1501 0 : s0 = _mm_minpos_epu16(s0);
1502 0 : temSum1 = _mm_extract_epi16(s0, 0);
1503 0 : if (temSum1 < lowSum) {
1504 0 : if (temSum1 != 0xFFFF) { // no overflow
1505 0 : lowSum = temSum1;
1506 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
1507 0 : yBest = i;
1508 : }
1509 : else {
1510 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
1511 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
1512 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
1513 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
1514 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
1515 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
1516 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
1517 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
1518 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
1519 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
1520 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
1521 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1522 0 : UPDATE_BEST(s0, 0, 0);
1523 0 : UPDATE_BEST(s0, 1, 0);
1524 0 : UPDATE_BEST(s0, 2, 0);
1525 0 : UPDATE_BEST(s0, 3, 0);
1526 0 : UPDATE_BEST(s3, 0, 4);
1527 0 : UPDATE_BEST(s3, 1, 4);
1528 0 : UPDATE_BEST(s3, 2, 4);
1529 0 : UPDATE_BEST(s3, 3, 4);
1530 : }
1531 : }
1532 : }
1533 :
1534 0 : if (leftover && j < search_area_width ) {
1535 0 : pSrc = src;
1536 0 : pRef = ref + j;
1537 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
1538 0 : for (k = 0; k < block_height; k++) {
1539 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
1540 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
1541 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
1542 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1543 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1544 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1545 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1546 0 : ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
1547 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
1548 0 : ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
1549 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1550 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1551 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1552 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1553 0 : pSrc += src_stride;
1554 0 : pRef += ref_stride;
1555 : }
1556 0 : ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
1557 0 : s3 = _mm256_castsi256_si128(ss7);
1558 0 : s4 = _mm256_extracti128_si256(ss7, 1);
1559 0 : s0 = _mm_adds_epu16(s3, s4);
1560 0 : s0 = _mm_or_si128(s0, s8);
1561 0 : s0 = _mm_minpos_epu16(s0);
1562 0 : temSum1 = _mm_extract_epi16(s0, 0);
1563 0 : if (temSum1 < lowSum) {
1564 0 : if (temSum1 != 0xFFFF) { // no overflow
1565 0 : lowSum = temSum1;
1566 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
1567 0 : yBest = i;
1568 : }
1569 : else {
1570 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
1571 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
1572 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
1573 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
1574 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
1575 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
1576 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
1577 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
1578 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
1579 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
1580 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
1581 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1582 0 : k = leftover;
1583 0 : while (k > 0) {
1584 0 : for (l = 0; l < 4 && k; l++, k--) {
1585 0 : temSum1 = _mm_extract_epi32(s0, 0);
1586 0 : s0 = _mm_srli_si128(s0, 4);
1587 0 : if (temSum1 < lowSum) {
1588 0 : lowSum = temSum1;
1589 0 : xBest = (int16_t)(j + leftover - k);
1590 0 : yBest = i;
1591 : }
1592 : }
1593 0 : s0 = s3;
1594 : }
1595 : }
1596 : }
1597 : }
1598 0 : ref += src_stride_raw;
1599 : }
1600 : }
1601 : else {
1602 : __m256i ss9, ss10;
1603 0 : for (i = 0; i < search_area_height; i++) {
1604 0 : uint32_t startW = (i & 1) << 3;
1605 0 : for (j = startW; j <= search_area_width - 8; j += 16) {
1606 0 : pSrc = src;
1607 0 : pRef = ref + j;
1608 0 : ss3 = ss4 = ss5 = ss6 = ss7 = ss8 = ss9 = ss10 = _mm256_setzero_si256();
1609 0 : for (k = 0; k < block_height; k++) {
1610 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
1611 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
1612 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
1613 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1614 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1615 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1616 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1617 0 : ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
1618 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
1619 0 : ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
1620 0 : ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1621 0 : ss8 = _mm256_adds_epu16(ss8, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1622 0 : ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1623 0 : ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1624 0 : pSrc += src_stride;
1625 0 : pRef += ref_stride;
1626 : }
1627 0 : ss0 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
1628 0 : ss0 = _mm256_adds_epu16(ss0, _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss8), _mm256_adds_epu16(ss9, ss10)));
1629 0 : s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
1630 0 : s0 = _mm_minpos_epu16(s0);
1631 0 : temSum1 = _mm_extract_epi16(s0, 0);
1632 0 : if (temSum1 < lowSum) {
1633 0 : if (temSum1 != 0xFFFF) { // no overflow
1634 0 : lowSum = temSum1;
1635 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
1636 0 : yBest = i;
1637 : }
1638 : else {
1639 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss3, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss5, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256())));
1640 0 : ss1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss3, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss5, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256())));
1641 0 : ss2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss7, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss9, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss10, _mm256_setzero_si256())));
1642 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss7, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss9, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss10, _mm256_setzero_si256())));
1643 0 : ss0 = _mm256_add_epi32(ss0, ss2);
1644 0 : ss1 = _mm256_add_epi32(ss1, ss3);
1645 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
1646 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss1), _mm256_extracti128_si256(ss1, 1));
1647 0 : UPDATE_BEST(s0, 0, 0);
1648 0 : UPDATE_BEST(s0, 1, 0);
1649 0 : UPDATE_BEST(s0, 2, 0);
1650 0 : UPDATE_BEST(s0, 3, 0);
1651 0 : UPDATE_BEST(s3, 0, 4);
1652 0 : UPDATE_BEST(s3, 1, 4);
1653 0 : UPDATE_BEST(s3, 2, 4);
1654 0 : UPDATE_BEST(s3, 3, 4);
1655 : }
1656 : }
1657 : }
1658 :
1659 0 : if (leftover && j < search_area_width ) {
1660 0 : pSrc = src;
1661 0 : pRef = ref + j;
1662 0 : ss3 = ss4 = ss5 = ss6 = ss7 = ss8 = ss9 = ss10 = _mm256_setzero_si256();
1663 0 : for (k = 0; k < block_height; k++) {
1664 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
1665 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
1666 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
1667 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1668 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1669 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1670 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1671 0 : ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
1672 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
1673 0 : ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
1674 0 : ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1675 0 : ss8 = _mm256_adds_epu16(ss8, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1676 0 : ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1677 0 : ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1678 0 : pSrc += src_stride;
1679 0 : pRef += ref_stride;
1680 : }
1681 0 : ss0 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
1682 0 : ss0 = _mm256_adds_epu16(ss0, _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss8), _mm256_adds_epu16(ss9, ss10)));
1683 0 : s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
1684 0 : s0 = _mm_or_si128(s0, s8);
1685 0 : s0 = _mm_minpos_epu16(s0);
1686 0 : temSum1 = _mm_extract_epi16(s0, 0);
1687 0 : if (temSum1 < lowSum) {
1688 0 : if (temSum1 != 0xFFFF) { // no overflow
1689 0 : lowSum = temSum1;
1690 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
1691 0 : yBest = i;
1692 : }
1693 : else {
1694 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss3, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss5, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256())));
1695 0 : ss1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss3, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss5, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256())));
1696 0 : ss2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss7, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss9, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss10, _mm256_setzero_si256())));
1697 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss7, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss9, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss10, _mm256_setzero_si256())));
1698 0 : ss0 = _mm256_add_epi32(ss0, ss2);
1699 0 : ss1 = _mm256_add_epi32(ss1, ss3);
1700 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
1701 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss1), _mm256_extracti128_si256(ss1, 1));
1702 0 : k = leftover;
1703 0 : while (k > 0) {
1704 0 : for (l = 0; l < 4 && k; l++, k--) {
1705 0 : temSum1 = _mm_extract_epi32(s0, 0);
1706 0 : s0 = _mm_srli_si128(s0, 4);
1707 0 : if (temSum1 < lowSum) {
1708 0 : lowSum = temSum1;
1709 0 : xBest = (int16_t)(j + leftover - k);
1710 0 : yBest = i;
1711 : }
1712 : }
1713 0 : s0 = s3;
1714 : }
1715 : }
1716 : }
1717 : }
1718 0 : ref += src_stride_raw;
1719 : }
1720 : }
1721 0 : break;
1722 :
1723 0 : default:
1724 : assert(0);
1725 0 : break;
1726 : }
1727 :
1728 0 : *best_sad = lowSum;
1729 0 : *x_search_center = xBest;
1730 0 : *y_search_center = yBest;
1731 0 : }
1732 :
1733 : /*******************************************************************************
1734 : * Requirement: width = 4, 8, 16, 24, 32, 48 or 64
1735 : * Requirement: block_height <= 64
1736 : * Requirement: block_height % 2 = 0 when width = 4 or 8
1737 : *******************************************************************************/
1738 63181 : void sad_loop_kernel_avx2_intrin(
1739 : uint8_t *src, // input parameter, source samples Ptr
1740 : uint32_t src_stride, // input parameter, source stride
1741 : uint8_t *ref, // input parameter, reference samples Ptr
1742 : uint32_t ref_stride, // input parameter, reference stride
1743 : uint32_t block_height, // input parameter, block height (M)
1744 : uint32_t block_width, // input parameter, block width (N)
1745 : uint64_t *best_sad,
1746 : int16_t *x_search_center,
1747 : int16_t *y_search_center,
1748 : uint32_t src_stride_raw, // input parameter, source stride (no line skipping)
1749 : int16_t search_area_width,
1750 : int16_t search_area_height)
1751 : {
1752 63181 : int16_t xBest = *x_search_center, yBest = *y_search_center;
1753 63181 : uint32_t lowSum = 0xffffff;
1754 63181 : uint32_t temSum1 = 0;
1755 : int16_t i, j;
1756 : uint32_t k, l;
1757 63181 : uint32_t leftover = search_area_width & 7;
1758 : const uint8_t *pRef, *pSrc;
1759 63181 : __m128i s0, s1, s2, s3, s4, s5, s6, s8 = _mm_set1_epi32(-1);
1760 : __m256i ss0, ss1, ss2, ss3, ss4, ss5, ss6, ss7, ss8;
1761 :
1762 63181 : if (leftover) {
1763 343 : for (k = 0; k < leftover; k++)
1764 294 : s8 = _mm_slli_si128(s8, 2);
1765 : }
1766 :
1767 63181 : switch (block_width) {
1768 0 : case 4:
1769 :
1770 0 : if (!(block_height % 4)) {
1771 0 : uint32_t srcStrideT = 3 * src_stride;
1772 0 : uint32_t refStrideT = 3 * ref_stride;
1773 0 : for (i = 0; i < search_area_height; i++) {
1774 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
1775 0 : pSrc = src;
1776 0 : pRef = ref + j;
1777 0 : ss3 = ss5 = _mm256_setzero_si256();
1778 0 : for (k = 0; k < block_height; k += 4) {
1779 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
1780 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
1781 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)pSrc), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)(pSrc + 2 * src_stride)), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + srcStrideT))), 0x1);
1782 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1783 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1784 0 : pSrc += src_stride << 2;
1785 0 : pRef += ref_stride << 2;
1786 : }
1787 0 : ss3 = _mm256_adds_epu16(ss3, ss5);
1788 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1789 0 : s3 = _mm_minpos_epu16(s3);
1790 0 : temSum1 = _mm_extract_epi16(s3, 0);
1791 0 : if (temSum1 < lowSum) {
1792 0 : lowSum = temSum1;
1793 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
1794 0 : yBest = i;
1795 : }
1796 : }
1797 :
1798 0 : if (leftover) {
1799 0 : pSrc = src;
1800 0 : pRef = ref + j;
1801 0 : ss3 = ss5 = _mm256_setzero_si256();
1802 0 : for (k = 0; k < block_height; k += 4) {
1803 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
1804 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
1805 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)pSrc), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)(pSrc + 2 * src_stride)), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + srcStrideT))), 0x1);
1806 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1807 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1808 0 : pSrc += src_stride << 2;
1809 0 : pRef += ref_stride << 2;
1810 : }
1811 0 : ss3 = _mm256_adds_epu16(ss3, ss5);
1812 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1813 0 : s3 = _mm_or_si128(s3, s8);
1814 0 : s3 = _mm_minpos_epu16(s3);
1815 0 : temSum1 = _mm_extract_epi16(s3, 0);
1816 0 : if (temSum1 < lowSum) {
1817 0 : lowSum = temSum1;
1818 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
1819 0 : yBest = i;
1820 : }
1821 : }
1822 0 : ref += src_stride_raw;
1823 : }
1824 : }
1825 : else {
1826 0 : for (i = 0; i < search_area_height; i++) {
1827 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
1828 0 : pSrc = src;
1829 0 : pRef = ref + j;
1830 0 : s3 = _mm_setzero_si128();
1831 0 : for (k = 0; k < block_height; k += 2) {
1832 0 : s0 = _mm_loadu_si128((__m128i*)pRef);
1833 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
1834 0 : s2 = _mm_cvtsi32_si128(*(uint32_t *)pSrc);
1835 0 : s5 = _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride));
1836 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
1837 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
1838 0 : pSrc += src_stride << 1;
1839 0 : pRef += ref_stride << 1;
1840 : }
1841 0 : s3 = _mm_minpos_epu16(s3);
1842 0 : temSum1 = _mm_extract_epi16(s3, 0);
1843 0 : if (temSum1 < lowSum) {
1844 0 : lowSum = temSum1;
1845 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
1846 0 : yBest = i;
1847 : }
1848 : }
1849 :
1850 0 : if (leftover) {
1851 0 : pSrc = src;
1852 0 : pRef = ref + j;
1853 0 : s3 = _mm_setzero_si128();
1854 0 : for (k = 0; k < block_height; k += 2) {
1855 0 : s0 = _mm_loadu_si128((__m128i*)pRef);
1856 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
1857 0 : s2 = _mm_cvtsi32_si128(*(uint32_t *)pSrc);
1858 0 : s5 = _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride));
1859 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
1860 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
1861 0 : pSrc += src_stride << 1;
1862 0 : pRef += ref_stride << 1;
1863 : }
1864 0 : s3 = _mm_or_si128(s3, s8);
1865 0 : s3 = _mm_minpos_epu16(s3);
1866 0 : temSum1 = _mm_extract_epi16(s3, 0);
1867 0 : if (temSum1 < lowSum) {
1868 0 : lowSum = temSum1;
1869 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
1870 0 : yBest = i;
1871 : }
1872 : }
1873 0 : ref += src_stride_raw;
1874 : }
1875 : }
1876 :
1877 0 : break;
1878 :
1879 0 : case 8:
1880 0 : if (!(block_height % 4)) {
1881 0 : uint32_t srcStrideT = 3 * src_stride;
1882 0 : uint32_t refStrideT = 3 * ref_stride;
1883 0 : for (i = 0; i < search_area_height; i++) {
1884 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
1885 0 : pSrc = src;
1886 0 : pRef = ref + j;
1887 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
1888 0 : for (k = 0; k < block_height; k += 4) {
1889 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
1890 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
1891 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)pSrc), _mm_loadl_epi64((__m128i*)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)(pSrc + 2 * src_stride)), _mm_loadl_epi64((__m128i*)(pSrc + srcStrideT))), 0x1);
1892 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1893 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1894 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1895 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1896 0 : pSrc += src_stride << 2;
1897 0 : pRef += ref_stride << 2;
1898 : }
1899 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
1900 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1901 0 : s3 = _mm_minpos_epu16(s3);
1902 0 : temSum1 = _mm_extract_epi16(s3, 0);
1903 0 : if (temSum1 < lowSum) {
1904 0 : lowSum = temSum1;
1905 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
1906 0 : yBest = i;
1907 : }
1908 : }
1909 :
1910 0 : if (leftover) {
1911 0 : pSrc = src;
1912 0 : pRef = ref + j;
1913 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
1914 0 : for (k = 0; k < block_height; k += 4) {
1915 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
1916 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
1917 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)pSrc), _mm_loadl_epi64((__m128i*)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)(pSrc + 2 * src_stride)), _mm_loadl_epi64((__m128i*)(pSrc + srcStrideT))), 0x1);
1918 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
1919 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
1920 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
1921 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
1922 0 : pSrc += src_stride << 2;
1923 0 : pRef += ref_stride << 2;
1924 : }
1925 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
1926 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
1927 0 : s3 = _mm_or_si128(s3, s8);
1928 0 : s3 = _mm_minpos_epu16(s3);
1929 0 : temSum1 = _mm_extract_epi16(s3, 0);
1930 0 : if (temSum1 < lowSum) {
1931 0 : lowSum = temSum1;
1932 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
1933 0 : yBest = i;
1934 : }
1935 : }
1936 0 : ref += src_stride_raw;
1937 : }
1938 : }
1939 : else {
1940 0 : for (i = 0; i < search_area_height; i++) {
1941 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
1942 0 : pSrc = src;
1943 0 : pRef = ref + j;
1944 0 : s3 = s4 = _mm_setzero_si128();
1945 0 : for (k = 0; k < block_height; k += 2) {
1946 0 : s0 = _mm_loadu_si128((__m128i*)pRef);
1947 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
1948 0 : s2 = _mm_loadl_epi64((__m128i*)pSrc);
1949 0 : s5 = _mm_loadl_epi64((__m128i*)(pSrc + src_stride));
1950 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
1951 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
1952 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
1953 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s1, s5, 5));
1954 0 : pSrc += src_stride << 1;
1955 0 : pRef += ref_stride << 1;
1956 : }
1957 0 : s3 = _mm_adds_epu16(s3, s4);
1958 0 : s3 = _mm_minpos_epu16(s3);
1959 0 : temSum1 = _mm_extract_epi16(s3, 0);
1960 0 : if (temSum1 < lowSum) {
1961 0 : lowSum = temSum1;
1962 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
1963 0 : yBest = i;
1964 : }
1965 : }
1966 :
1967 0 : if (leftover) {
1968 0 : pSrc = src;
1969 0 : pRef = ref + j;
1970 0 : s3 = s4 = _mm_setzero_si128();
1971 0 : for (k = 0; k < block_height; k += 2) {
1972 0 : s0 = _mm_loadu_si128((__m128i*)pRef);
1973 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
1974 0 : s2 = _mm_loadl_epi64((__m128i*)pSrc);
1975 0 : s5 = _mm_loadl_epi64((__m128i*)(pSrc + src_stride));
1976 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
1977 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
1978 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
1979 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s1, s5, 5));
1980 0 : pSrc += src_stride << 1;
1981 0 : pRef += ref_stride << 1;
1982 : }
1983 0 : s3 = _mm_adds_epu16(s3, s4);
1984 0 : s3 = _mm_or_si128(s3, s8);
1985 0 : s3 = _mm_minpos_epu16(s3);
1986 0 : temSum1 = _mm_extract_epi16(s3, 0);
1987 0 : if (temSum1 < lowSum) {
1988 0 : lowSum = temSum1;
1989 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
1990 0 : yBest = i;
1991 : }
1992 : }
1993 0 : ref += src_stride_raw;
1994 : }
1995 : }
1996 0 : break;
1997 :
1998 0 : case 16:
1999 0 : if (block_height <= 16) {
2000 0 : for (i = 0; i < search_area_height; i++) {
2001 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
2002 0 : pSrc = src;
2003 0 : pRef = ref + j;
2004 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2005 0 : for (k = 0; k < block_height; k += 2) {
2006 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
2007 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
2008 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
2009 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2010 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2011 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2012 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2013 0 : pSrc += 2 * src_stride;
2014 0 : pRef += 2 * ref_stride;
2015 : }
2016 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
2017 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2018 0 : s3 = _mm_minpos_epu16(s3);
2019 0 : temSum1 = _mm_extract_epi16(s3, 0);
2020 0 : if (temSum1 < lowSum) {
2021 0 : lowSum = temSum1;
2022 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
2023 0 : yBest = i;
2024 : }
2025 : }
2026 :
2027 0 : if (leftover) {
2028 0 : pSrc = src;
2029 0 : pRef = ref + j;
2030 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2031 0 : for (k = 0; k < block_height; k += 2) {
2032 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
2033 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
2034 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
2035 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2036 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2037 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2038 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2039 0 : pSrc += 2 * src_stride;
2040 0 : pRef += 2 * ref_stride;
2041 : }
2042 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
2043 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2044 0 : s3 = _mm_or_si128(s3, s8);
2045 0 : s3 = _mm_minpos_epu16(s3);
2046 0 : temSum1 = _mm_extract_epi16(s3, 0);
2047 0 : if (temSum1 < lowSum) {
2048 0 : lowSum = temSum1;
2049 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
2050 0 : yBest = i;
2051 : }
2052 : }
2053 0 : ref += src_stride_raw;
2054 : }
2055 : }
2056 0 : else if (block_height <= 32) {
2057 0 : for (i = 0; i < search_area_height; i++) {
2058 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
2059 0 : pSrc = src;
2060 0 : pRef = ref + j;
2061 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2062 0 : for (k = 0; k < block_height; k += 2) {
2063 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
2064 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
2065 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
2066 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2067 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2068 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2069 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2070 0 : pSrc += 2 * src_stride;
2071 0 : pRef += 2 * ref_stride;
2072 : }
2073 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
2074 0 : s3 = _mm256_castsi256_si128(ss3);
2075 0 : s5 = _mm256_extracti128_si256(ss3, 1);
2076 0 : s4 = _mm_minpos_epu16(s3);
2077 0 : s6 = _mm_minpos_epu16(s5);
2078 0 : s4 = _mm_unpacklo_epi16(s4, s4);
2079 0 : s4 = _mm_unpacklo_epi32(s4, s4);
2080 0 : s4 = _mm_unpacklo_epi64(s4, s4);
2081 0 : s6 = _mm_unpacklo_epi16(s6, s6);
2082 0 : s6 = _mm_unpacklo_epi32(s6, s6);
2083 0 : s6 = _mm_unpacklo_epi64(s6, s6);
2084 0 : s3 = _mm_sub_epi16(s3, s4);
2085 0 : s5 = _mm_adds_epu16(s5, s3);
2086 0 : s5 = _mm_sub_epi16(s5, s6);
2087 0 : s5 = _mm_minpos_epu16(s5);
2088 0 : temSum1 = _mm_extract_epi16(s5, 0);
2089 0 : temSum1 += _mm_extract_epi16(s4, 0);
2090 0 : temSum1 += _mm_extract_epi16(s6, 0);
2091 0 : if (temSum1 < lowSum) {
2092 0 : lowSum = temSum1;
2093 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
2094 0 : yBest = i;
2095 : }
2096 : }
2097 :
2098 0 : if (leftover) {
2099 0 : pSrc = src;
2100 0 : pRef = ref + j;
2101 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2102 0 : for (k = 0; k < block_height; k += 2) {
2103 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
2104 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
2105 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
2106 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2107 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2108 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2109 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2110 0 : pSrc += 2 * src_stride;
2111 0 : pRef += 2 * ref_stride;
2112 : }
2113 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
2114 0 : s3 = _mm256_castsi256_si128(ss3);
2115 0 : s5 = _mm256_extracti128_si256(ss3, 1);
2116 0 : s3 = _mm_or_si128(s3, s8);
2117 0 : s5 = _mm_or_si128(s5, s8);
2118 0 : s4 = _mm_minpos_epu16(s3);
2119 0 : s6 = _mm_minpos_epu16(s5);
2120 0 : s4 = _mm_unpacklo_epi16(s4, s4);
2121 0 : s4 = _mm_unpacklo_epi32(s4, s4);
2122 0 : s4 = _mm_unpacklo_epi64(s4, s4);
2123 0 : s6 = _mm_unpacklo_epi16(s6, s6);
2124 0 : s6 = _mm_unpacklo_epi32(s6, s6);
2125 0 : s6 = _mm_unpacklo_epi64(s6, s6);
2126 0 : s3 = _mm_sub_epi16(s3, s4);
2127 0 : s5 = _mm_adds_epu16(s5, s3);
2128 0 : s5 = _mm_sub_epi16(s5, s6);
2129 0 : s5 = _mm_minpos_epu16(s5);
2130 0 : temSum1 = _mm_extract_epi16(s5, 0);
2131 0 : temSum1 += _mm_extract_epi16(s4, 0);
2132 0 : temSum1 += _mm_extract_epi16(s6, 0);
2133 0 : if (temSum1 < lowSum) {
2134 0 : lowSum = temSum1;
2135 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
2136 0 : yBest = i;
2137 : }
2138 : }
2139 0 : ref += src_stride_raw;
2140 : }
2141 : }
2142 : else {
2143 0 : for (i = 0; i < search_area_height; i++) {
2144 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
2145 0 : pSrc = src;
2146 0 : pRef = ref + j;
2147 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2148 0 : for (k = 0; k < block_height; k += 2) {
2149 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
2150 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
2151 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
2152 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2153 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2154 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2155 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2156 0 : pSrc += 2 * src_stride;
2157 0 : pRef += 2 * ref_stride;
2158 : }
2159 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
2160 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
2161 0 : ss0 = _mm256_adds_epu16(ss3, ss5);
2162 0 : s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
2163 0 : s0 = _mm_minpos_epu16(s0);
2164 0 : temSum1 = _mm_extract_epi16(s0, 0);
2165 0 : if (temSum1 < lowSum) {
2166 0 : if (temSum1 != 0xFFFF) { // no overflow
2167 0 : lowSum = temSum1;
2168 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
2169 0 : yBest = i;
2170 : }
2171 : else {
2172 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
2173 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
2174 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
2175 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
2176 0 : ss4 = _mm256_add_epi32(ss4, ss6);
2177 0 : ss3 = _mm256_add_epi32(ss3, ss5);
2178 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
2179 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2180 0 : UPDATE_BEST(s0, 0, 0);
2181 0 : UPDATE_BEST(s0, 1, 0);
2182 0 : UPDATE_BEST(s0, 2, 0);
2183 0 : UPDATE_BEST(s0, 3, 0);
2184 0 : UPDATE_BEST(s3, 0, 4);
2185 0 : UPDATE_BEST(s3, 1, 4);
2186 0 : UPDATE_BEST(s3, 2, 4);
2187 0 : UPDATE_BEST(s3, 3, 4);
2188 : }
2189 : }
2190 : }
2191 :
2192 0 : if (leftover) {
2193 0 : pSrc = src;
2194 0 : pRef = ref + j;
2195 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2196 0 : for (k = 0; k < block_height; k += 2) {
2197 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
2198 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
2199 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
2200 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2201 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2202 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2203 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2204 0 : pSrc += 2 * src_stride;
2205 0 : pRef += 2 * ref_stride;
2206 : }
2207 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
2208 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
2209 0 : ss0 = _mm256_adds_epu16(ss3, ss5);
2210 0 : s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
2211 0 : s0 = _mm_or_si128(s0, s8);
2212 0 : s0 = _mm_minpos_epu16(s0);
2213 0 : temSum1 = _mm_extract_epi16(s0, 0);
2214 0 : if (temSum1 < lowSum) {
2215 0 : if (temSum1 != 0xFFFF) { // no overflow
2216 0 : lowSum = temSum1;
2217 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
2218 0 : yBest = i;
2219 : }
2220 : else {
2221 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
2222 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
2223 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
2224 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
2225 0 : ss4 = _mm256_add_epi32(ss4, ss6);
2226 0 : ss3 = _mm256_add_epi32(ss3, ss5);
2227 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
2228 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2229 0 : k = leftover;
2230 0 : while (k > 0) {
2231 0 : for (l = 0; l < 4 && k; l++, k--) {
2232 0 : temSum1 = _mm_extract_epi32(s0, 0);
2233 0 : s0 = _mm_srli_si128(s0, 4);
2234 0 : if (temSum1 < lowSum) {
2235 0 : lowSum = temSum1;
2236 0 : xBest = (int16_t)(j + leftover - k);
2237 0 : yBest = i;
2238 : }
2239 : }
2240 0 : s0 = s3;
2241 : }
2242 : }
2243 : }
2244 : }
2245 0 : ref += src_stride_raw;
2246 : }
2247 : }
2248 0 : break;
2249 :
2250 0 : case 24:
2251 0 : if (block_height <= 16) {
2252 0 : for (i = 0; i < search_area_height; i++) {
2253 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
2254 0 : pSrc = src;
2255 0 : pRef = ref + j;
2256 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2257 0 : for (k = 0; k < block_height; k++) {
2258 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2259 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2260 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2261 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2262 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2263 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2264 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2265 0 : pSrc += src_stride;
2266 0 : pRef += ref_stride;
2267 : }
2268 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
2269 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
2270 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2271 0 : s5 = _mm256_castsi256_si128(ss5);
2272 0 : s4 = _mm_minpos_epu16(s3);
2273 0 : s6 = _mm_minpos_epu16(s5);
2274 0 : s4 = _mm_unpacklo_epi16(s4, s4);
2275 0 : s4 = _mm_unpacklo_epi32(s4, s4);
2276 0 : s4 = _mm_unpacklo_epi64(s4, s4);
2277 0 : s6 = _mm_unpacklo_epi16(s6, s6);
2278 0 : s6 = _mm_unpacklo_epi32(s6, s6);
2279 0 : s6 = _mm_unpacklo_epi64(s6, s6);
2280 0 : s3 = _mm_sub_epi16(s3, s4);
2281 0 : s5 = _mm_adds_epu16(s5, s3);
2282 0 : s5 = _mm_sub_epi16(s5, s6);
2283 0 : s5 = _mm_minpos_epu16(s5);
2284 0 : temSum1 = _mm_extract_epi16(s5, 0);
2285 0 : temSum1 += _mm_extract_epi16(s4, 0);
2286 0 : temSum1 += _mm_extract_epi16(s6, 0);
2287 0 : if (temSum1 < lowSum) {
2288 0 : lowSum = temSum1;
2289 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
2290 0 : yBest = i;
2291 : }
2292 : }
2293 :
2294 0 : if (leftover) {
2295 0 : pSrc = src;
2296 0 : pRef = ref + j;
2297 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2298 0 : for (k = 0; k < block_height; k++) {
2299 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2300 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2301 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2302 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2303 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2304 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2305 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2306 0 : pSrc += src_stride;
2307 0 : pRef += ref_stride;
2308 : }
2309 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
2310 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
2311 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2312 0 : s5 = _mm256_castsi256_si128(ss5);
2313 0 : s3 = _mm_or_si128(s3, s8);
2314 0 : s5 = _mm_or_si128(s5, s8);
2315 0 : s4 = _mm_minpos_epu16(s3);
2316 0 : s6 = _mm_minpos_epu16(s5);
2317 0 : s4 = _mm_unpacklo_epi16(s4, s4);
2318 0 : s4 = _mm_unpacklo_epi32(s4, s4);
2319 0 : s4 = _mm_unpacklo_epi64(s4, s4);
2320 0 : s6 = _mm_unpacklo_epi16(s6, s6);
2321 0 : s6 = _mm_unpacklo_epi32(s6, s6);
2322 0 : s6 = _mm_unpacklo_epi64(s6, s6);
2323 0 : s3 = _mm_sub_epi16(s3, s4);
2324 0 : s5 = _mm_adds_epu16(s5, s3);
2325 0 : s5 = _mm_sub_epi16(s5, s6);
2326 0 : s5 = _mm_minpos_epu16(s5);
2327 0 : temSum1 = _mm_extract_epi16(s5, 0);
2328 0 : temSum1 += _mm_extract_epi16(s4, 0);
2329 0 : temSum1 += _mm_extract_epi16(s6, 0);
2330 0 : if (temSum1 < lowSum) {
2331 0 : lowSum = temSum1;
2332 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
2333 0 : yBest = i;
2334 : }
2335 : }
2336 0 : ref += src_stride_raw;
2337 : }
2338 : }
2339 : else {
2340 0 : for (i = 0; i < search_area_height; i++) {
2341 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
2342 0 : pSrc = src;
2343 0 : pRef = ref + j;
2344 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2345 0 : for (k = 0; k < block_height; k++) {
2346 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2347 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2348 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2349 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2350 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2351 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2352 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2353 0 : pSrc += src_stride;
2354 0 : pRef += ref_stride;
2355 : }
2356 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
2357 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
2358 0 : s3 = _mm256_castsi256_si128(ss3);
2359 0 : s4 = _mm256_extracti128_si256(ss3, 1);
2360 0 : s5 = _mm256_castsi256_si128(ss5);
2361 0 : s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), s5);
2362 0 : s0 = _mm_minpos_epu16(s0);
2363 0 : temSum1 = _mm_extract_epi16(s0, 0);
2364 0 : if (temSum1 < lowSum) {
2365 0 : if (temSum1 != 0xFFFF) { // no overflow
2366 0 : lowSum = temSum1;
2367 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
2368 0 : yBest = i;
2369 : }
2370 : else {
2371 0 : s0 = _mm_unpacklo_epi16(s3, _mm_setzero_si128());
2372 0 : s3 = _mm_unpackhi_epi16(s3, _mm_setzero_si128());
2373 0 : s1 = _mm_unpacklo_epi16(s4, _mm_setzero_si128());
2374 0 : s4 = _mm_unpackhi_epi16(s4, _mm_setzero_si128());
2375 0 : s2 = _mm_unpacklo_epi16(s5, _mm_setzero_si128());
2376 0 : s5 = _mm_unpackhi_epi16(s5, _mm_setzero_si128());
2377 0 : s0 = _mm_add_epi32(_mm_add_epi32(s0, s1), s2);
2378 0 : s3 = _mm_add_epi32(_mm_add_epi32(s3, s4), s5);
2379 0 : UPDATE_BEST(s0, 0, 0);
2380 0 : UPDATE_BEST(s0, 1, 0);
2381 0 : UPDATE_BEST(s0, 2, 0);
2382 0 : UPDATE_BEST(s0, 3, 0);
2383 0 : UPDATE_BEST(s3, 0, 4);
2384 0 : UPDATE_BEST(s3, 1, 4);
2385 0 : UPDATE_BEST(s3, 2, 4);
2386 0 : UPDATE_BEST(s3, 3, 4);
2387 : }
2388 : }
2389 : }
2390 :
2391 0 : if (leftover) {
2392 0 : pSrc = src;
2393 0 : pRef = ref + j;
2394 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2395 0 : for (k = 0; k < block_height; k++) {
2396 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2397 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2398 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2399 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2400 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2401 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2402 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2403 0 : pSrc += src_stride;
2404 0 : pRef += ref_stride;
2405 : }
2406 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
2407 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
2408 0 : s3 = _mm256_castsi256_si128(ss3);
2409 0 : s4 = _mm256_extracti128_si256(ss3, 1);
2410 0 : s5 = _mm256_castsi256_si128(ss5);
2411 0 : s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), s5);
2412 0 : s0 = _mm_or_si128(s0, s8);
2413 0 : s0 = _mm_minpos_epu16(s0);
2414 0 : temSum1 = _mm_extract_epi16(s0, 0);
2415 0 : if (temSum1 < lowSum) {
2416 0 : if (temSum1 != 0xFFFF) { // no overflow
2417 0 : lowSum = temSum1;
2418 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
2419 0 : yBest = i;
2420 : }
2421 : else {
2422 0 : s0 = _mm_unpacklo_epi16(s3, _mm_setzero_si128());
2423 0 : s3 = _mm_unpackhi_epi16(s3, _mm_setzero_si128());
2424 0 : s1 = _mm_unpacklo_epi16(s4, _mm_setzero_si128());
2425 0 : s4 = _mm_unpackhi_epi16(s4, _mm_setzero_si128());
2426 0 : s2 = _mm_unpacklo_epi16(s5, _mm_setzero_si128());
2427 0 : s5 = _mm_unpackhi_epi16(s5, _mm_setzero_si128());
2428 0 : s0 = _mm_add_epi32(_mm_add_epi32(s0, s1), s2);
2429 0 : s3 = _mm_add_epi32(_mm_add_epi32(s3, s4), s5);
2430 0 : k = leftover;
2431 0 : while (k > 0) {
2432 0 : for (l = 0; l < 4 && k; l++, k--) {
2433 0 : temSum1 = _mm_extract_epi32(s0, 0);
2434 0 : s0 = _mm_srli_si128(s0, 4);
2435 0 : if (temSum1 < lowSum) {
2436 0 : lowSum = temSum1;
2437 0 : xBest = (int16_t)(j + leftover - k);
2438 0 : yBest = i;
2439 : }
2440 : }
2441 0 : s0 = s3;
2442 : }
2443 : }
2444 : }
2445 : }
2446 0 : ref += src_stride_raw;
2447 : }
2448 : }
2449 0 : break;
2450 :
2451 31596 : case 32:
2452 31596 : if (block_height <= 16) {
2453 0 : for (i = 0; i < search_area_height; i++) {
2454 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
2455 0 : pSrc = src;
2456 0 : pRef = ref + j;
2457 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2458 0 : for (k = 0; k < block_height; k++) {
2459 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2460 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2461 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2462 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2463 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2464 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2465 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2466 0 : pSrc += src_stride;
2467 0 : pRef += ref_stride;
2468 : }
2469 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
2470 0 : s3 = _mm256_castsi256_si128(ss3);
2471 0 : s5 = _mm256_extracti128_si256(ss3, 1);
2472 0 : s4 = _mm_minpos_epu16(s3);
2473 0 : s6 = _mm_minpos_epu16(s5);
2474 0 : s4 = _mm_unpacklo_epi16(s4, s4);
2475 0 : s4 = _mm_unpacklo_epi32(s4, s4);
2476 0 : s4 = _mm_unpacklo_epi64(s4, s4);
2477 0 : s6 = _mm_unpacklo_epi16(s6, s6);
2478 0 : s6 = _mm_unpacklo_epi32(s6, s6);
2479 0 : s6 = _mm_unpacklo_epi64(s6, s6);
2480 0 : s3 = _mm_sub_epi16(s3, s4);
2481 0 : s5 = _mm_adds_epu16(s5, s3);
2482 0 : s5 = _mm_sub_epi16(s5, s6);
2483 0 : s5 = _mm_minpos_epu16(s5);
2484 0 : temSum1 = _mm_extract_epi16(s5, 0);
2485 0 : temSum1 += _mm_extract_epi16(s4, 0);
2486 0 : temSum1 += _mm_extract_epi16(s6, 0);
2487 0 : if (temSum1 < lowSum) {
2488 0 : lowSum = temSum1;
2489 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
2490 0 : yBest = i;
2491 : }
2492 : }
2493 :
2494 0 : if (leftover) {
2495 0 : pSrc = src;
2496 0 : pRef = ref + j;
2497 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2498 0 : for (k = 0; k < block_height; k++) {
2499 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2500 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2501 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2502 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2503 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2504 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2505 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2506 0 : pSrc += src_stride;
2507 0 : pRef += ref_stride;
2508 : }
2509 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
2510 0 : s3 = _mm256_castsi256_si128(ss3);
2511 0 : s5 = _mm256_extracti128_si256(ss3, 1);
2512 0 : s3 = _mm_or_si128(s3, s8);
2513 0 : s5 = _mm_or_si128(s5, s8);
2514 0 : s4 = _mm_minpos_epu16(s3);
2515 0 : s6 = _mm_minpos_epu16(s5);
2516 0 : s4 = _mm_unpacklo_epi16(s4, s4);
2517 0 : s4 = _mm_unpacklo_epi32(s4, s4);
2518 0 : s4 = _mm_unpacklo_epi64(s4, s4);
2519 0 : s6 = _mm_unpacklo_epi16(s6, s6);
2520 0 : s6 = _mm_unpacklo_epi32(s6, s6);
2521 0 : s6 = _mm_unpacklo_epi64(s6, s6);
2522 0 : s3 = _mm_sub_epi16(s3, s4);
2523 0 : s5 = _mm_adds_epu16(s5, s3);
2524 0 : s5 = _mm_sub_epi16(s5, s6);
2525 0 : s5 = _mm_minpos_epu16(s5);
2526 0 : temSum1 = _mm_extract_epi16(s5, 0);
2527 0 : temSum1 += _mm_extract_epi16(s4, 0);
2528 0 : temSum1 += _mm_extract_epi16(s6, 0);
2529 0 : if (temSum1 < lowSum) {
2530 0 : lowSum = temSum1;
2531 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
2532 0 : yBest = i;
2533 : }
2534 : }
2535 0 : ref += src_stride_raw;
2536 : }
2537 : }
2538 31596 : else if (block_height <= 32) {
2539 322460 : for (i = 0; i < search_area_height; i++) {
2540 658039 : for (j = 0; j <= search_area_width - 8; j += 8) {
2541 367175 : pSrc = src;
2542 367175 : pRef = ref + j;
2543 367175 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2544 12045500 : for (k = 0; k < block_height; k++) {
2545 11678300 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2546 23356600 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2547 11678300 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2548 11678300 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2549 11678300 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2550 11678300 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2551 11678300 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2552 11678300 : pSrc += src_stride;
2553 11678300 : pRef += ref_stride;
2554 : }
2555 367175 : ss3 = _mm256_adds_epu16(ss3, ss4);
2556 367175 : ss5 = _mm256_adds_epu16(ss5, ss6);
2557 367175 : ss6 = _mm256_adds_epu16(ss3, ss5);
2558 367175 : s3 = _mm256_castsi256_si128(ss6);
2559 367175 : s4 = _mm256_extracti128_si256(ss6, 1);
2560 367175 : s0 = _mm_adds_epu16(s3, s4);
2561 367175 : s0 = _mm_minpos_epu16(s0);
2562 367175 : temSum1 = _mm_extract_epi16(s0, 0);
2563 367175 : if (temSum1 < lowSum) {
2564 168486 : if (temSum1 != 0xFFFF) { // no overflow
2565 168475 : lowSum = temSum1;
2566 168475 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
2567 168475 : yBest = i;
2568 : }
2569 : else {
2570 22 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
2571 22 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
2572 22 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
2573 22 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
2574 11 : ss4 = _mm256_add_epi32(ss4, ss6);
2575 11 : ss3 = _mm256_add_epi32(ss3, ss5);
2576 22 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
2577 22 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2578 11 : UPDATE_BEST(s0, 0, 0);
2579 11 : UPDATE_BEST(s0, 1, 0);
2580 11 : UPDATE_BEST(s0, 2, 0);
2581 11 : UPDATE_BEST(s0, 3, 0);
2582 11 : UPDATE_BEST(s3, 0, 4);
2583 11 : UPDATE_BEST(s3, 1, 4);
2584 11 : UPDATE_BEST(s3, 2, 4);
2585 11 : UPDATE_BEST(s3, 3, 4);
2586 : }
2587 : }
2588 : }
2589 :
2590 290864 : if (leftover) {
2591 256 : pSrc = src;
2592 256 : pRef = ref + j;
2593 256 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2594 8448 : for (k = 0; k < block_height; k++) {
2595 8192 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2596 16384 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2597 8192 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2598 8192 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2599 8192 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2600 8192 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2601 8192 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2602 8192 : pSrc += src_stride;
2603 8192 : pRef += ref_stride;
2604 : }
2605 256 : ss3 = _mm256_adds_epu16(ss3, ss4);
2606 256 : ss5 = _mm256_adds_epu16(ss5, ss6);
2607 256 : ss6 = _mm256_adds_epu16(ss3, ss5);
2608 256 : s3 = _mm256_castsi256_si128(ss6);
2609 256 : s4 = _mm256_extracti128_si256(ss6, 1);
2610 256 : s0 = _mm_adds_epu16(s3, s4);
2611 : //s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
2612 256 : s0 = _mm_or_si128(s0, s8);
2613 256 : s0 = _mm_minpos_epu16(s0);
2614 256 : temSum1 = _mm_extract_epi16(s0, 0);
2615 256 : if (temSum1 < lowSum) {
2616 137 : if (temSum1 != 0xFFFF) { // no overflow
2617 129 : lowSum = temSum1;
2618 129 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
2619 129 : yBest = i;
2620 : }
2621 : else {
2622 16 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
2623 16 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
2624 16 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
2625 16 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
2626 8 : ss4 = _mm256_add_epi32(ss4, ss6);
2627 8 : ss3 = _mm256_add_epi32(ss3, ss5);
2628 16 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
2629 16 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2630 8 : k = leftover;
2631 24 : while (k > 0) {
2632 64 : for (l = 0; l < 4 && k; l++, k--) {
2633 48 : temSum1 = _mm_extract_epi32(s0, 0);
2634 48 : s0 = _mm_srli_si128(s0, 4);
2635 48 : if (temSum1 < lowSum) {
2636 16 : lowSum = temSum1;
2637 16 : xBest = (int16_t)(j + leftover - k);
2638 16 : yBest = i;
2639 : }
2640 : }
2641 16 : s0 = s3;
2642 : }
2643 : }
2644 : }
2645 : }
2646 290864 : ref += src_stride_raw;
2647 : }
2648 : }
2649 : else {
2650 0 : for (i = 0; i < search_area_height; i++) {
2651 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
2652 0 : pSrc = src;
2653 0 : pRef = ref + j;
2654 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2655 0 : for (k = 0; k < block_height; k++) {
2656 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2657 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2658 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2659 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2660 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2661 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2662 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2663 0 : pSrc += src_stride;
2664 0 : pRef += ref_stride;
2665 : }
2666 0 : ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
2667 0 : s3 = _mm256_castsi256_si128(ss7);
2668 0 : s4 = _mm256_extracti128_si256(ss7, 1);
2669 0 : s0 = _mm_adds_epu16(s3, s4);
2670 0 : s0 = _mm_minpos_epu16(s0);
2671 0 : temSum1 = _mm_extract_epi16(s0, 0);
2672 0 : if (temSum1 < lowSum) {
2673 0 : if (temSum1 != 0xFFFF) { // no overflow
2674 0 : lowSum = temSum1;
2675 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
2676 0 : yBest = i;
2677 : }
2678 : else {
2679 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
2680 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
2681 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
2682 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
2683 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
2684 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
2685 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
2686 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
2687 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
2688 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
2689 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
2690 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2691 0 : UPDATE_BEST(s0, 0, 0);
2692 0 : UPDATE_BEST(s0, 1, 0);
2693 0 : UPDATE_BEST(s0, 2, 0);
2694 0 : UPDATE_BEST(s0, 3, 0);
2695 0 : UPDATE_BEST(s3, 0, 4);
2696 0 : UPDATE_BEST(s3, 1, 4);
2697 0 : UPDATE_BEST(s3, 2, 4);
2698 0 : UPDATE_BEST(s3, 3, 4);
2699 : }
2700 : }
2701 : }
2702 :
2703 0 : if (leftover) {
2704 0 : pSrc = src;
2705 0 : pRef = ref + j;
2706 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2707 0 : for (k = 0; k < block_height; k++) {
2708 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2709 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2710 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2711 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2712 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2713 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2714 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2715 0 : pSrc += src_stride;
2716 0 : pRef += ref_stride;
2717 : }
2718 0 : ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
2719 0 : s3 = _mm256_castsi256_si128(ss7);
2720 0 : s4 = _mm256_extracti128_si256(ss7, 1);
2721 0 : s0 = _mm_adds_epu16(s3, s4);
2722 0 : s0 = _mm_minpos_epu16(s0);
2723 0 : temSum1 = _mm_extract_epi16(s0, 0);
2724 0 : if (temSum1 < lowSum) {
2725 0 : if (temSum1 != 0xFFFF) { // no overflow
2726 0 : lowSum = temSum1;
2727 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
2728 0 : yBest = i;
2729 : }
2730 : else {
2731 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
2732 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
2733 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
2734 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
2735 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
2736 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
2737 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
2738 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
2739 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
2740 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
2741 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
2742 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2743 0 : k = leftover;
2744 0 : while (k > 0) {
2745 0 : for (l = 0; l < 4 && k; l++, k--) {
2746 0 : temSum1 = _mm_extract_epi32(s0, 0);
2747 0 : s0 = _mm_srli_si128(s0, 4);
2748 0 : if (temSum1 < lowSum) {
2749 0 : lowSum = temSum1;
2750 0 : xBest = (int16_t)(j + leftover - k);
2751 0 : yBest = i;
2752 : }
2753 : }
2754 0 : s0 = s3;
2755 : }
2756 : }
2757 : }
2758 : }
2759 0 : ref += src_stride_raw;
2760 : }
2761 : }
2762 31596 : break;
2763 :
2764 0 : case 48:
2765 0 : if (block_height <= 32) {
2766 0 : for (i = 0; i < search_area_height; i++) {
2767 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
2768 0 : pSrc = src;
2769 0 : pRef = ref + j;
2770 0 : s3 = s4 = s5 = s6 = _mm_setzero_si128();
2771 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2772 0 : for (k = 0; k < block_height; k++) {
2773 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2774 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2775 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2776 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2777 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2778 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2779 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2780 0 : s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
2781 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
2782 0 : s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
2783 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
2784 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
2785 0 : s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
2786 0 : s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
2787 0 : pSrc += src_stride;
2788 0 : pRef += ref_stride;
2789 : }
2790 0 : s3 = _mm_adds_epu16(s3, s4);
2791 0 : s5 = _mm_adds_epu16(s5, s6);
2792 0 : s0 = _mm_adds_epu16(s3, s5);
2793 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
2794 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
2795 0 : ss6 = _mm256_adds_epu16(ss3, ss5);
2796 0 : s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss6), _mm256_extracti128_si256(ss6, 1)));
2797 0 : s0 = _mm_minpos_epu16(s0);
2798 0 : temSum1 = _mm_extract_epi16(s0, 0);
2799 0 : if (temSum1 < lowSum) {
2800 0 : if (temSum1 != 0xFFFF) { // no overflow
2801 0 : lowSum = temSum1;
2802 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
2803 0 : yBest = i;
2804 : }
2805 : else {
2806 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
2807 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
2808 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
2809 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
2810 0 : ss4 = _mm256_add_epi32(ss4, ss6);
2811 0 : ss3 = _mm256_add_epi32(ss3, ss5);
2812 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
2813 0 : s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2814 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
2815 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
2816 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
2817 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
2818 0 : UPDATE_BEST(s0, 0, 0);
2819 0 : UPDATE_BEST(s0, 1, 0);
2820 0 : UPDATE_BEST(s0, 2, 0);
2821 0 : UPDATE_BEST(s0, 3, 0);
2822 0 : UPDATE_BEST(s1, 0, 4);
2823 0 : UPDATE_BEST(s1, 1, 4);
2824 0 : UPDATE_BEST(s1, 2, 4);
2825 0 : UPDATE_BEST(s1, 3, 4);
2826 : }
2827 : }
2828 : }
2829 :
2830 0 : if (leftover) {
2831 0 : pSrc = src;
2832 0 : pRef = ref + j;
2833 0 : s3 = s4 = s5 = s6 = _mm_setzero_si128();
2834 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2835 0 : for (k = 0; k < block_height; k++) {
2836 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2837 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2838 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2839 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2840 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2841 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2842 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2843 0 : s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
2844 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
2845 0 : s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
2846 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
2847 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
2848 0 : s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
2849 0 : s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
2850 0 : pSrc += src_stride;
2851 0 : pRef += ref_stride;
2852 : }
2853 0 : s3 = _mm_adds_epu16(s3, s4);
2854 0 : s5 = _mm_adds_epu16(s5, s6);
2855 0 : s0 = _mm_adds_epu16(s3, s5);
2856 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
2857 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
2858 0 : ss6 = _mm256_adds_epu16(ss3, ss5);
2859 0 : s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss6), _mm256_extracti128_si256(ss6, 1)));
2860 0 : s0 = _mm_or_si128(s0, s8);
2861 0 : s0 = _mm_minpos_epu16(s0);
2862 0 : temSum1 = _mm_extract_epi16(s0, 0);
2863 0 : if (temSum1 < lowSum) {
2864 0 : if (temSum1 != 0xFFFF) { // no overflow
2865 0 : lowSum = temSum1;
2866 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
2867 0 : yBest = i;
2868 : }
2869 : else {
2870 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
2871 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
2872 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
2873 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
2874 0 : ss4 = _mm256_add_epi32(ss4, ss6);
2875 0 : ss3 = _mm256_add_epi32(ss3, ss5);
2876 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
2877 0 : s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2878 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
2879 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
2880 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
2881 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
2882 0 : k = leftover;
2883 0 : while (k > 0) {
2884 0 : for (l = 0; l < 4 && k; l++, k--) {
2885 0 : temSum1 = _mm_extract_epi32(s0, 0);
2886 0 : s0 = _mm_srli_si128(s0, 4);
2887 0 : if (temSum1 < lowSum) {
2888 0 : lowSum = temSum1;
2889 0 : xBest = (int16_t)(j + leftover - k);
2890 0 : yBest = i;
2891 : }
2892 : }
2893 0 : s0 = s1;
2894 : }
2895 : }
2896 : }
2897 : }
2898 0 : ref += src_stride_raw;
2899 : }
2900 : }
2901 : else {
2902 0 : for (i = 0; i < search_area_height; i++) {
2903 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
2904 0 : pSrc = src;
2905 0 : pRef = ref + j;
2906 0 : s3 = s4 = s5 = s6 = _mm_setzero_si128();
2907 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2908 0 : for (k = 0; k < block_height; k++) {
2909 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2910 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2911 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2912 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2913 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2914 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2915 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2916 0 : s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
2917 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
2918 0 : s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
2919 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
2920 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
2921 0 : s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
2922 0 : s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
2923 0 : pSrc += src_stride;
2924 0 : pRef += ref_stride;
2925 : }
2926 0 : s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
2927 0 : ss7 = _mm256_adds_epu16(ss3, ss4);
2928 0 : ss8 = _mm256_adds_epu16(ss5, ss6);
2929 0 : ss7 = _mm256_adds_epu16(ss7, ss8);
2930 0 : s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1)));
2931 0 : s0 = _mm_minpos_epu16(s0);
2932 0 : temSum1 = _mm_extract_epi16(s0, 0);
2933 0 : if (temSum1 < lowSum) {
2934 0 : if (temSum1 != 0xFFFF) { // no overflow
2935 0 : lowSum = temSum1;
2936 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
2937 0 : yBest = i;
2938 : }
2939 : else {
2940 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
2941 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
2942 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
2943 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
2944 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
2945 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
2946 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
2947 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
2948 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
2949 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
2950 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
2951 0 : s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
2952 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
2953 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s4, _mm_setzero_si128()));
2954 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
2955 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s6, _mm_setzero_si128()));
2956 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
2957 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s4, _mm_setzero_si128()));
2958 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
2959 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s6, _mm_setzero_si128()));
2960 0 : UPDATE_BEST(s0, 0, 0);
2961 0 : UPDATE_BEST(s0, 1, 0);
2962 0 : UPDATE_BEST(s0, 2, 0);
2963 0 : UPDATE_BEST(s0, 3, 0);
2964 0 : UPDATE_BEST(s1, 0, 4);
2965 0 : UPDATE_BEST(s1, 1, 4);
2966 0 : UPDATE_BEST(s1, 2, 4);
2967 0 : UPDATE_BEST(s1, 3, 4);
2968 : }
2969 : }
2970 : }
2971 :
2972 0 : if (leftover) {
2973 0 : pSrc = src;
2974 0 : pRef = ref + j;
2975 0 : s3 = s4 = s5 = s6 = _mm_setzero_si128();
2976 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
2977 0 : for (k = 0; k < block_height; k++) {
2978 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
2979 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
2980 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
2981 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
2982 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
2983 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
2984 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
2985 0 : s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
2986 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
2987 0 : s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
2988 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
2989 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
2990 0 : s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
2991 0 : s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
2992 0 : pSrc += src_stride;
2993 0 : pRef += ref_stride;
2994 : }
2995 0 : s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
2996 0 : ss7 = _mm256_adds_epu16(ss3, ss4);
2997 0 : ss8 = _mm256_adds_epu16(ss5, ss6);
2998 0 : ss7 = _mm256_adds_epu16(ss7, ss8);
2999 0 : s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1)));
3000 0 : s0 = _mm_or_si128(s0, s8);
3001 0 : s0 = _mm_minpos_epu16(s0);
3002 0 : temSum1 = _mm_extract_epi16(s0, 0);
3003 0 : if (temSum1 < lowSum) {
3004 0 : if (temSum1 != 0xFFFF) { // no overflow
3005 0 : lowSum = temSum1;
3006 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
3007 0 : yBest = i;
3008 : }
3009 : else {
3010 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
3011 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
3012 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
3013 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
3014 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
3015 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
3016 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
3017 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
3018 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
3019 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
3020 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
3021 0 : s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
3022 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
3023 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s4, _mm_setzero_si128()));
3024 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
3025 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s6, _mm_setzero_si128()));
3026 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
3027 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s4, _mm_setzero_si128()));
3028 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
3029 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s6, _mm_setzero_si128()));
3030 0 : k = leftover;
3031 0 : while (k > 0) {
3032 0 : for (l = 0; l < 4 && k; l++, k--) {
3033 0 : temSum1 = _mm_extract_epi32(s0, 0);
3034 0 : s0 = _mm_srli_si128(s0, 4);
3035 0 : if (temSum1 < lowSum) {
3036 0 : lowSum = temSum1;
3037 0 : xBest = (int16_t)(j + leftover - k);
3038 0 : yBest = i;
3039 : }
3040 : }
3041 0 : s0 = s1;
3042 : }
3043 : }
3044 : }
3045 : }
3046 0 : ref += src_stride_raw;
3047 : }
3048 : }
3049 0 : break;
3050 :
3051 31598 : case 64:
3052 31598 : if (block_height <= 32) {
3053 0 : for (i = 0; i < search_area_height; i++) {
3054 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
3055 0 : pSrc = src;
3056 0 : pRef = ref + j;
3057 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
3058 0 : for (k = 0; k < block_height; k++) {
3059 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
3060 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
3061 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
3062 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
3063 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
3064 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
3065 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
3066 0 : ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
3067 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
3068 0 : ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
3069 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
3070 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
3071 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
3072 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
3073 0 : pSrc += src_stride;
3074 0 : pRef += ref_stride;
3075 : }
3076 0 : ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
3077 0 : s3 = _mm256_castsi256_si128(ss7);
3078 0 : s4 = _mm256_extracti128_si256(ss7, 1);
3079 0 : s0 = _mm_adds_epu16(s3, s4);
3080 0 : s0 = _mm_minpos_epu16(s0);
3081 0 : temSum1 = _mm_extract_epi16(s0, 0);
3082 0 : if (temSum1 < lowSum) {
3083 0 : if (temSum1 != 0xFFFF) { // no overflow
3084 0 : lowSum = temSum1;
3085 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
3086 0 : yBest = i;
3087 : }
3088 : else {
3089 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
3090 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
3091 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
3092 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
3093 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
3094 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
3095 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
3096 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
3097 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
3098 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
3099 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
3100 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
3101 0 : UPDATE_BEST(s0, 0, 0);
3102 0 : UPDATE_BEST(s0, 1, 0);
3103 0 : UPDATE_BEST(s0, 2, 0);
3104 0 : UPDATE_BEST(s0, 3, 0);
3105 0 : UPDATE_BEST(s3, 0, 4);
3106 0 : UPDATE_BEST(s3, 1, 4);
3107 0 : UPDATE_BEST(s3, 2, 4);
3108 0 : UPDATE_BEST(s3, 3, 4);
3109 : }
3110 : }
3111 : }
3112 :
3113 0 : if (leftover) {
3114 0 : pSrc = src;
3115 0 : pRef = ref + j;
3116 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
3117 0 : for (k = 0; k < block_height; k++) {
3118 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
3119 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
3120 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
3121 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
3122 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
3123 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
3124 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
3125 0 : ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
3126 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
3127 0 : ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
3128 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
3129 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
3130 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
3131 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
3132 0 : pSrc += src_stride;
3133 0 : pRef += ref_stride;
3134 : }
3135 0 : ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
3136 0 : s3 = _mm256_castsi256_si128(ss7);
3137 0 : s4 = _mm256_extracti128_si256(ss7, 1);
3138 0 : s0 = _mm_adds_epu16(s3, s4);
3139 0 : s0 = _mm_or_si128(s0, s8);
3140 0 : s0 = _mm_minpos_epu16(s0);
3141 0 : temSum1 = _mm_extract_epi16(s0, 0);
3142 0 : if (temSum1 < lowSum) {
3143 0 : if (temSum1 != 0xFFFF) { // no overflow
3144 0 : lowSum = temSum1;
3145 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
3146 0 : yBest = i;
3147 : }
3148 : else {
3149 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
3150 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
3151 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
3152 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
3153 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
3154 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
3155 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
3156 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
3157 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
3158 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
3159 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
3160 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
3161 0 : k = leftover;
3162 0 : while (k > 0) {
3163 0 : for (l = 0; l < 4 && k; l++, k--) {
3164 0 : temSum1 = _mm_extract_epi32(s0, 0);
3165 0 : s0 = _mm_srli_si128(s0, 4);
3166 0 : if (temSum1 < lowSum) {
3167 0 : lowSum = temSum1;
3168 0 : xBest = (int16_t)(j + leftover - k);
3169 0 : yBest = i;
3170 : }
3171 : }
3172 0 : s0 = s3;
3173 : }
3174 : }
3175 : }
3176 : }
3177 0 : ref += src_stride_raw;
3178 : }
3179 : }
3180 : else {
3181 : __m256i ss9, ss10;
3182 177124 : for (i = 0; i < search_area_height; i++) {
3183 290987 : for (j = 0; j <= search_area_width - 8; j += 8) {
3184 145461 : pSrc = src;
3185 145461 : pRef = ref + j;
3186 145461 : ss3 = ss4 = ss5 = ss6 = ss7 = ss8 = ss9 = ss10 = _mm256_setzero_si256();
3187 9362210 : for (k = 0; k < block_height; k++) {
3188 9216750 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
3189 18433500 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
3190 9216750 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
3191 9216750 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
3192 9216750 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
3193 9216750 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
3194 9216750 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
3195 9216750 : ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
3196 9216750 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
3197 9216750 : ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
3198 9216750 : ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss0, ss2, 0));
3199 9216750 : ss8 = _mm256_adds_epu16(ss8, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
3200 9216750 : ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
3201 9216750 : ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
3202 9216750 : pSrc += src_stride;
3203 9216750 : pRef += ref_stride;
3204 : }
3205 436383 : ss0 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
3206 436383 : ss0 = _mm256_adds_epu16(ss0, _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss8), _mm256_adds_epu16(ss9, ss10)));
3207 436383 : s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
3208 145461 : s0 = _mm_minpos_epu16(s0);
3209 145461 : temSum1 = _mm_extract_epi16(s0, 0);
3210 145461 : if (temSum1 < lowSum) {
3211 101377 : if (temSum1 != 0xFFFF) { // no overflow
3212 72451 : lowSum = temSum1;
3213 72451 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
3214 72451 : yBest = i;
3215 : }
3216 : else {
3217 318186 : ss0 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss3, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss5, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256())));
3218 318186 : ss1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss3, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss5, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256())));
3219 318186 : ss2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss7, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss9, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss10, _mm256_setzero_si256())));
3220 318186 : ss3 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss7, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss9, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss10, _mm256_setzero_si256())));
3221 28926 : ss0 = _mm256_add_epi32(ss0, ss2);
3222 28926 : ss1 = _mm256_add_epi32(ss1, ss3);
3223 57852 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
3224 57852 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss1), _mm256_extracti128_si256(ss1, 1));
3225 28926 : UPDATE_BEST(s0, 0, 0);
3226 28926 : UPDATE_BEST(s0, 1, 0);
3227 28926 : UPDATE_BEST(s0, 2, 0);
3228 28926 : UPDATE_BEST(s0, 3, 0);
3229 28926 : UPDATE_BEST(s3, 0, 4);
3230 28926 : UPDATE_BEST(s3, 1, 4);
3231 28926 : UPDATE_BEST(s3, 2, 4);
3232 28926 : UPDATE_BEST(s3, 3, 4);
3233 : }
3234 : }
3235 : }
3236 :
3237 145526 : if (leftover) {
3238 68 : pSrc = src;
3239 68 : pRef = ref + j;
3240 68 : ss3 = ss4 = ss5 = ss6 = ss7 = ss8 = ss9 = ss10 = _mm256_setzero_si256();
3241 4420 : for (k = 0; k < block_height; k++) {
3242 4352 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
3243 8704 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
3244 4352 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
3245 4352 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
3246 4352 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
3247 4352 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
3248 4352 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
3249 4352 : ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
3250 4352 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
3251 4352 : ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
3252 4352 : ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss0, ss2, 0));
3253 4352 : ss8 = _mm256_adds_epu16(ss8, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
3254 4352 : ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
3255 4352 : ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
3256 4352 : pSrc += src_stride;
3257 4352 : pRef += ref_stride;
3258 : }
3259 204 : ss0 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
3260 204 : ss0 = _mm256_adds_epu16(ss0, _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss8), _mm256_adds_epu16(ss9, ss10)));
3261 204 : s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
3262 68 : s0 = _mm_or_si128(s0, s8);
3263 68 : s0 = _mm_minpos_epu16(s0);
3264 68 : temSum1 = _mm_extract_epi16(s0, 0);
3265 68 : if (temSum1 < lowSum) {
3266 68 : if (temSum1 != 0xFFFF) { // no overflow
3267 0 : lowSum = temSum1;
3268 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
3269 0 : yBest = i;
3270 : }
3271 : else {
3272 748 : ss0 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss3, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss5, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256())));
3273 748 : ss1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss3, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss5, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256())));
3274 748 : ss2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss7, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss9, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss10, _mm256_setzero_si256())));
3275 748 : ss3 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss7, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss9, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss10, _mm256_setzero_si256())));
3276 68 : ss0 = _mm256_add_epi32(ss0, ss2);
3277 68 : ss1 = _mm256_add_epi32(ss1, ss3);
3278 136 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
3279 136 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss1), _mm256_extracti128_si256(ss1, 1));
3280 68 : k = leftover;
3281 204 : while (k > 0) {
3282 544 : for (l = 0; l < 4 && k; l++, k--) {
3283 408 : temSum1 = _mm_extract_epi32(s0, 0);
3284 408 : s0 = _mm_srli_si128(s0, 4);
3285 408 : if (temSum1 < lowSum) {
3286 99 : lowSum = temSum1;
3287 99 : xBest = (int16_t)(j + leftover - k);
3288 99 : yBest = i;
3289 : }
3290 : }
3291 136 : s0 = s3;
3292 : }
3293 : }
3294 : }
3295 : }
3296 145526 : ref += src_stride_raw;
3297 : }
3298 : }
3299 31598 : break;
3300 :
3301 0 : default:
3302 : assert(0);
3303 0 : break;
3304 : }
3305 :
3306 63181 : *best_sad = lowSum;
3307 63181 : *x_search_center = xBest;
3308 63181 : *y_search_center = yBest;
3309 63181 : }
3310 :
3311 : /*******************************************************************************
3312 : * Requirement: height % 4 = 0
3313 : *******************************************************************************/
3314 : SIMD_INLINE uint32_t compute4x_m_sad_avx2(
3315 : const uint8_t *src, // input parameter, source samples Ptr
3316 : uint32_t src_stride, // input parameter, source stride
3317 : const uint8_t *ref, // input parameter, reference samples Ptr
3318 : uint32_t ref_stride, // input parameter, reference stride
3319 : uint32_t height) // input parameter, block height (M)
3320 : {
3321 10956100 : uint32_t y = height;
3322 : __m128i xmm0;
3323 10956100 : __m256i ymm = _mm256_setzero_si256();
3324 :
3325 : do {
3326 21261100 : const __m256i src0123 = load_u8_4x4_avx2(src, src_stride);
3327 21261200 : const __m256i ref0123 = load_u8_4x4_avx2(ref, ref_stride);
3328 21261500 : ymm = _mm256_add_epi32(ymm, _mm256_sad_epu8(src0123, ref0123));
3329 21261500 : src += src_stride << 2;
3330 21261500 : ref += ref_stride << 2;
3331 21261500 : y -= 4;
3332 21261500 : } while (y);
3333 :
3334 21913000 : xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm),
3335 10956500 : _mm256_extracti128_si256(ymm, 1));
3336 :
3337 10956500 : return (uint32_t)_mm_cvtsi128_si32(xmm0);
3338 : }
3339 :
3340 10956100 : uint32_t eb_compute4x_m_sad_avx2_intrin(
3341 : const uint8_t *src, // input parameter, source samples Ptr
3342 : uint32_t src_stride, // input parameter, source stride
3343 : const uint8_t *ref, // input parameter, reference samples Ptr
3344 : uint32_t ref_stride, // input parameter, reference stride
3345 : uint32_t height, // input parameter, block height (M)
3346 : uint32_t width) // input parameter, block width (N)
3347 : {
3348 : (void)width;
3349 10956500 : return compute4x_m_sad_avx2(src, src_stride, ref, ref_stride, height);
3350 : }
3351 :
3352 137181000 : static INLINE uint32_t sad_final_avx2(const __m256i sad) {
3353 137181000 : const __m128i sad_lo = _mm256_castsi256_si128(sad);
3354 137181000 : const __m128i sad_hi = _mm256_extracti128_si256(sad, 1);
3355 137181000 : const __m128i sum = _mm_add_epi32(sad_lo, sad_hi);
3356 137181000 : const __m128i sum_hi = _mm_srli_si128(sum, 8);
3357 137181000 : const __m128i d = _mm_add_epi32(sum, sum_hi);
3358 137181000 : return (uint32_t)_mm_cvtsi128_si32(d);
3359 : }
3360 :
3361 : /*******************************************************************************
3362 : * Requirement: height % 4 = 0
3363 : *******************************************************************************/
3364 : SIMD_INLINE uint32_t compute8x_m_sad_avx2(
3365 : const uint8_t *src, // input parameter, source samples Ptr
3366 : uint32_t src_stride, // input parameter, source stride
3367 : const uint8_t *ref, // input parameter, reference samples Ptr
3368 : uint32_t ref_stride, // input parameter, reference stride
3369 : uint32_t height) // input parameter, block height (M)
3370 : {
3371 64160600 : uint32_t y = height;
3372 64160600 : __m256i sad = _mm256_setzero_si256();
3373 :
3374 : do {
3375 210800000 : const __m256i src0123 = load_u8_8x4_avx2(src, src_stride);
3376 210824000 : const __m256i ref0123 = load_u8_8x4_avx2(ref, ref_stride);
3377 210800000 : sad = _mm256_add_epi32(sad, _mm256_sad_epu8(src0123, ref0123));
3378 210800000 : src += src_stride << 2;
3379 210800000 : ref += ref_stride << 2;
3380 210800000 : y -= 4;
3381 210800000 : } while (y);
3382 :
3383 64159900 : return sad_final_avx2(sad);
3384 : }
3385 :
3386 64160600 : uint32_t eb_compute8x_m_sad_avx2_intrin(
3387 : const uint8_t *src, // input parameter, source samples Ptr
3388 : uint32_t src_stride, // input parameter, source stride
3389 : const uint8_t *ref, // input parameter, reference samples Ptr
3390 : uint32_t ref_stride, // input parameter, reference stride
3391 : uint32_t height, // input parameter, block height (M)
3392 : uint32_t width) // input parameter, block width (N)
3393 : {
3394 : (void)width;
3395 64181900 : return compute8x_m_sad_avx2(src, src_stride, ref, ref_stride, height);
3396 : }
3397 :
3398 398655000 : static INLINE void compute16_sad_avx2(const uint8_t *const src,
3399 : const uint32_t src_stride, const uint8_t *const ref,
3400 : const uint32_t ref_stride, __m256i *const sum)
3401 : {
3402 398655000 : const __m256i s = loadu_u8_16x2_avx2(src, src_stride);
3403 398691000 : const __m256i r = loadu_u8_16x2_avx2(ref, ref_stride);
3404 398626000 : const __m256i sad = _mm256_sad_epu8(s, r);
3405 398626000 : *sum = _mm256_add_epi32(*sum, sad);
3406 398626000 : }
3407 :
3408 869164000 : static INLINE void compute32_sad_avx2(const uint8_t *const src,
3409 : const uint8_t *const ref, __m256i *const sum)
3410 : {
3411 869164000 : const __m256i s = _mm256_loadu_si256((__m256i *)src);
3412 869164000 : const __m256i r = _mm256_loadu_si256((__m256i *)ref);
3413 869164000 : const __m256i sad = _mm256_sad_epu8(s, r);
3414 869164000 : *sum = _mm256_add_epi32(*sum, sad);
3415 869164000 : }
3416 :
3417 : /*******************************************************************************
3418 : * Requirement: height % 4 = 0
3419 : *******************************************************************************/
3420 : SIMD_INLINE uint32_t compute16x_m_sad_avx2(
3421 : const uint8_t *src, // input parameter, source samples Ptr
3422 : uint32_t src_stride, // input parameter, source stride
3423 : const uint8_t *ref, // input parameter, reference samples Ptr
3424 : uint32_t ref_stride, // input parameter, reference stride
3425 : uint32_t height) // input parameter, block height (M)
3426 : {
3427 45180700 : uint32_t y = height;
3428 45180700 : __m256i sad = _mm256_setzero_si256();
3429 :
3430 : do {
3431 199715000 : compute16_sad_avx2(src + 0 * src_stride, src_stride,
3432 : ref + 0 * ref_stride, ref_stride, &sad);
3433 199785000 : compute16_sad_avx2(src + 2 * src_stride, src_stride,
3434 199785000 : ref + 2 * ref_stride, ref_stride, &sad);
3435 199718000 : src += src_stride << 2;
3436 199718000 : ref += ref_stride << 2;
3437 199718000 : y -= 4;
3438 199718000 : } while (y);
3439 :
3440 45183100 : return sad_final_avx2(sad);
3441 : }
3442 :
3443 45180700 : uint32_t eb_compute16x_m_sad_avx2_intrin(
3444 : const uint8_t *src, // input parameter, source samples Ptr
3445 : uint32_t src_stride, // input parameter, source stride
3446 : const uint8_t *ref, // input parameter, reference samples Ptr
3447 : uint32_t ref_stride, // input parameter, reference stride
3448 : uint32_t height, // input parameter, block height (M)
3449 : uint32_t width) // input parameter, block width (N)
3450 : {
3451 : (void)width;
3452 45191800 : return compute16x_m_sad_avx2(src, src_stride, ref, ref_stride, height);
3453 : }
3454 :
3455 : /*******************************************************************************
3456 : * Requirement: height % 2 = 0
3457 : *******************************************************************************/
3458 0 : uint32_t eb_compute24x_m_sad_avx2_intrin(
3459 : const uint8_t *src, // input parameter, source samples Ptr
3460 : uint32_t src_stride, // input parameter, source stride
3461 : const uint8_t *ref, // input parameter, reference samples Ptr
3462 : uint32_t ref_stride, // input parameter, reference stride
3463 : uint32_t height, // input parameter, block height (M)
3464 : uint32_t width) // input parameter, block width (N)
3465 : {
3466 0 : uint32_t y = height;
3467 0 : __m256i sad = _mm256_setzero_si256();
3468 :
3469 : (void)width;
3470 :
3471 : do {
3472 0 : compute32_sad_avx2(src + 0 * src_stride, ref + 0 * ref_stride, &sad);
3473 0 : compute32_sad_avx2(src + 1 * src_stride, ref + 1 * ref_stride, &sad);
3474 0 : src += src_stride << 1;
3475 0 : ref += ref_stride << 1;
3476 0 : y -= 2;
3477 0 : } while (y);
3478 :
3479 0 : const __m128i sad_lo = _mm256_castsi256_si128(sad);
3480 0 : const __m128i sad_hi = _mm256_extracti128_si256(sad, 1);
3481 0 : const __m128i sum_lo = _mm_add_epi32(sad_lo, _mm_srli_si128(sad_lo, 8));
3482 0 : const __m128i sum = _mm_add_epi32(sum_lo, sad_hi);
3483 :
3484 0 : return (uint32_t)_mm_cvtsi128_si32(sum);
3485 : }
3486 :
3487 : /*******************************************************************************
3488 : * Requirement: height % 2 = 0
3489 : *******************************************************************************/
3490 22134600 : static INLINE uint32_t compute32x_m_sad_avx2(
3491 : const uint8_t *src, // input parameter, source samples Ptr
3492 : uint32_t src_stride, // input parameter, source stride
3493 : const uint8_t *ref, // input parameter, reference samples Ptr
3494 : uint32_t ref_stride, // input parameter, reference stride
3495 : uint32_t height) // input parameter, block height (M)
3496 : {
3497 22134600 : uint32_t y = height;
3498 22134600 : __m256i sad = _mm256_setzero_si256();
3499 :
3500 : do {
3501 242598000 : compute32_sad_avx2(src + 0 * src_stride, ref + 0 * ref_stride, &sad);
3502 242640000 : compute32_sad_avx2(src + 1 * src_stride, ref + 1 * ref_stride, &sad);
3503 242600000 : src += src_stride << 1;
3504 242600000 : ref += ref_stride << 1;
3505 242600000 : y -= 2;
3506 242600000 : } while (y);
3507 :
3508 22135800 : return sad_final_avx2(sad);
3509 : }
3510 :
3511 22135400 : uint32_t eb_compute32x_m_sad_avx2_intrin(
3512 : const uint8_t *src, // input parameter, source samples Ptr
3513 : uint32_t src_stride, // input parameter, source stride
3514 : const uint8_t *ref, // input parameter, reference samples Ptr
3515 : uint32_t ref_stride, // input parameter, reference stride
3516 : uint32_t height, // input parameter, block height (M)
3517 : uint32_t width) // input parameter, block width (N)
3518 : {
3519 : (void)width;
3520 22135400 : return compute32x_m_sad_avx2(src, src_stride, ref, ref_stride, height);
3521 : }
3522 :
3523 : /*******************************************************************************
3524 : * Requirement: height % 2 = 0
3525 : *******************************************************************************/
3526 0 : uint32_t eb_compute48x_m_sad_avx2_intrin(
3527 : const uint8_t *src, // input parameter, source samples Ptr
3528 : uint32_t src_stride, // input parameter, source stride
3529 : const uint8_t *ref, // input parameter, reference samples Ptr
3530 : uint32_t ref_stride, // input parameter, reference stride
3531 : uint32_t height, // input parameter, block height (M)
3532 : uint32_t width) // input parameter, block width (N)
3533 : {
3534 0 : uint32_t y = height;
3535 0 : __m256i sad = _mm256_setzero_si256();
3536 :
3537 : (void)width;
3538 :
3539 : do {
3540 0 : compute32_sad_avx2(src + 0 * src_stride, ref + 0 * ref_stride, &sad);
3541 0 : compute32_sad_avx2(src + 1 * src_stride, ref + 1 * ref_stride, &sad);
3542 0 : compute16_sad_avx2(src + 32, src_stride, ref + 32, ref_stride, &sad);
3543 0 : src += src_stride << 1;
3544 0 : ref += ref_stride << 1;
3545 0 : y -= 2;
3546 0 : } while (y);
3547 :
3548 0 : return sad_final_avx2(sad);
3549 : }
3550 :
3551 : /*******************************************************************************
3552 : * Requirement: height % 2 = 0
3553 : *******************************************************************************/
3554 : SIMD_INLINE uint32_t compute64x_m_sad_avx2(
3555 : const uint8_t *src, // input parameter, source samples Ptr
3556 : uint32_t src_stride, // input parameter, source stride
3557 : const uint8_t *ref, // input parameter, reference samples Ptr
3558 : uint32_t ref_stride, // input parameter, reference stride
3559 : uint32_t height) // input parameter, block height (M)
3560 : {
3561 5935820 : uint32_t y = height;
3562 5935820 : __m256i sad = _mm256_setzero_si256();
3563 :
3564 : do {
3565 96917400 : compute32_sad_avx2(src, ref, &sad);
3566 96967000 : compute32_sad_avx2(src + 32, ref + 32, &sad);
3567 96932200 : compute32_sad_avx2(src + src_stride, ref + ref_stride, &sad);
3568 96930600 : compute32_sad_avx2(src + src_stride + 32, ref + ref_stride + 32, &sad);
3569 96917500 : src += src_stride << 1;
3570 96917500 : ref += ref_stride << 1;
3571 96917500 : y -= 2;
3572 96917500 : } while (y);
3573 :
3574 5935940 : return sad_final_avx2(sad);
3575 : }
3576 :
3577 : SIMD_INLINE uint32_t compute128x_m_sad_avx2(
3578 : const uint8_t *src, // input parameter, source samples Ptr
3579 : uint32_t src_stride, // input parameter, source stride
3580 : const uint8_t *ref, // input parameter, reference samples Ptr
3581 : uint32_t ref_stride, // input parameter, reference stride
3582 : uint32_t height) // input parameter, block height (M)
3583 : {
3584 0 : uint32_t y = height;
3585 0 : __m256i sad = _mm256_setzero_si256();
3586 :
3587 : do {
3588 0 : compute32_sad_avx2(src + 0 * 32, ref + 0 * 32, &sad);
3589 0 : compute32_sad_avx2(src + 1 * 32, ref + 1 * 32, &sad);
3590 0 : compute32_sad_avx2(src + 2 * 32, ref + 2 * 32, &sad);
3591 0 : compute32_sad_avx2(src + 3 * 32, ref + 3 * 32, &sad);
3592 0 : src += src_stride;
3593 0 : ref += ref_stride;
3594 0 : } while (--y);
3595 :
3596 0 : return sad_final_avx2(sad);
3597 : }
3598 :
3599 5935820 : uint32_t eb_compute64x_m_sad_avx2_intrin(
3600 : const uint8_t *src, // input parameter, source samples Ptr
3601 : uint32_t src_stride, // input parameter, source stride
3602 : const uint8_t *ref, // input parameter, reference samples Ptr
3603 : uint32_t ref_stride, // input parameter, reference stride
3604 : uint32_t height, // input parameter, block height (M)
3605 : uint32_t width) // input parameter, block width (N)
3606 : {
3607 : (void)width;
3608 5935980 : return compute64x_m_sad_avx2(src, src_stride, ref, ref_stride, height);
3609 : }
3610 :
3611 27775300 : static INLINE void sad_eight_8x2x2_avx2(const uint8_t *src,
3612 : const uint32_t src_stride, const uint8_t *ref, const uint32_t ref_stride,
3613 : __m256i d[2])
3614 : {
3615 27775300 : const __m256i s = loadu_u8_16x2_avx2(src, src_stride);
3616 25982200 : const __m256i r0 = loadu_u8_16x2_avx2(ref + 0, ref_stride);
3617 25043400 : const __m256i r1 = loadu_u8_16x2_avx2(ref + 8, ref_stride);
3618 23762700 : d[0] = _mm256_adds_epu16(d[0], _mm256_mpsadbw_epu8(r0, s, 0x00));
3619 23762700 : d[0] = _mm256_adds_epu16(d[0], _mm256_mpsadbw_epu8(r0, s, 0x2D)); // 101 101
3620 23762700 : d[1] = _mm256_adds_epu16(d[1], _mm256_mpsadbw_epu8(r1, s, 0x12)); // 010 010
3621 23762700 : d[1] = _mm256_adds_epu16(d[1], _mm256_mpsadbw_epu8(r1, s, 0x3F)); // 111 111
3622 23762700 : }
3623 :
3624 : /*
3625 : NOTE: Slower than avx2. Abandoned.
3626 : static INLINE void sad_eight_8x2x2_avx512(const uint8_t *const src,
3627 : const uint32_t src_stride, const uint8_t *const ref,
3628 : const uint32_t ref_stride, __m512i *const d)
3629 : {
3630 : const __m512i c0 =
3631 : _mm512_setr_epi32(0, 0, 0, 0, 2, 2, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6);
3632 : const __m512i c1 =
3633 : _mm512_setr_epi32(1, 1, 1, 1, 3, 3, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7);
3634 : const __m512i c2 = _mm512_setr_epi64(0, 1, 1, 2, 4, 5, 5, 6);
3635 :
3636 : const __m256i s01 = loadu_u8_16x2_avx2(src, src_stride);
3637 : const __m512i s = _mm512_castsi256_si512(s01);
3638 : const __m512i ss0 = _mm512_permutexvar_epi32(c0, s);
3639 : const __m512i ss1 = _mm512_permutexvar_epi32(c1, s);
3640 :
3641 : const __m256i r0 = _mm256_loadu_si256((__m256i*)ref);
3642 : const __m256i r1 = _mm256_loadu_si256((__m256i*)(ref + ref_stride));
3643 : const __m512i r = _mm512_inserti64x4(_mm512_castsi256_si512(r0), r1, 1);
3644 : const __m512i rr0 = _mm512_permutexvar_epi64(c2, r);
3645 :
3646 : *d = _mm512_adds_epu16(*d, _mm512_dbsad_epu8(ss0, rr0, 0x94)); //10 01 01 00
3647 : *d = _mm512_adds_epu16(*d, _mm512_dbsad_epu8(ss1, rr0, 0xE9)); //11 10 10 01
3648 : }
3649 :
3650 : Usage:
3651 : s_512 = _mm512_setzero_si512();
3652 : sad_eight_8x2x2_avx512(src + 0 * src_stride, 8 * src_stride,
3653 : ref + 0 * ref_stride, 8 * ref_stride, &s_512);
3654 : sad_eight_8x2x2_avx512(src + 2 * src_stride, 8 * src_stride,
3655 : ref + 2 * ref_stride, 8 * ref_stride, &s_512);
3656 : sad_eight_8x2x2_avx512(src + 4 * src_stride, 8 * src_stride,
3657 : ref + 4 * ref_stride, 8 * ref_stride, &s_512);
3658 : sad_eight_8x2x2_avx512(src + 6 * src_stride, 8 * src_stride,
3659 : ref + 6 * ref_stride, 8 * ref_stride, &s_512);
3660 : sad_eight_8x2x2_avx512(src + 1 * src_stride, 8 * src_stride,
3661 : ref + 1 * ref_stride, 8 * ref_stride, &s_512);
3662 : sad_eight_8x2x2_avx512(src + 3 * src_stride, 8 * src_stride,
3663 : ref + 3 * ref_stride, 8 * ref_stride, &s_512);
3664 : sad_eight_8x2x2_avx512(src + 5 * src_stride, 8 * src_stride,
3665 : ref + 5 * ref_stride, 8 * ref_stride, &s_512);
3666 : sad_eight_8x2x2_avx512(src + 7 * src_stride, 8 * src_stride,
3667 : ref + 7 * ref_stride, 8 * ref_stride, &s_512);
3668 : s_256[0] = _mm512_castsi512_si256(s_512);
3669 : s_256[1] = _mm512_extracti64x4_epi64(s_512, 1);
3670 : */
3671 :
3672 : /*******************************************************************************
3673 : * Requirement: p_best_sad8x8[i] must be less than 0x7FFFFFFF because signed comparison is used.
3674 : *******************************************************************************/
3675 12104600 : void get_eight_horizontal_search_point_results_8x8_16x16_pu_avx2_intrin(
3676 : uint8_t *src,
3677 : uint32_t src_stride,
3678 : uint8_t *ref,
3679 : uint32_t ref_stride,
3680 : uint32_t *p_best_sad8x8,
3681 : uint32_t *p_best_mv8x8,
3682 : uint32_t *p_best_sad16x16,
3683 : uint32_t *p_best_mv16x16,
3684 : uint32_t mv,
3685 : uint16_t *p_sad16x16,
3686 : EbBool sub_sad)
3687 : {
3688 : __m128i s_128[4], s16_128, best_sad_128, best_mv_128, mv_128;
3689 : __m256i s_256[2];
3690 :
3691 : /*
3692 : ------------------------------------- -----------------------------------
3693 : | 8x8_00 | 8x8_01 | 8x8_04 | 8x8_05 | 8x8_16 | 8x8_17 | 8x8_20 | 8x8_21 |
3694 : ------------------------------------- -----------------------------------
3695 : | 8x8_02 | 8x8_03 | 8x8_06 | 8x8_07 | 8x8_18 | 8x8_19 | 8x8_22 | 8x8_23 |
3696 : ----------------------- ----------- ---------------------- ----------
3697 : | 8x8_08 | 8x8_09 | 8x8_12 | 8x8_13 | 8x8_24 | 8x8_25 | 8x8_29 | 8x8_29 |
3698 : ---------------------- ----------- --------------------- ----------
3699 : | 8x8_10 | 8x8_11 | 8x8_14 | 8x8_15 | 8x8_26 | 8x8_27 | 8x8_30 | 8x8_31 |
3700 : ------------------------------------- -----------------------------------
3701 :
3702 : ------------------------------------- -----------------------------------
3703 : | 8x8_32 | 8x8_33 | 8x8_36 | 8x8_37 | 8x8_48 | 8x8_49 | 8x8_52 | 8x8_53 |
3704 : ------------------------------------- -----------------------------------
3705 : | 8x8_34 | 8x8_35 | 8x8_38 | 8x8_39 | 8x8_50 | 8x8_51 | 8x8_54 | 8x8_55 |
3706 : ----------------------- ----------- ---------------------- ----------
3707 : | 8x8_40 | 8x8_41 | 8x8_44 | 8x8_45 | 8x8_56 | 8x8_57 | 8x8_60 | 8x8_61 |
3708 : ---------------------- ----------- --------------------- ----------
3709 : | 8x8_42 | 8x8_43 | 8x8_46 | 8x8_48 | 8x8_58 | 8x8_59 | 8x8_62 | 8x8_63 |
3710 : ------------------------------------- -----------------------------------
3711 : */
3712 :
3713 : /*
3714 : ---------------------- ----------------------
3715 : | 16x16_0 | 16x16_1 | 16x16_4 | 16x16_5 |
3716 : ---------------------- ----------------------
3717 : | 16x16_2 | 16x16_3 | 16x16_6 | 16x16_7 |
3718 : ----------------------- -----------------------
3719 : | 16x16_8 | 16x16_9 | 16x16_12 | 16x16_13 |
3720 : ---------------------- ----------------------
3721 : | 16x16_10 | 16x16_11 | 16x16_14 | 16x16_15 |
3722 : ----------------------- -----------------------
3723 : */
3724 :
3725 : // 8x8_0, 8x8_1, 8x8_2 & 8x8_3
3726 12104600 : s_256[0] = s_256[1] = _mm256_setzero_si256();
3727 12104600 : sad_eight_8x2x2_avx2(src + 0 * src_stride, 8 * src_stride, ref + 0 * ref_stride, 8 * ref_stride, s_256);
3728 10196500 : sad_eight_8x2x2_avx2(src + 2 * src_stride, 8 * src_stride, ref + 2 * ref_stride, 8 * ref_stride, s_256);
3729 9905510 : sad_eight_8x2x2_avx2(src + 4 * src_stride, 8 * src_stride, ref + 4 * ref_stride, 8 * ref_stride, s_256);
3730 9851360 : sad_eight_8x2x2_avx2(src + 6 * src_stride, 8 * src_stride, ref + 6 * ref_stride, 8 * ref_stride, s_256);
3731 :
3732 : //16x16
3733 9961550 : if (sub_sad) {
3734 9961550 : s_256[0] = _mm256_slli_epi16(s_256[0], 1);
3735 19923100 : s_256[1] = _mm256_slli_epi16(s_256[1], 1);
3736 : }
3737 : else {
3738 : // 8x8_0, 8x8_1, 8x8_2 & 8x8_3
3739 0 : sad_eight_8x2x2_avx2(src + 1 * src_stride, 8 * src_stride, ref + 1 * ref_stride, 8 * ref_stride, s_256);
3740 0 : sad_eight_8x2x2_avx2(src + 3 * src_stride, 8 * src_stride, ref + 3 * ref_stride, 8 * ref_stride, s_256);
3741 0 : sad_eight_8x2x2_avx2(src + 5 * src_stride, 8 * src_stride, ref + 5 * ref_stride, 8 * ref_stride, s_256);
3742 0 : sad_eight_8x2x2_avx2(src + 7 * src_stride, 8 * src_stride, ref + 7 * ref_stride, 8 * ref_stride, s_256);
3743 : }
3744 :
3745 10018000 : s_128[0] = _mm256_castsi256_si128(s_256[0]);
3746 10018000 : s_128[1] = _mm256_castsi256_si128(s_256[1]);
3747 10018000 : s_128[2] = _mm256_extracti128_si256(s_256[0], 1);
3748 10018000 : s_128[3] = _mm256_extracti128_si256(s_256[1], 1);
3749 10018000 : s16_128 = _mm_adds_epu16(s_128[0], s_128[1]);
3750 10018000 : s16_128 = _mm_adds_epu16(s16_128, s_128[2]);
3751 20035900 : s16_128 = _mm_adds_epu16(s16_128, s_128[3]);
3752 :
3753 : //sotore the 8 SADs(16x16 SADs)
3754 : _mm_store_si128((__m128i*)p_sad16x16, s16_128);
3755 :
3756 : //find the best for 16x16
3757 10018000 : const __m128i minpos16 = _mm_minpos_epu16(s16_128);
3758 10018000 : const uint32_t sad = _mm_extract_epi16(minpos16, 0);
3759 :
3760 10018000 : if (sad < p_best_sad16x16[0]) {
3761 970301 : const int32_t best_mv = 4 * _mm_extract_epi16(minpos16, 1);
3762 970301 : const int16_t xMv = _MVXT(mv) + (int16_t)best_mv;
3763 970301 : const int16_t yMv = _MVYT(mv);
3764 970301 : p_best_sad16x16[0] = sad;
3765 970301 : *p_best_mv16x16 = ((uint16_t)yMv << 16) | ((uint16_t)xMv);
3766 : }
3767 :
3768 : //find the best for 8x8_0, 8x8_1, 8x8_2 & 8x8_3
3769 10018000 : s_128[0] = _mm_minpos_epu16(s_128[0]);
3770 10018000 : s_128[1] = _mm_minpos_epu16(s_128[1]);
3771 10018000 : s_128[2] = _mm_minpos_epu16(s_128[2]);
3772 10018000 : s_128[3] = _mm_minpos_epu16(s_128[3]);
3773 10018000 : s_128[0] = _mm_unpacklo_epi16(s_128[0], s_128[1]);
3774 10018000 : s_128[2] = _mm_unpacklo_epi16(s_128[2], s_128[3]);
3775 20035900 : s_128[0] = _mm_unpacklo_epi32(s_128[0], s_128[2]);
3776 20035900 : s_128[1] = _mm_unpackhi_epi16(s_128[0], _mm_setzero_si128());
3777 10018000 : const __m128i sad_128 = _mm_unpacklo_epi16(s_128[0], _mm_setzero_si128());
3778 20035900 : const __m128i offset_128 = _mm_slli_epi16(s_128[1], 2);
3779 :
3780 10018000 : best_sad_128 = _mm_loadu_si128((__m128i*)p_best_sad8x8);
3781 10018000 : const __m128i mask = _mm_cmpgt_epi32(best_sad_128, sad_128);
3782 10018000 : best_sad_128 = _mm_min_epu32(sad_128, best_sad_128);
3783 : _mm_storeu_si128((__m128i*)p_best_sad8x8, best_sad_128);
3784 :
3785 20035900 : mv_128 = _mm_set1_epi32(mv);
3786 10018000 : mv_128 = _mm_add_epi16(mv_128, offset_128);
3787 10018000 : mv_128 = _mm_and_si128(mv_128, mask);
3788 10018000 : best_mv_128 = _mm_loadu_si128((__m128i*)p_best_mv8x8);
3789 10018000 : best_mv_128 = _mm_andnot_si128(mask, best_mv_128);
3790 10018000 : best_mv_128 = _mm_or_si128(best_mv_128, mv_128);
3791 : _mm_storeu_si128((__m128i*)p_best_mv8x8, best_mv_128);
3792 10018000 : }
3793 :
3794 3140520 : static INLINE __m256i add_4_sad_avx2(
3795 : const uint16_t *const p_sad16x16)
3796 : {
3797 3140520 : const __m128i s0 = _mm_loadu_si128((__m128i*)(p_sad16x16 + 0 * 8));
3798 3140520 : const __m128i s1 = _mm_loadu_si128((__m128i*)(p_sad16x16 + 1 * 8));
3799 3140520 : const __m128i s2 = _mm_loadu_si128((__m128i*)(p_sad16x16 + 2 * 8));
3800 6281050 : const __m128i s3 = _mm_loadu_si128((__m128i*)(p_sad16x16 + 3 * 8));
3801 : __m256i s_256[4];
3802 :
3803 3140520 : s_256[0] = _mm256_cvtepu16_epi32(s0);
3804 3140520 : s_256[1] = _mm256_cvtepu16_epi32(s1);
3805 3140520 : s_256[2] = _mm256_cvtepu16_epi32(s2);
3806 3140520 : s_256[3] = _mm256_cvtepu16_epi32(s3);
3807 :
3808 3140520 : s_256[0] = _mm256_add_epi32(s_256[0], s_256[1]);
3809 3140520 : s_256[2] = _mm256_add_epi32(s_256[2], s_256[3]);
3810 6281050 : return _mm256_add_epi32(s_256[0], s_256[2]);
3811 : }
3812 :
3813 1766440 : static INLINE void update_best_sse2(const __m128i sad, const uint32_t mv,
3814 : uint32_t *const p_best_sad32x32, uint32_t *const p_best_mv32x32)
3815 : {
3816 1766440 : const __m128i minpos = _mm_minpos_epu16(sad);
3817 1766440 : const uint32_t min_sad = (uint16_t)_mm_extract_epi16(minpos, 0);
3818 :
3819 1766440 : if (min_sad < *p_best_sad32x32) {
3820 185317 : const int32_t best_mv = 4 * _mm_extract_epi16(minpos, 1);
3821 185317 : const int16_t xMv = _MVXT(mv) + (int16_t)best_mv;
3822 185317 : const int16_t yMv = _MVYT(mv);
3823 185317 : *p_best_sad32x32 = min_sad;
3824 185317 : *p_best_mv32x32 = ((uint16_t)yMv << 16) | ((uint16_t)xMv);
3825 : }
3826 1766440 : }
3827 :
3828 : /*******************************************
3829 : Calcualte SAD for 32x32,64x64 from 16x16
3830 : and check if there is improvement, if yes keep
3831 : the best SAD+MV
3832 : *******************************************/
3833 787935 : void get_eight_horizontal_search_point_results_32x32_64x64_pu_avx2_intrin(
3834 : uint16_t *p_sad16x16,
3835 : uint32_t *p_best_sad32x32,
3836 : uint32_t *p_best_sad64x64,
3837 : uint32_t *p_best_mv32x32,
3838 : uint32_t *p_best_mv64x64,
3839 : uint32_t mv)
3840 : {
3841 : __m256i s_256[4], sum[2];
3842 :
3843 : /*--------------------
3844 : | 32x32_0 | 32x32_1
3845 : ----------------------
3846 : | 32x32_2 | 32x32_3
3847 : ----------------------*/
3848 :
3849 : /* data ordering in p_sad16x16 buffer
3850 :
3851 : Search Search Search
3852 : Point 0 Point 1 Point 7
3853 : ---------------------------------------
3854 : 16x16_0 | x | x | ...... | x |
3855 : ---------------------------------------
3856 : 16x16_1 | x | x | ...... | x |
3857 :
3858 : 16x16_n | x | x | ...... | x |
3859 :
3860 : ---------------------------------------
3861 : 16x16_15 | x | x | ...... | x |
3862 : ---------------------------------------
3863 : */
3864 :
3865 787935 : s_256[0] = add_4_sad_avx2(p_sad16x16 + 0 * 8);
3866 787661 : s_256[1] = add_4_sad_avx2(p_sad16x16 + 4 * 8);
3867 787401 : s_256[2] = add_4_sad_avx2(p_sad16x16 + 8 * 8);
3868 787347 : s_256[3] = add_4_sad_avx2(p_sad16x16 + 12 * 8);
3869 :
3870 787607 : sum[0] = _mm256_add_epi32(s_256[0], s_256[1]);
3871 787607 : sum[1] = _mm256_add_epi32(s_256[2], s_256[3]);
3872 787607 : sum[0] = _mm256_add_epi32(sum[0], sum[1]);
3873 787607 : const __m128i sad_0 = _mm256_castsi256_si128(sum[0]);
3874 787607 : const __m128i sad_1 = _mm256_extracti128_si256(sum[0], 1);
3875 :
3876 787607 : const __m128i ss = _mm_packus_epi32(sad_0, sad_1);
3877 787607 : const __m128i minpos = _mm_minpos_epu16(ss);
3878 787607 : const uint32_t min_sad = (uint16_t)_mm_extract_epi16(minpos, 0);
3879 :
3880 787607 : if (min_sad != 0xFFFF) {
3881 442030 : if (min_sad < *p_best_sad64x64) {
3882 57351 : const uint32_t bestMV64x64 = 4 * _mm_extract_epi16(minpos, 1);
3883 57351 : const int16_t xMv = _MVXT(mv) + (int16_t)bestMV64x64;
3884 57351 : const int16_t yMv = _MVYT(mv);
3885 57351 : *p_best_sad64x64 = min_sad;
3886 57351 : *p_best_mv64x64 = ((uint16_t)yMv << 16) | ((uint16_t)xMv);
3887 : }
3888 :
3889 442030 : s_256[0] = _mm256_packus_epi32(s_256[0], s_256[1]);
3890 442030 : s_256[2] = _mm256_packus_epi32(s_256[2], s_256[3]);
3891 442030 : s_256[0] = _mm256_permute4x64_epi64(s_256[0], 0xD8);
3892 442030 : s_256[2] = _mm256_permute4x64_epi64(s_256[2], 0xD8);
3893 :
3894 442030 : const __m128i s0_128 = _mm256_castsi256_si128(s_256[0]);
3895 442030 : const __m128i s1_128 = _mm256_extracti128_si256(s_256[0], 1);
3896 442030 : const __m128i s2_128 = _mm256_castsi256_si128(s_256[2]);
3897 442030 : const __m128i s3_128 = _mm256_extracti128_si256(s_256[2], 1);
3898 :
3899 442030 : update_best_sse2(s0_128, mv, &p_best_sad32x32[0], &p_best_mv32x32[0]);
3900 441977 : update_best_sse2(s1_128, mv, &p_best_sad32x32[1], &p_best_mv32x32[1]);
3901 441965 : update_best_sse2(s2_128, mv, &p_best_sad32x32[2], &p_best_mv32x32[2]);
3902 442005 : update_best_sse2(s3_128, mv, &p_best_sad32x32[3], &p_best_mv32x32[3]);
3903 : }
3904 : else {
3905 : __m128i s0, s1, s2, s3, s4, s5;
3906 : __m256i ss0, ss1, ss2, ss3, ss4, ss5, ss6, ss7;
3907 345577 : const __m128i min_val0 = _mm_min_epu32(sad_0, sad_1);
3908 345577 : const __m128i min_val0_hi = _mm_srli_si128(min_val0, 8);
3909 345577 : const __m128i min_val1 = _mm_min_epu32(min_val0, min_val0_hi);
3910 345577 : const __m128i min_val1_hi = _mm_srli_si128(min_val1, 4);
3911 345577 : const __m128i min_val2 = _mm_min_epu32(min_val1, min_val1_hi);
3912 345577 : const uint32_t min_val = _mm_cvtsi128_si32(min_val2);
3913 :
3914 345577 : if (min_val < *p_best_sad64x64) {
3915 38715 : const __m128i mask0 = _mm_cmpgt_epi32(sad_0, sad_1);
3916 38715 : const __m128i mask1 = _mm_cmpgt_epi32(min_val0, min_val0_hi);
3917 38715 : const __m128i mask2 = _mm_cmpgt_epi32(min_val1, min_val1_hi);
3918 : __m128i offset0, offset1;
3919 :
3920 38715 : offset0 = _mm_setr_epi32(0 * 4, 1 * 4, 2 * 4, 3 * 4);
3921 38715 : offset1 = _mm_setr_epi32(4 * 4, 5 * 4, 6 * 4, 7 * 4);
3922 38715 : offset0 = _mm_andnot_si128(mask0, offset0);
3923 38715 : offset1 = _mm_and_si128(mask0, offset1);
3924 38715 : offset0 = _mm_or_si128(offset0, offset1);
3925 :
3926 38715 : offset1 = _mm_srli_si128(offset0, 8);
3927 38715 : offset0 = _mm_andnot_si128(mask1, offset0);
3928 38715 : offset1 = _mm_and_si128(mask1, offset1);
3929 38715 : offset0 = _mm_or_si128(offset0, offset1);
3930 :
3931 38715 : offset1 = _mm_srli_si128(offset0, 4);
3932 38715 : offset0 = _mm_andnot_si128(mask2, offset0);
3933 38715 : offset1 = _mm_and_si128(mask2, offset1);
3934 38715 : offset0 = _mm_or_si128(offset0, offset1);
3935 :
3936 38715 : const uint32_t bestMV64x64 = _mm_cvtsi128_si32(offset0);
3937 38715 : const int16_t xMv = _MVXT(mv) + (int16_t)bestMV64x64;
3938 38715 : const int16_t yMv = _MVYT(mv);
3939 38715 : *p_best_sad64x64 = min_val;
3940 38715 : *p_best_mv64x64 = ((uint16_t)yMv << 16) | ((uint16_t)xMv);
3941 : }
3942 :
3943 : // XY
3944 : // X: 32x32 block [0..3]
3945 : // Y: Search position [0..7]
3946 345577 : ss0 = s_256[0]; // 07 06 05 04 03 02 01 00
3947 345577 : ss1 = s_256[1]; // 17 16 15 14 13 12 11 10
3948 345577 : ss2 = s_256[2]; // 27 26 25 24 23 22 21 20
3949 345577 : ss3 = s_256[3]; // 37 36 35 34 33 32 31 30
3950 345577 : ss4 = _mm256_unpacklo_epi32(ss0, ss1); // 15 05 14 04 11 01 10 00
3951 345577 : ss5 = _mm256_unpacklo_epi32(ss2, ss3); // 35 25 34 24 31 21 30 20
3952 345577 : ss6 = _mm256_unpackhi_epi32(ss0, ss1); // 17 07 16 06 13 03 12 02
3953 345577 : ss7 = _mm256_unpackhi_epi32(ss2, ss3); // 37 27 36 26 33 23 32 22
3954 345577 : ss0 = _mm256_unpacklo_epi64(ss4, ss5); // 34 24 14 04 30 20 10 00
3955 345577 : ss1 = _mm256_unpackhi_epi64(ss4, ss5); // 35 25 15 05 31 21 11 01
3956 345577 : ss2 = _mm256_unpacklo_epi64(ss6, ss7); // 36 26 16 06 32 22 12 02
3957 345577 : ss3 = _mm256_unpackhi_epi64(ss6, ss7); // 37 27 17 07 33 23 13 03
3958 :
3959 : // ss4 | ss5-2 | ss6 |
3960 : // a0 : a1 | a2 : a3 | min(a0, a1) : min(a2, a3) | | (ss4 & !ss6) | ((ss5-2) & ss6) | ((ss4 & !ss6) | ((ss5-2) & ss6)) |
3961 : // > (-1) | > (-3) | > (-1) | a3 | 0 | -3 | -3 |
3962 : // > (-1) | > (-3) | <= (0) | a1 | -1 | 0 | -1 |
3963 : // > (-1) | <= (-2) | > (-1) | a2 | 0 | -2 | -2 |
3964 : // > (-1) | <= (-2) | <= (0) | a1 | -1 | 0 | -1 |
3965 : // <= (0) | > (-3) | > (-1) | a3 | 0 | -3 | -3 |
3966 : // <= (0) | > (-3) | <= (0) | a0 | 0 | 0 | 0 |
3967 : // <= (0) | <= (-2) | > (-1) | a2 | 0 | -2 | -2 |
3968 : // <= (0) | <= (-2) | <= (0) | a0 | 0 | 0 | 0 |
3969 :
3970 : // *** 8 search points per position ***
3971 :
3972 : // ss0: Search Pos 0,4 for blocks 0,1,2,3
3973 : // ss1: Search Pos 1,5 for blocks 0,1,2,3
3974 : // ss2: Search Pos 2,6 for blocks 0,1,2,3
3975 : // ss3: Search Pos 3,7 for blocks 0,1,2,3
3976 :
3977 345577 : ss4 = _mm256_cmpgt_epi32(ss0, ss1);
3978 345577 : ss0 = _mm256_min_epi32(ss0, ss1);
3979 345577 : ss5 = _mm256_cmpgt_epi32(ss2, ss3);
3980 345577 : ss2 = _mm256_min_epi32(ss2, ss3);
3981 691154 : ss5 = _mm256_sub_epi32(ss5, _mm256_set1_epi32(2)); // ss5-2
3982 :
3983 : // *** 4 search points per position ***
3984 345577 : ss6 = _mm256_cmpgt_epi32(ss0, ss2);
3985 345577 : ss0 = _mm256_min_epi32(ss0, ss2);
3986 345577 : ss5 = _mm256_and_si256(ss5, ss6); // (ss5-2) & ss6
3987 345577 : ss4 = _mm256_andnot_si256(ss6, ss4); // ss4 & !ss6
3988 345577 : ss4 = _mm256_or_si256(ss4, ss5); // (ss4 & !ss6) | ((ss5-2) & ss6)
3989 :
3990 : // *** 2 search points per position ***
3991 :
3992 : // ss0 = 8 SADs, two search points for each 32x32
3993 : // ss4 = 8 MVs, two search points for each 32x32
3994 : //
3995 : // XY
3996 : // X: 32x32 block [0..3]
3997 : // Y: search position [0..1]
3998 : // Format: 00 10 20 30 01 11 21 31
3999 :
4000 : // Each 128 bits contains 4 32x32 32bit block results
4001 : // SAD
4002 345577 : s0 = _mm256_castsi256_si128(ss0);
4003 345577 : s1 = _mm256_extracti128_si256(ss0, 1);
4004 : // MV
4005 345577 : s2 = _mm256_castsi256_si128(ss4);
4006 345577 : s3 = _mm256_extracti128_si256(ss4, 1);
4007 :
4008 : // Choose the best MV out of the two, use s4 to hold results of min
4009 345577 : s4 = _mm_cmpgt_epi32(s0, s1);
4010 345577 : s0 = _mm_min_epi32(s0, s1);
4011 :
4012 : // Extract MV's based on the blocks to s2
4013 691154 : s3 = _mm_sub_epi32(s3, _mm_set1_epi32(4)); // s3-4
4014 : // Remove the MV's are not used from s2
4015 345577 : s2 = _mm_andnot_si128(s4, s2);
4016 : // Remove the MV's that are not used from s3 (inverse from s2 above operation)
4017 345577 : s3 = _mm_and_si128(s4, s3);
4018 : // Combine the remaining candidates into s2
4019 345577 : s2 = _mm_or_si128(s2, s3);
4020 : // Convert MV's into encoders format
4021 345577 : s2 = _mm_slli_epi32(s2, 2); // mv info (negative)
4022 :
4023 : // ***SAD***
4024 : // s0: current SAD candidates for each 32x32
4025 : // s1: best SAD's for 32x32
4026 :
4027 : // Load best SAD's
4028 345577 : s1 = _mm_loadu_si128((__m128i*)p_best_sad32x32);
4029 :
4030 : // Determine which candidates are better than the current best SAD's.
4031 : // s4 is used to determine the MV's of the new best SAD's
4032 345577 : s4 = _mm_cmpgt_epi32(s1, s0);
4033 : // Combine old and new min SAD's
4034 345577 : s0 = _mm_min_epu32(s0, s1);
4035 : // Store new best SAD's back to memory
4036 : _mm_storeu_si128((__m128i*)p_best_sad32x32, s0);
4037 :
4038 : // ***Motion Vectors***
4039 : // Load best MV's
4040 : // s3: candidate MV's
4041 : // s4: results of comparing SAD's
4042 : // s5: previous best MV's
4043 :
4044 : // Load previous best MV's
4045 345577 : s5 = _mm_loadu_si128((__m128i*)p_best_mv32x32);
4046 : // Remove the MV's that are being replaced
4047 345577 : s5 = _mm_andnot_si128(s4, s5);
4048 :
4049 : //Set mvx to s0 and mvy to s1
4050 345577 : s0 = _mm_set1_epi32(mv & 0xFFFF);
4051 691154 : s1 = _mm_set1_epi32(mv & 0xFFFF0000);
4052 :
4053 : // Add candidate MV's to base MV
4054 345577 : s3 = _mm_sub_epi32(s0, s2);
4055 : // Limit to int16_t
4056 691154 : s3 = _mm_and_si128(s3, _mm_set1_epi32(0xFFFF));
4057 : //mvy | mvx
4058 345577 : s3 = _mm_or_si128(s3, s1);
4059 :
4060 : // Remove non-candidate's
4061 345577 : s3 = _mm_and_si128(s3, s4);
4062 : // Combine remaining candidates with remaining best MVs
4063 345577 : s3 = _mm_or_si128(s3, s5);
4064 : // Store back to memory
4065 : _mm_storeu_si128((__m128i*)p_best_mv32x32, s3);
4066 : }
4067 787610 : }
4068 :
4069 : /*******************************************************************************
4070 : * Requirement: width = 4, 8, 16, 24, 32, 48 or 64
4071 : * Requirement: block_height <= 64
4072 : * Requirement: block_height % 2 = 0 when width = 4 or 8
4073 : *******************************************************************************/
4074 31594 : void sad_loop_kernel_avx2_hme_l0_intrin(
4075 : uint8_t *src, // input parameter, source samples Ptr
4076 : uint32_t src_stride, // input parameter, source stride
4077 : uint8_t *ref, // input parameter, reference samples Ptr
4078 : uint32_t ref_stride, // input parameter, reference stride
4079 : uint32_t block_height, // input parameter, block height (M)
4080 : uint32_t block_width, // input parameter, block width (N)
4081 : uint64_t *best_sad,
4082 : int16_t *x_search_center,
4083 : int16_t *y_search_center,
4084 : uint32_t src_stride_raw, // input parameter, source stride (no line skipping)
4085 : int16_t search_area_width,
4086 : int16_t search_area_height)
4087 : {
4088 31594 : int16_t xBest = *x_search_center, yBest = *y_search_center;
4089 31594 : uint32_t lowSum = 0xffffff;
4090 31594 : uint32_t temSum1 = 0;
4091 : int16_t i, j;
4092 : uint32_t k;
4093 : const uint8_t *pRef, *pSrc;
4094 31594 : __m128i s0, s1, s2, s3, s4, s5, s6, s7 = _mm_set1_epi32(-1);
4095 : __m256i ss0, ss1, ss2, ss3, ss4, ss5, ss6, ss7, ss8, ss9, ss10, ss11;
4096 :
4097 31594 : switch (block_width) {
4098 0 : case 4:
4099 :
4100 0 : if (!(block_height % 4)) {
4101 0 : uint32_t srcStrideT = 3 * src_stride;
4102 0 : uint32_t refStrideT = 3 * ref_stride;
4103 0 : for (i = 0; i < search_area_height; i++) {
4104 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4105 0 : pSrc = src;
4106 0 : pRef = ref + j;
4107 0 : ss3 = ss5 = _mm256_setzero_si256();
4108 0 : for (k = 0; k < block_height; k += 4) {
4109 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
4110 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
4111 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)pSrc), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_cvtsi32_si128(*(uint32_t *)(pSrc + 2 * src_stride)), _mm_cvtsi32_si128(*(uint32_t *)(pSrc + srcStrideT))), 0x1);
4112 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4113 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4114 0 : pSrc += src_stride << 2;
4115 0 : pRef += ref_stride << 2;
4116 : }
4117 0 : ss3 = _mm256_adds_epu16(ss3, ss5);
4118 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
4119 0 : s3 = _mm_minpos_epu16(s3);
4120 0 : temSum1 = _mm_extract_epi16(s3, 0);
4121 0 : if (temSum1 < lowSum) {
4122 0 : lowSum = temSum1;
4123 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
4124 0 : yBest = i;
4125 : }
4126 : }
4127 0 : ref += src_stride_raw;
4128 : }
4129 : }
4130 : else {
4131 0 : for (i = 0; i < search_area_height; i++) {
4132 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4133 0 : pSrc = src;
4134 0 : pRef = ref + j;
4135 0 : s3 = _mm_setzero_si128();
4136 0 : for (k = 0; k < block_height; k += 2) {
4137 0 : s0 = _mm_loadu_si128((__m128i*)pRef);
4138 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
4139 0 : s2 = _mm_cvtsi32_si128(*(uint32_t *)pSrc);
4140 0 : s5 = _mm_cvtsi32_si128(*(uint32_t *)(pSrc + src_stride));
4141 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
4142 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
4143 0 : pSrc += src_stride << 1;
4144 0 : pRef += ref_stride << 1;
4145 : }
4146 0 : s3 = _mm_minpos_epu16(s3);
4147 0 : temSum1 = _mm_extract_epi16(s3, 0);
4148 0 : if (temSum1 < lowSum) {
4149 0 : lowSum = temSum1;
4150 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
4151 0 : yBest = i;
4152 : }
4153 : }
4154 0 : ref += src_stride_raw;
4155 : }
4156 : }
4157 :
4158 0 : break;
4159 :
4160 0 : case 8:
4161 0 : if (!(block_height % 4)) {
4162 0 : uint32_t srcStrideT = 3 * src_stride;
4163 0 : uint32_t refStrideT = 3 * ref_stride;
4164 0 : for (i = 0; i < search_area_height; i++) {
4165 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4166 0 : pSrc = src;
4167 0 : pRef = ref + j;
4168 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4169 0 : for (k = 0; k < block_height; k += 4) {
4170 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + 2 * ref_stride)), 0x1);
4171 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + ref_stride))), _mm_loadu_si128((__m128i*)(pRef + refStrideT)), 0x1);
4172 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)pSrc), _mm_loadl_epi64((__m128i*)(pSrc + src_stride)))), _mm_unpacklo_epi64(_mm_loadl_epi64((__m128i*)(pSrc + 2 * src_stride)), _mm_loadl_epi64((__m128i*)(pSrc + srcStrideT))), 0x1);
4173 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4174 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4175 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4176 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4177 0 : pSrc += src_stride << 2;
4178 0 : pRef += ref_stride << 2;
4179 : }
4180 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
4181 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
4182 0 : s3 = _mm_minpos_epu16(s3);
4183 0 : temSum1 = _mm_extract_epi16(s3, 0);
4184 0 : if (temSum1 < lowSum) {
4185 0 : lowSum = temSum1;
4186 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
4187 0 : yBest = i;
4188 : }
4189 : }
4190 0 : ref += src_stride_raw;
4191 : }
4192 : }
4193 : else {
4194 0 : for (i = 0; i < search_area_height; i++) {
4195 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4196 0 : pSrc = src;
4197 0 : pRef = ref + j;
4198 0 : s3 = s4 = _mm_setzero_si128();
4199 0 : for (k = 0; k < block_height; k += 2) {
4200 0 : s0 = _mm_loadu_si128((__m128i*)pRef);
4201 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + ref_stride));
4202 0 : s2 = _mm_loadl_epi64((__m128i*)pSrc);
4203 0 : s5 = _mm_loadl_epi64((__m128i*)(pSrc + src_stride));
4204 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
4205 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
4206 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s1, s5, 0));
4207 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s1, s5, 5));
4208 0 : pSrc += src_stride << 1;
4209 0 : pRef += ref_stride << 1;
4210 : }
4211 0 : s3 = _mm_adds_epu16(s3, s4);
4212 0 : s3 = _mm_minpos_epu16(s3);
4213 0 : temSum1 = _mm_extract_epi16(s3, 0);
4214 0 : if (temSum1 < lowSum) {
4215 0 : lowSum = temSum1;
4216 0 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
4217 0 : yBest = i;
4218 : }
4219 : }
4220 0 : ref += src_stride_raw;
4221 : }
4222 : }
4223 0 : break;
4224 :
4225 31597 : case 16:
4226 31597 : if (block_height <= 16) {
4227 758605 : for (i = 0; i < search_area_height; i++) {
4228 3474890 : for (j = 0; j <= search_area_width - 16; j += 16) {
4229 2747880 : pSrc = src;
4230 2747880 : pRef = ref + j;
4231 2747880 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4232 2747880 : ss7 = ss9 = ss10 = ss11 = _mm256_setzero_si256();
4233 24145200 : for (k = 0; k < block_height; k += 2) {
4234 64192100 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
4235 64192100 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
4236 64192100 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
4237 21397400 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4238 21397400 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4239 21397400 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4240 21397400 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4241 :
4242 64192100 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 16))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 16)), 0x1);
4243 21397400 : ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss1, ss2, 0));
4244 21397400 : ss11 = _mm256_adds_epu16(ss11, _mm256_mpsadbw_epu8(ss1, ss2, 45));
4245 21397400 : ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss0, ss2, 18));
4246 21397400 : ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss0, ss2, 63));
4247 :
4248 21397400 : pSrc += 2 * src_stride;
4249 21397400 : pRef += 2 * ref_stride;
4250 : }
4251 5495770 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
4252 8243660 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
4253 2747880 : s3 = _mm_minpos_epu16(s3);
4254 2747880 : temSum1 = _mm_extract_epi16(s3, 0);
4255 2747880 : if (temSum1 < lowSum) {
4256 194478 : lowSum = temSum1;
4257 194478 : xBest = (int16_t)(j + _mm_extract_epi16(s3, 1));
4258 194478 : yBest = i;
4259 : }
4260 :
4261 5495770 : ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss11), _mm256_adds_epu16(ss9, ss10));
4262 8243660 : s7 = _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1));
4263 2747880 : s7 = _mm_minpos_epu16(s7);
4264 2747880 : temSum1 = _mm_extract_epi16(s7, 0);
4265 2747880 : if (temSum1 < lowSum) {
4266 60971 : lowSum = temSum1;
4267 60971 : xBest = (int16_t)(j + 8 + _mm_extract_epi16(s7, 1));
4268 60971 : yBest = i;
4269 : }
4270 : }
4271 727007 : ref += src_stride_raw;
4272 : }
4273 : }
4274 0 : else if (block_height <= 32) {
4275 0 : for (i = 0; i < search_area_height; i++) {
4276 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4277 0 : pSrc = src;
4278 0 : pRef = ref + j;
4279 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4280 0 : for (k = 0; k < block_height; k += 2) {
4281 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
4282 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
4283 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
4284 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4285 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4286 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4287 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4288 0 : pSrc += 2 * src_stride;
4289 0 : pRef += 2 * ref_stride;
4290 : }
4291 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
4292 0 : s3 = _mm256_castsi256_si128(ss3);
4293 0 : s5 = _mm256_extracti128_si256(ss3, 1);
4294 0 : s4 = _mm_minpos_epu16(s3);
4295 0 : s6 = _mm_minpos_epu16(s5);
4296 0 : s4 = _mm_unpacklo_epi16(s4, s4);
4297 0 : s4 = _mm_unpacklo_epi32(s4, s4);
4298 0 : s4 = _mm_unpacklo_epi64(s4, s4);
4299 0 : s6 = _mm_unpacklo_epi16(s6, s6);
4300 0 : s6 = _mm_unpacklo_epi32(s6, s6);
4301 0 : s6 = _mm_unpacklo_epi64(s6, s6);
4302 0 : s3 = _mm_sub_epi16(s3, s4);
4303 0 : s5 = _mm_adds_epu16(s5, s3);
4304 0 : s5 = _mm_sub_epi16(s5, s6);
4305 0 : s5 = _mm_minpos_epu16(s5);
4306 0 : temSum1 = _mm_extract_epi16(s5, 0);
4307 0 : temSum1 += _mm_extract_epi16(s4, 0);
4308 0 : temSum1 += _mm_extract_epi16(s6, 0);
4309 0 : if (temSum1 < lowSum) {
4310 0 : lowSum = temSum1;
4311 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
4312 0 : yBest = i;
4313 : }
4314 : }
4315 0 : ref += src_stride_raw;
4316 : }
4317 : }
4318 : else {
4319 0 : for (i = 0; i < search_area_height; i++) {
4320 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4321 0 : pSrc = src;
4322 0 : pRef = ref + j;
4323 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4324 0 : for (k = 0; k < block_height; k += 2) {
4325 0 : ss0 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pRef)), _mm_loadu_si128((__m128i*)(pRef + ref_stride)), 0x1);
4326 0 : ss1 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pRef + 8))), _mm_loadu_si128((__m128i*)(pRef + ref_stride + 8)), 0x1);
4327 0 : ss2 = _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pSrc)), _mm_loadu_si128((__m128i*)(pSrc + src_stride)), 0x1);
4328 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4329 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4330 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4331 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4332 0 : pSrc += 2 * src_stride;
4333 0 : pRef += 2 * ref_stride;
4334 : }
4335 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
4336 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
4337 0 : ss0 = _mm256_adds_epu16(ss3, ss5);
4338 0 : s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
4339 0 : s0 = _mm_minpos_epu16(s0);
4340 0 : temSum1 = _mm_extract_epi16(s0, 0);
4341 0 : if (temSum1 < lowSum) {
4342 0 : if (temSum1 != 0xFFFF) { // no overflow
4343 0 : lowSum = temSum1;
4344 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
4345 0 : yBest = i;
4346 : }
4347 : else {
4348 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
4349 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
4350 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
4351 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
4352 0 : ss4 = _mm256_add_epi32(ss4, ss6);
4353 0 : ss3 = _mm256_add_epi32(ss3, ss5);
4354 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
4355 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
4356 0 : UPDATE_BEST(s0, 0, 0);
4357 0 : UPDATE_BEST(s0, 1, 0);
4358 0 : UPDATE_BEST(s0, 2, 0);
4359 0 : UPDATE_BEST(s0, 3, 0);
4360 0 : UPDATE_BEST(s3, 0, 4);
4361 0 : UPDATE_BEST(s3, 1, 4);
4362 0 : UPDATE_BEST(s3, 2, 4);
4363 0 : UPDATE_BEST(s3, 3, 4);
4364 : }
4365 : }
4366 : }
4367 0 : ref += src_stride_raw;
4368 : }
4369 : }
4370 31597 : break;
4371 :
4372 0 : case 24:
4373 0 : if (block_height <= 16) {
4374 0 : for (i = 0; i < search_area_height; i++) {
4375 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4376 0 : pSrc = src;
4377 0 : pRef = ref + j;
4378 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4379 0 : for (k = 0; k < block_height; k++) {
4380 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
4381 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
4382 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
4383 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4384 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4385 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4386 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4387 0 : pSrc += src_stride;
4388 0 : pRef += ref_stride;
4389 : }
4390 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
4391 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
4392 0 : s3 = _mm_adds_epu16(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
4393 0 : s5 = _mm256_castsi256_si128(ss5);
4394 0 : s4 = _mm_minpos_epu16(s3);
4395 0 : s6 = _mm_minpos_epu16(s5);
4396 0 : s4 = _mm_unpacklo_epi16(s4, s4);
4397 0 : s4 = _mm_unpacklo_epi32(s4, s4);
4398 0 : s4 = _mm_unpacklo_epi64(s4, s4);
4399 0 : s6 = _mm_unpacklo_epi16(s6, s6);
4400 0 : s6 = _mm_unpacklo_epi32(s6, s6);
4401 0 : s6 = _mm_unpacklo_epi64(s6, s6);
4402 0 : s3 = _mm_sub_epi16(s3, s4);
4403 0 : s5 = _mm_adds_epu16(s5, s3);
4404 0 : s5 = _mm_sub_epi16(s5, s6);
4405 0 : s5 = _mm_minpos_epu16(s5);
4406 0 : temSum1 = _mm_extract_epi16(s5, 0);
4407 0 : temSum1 += _mm_extract_epi16(s4, 0);
4408 0 : temSum1 += _mm_extract_epi16(s6, 0);
4409 0 : if (temSum1 < lowSum) {
4410 0 : lowSum = temSum1;
4411 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
4412 0 : yBest = i;
4413 : }
4414 : }
4415 0 : ref += src_stride_raw;
4416 : }
4417 : }
4418 : else {
4419 0 : for (i = 0; i < search_area_height; i++) {
4420 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4421 0 : pSrc = src;
4422 0 : pRef = ref + j;
4423 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4424 0 : for (k = 0; k < block_height; k++) {
4425 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
4426 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
4427 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
4428 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4429 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4430 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4431 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4432 0 : pSrc += src_stride;
4433 0 : pRef += ref_stride;
4434 : }
4435 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
4436 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
4437 0 : s3 = _mm256_castsi256_si128(ss3);
4438 0 : s4 = _mm256_extracti128_si256(ss3, 1);
4439 0 : s5 = _mm256_castsi256_si128(ss5);
4440 0 : s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), s5);
4441 0 : s0 = _mm_minpos_epu16(s0);
4442 0 : temSum1 = _mm_extract_epi16(s0, 0);
4443 0 : if (temSum1 < lowSum) {
4444 0 : if (temSum1 != 0xFFFF) { // no overflow
4445 0 : lowSum = temSum1;
4446 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
4447 0 : yBest = i;
4448 : }
4449 : else {
4450 0 : s0 = _mm_unpacklo_epi16(s3, _mm_setzero_si128());
4451 0 : s3 = _mm_unpackhi_epi16(s3, _mm_setzero_si128());
4452 0 : s1 = _mm_unpacklo_epi16(s4, _mm_setzero_si128());
4453 0 : s4 = _mm_unpackhi_epi16(s4, _mm_setzero_si128());
4454 0 : s2 = _mm_unpacklo_epi16(s5, _mm_setzero_si128());
4455 0 : s5 = _mm_unpackhi_epi16(s5, _mm_setzero_si128());
4456 0 : s0 = _mm_add_epi32(_mm_add_epi32(s0, s1), s2);
4457 0 : s3 = _mm_add_epi32(_mm_add_epi32(s3, s4), s5);
4458 0 : UPDATE_BEST(s0, 0, 0);
4459 0 : UPDATE_BEST(s0, 1, 0);
4460 0 : UPDATE_BEST(s0, 2, 0);
4461 0 : UPDATE_BEST(s0, 3, 0);
4462 0 : UPDATE_BEST(s3, 0, 4);
4463 0 : UPDATE_BEST(s3, 1, 4);
4464 0 : UPDATE_BEST(s3, 2, 4);
4465 0 : UPDATE_BEST(s3, 3, 4);
4466 : }
4467 : }
4468 : }
4469 0 : ref += src_stride_raw;
4470 : }
4471 : }
4472 0 : break;
4473 :
4474 0 : case 32:
4475 0 : if (block_height <= 16) {
4476 0 : for (i = 0; i < search_area_height; i++) {
4477 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4478 0 : pSrc = src;
4479 0 : pRef = ref + j;
4480 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4481 0 : for (k = 0; k < block_height; k++) {
4482 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
4483 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
4484 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
4485 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4486 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4487 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4488 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4489 0 : pSrc += src_stride;
4490 0 : pRef += ref_stride;
4491 : }
4492 0 : ss3 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
4493 0 : s3 = _mm256_castsi256_si128(ss3);
4494 0 : s5 = _mm256_extracti128_si256(ss3, 1);
4495 0 : s4 = _mm_minpos_epu16(s3);
4496 0 : s6 = _mm_minpos_epu16(s5);
4497 0 : s4 = _mm_unpacklo_epi16(s4, s4);
4498 0 : s4 = _mm_unpacklo_epi32(s4, s4);
4499 0 : s4 = _mm_unpacklo_epi64(s4, s4);
4500 0 : s6 = _mm_unpacklo_epi16(s6, s6);
4501 0 : s6 = _mm_unpacklo_epi32(s6, s6);
4502 0 : s6 = _mm_unpacklo_epi64(s6, s6);
4503 0 : s3 = _mm_sub_epi16(s3, s4);
4504 0 : s5 = _mm_adds_epu16(s5, s3);
4505 0 : s5 = _mm_sub_epi16(s5, s6);
4506 0 : s5 = _mm_minpos_epu16(s5);
4507 0 : temSum1 = _mm_extract_epi16(s5, 0);
4508 0 : temSum1 += _mm_extract_epi16(s4, 0);
4509 0 : temSum1 += _mm_extract_epi16(s6, 0);
4510 0 : if (temSum1 < lowSum) {
4511 0 : lowSum = temSum1;
4512 0 : xBest = (int16_t)(j + _mm_extract_epi16(s5, 1));
4513 0 : yBest = i;
4514 : }
4515 : }
4516 0 : ref += src_stride_raw;
4517 : }
4518 : }
4519 0 : else if (block_height <= 32) {
4520 0 : for (i = 0; i < search_area_height; i++) {
4521 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4522 0 : pSrc = src;
4523 0 : pRef = ref + j;
4524 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4525 0 : for (k = 0; k < block_height; k++) {
4526 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
4527 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
4528 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
4529 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4530 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4531 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4532 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4533 0 : pSrc += src_stride;
4534 0 : pRef += ref_stride;
4535 : }
4536 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
4537 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
4538 0 : ss6 = _mm256_adds_epu16(ss3, ss5);
4539 0 : s3 = _mm256_castsi256_si128(ss6);
4540 0 : s4 = _mm256_extracti128_si256(ss6, 1);
4541 0 : s0 = _mm_adds_epu16(s3, s4);
4542 0 : s0 = _mm_minpos_epu16(s0);
4543 0 : temSum1 = _mm_extract_epi16(s0, 0);
4544 0 : if (temSum1 < lowSum) {
4545 0 : if (temSum1 != 0xFFFF) { // no overflow
4546 0 : lowSum = temSum1;
4547 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
4548 0 : yBest = i;
4549 : }
4550 : else {
4551 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
4552 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
4553 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
4554 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
4555 0 : ss4 = _mm256_add_epi32(ss4, ss6);
4556 0 : ss3 = _mm256_add_epi32(ss3, ss5);
4557 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
4558 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
4559 0 : UPDATE_BEST(s0, 0, 0);
4560 0 : UPDATE_BEST(s0, 1, 0);
4561 0 : UPDATE_BEST(s0, 2, 0);
4562 0 : UPDATE_BEST(s0, 3, 0);
4563 0 : UPDATE_BEST(s3, 0, 4);
4564 0 : UPDATE_BEST(s3, 1, 4);
4565 0 : UPDATE_BEST(s3, 2, 4);
4566 0 : UPDATE_BEST(s3, 3, 4);
4567 : }
4568 : }
4569 : }
4570 0 : ref += src_stride_raw;
4571 : }
4572 : }
4573 : else {
4574 0 : for (i = 0; i < search_area_height; i++) {
4575 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4576 0 : pSrc = src;
4577 0 : pRef = ref + j;
4578 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4579 0 : for (k = 0; k < block_height; k++) {
4580 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
4581 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
4582 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
4583 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4584 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4585 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4586 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4587 0 : pSrc += src_stride;
4588 0 : pRef += ref_stride;
4589 : }
4590 0 : ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
4591 0 : s3 = _mm256_castsi256_si128(ss7);
4592 0 : s4 = _mm256_extracti128_si256(ss7, 1);
4593 0 : s0 = _mm_adds_epu16(s3, s4);
4594 0 : s0 = _mm_minpos_epu16(s0);
4595 0 : temSum1 = _mm_extract_epi16(s0, 0);
4596 0 : if (temSum1 < lowSum) {
4597 0 : if (temSum1 != 0xFFFF) { // no overflow
4598 0 : lowSum = temSum1;
4599 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
4600 0 : yBest = i;
4601 : }
4602 : else {
4603 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
4604 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
4605 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
4606 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
4607 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
4608 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
4609 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
4610 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
4611 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
4612 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
4613 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
4614 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
4615 0 : UPDATE_BEST(s0, 0, 0);
4616 0 : UPDATE_BEST(s0, 1, 0);
4617 0 : UPDATE_BEST(s0, 2, 0);
4618 0 : UPDATE_BEST(s0, 3, 0);
4619 0 : UPDATE_BEST(s3, 0, 4);
4620 0 : UPDATE_BEST(s3, 1, 4);
4621 0 : UPDATE_BEST(s3, 2, 4);
4622 0 : UPDATE_BEST(s3, 3, 4);
4623 : }
4624 : }
4625 : }
4626 0 : ref += src_stride_raw;
4627 : }
4628 : }
4629 0 : break;
4630 :
4631 0 : case 48:
4632 0 : if (block_height <= 32) {
4633 0 : for (i = 0; i < search_area_height; i++) {
4634 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4635 0 : pSrc = src;
4636 0 : pRef = ref + j;
4637 0 : s3 = s4 = s5 = s6 = _mm_setzero_si128();
4638 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4639 0 : for (k = 0; k < block_height; k++) {
4640 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
4641 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
4642 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
4643 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4644 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4645 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4646 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4647 0 : s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
4648 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
4649 0 : s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
4650 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
4651 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
4652 0 : s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
4653 0 : s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
4654 0 : pSrc += src_stride;
4655 0 : pRef += ref_stride;
4656 : }
4657 0 : s3 = _mm_adds_epu16(s3, s4);
4658 0 : s5 = _mm_adds_epu16(s5, s6);
4659 0 : s0 = _mm_adds_epu16(s3, s5);
4660 0 : ss3 = _mm256_adds_epu16(ss3, ss4);
4661 0 : ss5 = _mm256_adds_epu16(ss5, ss6);
4662 0 : ss6 = _mm256_adds_epu16(ss3, ss5);
4663 0 : s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss6), _mm256_extracti128_si256(ss6, 1)));
4664 0 : s0 = _mm_minpos_epu16(s0);
4665 0 : temSum1 = _mm_extract_epi16(s0, 0);
4666 0 : if (temSum1 < lowSum) {
4667 0 : if (temSum1 != 0xFFFF) { // no overflow
4668 0 : lowSum = temSum1;
4669 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
4670 0 : yBest = i;
4671 : }
4672 : else {
4673 0 : ss4 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
4674 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
4675 0 : ss6 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
4676 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
4677 0 : ss4 = _mm256_add_epi32(ss4, ss6);
4678 0 : ss3 = _mm256_add_epi32(ss3, ss5);
4679 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss4), _mm256_extracti128_si256(ss4, 1));
4680 0 : s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
4681 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
4682 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
4683 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
4684 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
4685 0 : UPDATE_BEST(s0, 0, 0);
4686 0 : UPDATE_BEST(s0, 1, 0);
4687 0 : UPDATE_BEST(s0, 2, 0);
4688 0 : UPDATE_BEST(s0, 3, 0);
4689 0 : UPDATE_BEST(s1, 0, 4);
4690 0 : UPDATE_BEST(s1, 1, 4);
4691 0 : UPDATE_BEST(s1, 2, 4);
4692 0 : UPDATE_BEST(s1, 3, 4);
4693 : }
4694 : }
4695 : }
4696 0 : ref += src_stride_raw;
4697 : }
4698 : }
4699 : else {
4700 0 : for (i = 0; i < search_area_height; i++) {
4701 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4702 0 : pSrc = src;
4703 0 : pRef = ref + j;
4704 0 : s3 = s4 = s5 = s6 = _mm_setzero_si128();
4705 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4706 0 : for (k = 0; k < block_height; k++) {
4707 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
4708 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
4709 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
4710 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4711 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4712 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4713 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4714 0 : s0 = _mm_loadu_si128((__m128i*)(pRef + 32));
4715 0 : s1 = _mm_loadu_si128((__m128i*)(pRef + 40));
4716 0 : s2 = _mm_loadu_si128((__m128i*)(pSrc + 32));
4717 0 : s3 = _mm_adds_epu16(s3, _mm_mpsadbw_epu8(s0, s2, 0));
4718 0 : s4 = _mm_adds_epu16(s4, _mm_mpsadbw_epu8(s0, s2, 5));
4719 0 : s5 = _mm_adds_epu16(s5, _mm_mpsadbw_epu8(s1, s2, 2));
4720 0 : s6 = _mm_adds_epu16(s6, _mm_mpsadbw_epu8(s1, s2, 7));
4721 0 : pSrc += src_stride;
4722 0 : pRef += ref_stride;
4723 : }
4724 0 : s0 = _mm_adds_epu16(_mm_adds_epu16(s3, s4), _mm_adds_epu16(s5, s6));
4725 0 : ss7 = _mm256_adds_epu16(ss3, ss4);
4726 0 : ss8 = _mm256_adds_epu16(ss5, ss6);
4727 0 : ss7 = _mm256_adds_epu16(ss7, ss8);
4728 0 : s0 = _mm_adds_epu16(s0, _mm_adds_epu16(_mm256_castsi256_si128(ss7), _mm256_extracti128_si256(ss7, 1)));
4729 0 : s0 = _mm_minpos_epu16(s0);
4730 0 : temSum1 = _mm_extract_epi16(s0, 0);
4731 0 : if (temSum1 < lowSum) {
4732 0 : if (temSum1 != 0xFFFF) { // no overflow
4733 0 : lowSum = temSum1;
4734 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
4735 0 : yBest = i;
4736 : }
4737 : else {
4738 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
4739 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
4740 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
4741 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
4742 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
4743 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
4744 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
4745 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
4746 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
4747 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
4748 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
4749 0 : s1 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
4750 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s3, _mm_setzero_si128()));
4751 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s4, _mm_setzero_si128()));
4752 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s5, _mm_setzero_si128()));
4753 0 : s0 = _mm_add_epi32(s0, _mm_unpacklo_epi16(s6, _mm_setzero_si128()));
4754 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s3, _mm_setzero_si128()));
4755 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s4, _mm_setzero_si128()));
4756 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s5, _mm_setzero_si128()));
4757 0 : s1 = _mm_add_epi32(s1, _mm_unpackhi_epi16(s6, _mm_setzero_si128()));
4758 0 : UPDATE_BEST(s0, 0, 0);
4759 0 : UPDATE_BEST(s0, 1, 0);
4760 0 : UPDATE_BEST(s0, 2, 0);
4761 0 : UPDATE_BEST(s0, 3, 0);
4762 0 : UPDATE_BEST(s1, 0, 4);
4763 0 : UPDATE_BEST(s1, 1, 4);
4764 0 : UPDATE_BEST(s1, 2, 4);
4765 0 : UPDATE_BEST(s1, 3, 4);
4766 : }
4767 : }
4768 : }
4769 0 : ref += src_stride_raw;
4770 : }
4771 : }
4772 0 : break;
4773 :
4774 0 : case 64:
4775 0 : if (block_height <= 32) {
4776 0 : for (i = 0; i < search_area_height; i++) {
4777 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4778 0 : pSrc = src;
4779 0 : pRef = ref + j;
4780 0 : ss3 = ss4 = ss5 = ss6 = _mm256_setzero_si256();
4781 0 : for (k = 0; k < block_height; k++) {
4782 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
4783 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
4784 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
4785 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4786 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4787 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4788 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4789 0 : ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
4790 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
4791 0 : ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
4792 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4793 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4794 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4795 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4796 0 : pSrc += src_stride;
4797 0 : pRef += ref_stride;
4798 : }
4799 0 : ss7 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
4800 0 : s3 = _mm256_castsi256_si128(ss7);
4801 0 : s4 = _mm256_extracti128_si256(ss7, 1);
4802 0 : s0 = _mm_adds_epu16(s3, s4);
4803 0 : s0 = _mm_minpos_epu16(s0);
4804 0 : temSum1 = _mm_extract_epi16(s0, 0);
4805 0 : if (temSum1 < lowSum) {
4806 0 : if (temSum1 != 0xFFFF) { // no overflow
4807 0 : lowSum = temSum1;
4808 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
4809 0 : yBest = i;
4810 : }
4811 : else {
4812 0 : ss0 = _mm256_unpacklo_epi16(ss3, _mm256_setzero_si256());
4813 0 : ss3 = _mm256_unpackhi_epi16(ss3, _mm256_setzero_si256());
4814 0 : ss1 = _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256());
4815 0 : ss4 = _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256());
4816 0 : ss2 = _mm256_unpacklo_epi16(ss5, _mm256_setzero_si256());
4817 0 : ss5 = _mm256_unpackhi_epi16(ss5, _mm256_setzero_si256());
4818 0 : ss7 = _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256());
4819 0 : ss6 = _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256());
4820 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(ss0, ss1), _mm256_add_epi32(ss2, ss7));
4821 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(ss3, ss4), _mm256_add_epi32(ss5, ss6));
4822 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
4823 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss3), _mm256_extracti128_si256(ss3, 1));
4824 0 : UPDATE_BEST(s0, 0, 0);
4825 0 : UPDATE_BEST(s0, 1, 0);
4826 0 : UPDATE_BEST(s0, 2, 0);
4827 0 : UPDATE_BEST(s0, 3, 0);
4828 0 : UPDATE_BEST(s3, 0, 4);
4829 0 : UPDATE_BEST(s3, 1, 4);
4830 0 : UPDATE_BEST(s3, 2, 4);
4831 0 : UPDATE_BEST(s3, 3, 4);
4832 : }
4833 : }
4834 : }
4835 0 : ref += src_stride_raw;
4836 : }
4837 : }
4838 : else {
4839 : __m256i ss9, ss10;
4840 0 : for (i = 0; i < search_area_height; i++) {
4841 0 : for (j = 0; j <= search_area_width - 8; j += 8) {
4842 0 : pSrc = src;
4843 0 : pRef = ref + j;
4844 0 : ss3 = ss4 = ss5 = ss6 = ss7 = ss8 = ss9 = ss10 = _mm256_setzero_si256();
4845 0 : for (k = 0; k < block_height; k++) {
4846 0 : ss0 = _mm256_loadu_si256((__m256i*)pRef);
4847 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 8));
4848 0 : ss2 = _mm256_loadu_si256((__m256i *)pSrc);
4849 0 : ss3 = _mm256_adds_epu16(ss3, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4850 0 : ss4 = _mm256_adds_epu16(ss4, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4851 0 : ss5 = _mm256_adds_epu16(ss5, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4852 0 : ss6 = _mm256_adds_epu16(ss6, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4853 0 : ss0 = _mm256_loadu_si256((__m256i*)(pRef + 32));
4854 0 : ss1 = _mm256_loadu_si256((__m256i*)(pRef + 40));
4855 0 : ss2 = _mm256_loadu_si256((__m256i *)(pSrc + 32));
4856 0 : ss7 = _mm256_adds_epu16(ss7, _mm256_mpsadbw_epu8(ss0, ss2, 0));
4857 0 : ss8 = _mm256_adds_epu16(ss8, _mm256_mpsadbw_epu8(ss0, ss2, 45)); // 101 101
4858 0 : ss9 = _mm256_adds_epu16(ss9, _mm256_mpsadbw_epu8(ss1, ss2, 18)); // 010 010
4859 0 : ss10 = _mm256_adds_epu16(ss10, _mm256_mpsadbw_epu8(ss1, ss2, 63)); // 111 111
4860 0 : pSrc += src_stride;
4861 0 : pRef += ref_stride;
4862 : }
4863 0 : ss0 = _mm256_adds_epu16(_mm256_adds_epu16(ss3, ss4), _mm256_adds_epu16(ss5, ss6));
4864 0 : ss0 = _mm256_adds_epu16(ss0, _mm256_adds_epu16(_mm256_adds_epu16(ss7, ss8), _mm256_adds_epu16(ss9, ss10)));
4865 0 : s0 = _mm_adds_epu16(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
4866 0 : s0 = _mm_minpos_epu16(s0);
4867 0 : temSum1 = _mm_extract_epi16(s0, 0);
4868 0 : if (temSum1 < lowSum) {
4869 0 : if (temSum1 != 0xFFFF) { // no overflow
4870 0 : lowSum = temSum1;
4871 0 : xBest = (int16_t)(j + _mm_extract_epi16(s0, 1));
4872 0 : yBest = i;
4873 : }
4874 : else {
4875 0 : ss0 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss3, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss5, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss6, _mm256_setzero_si256())));
4876 0 : ss1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss3, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss4, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss5, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss6, _mm256_setzero_si256())));
4877 0 : ss2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpacklo_epi16(ss7, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpacklo_epi16(ss9, _mm256_setzero_si256()), _mm256_unpacklo_epi16(ss10, _mm256_setzero_si256())));
4878 0 : ss3 = _mm256_add_epi32(_mm256_add_epi32(_mm256_unpackhi_epi16(ss7, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss8, _mm256_setzero_si256())), _mm256_add_epi32(_mm256_unpackhi_epi16(ss9, _mm256_setzero_si256()), _mm256_unpackhi_epi16(ss10, _mm256_setzero_si256())));
4879 0 : ss0 = _mm256_add_epi32(ss0, ss2);
4880 0 : ss1 = _mm256_add_epi32(ss1, ss3);
4881 0 : s0 = _mm_add_epi32(_mm256_castsi256_si128(ss0), _mm256_extracti128_si256(ss0, 1));
4882 0 : s3 = _mm_add_epi32(_mm256_castsi256_si128(ss1), _mm256_extracti128_si256(ss1, 1));
4883 0 : UPDATE_BEST(s0, 0, 0);
4884 0 : UPDATE_BEST(s0, 1, 0);
4885 0 : UPDATE_BEST(s0, 2, 0);
4886 0 : UPDATE_BEST(s0, 3, 0);
4887 0 : UPDATE_BEST(s3, 0, 4);
4888 0 : UPDATE_BEST(s3, 1, 4);
4889 0 : UPDATE_BEST(s3, 2, 4);
4890 0 : UPDATE_BEST(s3, 3, 4);
4891 : }
4892 : }
4893 : }
4894 0 : ref += src_stride_raw;
4895 : }
4896 : }
4897 0 : break;
4898 :
4899 0 : default:
4900 : assert(0);
4901 0 : break;
4902 : }
4903 :
4904 31594 : *best_sad = lowSum;
4905 31594 : *x_search_center = xBest;
4906 31594 : *y_search_center = yBest;
4907 31594 : }
4908 :
4909 0 : uint32_t eb_aom_sad4x4_avx2(const uint8_t *src_ptr, int src_stride,
4910 : const uint8_t *ref_ptr, int ref_stride) {
4911 0 : return compute4x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 4);
4912 : }
4913 :
4914 0 : uint32_t eb_aom_sad4x8_avx2(const uint8_t *src_ptr, int src_stride,
4915 : const uint8_t *ref_ptr, int ref_stride) {
4916 0 : return compute4x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 8);
4917 : }
4918 :
4919 0 : uint32_t eb_aom_sad4x16_avx2(const uint8_t *src_ptr, int src_stride,
4920 : const uint8_t *ref_ptr, int ref_stride) {
4921 0 : return compute4x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 16);
4922 : }
4923 :
4924 0 : uint32_t eb_aom_sad8x4_avx2(const uint8_t *src_ptr, int src_stride,
4925 : const uint8_t *ref_ptr, int ref_stride) {
4926 0 : return compute8x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 4);
4927 : }
4928 :
4929 0 : uint32_t eb_aom_sad8x8_avx2(const uint8_t *src_ptr, int src_stride,
4930 : const uint8_t *ref_ptr, int ref_stride) {
4931 0 : return compute8x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 8);
4932 : }
4933 :
4934 0 : uint32_t eb_aom_sad8x16_avx2(const uint8_t *src_ptr, int src_stride,
4935 : const uint8_t *ref_ptr, int ref_stride) {
4936 0 : return compute8x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 16);
4937 : }
4938 :
4939 0 : uint32_t eb_aom_sad8x32_avx2(const uint8_t *src_ptr, int src_stride,
4940 : const uint8_t *ref_ptr, int ref_stride) {
4941 0 : return compute8x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 32);
4942 : }
4943 :
4944 0 : uint32_t eb_aom_sad16x4_avx2(const uint8_t *src_ptr, int src_stride,
4945 : const uint8_t *ref_ptr, int ref_stride) {
4946 0 : return compute16x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 4);
4947 : }
4948 :
4949 0 : uint32_t eb_aom_sad16x8_avx2(const uint8_t *src_ptr, int src_stride,
4950 : const uint8_t *ref_ptr, int ref_stride) {
4951 0 : return compute16x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 8);
4952 : }
4953 :
4954 0 : uint32_t eb_aom_sad16x16_avx2(const uint8_t *src_ptr, int src_stride,
4955 : const uint8_t *ref_ptr, int ref_stride) {
4956 0 : return compute16x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 16);
4957 : }
4958 :
4959 0 : uint32_t eb_aom_sad16x32_avx2(const uint8_t *src_ptr, int src_stride,
4960 : const uint8_t *ref_ptr, int ref_stride) {
4961 0 : return compute16x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 32);
4962 : }
4963 :
4964 0 : uint32_t eb_aom_sad16x64_avx2(const uint8_t *src_ptr, int src_stride,
4965 : const uint8_t *ref_ptr, int ref_stride) {
4966 0 : return compute16x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 64);
4967 : }
4968 :
4969 0 : uint32_t eb_aom_sad32x8_avx2(const uint8_t *src_ptr, int src_stride,
4970 : const uint8_t *ref_ptr, int ref_stride) {
4971 0 : return compute32x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 8);
4972 : }
4973 :
4974 0 : uint32_t eb_aom_sad32x16_avx2(const uint8_t *src_ptr, int src_stride,
4975 : const uint8_t *ref_ptr, int ref_stride) {
4976 0 : return compute32x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 16);
4977 : }
4978 :
4979 0 : uint32_t eb_aom_sad32x32_avx2(const uint8_t *src_ptr, int src_stride,
4980 : const uint8_t *ref_ptr, int ref_stride) {
4981 0 : return compute32x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 32);
4982 : }
4983 :
4984 0 : uint32_t eb_aom_sad32x64_avx2(const uint8_t *src_ptr, int src_stride,
4985 : const uint8_t *ref_ptr, int ref_stride) {
4986 0 : return compute32x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 64);
4987 : }
4988 :
4989 0 : uint32_t eb_aom_sad64x16_avx2(const uint8_t *src_ptr, int src_stride,
4990 : const uint8_t *ref_ptr, int ref_stride) {
4991 0 : return compute64x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 16);
4992 : }
4993 :
4994 0 : uint32_t eb_aom_sad64x32_avx2(const uint8_t *src_ptr, int src_stride,
4995 : const uint8_t *ref_ptr, int ref_stride) {
4996 0 : return compute64x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 32);
4997 : }
4998 :
4999 0 : uint32_t eb_aom_sad64x64_avx2(const uint8_t *src_ptr, int src_stride,
5000 : const uint8_t *ref_ptr, int ref_stride) {
5001 0 : return compute64x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 64);
5002 : }
5003 :
5004 0 : uint32_t eb_aom_sad128x64_avx2(const uint8_t *src_ptr, int src_stride,
5005 : const uint8_t *ref_ptr, int ref_stride) {
5006 0 : return compute128x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride, 64);
5007 : }
5008 :
5009 0 : uint32_t eb_aom_sad128x128_avx2(const uint8_t *src_ptr, int src_stride,
5010 : const uint8_t *ref_ptr, int ref_stride) {
5011 0 : return compute128x_m_sad_avx2(src_ptr, src_stride, ref_ptr, ref_stride,
5012 : 128);
5013 : }
5014 :
5015 : SIMD_INLINE void eb_aom_sad4xhx4d_calc_avx2(
5016 : const uint8_t *src, int src_stride,
5017 : const uint8_t *const ref[4], int ref_stride,
5018 : uint32_t res[4], uint32_t height) {
5019 : uint32_t y;
5020 0 : uint32_t hsteps = height >> 2;
5021 : const uint8_t *ref0, *ref1, *ref2, *ref3;
5022 : assert(!(height % 4));
5023 :
5024 0 : ref0 = ref[0];
5025 0 : ref1 = ref[1];
5026 0 : ref2 = ref[2];
5027 0 : ref3 = ref[3];
5028 :
5029 0 : __m256i mm256_sad0 = _mm256_setzero_si256();
5030 0 : __m256i mm256_sad1 = _mm256_setzero_si256();
5031 0 : __m256i mm256_sad2 = _mm256_setzero_si256();
5032 0 : __m256i mm256_sad3 = _mm256_setzero_si256();
5033 : __m256i mm256_src;
5034 : __m256i mm256_ref0;
5035 : __m256i mm256_ref1;
5036 : __m256i mm256_ref2;
5037 : __m256i mm256_ref3;
5038 :
5039 0 : for (y = 0; y < hsteps; y++) {
5040 0 : mm256_src = _mm256_setr_epi32(*(uint32_t*)src,
5041 0 : *(uint32_t*)(src + 1 * src_stride),
5042 0 : *(uint32_t*)(src + 2 * src_stride),
5043 0 : *(uint32_t*)(src + 3 * src_stride),
5044 : 0, 0, 0, 0);
5045 :
5046 0 : mm256_ref0 = _mm256_setr_epi32(*(uint32_t*)ref0,
5047 0 : *(uint32_t*)(ref0 + 1 * ref_stride),
5048 0 : *(uint32_t*)(ref0 + 2 * ref_stride),
5049 0 : *(uint32_t*)(ref0 + 3 * ref_stride),
5050 : 0, 0, 0, 0);
5051 :
5052 0 : mm256_ref1 = _mm256_setr_epi32(*(uint32_t*)ref1,
5053 0 : *(uint32_t*)(ref1 + 1 * ref_stride),
5054 0 : *(uint32_t*)(ref1 + 2 * ref_stride),
5055 0 : *(uint32_t*)(ref1 + 3 * ref_stride),
5056 : 0, 0, 0, 0);
5057 :
5058 0 : mm256_ref2 = _mm256_setr_epi32(*(uint32_t*)ref2,
5059 0 : *(uint32_t*)(ref2 + 1 * ref_stride),
5060 0 : *(uint32_t*)(ref2 + 2 * ref_stride),
5061 0 : *(uint32_t*)(ref2 + 3 * ref_stride),
5062 : 0, 0, 0, 0);
5063 :
5064 0 : mm256_ref3 = _mm256_setr_epi32(*(uint32_t*)ref3,
5065 0 : *(uint32_t*)(ref3 + 1 * ref_stride),
5066 0 : *(uint32_t*)(ref3 + 2 * ref_stride),
5067 0 : *(uint32_t*)(ref3 + 3 * ref_stride),
5068 : 0, 0, 0, 0);
5069 :
5070 0 : mm256_sad0 = _mm256_add_epi16(mm256_sad0,
5071 : _mm256_sad_epu8(mm256_src, mm256_ref0));
5072 :
5073 0 : mm256_sad1 = _mm256_add_epi16(mm256_sad1,
5074 : _mm256_sad_epu8(mm256_src, mm256_ref1));
5075 :
5076 0 : mm256_sad2 = _mm256_add_epi16(mm256_sad2,
5077 : _mm256_sad_epu8(mm256_src, mm256_ref2));
5078 :
5079 0 : mm256_sad3 = _mm256_add_epi16(mm256_sad3,
5080 : _mm256_sad_epu8(mm256_src, mm256_ref3));
5081 :
5082 0 : src += src_stride << 2;
5083 0 : ref0 += ref_stride << 2;
5084 0 : ref1 += ref_stride << 2;
5085 0 : ref2 += ref_stride << 2;
5086 0 : ref3 += ref_stride << 2;
5087 : }
5088 :
5089 0 : res[0] = _mm256_extract_epi32(mm256_sad0, 0) + _mm256_extract_epi32(
5090 : mm256_sad0, 2);
5091 0 : res[1] = _mm256_extract_epi32(mm256_sad1, 0) + _mm256_extract_epi32(
5092 : mm256_sad1, 2);
5093 0 : res[2] = _mm256_extract_epi32(mm256_sad2, 0) + _mm256_extract_epi32(
5094 : mm256_sad2, 2);
5095 0 : res[3] = _mm256_extract_epi32(mm256_sad3, 0) + _mm256_extract_epi32(
5096 : mm256_sad3, 2);
5097 0 : }
5098 :
5099 0 : void eb_aom_sad4x4x4d_avx2(
5100 : const uint8_t *src, int src_stride,
5101 : const uint8_t *const ref[4], int ref_stride,
5102 : uint32_t res[4]) {
5103 : eb_aom_sad4xhx4d_calc_avx2(src, src_stride,
5104 : ref, ref_stride, res, 4);
5105 0 : }
5106 :
5107 0 : void eb_aom_sad4x8x4d_avx2(
5108 : const uint8_t *src, int src_stride,
5109 : const uint8_t *const ref[4], int ref_stride,
5110 : uint32_t res[4]) {
5111 : eb_aom_sad4xhx4d_calc_avx2(src, src_stride,
5112 : ref, ref_stride, res, 8);
5113 0 : }
5114 :
5115 0 : void eb_aom_sad4x16x4d_avx2(
5116 : const uint8_t *src, int src_stride,
5117 : const uint8_t *const ref[4], int ref_stride,
5118 : uint32_t res[4]) {
5119 : eb_aom_sad4xhx4d_calc_avx2(src, src_stride,
5120 : ref, ref_stride, res, 16);
5121 0 : }
5122 :
5123 : SIMD_INLINE void eb_aom_sad8xhx4d_calc_avx2(
5124 : const uint8_t *src, int src_stride,
5125 : const uint8_t *const ref[4], int ref_stride,
5126 : uint32_t res[4], uint32_t height) {
5127 : __m128i xmm0;
5128 0 : __m256i ymm0 = _mm256_setzero_si256();
5129 0 : __m256i ymm1 = _mm256_setzero_si256();
5130 0 : __m256i ymm2 = _mm256_setzero_si256();
5131 0 : __m256i ymm3 = _mm256_setzero_si256();
5132 : uint32_t y;
5133 :
5134 : const uint8_t *ref0, *ref1, *ref2, *ref3;
5135 :
5136 0 : ref0 = ref[0];
5137 0 : ref1 = ref[1];
5138 0 : ref2 = ref[2];
5139 0 : ref3 = ref[3];
5140 :
5141 0 : for (y = 0; y < height; y += 4) {
5142 : __m128i src01, src23;
5143 0 : src01 = _mm_loadl_epi64((__m128i *)(src + 0 * src_stride));
5144 0 : src01 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src01),
5145 0 : (double *)(src + 1 * src_stride)));
5146 0 : src23 = _mm_loadl_epi64((__m128i *)(src + 2 * src_stride));
5147 0 : src23 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src23),
5148 0 : (double *)(src + 3 * src_stride)));
5149 0 : const __m256i src0123 = _mm256_setr_m128i(src01, src23);
5150 :
5151 0 : src01 = _mm_loadl_epi64((__m128i *)(ref0 + 0 * ref_stride));
5152 0 : src01 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src01),
5153 0 : (double *)(ref0 + 1 * ref_stride)));
5154 0 : src23 = _mm_loadl_epi64((__m128i *)(ref0 + 2 * ref_stride));
5155 0 : src23 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src23),
5156 0 : (double *)(ref0 + 3 * ref_stride)));
5157 0 : const __m256i ref0123_0 = _mm256_setr_m128i(src01, src23);
5158 :
5159 0 : src01 = _mm_loadl_epi64((__m128i *)(ref1 + 0 * ref_stride));
5160 0 : src01 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src01),
5161 0 : (double *)(ref1 + 1 * ref_stride)));
5162 0 : src23 = _mm_loadl_epi64((__m128i *)(ref1 + 2 * ref_stride));
5163 0 : src23 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src23),
5164 0 : (double *)(ref1 + 3 * ref_stride)));
5165 0 : const __m256i ref0123_1 = _mm256_setr_m128i(src01, src23);
5166 :
5167 0 : src01 = _mm_loadl_epi64((__m128i *)(ref2 + 0 * ref_stride));
5168 0 : src01 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src01),
5169 0 : (double *)(ref2 + 1 * ref_stride)));
5170 0 : src23 = _mm_loadl_epi64((__m128i *)(ref2 + 2 * ref_stride));
5171 0 : src23 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src23),
5172 0 : (double *)(ref2 + 3 * ref_stride)));
5173 0 : const __m256i ref0123_2 = _mm256_setr_m128i(src01, src23);
5174 :
5175 0 : src01 = _mm_loadl_epi64((__m128i *)(ref3 + 0 * ref_stride));
5176 0 : src01 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src01),
5177 0 : (double *)(ref3 + 1 * ref_stride)));
5178 0 : src23 = _mm_loadl_epi64((__m128i *)(ref3 + 2 * ref_stride));
5179 0 : src23 = _mm_castpd_si128(_mm_loadh_pd(_mm_castsi128_pd(src23),
5180 0 : (double *)(ref3 + 3 * ref_stride)));
5181 0 : const __m256i ref0123_3 = _mm256_setr_m128i(src01, src23);
5182 :
5183 0 : ymm0 = _mm256_add_epi32(ymm0, _mm256_sad_epu8(src0123, ref0123_0));
5184 0 : ymm1 = _mm256_add_epi32(ymm1, _mm256_sad_epu8(src0123, ref0123_1));
5185 0 : ymm2 = _mm256_add_epi32(ymm2, _mm256_sad_epu8(src0123, ref0123_2));
5186 0 : ymm3 = _mm256_add_epi32(ymm3, _mm256_sad_epu8(src0123, ref0123_3));
5187 0 : src += src_stride << 2;
5188 0 : ref0 += ref_stride << 2;
5189 0 : ref1 += ref_stride << 2;
5190 0 : ref2 += ref_stride << 2;
5191 0 : ref3 += ref_stride << 2;
5192 : }
5193 :
5194 0 : xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm0),
5195 0 : _mm256_extracti128_si256(ymm0, 1));
5196 0 : xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
5197 0 : res[0] = (uint32_t)_mm_cvtsi128_si32(xmm0);
5198 :
5199 0 : xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm1),
5200 0 : _mm256_extracti128_si256(ymm1, 1));
5201 0 : xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
5202 0 : res[1] = (uint32_t)_mm_cvtsi128_si32(xmm0);
5203 :
5204 0 : xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm2),
5205 0 : _mm256_extracti128_si256(ymm2, 1));
5206 0 : xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
5207 0 : res[2] = (uint32_t)_mm_cvtsi128_si32(xmm0);
5208 :
5209 0 : xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm3),
5210 0 : _mm256_extracti128_si256(ymm3, 1));
5211 0 : xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
5212 0 : res[3] = (uint32_t)_mm_cvtsi128_si32(xmm0);
5213 0 : }
5214 :
5215 0 : void eb_aom_sad8x4x4d_avx2(
5216 : const uint8_t *src, int src_stride,
5217 : const uint8_t *const ref[4], int ref_stride,
5218 : uint32_t res[4]) {
5219 : eb_aom_sad8xhx4d_calc_avx2(src, src_stride,
5220 : ref, ref_stride, res, 4);
5221 0 : }
5222 :
5223 0 : void eb_aom_sad8x8x4d_avx2(
5224 : const uint8_t *src, int src_stride,
5225 : const uint8_t *const ref[4], int ref_stride,
5226 : uint32_t res[4]) {
5227 : eb_aom_sad8xhx4d_calc_avx2(src, src_stride,
5228 : ref, ref_stride, res, 8);
5229 0 : }
5230 :
5231 0 : void eb_aom_sad8x16x4d_avx2(
5232 : const uint8_t *src, int src_stride,
5233 : const uint8_t *const ref[4], int ref_stride,
5234 : uint32_t res[4]) {
5235 : eb_aom_sad8xhx4d_calc_avx2(src, src_stride,
5236 : ref, ref_stride, res, 16);
5237 0 : }
5238 :
5239 0 : void eb_aom_sad8x32x4d_avx2(
5240 : const uint8_t *src, int src_stride,
5241 : const uint8_t *const ref[4], int ref_stride,
5242 : uint32_t res[4]) {
5243 : eb_aom_sad8xhx4d_calc_avx2(src, src_stride,
5244 : ref, ref_stride, res, 32);
5245 0 : }
5246 :
5247 : SIMD_INLINE void eb_aom_sad16xhx4d_calc_avx2(
5248 : const uint8_t *src, int src_stride,
5249 : const uint8_t *const ref[4], int ref_stride,
5250 : uint32_t res[4], uint32_t height) {
5251 : __m128i xmm0;
5252 0 : __m256i ymm0 = _mm256_setzero_si256();
5253 0 : __m256i ymm1 = _mm256_setzero_si256();
5254 0 : __m256i ymm2 = _mm256_setzero_si256();
5255 0 : __m256i ymm3 = _mm256_setzero_si256();
5256 : uint32_t y;
5257 :
5258 : const uint8_t *ref0, *ref1, *ref2, *ref3;
5259 :
5260 0 : ref0 = ref[0];
5261 0 : ref1 = ref[1];
5262 0 : ref2 = ref[2];
5263 0 : ref3 = ref[3];
5264 :
5265 0 : for (y = 0; y < height; y += 2) {
5266 0 : __m256i src0 = _mm256_setr_m128i(
5267 : _mm_loadu_si128((__m128i *)(src + 0 * src_stride)),
5268 : _mm_loadu_si128((__m128i *)(src + 1 * src_stride)));
5269 :
5270 0 : __m256i r0 = _mm256_setr_m128i(
5271 : _mm_loadu_si128((__m128i *)(ref0 + 0 * ref_stride)),
5272 : _mm_loadu_si128((__m128i *)(ref0 + 1 * ref_stride)));
5273 :
5274 0 : __m256i r1 = _mm256_setr_m128i(
5275 : _mm_loadu_si128((__m128i *)(ref1 + 0 * ref_stride)),
5276 : _mm_loadu_si128((__m128i *)(ref1 + 1 * ref_stride)));
5277 :
5278 0 : __m256i r2 = _mm256_setr_m128i(
5279 : _mm_loadu_si128((__m128i *)(ref2 + 0 * ref_stride)),
5280 : _mm_loadu_si128((__m128i *)(ref2 + 1 * ref_stride)));
5281 :
5282 0 : __m256i r3 = _mm256_setr_m128i(
5283 : _mm_loadu_si128((__m128i *)(ref3 + 0 * ref_stride)),
5284 : _mm_loadu_si128((__m128i *)(ref3 + 1 * ref_stride)));
5285 :
5286 0 : ymm0 = _mm256_add_epi32(ymm0, _mm256_sad_epu8(src0, r0));
5287 0 : ymm1 = _mm256_add_epi32(ymm1, _mm256_sad_epu8(src0, r1));
5288 0 : ymm2 = _mm256_add_epi32(ymm2, _mm256_sad_epu8(src0, r2));
5289 0 : ymm3 = _mm256_add_epi32(ymm3, _mm256_sad_epu8(src0, r3));
5290 :
5291 0 : src += src_stride << 1;
5292 0 : ref0 += ref_stride << 1;
5293 0 : ref1 += ref_stride << 1;
5294 0 : ref2 += ref_stride << 1;
5295 0 : ref3 += ref_stride << 1;
5296 : }
5297 :
5298 0 : xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm0),
5299 0 : _mm256_extracti128_si256(ymm0, 1));
5300 0 : xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
5301 0 : res[0] = (uint32_t)_mm_cvtsi128_si32(xmm0);
5302 :
5303 0 : xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm1),
5304 0 : _mm256_extracti128_si256(ymm1, 1));
5305 0 : xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
5306 0 : res[1] = (uint32_t)_mm_cvtsi128_si32(xmm0);
5307 :
5308 0 : xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm2),
5309 0 : _mm256_extracti128_si256(ymm2, 1));
5310 0 : xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
5311 0 : res[2] = (uint32_t)_mm_cvtsi128_si32(xmm0);
5312 :
5313 0 : xmm0 = _mm_add_epi32(_mm256_castsi256_si128(ymm3),
5314 0 : _mm256_extracti128_si256(ymm3, 1));
5315 0 : xmm0 = _mm_add_epi32(xmm0, _mm_srli_si128(xmm0, 8));
5316 0 : res[3] = (uint32_t)_mm_cvtsi128_si32(xmm0);
5317 0 : }
5318 :
5319 0 : void eb_aom_sad16x4x4d_avx2(
5320 : const uint8_t *src, int src_stride,
5321 : const uint8_t *const ref[4], int ref_stride,
5322 : uint32_t res[4]) {
5323 : eb_aom_sad16xhx4d_calc_avx2(src, src_stride,
5324 : ref, ref_stride, res, 4);
5325 0 : }
5326 :
5327 0 : void eb_aom_sad16x8x4d_avx2(
5328 : const uint8_t *src, int src_stride,
5329 : const uint8_t *const ref[4], int ref_stride,
5330 : uint32_t res[4]) {
5331 : eb_aom_sad16xhx4d_calc_avx2(src, src_stride,
5332 : ref, ref_stride, res, 8);
5333 0 : }
5334 :
5335 0 : void eb_aom_sad16x16x4d_avx2(
5336 : const uint8_t *src, int src_stride,
5337 : const uint8_t *const ref[4], int ref_stride,
5338 : uint32_t res[4]) {
5339 : eb_aom_sad16xhx4d_calc_avx2(src, src_stride,
5340 : ref, ref_stride, res, 16);
5341 0 : }
5342 :
5343 0 : void eb_aom_sad16x32x4d_avx2(
5344 : const uint8_t *src, int src_stride,
5345 : const uint8_t *const ref[4], int ref_stride,
5346 : uint32_t res[4]) {
5347 : eb_aom_sad16xhx4d_calc_avx2(src, src_stride,
5348 : ref, ref_stride, res, 32);
5349 0 : }
5350 :
5351 0 : void eb_aom_sad16x64x4d_avx2(
5352 : const uint8_t *src, int src_stride,
5353 : const uint8_t *const ref[4], int ref_stride,
5354 : uint32_t res[4]) {
5355 : eb_aom_sad16xhx4d_calc_avx2(src, src_stride,
5356 : ref, ref_stride, res, 64);
5357 0 : }
5358 :
5359 0 : void eb_aom_sad32x8x4d_avx2(const uint8_t *src, int src_stride,
5360 : const uint8_t *const ref[4], int ref_stride,
5361 : uint32_t res[4]) {
5362 : __m256i src_reg, ref0_reg, ref1_reg, ref2_reg, ref3_reg;
5363 : __m256i sum_ref0, sum_ref1, sum_ref2, sum_ref3;
5364 : __m256i sum_mlow, sum_mhigh;
5365 : int i;
5366 : const uint8_t *ref0, *ref1, *ref2, *ref3;
5367 :
5368 0 : ref0 = ref[0];
5369 0 : ref1 = ref[1];
5370 0 : ref2 = ref[2];
5371 0 : ref3 = ref[3];
5372 0 : sum_ref0 = _mm256_set1_epi16(0);
5373 0 : sum_ref1 = _mm256_set1_epi16(0);
5374 0 : sum_ref2 = _mm256_set1_epi16(0);
5375 0 : sum_ref3 = _mm256_set1_epi16(0);
5376 0 : for (i = 0; i < 8; i++) {
5377 : // load src and all refs
5378 0 : src_reg = _mm256_loadu_si256((const __m256i *)src);
5379 0 : ref0_reg = _mm256_loadu_si256((const __m256i *)ref0);
5380 0 : ref1_reg = _mm256_loadu_si256((const __m256i *)ref1);
5381 0 : ref2_reg = _mm256_loadu_si256((const __m256i *)ref2);
5382 0 : ref3_reg = _mm256_loadu_si256((const __m256i *)ref3);
5383 : // sum of the absolute differences between every ref-i to src
5384 0 : ref0_reg = _mm256_sad_epu8(ref0_reg, src_reg);
5385 0 : ref1_reg = _mm256_sad_epu8(ref1_reg, src_reg);
5386 0 : ref2_reg = _mm256_sad_epu8(ref2_reg, src_reg);
5387 0 : ref3_reg = _mm256_sad_epu8(ref3_reg, src_reg);
5388 : // sum every ref-i
5389 0 : sum_ref0 = _mm256_add_epi32(sum_ref0, ref0_reg);
5390 0 : sum_ref1 = _mm256_add_epi32(sum_ref1, ref1_reg);
5391 0 : sum_ref2 = _mm256_add_epi32(sum_ref2, ref2_reg);
5392 0 : sum_ref3 = _mm256_add_epi32(sum_ref3, ref3_reg);
5393 :
5394 0 : src += src_stride;
5395 0 : ref0 += ref_stride;
5396 0 : ref1 += ref_stride;
5397 0 : ref2 += ref_stride;
5398 0 : ref3 += ref_stride;
5399 : }
5400 : {
5401 : __m128i sum;
5402 : // in sum_ref-i the result is saved in the first 4 bytes
5403 : // the other 4 bytes are zeroed.
5404 : // sum_ref1 and sum_ref3 are shifted left by 4 bytes
5405 0 : sum_ref1 = _mm256_slli_si256(sum_ref1, 4);
5406 0 : sum_ref3 = _mm256_slli_si256(sum_ref3, 4);
5407 :
5408 : // merge sum_ref0 and sum_ref1 also sum_ref2 and sum_ref3
5409 0 : sum_ref0 = _mm256_or_si256(sum_ref0, sum_ref1);
5410 0 : sum_ref2 = _mm256_or_si256(sum_ref2, sum_ref3);
5411 :
5412 : // merge every 64 bit from each sum_ref-i
5413 0 : sum_mlow = _mm256_unpacklo_epi64(sum_ref0, sum_ref2);
5414 0 : sum_mhigh = _mm256_unpackhi_epi64(sum_ref0, sum_ref2);
5415 :
5416 : // add the low 64 bit to the high 64 bit
5417 0 : sum_mlow = _mm256_add_epi32(sum_mlow, sum_mhigh);
5418 :
5419 : // add the low 128 bit to the high 128 bit
5420 0 : sum = _mm_add_epi32(_mm256_castsi256_si128(sum_mlow),
5421 0 : _mm256_extractf128_si256(sum_mlow, 1));
5422 :
5423 : _mm_storeu_si128((__m128i *)(res), sum);
5424 : }
5425 : _mm256_zeroupper();
5426 0 : }
5427 :
5428 0 : void eb_aom_sad32x16x4d_avx2(const uint8_t *src, int src_stride,
5429 : const uint8_t *const ref[4], int ref_stride,
5430 : uint32_t res[4]) {
5431 : __m256i src_reg, ref0_reg, ref1_reg, ref2_reg, ref3_reg;
5432 : __m256i sum_ref0, sum_ref1, sum_ref2, sum_ref3;
5433 : __m256i sum_mlow, sum_mhigh;
5434 : int i;
5435 : const uint8_t *ref0, *ref1, *ref2, *ref3;
5436 :
5437 0 : ref0 = ref[0];
5438 0 : ref1 = ref[1];
5439 0 : ref2 = ref[2];
5440 0 : ref3 = ref[3];
5441 0 : sum_ref0 = _mm256_set1_epi16(0);
5442 0 : sum_ref1 = _mm256_set1_epi16(0);
5443 0 : sum_ref2 = _mm256_set1_epi16(0);
5444 0 : sum_ref3 = _mm256_set1_epi16(0);
5445 0 : for (i = 0; i < 16; i++) {
5446 : // load src and all refs
5447 0 : src_reg = _mm256_loadu_si256((const __m256i *)src);
5448 0 : ref0_reg = _mm256_loadu_si256((const __m256i *)ref0);
5449 0 : ref1_reg = _mm256_loadu_si256((const __m256i *)ref1);
5450 0 : ref2_reg = _mm256_loadu_si256((const __m256i *)ref2);
5451 0 : ref3_reg = _mm256_loadu_si256((const __m256i *)ref3);
5452 : // sum of the absolute differences between every ref-i to src
5453 0 : ref0_reg = _mm256_sad_epu8(ref0_reg, src_reg);
5454 0 : ref1_reg = _mm256_sad_epu8(ref1_reg, src_reg);
5455 0 : ref2_reg = _mm256_sad_epu8(ref2_reg, src_reg);
5456 0 : ref3_reg = _mm256_sad_epu8(ref3_reg, src_reg);
5457 : // sum every ref-i
5458 0 : sum_ref0 = _mm256_add_epi32(sum_ref0, ref0_reg);
5459 0 : sum_ref1 = _mm256_add_epi32(sum_ref1, ref1_reg);
5460 0 : sum_ref2 = _mm256_add_epi32(sum_ref2, ref2_reg);
5461 0 : sum_ref3 = _mm256_add_epi32(sum_ref3, ref3_reg);
5462 :
5463 0 : src += src_stride;
5464 0 : ref0 += ref_stride;
5465 0 : ref1 += ref_stride;
5466 0 : ref2 += ref_stride;
5467 0 : ref3 += ref_stride;
5468 : }
5469 : {
5470 : __m128i sum;
5471 : // in sum_ref-i the result is saved in the first 4 bytes
5472 : // the other 4 bytes are zeroed.
5473 : // sum_ref1 and sum_ref3 are shifted left by 4 bytes
5474 0 : sum_ref1 = _mm256_slli_si256(sum_ref1, 4);
5475 0 : sum_ref3 = _mm256_slli_si256(sum_ref3, 4);
5476 :
5477 : // merge sum_ref0 and sum_ref1 also sum_ref2 and sum_ref3
5478 0 : sum_ref0 = _mm256_or_si256(sum_ref0, sum_ref1);
5479 0 : sum_ref2 = _mm256_or_si256(sum_ref2, sum_ref3);
5480 :
5481 : // merge every 64 bit from each sum_ref-i
5482 0 : sum_mlow = _mm256_unpacklo_epi64(sum_ref0, sum_ref2);
5483 0 : sum_mhigh = _mm256_unpackhi_epi64(sum_ref0, sum_ref2);
5484 :
5485 : // add the low 64 bit to the high 64 bit
5486 0 : sum_mlow = _mm256_add_epi32(sum_mlow, sum_mhigh);
5487 :
5488 : // add the low 128 bit to the high 128 bit
5489 0 : sum = _mm_add_epi32(_mm256_castsi256_si128(sum_mlow),
5490 0 : _mm256_extractf128_si256(sum_mlow, 1));
5491 :
5492 : _mm_storeu_si128((__m128i *)(res), sum);
5493 : }
5494 : _mm256_zeroupper();
5495 0 : }
5496 :
5497 0 : static INLINE void sad32x32x4d_avx2(const uint8_t *src, int src_stride,
5498 : const uint8_t *const ref[4], int ref_stride,
5499 : uint32_t res[4]) {
5500 : __m256i src_reg, ref0_reg, ref1_reg, ref2_reg, ref3_reg;
5501 : __m256i sum_ref0, sum_ref1, sum_ref2, sum_ref3;
5502 : __m256i sum_mlow, sum_mhigh;
5503 : int i;
5504 : const uint8_t *ref0, *ref1, *ref2, *ref3;
5505 :
5506 0 : ref0 = ref[0];
5507 0 : ref1 = ref[1];
5508 0 : ref2 = ref[2];
5509 0 : ref3 = ref[3];
5510 0 : sum_ref0 = _mm256_set1_epi16(0);
5511 0 : sum_ref1 = _mm256_set1_epi16(0);
5512 0 : sum_ref2 = _mm256_set1_epi16(0);
5513 0 : sum_ref3 = _mm256_set1_epi16(0);
5514 0 : for (i = 0; i < 32; i++) {
5515 : // load src and all refs
5516 0 : src_reg = _mm256_loadu_si256((const __m256i *)src);
5517 0 : ref0_reg = _mm256_loadu_si256((const __m256i *)ref0);
5518 0 : ref1_reg = _mm256_loadu_si256((const __m256i *)ref1);
5519 0 : ref2_reg = _mm256_loadu_si256((const __m256i *)ref2);
5520 0 : ref3_reg = _mm256_loadu_si256((const __m256i *)ref3);
5521 : // sum of the absolute differences between every ref-i to src
5522 0 : ref0_reg = _mm256_sad_epu8(ref0_reg, src_reg);
5523 0 : ref1_reg = _mm256_sad_epu8(ref1_reg, src_reg);
5524 0 : ref2_reg = _mm256_sad_epu8(ref2_reg, src_reg);
5525 0 : ref3_reg = _mm256_sad_epu8(ref3_reg, src_reg);
5526 : // sum every ref-i
5527 0 : sum_ref0 = _mm256_add_epi32(sum_ref0, ref0_reg);
5528 0 : sum_ref1 = _mm256_add_epi32(sum_ref1, ref1_reg);
5529 0 : sum_ref2 = _mm256_add_epi32(sum_ref2, ref2_reg);
5530 0 : sum_ref3 = _mm256_add_epi32(sum_ref3, ref3_reg);
5531 :
5532 0 : src += src_stride;
5533 0 : ref0 += ref_stride;
5534 0 : ref1 += ref_stride;
5535 0 : ref2 += ref_stride;
5536 0 : ref3 += ref_stride;
5537 : }
5538 : {
5539 : __m128i sum;
5540 : // in sum_ref-i the result is saved in the first 4 bytes
5541 : // the other 4 bytes are zeroed.
5542 : // sum_ref1 and sum_ref3 are shifted left by 4 bytes
5543 0 : sum_ref1 = _mm256_slli_si256(sum_ref1, 4);
5544 0 : sum_ref3 = _mm256_slli_si256(sum_ref3, 4);
5545 :
5546 : // merge sum_ref0 and sum_ref1 also sum_ref2 and sum_ref3
5547 0 : sum_ref0 = _mm256_or_si256(sum_ref0, sum_ref1);
5548 0 : sum_ref2 = _mm256_or_si256(sum_ref2, sum_ref3);
5549 :
5550 : // merge every 64 bit from each sum_ref-i
5551 0 : sum_mlow = _mm256_unpacklo_epi64(sum_ref0, sum_ref2);
5552 0 : sum_mhigh = _mm256_unpackhi_epi64(sum_ref0, sum_ref2);
5553 :
5554 : // add the low 64 bit to the high 64 bit
5555 0 : sum_mlow = _mm256_add_epi32(sum_mlow, sum_mhigh);
5556 :
5557 : // add the low 128 bit to the high 128 bit
5558 0 : sum = _mm_add_epi32(_mm256_castsi256_si128(sum_mlow),
5559 0 : _mm256_extractf128_si256(sum_mlow, 1));
5560 :
5561 : _mm_storeu_si128((__m128i *)(res), sum);
5562 : }
5563 : _mm256_zeroupper();
5564 0 : }
5565 :
5566 0 : void eb_aom_sad32x32x4d_avx2(const uint8_t *src, int src_stride,
5567 : const uint8_t *const ref[4], int ref_stride,
5568 : uint32_t res[4]) {
5569 0 : sad32x32x4d_avx2(src, src_stride, ref, ref_stride, res);
5570 0 : }
5571 :
5572 0 : void eb_aom_sad64x16x4d_avx2(const uint8_t *src, int src_stride,
5573 : const uint8_t *const ref[4], int ref_stride,
5574 : uint32_t res[4]) {
5575 : __m256i src_reg, srcnext_reg, ref0_reg, ref0next_reg;
5576 : __m256i ref1_reg, ref1next_reg, ref2_reg, ref2next_reg;
5577 : __m256i ref3_reg, ref3next_reg;
5578 : __m256i sum_ref0, sum_ref1, sum_ref2, sum_ref3;
5579 : __m256i sum_mlow, sum_mhigh;
5580 : int i;
5581 : const uint8_t *ref0, *ref1, *ref2, *ref3;
5582 :
5583 0 : ref0 = ref[0];
5584 0 : ref1 = ref[1];
5585 0 : ref2 = ref[2];
5586 0 : ref3 = ref[3];
5587 0 : sum_ref0 = _mm256_set1_epi16(0);
5588 0 : sum_ref1 = _mm256_set1_epi16(0);
5589 0 : sum_ref2 = _mm256_set1_epi16(0);
5590 0 : sum_ref3 = _mm256_set1_epi16(0);
5591 0 : for (i = 0; i < 16; i++) {
5592 : // load 64 bytes from src and all refs
5593 0 : src_reg = _mm256_loadu_si256((const __m256i *)src);
5594 0 : srcnext_reg = _mm256_loadu_si256((const __m256i *)(src + 32));
5595 0 : ref0_reg = _mm256_loadu_si256((const __m256i *)ref0);
5596 0 : ref0next_reg = _mm256_loadu_si256((const __m256i *)(ref0 + 32));
5597 0 : ref1_reg = _mm256_loadu_si256((const __m256i *)ref1);
5598 0 : ref1next_reg = _mm256_loadu_si256((const __m256i *)(ref1 + 32));
5599 0 : ref2_reg = _mm256_loadu_si256((const __m256i *)ref2);
5600 0 : ref2next_reg = _mm256_loadu_si256((const __m256i *)(ref2 + 32));
5601 0 : ref3_reg = _mm256_loadu_si256((const __m256i *)ref3);
5602 0 : ref3next_reg = _mm256_loadu_si256((const __m256i *)(ref3 + 32));
5603 : // sum of the absolute differences between every ref-i to src
5604 0 : ref0_reg = _mm256_sad_epu8(ref0_reg, src_reg);
5605 0 : ref1_reg = _mm256_sad_epu8(ref1_reg, src_reg);
5606 0 : ref2_reg = _mm256_sad_epu8(ref2_reg, src_reg);
5607 0 : ref3_reg = _mm256_sad_epu8(ref3_reg, src_reg);
5608 0 : ref0next_reg = _mm256_sad_epu8(ref0next_reg, srcnext_reg);
5609 0 : ref1next_reg = _mm256_sad_epu8(ref1next_reg, srcnext_reg);
5610 0 : ref2next_reg = _mm256_sad_epu8(ref2next_reg, srcnext_reg);
5611 0 : ref3next_reg = _mm256_sad_epu8(ref3next_reg, srcnext_reg);
5612 :
5613 : // sum every ref-i
5614 0 : sum_ref0 = _mm256_add_epi32(sum_ref0, ref0_reg);
5615 0 : sum_ref1 = _mm256_add_epi32(sum_ref1, ref1_reg);
5616 0 : sum_ref2 = _mm256_add_epi32(sum_ref2, ref2_reg);
5617 0 : sum_ref3 = _mm256_add_epi32(sum_ref3, ref3_reg);
5618 0 : sum_ref0 = _mm256_add_epi32(sum_ref0, ref0next_reg);
5619 0 : sum_ref1 = _mm256_add_epi32(sum_ref1, ref1next_reg);
5620 0 : sum_ref2 = _mm256_add_epi32(sum_ref2, ref2next_reg);
5621 0 : sum_ref3 = _mm256_add_epi32(sum_ref3, ref3next_reg);
5622 0 : src += src_stride;
5623 0 : ref0 += ref_stride;
5624 0 : ref1 += ref_stride;
5625 0 : ref2 += ref_stride;
5626 0 : ref3 += ref_stride;
5627 : }
5628 : {
5629 : __m128i sum;
5630 :
5631 : // in sum_ref-i the result is saved in the first 4 bytes
5632 : // the other 4 bytes are zeroed.
5633 : // sum_ref1 and sum_ref3 are shifted left by 4 bytes
5634 0 : sum_ref1 = _mm256_slli_si256(sum_ref1, 4);
5635 0 : sum_ref3 = _mm256_slli_si256(sum_ref3, 4);
5636 :
5637 : // merge sum_ref0 and sum_ref1 also sum_ref2 and sum_ref3
5638 0 : sum_ref0 = _mm256_or_si256(sum_ref0, sum_ref1);
5639 0 : sum_ref2 = _mm256_or_si256(sum_ref2, sum_ref3);
5640 :
5641 : // merge every 64 bit from each sum_ref-i
5642 0 : sum_mlow = _mm256_unpacklo_epi64(sum_ref0, sum_ref2);
5643 0 : sum_mhigh = _mm256_unpackhi_epi64(sum_ref0, sum_ref2);
5644 :
5645 : // add the low 64 bit to the high 64 bit
5646 0 : sum_mlow = _mm256_add_epi32(sum_mlow, sum_mhigh);
5647 :
5648 : // add the low 128 bit to the high 128 bit
5649 0 : sum = _mm_add_epi32(_mm256_castsi256_si128(sum_mlow),
5650 0 : _mm256_extractf128_si256(sum_mlow, 1));
5651 :
5652 : _mm_storeu_si128((__m128i *)(res), sum);
5653 : }
5654 : _mm256_zeroupper();
5655 0 : }
5656 :
5657 : SIMD_INLINE void sad64x64x4d_avx2(const uint8_t *src, int src_stride,
5658 : const uint8_t *const ref[4], int ref_stride,
5659 : uint32_t res[4]) {
5660 : __m256i src_reg, srcnext_reg, ref0_reg, ref0next_reg;
5661 : __m256i ref1_reg, ref1next_reg, ref2_reg, ref2next_reg;
5662 : __m256i ref3_reg, ref3next_reg;
5663 : __m256i sum_ref0, sum_ref1, sum_ref2, sum_ref3;
5664 : __m256i sum_mlow, sum_mhigh;
5665 : int i;
5666 : const uint8_t *ref0, *ref1, *ref2, *ref3;
5667 :
5668 0 : ref0 = ref[0];
5669 0 : ref1 = ref[1];
5670 0 : ref2 = ref[2];
5671 0 : ref3 = ref[3];
5672 0 : sum_ref0 = _mm256_set1_epi16(0);
5673 0 : sum_ref1 = _mm256_set1_epi16(0);
5674 0 : sum_ref2 = _mm256_set1_epi16(0);
5675 0 : sum_ref3 = _mm256_set1_epi16(0);
5676 0 : for (i = 0; i < 64; i++) {
5677 : // load 64 bytes from src and all refs
5678 0 : src_reg = _mm256_loadu_si256((const __m256i *)src);
5679 0 : srcnext_reg = _mm256_loadu_si256((const __m256i *)(src + 32));
5680 0 : ref0_reg = _mm256_loadu_si256((const __m256i *)ref0);
5681 0 : ref0next_reg = _mm256_loadu_si256((const __m256i *)(ref0 + 32));
5682 0 : ref1_reg = _mm256_loadu_si256((const __m256i *)ref1);
5683 0 : ref1next_reg = _mm256_loadu_si256((const __m256i *)(ref1 + 32));
5684 0 : ref2_reg = _mm256_loadu_si256((const __m256i *)ref2);
5685 0 : ref2next_reg = _mm256_loadu_si256((const __m256i *)(ref2 + 32));
5686 0 : ref3_reg = _mm256_loadu_si256((const __m256i *)ref3);
5687 0 : ref3next_reg = _mm256_loadu_si256((const __m256i *)(ref3 + 32));
5688 : // sum of the absolute differences between every ref-i to src
5689 0 : ref0_reg = _mm256_sad_epu8(ref0_reg, src_reg);
5690 0 : ref1_reg = _mm256_sad_epu8(ref1_reg, src_reg);
5691 0 : ref2_reg = _mm256_sad_epu8(ref2_reg, src_reg);
5692 0 : ref3_reg = _mm256_sad_epu8(ref3_reg, src_reg);
5693 0 : ref0next_reg = _mm256_sad_epu8(ref0next_reg, srcnext_reg);
5694 0 : ref1next_reg = _mm256_sad_epu8(ref1next_reg, srcnext_reg);
5695 0 : ref2next_reg = _mm256_sad_epu8(ref2next_reg, srcnext_reg);
5696 0 : ref3next_reg = _mm256_sad_epu8(ref3next_reg, srcnext_reg);
5697 :
5698 : // sum every ref-i
5699 0 : sum_ref0 = _mm256_add_epi32(sum_ref0, ref0_reg);
5700 0 : sum_ref1 = _mm256_add_epi32(sum_ref1, ref1_reg);
5701 0 : sum_ref2 = _mm256_add_epi32(sum_ref2, ref2_reg);
5702 0 : sum_ref3 = _mm256_add_epi32(sum_ref3, ref3_reg);
5703 0 : sum_ref0 = _mm256_add_epi32(sum_ref0, ref0next_reg);
5704 0 : sum_ref1 = _mm256_add_epi32(sum_ref1, ref1next_reg);
5705 0 : sum_ref2 = _mm256_add_epi32(sum_ref2, ref2next_reg);
5706 0 : sum_ref3 = _mm256_add_epi32(sum_ref3, ref3next_reg);
5707 0 : src += src_stride;
5708 0 : ref0 += ref_stride;
5709 0 : ref1 += ref_stride;
5710 0 : ref2 += ref_stride;
5711 0 : ref3 += ref_stride;
5712 : }
5713 : {
5714 : __m128i sum;
5715 :
5716 : // in sum_ref-i the result is saved in the first 4 bytes
5717 : // the other 4 bytes are zeroed.
5718 : // sum_ref1 and sum_ref3 are shifted left by 4 bytes
5719 0 : sum_ref1 = _mm256_slli_si256(sum_ref1, 4);
5720 0 : sum_ref3 = _mm256_slli_si256(sum_ref3, 4);
5721 :
5722 : // merge sum_ref0 and sum_ref1 also sum_ref2 and sum_ref3
5723 0 : sum_ref0 = _mm256_or_si256(sum_ref0, sum_ref1);
5724 0 : sum_ref2 = _mm256_or_si256(sum_ref2, sum_ref3);
5725 :
5726 : // merge every 64 bit from each sum_ref-i
5727 0 : sum_mlow = _mm256_unpacklo_epi64(sum_ref0, sum_ref2);
5728 0 : sum_mhigh = _mm256_unpackhi_epi64(sum_ref0, sum_ref2);
5729 :
5730 : // add the low 64 bit to the high 64 bit
5731 0 : sum_mlow = _mm256_add_epi32(sum_mlow, sum_mhigh);
5732 :
5733 : // add the low 128 bit to the high 128 bit
5734 0 : sum = _mm_add_epi32(_mm256_castsi256_si128(sum_mlow),
5735 0 : _mm256_extractf128_si256(sum_mlow, 1));
5736 :
5737 : _mm_storeu_si128((__m128i *)(res), sum);
5738 : }
5739 : _mm256_zeroupper();
5740 0 : }
5741 :
5742 0 : void eb_aom_sad64x64x4d_avx2(const uint8_t *src, int src_stride,
5743 : const uint8_t *const ref[4], int ref_stride,
5744 : uint32_t res[4]) {
5745 : sad64x64x4d_avx2(src, src_stride, ref, ref_stride, res);
5746 0 : }
5747 :
5748 0 : void eb_aom_sad32x64x4d_avx2(const uint8_t *src, int src_stride,
5749 : const uint8_t *const ref[4], int ref_stride,
5750 : uint32_t res[4]) {
5751 : const uint8_t *rf[4];
5752 : uint32_t sum0[4];
5753 : uint32_t sum1[4];
5754 :
5755 0 : rf[0] = ref[0];
5756 0 : rf[1] = ref[1];
5757 0 : rf[2] = ref[2];
5758 0 : rf[3] = ref[3];
5759 0 : sad32x32x4d_avx2(src, src_stride, rf, ref_stride, sum0);
5760 0 : src += src_stride << 5;
5761 0 : rf[0] += ref_stride << 5;
5762 0 : rf[1] += ref_stride << 5;
5763 0 : rf[2] += ref_stride << 5;
5764 0 : rf[3] += ref_stride << 5;
5765 0 : sad32x32x4d_avx2(src, src_stride, rf, ref_stride, sum1);
5766 0 : res[0] = sum0[0] + sum1[0];
5767 0 : res[1] = sum0[1] + sum1[1];
5768 0 : res[2] = sum0[2] + sum1[2];
5769 0 : res[3] = sum0[3] + sum1[3];
5770 0 : }
5771 :
5772 0 : void eb_aom_sad64x32x4d_avx2(const uint8_t *src, int src_stride,
5773 : const uint8_t *const ref[4], int ref_stride,
5774 : uint32_t res[4]) {
5775 : const uint8_t *rf[4];
5776 : uint32_t sum0[4];
5777 : uint32_t sum1[4];
5778 0 : unsigned int half_width = 32;
5779 :
5780 0 : rf[0] = ref[0];
5781 0 : rf[1] = ref[1];
5782 0 : rf[2] = ref[2];
5783 0 : rf[3] = ref[3];
5784 0 : sad32x32x4d_avx2(src, src_stride, rf, ref_stride, sum0);
5785 0 : src += half_width;
5786 0 : rf[0] += half_width;
5787 0 : rf[1] += half_width;
5788 0 : rf[2] += half_width;
5789 0 : rf[3] += half_width;
5790 0 : sad32x32x4d_avx2(src, src_stride, rf, ref_stride, sum1);
5791 0 : res[0] = sum0[0] + sum1[0];
5792 0 : res[1] = sum0[1] + sum1[1];
5793 0 : res[2] = sum0[2] + sum1[2];
5794 0 : res[3] = sum0[3] + sum1[3];
5795 0 : }
5796 :
5797 0 : static INLINE unsigned int sad32x32(const uint8_t *src_ptr, int src_stride,
5798 : const uint8_t *ref_ptr, int ref_stride) {
5799 : __m256i s1, s2, r1, r2;
5800 0 : __m256i sum = _mm256_setzero_si256();
5801 : __m128i sum_i128;
5802 : int i;
5803 :
5804 0 : for (i = 0; i < 16; ++i) {
5805 0 : r1 = _mm256_loadu_si256((__m256i const *)ref_ptr);
5806 0 : r2 = _mm256_loadu_si256((__m256i const *)(ref_ptr + ref_stride));
5807 0 : s1 = _mm256_sad_epu8(r1, _mm256_loadu_si256((__m256i const *)src_ptr));
5808 0 : s2 = _mm256_sad_epu8(
5809 0 : r2, _mm256_loadu_si256((__m256i const *)(src_ptr + src_stride)));
5810 0 : sum = _mm256_add_epi32(sum, _mm256_add_epi32(s1, s2));
5811 0 : ref_ptr += ref_stride << 1;
5812 0 : src_ptr += src_stride << 1;
5813 : }
5814 :
5815 0 : sum = _mm256_add_epi32(sum, _mm256_srli_si256(sum, 8));
5816 0 : sum_i128 = _mm_add_epi32(_mm256_extracti128_si256(sum, 1),
5817 : _mm256_castsi256_si128(sum));
5818 0 : return _mm_cvtsi128_si32(sum_i128);
5819 : }
5820 :
5821 : SIMD_INLINE unsigned int sad64x32(const uint8_t *src_ptr, int src_stride,
5822 : const uint8_t *ref_ptr, int ref_stride) {
5823 0 : unsigned int half_width = 32;
5824 0 : uint32_t sum = sad32x32(src_ptr, src_stride, ref_ptr, ref_stride);
5825 0 : src_ptr += half_width;
5826 0 : ref_ptr += half_width;
5827 0 : sum += sad32x32(src_ptr, src_stride, ref_ptr, ref_stride);
5828 0 : return sum;
5829 : }
5830 :
5831 : SIMD_INLINE unsigned int sad64x64(const uint8_t *src_ptr, int src_stride,
5832 : const uint8_t *ref_ptr, int ref_stride) {
5833 0 : uint32_t sum = sad64x32(src_ptr, src_stride, ref_ptr, ref_stride);
5834 0 : src_ptr += src_stride << 5;
5835 0 : ref_ptr += ref_stride << 5;
5836 0 : sum += sad64x32(src_ptr, src_stride, ref_ptr, ref_stride);
5837 0 : return sum;
5838 : }
5839 :
5840 0 : unsigned int eb_aom_sad64x128_avx2(const uint8_t *src_ptr, int src_stride,
5841 : const uint8_t *ref_ptr, int ref_stride) {
5842 0 : uint32_t sum = sad64x64(src_ptr, src_stride, ref_ptr, ref_stride);
5843 0 : src_ptr += src_stride << 6;
5844 0 : ref_ptr += ref_stride << 6;
5845 0 : sum += sad64x64(src_ptr, src_stride, ref_ptr, ref_stride);
5846 0 : return sum;
5847 : }
5848 :
5849 : SIMD_INLINE void sad64x64x4d(const uint8_t *src, int src_stride,
5850 : const uint8_t *const ref[4], int ref_stride,
5851 : __m128i *res) {
5852 : uint32_t sum[4];
5853 : sad64x64x4d_avx2(src, src_stride, ref, ref_stride, sum);
5854 0 : *res = _mm_loadu_si128((const __m128i *)sum);
5855 0 : }
5856 :
5857 0 : void eb_aom_sad64x128x4d_avx2(const uint8_t *src, int src_stride,
5858 : const uint8_t *const ref[4], int ref_stride,
5859 : uint32_t res[4]) {
5860 : __m128i sum0, sum1;
5861 : const uint8_t *rf[4];
5862 :
5863 0 : rf[0] = ref[0];
5864 0 : rf[1] = ref[1];
5865 0 : rf[2] = ref[2];
5866 0 : rf[3] = ref[3];
5867 : sad64x64x4d(src, src_stride, rf, ref_stride, &sum0);
5868 0 : src += src_stride << 6;
5869 0 : rf[0] += ref_stride << 6;
5870 0 : rf[1] += ref_stride << 6;
5871 0 : rf[2] += ref_stride << 6;
5872 0 : rf[3] += ref_stride << 6;
5873 : sad64x64x4d(src, src_stride, rf, ref_stride, &sum1);
5874 0 : sum0 = _mm_add_epi32(sum0, sum1);
5875 0 : _mm_storeu_si128((__m128i *)res, sum0);
5876 0 : }
5877 :
5878 : SIMD_INLINE void sad128x64x4d_avx2(const uint8_t *src, int src_stride,
5879 : const uint8_t *const ref[4], int ref_stride,
5880 : uint32_t res[4]) {
5881 : __m128i sum0, sum1;
5882 0 : unsigned int half_width = 64;
5883 : const uint8_t *rf[4];
5884 :
5885 0 : rf[0] = ref[0];
5886 0 : rf[1] = ref[1];
5887 0 : rf[2] = ref[2];
5888 0 : rf[3] = ref[3];
5889 : sad64x64x4d(src, src_stride, rf, ref_stride, &sum0);
5890 0 : src += half_width;
5891 0 : rf[0] += half_width;
5892 0 : rf[1] += half_width;
5893 0 : rf[2] += half_width;
5894 0 : rf[3] += half_width;
5895 : sad64x64x4d(src, src_stride, rf, ref_stride, &sum1);
5896 0 : sum0 = _mm_add_epi32(sum0, sum1);
5897 0 : _mm_storeu_si128((__m128i *)res, sum0);
5898 0 : }
5899 :
5900 0 : void eb_aom_sad128x64x4d_avx2(const uint8_t *src, int src_stride,
5901 : const uint8_t *const ref[4], int ref_stride,
5902 : uint32_t res[4]) {
5903 : sad128x64x4d_avx2(src, src_stride, ref, ref_stride, res);
5904 0 : }
5905 :
5906 0 : void eb_aom_sad128x128x4d_avx2(const uint8_t *src, int src_stride,
5907 : const uint8_t *const ref[4], int ref_stride,
5908 : uint32_t res[4]) {
5909 : const uint8_t *rf[4];
5910 : uint32_t sum0[4];
5911 : uint32_t sum1[4];
5912 :
5913 0 : rf[0] = ref[0];
5914 0 : rf[1] = ref[1];
5915 0 : rf[2] = ref[2];
5916 0 : rf[3] = ref[3];
5917 : sad128x64x4d_avx2(src, src_stride, rf, ref_stride, sum0);
5918 0 : src += src_stride << 6;
5919 0 : rf[0] += ref_stride << 6;
5920 0 : rf[1] += ref_stride << 6;
5921 0 : rf[2] += ref_stride << 6;
5922 0 : rf[3] += ref_stride << 6;
5923 : sad128x64x4d_avx2(src, src_stride, rf, ref_stride, sum1);
5924 0 : res[0] = sum0[0] + sum1[0];
5925 0 : res[1] = sum0[1] + sum1[1];
5926 0 : res[2] = sum0[2] + sum1[2];
5927 0 : res[3] = sum0[3] + sum1[3];
5928 0 : }
5929 :
5930 34282600 : void ext_all_sad_calculation_8x8_16x16_avx2(
5931 : uint8_t *src,
5932 : uint32_t src_stride,
5933 : uint8_t *ref,
5934 : uint32_t ref_stride,
5935 : uint32_t mv,
5936 : uint32_t *p_best_sad8x8,
5937 : uint32_t *p_best_sad16x16,
5938 : uint32_t *p_best_mv8x8,
5939 : uint32_t *p_best_mv16x16,
5940 : uint32_t p_eight_sad16x16[16][8],
5941 : uint32_t p_eight_sad8x8[64][8])
5942 : {
5943 : static const char offsets[16] = {
5944 : 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15
5945 : };
5946 :
5947 : //---- 16x16 : 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15
5948 171158000 : for (int y = 0; y < 4; y++) {
5949 681580000 : for (int x = 0; x < 4; x++) {
5950 544705000 : const uint32_t start_16x16_pos = offsets[4 * y + x];
5951 544705000 : const uint32_t start_8x8_pos = 4 * start_16x16_pos;
5952 544705000 : const uint8_t *s = src + 16 * y * src_stride + 16 * x;
5953 544705000 : const uint8_t *r = ref + 16 * y * ref_stride + 16 * x;
5954 544705000 : __m256i sad02 = _mm256_setzero_si256();
5955 544705000 : __m256i sad13 = _mm256_setzero_si256();
5956 :
5957 2689560000 : for (int i = 0; i < 4; i++)
5958 : {
5959 2144860000 : const __m128i src01 = _mm_loadu_si128((__m128i *)(s + 0 * src_stride));
5960 4289720000 : const __m128i src23 = _mm_loadu_si128((__m128i *)(s + 8 * src_stride));
5961 2144860000 : const __m128i ref0 = _mm_loadu_si128((__m128i *)(r + 0 * ref_stride + 0));
5962 2144860000 : const __m128i ref1 = _mm_loadu_si128((__m128i *)(r + 0 * ref_stride + 8));
5963 2144860000 : const __m128i ref2 = _mm_loadu_si128((__m128i *)(r + 8 * ref_stride + 0));
5964 2144860000 : const __m128i ref3 = _mm_loadu_si128((__m128i *)(r + 8 * ref_stride + 8));
5965 2144860000 : const __m256i src0123 = _mm256_insertf128_si256(_mm256_castsi128_si256(src01), src23, 1);
5966 2144860000 : const __m256i ref02 = _mm256_insertf128_si256(_mm256_castsi128_si256(ref0), ref2, 1);
5967 2144860000 : const __m256i ref13 = _mm256_insertf128_si256(_mm256_castsi128_si256(ref1), ref3, 1);
5968 2144860000 : sad02 = _mm256_adds_epu16(sad02, _mm256_mpsadbw_epu8(ref02, src0123, 0)); // 000 000
5969 2144860000 : sad02 = _mm256_adds_epu16(sad02, _mm256_mpsadbw_epu8(ref02, src0123, 45)); // 101 101
5970 2144860000 : sad13 = _mm256_adds_epu16(sad13, _mm256_mpsadbw_epu8(ref13, src0123, 18)); // 010 010
5971 2144860000 : sad13 = _mm256_adds_epu16(sad13, _mm256_mpsadbw_epu8(ref13, src0123, 63)); // 111 111
5972 2144860000 : s += 2 * src_stride;
5973 2144860000 : r += 2 * ref_stride;
5974 : }
5975 :
5976 544705000 : sad02 = _mm256_slli_epi16(sad02, 1);
5977 544705000 : sad13 = _mm256_slli_epi16(sad13, 1);
5978 :
5979 544705000 : const __m256i sad0202 = _mm256_permute4x64_epi64(sad02, 0xD8);
5980 544705000 : const __m256i sad1313 = _mm256_permute4x64_epi64(sad13, 0xD8);
5981 1089410000 : const __m256i sad00 = _mm256_unpacklo_epi16(sad0202, _mm256_setzero_si256());
5982 1089410000 : const __m256i sad11 = _mm256_unpacklo_epi16(sad1313, _mm256_setzero_si256());
5983 1089410000 : const __m256i sad22 = _mm256_unpackhi_epi16(sad0202, _mm256_setzero_si256());
5984 544705000 : const __m256i sad33 = _mm256_unpackhi_epi16(sad1313, _mm256_setzero_si256());
5985 :
5986 544705000 : _mm256_storeu_si256((__m256i*)(p_eight_sad8x8[0 + start_8x8_pos]), sad00);
5987 544705000 : _mm256_storeu_si256((__m256i*)(p_eight_sad8x8[1 + start_8x8_pos]), sad11);
5988 544705000 : _mm256_storeu_si256((__m256i*)(p_eight_sad8x8[2 + start_8x8_pos]), sad22);
5989 544705000 : _mm256_storeu_si256((__m256i*)(p_eight_sad8x8[3 + start_8x8_pos]), sad33);
5990 :
5991 544705000 : const __m128i sad0 = _mm256_castsi256_si128(sad02);
5992 544705000 : const __m128i sad1 = _mm256_castsi256_si128(sad13);
5993 544705000 : const __m128i sad2 = _mm256_extracti128_si256(sad02, 1);
5994 544705000 : const __m128i sad3 = _mm256_extracti128_si256(sad13, 1);
5995 :
5996 544705000 : const __m128i minpos0 = _mm_minpos_epu16(sad0);
5997 544705000 : const __m128i minpos1 = _mm_minpos_epu16(sad1);
5998 544705000 : const __m128i minpos2 = _mm_minpos_epu16(sad2);
5999 544705000 : const __m128i minpos3 = _mm_minpos_epu16(sad3);
6000 :
6001 544705000 : const __m128i minpos01 = _mm_unpacklo_epi16(minpos0, minpos1);
6002 544705000 : const __m128i minpos23 = _mm_unpacklo_epi16(minpos2, minpos3);
6003 544705000 : const __m128i minpos0123 = _mm_unpacklo_epi32(minpos01, minpos23);
6004 1089410000 : const __m128i sad8x8 = _mm_unpacklo_epi16(minpos0123, _mm_setzero_si128());
6005 1089410000 : const __m128i pos0123 = _mm_unpackhi_epi16(minpos0123, _mm_setzero_si128());
6006 544705000 : const __m128i pos8x8 = _mm_slli_epi32(pos0123, 2);
6007 :
6008 1089410000 : __m128i best_sad8x8 = _mm_loadu_si128((__m128i *)(p_best_sad8x8 + start_8x8_pos));
6009 544705000 : const __m128i mask = _mm_cmplt_epi32(sad8x8, best_sad8x8);
6010 544705000 : best_sad8x8 = _mm_min_epi32(best_sad8x8, sad8x8);
6011 544705000 : _mm_storeu_si128((__m128i *)(p_best_sad8x8 + start_8x8_pos), best_sad8x8);
6012 :
6013 544705000 : __m128i best_mv8x8 = _mm_loadu_si128((__m128i *)(p_best_mv8x8 + start_8x8_pos));
6014 1089410000 : const __m128i mvs = _mm_set1_epi32(mv);
6015 544705000 : const __m128i mv8x8 = _mm_add_epi16(mvs, pos8x8);
6016 544705000 : best_mv8x8 = _mm_blendv_epi8(best_mv8x8, mv8x8, mask);
6017 544705000 : _mm_storeu_si128((__m128i *)(p_best_mv8x8 + start_8x8_pos), best_mv8x8);
6018 :
6019 544705000 : const __m128i sum01 = _mm_add_epi16(sad0, sad1);
6020 544705000 : const __m128i sum23 = _mm_add_epi16(sad2, sad3);
6021 544705000 : const __m128i sad16x16_16 = _mm_add_epi16(sum01, sum23);
6022 544705000 : const __m256i sad16x16_32 = _mm256_cvtepu16_epi32(sad16x16_16);
6023 544705000 : _mm256_storeu_si256((__m256i*)(p_eight_sad16x16[start_16x16_pos]), sad16x16_32);
6024 :
6025 544705000 : const __m128i minpos16x16 = _mm_minpos_epu16(sad16x16_16);
6026 544705000 : const uint32_t min16x16 = _mm_extract_epi16(minpos16x16, 0);
6027 :
6028 544705000 : if (min16x16 < p_best_sad16x16[start_16x16_pos]) {
6029 4025300 : p_best_sad16x16[start_16x16_pos] = min16x16;
6030 :
6031 4025300 : const __m128i pos = _mm_srli_si128(minpos16x16, 2);
6032 4025300 : const __m128i pos16x16 = _mm_slli_epi32(pos, 2);
6033 4025300 : const __m128i mv16x16 = _mm_add_epi16(mvs, pos16x16);
6034 4025300 : p_best_mv16x16[start_16x16_pos] = _mm_extract_epi32(mv16x16, 0);
6035 : }
6036 : }
6037 : }
6038 34282600 : }
6039 :
6040 : #define avx2_find_min_pos_init() \
6041 : const __m256i idx_min_pos_prv = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7)
6042 :
6043 : /* Horizontally search the minimum value in vector.
6044 : Store the minimum index in best_id.
6045 : To fast calculations, reduce available max value to 27 bits.
6046 : First call avx2_find_min_pos_init in function
6047 : */
6048 : #define avx2_find_min_pos(in, best_id) { \
6049 : __m256i x = _mm256_slli_epi32(in, 3); /* x = x<<3 | idx */\
6050 : x = _mm256_add_epi32(x, idx_min_pos_prv); /*x = [12345678]*/ \
6051 : const __m256i y = _mm256_permute2f128_si256(x, x, 1); /*y = [56781234]*/ \
6052 : const __m256i m1 = _mm256_min_epu32(x, y); /*m1 = [12341234]*/ \
6053 : const __m256i m2 = _mm256_permute4x64_epi64(m1, 5); /*m2 = [34123412]*/ \
6054 : const __m256i m3 = _mm256_min_epu32(m1, m2); /*m3 = [12121212]*/ \
6055 : const __m256i m4 = _mm256_shuffle_epi32(m3, 5); /*m4 = [21212121]*/ \
6056 : const __m256i m = _mm256_min_epu32(m3, m4); /*m5 = [11111111]*/ \
6057 : /* (x<<3 | idx) & (0b000111) = idx */ \
6058 : best_id = _mm256_extract_epi16(m, 0) & 0x07; }
6059 :
6060 34284600 : void ext_eigth_sad_calculation_nsq_avx2(
6061 : uint32_t p_sad8x8[64][8],
6062 : uint32_t p_sad16x16[16][8],
6063 : uint32_t p_sad32x32[4][8],
6064 : uint32_t *p_best_sad64x32,
6065 : uint32_t *p_best_mv64x32,
6066 : uint32_t *p_best_sad32x16,
6067 : uint32_t *p_best_mv32x16,
6068 : uint32_t *p_best_sad16x8,
6069 : uint32_t *p_best_mv16x8,
6070 : uint32_t *p_best_sad32x64,
6071 : uint32_t *p_best_mv32x64,
6072 : uint32_t *p_best_sad16x32,
6073 : uint32_t *p_best_mv16x32,
6074 : uint32_t *p_best_sad8x16,
6075 : uint32_t *p_best_mv8x16,
6076 : uint32_t *p_best_sad32x8,
6077 : uint32_t *p_best_mv32x8,
6078 : uint32_t *p_best_sad8x32,
6079 : uint32_t *p_best_mv8x32,
6080 : uint32_t *p_best_sad64x16,
6081 : uint32_t *p_best_mv64x16,
6082 : uint32_t *p_best_sad16x64,
6083 : uint32_t *p_best_mv16x64,
6084 : uint32_t mv) {
6085 34284600 : avx2_find_min_pos_init();
6086 : uint8_t search_index;
6087 : DECLARE_ALIGNED(32, uint32_t, sad[8]);
6088 : DECLARE_ALIGNED(32, uint32_t, sad_16x8[32][8]);
6089 : DECLARE_ALIGNED(32, uint32_t, sad_8x16[32][8]);
6090 : DECLARE_ALIGNED(32, uint32_t, sad_32x16[8][8]);
6091 : DECLARE_ALIGNED(32, uint32_t, sad_16x32[8][8]);
6092 : DECLARE_ALIGNED(32, uint32_t, computed_idx[8]);
6093 :
6094 34284600 : __m256i search_idx_avx2 = _mm256_setr_epi32(0, 4, 8, 12, 16, 20, 24, 28);
6095 68569300 : __m256i mv_avx2 = _mm256_set1_epi32(mv);
6096 34284600 : __m256i new_mv_avx2 = _mm256_add_epi32(search_idx_avx2, mv_avx2);
6097 68569300 : new_mv_avx2 = _mm256_and_si256(new_mv_avx2, _mm256_set1_epi32(0xffff));
6098 68569300 : *(__m256i *)computed_idx = _mm256_or_si256(new_mv_avx2,
6099 : _mm256_and_si256(mv_avx2, _mm256_set1_epi32(0xffff0000)));
6100 :
6101 : #define ADD_VECS(dst, a, b) \
6102 : *(__m256i *) dst = _mm256_add_epi32( \
6103 : _mm256_loadu_si256((__m256i const *) a), \
6104 : _mm256_loadu_si256((__m256i const *) b));
6105 :
6106 : #define SEARCH_BEST(serch, best, best_mv) \
6107 : avx2_find_min_pos(*(__m256i*)serch, search_index); \
6108 : if (serch[search_index] < best) { \
6109 : best = serch[search_index]; \
6110 : best_mv = computed_idx[search_index]; \
6111 : }
6112 :
6113 : #define SEARCH_CALC_BEST(a, b, best, best_mv) \
6114 : ADD_VECS(sad, a, b);\
6115 : SEARCH_BEST(sad, best, best_mv)
6116 :
6117 : // 32x16
6118 102854000 : ADD_VECS(sad_32x16[0], p_sad16x16[0], p_sad16x16[1]);
6119 102854000 : ADD_VECS(sad_32x16[1], p_sad16x16[2], p_sad16x16[3]);
6120 102854000 : ADD_VECS(sad_32x16[2], p_sad16x16[4], p_sad16x16[5]);
6121 102854000 : ADD_VECS(sad_32x16[3], p_sad16x16[6], p_sad16x16[7]);
6122 102854000 : ADD_VECS(sad_32x16[4], p_sad16x16[8], p_sad16x16[9]);
6123 102854000 : ADD_VECS(sad_32x16[5], p_sad16x16[10], p_sad16x16[11]);
6124 102854000 : ADD_VECS(sad_32x16[6], p_sad16x16[12], p_sad16x16[13]);
6125 102854000 : ADD_VECS(sad_32x16[7], p_sad16x16[14], p_sad16x16[15]);
6126 :
6127 : // 16x8
6128 102854000 : ADD_VECS(sad_16x8[0], p_sad8x8[0], p_sad8x8[1]);
6129 102854000 : ADD_VECS(sad_16x8[1], p_sad8x8[2], p_sad8x8[3]);
6130 102854000 : ADD_VECS(sad_16x8[2], p_sad8x8[4], p_sad8x8[5]);
6131 102854000 : ADD_VECS(sad_16x8[3], p_sad8x8[6], p_sad8x8[7]);
6132 102854000 : ADD_VECS(sad_16x8[4], p_sad8x8[8], p_sad8x8[9]);
6133 102854000 : ADD_VECS(sad_16x8[5], p_sad8x8[10], p_sad8x8[11]);
6134 102854000 : ADD_VECS(sad_16x8[6], p_sad8x8[12], p_sad8x8[13]);
6135 102854000 : ADD_VECS(sad_16x8[7], p_sad8x8[14], p_sad8x8[15]);
6136 102854000 : ADD_VECS(sad_16x8[8], p_sad8x8[16], p_sad8x8[17]);
6137 102854000 : ADD_VECS(sad_16x8[9], p_sad8x8[18], p_sad8x8[19]);
6138 102854000 : ADD_VECS(sad_16x8[10], p_sad8x8[20], p_sad8x8[21]);
6139 102854000 : ADD_VECS(sad_16x8[11], p_sad8x8[22], p_sad8x8[23]);
6140 102854000 : ADD_VECS(sad_16x8[12], p_sad8x8[24], p_sad8x8[25]);
6141 102854000 : ADD_VECS(sad_16x8[13], p_sad8x8[26], p_sad8x8[27]);
6142 102854000 : ADD_VECS(sad_16x8[14], p_sad8x8[28], p_sad8x8[29]);
6143 102854000 : ADD_VECS(sad_16x8[15], p_sad8x8[30], p_sad8x8[31]);
6144 102854000 : ADD_VECS(sad_16x8[16], p_sad8x8[32], p_sad8x8[33]);
6145 102854000 : ADD_VECS(sad_16x8[17], p_sad8x8[34], p_sad8x8[35]);
6146 102854000 : ADD_VECS(sad_16x8[18], p_sad8x8[36], p_sad8x8[37]);
6147 102854000 : ADD_VECS(sad_16x8[19], p_sad8x8[38], p_sad8x8[39]);
6148 102854000 : ADD_VECS(sad_16x8[20], p_sad8x8[40], p_sad8x8[41]);
6149 102854000 : ADD_VECS(sad_16x8[21], p_sad8x8[42], p_sad8x8[43]);
6150 102854000 : ADD_VECS(sad_16x8[22], p_sad8x8[44], p_sad8x8[45]);
6151 102854000 : ADD_VECS(sad_16x8[23], p_sad8x8[46], p_sad8x8[47]);
6152 102854000 : ADD_VECS(sad_16x8[24], p_sad8x8[48], p_sad8x8[49]);
6153 102854000 : ADD_VECS(sad_16x8[25], p_sad8x8[50], p_sad8x8[51]);
6154 102854000 : ADD_VECS(sad_16x8[26], p_sad8x8[52], p_sad8x8[53]);
6155 102854000 : ADD_VECS(sad_16x8[27], p_sad8x8[54], p_sad8x8[55]);
6156 102854000 : ADD_VECS(sad_16x8[28], p_sad8x8[56], p_sad8x8[57]);
6157 102854000 : ADD_VECS(sad_16x8[29], p_sad8x8[58], p_sad8x8[59]);
6158 102854000 : ADD_VECS(sad_16x8[30], p_sad8x8[60], p_sad8x8[61]);
6159 102854000 : ADD_VECS(sad_16x8[31], p_sad8x8[62], p_sad8x8[63]);
6160 : // 16x32
6161 102854000 : ADD_VECS(sad_16x32[0], p_sad16x16[0], p_sad16x16[2]);
6162 102854000 : ADD_VECS(sad_16x32[1], p_sad16x16[1], p_sad16x16[3]);
6163 102854000 : ADD_VECS(sad_16x32[2], p_sad16x16[4], p_sad16x16[6]);
6164 102854000 : ADD_VECS(sad_16x32[3], p_sad16x16[5], p_sad16x16[7]);
6165 102854000 : ADD_VECS(sad_16x32[4], p_sad16x16[8], p_sad16x16[10]);
6166 102854000 : ADD_VECS(sad_16x32[5], p_sad16x16[9], p_sad16x16[11]);
6167 102854000 : ADD_VECS(sad_16x32[6], p_sad16x16[12], p_sad16x16[14]);
6168 102854000 : ADD_VECS(sad_16x32[7], p_sad16x16[13], p_sad16x16[15]);
6169 : // 8x16
6170 102854000 : ADD_VECS(sad_8x16[0], p_sad8x8[0], p_sad8x8[2]);
6171 102854000 : ADD_VECS(sad_8x16[1], p_sad8x8[1], p_sad8x8[3]);
6172 102854000 : ADD_VECS(sad_8x16[2], p_sad8x8[4], p_sad8x8[6]);
6173 102854000 : ADD_VECS(sad_8x16[3], p_sad8x8[5], p_sad8x8[7]);
6174 102854000 : ADD_VECS(sad_8x16[4], p_sad8x8[8], p_sad8x8[10]);
6175 102854000 : ADD_VECS(sad_8x16[5], p_sad8x8[9], p_sad8x8[11]);
6176 102854000 : ADD_VECS(sad_8x16[6], p_sad8x8[12], p_sad8x8[14]);
6177 102854000 : ADD_VECS(sad_8x16[7], p_sad8x8[13], p_sad8x8[15]);
6178 102854000 : ADD_VECS(sad_8x16[8], p_sad8x8[16], p_sad8x8[18]);
6179 102854000 : ADD_VECS(sad_8x16[9], p_sad8x8[17], p_sad8x8[19]);
6180 102854000 : ADD_VECS(sad_8x16[10], p_sad8x8[20], p_sad8x8[22]);
6181 102854000 : ADD_VECS(sad_8x16[11], p_sad8x8[21], p_sad8x8[23]);
6182 102854000 : ADD_VECS(sad_8x16[12], p_sad8x8[24], p_sad8x8[26]);
6183 102854000 : ADD_VECS(sad_8x16[13], p_sad8x8[25], p_sad8x8[27]);
6184 102854000 : ADD_VECS(sad_8x16[14], p_sad8x8[28], p_sad8x8[30]);
6185 102854000 : ADD_VECS(sad_8x16[15], p_sad8x8[29], p_sad8x8[31]);
6186 102854000 : ADD_VECS(sad_8x16[16], p_sad8x8[32], p_sad8x8[34]);
6187 102854000 : ADD_VECS(sad_8x16[17], p_sad8x8[33], p_sad8x8[35]);
6188 102854000 : ADD_VECS(sad_8x16[18], p_sad8x8[36], p_sad8x8[38]);
6189 102854000 : ADD_VECS(sad_8x16[19], p_sad8x8[37], p_sad8x8[39]);
6190 102854000 : ADD_VECS(sad_8x16[20], p_sad8x8[40], p_sad8x8[42]);
6191 102854000 : ADD_VECS(sad_8x16[21], p_sad8x8[41], p_sad8x8[43]);
6192 102854000 : ADD_VECS(sad_8x16[22], p_sad8x8[44], p_sad8x8[46]);
6193 102854000 : ADD_VECS(sad_8x16[23], p_sad8x8[45], p_sad8x8[47]);
6194 102854000 : ADD_VECS(sad_8x16[24], p_sad8x8[48], p_sad8x8[50]);
6195 102854000 : ADD_VECS(sad_8x16[25], p_sad8x8[49], p_sad8x8[51]);
6196 102854000 : ADD_VECS(sad_8x16[26], p_sad8x8[52], p_sad8x8[54]);
6197 102854000 : ADD_VECS(sad_8x16[27], p_sad8x8[53], p_sad8x8[55]);
6198 102854000 : ADD_VECS(sad_8x16[28], p_sad8x8[56], p_sad8x8[58]);
6199 102854000 : ADD_VECS(sad_8x16[29], p_sad8x8[57], p_sad8x8[59]);
6200 102854000 : ADD_VECS(sad_8x16[30], p_sad8x8[60], p_sad8x8[62]);
6201 102854000 : ADD_VECS(sad_8x16[31], p_sad8x8[61], p_sad8x8[63]);
6202 :
6203 : // 32x16
6204 205708000 : SEARCH_BEST(sad_32x16[0], p_best_sad32x16[0], p_best_mv32x16[0]);
6205 205708000 : SEARCH_BEST(sad_32x16[1], p_best_sad32x16[1], p_best_mv32x16[1]);
6206 205708000 : SEARCH_BEST(sad_32x16[2], p_best_sad32x16[2], p_best_mv32x16[2]);
6207 205708000 : SEARCH_BEST(sad_32x16[3], p_best_sad32x16[3], p_best_mv32x16[3]);
6208 205708000 : SEARCH_BEST(sad_32x16[4], p_best_sad32x16[4], p_best_mv32x16[4]);
6209 205708000 : SEARCH_BEST(sad_32x16[5], p_best_sad32x16[5], p_best_mv32x16[5]);
6210 205708000 : SEARCH_BEST(sad_32x16[6], p_best_sad32x16[6], p_best_mv32x16[6]);
6211 205708000 : SEARCH_BEST(sad_32x16[7], p_best_sad32x16[7], p_best_mv32x16[7]);
6212 : // 16x8
6213 205708000 : SEARCH_BEST(sad_16x8[0], p_best_sad16x8[0], p_best_mv16x8[0]);
6214 205708000 : SEARCH_BEST(sad_16x8[1], p_best_sad16x8[1], p_best_mv16x8[1]);
6215 205708000 : SEARCH_BEST(sad_16x8[2], p_best_sad16x8[2], p_best_mv16x8[2]);
6216 205708000 : SEARCH_BEST(sad_16x8[3], p_best_sad16x8[3], p_best_mv16x8[3]);
6217 205708000 : SEARCH_BEST(sad_16x8[4], p_best_sad16x8[4], p_best_mv16x8[4]);
6218 205708000 : SEARCH_BEST(sad_16x8[5], p_best_sad16x8[5], p_best_mv16x8[5]);
6219 205708000 : SEARCH_BEST(sad_16x8[6], p_best_sad16x8[6], p_best_mv16x8[6]);
6220 205708000 : SEARCH_BEST(sad_16x8[7], p_best_sad16x8[7], p_best_mv16x8[7]);
6221 205708000 : SEARCH_BEST(sad_16x8[8], p_best_sad16x8[8], p_best_mv16x8[8]);
6222 205708000 : SEARCH_BEST(sad_16x8[9], p_best_sad16x8[9], p_best_mv16x8[9]);
6223 205708000 : SEARCH_BEST(sad_16x8[10], p_best_sad16x8[10], p_best_mv16x8[10]);
6224 205708000 : SEARCH_BEST(sad_16x8[11], p_best_sad16x8[11], p_best_mv16x8[11]);
6225 205708000 : SEARCH_BEST(sad_16x8[12], p_best_sad16x8[12], p_best_mv16x8[12]);
6226 205708000 : SEARCH_BEST(sad_16x8[13], p_best_sad16x8[13], p_best_mv16x8[13]);
6227 205708000 : SEARCH_BEST(sad_16x8[14], p_best_sad16x8[14], p_best_mv16x8[14]);
6228 205708000 : SEARCH_BEST(sad_16x8[15], p_best_sad16x8[15], p_best_mv16x8[15]);
6229 205708000 : SEARCH_BEST(sad_16x8[16], p_best_sad16x8[16], p_best_mv16x8[16]);
6230 205708000 : SEARCH_BEST(sad_16x8[17], p_best_sad16x8[17], p_best_mv16x8[17]);
6231 205708000 : SEARCH_BEST(sad_16x8[18], p_best_sad16x8[18], p_best_mv16x8[18]);
6232 205708000 : SEARCH_BEST(sad_16x8[19], p_best_sad16x8[19], p_best_mv16x8[19]);
6233 205708000 : SEARCH_BEST(sad_16x8[20], p_best_sad16x8[20], p_best_mv16x8[20]);
6234 205708000 : SEARCH_BEST(sad_16x8[21], p_best_sad16x8[21], p_best_mv16x8[21]);
6235 205708000 : SEARCH_BEST(sad_16x8[22], p_best_sad16x8[22], p_best_mv16x8[22]);
6236 205708000 : SEARCH_BEST(sad_16x8[23], p_best_sad16x8[23], p_best_mv16x8[23]);
6237 205708000 : SEARCH_BEST(sad_16x8[24], p_best_sad16x8[24], p_best_mv16x8[24]);
6238 205708000 : SEARCH_BEST(sad_16x8[25], p_best_sad16x8[25], p_best_mv16x8[25]);
6239 205708000 : SEARCH_BEST(sad_16x8[26], p_best_sad16x8[26], p_best_mv16x8[26]);
6240 205708000 : SEARCH_BEST(sad_16x8[27], p_best_sad16x8[27], p_best_mv16x8[27]);
6241 205708000 : SEARCH_BEST(sad_16x8[28], p_best_sad16x8[28], p_best_mv16x8[28]);
6242 205708000 : SEARCH_BEST(sad_16x8[29], p_best_sad16x8[29], p_best_mv16x8[29]);
6243 205708000 : SEARCH_BEST(sad_16x8[30], p_best_sad16x8[30], p_best_mv16x8[30]);
6244 205708000 : SEARCH_BEST(sad_16x8[31], p_best_sad16x8[31], p_best_mv16x8[31]);
6245 : // 16x32
6246 205708000 : SEARCH_BEST(sad_16x32[0], p_best_sad16x32[0], p_best_mv16x32[0]);
6247 205708000 : SEARCH_BEST(sad_16x32[1], p_best_sad16x32[1], p_best_mv16x32[1]);
6248 205708000 : SEARCH_BEST(sad_16x32[2], p_best_sad16x32[2], p_best_mv16x32[2]);
6249 205708000 : SEARCH_BEST(sad_16x32[3], p_best_sad16x32[3], p_best_mv16x32[3]);
6250 205708000 : SEARCH_BEST(sad_16x32[4], p_best_sad16x32[4], p_best_mv16x32[4]);
6251 205708000 : SEARCH_BEST(sad_16x32[5], p_best_sad16x32[5], p_best_mv16x32[5]);
6252 205708000 : SEARCH_BEST(sad_16x32[6], p_best_sad16x32[6], p_best_mv16x32[6]);
6253 205708000 : SEARCH_BEST(sad_16x32[7], p_best_sad16x32[7], p_best_mv16x32[7]);
6254 : // 8x16
6255 205708000 : SEARCH_BEST(sad_8x16[0], p_best_sad8x16[0], p_best_mv8x16[0]);
6256 205708000 : SEARCH_BEST(sad_8x16[1], p_best_sad8x16[1], p_best_mv8x16[1]);
6257 205708000 : SEARCH_BEST(sad_8x16[2], p_best_sad8x16[2], p_best_mv8x16[2]);
6258 205708000 : SEARCH_BEST(sad_8x16[3], p_best_sad8x16[3], p_best_mv8x16[3]);
6259 205708000 : SEARCH_BEST(sad_8x16[4], p_best_sad8x16[4], p_best_mv8x16[4]);
6260 205708000 : SEARCH_BEST(sad_8x16[5], p_best_sad8x16[5], p_best_mv8x16[5]);
6261 205708000 : SEARCH_BEST(sad_8x16[6], p_best_sad8x16[6], p_best_mv8x16[6]);
6262 205708000 : SEARCH_BEST(sad_8x16[7], p_best_sad8x16[7], p_best_mv8x16[7]);
6263 205708000 : SEARCH_BEST(sad_8x16[8], p_best_sad8x16[8], p_best_mv8x16[8]);
6264 205708000 : SEARCH_BEST(sad_8x16[9], p_best_sad8x16[9], p_best_mv8x16[9]);
6265 205708000 : SEARCH_BEST(sad_8x16[10], p_best_sad8x16[10], p_best_mv8x16[10]);
6266 205708000 : SEARCH_BEST(sad_8x16[11], p_best_sad8x16[11], p_best_mv8x16[11]);
6267 205708000 : SEARCH_BEST(sad_8x16[12], p_best_sad8x16[12], p_best_mv8x16[12]);
6268 205708000 : SEARCH_BEST(sad_8x16[13], p_best_sad8x16[13], p_best_mv8x16[13]);
6269 205708000 : SEARCH_BEST(sad_8x16[14], p_best_sad8x16[14], p_best_mv8x16[14]);
6270 205708000 : SEARCH_BEST(sad_8x16[15], p_best_sad8x16[15], p_best_mv8x16[15]);
6271 205708000 : SEARCH_BEST(sad_8x16[16], p_best_sad8x16[16], p_best_mv8x16[16]);
6272 205708000 : SEARCH_BEST(sad_8x16[17], p_best_sad8x16[17], p_best_mv8x16[17]);
6273 205708000 : SEARCH_BEST(sad_8x16[18], p_best_sad8x16[18], p_best_mv8x16[18]);
6274 205708000 : SEARCH_BEST(sad_8x16[19], p_best_sad8x16[19], p_best_mv8x16[19]);
6275 205708000 : SEARCH_BEST(sad_8x16[20], p_best_sad8x16[20], p_best_mv8x16[20]);
6276 205708000 : SEARCH_BEST(sad_8x16[21], p_best_sad8x16[21], p_best_mv8x16[21]);
6277 205708000 : SEARCH_BEST(sad_8x16[22], p_best_sad8x16[22], p_best_mv8x16[22]);
6278 205708000 : SEARCH_BEST(sad_8x16[23], p_best_sad8x16[23], p_best_mv8x16[23]);
6279 205708000 : SEARCH_BEST(sad_8x16[24], p_best_sad8x16[24], p_best_mv8x16[24]);
6280 205708000 : SEARCH_BEST(sad_8x16[25], p_best_sad8x16[25], p_best_mv8x16[25]);
6281 205708000 : SEARCH_BEST(sad_8x16[26], p_best_sad8x16[26], p_best_mv8x16[26]);
6282 205708000 : SEARCH_BEST(sad_8x16[27], p_best_sad8x16[27], p_best_mv8x16[27]);
6283 205708000 : SEARCH_BEST(sad_8x16[28], p_best_sad8x16[28], p_best_mv8x16[28]);
6284 205708000 : SEARCH_BEST(sad_8x16[29], p_best_sad8x16[29], p_best_mv8x16[29]);
6285 205708000 : SEARCH_BEST(sad_8x16[30], p_best_sad8x16[30], p_best_mv8x16[30]);
6286 205708000 : SEARCH_BEST(sad_8x16[31], p_best_sad8x16[31], p_best_mv8x16[31]);
6287 :
6288 308562000 : SEARCH_CALC_BEST(p_sad32x32[0], p_sad32x32[1], p_best_sad64x32[0],
6289 : p_best_mv64x32[0]);
6290 308562000 : SEARCH_CALC_BEST(p_sad32x32[2], p_sad32x32[3], p_best_sad64x32[1],
6291 : p_best_mv64x32[1]);
6292 274277000 : SEARCH_CALC_BEST(sad_32x16[0], sad_32x16[2], p_best_sad64x16[0],
6293 : p_best_mv64x16[0]);
6294 274277000 : SEARCH_CALC_BEST(sad_32x16[1], sad_32x16[3], p_best_sad64x16[1],
6295 : p_best_mv64x16[1]);
6296 274277000 : SEARCH_CALC_BEST(sad_32x16[4], sad_32x16[6], p_best_sad64x16[2],
6297 : p_best_mv64x16[2]);
6298 274277000 : SEARCH_CALC_BEST(sad_32x16[5], sad_32x16[7], p_best_sad64x16[3],
6299 : p_best_mv64x16[3]);
6300 308562000 : SEARCH_CALC_BEST(p_sad32x32[0], p_sad32x32[2], p_best_sad32x64[0],
6301 : p_best_mv32x64[0]);
6302 308562000 : SEARCH_CALC_BEST(p_sad32x32[1], p_sad32x32[3], p_best_sad32x64[1],
6303 : p_best_mv32x64[1]);
6304 274277000 : SEARCH_CALC_BEST(sad_16x32[0], sad_16x32[4], p_best_sad16x64[0],
6305 : p_best_mv16x64[0]);
6306 274277000 : SEARCH_CALC_BEST(sad_16x32[1], sad_16x32[5], p_best_sad16x64[1],
6307 : p_best_mv16x64[1]);
6308 274277000 : SEARCH_CALC_BEST(sad_16x32[2], sad_16x32[6], p_best_sad16x64[2],
6309 : p_best_mv16x64[2]);
6310 274277000 : SEARCH_CALC_BEST(sad_16x32[3], sad_16x32[7], p_best_sad16x64[3],
6311 : p_best_mv16x64[3]);
6312 274277000 : SEARCH_CALC_BEST(sad_16x8[0], sad_16x8[2], p_best_sad32x8[0],
6313 : p_best_mv32x8[0]);
6314 274277000 : SEARCH_CALC_BEST(sad_16x8[1], sad_16x8[3], p_best_sad32x8[1],
6315 : p_best_mv32x8[1]);
6316 274277000 : SEARCH_CALC_BEST(sad_16x8[4], sad_16x8[6], p_best_sad32x8[2],
6317 : p_best_mv32x8[2]);
6318 274277000 : SEARCH_CALC_BEST(sad_16x8[5], sad_16x8[7], p_best_sad32x8[3],
6319 : p_best_mv32x8[3]);
6320 274277000 : SEARCH_CALC_BEST(sad_16x8[8], sad_16x8[10], p_best_sad32x8[4],
6321 : p_best_mv32x8[4]);
6322 274277000 : SEARCH_CALC_BEST(sad_16x8[9], sad_16x8[11], p_best_sad32x8[5],
6323 : p_best_mv32x8[5]);
6324 274277000 : SEARCH_CALC_BEST(sad_16x8[12], sad_16x8[14], p_best_sad32x8[6],
6325 : p_best_mv32x8[6]);
6326 274277000 : SEARCH_CALC_BEST(sad_16x8[13], sad_16x8[15], p_best_sad32x8[7],
6327 : p_best_mv32x8[7]);
6328 274277000 : SEARCH_CALC_BEST(sad_16x8[16], sad_16x8[18], p_best_sad32x8[8],
6329 : p_best_mv32x8[8]);
6330 274277000 : SEARCH_CALC_BEST(sad_16x8[17], sad_16x8[19], p_best_sad32x8[9],
6331 : p_best_mv32x8[9]);
6332 274277000 : SEARCH_CALC_BEST(sad_16x8[20], sad_16x8[22], p_best_sad32x8[10],
6333 : p_best_mv32x8[10]);
6334 274277000 : SEARCH_CALC_BEST(sad_16x8[21], sad_16x8[23], p_best_sad32x8[11],
6335 : p_best_mv32x8[11]);
6336 274277000 : SEARCH_CALC_BEST(sad_16x8[24], sad_16x8[26], p_best_sad32x8[12],
6337 : p_best_mv32x8[12]);
6338 274277000 : SEARCH_CALC_BEST(sad_16x8[25], sad_16x8[27], p_best_sad32x8[13],
6339 : p_best_mv32x8[13]);
6340 274277000 : SEARCH_CALC_BEST(sad_16x8[28], sad_16x8[30], p_best_sad32x8[14],
6341 : p_best_mv32x8[14]);
6342 274277000 : SEARCH_CALC_BEST(sad_16x8[29], sad_16x8[31], p_best_sad32x8[15],
6343 : p_best_mv32x8[15]);
6344 274277000 : SEARCH_CALC_BEST(sad_8x16[0], sad_8x16[4], p_best_sad8x32[0],
6345 : p_best_mv8x32[0]);
6346 274277000 : SEARCH_CALC_BEST(sad_8x16[1], sad_8x16[5], p_best_sad8x32[1],
6347 : p_best_mv8x32[1]);
6348 274277000 : SEARCH_CALC_BEST(sad_8x16[2], sad_8x16[6], p_best_sad8x32[2],
6349 : p_best_mv8x32[2]);
6350 274277000 : SEARCH_CALC_BEST(sad_8x16[3], sad_8x16[7], p_best_sad8x32[3],
6351 : p_best_mv8x32[3]);
6352 274277000 : SEARCH_CALC_BEST(sad_8x16[8], sad_8x16[12], p_best_sad8x32[4],
6353 : p_best_mv8x32[4]);
6354 274277000 : SEARCH_CALC_BEST(sad_8x16[9], sad_8x16[13], p_best_sad8x32[5],
6355 : p_best_mv8x32[5]);
6356 274277000 : SEARCH_CALC_BEST(sad_8x16[10], sad_8x16[14], p_best_sad8x32[6],
6357 : p_best_mv8x32[6]);
6358 274277000 : SEARCH_CALC_BEST(sad_8x16[11], sad_8x16[15], p_best_sad8x32[7],
6359 : p_best_mv8x32[7]);
6360 274277000 : SEARCH_CALC_BEST(sad_8x16[16], sad_8x16[20], p_best_sad8x32[8],
6361 : p_best_mv8x32[8]);
6362 274277000 : SEARCH_CALC_BEST(sad_8x16[17], sad_8x16[21], p_best_sad8x32[9],
6363 : p_best_mv8x32[9]);
6364 274277000 : SEARCH_CALC_BEST(sad_8x16[18], sad_8x16[22], p_best_sad8x32[10],
6365 : p_best_mv8x32[10]);
6366 274277000 : SEARCH_CALC_BEST(sad_8x16[19], sad_8x16[23], p_best_sad8x32[11],
6367 : p_best_mv8x32[11]);
6368 274277000 : SEARCH_CALC_BEST(sad_8x16[24], sad_8x16[28], p_best_sad8x32[12],
6369 : p_best_mv8x32[12]);
6370 274277000 : SEARCH_CALC_BEST(sad_8x16[25], sad_8x16[29], p_best_sad8x32[13],
6371 : p_best_mv8x32[13]);
6372 274277000 : SEARCH_CALC_BEST(sad_8x16[26], sad_8x16[30], p_best_sad8x32[14],
6373 : p_best_mv8x32[14]);
6374 274277000 : SEARCH_CALC_BEST(sad_8x16[27], sad_8x16[31], p_best_sad8x32[15],
6375 : p_best_mv8x32[15]);
6376 :
6377 : #undef SEARCH_CALC_BEST
6378 : #undef SEARCH_BEST
6379 : #undef ADD_VECS
6380 34284600 : }
6381 :
6382 34293400 : void ext_eight_sad_calculation_32x32_64x64_avx2(
6383 : uint32_t p_sad16x16[16][8],
6384 : uint32_t *p_best_sad32x32,
6385 : uint32_t *p_best_sad64x64,
6386 : uint32_t *p_best_mv32x32,
6387 : uint32_t *p_best_mv64x64,
6388 : uint32_t mv,
6389 : uint32_t p_sad32x32[4][8]) {
6390 34293400 : avx2_find_min_pos_init();
6391 : uint32_t si_a, si_b, si_c, si_d, si_e;
6392 :
6393 68586800 : const __m256i tmp0 = _mm256_add_epi32(
6394 : _mm256_loadu_si256((__m256i const *)p_sad16x16[0]),
6395 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[1]));
6396 :
6397 68586800 : const __m256i tmp1 = _mm256_add_epi32(
6398 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[2]),
6399 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[3]));
6400 :
6401 34293400 : const __m256i sad32_a = _mm256_add_epi32(tmp0, tmp1);
6402 : _mm256_storeu_si256((__m256i *)p_sad32x32[0], sad32_a);
6403 :
6404 34293400 : const __m256i tmp2 = _mm256_add_epi32(
6405 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[4]),
6406 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[5]));
6407 :
6408 68586800 : const __m256i tmp3 = _mm256_add_epi32(
6409 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[6]),
6410 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[7]));
6411 :
6412 34293400 : const __m256i sad32_b = _mm256_add_epi32(tmp2, tmp3);
6413 34293400 : _mm256_storeu_si256((__m256i *)p_sad32x32[1], sad32_b);
6414 :
6415 34293400 : const __m256i tmp4 = _mm256_add_epi32(
6416 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[8]),
6417 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[9]));
6418 :
6419 68586800 : const __m256i tmp5 = _mm256_add_epi32(
6420 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[10]),
6421 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[11]));
6422 :
6423 34293400 : const __m256i sad32_c = _mm256_add_epi32(tmp4, tmp5);
6424 34293400 : _mm256_storeu_si256((__m256i *)p_sad32x32[2], sad32_c);
6425 :
6426 34293400 : const __m256i tmp6 = _mm256_add_epi32(
6427 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[12]),
6428 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[13]));
6429 :
6430 68586800 : const __m256i tmp7 = _mm256_add_epi32(
6431 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[14]),
6432 34293400 : _mm256_loadu_si256((__m256i const *)p_sad16x16[15]));
6433 :
6434 34293400 : const __m256i sad32_d = _mm256_add_epi32(tmp6, tmp7);
6435 34293400 : _mm256_storeu_si256((__m256i *)p_sad32x32[3], sad32_d);
6436 :
6437 : DECLARE_ALIGNED(32, uint32_t, sad64x64[8]);
6438 34293400 : const __m256i tmp8 = _mm256_add_epi32(sad32_a, sad32_b);
6439 34293400 : const __m256i tmp9 = _mm256_add_epi32(sad32_c, sad32_d);
6440 68586800 : *((__m256i *)sad64x64) = _mm256_add_epi32(tmp8, tmp9);
6441 :
6442 : DECLARE_ALIGNED(32, uint32_t, computed_idx[8]);
6443 34293400 : __m256i search_idx_avx2 = _mm256_setr_epi32(0, 4, 8, 12, 16, 20, 24, 28);
6444 68586800 : __m256i mv_avx2 = _mm256_set1_epi32(mv);
6445 34293400 : __m256i new_mv_avx2 = _mm256_add_epi32(search_idx_avx2, mv_avx2);
6446 68586800 : new_mv_avx2 = _mm256_and_si256(new_mv_avx2, _mm256_set1_epi32(0xffff));
6447 102880000 : *(__m256i *)computed_idx = _mm256_or_si256(
6448 : new_mv_avx2, _mm256_and_si256(mv_avx2, _mm256_set1_epi32(0xffff0000)));
6449 :
6450 171467000 : avx2_find_min_pos(sad32_a, si_a);
6451 171467000 : avx2_find_min_pos(sad32_b, si_b);
6452 171467000 : avx2_find_min_pos(sad32_c, si_c);
6453 137174000 : avx2_find_min_pos(sad32_d, si_d);
6454 171467000 : avx2_find_min_pos(*(__m256i*)sad64x64, si_e);
6455 :
6456 34293400 : if (p_sad32x32[0][si_a] < p_best_sad32x32[0]) {
6457 362090 : p_best_sad32x32[0] = p_sad32x32[0][si_a];
6458 362090 : p_best_mv32x32[0] = computed_idx[si_a];
6459 : }
6460 :
6461 34293400 : if (p_sad32x32[1][si_b] < p_best_sad32x32[1]) {
6462 381543 : p_best_sad32x32[1] = p_sad32x32[1][si_b];
6463 381543 : p_best_mv32x32[1] = computed_idx[si_b];
6464 : }
6465 :
6466 34293400 : if (p_sad32x32[2][si_c] < p_best_sad32x32[2]) {
6467 399085 : p_best_sad32x32[2] = p_sad32x32[2][si_c];
6468 399085 : p_best_mv32x32[2] = computed_idx[si_c];
6469 : }
6470 :
6471 34293400 : if (p_sad32x32[3][si_d] < p_best_sad32x32[3]) {
6472 420474 : p_best_sad32x32[3] = p_sad32x32[3][si_d];
6473 420474 : p_best_mv32x32[3] = computed_idx[si_d];
6474 : }
6475 :
6476 34293400 : if (sad64x64[si_e] < p_best_sad64x64[0]) {
6477 640618 : p_best_sad64x64[0] = sad64x64[si_e];
6478 640618 : p_best_mv64x64[0] = computed_idx[si_e];
6479 : }
6480 34293400 : }
6481 :
6482 :
6483 125061000 : uint32_t nxm_sad_kernel_sub_sampled_helper_avx2(
6484 : const uint8_t *src,
6485 : uint32_t src_stride,
6486 : const uint8_t *ref,
6487 : uint32_t ref_stride,
6488 : uint32_t height,
6489 : uint32_t width)
6490 : {
6491 125061000 : uint32_t nxm_sad = 0;
6492 :
6493 125061000 : switch (width) {
6494 10956200 : case 4:
6495 10956200 : nxm_sad = eb_compute4x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6496 51512300 : case 8:
6497 51512300 : nxm_sad = eb_compute8x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6498 38875200 : case 16:
6499 38875200 : nxm_sad = eb_compute16x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6500 0 : case 24:
6501 0 : nxm_sad = fast_loop_nxm_sad_kernel(src, src_stride, ref, ref_stride, height, width); break;
6502 18907600 : case 32:
6503 18907600 : nxm_sad = eb_compute32x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6504 0 : case 48:
6505 0 : nxm_sad = fast_loop_nxm_sad_kernel(src, src_stride, ref, ref_stride, height, width); break;
6506 5089090 : case 64:
6507 5089090 : nxm_sad = eb_compute64x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6508 0 : case 128:
6509 0 : nxm_sad = fast_loop_nxm_sad_kernel(src, src_stride, ref, ref_stride, height, width); break;
6510 125174000 : default:
6511 : assert(0);
6512 : }
6513 :
6514 125174000 : return nxm_sad;
6515 : };
6516 :
6517 22985400 : uint32_t nxm_sad_kernel_helper_avx2(
6518 : const uint8_t *src,
6519 : uint32_t src_stride,
6520 : const uint8_t *ref,
6521 : uint32_t ref_stride,
6522 : uint32_t height,
6523 : uint32_t width)
6524 : {
6525 :
6526 22985400 : uint32_t nxm_sad = 0;
6527 :
6528 22985400 : switch (width) {
6529 0 : case 4:
6530 0 : nxm_sad = eb_compute4x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6531 12654100 : case 8:
6532 12654100 : nxm_sad = eb_compute8x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6533 6309380 : case 16:
6534 6309380 : nxm_sad = eb_compute16x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6535 0 : case 24:
6536 0 : nxm_sad = eb_compute24x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6537 3228780 : case 32:
6538 3228780 : nxm_sad = eb_compute32x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6539 0 : case 48:
6540 0 : nxm_sad = eb_compute48x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6541 846887 : case 64:
6542 846887 : nxm_sad = eb_compute64x_m_sad_avx2_intrin(src, src_stride, ref, ref_stride, height, width); break;
6543 0 : case 40:
6544 : case 52:
6545 0 : break; //void_func();
6546 22989600 : default:
6547 : assert(0);
6548 : }
6549 :
6550 22989600 : return nxm_sad;
6551 : }
6552 :
6553 :
|