Coverage Report

Created: 2026-10-17 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/avm/av2/common/x86/reconinter_avx2.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2021, Alliance for Open Media. All rights reserved
3
 *
4
 * This source code is subject to the terms of the BSD 3-Clause Clear License
5
 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6
 * License was not distributed with this source code in the LICENSE file, you
7
 * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  If the
8
 * Alliance for Open Media Patent License 1.0 was not distributed with this
9
 * source code in the PATENTS file, you can obtain it at
10
 * aomedia.org/license/patent-license/.
11
 */
12
13
#include <immintrin.h>
14
15
#include "config/av2_rtcd.h"
16
17
#include "avm/avm_integer.h"
18
#include "avm_dsp/blend.h"
19
#include "avm_dsp/x86/synonyms.h"
20
#include "avm_dsp/x86/synonyms_avx2.h"
21
#include "av2/common/blockd.h"
22
23
static INLINE __m256i calc_mask_d16_avx2(const __m256i *data_src0,
24
                                         const __m256i *data_src1,
25
                                         const __m256i *round_const,
26
                                         const __m256i *mask_base_16,
27
0
                                         const __m256i *clip_diff, int round) {
28
0
  const __m256i diffa = _mm256_subs_epu16(*data_src0, *data_src1);
29
0
  const __m256i diffb = _mm256_subs_epu16(*data_src1, *data_src0);
30
0
  const __m256i diff = _mm256_max_epu16(diffa, diffb);
31
0
  const __m256i diff_round =
32
0
      _mm256_srli_epi16(_mm256_adds_epu16(diff, *round_const), round);
33
0
  const __m256i diff_factor = _mm256_srli_epi16(diff_round, DIFF_FACTOR_LOG2);
34
0
  const __m256i diff_mask = _mm256_adds_epi16(diff_factor, *mask_base_16);
35
0
  const __m256i diff_clamp = _mm256_min_epi16(diff_mask, *clip_diff);
36
0
  return diff_clamp;
37
0
}
38
39
static INLINE __m256i calc_mask_d16_inv_avx2(const __m256i *data_src0,
40
                                             const __m256i *data_src1,
41
                                             const __m256i *round_const,
42
                                             const __m256i *mask_base_16,
43
                                             const __m256i *clip_diff,
44
0
                                             int round) {
45
0
  const __m256i diffa = _mm256_subs_epu16(*data_src0, *data_src1);
46
0
  const __m256i diffb = _mm256_subs_epu16(*data_src1, *data_src0);
47
0
  const __m256i diff = _mm256_max_epu16(diffa, diffb);
48
0
  const __m256i diff_round =
49
0
      _mm256_srli_epi16(_mm256_adds_epu16(diff, *round_const), round);
50
0
  const __m256i diff_factor = _mm256_srli_epi16(diff_round, DIFF_FACTOR_LOG2);
51
0
  const __m256i diff_mask = _mm256_adds_epi16(diff_factor, *mask_base_16);
52
0
  const __m256i diff_clamp = _mm256_min_epi16(diff_mask, *clip_diff);
53
0
  const __m256i diff_const_16 = _mm256_sub_epi16(*clip_diff, diff_clamp);
54
0
  return diff_const_16;
55
0
}
56
57
static INLINE void build_compound_diffwtd_mask_d16_avx2(
58
    uint8_t *mask, const CONV_BUF_TYPE *src0, int src0_stride,
59
0
    const CONV_BUF_TYPE *src1, int src1_stride, int h, int w, int shift) {
60
0
  const int mask_base = 38;
61
0
  const __m256i _r = _mm256_set1_epi16((1 << shift) >> 1);
62
0
  const __m256i y38 = _mm256_set1_epi16(mask_base);
63
0
  const __m256i y64 = _mm256_set1_epi16(AVM_BLEND_A64_MAX_ALPHA);
64
0
  int i = 0;
65
0
  if (w == 4) {
66
0
    do {
67
0
      const __m128i s0A = xx_loadl_64(src0);
68
0
      const __m128i s0B = xx_loadl_64(src0 + src0_stride);
69
0
      const __m128i s0C = xx_loadl_64(src0 + src0_stride * 2);
70
0
      const __m128i s0D = xx_loadl_64(src0 + src0_stride * 3);
71
0
      const __m128i s1A = xx_loadl_64(src1);
72
0
      const __m128i s1B = xx_loadl_64(src1 + src1_stride);
73
0
      const __m128i s1C = xx_loadl_64(src1 + src1_stride * 2);
74
0
      const __m128i s1D = xx_loadl_64(src1 + src1_stride * 3);
75
0
      const __m256i s0 = yy_set_m128i(_mm_unpacklo_epi64(s0C, s0D),
76
0
                                      _mm_unpacklo_epi64(s0A, s0B));
77
0
      const __m256i s1 = yy_set_m128i(_mm_unpacklo_epi64(s1C, s1D),
78
0
                                      _mm_unpacklo_epi64(s1A, s1B));
79
0
      const __m256i m16 = calc_mask_d16_avx2(&s0, &s1, &_r, &y38, &y64, shift);
80
0
      const __m256i m8 = _mm256_packus_epi16(m16, _mm256_setzero_si256());
81
0
      xx_storeu_128(mask,
82
0
                    _mm256_castsi256_si128(_mm256_permute4x64_epi64(m8, 0xd8)));
83
0
      src0 += src0_stride << 2;
84
0
      src1 += src1_stride << 2;
85
0
      mask += 16;
86
0
      i += 4;
87
0
    } while (i < h);
88
0
  } else if (w == 8) {
89
0
    do {
90
0
      const __m256i s0AB = yy_loadu2_128(src0 + src0_stride, src0);
91
0
      const __m256i s0CD =
92
0
          yy_loadu2_128(src0 + src0_stride * 3, src0 + src0_stride * 2);
93
0
      const __m256i s1AB = yy_loadu2_128(src1 + src1_stride, src1);
94
0
      const __m256i s1CD =
95
0
          yy_loadu2_128(src1 + src1_stride * 3, src1 + src1_stride * 2);
96
0
      const __m256i m16AB =
97
0
          calc_mask_d16_avx2(&s0AB, &s1AB, &_r, &y38, &y64, shift);
98
0
      const __m256i m16CD =
99
0
          calc_mask_d16_avx2(&s0CD, &s1CD, &_r, &y38, &y64, shift);
100
0
      const __m256i m8 = _mm256_packus_epi16(m16AB, m16CD);
101
0
      yy_storeu_256(mask, _mm256_permute4x64_epi64(m8, 0xd8));
102
0
      src0 += src0_stride << 2;
103
0
      src1 += src1_stride << 2;
104
0
      mask += 32;
105
0
      i += 4;
106
0
    } while (i < h);
107
0
  } else if (w == 16) {
108
0
    do {
109
0
      const __m256i s0A = yy_loadu_256(src0);
110
0
      const __m256i s0B = yy_loadu_256(src0 + src0_stride);
111
0
      const __m256i s1A = yy_loadu_256(src1);
112
0
      const __m256i s1B = yy_loadu_256(src1 + src1_stride);
113
0
      const __m256i m16A =
114
0
          calc_mask_d16_avx2(&s0A, &s1A, &_r, &y38, &y64, shift);
115
0
      const __m256i m16B =
116
0
          calc_mask_d16_avx2(&s0B, &s1B, &_r, &y38, &y64, shift);
117
0
      const __m256i m8 = _mm256_packus_epi16(m16A, m16B);
118
0
      yy_storeu_256(mask, _mm256_permute4x64_epi64(m8, 0xd8));
119
0
      src0 += src0_stride << 1;
120
0
      src1 += src1_stride << 1;
121
0
      mask += 32;
122
0
      i += 2;
123
0
    } while (i < h);
124
0
  } else if (w == 32) {
125
0
    do {
126
0
      const __m256i s0A = yy_loadu_256(src0);
127
0
      const __m256i s0B = yy_loadu_256(src0 + 16);
128
0
      const __m256i s1A = yy_loadu_256(src1);
129
0
      const __m256i s1B = yy_loadu_256(src1 + 16);
130
0
      const __m256i m16A =
131
0
          calc_mask_d16_avx2(&s0A, &s1A, &_r, &y38, &y64, shift);
132
0
      const __m256i m16B =
133
0
          calc_mask_d16_avx2(&s0B, &s1B, &_r, &y38, &y64, shift);
134
0
      const __m256i m8 = _mm256_packus_epi16(m16A, m16B);
135
0
      yy_storeu_256(mask, _mm256_permute4x64_epi64(m8, 0xd8));
136
0
      src0 += src0_stride;
137
0
      src1 += src1_stride;
138
0
      mask += 32;
139
0
      i += 1;
140
0
    } while (i < h);
141
0
  } else if (w == 64) {
142
0
    do {
143
0
      const __m256i s0A = yy_loadu_256(src0);
144
0
      const __m256i s0B = yy_loadu_256(src0 + 16);
145
0
      const __m256i s0C = yy_loadu_256(src0 + 32);
146
0
      const __m256i s0D = yy_loadu_256(src0 + 48);
147
0
      const __m256i s1A = yy_loadu_256(src1);
148
0
      const __m256i s1B = yy_loadu_256(src1 + 16);
149
0
      const __m256i s1C = yy_loadu_256(src1 + 32);
150
0
      const __m256i s1D = yy_loadu_256(src1 + 48);
151
0
      const __m256i m16A =
152
0
          calc_mask_d16_avx2(&s0A, &s1A, &_r, &y38, &y64, shift);
153
0
      const __m256i m16B =
154
0
          calc_mask_d16_avx2(&s0B, &s1B, &_r, &y38, &y64, shift);
155
0
      const __m256i m16C =
156
0
          calc_mask_d16_avx2(&s0C, &s1C, &_r, &y38, &y64, shift);
157
0
      const __m256i m16D =
158
0
          calc_mask_d16_avx2(&s0D, &s1D, &_r, &y38, &y64, shift);
159
0
      const __m256i m8AB = _mm256_packus_epi16(m16A, m16B);
160
0
      const __m256i m8CD = _mm256_packus_epi16(m16C, m16D);
161
0
      yy_storeu_256(mask, _mm256_permute4x64_epi64(m8AB, 0xd8));
162
0
      yy_storeu_256(mask + 32, _mm256_permute4x64_epi64(m8CD, 0xd8));
163
0
      src0 += src0_stride;
164
0
      src1 += src1_stride;
165
0
      mask += 64;
166
0
      i += 1;
167
0
    } while (i < h);
168
0
  } else if (w == 128) {
169
0
    do {
170
0
      const __m256i s0A = yy_loadu_256(src0);
171
0
      const __m256i s0B = yy_loadu_256(src0 + 16);
172
0
      const __m256i s0C = yy_loadu_256(src0 + 32);
173
0
      const __m256i s0D = yy_loadu_256(src0 + 48);
174
0
      const __m256i s0E = yy_loadu_256(src0 + 64);
175
0
      const __m256i s0F = yy_loadu_256(src0 + 80);
176
0
      const __m256i s0G = yy_loadu_256(src0 + 96);
177
0
      const __m256i s0H = yy_loadu_256(src0 + 112);
178
0
      const __m256i s1A = yy_loadu_256(src1);
179
0
      const __m256i s1B = yy_loadu_256(src1 + 16);
180
0
      const __m256i s1C = yy_loadu_256(src1 + 32);
181
0
      const __m256i s1D = yy_loadu_256(src1 + 48);
182
0
      const __m256i s1E = yy_loadu_256(src1 + 64);
183
0
      const __m256i s1F = yy_loadu_256(src1 + 80);
184
0
      const __m256i s1G = yy_loadu_256(src1 + 96);
185
0
      const __m256i s1H = yy_loadu_256(src1 + 112);
186
0
      const __m256i m16A =
187
0
          calc_mask_d16_avx2(&s0A, &s1A, &_r, &y38, &y64, shift);
188
0
      const __m256i m16B =
189
0
          calc_mask_d16_avx2(&s0B, &s1B, &_r, &y38, &y64, shift);
190
0
      const __m256i m16C =
191
0
          calc_mask_d16_avx2(&s0C, &s1C, &_r, &y38, &y64, shift);
192
0
      const __m256i m16D =
193
0
          calc_mask_d16_avx2(&s0D, &s1D, &_r, &y38, &y64, shift);
194
0
      const __m256i m16E =
195
0
          calc_mask_d16_avx2(&s0E, &s1E, &_r, &y38, &y64, shift);
196
0
      const __m256i m16F =
197
0
          calc_mask_d16_avx2(&s0F, &s1F, &_r, &y38, &y64, shift);
198
0
      const __m256i m16G =
199
0
          calc_mask_d16_avx2(&s0G, &s1G, &_r, &y38, &y64, shift);
200
0
      const __m256i m16H =
201
0
          calc_mask_d16_avx2(&s0H, &s1H, &_r, &y38, &y64, shift);
202
0
      const __m256i m8AB = _mm256_packus_epi16(m16A, m16B);
203
0
      const __m256i m8CD = _mm256_packus_epi16(m16C, m16D);
204
0
      const __m256i m8EF = _mm256_packus_epi16(m16E, m16F);
205
0
      const __m256i m8GH = _mm256_packus_epi16(m16G, m16H);
206
0
      yy_storeu_256(mask, _mm256_permute4x64_epi64(m8AB, 0xd8));
207
0
      yy_storeu_256(mask + 32, _mm256_permute4x64_epi64(m8CD, 0xd8));
208
0
      yy_storeu_256(mask + 64, _mm256_permute4x64_epi64(m8EF, 0xd8));
209
0
      yy_storeu_256(mask + 96, _mm256_permute4x64_epi64(m8GH, 0xd8));
210
0
      src0 += src0_stride;
211
0
      src1 += src1_stride;
212
0
      mask += 128;
213
0
      i += 1;
214
0
    } while (i < h);
215
0
  } else {
216
0
    assert(w == 256);
217
0
    do {
218
0
      const CONV_BUF_TYPE *src0_ptr = src0;
219
0
      const CONV_BUF_TYPE *src1_ptr = src1;
220
0
      for (int loop = 0; loop < 2; loop++) {
221
0
        const __m256i s0A = yy_loadu_256(src0_ptr);
222
0
        const __m256i s0B = yy_loadu_256(src0_ptr + 16);
223
0
        const __m256i s0C = yy_loadu_256(src0_ptr + 32);
224
0
        const __m256i s0D = yy_loadu_256(src0_ptr + 48);
225
0
        const __m256i s0E = yy_loadu_256(src0_ptr + 64);
226
0
        const __m256i s0F = yy_loadu_256(src0_ptr + 80);
227
0
        const __m256i s0G = yy_loadu_256(src0_ptr + 96);
228
0
        const __m256i s0H = yy_loadu_256(src0_ptr + 112);
229
0
        const __m256i s1A = yy_loadu_256(src1_ptr);
230
0
        const __m256i s1B = yy_loadu_256(src1_ptr + 16);
231
0
        const __m256i s1C = yy_loadu_256(src1_ptr + 32);
232
0
        const __m256i s1D = yy_loadu_256(src1_ptr + 48);
233
0
        const __m256i s1E = yy_loadu_256(src1_ptr + 64);
234
0
        const __m256i s1F = yy_loadu_256(src1_ptr + 80);
235
0
        const __m256i s1G = yy_loadu_256(src1_ptr + 96);
236
0
        const __m256i s1H = yy_loadu_256(src1_ptr + 112);
237
0
        const __m256i m16A =
238
0
            calc_mask_d16_avx2(&s0A, &s1A, &_r, &y38, &y64, shift);
239
0
        const __m256i m16B =
240
0
            calc_mask_d16_avx2(&s0B, &s1B, &_r, &y38, &y64, shift);
241
0
        const __m256i m16C =
242
0
            calc_mask_d16_avx2(&s0C, &s1C, &_r, &y38, &y64, shift);
243
0
        const __m256i m16D =
244
0
            calc_mask_d16_avx2(&s0D, &s1D, &_r, &y38, &y64, shift);
245
0
        const __m256i m16E =
246
0
            calc_mask_d16_avx2(&s0E, &s1E, &_r, &y38, &y64, shift);
247
0
        const __m256i m16F =
248
0
            calc_mask_d16_avx2(&s0F, &s1F, &_r, &y38, &y64, shift);
249
0
        const __m256i m16G =
250
0
            calc_mask_d16_avx2(&s0G, &s1G, &_r, &y38, &y64, shift);
251
0
        const __m256i m16H =
252
0
            calc_mask_d16_avx2(&s0H, &s1H, &_r, &y38, &y64, shift);
253
0
        const __m256i m8AB = _mm256_packus_epi16(m16A, m16B);
254
0
        const __m256i m8CD = _mm256_packus_epi16(m16C, m16D);
255
0
        const __m256i m8EF = _mm256_packus_epi16(m16E, m16F);
256
0
        const __m256i m8GH = _mm256_packus_epi16(m16G, m16H);
257
0
        yy_storeu_256(mask, _mm256_permute4x64_epi64(m8AB, 0xd8));
258
0
        yy_storeu_256(mask + 32, _mm256_permute4x64_epi64(m8CD, 0xd8));
259
0
        yy_storeu_256(mask + 64, _mm256_permute4x64_epi64(m8EF, 0xd8));
260
0
        yy_storeu_256(mask + 96, _mm256_permute4x64_epi64(m8GH, 0xd8));
261
0
        src0_ptr += 128;
262
0
        src1_ptr += 128;
263
0
        mask += 128;
264
0
      }
265
0
      src0 += src0_stride;
266
0
      src1 += src1_stride;
267
0
      i += 1;
268
0
    } while (i < h);
269
0
  }
270
0
}
271
272
static INLINE void build_compound_diffwtd_mask_d16_inv_avx2(
273
    uint8_t *mask, const CONV_BUF_TYPE *src0, int src0_stride,
274
0
    const CONV_BUF_TYPE *src1, int src1_stride, int h, int w, int shift) {
275
0
  const int mask_base = 38;
276
0
  const __m256i _r = _mm256_set1_epi16((1 << shift) >> 1);
277
0
  const __m256i y38 = _mm256_set1_epi16(mask_base);
278
0
  const __m256i y64 = _mm256_set1_epi16(AVM_BLEND_A64_MAX_ALPHA);
279
0
  int i = 0;
280
0
  if (w == 4) {
281
0
    do {
282
0
      const __m128i s0A = xx_loadl_64(src0);
283
0
      const __m128i s0B = xx_loadl_64(src0 + src0_stride);
284
0
      const __m128i s0C = xx_loadl_64(src0 + src0_stride * 2);
285
0
      const __m128i s0D = xx_loadl_64(src0 + src0_stride * 3);
286
0
      const __m128i s1A = xx_loadl_64(src1);
287
0
      const __m128i s1B = xx_loadl_64(src1 + src1_stride);
288
0
      const __m128i s1C = xx_loadl_64(src1 + src1_stride * 2);
289
0
      const __m128i s1D = xx_loadl_64(src1 + src1_stride * 3);
290
0
      const __m256i s0 = yy_set_m128i(_mm_unpacklo_epi64(s0C, s0D),
291
0
                                      _mm_unpacklo_epi64(s0A, s0B));
292
0
      const __m256i s1 = yy_set_m128i(_mm_unpacklo_epi64(s1C, s1D),
293
0
                                      _mm_unpacklo_epi64(s1A, s1B));
294
0
      const __m256i m16 =
295
0
          calc_mask_d16_inv_avx2(&s0, &s1, &_r, &y38, &y64, shift);
296
0
      const __m256i m8 = _mm256_packus_epi16(m16, _mm256_setzero_si256());
297
0
      xx_storeu_128(mask,
298
0
                    _mm256_castsi256_si128(_mm256_permute4x64_epi64(m8, 0xd8)));
299
0
      src0 += src0_stride << 2;
300
0
      src1 += src1_stride << 2;
301
0
      mask += 16;
302
0
      i += 4;
303
0
    } while (i < h);
304
0
  } else if (w == 8) {
305
0
    do {
306
0
      const __m256i s0AB = yy_loadu2_128(src0 + src0_stride, src0);
307
0
      const __m256i s0CD =
308
0
          yy_loadu2_128(src0 + src0_stride * 3, src0 + src0_stride * 2);
309
0
      const __m256i s1AB = yy_loadu2_128(src1 + src1_stride, src1);
310
0
      const __m256i s1CD =
311
0
          yy_loadu2_128(src1 + src1_stride * 3, src1 + src1_stride * 2);
312
0
      const __m256i m16AB =
313
0
          calc_mask_d16_inv_avx2(&s0AB, &s1AB, &_r, &y38, &y64, shift);
314
0
      const __m256i m16CD =
315
0
          calc_mask_d16_inv_avx2(&s0CD, &s1CD, &_r, &y38, &y64, shift);
316
0
      const __m256i m8 = _mm256_packus_epi16(m16AB, m16CD);
317
0
      yy_storeu_256(mask, _mm256_permute4x64_epi64(m8, 0xd8));
318
0
      src0 += src0_stride << 2;
319
0
      src1 += src1_stride << 2;
320
0
      mask += 32;
321
0
      i += 4;
322
0
    } while (i < h);
323
0
  } else if (w == 16) {
324
0
    do {
325
0
      const __m256i s0A = yy_loadu_256(src0);
326
0
      const __m256i s0B = yy_loadu_256(src0 + src0_stride);
327
0
      const __m256i s1A = yy_loadu_256(src1);
328
0
      const __m256i s1B = yy_loadu_256(src1 + src1_stride);
329
0
      const __m256i m16A =
330
0
          calc_mask_d16_inv_avx2(&s0A, &s1A, &_r, &y38, &y64, shift);
331
0
      const __m256i m16B =
332
0
          calc_mask_d16_inv_avx2(&s0B, &s1B, &_r, &y38, &y64, shift);
333
0
      const __m256i m8 = _mm256_packus_epi16(m16A, m16B);
334
0
      yy_storeu_256(mask, _mm256_permute4x64_epi64(m8, 0xd8));
335
0
      src0 += src0_stride << 1;
336
0
      src1 += src1_stride << 1;
337
0
      mask += 32;
338
0
      i += 2;
339
0
    } while (i < h);
340
0
  } else if (w == 32) {
341
0
    do {
342
0
      const __m256i s0A = yy_loadu_256(src0);
343
0
      const __m256i s0B = yy_loadu_256(src0 + 16);
344
0
      const __m256i s1A = yy_loadu_256(src1);
345
0
      const __m256i s1B = yy_loadu_256(src1 + 16);
346
0
      const __m256i m16A =
347
0
          calc_mask_d16_inv_avx2(&s0A, &s1A, &_r, &y38, &y64, shift);
348
0
      const __m256i m16B =
349
0
          calc_mask_d16_inv_avx2(&s0B, &s1B, &_r, &y38, &y64, shift);
350
0
      const __m256i m8 = _mm256_packus_epi16(m16A, m16B);
351
0
      yy_storeu_256(mask, _mm256_permute4x64_epi64(m8, 0xd8));
352
0
      src0 += src0_stride;
353
0
      src1 += src1_stride;
354
0
      mask += 32;
355
0
      i += 1;
356
0
    } while (i < h);
357
0
  } else if (w == 64) {
358
0
    do {
359
0
      const __m256i s0A = yy_loadu_256(src0);
360
0
      const __m256i s0B = yy_loadu_256(src0 + 16);
361
0
      const __m256i s0C = yy_loadu_256(src0 + 32);
362
0
      const __m256i s0D = yy_loadu_256(src0 + 48);
363
0
      const __m256i s1A = yy_loadu_256(src1);
364
0
      const __m256i s1B = yy_loadu_256(src1 + 16);
365
0
      const __m256i s1C = yy_loadu_256(src1 + 32);
366
0
      const __m256i s1D = yy_loadu_256(src1 + 48);
367
0
      const __m256i m16A =
368
0
          calc_mask_d16_inv_avx2(&s0A, &s1A, &_r, &y38, &y64, shift);
369
0
      const __m256i m16B =
370
0
          calc_mask_d16_inv_avx2(&s0B, &s1B, &_r, &y38, &y64, shift);
371
0
      const __m256i m16C =
372
0
          calc_mask_d16_inv_avx2(&s0C, &s1C, &_r, &y38, &y64, shift);
373
0
      const __m256i m16D =
374
0
          calc_mask_d16_inv_avx2(&s0D, &s1D, &_r, &y38, &y64, shift);
375
0
      const __m256i m8AB = _mm256_packus_epi16(m16A, m16B);
376
0
      const __m256i m8CD = _mm256_packus_epi16(m16C, m16D);
377
0
      yy_storeu_256(mask, _mm256_permute4x64_epi64(m8AB, 0xd8));
378
0
      yy_storeu_256(mask + 32, _mm256_permute4x64_epi64(m8CD, 0xd8));
379
0
      src0 += src0_stride;
380
0
      src1 += src1_stride;
381
0
      mask += 64;
382
0
      i += 1;
383
0
    } while (i < h);
384
0
  } else if (w == 128) {
385
0
    do {
386
0
      const __m256i s0A = yy_loadu_256(src0);
387
0
      const __m256i s0B = yy_loadu_256(src0 + 16);
388
0
      const __m256i s0C = yy_loadu_256(src0 + 32);
389
0
      const __m256i s0D = yy_loadu_256(src0 + 48);
390
0
      const __m256i s0E = yy_loadu_256(src0 + 64);
391
0
      const __m256i s0F = yy_loadu_256(src0 + 80);
392
0
      const __m256i s0G = yy_loadu_256(src0 + 96);
393
0
      const __m256i s0H = yy_loadu_256(src0 + 112);
394
0
      const __m256i s1A = yy_loadu_256(src1);
395
0
      const __m256i s1B = yy_loadu_256(src1 + 16);
396
0
      const __m256i s1C = yy_loadu_256(src1 + 32);
397
0
      const __m256i s1D = yy_loadu_256(src1 + 48);
398
0
      const __m256i s1E = yy_loadu_256(src1 + 64);
399
0
      const __m256i s1F = yy_loadu_256(src1 + 80);
400
0
      const __m256i s1G = yy_loadu_256(src1 + 96);
401
0
      const __m256i s1H = yy_loadu_256(src1 + 112);
402
0
      const __m256i m16A =
403
0
          calc_mask_d16_inv_avx2(&s0A, &s1A, &_r, &y38, &y64, shift);
404
0
      const __m256i m16B =
405
0
          calc_mask_d16_inv_avx2(&s0B, &s1B, &_r, &y38, &y64, shift);
406
0
      const __m256i m16C =
407
0
          calc_mask_d16_inv_avx2(&s0C, &s1C, &_r, &y38, &y64, shift);
408
0
      const __m256i m16D =
409
0
          calc_mask_d16_inv_avx2(&s0D, &s1D, &_r, &y38, &y64, shift);
410
0
      const __m256i m16E =
411
0
          calc_mask_d16_inv_avx2(&s0E, &s1E, &_r, &y38, &y64, shift);
412
0
      const __m256i m16F =
413
0
          calc_mask_d16_inv_avx2(&s0F, &s1F, &_r, &y38, &y64, shift);
414
0
      const __m256i m16G =
415
0
          calc_mask_d16_inv_avx2(&s0G, &s1G, &_r, &y38, &y64, shift);
416
0
      const __m256i m16H =
417
0
          calc_mask_d16_inv_avx2(&s0H, &s1H, &_r, &y38, &y64, shift);
418
0
      const __m256i m8AB = _mm256_packus_epi16(m16A, m16B);
419
0
      const __m256i m8CD = _mm256_packus_epi16(m16C, m16D);
420
0
      const __m256i m8EF = _mm256_packus_epi16(m16E, m16F);
421
0
      const __m256i m8GH = _mm256_packus_epi16(m16G, m16H);
422
0
      yy_storeu_256(mask, _mm256_permute4x64_epi64(m8AB, 0xd8));
423
0
      yy_storeu_256(mask + 32, _mm256_permute4x64_epi64(m8CD, 0xd8));
424
0
      yy_storeu_256(mask + 64, _mm256_permute4x64_epi64(m8EF, 0xd8));
425
0
      yy_storeu_256(mask + 96, _mm256_permute4x64_epi64(m8GH, 0xd8));
426
0
      src0 += src0_stride;
427
0
      src1 += src1_stride;
428
0
      mask += 128;
429
0
      i += 1;
430
0
    } while (i < h);
431
0
  } else {
432
0
    assert(w == 256);
433
0
    do {
434
0
      const CONV_BUF_TYPE *src0_ptr = src0;
435
0
      const CONV_BUF_TYPE *src1_ptr = src1;
436
0
      for (int loop = 0; loop < 2; loop++) {
437
0
        const __m256i s0A = yy_loadu_256(src0_ptr);
438
0
        const __m256i s0B = yy_loadu_256(src0_ptr + 16);
439
0
        const __m256i s0C = yy_loadu_256(src0_ptr + 32);
440
0
        const __m256i s0D = yy_loadu_256(src0_ptr + 48);
441
0
        const __m256i s0E = yy_loadu_256(src0_ptr + 64);
442
0
        const __m256i s0F = yy_loadu_256(src0_ptr + 80);
443
0
        const __m256i s0G = yy_loadu_256(src0_ptr + 96);
444
0
        const __m256i s0H = yy_loadu_256(src0_ptr + 112);
445
0
        const __m256i s1A = yy_loadu_256(src1_ptr);
446
0
        const __m256i s1B = yy_loadu_256(src1_ptr + 16);
447
0
        const __m256i s1C = yy_loadu_256(src1_ptr + 32);
448
0
        const __m256i s1D = yy_loadu_256(src1_ptr + 48);
449
0
        const __m256i s1E = yy_loadu_256(src1_ptr + 64);
450
0
        const __m256i s1F = yy_loadu_256(src1_ptr + 80);
451
0
        const __m256i s1G = yy_loadu_256(src1_ptr + 96);
452
0
        const __m256i s1H = yy_loadu_256(src1_ptr + 112);
453
0
        const __m256i m16A =
454
0
            calc_mask_d16_inv_avx2(&s0A, &s1A, &_r, &y38, &y64, shift);
455
0
        const __m256i m16B =
456
0
            calc_mask_d16_inv_avx2(&s0B, &s1B, &_r, &y38, &y64, shift);
457
0
        const __m256i m16C =
458
0
            calc_mask_d16_inv_avx2(&s0C, &s1C, &_r, &y38, &y64, shift);
459
0
        const __m256i m16D =
460
0
            calc_mask_d16_inv_avx2(&s0D, &s1D, &_r, &y38, &y64, shift);
461
0
        const __m256i m16E =
462
0
            calc_mask_d16_inv_avx2(&s0E, &s1E, &_r, &y38, &y64, shift);
463
0
        const __m256i m16F =
464
0
            calc_mask_d16_inv_avx2(&s0F, &s1F, &_r, &y38, &y64, shift);
465
0
        const __m256i m16G =
466
0
            calc_mask_d16_inv_avx2(&s0G, &s1G, &_r, &y38, &y64, shift);
467
0
        const __m256i m16H =
468
0
            calc_mask_d16_inv_avx2(&s0H, &s1H, &_r, &y38, &y64, shift);
469
0
        const __m256i m8AB = _mm256_packus_epi16(m16A, m16B);
470
0
        const __m256i m8CD = _mm256_packus_epi16(m16C, m16D);
471
0
        const __m256i m8EF = _mm256_packus_epi16(m16E, m16F);
472
0
        const __m256i m8GH = _mm256_packus_epi16(m16G, m16H);
473
0
        yy_storeu_256(mask, _mm256_permute4x64_epi64(m8AB, 0xd8));
474
0
        yy_storeu_256(mask + 32, _mm256_permute4x64_epi64(m8CD, 0xd8));
475
0
        yy_storeu_256(mask + 64, _mm256_permute4x64_epi64(m8EF, 0xd8));
476
0
        yy_storeu_256(mask + 96, _mm256_permute4x64_epi64(m8GH, 0xd8));
477
0
        src0_ptr += 128;
478
0
        src1_ptr += 128;
479
0
        mask += 128;
480
0
      }
481
0
      src0 += src0_stride;
482
0
      src1 += src1_stride;
483
0
      i += 1;
484
0
    } while (i < h);
485
0
  }
486
0
}
487
488
void av2_build_compound_diffwtd_mask_d16_avx2(
489
    uint8_t *mask, DIFFWTD_MASK_TYPE mask_type, const CONV_BUF_TYPE *src0,
490
    int src0_stride, const CONV_BUF_TYPE *src1, int src1_stride, int h, int w,
491
0
    ConvolveParams *conv_params, int bd) {
492
0
  const int shift =
493
0
      2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1 + (bd - 8);
494
  // When rounding constant is added, there is a possibility of overflow.
495
  // However that much precision is not required. Code should very well work for
496
  // other values of DIFF_FACTOR_LOG2 and AVM_BLEND_A64_MAX_ALPHA as well. But
497
  // there is a possibility of corner case bugs.
498
0
  assert(DIFF_FACTOR_LOG2 == 4);
499
0
  assert(AVM_BLEND_A64_MAX_ALPHA == 64);
500
501
0
  if (mask_type == DIFFWTD_38) {
502
0
    build_compound_diffwtd_mask_d16_avx2(mask, src0, src0_stride, src1,
503
0
                                         src1_stride, h, w, shift);
504
0
  } else {
505
0
    build_compound_diffwtd_mask_d16_inv_avx2(mask, src0, src0_stride, src1,
506
0
                                             src1_stride, h, w, shift);
507
0
  }
508
0
}
509
510
void av2_build_compound_diffwtd_mask_highbd_avx2(
511
    uint8_t *mask, DIFFWTD_MASK_TYPE mask_type, const uint16_t *ssrc0,
512
    int src0_stride, const uint16_t *ssrc1, int src1_stride, int h, int w,
513
0
    int bd) {
514
0
  if (w < 16) {
515
0
    av2_build_compound_diffwtd_mask_highbd_ssse3(
516
0
        mask, mask_type, ssrc0, src0_stride, ssrc1, src1_stride, h, w, bd);
517
0
  } else {
518
0
    assert(mask_type == DIFFWTD_38 || mask_type == DIFFWTD_38_INV);
519
0
    assert(bd >= 8);
520
0
    assert((w % 16) == 0);
521
0
    const __m256i y0 = _mm256_setzero_si256();
522
0
    const __m256i yAVM_BLEND_A64_MAX_ALPHA =
523
0
        _mm256_set1_epi16(AVM_BLEND_A64_MAX_ALPHA);
524
0
    const int mask_base = 38;
525
0
    const __m256i ymask_base = _mm256_set1_epi16(mask_base);
526
0
    if (bd == 8) {
527
0
      if (mask_type == DIFFWTD_38_INV) {
528
0
        for (int i = 0; i < h; ++i) {
529
0
          for (int j = 0; j < w; j += 16) {
530
0
            __m256i s0 = _mm256_loadu_si256((const __m256i *)&ssrc0[j]);
531
0
            __m256i s1 = _mm256_loadu_si256((const __m256i *)&ssrc1[j]);
532
0
            __m256i diff = _mm256_srai_epi16(
533
0
                _mm256_abs_epi16(_mm256_sub_epi16(s0, s1)), DIFF_FACTOR_LOG2);
534
0
            __m256i m = _mm256_min_epi16(
535
0
                _mm256_max_epi16(y0, _mm256_add_epi16(diff, ymask_base)),
536
0
                yAVM_BLEND_A64_MAX_ALPHA);
537
0
            m = _mm256_sub_epi16(yAVM_BLEND_A64_MAX_ALPHA, m);
538
0
            m = _mm256_packus_epi16(m, m);
539
0
            m = _mm256_permute4x64_epi64(m, _MM_SHUFFLE(0, 0, 2, 0));
540
0
            __m128i m0 = _mm256_castsi256_si128(m);
541
0
            _mm_storeu_si128((__m128i *)&mask[j], m0);
542
0
          }
543
0
          ssrc0 += src0_stride;
544
0
          ssrc1 += src1_stride;
545
0
          mask += w;
546
0
        }
547
0
      } else {
548
0
        for (int i = 0; i < h; ++i) {
549
0
          for (int j = 0; j < w; j += 16) {
550
0
            __m256i s0 = _mm256_loadu_si256((const __m256i *)&ssrc0[j]);
551
0
            __m256i s1 = _mm256_loadu_si256((const __m256i *)&ssrc1[j]);
552
0
            __m256i diff = _mm256_srai_epi16(
553
0
                _mm256_abs_epi16(_mm256_sub_epi16(s0, s1)), DIFF_FACTOR_LOG2);
554
0
            __m256i m = _mm256_min_epi16(
555
0
                _mm256_max_epi16(y0, _mm256_add_epi16(diff, ymask_base)),
556
0
                yAVM_BLEND_A64_MAX_ALPHA);
557
0
            m = _mm256_packus_epi16(m, m);
558
0
            m = _mm256_permute4x64_epi64(m, _MM_SHUFFLE(0, 0, 2, 0));
559
0
            __m128i m0 = _mm256_castsi256_si128(m);
560
0
            _mm_storeu_si128((__m128i *)&mask[j], m0);
561
0
          }
562
0
          ssrc0 += src0_stride;
563
0
          ssrc1 += src1_stride;
564
0
          mask += w;
565
0
        }
566
0
      }
567
0
    } else {
568
0
      const __m128i xshift = xx_set1_64_from_32i(bd - 8 + DIFF_FACTOR_LOG2);
569
0
      if (mask_type == DIFFWTD_38_INV) {
570
0
        for (int i = 0; i < h; ++i) {
571
0
          for (int j = 0; j < w; j += 16) {
572
0
            __m256i s0 = _mm256_loadu_si256((const __m256i *)&ssrc0[j]);
573
0
            __m256i s1 = _mm256_loadu_si256((const __m256i *)&ssrc1[j]);
574
0
            __m256i diff = _mm256_sra_epi16(
575
0
                _mm256_abs_epi16(_mm256_sub_epi16(s0, s1)), xshift);
576
0
            __m256i m = _mm256_min_epi16(
577
0
                _mm256_max_epi16(y0, _mm256_add_epi16(diff, ymask_base)),
578
0
                yAVM_BLEND_A64_MAX_ALPHA);
579
0
            m = _mm256_sub_epi16(yAVM_BLEND_A64_MAX_ALPHA, m);
580
0
            m = _mm256_packus_epi16(m, m);
581
0
            m = _mm256_permute4x64_epi64(m, _MM_SHUFFLE(0, 0, 2, 0));
582
0
            __m128i m0 = _mm256_castsi256_si128(m);
583
0
            _mm_storeu_si128((__m128i *)&mask[j], m0);
584
0
          }
585
0
          ssrc0 += src0_stride;
586
0
          ssrc1 += src1_stride;
587
0
          mask += w;
588
0
        }
589
0
      } else {
590
0
        for (int i = 0; i < h; ++i) {
591
0
          for (int j = 0; j < w; j += 16) {
592
0
            __m256i s0 = _mm256_loadu_si256((const __m256i *)&ssrc0[j]);
593
0
            __m256i s1 = _mm256_loadu_si256((const __m256i *)&ssrc1[j]);
594
0
            __m256i diff = _mm256_sra_epi16(
595
0
                _mm256_abs_epi16(_mm256_sub_epi16(s0, s1)), xshift);
596
0
            __m256i m = _mm256_min_epi16(
597
0
                _mm256_max_epi16(y0, _mm256_add_epi16(diff, ymask_base)),
598
0
                yAVM_BLEND_A64_MAX_ALPHA);
599
0
            m = _mm256_packus_epi16(m, m);
600
0
            m = _mm256_permute4x64_epi64(m, _MM_SHUFFLE(0, 0, 2, 0));
601
0
            __m128i m0 = _mm256_castsi256_si128(m);
602
0
            _mm_storeu_si128((__m128i *)&mask[j], m0);
603
0
          }
604
0
          ssrc0 += src0_stride;
605
0
          ssrc1 += src1_stride;
606
0
          mask += w;
607
0
        }
608
0
      }
609
0
    }
610
0
  }
611
0
}
612
613
static const uint8_t refinemv_pad_left[14][16] = {
614
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
615
  { 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
616
  { 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
617
  { 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
618
  { 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
619
  { 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
620
  { 6, 6, 6, 6, 6, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
621
  { 7, 7, 7, 7, 7, 7, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
622
  { 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14, 15 },
623
  { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 11, 12, 13, 14, 15 },
624
  { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 12, 13, 14, 15 },
625
  { 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 13, 14, 15 },
626
  { 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 14, 15 },
627
  { 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 15 },
628
};
629
630
static const uint8_t refinemv_pad_left_bw_greater_than_15[16][16] = {
631
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
632
  { 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
633
  { 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
634
  { 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
635
  { 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
636
  { 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
637
  { 6, 6, 6, 6, 6, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
638
  { 7, 7, 7, 7, 7, 7, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
639
  { 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14, 15 },
640
  { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 11, 12, 13, 14, 15 },
641
  { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 12, 13, 14, 15 },
642
  { 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 13, 14, 15 },
643
  { 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 14, 15 },
644
  { 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 15 },
645
  { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15 },
646
  { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 },
647
};
648
649
static const uint8_t refinemv_pad_right_arr[16][16] = {
650
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
651
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14 },
652
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13 },
653
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 12, 12 },
654
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 11, 11, 11 },
655
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10 },
656
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9 },
657
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8 },
658
  { 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7 },
659
  { 0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 },
660
  { 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 },
661
  { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
662
  { 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
663
  { 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
664
  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
665
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
666
};
667
668
static const uint8_t refinemv_pad_right_bw_31[15][16] = {
669
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
670
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 15 },
671
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 12, 15 },
672
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 11, 11, 15 },
673
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 15 },
674
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 15 },
675
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 15 },
676
  { 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 15 },
677
  { 0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 15 },
678
  { 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 15 },
679
  { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 15 },
680
  { 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 15 },
681
  { 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15 },
682
  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 15 },
683
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 },
684
};
685
686
static const uint8_t refinemv_pad_right_bw_23[8][16] = {
687
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
688
  { 0, 1, 2, 3, 4, 5, 5, 5, 8, 9, 10, 11, 12, 13, 13, 14 },
689
  { 0, 1, 2, 3, 4, 4, 4, 4, 8, 9, 10, 11, 12, 12, 12, 13 },
690
  { 0, 1, 2, 3, 3, 3, 3, 3, 8, 9, 10, 11, 11, 11, 11, 12 },
691
  { 0, 1, 2, 2, 2, 2, 2, 2, 8, 9, 10, 10, 10, 10, 10, 11 },
692
  { 0, 1, 1, 1, 1, 1, 1, 1, 8, 9, 9, 9, 9, 9, 9, 9 },
693
  { 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8 },
694
  { 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8 },
695
};
696
697
static const uint8_t refinemv_pad_left_bw_23[8][16] = {
698
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
699
  { 1, 1, 2, 3, 4, 5, 6, 5, 9, 9, 10, 11, 12, 13, 14, 14 },
700
  { 2, 2, 2, 3, 4, 5, 6, 4, 10, 10, 10, 11, 12, 13, 14, 15 },
701
  { 3, 3, 3, 3, 4, 5, 6, 3, 11, 11, 11, 11, 12, 13, 14, 15 },
702
  { 4, 4, 4, 4, 4, 5, 6, 2, 12, 12, 12, 12, 12, 13, 14, 15 },
703
  { 5, 5, 5, 5, 5, 5, 6, 1, 13, 13, 13, 13, 13, 13, 14, 15 },
704
  { 6, 6, 6, 6, 6, 6, 6, 0, 14, 14, 14, 14, 14, 14, 14, 15 },
705
  { 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8 },
706
};
707
708
static const uint8_t refinemv_pad_right_bw_15[14][16] = {
709
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
710
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 15 },
711
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 12, 15 },
712
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 11, 11, 15 },
713
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 15 },
714
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 15 },
715
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 15 },
716
  { 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 15 },
