Line data Source code
1 : /*
2 : * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3 : *
4 : * This source code is subject to the terms of the BSD 2 Clause License and
5 : * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 : * was not distributed with this source code in the LICENSE file, you can
7 : * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 : * Media Patent License 1.0 was not distributed with this source code in the
9 : * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 : */
11 :
12 : #include <immintrin.h>
13 :
14 : #include "./aom_config.h"
15 : #include "./aom_dsp_rtcd.h"
16 :
17 : #include "aom/aom_integer.h"
18 : #include "aom_ports/mem.h"
19 :
20 : // SAD
21 0 : static INLINE unsigned int get_sad_from_mm256_epi32(const __m256i *v) {
22 : // input 8 32-bit summation
23 : __m128i lo128, hi128;
24 0 : __m256i u = _mm256_srli_si256(*v, 8);
25 0 : u = _mm256_add_epi32(u, *v);
26 :
27 : // 4 32-bit summation
28 0 : hi128 = _mm256_extracti128_si256(u, 1);
29 0 : lo128 = _mm256_castsi256_si128(u);
30 0 : lo128 = _mm_add_epi32(hi128, lo128);
31 :
32 : // 2 32-bit summation
33 0 : hi128 = _mm_srli_si128(lo128, 4);
34 0 : lo128 = _mm_add_epi32(lo128, hi128);
35 :
36 0 : return (unsigned int)_mm_cvtsi128_si32(lo128);
37 : }
38 :
39 0 : unsigned int aom_highbd_sad16x8_avx2(const uint8_t *src, int src_stride,
40 : const uint8_t *ref, int ref_stride) {
41 0 : const uint16_t *src_ptr = CONVERT_TO_SHORTPTR(src);
42 0 : const uint16_t *ref_ptr = CONVERT_TO_SHORTPTR(ref);
43 :
44 : // first 4 rows
45 0 : __m256i s0 = _mm256_loadu_si256((const __m256i *)src_ptr);
46 0 : __m256i s1 = _mm256_loadu_si256((const __m256i *)(src_ptr + src_stride));
47 0 : __m256i s2 = _mm256_loadu_si256((const __m256i *)(src_ptr + 2 * src_stride));
48 0 : __m256i s3 = _mm256_loadu_si256((const __m256i *)(src_ptr + 3 * src_stride));
49 :
50 0 : __m256i r0 = _mm256_loadu_si256((const __m256i *)ref_ptr);
51 0 : __m256i r1 = _mm256_loadu_si256((const __m256i *)(ref_ptr + ref_stride));
52 0 : __m256i r2 = _mm256_loadu_si256((const __m256i *)(ref_ptr + 2 * ref_stride));
53 0 : __m256i r3 = _mm256_loadu_si256((const __m256i *)(ref_ptr + 3 * ref_stride));
54 :
55 0 : __m256i u0 = _mm256_sub_epi16(s0, r0);
56 0 : __m256i u1 = _mm256_sub_epi16(s1, r1);
57 0 : __m256i u2 = _mm256_sub_epi16(s2, r2);
58 0 : __m256i u3 = _mm256_sub_epi16(s3, r3);
59 0 : __m256i zero = _mm256_setzero_si256();
60 : __m256i sum0, sum1;
61 :
62 0 : u0 = _mm256_abs_epi16(u0);
63 0 : u1 = _mm256_abs_epi16(u1);
64 0 : u2 = _mm256_abs_epi16(u2);
65 0 : u3 = _mm256_abs_epi16(u3);
66 :
67 0 : sum0 = _mm256_add_epi16(u0, u1);
68 0 : sum0 = _mm256_add_epi16(sum0, u2);
69 0 : sum0 = _mm256_add_epi16(sum0, u3);
70 :
71 : // second 4 rows
72 0 : src_ptr += src_stride << 2;
73 0 : ref_ptr += ref_stride << 2;
74 0 : s0 = _mm256_loadu_si256((const __m256i *)src_ptr);
75 0 : s1 = _mm256_loadu_si256((const __m256i *)(src_ptr + src_stride));
76 0 : s2 = _mm256_loadu_si256((const __m256i *)(src_ptr + 2 * src_stride));
77 0 : s3 = _mm256_loadu_si256((const __m256i *)(src_ptr + 3 * src_stride));
78 :
79 0 : r0 = _mm256_loadu_si256((const __m256i *)ref_ptr);
80 0 : r1 = _mm256_loadu_si256((const __m256i *)(ref_ptr + ref_stride));
81 0 : r2 = _mm256_loadu_si256((const __m256i *)(ref_ptr + 2 * ref_stride));
82 0 : r3 = _mm256_loadu_si256((const __m256i *)(ref_ptr + 3 * ref_stride));
83 :
84 0 : u0 = _mm256_sub_epi16(s0, r0);
85 0 : u1 = _mm256_sub_epi16(s1, r1);
86 0 : u2 = _mm256_sub_epi16(s2, r2);
87 0 : u3 = _mm256_sub_epi16(s3, r3);
88 :
89 0 : u0 = _mm256_abs_epi16(u0);
90 0 : u1 = _mm256_abs_epi16(u1);
91 0 : u2 = _mm256_abs_epi16(u2);
92 0 : u3 = _mm256_abs_epi16(u3);
93 :
94 0 : sum1 = _mm256_add_epi16(u0, u1);
95 0 : sum1 = _mm256_add_epi16(sum1, u2);
96 0 : sum1 = _mm256_add_epi16(sum1, u3);
97 :
98 : // find out the SAD
99 0 : s0 = _mm256_unpacklo_epi16(sum0, zero);
100 0 : s1 = _mm256_unpackhi_epi16(sum0, zero);
101 0 : r0 = _mm256_unpacklo_epi16(sum1, zero);
102 0 : r1 = _mm256_unpackhi_epi16(sum1, zero);
103 0 : s0 = _mm256_add_epi32(s0, s1);
104 0 : r0 = _mm256_add_epi32(r0, r1);
105 0 : sum0 = _mm256_add_epi32(s0, r0);
106 : // 8 32-bit summation
107 :
108 0 : return (unsigned int)get_sad_from_mm256_epi32(&sum0);
109 : }
110 :
111 0 : unsigned int aom_highbd_sad16x16_avx2(const uint8_t *src, int src_stride,
112 : const uint8_t *ref, int ref_stride) {
113 0 : const uint16_t *src_ptr = CONVERT_TO_SHORTPTR(src);
114 0 : const uint16_t *ref_ptr = CONVERT_TO_SHORTPTR(ref);
115 : __m256i s0, s1, s2, s3, r0, r1, r2, r3, u0, u1, u2, u3;
116 : __m256i sum0;
117 0 : __m256i sum = _mm256_setzero_si256();
118 0 : const __m256i zero = _mm256_setzero_si256();
119 0 : int row = 0;
120 :
121 : // Loop for every 4 rows
122 0 : while (row < 16) {
123 0 : s0 = _mm256_loadu_si256((const __m256i *)src_ptr);
124 0 : s1 = _mm256_loadu_si256((const __m256i *)(src_ptr + src_stride));
125 0 : s2 = _mm256_loadu_si256((const __m256i *)(src_ptr + 2 * src_stride));
126 0 : s3 = _mm256_loadu_si256((const __m256i *)(src_ptr + 3 * src_stride));
127 :
128 0 : r0 = _mm256_loadu_si256((const __m256i *)ref_ptr);
129 0 : r1 = _mm256_loadu_si256((const __m256i *)(ref_ptr + ref_stride));
130 0 : r2 = _mm256_loadu_si256((const __m256i *)(ref_ptr + 2 * ref_stride));
131 0 : r3 = _mm256_loadu_si256((const __m256i *)(ref_ptr + 3 * ref_stride));
132 :
133 0 : u0 = _mm256_sub_epi16(s0, r0);
134 0 : u1 = _mm256_sub_epi16(s1, r1);
135 0 : u2 = _mm256_sub_epi16(s2, r2);
136 0 : u3 = _mm256_sub_epi16(s3, r3);
137 :
138 0 : u0 = _mm256_abs_epi16(u0);
139 0 : u1 = _mm256_abs_epi16(u1);
140 0 : u2 = _mm256_abs_epi16(u2);
141 0 : u3 = _mm256_abs_epi16(u3);
142 :
143 0 : sum0 = _mm256_add_epi16(u0, u1);
144 0 : sum0 = _mm256_add_epi16(sum0, u2);
145 0 : sum0 = _mm256_add_epi16(sum0, u3);
146 :
147 0 : s0 = _mm256_unpacklo_epi16(sum0, zero);
148 0 : s1 = _mm256_unpackhi_epi16(sum0, zero);
149 0 : sum = _mm256_add_epi32(sum, s0);
150 0 : sum = _mm256_add_epi32(sum, s1);
151 : // 8 32-bit summation
152 :
153 0 : row += 4;
154 0 : src_ptr += src_stride << 2;
155 0 : ref_ptr += ref_stride << 2;
156 : }
157 0 : return get_sad_from_mm256_epi32(&sum);
158 : }
159 :
160 0 : static void sad32x4(const uint16_t *src_ptr, int src_stride,
161 : const uint16_t *ref_ptr, int ref_stride,
162 : const uint16_t *sec_ptr, __m256i *sad_acc) {
163 : __m256i s0, s1, s2, s3, r0, r1, r2, r3;
164 0 : const __m256i zero = _mm256_setzero_si256();
165 0 : int row_sections = 0;
166 :
167 0 : while (row_sections < 2) {
168 0 : s0 = _mm256_loadu_si256((const __m256i *)src_ptr);
169 0 : s1 = _mm256_loadu_si256((const __m256i *)(src_ptr + 16));
170 0 : s2 = _mm256_loadu_si256((const __m256i *)(src_ptr + src_stride));
171 0 : s3 = _mm256_loadu_si256((const __m256i *)(src_ptr + src_stride + 16));
172 :
173 0 : r0 = _mm256_loadu_si256((const __m256i *)ref_ptr);
174 0 : r1 = _mm256_loadu_si256((const __m256i *)(ref_ptr + 16));
175 0 : r2 = _mm256_loadu_si256((const __m256i *)(ref_ptr + ref_stride));
176 0 : r3 = _mm256_loadu_si256((const __m256i *)(ref_ptr + ref_stride + 16));
177 :
178 0 : if (sec_ptr) {
179 0 : r0 = _mm256_avg_epu16(r0, _mm256_loadu_si256((const __m256i *)sec_ptr));
180 0 : r1 = _mm256_avg_epu16(
181 0 : r1, _mm256_loadu_si256((const __m256i *)(sec_ptr + 16)));
182 0 : r2 = _mm256_avg_epu16(
183 0 : r2, _mm256_loadu_si256((const __m256i *)(sec_ptr + 32)));
184 0 : r3 = _mm256_avg_epu16(
185 0 : r3, _mm256_loadu_si256((const __m256i *)(sec_ptr + 48)));
186 : }
187 0 : s0 = _mm256_sub_epi16(s0, r0);
188 0 : s1 = _mm256_sub_epi16(s1, r1);
189 0 : s2 = _mm256_sub_epi16(s2, r2);
190 0 : s3 = _mm256_sub_epi16(s3, r3);
191 :
192 0 : s0 = _mm256_abs_epi16(s0);
193 0 : s1 = _mm256_abs_epi16(s1);
194 0 : s2 = _mm256_abs_epi16(s2);
195 0 : s3 = _mm256_abs_epi16(s3);
196 :
197 0 : s0 = _mm256_add_epi16(s0, s1);
198 0 : s0 = _mm256_add_epi16(s0, s2);
199 0 : s0 = _mm256_add_epi16(s0, s3);
200 :
201 0 : r0 = _mm256_unpacklo_epi16(s0, zero);
202 0 : r1 = _mm256_unpackhi_epi16(s0, zero);
203 :
204 0 : r0 = _mm256_add_epi32(r0, r1);
205 0 : *sad_acc = _mm256_add_epi32(*sad_acc, r0);
206 :
207 0 : row_sections += 1;
208 0 : src_ptr += src_stride << 1;
209 0 : ref_ptr += ref_stride << 1;
210 0 : if (sec_ptr) sec_ptr += 32 << 1;
211 : }
212 0 : }
213 :
214 0 : unsigned int aom_highbd_sad32x16_avx2(const uint8_t *src, int src_stride,
215 : const uint8_t *ref, int ref_stride) {
216 0 : __m256i sad = _mm256_setzero_si256();
217 0 : uint16_t *srcp = CONVERT_TO_SHORTPTR(src);
218 0 : uint16_t *refp = CONVERT_TO_SHORTPTR(ref);
219 0 : const int left_shift = 2;
220 0 : int row_section = 0;
221 :
222 0 : while (row_section < 4) {
223 0 : sad32x4(srcp, src_stride, refp, ref_stride, NULL, &sad);
224 0 : srcp += src_stride << left_shift;
225 0 : refp += ref_stride << left_shift;
226 0 : row_section += 1;
227 : }
228 0 : return get_sad_from_mm256_epi32(&sad);
229 : }
230 :
231 0 : unsigned int aom_highbd_sad16x32_avx2(const uint8_t *src, int src_stride,
232 : const uint8_t *ref, int ref_stride) {
233 0 : uint32_t sum = aom_highbd_sad16x16_avx2(src, src_stride, ref, ref_stride);
234 0 : src += src_stride << 4;
235 0 : ref += ref_stride << 4;
236 0 : sum += aom_highbd_sad16x16_avx2(src, src_stride, ref, ref_stride);
237 0 : return sum;
238 : }
239 :
240 0 : unsigned int aom_highbd_sad32x32_avx2(const uint8_t *src, int src_stride,
241 : const uint8_t *ref, int ref_stride) {
242 0 : uint32_t sum = aom_highbd_sad32x16_avx2(src, src_stride, ref, ref_stride);
243 0 : src += src_stride << 4;
244 0 : ref += ref_stride << 4;
245 0 : sum += aom_highbd_sad32x16_avx2(src, src_stride, ref, ref_stride);
246 0 : return sum;
247 : }
248 :
249 0 : unsigned int aom_highbd_sad32x64_avx2(const uint8_t *src, int src_stride,
250 : const uint8_t *ref, int ref_stride) {
251 0 : uint32_t sum = aom_highbd_sad32x32_avx2(src, src_stride, ref, ref_stride);
252 0 : src += src_stride << 5;
253 0 : ref += ref_stride << 5;
254 0 : sum += aom_highbd_sad32x32_avx2(src, src_stride, ref, ref_stride);
255 0 : return sum;
256 : }
257 :
258 0 : static void sad64x2(const uint16_t *src_ptr, int src_stride,
259 : const uint16_t *ref_ptr, int ref_stride,
260 : const uint16_t *sec_ptr, __m256i *sad_acc) {
261 : __m256i s[8], r[8];
262 0 : const __m256i zero = _mm256_setzero_si256();
263 :
264 0 : s[0] = _mm256_loadu_si256((const __m256i *)src_ptr);
265 0 : s[1] = _mm256_loadu_si256((const __m256i *)(src_ptr + 16));
266 0 : s[2] = _mm256_loadu_si256((const __m256i *)(src_ptr + 32));
267 0 : s[3] = _mm256_loadu_si256((const __m256i *)(src_ptr + 48));
268 0 : s[4] = _mm256_loadu_si256((const __m256i *)(src_ptr + src_stride));
269 0 : s[5] = _mm256_loadu_si256((const __m256i *)(src_ptr + src_stride + 16));
270 0 : s[6] = _mm256_loadu_si256((const __m256i *)(src_ptr + src_stride + 32));
271 0 : s[7] = _mm256_loadu_si256((const __m256i *)(src_ptr + src_stride + 48));
272 :
273 0 : r[0] = _mm256_loadu_si256((const __m256i *)ref_ptr);
274 0 : r[1] = _mm256_loadu_si256((const __m256i *)(ref_ptr + 16));
275 0 : r[2] = _mm256_loadu_si256((const __m256i *)(ref_ptr + 32));
276 0 : r[3] = _mm256_loadu_si256((const __m256i *)(ref_ptr + 48));
277 0 : r[4] = _mm256_loadu_si256((const __m256i *)(ref_ptr + ref_stride));
278 0 : r[5] = _mm256_loadu_si256((const __m256i *)(ref_ptr + ref_stride + 16));
279 0 : r[6] = _mm256_loadu_si256((const __m256i *)(ref_ptr + ref_stride + 32));
280 0 : r[7] = _mm256_loadu_si256((const __m256i *)(ref_ptr + ref_stride + 48));
281 :
282 0 : if (sec_ptr) {
283 0 : r[0] = _mm256_avg_epu16(r[0], _mm256_loadu_si256((const __m256i *)sec_ptr));
284 0 : r[1] = _mm256_avg_epu16(
285 0 : r[1], _mm256_loadu_si256((const __m256i *)(sec_ptr + 16)));
286 0 : r[2] = _mm256_avg_epu16(
287 0 : r[2], _mm256_loadu_si256((const __m256i *)(sec_ptr + 32)));
288 0 : r[3] = _mm256_avg_epu16(
289 0 : r[3], _mm256_loadu_si256((const __m256i *)(sec_ptr + 48)));
290 0 : r[4] = _mm256_avg_epu16(
291 0 : r[4], _mm256_loadu_si256((const __m256i *)(sec_ptr + 64)));
292 0 : r[5] = _mm256_avg_epu16(
293 0 : r[5], _mm256_loadu_si256((const __m256i *)(sec_ptr + 80)));
294 0 : r[6] = _mm256_avg_epu16(
295 0 : r[6], _mm256_loadu_si256((const __m256i *)(sec_ptr + 96)));
296 0 : r[7] = _mm256_avg_epu16(
297 0 : r[7], _mm256_loadu_si256((const __m256i *)(sec_ptr + 112)));
298 : }
299 :
300 0 : s[0] = _mm256_sub_epi16(s[0], r[0]);
301 0 : s[1] = _mm256_sub_epi16(s[1], r[1]);
302 0 : s[2] = _mm256_sub_epi16(s[2], r[2]);
303 0 : s[3] = _mm256_sub_epi16(s[3], r[3]);
304 0 : s[4] = _mm256_sub_epi16(s[4], r[4]);
305 0 : s[5] = _mm256_sub_epi16(s[5], r[5]);
306 0 : s[6] = _mm256_sub_epi16(s[6], r[6]);
307 0 : s[7] = _mm256_sub_epi16(s[7], r[7]);
308 :
309 0 : s[0] = _mm256_abs_epi16(s[0]);
310 0 : s[1] = _mm256_abs_epi16(s[1]);
311 0 : s[2] = _mm256_abs_epi16(s[2]);
312 0 : s[3] = _mm256_abs_epi16(s[3]);
313 0 : s[4] = _mm256_abs_epi16(s[4]);
314 0 : s[5] = _mm256_abs_epi16(s[5]);
315 0 : s[6] = _mm256_abs_epi16(s[6]);
316 0 : s[7] = _mm256_abs_epi16(s[7]);
317 :
318 0 : s[0] = _mm256_add_epi16(s[0], s[1]);
319 0 : s[0] = _mm256_add_epi16(s[0], s[2]);
320 0 : s[0] = _mm256_add_epi16(s[0], s[3]);
321 :
322 0 : s[4] = _mm256_add_epi16(s[4], s[5]);
323 0 : s[4] = _mm256_add_epi16(s[4], s[6]);
324 0 : s[4] = _mm256_add_epi16(s[4], s[7]);
325 :
326 0 : r[0] = _mm256_unpacklo_epi16(s[0], zero);
327 0 : r[1] = _mm256_unpackhi_epi16(s[0], zero);
328 0 : r[2] = _mm256_unpacklo_epi16(s[4], zero);
329 0 : r[3] = _mm256_unpackhi_epi16(s[4], zero);
330 :
331 0 : r[0] = _mm256_add_epi32(r[0], r[1]);
332 0 : r[0] = _mm256_add_epi32(r[0], r[2]);
333 0 : r[0] = _mm256_add_epi32(r[0], r[3]);
334 0 : *sad_acc = _mm256_add_epi32(*sad_acc, r[0]);
335 0 : }
336 :
337 0 : unsigned int aom_highbd_sad64x32_avx2(const uint8_t *src, int src_stride,
338 : const uint8_t *ref, int ref_stride) {
339 0 : __m256i sad = _mm256_setzero_si256();
340 0 : uint16_t *srcp = CONVERT_TO_SHORTPTR(src);
341 0 : uint16_t *refp = CONVERT_TO_SHORTPTR(ref);
342 0 : const int left_shift = 1;
343 0 : int row_section = 0;
344 :
345 0 : while (row_section < 16) {
346 0 : sad64x2(srcp, src_stride, refp, ref_stride, NULL, &sad);
347 0 : srcp += src_stride << left_shift;
348 0 : refp += ref_stride << left_shift;
349 0 : row_section += 1;
350 : }
351 0 : return get_sad_from_mm256_epi32(&sad);
352 : }
353 :
354 0 : unsigned int aom_highbd_sad64x64_avx2(const uint8_t *src, int src_stride,
355 : const uint8_t *ref, int ref_stride) {
356 0 : uint32_t sum = aom_highbd_sad64x32_avx2(src, src_stride, ref, ref_stride);
357 0 : src += src_stride << 5;
358 0 : ref += ref_stride << 5;
359 0 : sum += aom_highbd_sad64x32_avx2(src, src_stride, ref, ref_stride);
360 0 : return sum;
361 : }
362 :
363 : #if CONFIG_EXT_PARTITION
364 : static void sad128x1(const uint16_t *src_ptr, const uint16_t *ref_ptr,
365 : const uint16_t *sec_ptr, __m256i *sad_acc) {
366 : __m256i s[8], r[8];
367 : const __m256i zero = _mm256_setzero_si256();
368 :
369 : s[0] = _mm256_loadu_si256((const __m256i *)src_ptr);
370 : s[1] = _mm256_loadu_si256((const __m256i *)(src_ptr + 16));
371 : s[2] = _mm256_loadu_si256((const __m256i *)(src_ptr + 32));
372 : s[3] = _mm256_loadu_si256((const __m256i *)(src_ptr + 48));
373 : s[4] = _mm256_loadu_si256((const __m256i *)(src_ptr + 64));
374 : s[5] = _mm256_loadu_si256((const __m256i *)(src_ptr + 80));
375 : s[6] = _mm256_loadu_si256((const __m256i *)(src_ptr + 96));
376 : s[7] = _mm256_loadu_si256((const __m256i *)(src_ptr + 112));
377 :
378 : r[0] = _mm256_loadu_si256((const __m256i *)ref_ptr);
379 : r[1] = _mm256_loadu_si256((const __m256i *)(ref_ptr + 16));
380 : r[2] = _mm256_loadu_si256((const __m256i *)(ref_ptr + 32));
381 : r[3] = _mm256_loadu_si256((const __m256i *)(ref_ptr + 48));
382 : r[4] = _mm256_loadu_si256((const __m256i *)(ref_ptr + 64));
383 : r[5] = _mm256_loadu_si256((const __m256i *)(ref_ptr + 80));
384 : r[6] = _mm256_loadu_si256((const __m256i *)(ref_ptr + 96));
385 : r[7] = _mm256_loadu_si256((const __m256i *)(ref_ptr + 112));
386 :
387 : if (sec_ptr) {
388 : r[0] = _mm256_avg_epu16(r[0], _mm256_loadu_si256((const __m256i *)sec_ptr));
389 : r[1] = _mm256_avg_epu16(
390 : r[1], _mm256_loadu_si256((const __m256i *)(sec_ptr + 16)));
391 : r[2] = _mm256_avg_epu16(
392 : r[2], _mm256_loadu_si256((const __m256i *)(sec_ptr + 32)));
393 : r[3] = _mm256_avg_epu16(
394 : r[3], _mm256_loadu_si256((const __m256i *)(sec_ptr + 48)));
395 : r[4] = _mm256_avg_epu16(
396 : r[4], _mm256_loadu_si256((const __m256i *)(sec_ptr + 64)));
397 : r[5] = _mm256_avg_epu16(
398 : r[5], _mm256_loadu_si256((const __m256i *)(sec_ptr + 80)));
399 : r[6] = _mm256_avg_epu16(
400 : r[6], _mm256_loadu_si256((const __m256i *)(sec_ptr + 96)));
401 : r[7] = _mm256_avg_epu16(
402 : r[7], _mm256_loadu_si256((const __m256i *)(sec_ptr + 112)));
403 : }
404 :
405 : s[0] = _mm256_sub_epi16(s[0], r[0]);
406 : s[1] = _mm256_sub_epi16(s[1], r[1]);
407 : s[2] = _mm256_sub_epi16(s[2], r[2]);
408 : s[3] = _mm256_sub_epi16(s[3], r[3]);
409 : s[4] = _mm256_sub_epi16(s[4], r[4]);
410 : s[5] = _mm256_sub_epi16(s[5], r[5]);
411 : s[6] = _mm256_sub_epi16(s[6], r[6]);
412 : s[7] = _mm256_sub_epi16(s[7], r[7]);
413 :
414 : s[0] = _mm256_abs_epi16(s[0]);
415 : s[1] = _mm256_abs_epi16(s[1]);
416 : s[2] = _mm256_abs_epi16(s[2]);
417 : s[3] = _mm256_abs_epi16(s[3]);
418 : s[4] = _mm256_abs_epi16(s[4]);
419 : s[5] = _mm256_abs_epi16(s[5]);
420 : s[6] = _mm256_abs_epi16(s[6]);
421 : s[7] = _mm256_abs_epi16(s[7]);
422 :
423 : s[0] = _mm256_add_epi16(s[0], s[1]);
424 : s[0] = _mm256_add_epi16(s[0], s[2]);
425 : s[0] = _mm256_add_epi16(s[0], s[3]);
426 :
427 : s[4] = _mm256_add_epi16(s[4], s[5]);
428 : s[4] = _mm256_add_epi16(s[4], s[6]);
429 : s[4] = _mm256_add_epi16(s[4], s[7]);
430 :
431 : r[0] = _mm256_unpacklo_epi16(s[0], zero);
432 : r[1] = _mm256_unpackhi_epi16(s[0], zero);
433 : r[2] = _mm256_unpacklo_epi16(s[4], zero);
434 : r[3] = _mm256_unpackhi_epi16(s[4], zero);
435 :
436 : r[0] = _mm256_add_epi32(r[0], r[1]);
437 : r[0] = _mm256_add_epi32(r[0], r[2]);
438 : r[0] = _mm256_add_epi32(r[0], r[3]);
439 : *sad_acc = _mm256_add_epi32(*sad_acc, r[0]);
440 : }
441 :
442 : unsigned int aom_highbd_sad128x64_avx2(const uint8_t *src, int src_stride,
443 : const uint8_t *ref, int ref_stride) {
444 : __m256i sad = _mm256_setzero_si256();
445 : uint16_t *srcp = CONVERT_TO_SHORTPTR(src);
446 : uint16_t *refp = CONVERT_TO_SHORTPTR(ref);
447 : int row = 0;
448 : while (row < 64) {
449 : sad128x1(srcp, refp, NULL, &sad);
450 : srcp += src_stride;
451 : refp += ref_stride;
452 : row += 1;
453 : }
454 : return get_sad_from_mm256_epi32(&sad);
455 : }
456 :
457 : unsigned int aom_highbd_sad64x128_avx2(const uint8_t *src, int src_stride,
458 : const uint8_t *ref, int ref_stride) {
459 : uint32_t sum = aom_highbd_sad64x64_avx2(src, src_stride, ref, ref_stride);
460 : src += src_stride << 6;
461 : ref += ref_stride << 6;
462 : sum += aom_highbd_sad64x64_avx2(src, src_stride, ref, ref_stride);
463 : return sum;
464 : }
465 :
466 : unsigned int aom_highbd_sad128x128_avx2(const uint8_t *src, int src_stride,
467 : const uint8_t *ref, int ref_stride) {
468 : uint32_t sum = aom_highbd_sad128x64_avx2(src, src_stride, ref, ref_stride);
469 : src += src_stride << 6;
470 : ref += ref_stride << 6;
471 : sum += aom_highbd_sad128x64_avx2(src, src_stride, ref, ref_stride);
472 : return sum;
473 : }
474 : #endif // CONFIG_EXT_PARTITION
475 :
476 : // If sec_ptr = 0, calculate regular SAD. Otherwise, calculate average SAD.
477 0 : static INLINE void sad16x4(const uint16_t *src_ptr, int src_stride,
478 : const uint16_t *ref_ptr, int ref_stride,
479 : const uint16_t *sec_ptr, __m256i *sad_acc) {
480 : __m256i s0, s1, s2, s3, r0, r1, r2, r3;
481 0 : const __m256i zero = _mm256_setzero_si256();
482 :
483 0 : s0 = _mm256_loadu_si256((const __m256i *)src_ptr);
484 0 : s1 = _mm256_loadu_si256((const __m256i *)(src_ptr + src_stride));
485 0 : s2 = _mm256_loadu_si256((const __m256i *)(src_ptr + 2 * src_stride));
486 0 : s3 = _mm256_loadu_si256((const __m256i *)(src_ptr + 3 * src_stride));
487 :
488 0 : r0 = _mm256_loadu_si256((const __m256i *)ref_ptr);
489 0 : r1 = _mm256_loadu_si256((const __m256i *)(ref_ptr + ref_stride));
490 0 : r2 = _mm256_loadu_si256((const __m256i *)(ref_ptr + 2 * ref_stride));
491 0 : r3 = _mm256_loadu_si256((const __m256i *)(ref_ptr + 3 * ref_stride));
492 :
493 0 : if (sec_ptr) {
494 0 : r0 = _mm256_avg_epu16(r0, _mm256_loadu_si256((const __m256i *)sec_ptr));
495 0 : r1 = _mm256_avg_epu16(r1,
496 0 : _mm256_loadu_si256((const __m256i *)(sec_ptr + 16)));
497 0 : r2 = _mm256_avg_epu16(r2,
498 0 : _mm256_loadu_si256((const __m256i *)(sec_ptr + 32)));
499 0 : r3 = _mm256_avg_epu16(r3,
500 0 : _mm256_loadu_si256((const __m256i *)(sec_ptr + 48)));
501 : }
502 :
503 0 : s0 = _mm256_sub_epi16(s0, r0);
504 0 : s1 = _mm256_sub_epi16(s1, r1);
505 0 : s2 = _mm256_sub_epi16(s2, r2);
506 0 : s3 = _mm256_sub_epi16(s3, r3);
507 :
508 0 : s0 = _mm256_abs_epi16(s0);
509 0 : s1 = _mm256_abs_epi16(s1);
510 0 : s2 = _mm256_abs_epi16(s2);
511 0 : s3 = _mm256_abs_epi16(s3);
512 :
513 0 : s0 = _mm256_add_epi16(s0, s1);
514 0 : s0 = _mm256_add_epi16(s0, s2);
515 0 : s0 = _mm256_add_epi16(s0, s3);
516 :
517 0 : r0 = _mm256_unpacklo_epi16(s0, zero);
518 0 : r1 = _mm256_unpackhi_epi16(s0, zero);
519 :
520 0 : r0 = _mm256_add_epi32(r0, r1);
521 0 : *sad_acc = _mm256_add_epi32(*sad_acc, r0);
522 0 : }
523 :
524 0 : unsigned int aom_highbd_sad16x8_avg_avx2(const uint8_t *src, int src_stride,
525 : const uint8_t *ref, int ref_stride,
526 : const uint8_t *second_pred) {
527 0 : __m256i sad = _mm256_setzero_si256();
528 0 : uint16_t *srcp = CONVERT_TO_SHORTPTR(src);
529 0 : uint16_t *refp = CONVERT_TO_SHORTPTR(ref);
530 0 : uint16_t *secp = CONVERT_TO_SHORTPTR(second_pred);
531 :
532 0 : sad16x4(srcp, src_stride, refp, ref_stride, secp, &sad);
533 :
534 : // Next 4 rows
535 0 : srcp += src_stride << 2;
536 0 : refp += ref_stride << 2;
537 0 : secp += 64;
538 0 : sad16x4(srcp, src_stride, refp, ref_stride, secp, &sad);
539 0 : return get_sad_from_mm256_epi32(&sad);
540 : }
541 :
542 0 : unsigned int aom_highbd_sad16x16_avg_avx2(const uint8_t *src, int src_stride,
543 : const uint8_t *ref, int ref_stride,
544 : const uint8_t *second_pred) {
545 0 : const int left_shift = 3;
546 0 : uint32_t sum = aom_highbd_sad16x8_avg_avx2(src, src_stride, ref, ref_stride,
547 : second_pred);
548 0 : src += src_stride << left_shift;
549 0 : ref += ref_stride << left_shift;
550 0 : second_pred += 16 << left_shift;
551 0 : sum += aom_highbd_sad16x8_avg_avx2(src, src_stride, ref, ref_stride,
552 : second_pred);
553 0 : return sum;
554 : }
555 :
556 0 : unsigned int aom_highbd_sad16x32_avg_avx2(const uint8_t *src, int src_stride,
557 : const uint8_t *ref, int ref_stride,
558 : const uint8_t *second_pred) {
559 0 : const int left_shift = 4;
560 0 : uint32_t sum = aom_highbd_sad16x16_avg_avx2(src, src_stride, ref, ref_stride,
561 : second_pred);
562 0 : src += src_stride << left_shift;
563 0 : ref += ref_stride << left_shift;
564 0 : second_pred += 16 << left_shift;
565 0 : sum += aom_highbd_sad16x16_avg_avx2(src, src_stride, ref, ref_stride,
566 : second_pred);
567 0 : return sum;
568 : }
569 :
570 0 : unsigned int aom_highbd_sad32x16_avg_avx2(const uint8_t *src, int src_stride,
571 : const uint8_t *ref, int ref_stride,
572 : const uint8_t *second_pred) {
573 0 : __m256i sad = _mm256_setzero_si256();
574 0 : uint16_t *srcp = CONVERT_TO_SHORTPTR(src);
575 0 : uint16_t *refp = CONVERT_TO_SHORTPTR(ref);
576 0 : uint16_t *secp = CONVERT_TO_SHORTPTR(second_pred);
577 0 : const int left_shift = 2;
578 0 : int row_section = 0;
579 :
580 0 : while (row_section < 4) {
581 0 : sad32x4(srcp, src_stride, refp, ref_stride, secp, &sad);
582 0 : srcp += src_stride << left_shift;
583 0 : refp += ref_stride << left_shift;
584 0 : secp += 32 << left_shift;
585 0 : row_section += 1;
586 : }
587 0 : return get_sad_from_mm256_epi32(&sad);
588 : }
589 :
590 0 : unsigned int aom_highbd_sad32x32_avg_avx2(const uint8_t *src, int src_stride,
591 : const uint8_t *ref, int ref_stride,
592 : const uint8_t *second_pred) {
593 0 : const int left_shift = 4;
594 0 : uint32_t sum = aom_highbd_sad32x16_avg_avx2(src, src_stride, ref, ref_stride,
595 : second_pred);
596 0 : src += src_stride << left_shift;
597 0 : ref += ref_stride << left_shift;
598 0 : second_pred += 32 << left_shift;
599 0 : sum += aom_highbd_sad32x16_avg_avx2(src, src_stride, ref, ref_stride,
600 : second_pred);
601 0 : return sum;
602 : }
603 :
604 0 : unsigned int aom_highbd_sad32x64_avg_avx2(const uint8_t *src, int src_stride,
605 : const uint8_t *ref, int ref_stride,
606 : const uint8_t *second_pred) {
607 0 : const int left_shift = 5;
608 0 : uint32_t sum = aom_highbd_sad32x32_avg_avx2(src, src_stride, ref, ref_stride,
609 : second_pred);
610 0 : src += src_stride << left_shift;
611 0 : ref += ref_stride << left_shift;
612 0 : second_pred += 32 << left_shift;
613 0 : sum += aom_highbd_sad32x32_avg_avx2(src, src_stride, ref, ref_stride,
614 : second_pred);
615 0 : return sum;
616 : }
617 :
618 0 : unsigned int aom_highbd_sad64x32_avg_avx2(const uint8_t *src, int src_stride,
619 : const uint8_t *ref, int ref_stride,
620 : const uint8_t *second_pred) {
621 0 : __m256i sad = _mm256_setzero_si256();
622 0 : uint16_t *srcp = CONVERT_TO_SHORTPTR(src);
623 0 : uint16_t *refp = CONVERT_TO_SHORTPTR(ref);
624 0 : uint16_t *secp = CONVERT_TO_SHORTPTR(second_pred);
625 0 : const int left_shift = 1;
626 0 : int row_section = 0;
627 :
628 0 : while (row_section < 16) {
629 0 : sad64x2(srcp, src_stride, refp, ref_stride, secp, &sad);
630 0 : srcp += src_stride << left_shift;
631 0 : refp += ref_stride << left_shift;
632 0 : secp += 64 << left_shift;
633 0 : row_section += 1;
634 : }
635 0 : return get_sad_from_mm256_epi32(&sad);
636 : }
637 :
638 0 : unsigned int aom_highbd_sad64x64_avg_avx2(const uint8_t *src, int src_stride,
639 : const uint8_t *ref, int ref_stride,
640 : const uint8_t *second_pred) {
641 0 : const int left_shift = 5;
642 0 : uint32_t sum = aom_highbd_sad64x32_avg_avx2(src, src_stride, ref, ref_stride,
643 : second_pred);
644 0 : src += src_stride << left_shift;
645 0 : ref += ref_stride << left_shift;
646 0 : second_pred += 64 << left_shift;
647 0 : sum += aom_highbd_sad64x32_avg_avx2(src, src_stride, ref, ref_stride,
648 : second_pred);
649 0 : return sum;
650 : }
651 :
652 : #if CONFIG_EXT_PARTITION
653 : unsigned int aom_highbd_sad64x128_avg_avx2(const uint8_t *src, int src_stride,
654 : const uint8_t *ref, int ref_stride,
655 : const uint8_t *second_pred) {
656 : const int left_shift = 6;
657 : uint32_t sum = aom_highbd_sad64x64_avg_avx2(src, src_stride, ref, ref_stride,
658 : second_pred);
659 : src += src_stride << left_shift;
660 : ref += ref_stride << left_shift;
661 : second_pred += 64 << left_shift;
662 : sum += aom_highbd_sad64x64_avg_avx2(src, src_stride, ref, ref_stride,
663 : second_pred);
664 : return sum;
665 : }
666 :
667 : unsigned int aom_highbd_sad128x64_avg_avx2(const uint8_t *src, int src_stride,
668 : const uint8_t *ref, int ref_stride,
669 : const uint8_t *second_pred) {
670 : __m256i sad = _mm256_setzero_si256();
671 : uint16_t *srcp = CONVERT_TO_SHORTPTR(src);
672 : uint16_t *refp = CONVERT_TO_SHORTPTR(ref);
673 : uint16_t *secp = CONVERT_TO_SHORTPTR(second_pred);
674 : int row = 0;
675 : while (row < 64) {
676 : sad128x1(srcp, refp, secp, &sad);
677 : srcp += src_stride;
678 : refp += ref_stride;
679 : secp += 16 << 3;
680 : row += 1;
681 : }
682 : return get_sad_from_mm256_epi32(&sad);
683 : }
684 :
685 : unsigned int aom_highbd_sad128x128_avg_avx2(const uint8_t *src, int src_stride,
686 : const uint8_t *ref, int ref_stride,
687 : const uint8_t *second_pred) {
688 : unsigned int sum;
689 : const int left_shift = 6;
690 :
691 : sum = aom_highbd_sad128x64_avg_avx2(src, src_stride, ref, ref_stride,
692 : second_pred);
693 : src += src_stride << left_shift;
694 : ref += ref_stride << left_shift;
695 : second_pred += 128 << left_shift;
696 : sum += aom_highbd_sad128x64_avg_avx2(src, src_stride, ref, ref_stride,
697 : second_pred);
698 : return sum;
699 : }
700 : #endif // CONFIG_EXT_PARTITION
701 :
702 : // SAD 4D
703 : // Combine 4 __m256i vectors to uint32_t result[4]
704 0 : static INLINE void get_4d_sad_from_mm256_epi32(const __m256i *v,
705 : uint32_t *res) {
706 : __m256i u0, u1, u2, u3;
707 0 : const __m256i mask = _mm256_set1_epi64x(UINT32_MAX);
708 : __m128i sad;
709 :
710 : // 8 32-bit summation
711 0 : u0 = _mm256_srli_si256(v[0], 4);
712 0 : u1 = _mm256_srli_si256(v[1], 4);
713 0 : u2 = _mm256_srli_si256(v[2], 4);
714 0 : u3 = _mm256_srli_si256(v[3], 4);
715 :
716 0 : u0 = _mm256_add_epi32(u0, v[0]);
717 0 : u1 = _mm256_add_epi32(u1, v[1]);
718 0 : u2 = _mm256_add_epi32(u2, v[2]);
719 0 : u3 = _mm256_add_epi32(u3, v[3]);
720 :
721 0 : u0 = _mm256_and_si256(u0, mask);
722 0 : u1 = _mm256_and_si256(u1, mask);
723 0 : u2 = _mm256_and_si256(u2, mask);
724 0 : u3 = _mm256_and_si256(u3, mask);
725 : // 4 32-bit summation, evenly positioned
726 :
727 0 : u1 = _mm256_slli_si256(u1, 4);
728 0 : u3 = _mm256_slli_si256(u3, 4);
729 :
730 0 : u0 = _mm256_or_si256(u0, u1);
731 0 : u2 = _mm256_or_si256(u2, u3);
732 : // 8 32-bit summation, interleaved
733 :
734 0 : u1 = _mm256_unpacklo_epi64(u0, u2);
735 0 : u3 = _mm256_unpackhi_epi64(u0, u2);
736 :
737 0 : u0 = _mm256_add_epi32(u1, u3);
738 0 : sad = _mm_add_epi32(_mm256_extractf128_si256(u0, 1),
739 : _mm256_castsi256_si128(u0));
740 : _mm_storeu_si128((__m128i *)res, sad);
741 0 : }
742 :
743 0 : static void convert_pointers(const uint8_t *const ref8[],
744 : const uint16_t *ref[]) {
745 0 : ref[0] = CONVERT_TO_SHORTPTR(ref8[0]);
746 0 : ref[1] = CONVERT_TO_SHORTPTR(ref8[1]);
747 0 : ref[2] = CONVERT_TO_SHORTPTR(ref8[2]);
748 0 : ref[3] = CONVERT_TO_SHORTPTR(ref8[3]);
749 0 : }
750 :
751 0 : static void init_sad(__m256i *s) {
752 0 : s[0] = _mm256_setzero_si256();
753 0 : s[1] = _mm256_setzero_si256();
754 0 : s[2] = _mm256_setzero_si256();
755 0 : s[3] = _mm256_setzero_si256();
756 0 : }
757 :
758 0 : void aom_highbd_sad16x8x4d_avx2(const uint8_t *src, int src_stride,
759 : const uint8_t *const ref_array[],
760 : int ref_stride, uint32_t *sad_array) {
761 : __m256i sad_vec[4];
762 : const uint16_t *refp[4];
763 0 : const uint16_t *keep = CONVERT_TO_SHORTPTR(src);
764 : const uint16_t *srcp;
765 0 : const int shift_for_4_rows = 2;
766 : int i;
767 :
768 0 : init_sad(sad_vec);
769 0 : convert_pointers(ref_array, refp);
770 :
771 0 : for (i = 0; i < 4; ++i) {
772 0 : srcp = keep;
773 0 : sad16x4(srcp, src_stride, refp[i], ref_stride, 0, &sad_vec[i]);
774 0 : srcp += src_stride << shift_for_4_rows;
775 0 : refp[i] += ref_stride << shift_for_4_rows;
776 0 : sad16x4(srcp, src_stride, refp[i], ref_stride, 0, &sad_vec[i]);
777 : }
778 0 : get_4d_sad_from_mm256_epi32(sad_vec, sad_array);
779 0 : }
780 :
781 0 : void aom_highbd_sad16x16x4d_avx2(const uint8_t *src, int src_stride,
782 : const uint8_t *const ref_array[],
783 : int ref_stride, uint32_t *sad_array) {
784 : uint32_t first8rows[4];
785 : uint32_t second8rows[4];
786 : const uint8_t *ref[4];
787 0 : const int shift_for_8_rows = 3;
788 :
789 0 : ref[0] = ref_array[0];
790 0 : ref[1] = ref_array[1];
791 0 : ref[2] = ref_array[2];
792 0 : ref[3] = ref_array[3];
793 :
794 0 : aom_highbd_sad16x8x4d_avx2(src, src_stride, ref, ref_stride, first8rows);
795 0 : src += src_stride << shift_for_8_rows;
796 0 : ref[0] += ref_stride << shift_for_8_rows;
797 0 : ref[1] += ref_stride << shift_for_8_rows;
798 0 : ref[2] += ref_stride << shift_for_8_rows;
799 0 : ref[3] += ref_stride << shift_for_8_rows;
800 0 : aom_highbd_sad16x8x4d_avx2(src, src_stride, ref, ref_stride, second8rows);
801 0 : sad_array[0] = first8rows[0] + second8rows[0];
802 0 : sad_array[1] = first8rows[1] + second8rows[1];
803 0 : sad_array[2] = first8rows[2] + second8rows[2];
804 0 : sad_array[3] = first8rows[3] + second8rows[3];
805 0 : }
806 :
807 0 : void aom_highbd_sad16x32x4d_avx2(const uint8_t *src, int src_stride,
808 : const uint8_t *const ref_array[],
809 : int ref_stride, uint32_t *sad_array) {
810 : uint32_t first_half[4];
811 : uint32_t second_half[4];
812 : const uint8_t *ref[4];
813 0 : const int shift_for_rows = 4;
814 :
815 0 : ref[0] = ref_array[0];
816 0 : ref[1] = ref_array[1];
817 0 : ref[2] = ref_array[2];
818 0 : ref[3] = ref_array[3];
819 :
820 0 : aom_highbd_sad16x16x4d_avx2(src, src_stride, ref, ref_stride, first_half);
821 0 : src += src_stride << shift_for_rows;
822 0 : ref[0] += ref_stride << shift_for_rows;
823 0 : ref[1] += ref_stride << shift_for_rows;
824 0 : ref[2] += ref_stride << shift_for_rows;
825 0 : ref[3] += ref_stride << shift_for_rows;
826 0 : aom_highbd_sad16x16x4d_avx2(src, src_stride, ref, ref_stride, second_half);
827 0 : sad_array[0] = first_half[0] + second_half[0];
828 0 : sad_array[1] = first_half[1] + second_half[1];
829 0 : sad_array[2] = first_half[2] + second_half[2];
830 0 : sad_array[3] = first_half[3] + second_half[3];
831 0 : }
832 :
833 0 : void aom_highbd_sad32x16x4d_avx2(const uint8_t *src, int src_stride,
834 : const uint8_t *const ref_array[],
835 : int ref_stride, uint32_t *sad_array) {
836 : __m256i sad_vec[4];
837 : const uint16_t *refp[4];
838 0 : const uint16_t *keep = CONVERT_TO_SHORTPTR(src);
839 : const uint16_t *srcp;
840 0 : const int shift_for_4_rows = 2;
841 : int i;
842 : int rows_section;
843 :
844 0 : init_sad(sad_vec);
845 0 : convert_pointers(ref_array, refp);
846 :
847 0 : for (i = 0; i < 4; ++i) {
848 0 : srcp = keep;
849 0 : rows_section = 0;
850 0 : while (rows_section < 4) {
851 0 : sad32x4(srcp, src_stride, refp[i], ref_stride, 0, &sad_vec[i]);
852 0 : srcp += src_stride << shift_for_4_rows;
853 0 : refp[i] += ref_stride << shift_for_4_rows;
854 0 : rows_section++;
855 : }
856 : }
857 0 : get_4d_sad_from_mm256_epi32(sad_vec, sad_array);
858 0 : }
859 :
860 0 : void aom_highbd_sad32x32x4d_avx2(const uint8_t *src, int src_stride,
861 : const uint8_t *const ref_array[],
862 : int ref_stride, uint32_t *sad_array) {
863 : uint32_t first_half[4];
864 : uint32_t second_half[4];
865 : const uint8_t *ref[4];
866 0 : const int shift_for_rows = 4;
867 :
868 0 : ref[0] = ref_array[0];
869 0 : ref[1] = ref_array[1];
870 0 : ref[2] = ref_array[2];
871 0 : ref[3] = ref_array[3];
872 :
873 0 : aom_highbd_sad32x16x4d_avx2(src, src_stride, ref, ref_stride, first_half);
874 0 : src += src_stride << shift_for_rows;
875 0 : ref[0] += ref_stride << shift_for_rows;
876 0 : ref[1] += ref_stride << shift_for_rows;
877 0 : ref[2] += ref_stride << shift_for_rows;
878 0 : ref[3] += ref_stride << shift_for_rows;
879 0 : aom_highbd_sad32x16x4d_avx2(src, src_stride, ref, ref_stride, second_half);
880 0 : sad_array[0] = first_half[0] + second_half[0];
881 0 : sad_array[1] = first_half[1] + second_half[1];
882 0 : sad_array[2] = first_half[2] + second_half[2];
883 0 : sad_array[3] = first_half[3] + second_half[3];
884 0 : }
885 :
886 0 : void aom_highbd_sad32x64x4d_avx2(const uint8_t *src, int src_stride,
887 : const uint8_t *const ref_array[],
888 : int ref_stride, uint32_t *sad_array) {
889 : uint32_t first_half[4];
890 : uint32_t second_half[4];
891 : const uint8_t *ref[4];
892 0 : const int shift_for_rows = 5;
893 :
894 0 : ref[0] = ref_array[0];
895 0 : ref[1] = ref_array[1];
896 0 : ref[2] = ref_array[2];
897 0 : ref[3] = ref_array[3];
898 :
899 0 : aom_highbd_sad32x32x4d_avx2(src, src_stride, ref, ref_stride, first_half);
900 0 : src += src_stride << shift_for_rows;
901 0 : ref[0] += ref_stride << shift_for_rows;
902 0 : ref[1] += ref_stride << shift_for_rows;
903 0 : ref[2] += ref_stride << shift_for_rows;
904 0 : ref[3] += ref_stride << shift_for_rows;
905 0 : aom_highbd_sad32x32x4d_avx2(src, src_stride, ref, ref_stride, second_half);
906 0 : sad_array[0] = first_half[0] + second_half[0];
907 0 : sad_array[1] = first_half[1] + second_half[1];
908 0 : sad_array[2] = first_half[2] + second_half[2];
909 0 : sad_array[3] = first_half[3] + second_half[3];
910 0 : }
911 :
912 0 : void aom_highbd_sad64x32x4d_avx2(const uint8_t *src, int src_stride,
913 : const uint8_t *const ref_array[],
914 : int ref_stride, uint32_t *sad_array) {
915 : __m256i sad_vec[4];
916 : const uint16_t *refp[4];
917 0 : const uint16_t *keep = CONVERT_TO_SHORTPTR(src);
918 : const uint16_t *srcp;
919 0 : const int shift_for_rows = 1;
920 : int i;
921 : int rows_section;
922 :
923 0 : init_sad(sad_vec);
924 0 : convert_pointers(ref_array, refp);
925 :
926 0 : for (i = 0; i < 4; ++i) {
927 0 : srcp = keep;
928 0 : rows_section = 0;
929 0 : while (rows_section < 16) {
930 0 : sad64x2(srcp, src_stride, refp[i], ref_stride, NULL, &sad_vec[i]);
931 0 : srcp += src_stride << shift_for_rows;
932 0 : refp[i] += ref_stride << shift_for_rows;
933 0 : rows_section++;
934 : }
935 : }
936 0 : get_4d_sad_from_mm256_epi32(sad_vec, sad_array);
937 0 : }
938 :
939 0 : void aom_highbd_sad64x64x4d_avx2(const uint8_t *src, int src_stride,
940 : const uint8_t *const ref_array[],
941 : int ref_stride, uint32_t *sad_array) {
942 : uint32_t first_half[4];
943 : uint32_t second_half[4];
944 : const uint8_t *ref[4];
945 0 : const int shift_for_rows = 5;
946 :
947 0 : ref[0] = ref_array[0];
948 0 : ref[1] = ref_array[1];
949 0 : ref[2] = ref_array[2];
950 0 : ref[3] = ref_array[3];
951 :
952 0 : aom_highbd_sad64x32x4d_avx2(src, src_stride, ref, ref_stride, first_half);
953 0 : src += src_stride << shift_for_rows;
954 0 : ref[0] += ref_stride << shift_for_rows;
955 0 : ref[1] += ref_stride << shift_for_rows;
956 0 : ref[2] += ref_stride << shift_for_rows;
957 0 : ref[3] += ref_stride << shift_for_rows;
958 0 : aom_highbd_sad64x32x4d_avx2(src, src_stride, ref, ref_stride, second_half);
959 0 : sad_array[0] = first_half[0] + second_half[0];
960 0 : sad_array[1] = first_half[1] + second_half[1];
961 0 : sad_array[2] = first_half[2] + second_half[2];
962 0 : sad_array[3] = first_half[3] + second_half[3];
963 0 : }
964 :
965 : #if CONFIG_EXT_PARTITION
966 : void aom_highbd_sad64x128x4d_avx2(const uint8_t *src, int src_stride,
967 : const uint8_t *const ref_array[],
968 : int ref_stride, uint32_t *sad_array) {
969 : uint32_t first_half[4];
970 : uint32_t second_half[4];
971 : const uint8_t *ref[4];
972 : const int shift_for_rows = 6;
973 :
974 : ref[0] = ref_array[0];
975 : ref[1] = ref_array[1];
976 : ref[2] = ref_array[2];
977 : ref[3] = ref_array[3];
978 :
979 : aom_highbd_sad64x64x4d_avx2(src, src_stride, ref, ref_stride, first_half);
980 : src += src_stride << shift_for_rows;
981 : ref[0] += ref_stride << shift_for_rows;
982 : ref[1] += ref_stride << shift_for_rows;
983 : ref[2] += ref_stride << shift_for_rows;
984 : ref[3] += ref_stride << shift_for_rows;
985 : aom_highbd_sad64x64x4d_avx2(src, src_stride, ref, ref_stride, second_half);
986 : sad_array[0] = first_half[0] + second_half[0];
987 : sad_array[1] = first_half[1] + second_half[1];
988 : sad_array[2] = first_half[2] + second_half[2];
989 : sad_array[3] = first_half[3] + second_half[3];
990 : }
991 :
992 : void aom_highbd_sad128x64x4d_avx2(const uint8_t *src, int src_stride,
993 : const uint8_t *const ref_array[],
994 : int ref_stride, uint32_t *sad_array) {
995 : __m256i sad_vec[4];
996 : const uint16_t *refp[4];
997 : const uint16_t *keep = CONVERT_TO_SHORTPTR(src);
998 : const uint16_t *srcp;
999 : int i;
1000 : int rows_section;
1001 :
1002 : init_sad(sad_vec);
1003 : convert_pointers(ref_array, refp);
1004 :
1005 : for (i = 0; i < 4; ++i) {
1006 : srcp = keep;
1007 : rows_section = 0;
1008 : while (rows_section < 64) {
1009 : sad128x1(srcp, refp[i], NULL, &sad_vec[i]);
1010 : srcp += src_stride;
1011 : refp[i] += ref_stride;
1012 : rows_section++;
1013 : }
1014 : }
1015 : get_4d_sad_from_mm256_epi32(sad_vec, sad_array);
1016 : }
1017 :
1018 : void aom_highbd_sad128x128x4d_avx2(const uint8_t *src, int src_stride,
1019 : const uint8_t *const ref_array[],
1020 : int ref_stride, uint32_t *sad_array) {
1021 : uint32_t first_half[4];
1022 : uint32_t second_half[4];
1023 : const uint8_t *ref[4];
1024 : const int shift_for_rows = 6;
1025 :
1026 : ref[0] = ref_array[0];
1027 : ref[1] = ref_array[1];
1028 : ref[2] = ref_array[2];
1029 : ref[3] = ref_array[3];
1030 :
1031 : aom_highbd_sad128x64x4d_avx2(src, src_stride, ref, ref_stride, first_half);
1032 : src += src_stride << shift_for_rows;
1033 : ref[0] += ref_stride << shift_for_rows;
1034 : ref[1] += ref_stride << shift_for_rows;
1035 : ref[2] += ref_stride << shift_for_rows;
1036 : ref[3] += ref_stride << shift_for_rows;
1037 : aom_highbd_sad128x64x4d_avx2(src, src_stride, ref, ref_stride, second_half);
1038 : sad_array[0] = first_half[0] + second_half[0];
1039 : sad_array[1] = first_half[1] + second_half[1];
1040 : sad_array[2] = first_half[2] + second_half[2];
1041 : sad_array[3] = first_half[3] + second_half[3];
1042 : }
1043 : #endif // CONFIG_EXT_PARTITION
|