717
  { 0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 15 },
718
  { 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 15 },
719
  { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 15 },
720
  { 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 15 },
721
  { 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15 },
722
  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 15 },
723
};
724
725
static const uint8_t refinemv_pad_right_bw_11[10][16] = {
726
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
727
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 11, 12, 13, 14, 15 },
728
  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 11, 12, 13, 14, 15 },
729
  { 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 11, 12, 13, 14, 15 },
730
  { 0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 11, 12, 13, 14, 15 },
731
  { 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 11, 12, 13, 14, 15 },
732
  { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 11, 12, 13, 14, 15 },
733
  { 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 11, 12, 13, 14, 15 },
734
  { 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 11, 12, 13, 14, 15 },
735
  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 12, 13, 14, 15 },
736
};
737
738
DECLARE_ALIGNED(32, static const uint8_t, pad_mc_border_shuffle_pattern[32]) = {
739
  0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15,
740
  0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15
741
};
742
743
DECLARE_ALIGNED(32, static const uint8_t, pad_mc_border_arrange_bytes[32]) = {
744
  0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15,
745
  0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15
746
};
747
748
// AVX2 implementation for refinemv_highbd_pad_mc_border_c for b_w = 15.
749
void refinemv_highbd_pad_mc_border_avx2(const uint16_t *src, int src_stride,
750
                                        uint16_t *dst, int dst_stride, int x0,
751
                                        int y0, int b_w, int b_h,
752
0
                                        const ReferenceArea *ref_area) {
753
0
  if (b_w != 15 && b_w != 11 && b_w != 23 && b_w != 31) {
754
0
    refinemv_highbd_pad_mc_border_c(src, src_stride, dst, dst_stride, x0, y0,
755
0
                                    b_w, b_h, ref_area);
756
0
    return;
757
0
  }
758
759
0
  assert(b_w == 15 || b_w == 11 || b_w == 23 || b_w == 31);
760
0
  const int ref_x0 = ref_area->pad_block.x0;
761
0
  const int ref_y0 = ref_area->pad_block.y0;
762
0
  const int ref_x1 = ref_area->pad_block.x1;
763
0
  const int ref_y1 = ref_area->pad_block.y1;
764
765
  // Get a pointer to the start of the real data for this row.
766
0
  const uint16_t *ref_row = src - x0 - y0 * src_stride;
767
768
0
  if (y0 >= ref_area->pad_block.y1)
769
0
    ref_row += (ref_area->pad_block.y1 - 1) * src_stride;
770
0
  else if (y0 >= ref_area->pad_block.y0)
771
0
    ref_row += y0 * src_stride;
772
0
  else
773
0
    ref_row += ref_area->pad_block.y0 * src_stride;
774
775
0
  int left = x0 < ref_x0 ? ref_x0 - x0 : 0;
776
0
  if (left > b_w) left = b_w;
777
0
  int right = (x0 + b_w > ref_x1) ? (x0 + b_w - ref_x1) : 0;
778
0
  if (right > b_w) right = b_w;
779
0
  if (b_w == 23) {
780
0
    if (left < (b_w - 1) && right < (b_w - 1) && (left != 0 || right != 0)) {
781
0
      const __m256i shuffle_input_reg =
782
0
          _mm256_load_si256((__m256i *)pad_mc_border_arrange_bytes);
783
0
      const __m256i shuffle_output_reg =
784
0
          _mm256_load_si256((__m256i *)pad_mc_border_shuffle_pattern);
785
0
      if (left < 16) {
786
0
        const __m128i shuffle_left = _mm_loadu_si128(
787
0
            (__m128i *)refinemv_pad_left_bw_greater_than_15[left]);
788
0
        const __m256i shuffle_reg_left = _mm256_inserti128_si256(
789
0
            _mm256_castsi128_si256(shuffle_left), shuffle_left, 1);
790
0
        if (right > 6) {
791
0
          const uint8_t *refinemv_pad_right = refinemv_pad_right_arr[right - 7];
792
0
          const __m128i shuffle_right =
793
0
              _mm_loadu_si128((__m128i *)refinemv_pad_right);
794
0
          const __m256i shuffle_reg_right = _mm256_inserti128_si256(
795
0
              _mm256_castsi128_si256(shuffle_right), shuffle_right, 1);
796
0
          __m256i out_reg_lo;
797
0
          __m128i out_reg_hi;
798
0
          do {
799
            // s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15
800
0
            const __m256i src_lo =
801
0
                _mm256_loadu_si256((__m256i *)(ref_row + x0));
802
803
0
            const __m256i src_01 =
804
0
                _mm256_shuffle_epi8(src_lo, shuffle_input_reg);
805
0
            __m256i src_reg = _mm256_permute4x64_epi64(src_01, 0xD8);
806
807
0
            src_reg = _mm256_shuffle_epi8(src_reg, shuffle_reg_left);
808
0
            src_reg = _mm256_shuffle_epi8(src_reg, shuffle_reg_right);
809
810
0
            out_reg_lo = _mm256_shuffle_epi8(
811
0
                _mm256_permute4x64_epi64(src_reg, 0xD8), shuffle_output_reg);
812
0
            out_reg_hi = _mm_set1_epi16(ref_row[b_w + x0 - right - 1]);
813
0
            do {
814
0
              _mm256_storeu_si256((__m256i *)dst, out_reg_lo);
815
0
              _mm_storeu_si128((__m128i *)(dst + 16), out_reg_hi);
816
0
              dst += dst_stride;
817
0
              ++y0;
818
0
              --b_h;
819
0
            } while ((y0 <= ref_y0 || y0 >= ref_y1) && b_h);
820
0
            ref_row += src_stride;
821
0
          } while (b_h);
822
0
        } else {
823
0
          const uint8_t *refinemv_pad_right = refinemv_pad_right_bw_23[right];
824
0
          const __m128i shuffle_right =
825
0
              _mm_loadu_si128((__m128i *)refinemv_pad_right);
826
0
          __m256i out_reg_lo;
827
0
          __m128i out_reg_hi;
828
0
          do {
829
            // s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15
830
0
            const __m256i src_lo =
831
0
                _mm256_loadu_si256((__m256i *)(ref_row + x0));
832
            // s17 s18 s19 s20 s21 s22 x x
833
0
            const __m128i src_hi =
834
0
                _mm_loadu_si128((__m128i *)(ref_row + x0 + 16));
835
836
0
            const __m256i src_01 =
837
0
                _mm256_shuffle_epi8(src_lo, shuffle_input_reg);
838
0
            __m128i src_01_hi = _mm_shuffle_epi8(
839
0
                src_hi, _mm256_castsi256_si128(shuffle_input_reg));
840
0
            __m256i src_reg = _mm256_permute4x64_epi64(src_01, 0xD8);
841
842
0
            src_reg = _mm256_shuffle_epi8(src_reg, shuffle_reg_left);
843
0
            src_01_hi = _mm_shuffle_epi8(src_01_hi, shuffle_right);
844
845
0
            out_reg_lo = _mm256_shuffle_epi8(
846
0
                _mm256_permute4x64_epi64(src_reg, 0xD8), shuffle_output_reg);
847
0
            out_reg_hi = _mm_shuffle_epi8(
848
0
                src_01_hi, _mm256_castsi256_si128(shuffle_output_reg));
849
0
            do {
850
0
              _mm256_storeu_si256((__m256i *)dst, out_reg_lo);
851
0
              _mm_storeu_si128((__m128i *)(dst + 16), out_reg_hi);
852
0
              dst += dst_stride;
853
0
              ++y0;
854
0
              --b_h;
855
0
            } while ((y0 <= ref_y0 || y0 >= ref_y1) && b_h);
856
0
            ref_row += src_stride;
857
0
          } while (b_h);
858
0
        }
859
0
      } else {
860
0
        if (right > 6) {
861
0
          const uint8_t *refinemv_pad_right = refinemv_pad_right_arr[right - 7];
862
0
          const __m128i shuffle_right =
863
0
              _mm_loadu_si128((__m128i *)refinemv_pad_right);
864
0
          const __m256i shuffle_reg_right = _mm256_inserti128_si256(
865
0
              _mm256_castsi128_si256(shuffle_right), shuffle_right, 1);
866
0
          __m256i out_reg_lo;
867
0
          __m128i out_reg_hi;
868
0
          do {
869
            // s0
870
0
            const __m256i src_lo = _mm256_set1_epi16(ref_row[x0 + left]);
871
872
0
            const __m256i src_01 =
873
0
                _mm256_shuffle_epi8(src_lo, shuffle_input_reg);
874
0
            __m256i src_reg = _mm256_permute4x64_epi64(src_01, 0xD8);
875
0
            src_reg = _mm256_shuffle_epi8(src_reg, shuffle_reg_right);
876
877
0
            out_reg_lo = _mm256_shuffle_epi8(
878
0
                _mm256_permute4x64_epi64(src_reg, 0xD8), shuffle_output_reg);
879
0
            out_reg_hi = _mm_set1_epi16(ref_row[b_w + x0 - right - 1]);
880
0
            do {
881
0
              _mm256_storeu_si256((__m256i *)dst, out_reg_lo);
882
0
              _mm_storeu_si128((__m128i *)(dst + 16), out_reg_hi);
883
0
              dst += dst_stride;
884
0
              ++y0;
885
0
              --b_h;
886
0
            } while ((y0 <= ref_y0 || y0 >= ref_y1) && b_h);
887
0
            ref_row += src_stride;
888
0
          } while (b_h);
889
0
        } else {
890
0
          const uint8_t *refinemv_pad_right = refinemv_pad_right_bw_23[right];
891
0
          const __m128i shuffle_right =
892
0
              _mm_loadu_si128((__m128i *)refinemv_pad_right);
893
0
          const __m128i shuffle_left =
894
0
              _mm_loadu_si128((__m128i *)refinemv_pad_left_bw_23[left - 16]);
895
0
          __m256i out_reg_lo;
896
0
          __m128i out_reg_hi;
897
0
          do {
898
            // s0
899
0
            const __m256i src_lo = _mm256_set1_epi16(ref_row[x0 + left]);
900
            // s17 s18 s19 s20 s21 s22 x x
901
0
            const __m128i src_hi =
902
0
                _mm_loadu_si128((__m128i *)(ref_row + x0 + 16));
903
904
0
            __m128i src_01_hi = _mm_shuffle_epi8(
905
0
                src_hi, _mm256_castsi256_si128(shuffle_input_reg));
906
0
            src_01_hi = _mm_shuffle_epi8(src_01_hi, shuffle_left);
907
0
            src_01_hi = _mm_shuffle_epi8(src_01_hi, shuffle_right);
908
909
0
            out_reg_lo = src_lo;
910
0
            out_reg_hi = _mm_shuffle_epi8(
911
0
                src_01_hi, _mm256_castsi256_si128(shuffle_output_reg));
912
0
            do {
913
0
              _mm256_storeu_si256((__m256i *)dst, out_reg_lo);
914
0
              _mm_storeu_si128((__m128i *)(dst + 16), out_reg_hi);
915
0
              dst += dst_stride;
916
0
              ++y0;
917
0
              --b_h;
918
0
            } while ((y0 <= ref_y0 || y0 >= ref_y1) && b_h);
919
0
            ref_row += src_stride;
920
0
          } while (b_h);
921
0
        }
922
0
      }
923
0
    } else if (left == 0 && right == 0) {
924
0
      do {
925
0
        const __m256i src_lo = _mm256_loadu_si256((__m256i *)(ref_row + x0));
926
0
        const __m128i src_hi = _mm_loadu_si128((__m128i *)(ref_row + x0 + 16));
927
0
        _mm256_storeu_si256((__m256i *)dst, src_lo);
928
0
        _mm_storeu_si128((__m128i *)(dst + 16), src_hi);
929
0
        dst += dst_stride;
930
0
        ++y0;
931
0
        if (y0 > ref_y0 && y0 < ref_y1) ref_row += src_stride;
932
0
      } while (--b_h);
933
0
    } else {
934
0
      const uint16_t *cur_ref_row =
935
0
          (left >= (b_w - 1)) ? (ref_row + ref_x0) : (ref_row + ref_x1 - 1);
936
0
      do {
937
0
        const __m256i src_0 = _mm256_set1_epi16(cur_ref_row[0]);
938
0
        _mm256_storeu_si256((__m256i *)dst, src_0);
939
0
        _mm_storeu_si128((__m128i *)(dst + 16), _mm256_castsi256_si128(src_0));
940
0
        dst += dst_stride;
941
0
        ++y0;
942
0
        if (y0 > ref_y0 && y0 < ref_y1) cur_ref_row += src_stride;
943
0
      } while (--b_h);
944
0
    }
945
0
  } else if (b_w == 31) {
946
0
    if (left < (b_w - 1) && right < (b_w - 1) && (left != 0 || right != 0)) {
947
0
      const __m256i shuffle_input_reg =
948
0
          _mm256_load_si256((__m256i *)pad_mc_border_arrange_bytes);
949
0
      const __m256i shuffle_output_reg =
950
0
          _mm256_load_si256((__m256i *)pad_mc_border_shuffle_pattern);
951
0
      if (left < 16) {
952
0
        if (right > 14) {
953
0
          const uint8_t *refine_mv_pad_right =
954
0
              refinemv_pad_right_arr[right - 15];
955
0
          const uint8_t *refine_mv_pad_left =
956
0
              refinemv_pad_left_bw_greater_than_15[left];
957
0
          const __m128i shuffle_right =
958
0
              _mm_loadu_si128((__m128i *)refine_mv_pad_right);
959
0
          const __m256i shuffle_reg_right = _mm256_inserti128_si256(
960
0
              _mm256_castsi128_si256(shuffle_right), shuffle_right, 1);
961
0
          const __m128i shuffle_left =
962
0
              _mm_loadu_si128((__m128i *)refine_mv_pad_left);
963
0
          const __m256i shuffle_reg_left = _mm256_inserti128_si256(
964
0
              _mm256_castsi128_si256(shuffle_left), shuffle_left, 1);
965
0
          __m256i out_reg_lo, out_reg_hi;
966
0
          do {
967
            // s0
968
0
            const __m256i src_lo =
969
0
                _mm256_loadu_si256((__m256i *)(ref_row + x0));
970
971
0
            const __m256i src_01 =
972
0
                _mm256_shuffle_epi8(src_lo, shuffle_input_reg);
973
0
            __m256i src_reg = _mm256_permute4x64_epi64(src_01, 0xD8);
974
0
            src_reg = _mm256_shuffle_epi8(src_reg, shuffle_reg_left);
975
0
            src_reg = _mm256_shuffle_epi8(src_reg, shuffle_reg_right);
976
977
0
            out_reg_lo = _mm256_shuffle_epi8(
978
0
                _mm256_permute4x64_epi64(src_reg, 0xD8), shuffle_output_reg);
979
0
            out_reg_hi = _mm256_set1_epi16(ref_row[b_w + x0 - right - 1]);
980
0
            do {
981
0
              _mm256_storeu_si256((__m256i *)dst, out_reg_lo);
982
0
              _mm256_storeu_si256((__m256i *)(dst + 16), out_reg_hi);
983
0
              dst += dst_stride;
984
0
              ++y0;
985
0
              --b_h;
986
0
            } while ((y0 <= ref_y0 || y0 >= ref_y1) && b_h);
987
0
            ref_row += src_stride;
988
0
          } while (b_h);
989
0
        } else {
990
0
          const uint8_t *refinemv_pad_right = refinemv_pad_right_bw_31[right];
991
0
          const uint8_t *refine_mv_pad_left =
992
0
              refinemv_pad_left_bw_greater_than_15[left];
993
0
          const __m128i shuffle_right =
994
0
              _mm_loadu_si128((__m128i *)refinemv_pad_right);
995
0
          const __m256i shuffle_reg_right = _mm256_inserti128_si256(
996
0
              _mm256_castsi128_si256(shuffle_right), shuffle_right, 1);
997
0
          const __m128i shuffle_left =
998
0
              _mm_loadu_si128((__m128i *)refine_mv_pad_left);
999
0
          const __m256i shuffle_reg_left = _mm256_inserti128_si256(
1000
0
              _mm256_castsi128_si256(shuffle_left), shuffle_left, 1);
1001
0
          __m256i out_reg_lo, out_reg_hi;
1002
0
          do {
1003
            // s0
1004
0
            const __m256i src_lo =
1005
0
                _mm256_loadu_si256((__m256i *)(ref_row + x0));
1006
0
            const __m256i src_hi =
1007
0
                _mm256_loadu_si256((__m256i *)(ref_row + x0 + 16));
1008
1009
0
            const __m256i src_01 =
1010
0
                _mm256_shuffle_epi8(src_lo, shuffle_input_reg);
1011
0
            const __m256i src_02 =
1012
0
                _mm256_shuffle_epi8(src_hi, shuffle_input_reg);
1013
0
            __m256i src_reg_lo = _mm256_permute4x64_epi64(src_01, 0xD8);
1014
0
            __m256i src_reg_hi = _mm256_permute4x64_epi64(src_02, 0xD8);
1015
0
            src_reg_lo = _mm256_shuffle_epi8(src_reg_lo, shuffle_reg_left);
1016
0
            src_reg_hi = _mm256_shuffle_epi8(src_reg_hi, shuffle_reg_right);
1017
1018
0
            out_reg_lo = _mm256_shuffle_epi8(
1019
0
                _mm256_permute4x64_epi64(src_reg_lo, 0xD8), shuffle_output_reg);
1020
0
            out_reg_hi = _mm256_shuffle_epi8(
1021
0
                _mm256_permute4x64_epi64(src_reg_hi, 0xD8), shuffle_output_reg);
1022
0
            do {
1023
0
              _mm256_storeu_si256((__m256i *)dst, out_reg_lo);
1024
0
              _mm256_storeu_si256((__m256i *)(dst + 16), out_reg_hi);
1025
0
              dst += dst_stride;
1026
0
              ++y0;
1027
0
              --b_h;
1028
0
            } while ((y0 <= ref_y0 || y0 >= ref_y1) && b_h);
1029
0
            ref_row += src_stride;
1030
0
          } while (b_h);
1031
0
        }
1032
0
      } else {
1033
0
        assert(right < 14);
1034
0
        const uint8_t *refinemv_pad_right = refinemv_pad_right_bw_31[right];
1035
0
        const uint8_t *refine_mv_pad_left =
1036
0
            refinemv_pad_left_bw_greater_than_15[left - 16];
1037
0
        const __m128i shuffle_right =
1038
0
            _mm_loadu_si128((__m128i *)refinemv_pad_right);
1039
0
        const __m256i shuffle_reg_right = _mm256_inserti128_si256(
1040
0
            _mm256_castsi128_si256(shuffle_right), shuffle_right, 1);
1041
0
        const __m128i shuffle_left =
1042
0
            _mm_loadu_si128((__m128i *)refine_mv_pad_left);
1043
0
        const __m256i shuffle_reg_left = _mm256_inserti128_si256(
1044
0
            _mm256_castsi128_si256(shuffle_left), shuffle_left, 1);
1045
0
        __m256i out_reg_lo, out_reg_hi;
1046
0
        do {
1047
0
          out_reg_lo = _mm256_set1_epi16(ref_row[x0 + left]);
1048
0
          const __m256i src_hi =
1049
0
              _mm256_loadu_si256((__m256i *)(ref_row + x0 + 16));
1050
1051
0
          const __m256i src_02 = _mm256_shuffle_epi8(src_hi, shuffle_input_reg);
1052
0
          __m256i src_reg_hi = _mm256_permute4x64_epi64(src_02, 0xD8);
1053
0
          src_reg_hi = _mm256_shuffle_epi8(src_reg_hi, shuffle_reg_left);
1054
0
          src_reg_hi = _mm256_shuffle_epi8(src_reg_hi, shuffle_reg_right);
1055
1056
0
          out_reg_hi = _mm256_shuffle_epi8(
1057
0
              _mm256_permute4x64_epi64(src_reg_hi, 0xD8), shuffle_output_reg);
1058
0
          do {
1059
0
            _mm256_storeu_si256((__m256i *)dst, out_reg_lo);
1060
0
            _mm256_storeu_si256((__m256i *)(dst + 16), out_reg_hi);
1061
0
            dst += dst_stride;
1062
0
            ++y0;
1063
0
            --b_h;
1064
0
          } while ((y0 <= ref_y0 || y0 >= ref_y1) && b_h);
1065
0
          ref_row += src_stride;
1066
0
        } while (b_h);
1067
0
      }
1068
0
    } else if (left == 0 && right == 0) {
1069
0
      do {
1070
0
        const __m256i src_lo = _mm256_loadu_si256((__m256i *)(ref_row + x0));
1071
0
        const __m256i src_hi =
1072
0
            _mm256_loadu_si256((__m256i *)(ref_row + x0 + 16));
1073
0
        _mm256_storeu_si256((__m256i *)dst, src_lo);
1074
0
        _mm256_storeu_si256((__m256i *)(dst + 16), src_hi);
1075
0
        dst += dst_stride;
1076
0
        ++y0;
1077
0
        if (y0 > ref_y0 && y0 < ref_y1) ref_row += src_stride;
1078
0
      } while (--b_h);
1079
0
    } else {
1080
0
      const uint16_t *cur_ref_row =
1081
0
          (left >= (b_w - 1)) ? (ref_row + ref_x0) : (ref_row + ref_x1 - 1);
1082
0
      do {
1083
0
        const __m256i src_0 = _mm256_set1_epi16(cur_ref_row[0]);
1084
0
        _mm256_storeu_si256((__m256i *)dst, src_0);
1085
0
        _mm256_storeu_si256((__m256i *)(dst + 16), src_0);
1086
0
        dst += dst_stride;
1087
0
        ++y0;
1088
0
        if (y0 > ref_y0 && y0 < ref_y1) cur_ref_row += src_stride;
1089
0
      } while (--b_h);
1090
0
    }
1091
0
  } else {
1092
0
    if (left < (b_w - 1) && right < (b_w - 1) && (left != 0 || right != 0)) {
1093
0
      const __m128i shuffle_left =
1094
0
          _mm_loadu_si128((__m128i *)refinemv_pad_left[left]);
1095
0
      const __m256i shuffle_reg_left = _mm256_inserti128_si256(
1096
0
          _mm256_castsi128_si256(shuffle_left), shuffle_left, 1);
1097
1098
0
      const uint8_t *refinemv_pad_right = b_w == 15
1099
0
                                              ? refinemv_pad_right_bw_15[right]
1100
0
                                              : refinemv_pad_right_bw_11[right];
1101
1102
0
      const __m128i shuffle_right =
1103
0
          _mm_loadu_si128((__m128i *)refinemv_pad_right);
1104
0
      const __m256i shuffle_reg_right = _mm256_inserti128_si256(
1105
0
          _mm256_castsi128_si256(shuffle_right), shuffle_right, 1);
1106
1107
0
      const __m256i shuffle_input_reg =
1108
0
          _mm256_load_si256((__m256i *)pad_mc_border_arrange_bytes);
1109
0
      const __m256i shuffle_output_reg =
1110
0
          _mm256_load_si256((__m256i *)pad_mc_border_shuffle_pattern);
1111
0
      __m256i out_reg;
1112
0
      do {
1113
0
        const __m256i src_0 = _mm256_loadu_si256((__m256i *)(ref_row + x0));
1114
1115
0
        const __m256i src_01 = _mm256_shuffle_epi8(src_0, shuffle_input_reg);
1116
0
        __m256i src_reg = _mm256_permute4x64_epi64(src_01, 0xD8);
1117
1118
0
        src_reg = _mm256_shuffle_epi8(src_reg, shuffle_reg_left);
1119
0
        src_reg = _mm256_shuffle_epi8(src_reg, shuffle_reg_right);
1120
1121
0
        out_reg = _mm256_shuffle_epi8(_mm256_permute4x64_epi64(src_reg, 0xD8),
1122
0
                                      shuffle_output_reg);
1123
0
        do {
1124
0
          _mm256_storeu_si256((__m256i *)dst, out_reg);
1125
0
          dst += dst_stride;
1126
0
          ++y0;
1127
0
          --b_h;
1128
0
        } while ((y0 <= ref_y0 || y0 >= ref_y1) && b_h);
1129
0
        ref_row += src_stride;
1130
0
      } while (b_h);
1131
0
    } else if (left == 0 && right == 0) {
1132
0
      do {
1133
0
        const __m256i src_0 = _mm256_loadu_si256((__m256i *)(ref_row + x0));
1134
0
        _mm256_storeu_si256((__m256i *)dst, src_0);
1135
0
        dst += dst_stride;
1136
0
        ++y0;
1137
0
        if (y0 > ref_y0 && y0 < ref_y1) ref_row += src_stride;
1138
0
      } while (--b_h);
1139
0
    } else {
1140
0
      const uint16_t *cur_ref_row =
1141
0
          (left >= (b_w - 1)) ? (ref_row + ref_x0) : (ref_row + ref_x1 - 1);
1142
0
      do {
1143
0
        const __m256i src_0 = _mm256_set1_epi16(cur_ref_row[0]);
1144
0
        _mm256_storeu_si256((__m256i *)dst, src_0);
1145
0
        dst += dst_stride;
1146
0
        ++y0;
1147
0
        if (y0 > ref_y0 && y0 < ref_y1) cur_ref_row += src_stride;
1148
0
      } while (--b_h);
1149
0
    }
1150
0
  }
1151
0
}