Coverage Report

Created: 2026-09-07 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/aom/aom_dsp/x86/sse_sse4.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2018, 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 <assert.h>
13
#include <smmintrin.h>
14
15
#include "config/aom_config.h"
16
#include "config/aom_dsp_rtcd.h"
17
18
#include "aom_ports/mem.h"
19
#include "aom/aom_integer.h"
20
#include "aom_dsp/x86/synonyms.h"
21
22
0
static inline int64_t summary_all_sse4(const __m128i *sum_all) {
23
0
  int64_t sum;
24
0
  const __m128i sum0 = _mm_cvtepu32_epi64(*sum_all);
25
0
  const __m128i sum1 = _mm_cvtepu32_epi64(_mm_srli_si128(*sum_all, 8));
26
0
  const __m128i sum_2x64 = _mm_add_epi64(sum0, sum1);
27
0
  const __m128i sum_1x64 = _mm_add_epi64(sum_2x64, _mm_srli_si128(sum_2x64, 8));
28
0
  xx_storel_64(&sum, sum_1x64);
29
0
  return sum;
30
0
}
31
32
#if CONFIG_AV1_HIGHBITDEPTH
33
0
static inline void summary_32_sse4(const __m128i *sum32, __m128i *sum64) {
34
0
  const __m128i sum0 = _mm_cvtepu32_epi64(*sum32);
35
0
  const __m128i sum1 = _mm_cvtepu32_epi64(_mm_srli_si128(*sum32, 8));
36
0
  *sum64 = _mm_add_epi64(sum0, *sum64);
37
0
  *sum64 = _mm_add_epi64(sum1, *sum64);
38
0
}
39
#endif
40
41
static inline void sse_w16_sse4_1(__m128i *sum, const uint8_t *a,
42
0
                                  const uint8_t *b) {
43
0
  const __m128i v_a0 = xx_loadu_128(a);
44
0
  const __m128i v_b0 = xx_loadu_128(b);
45
0
  const __m128i v_a00_w = _mm_cvtepu8_epi16(v_a0);
46
0
  const __m128i v_a01_w = _mm_cvtepu8_epi16(_mm_srli_si128(v_a0, 8));
47
0
  const __m128i v_b00_w = _mm_cvtepu8_epi16(v_b0);
48
0
  const __m128i v_b01_w = _mm_cvtepu8_epi16(_mm_srli_si128(v_b0, 8));
49
0
  const __m128i v_d00_w = _mm_sub_epi16(v_a00_w, v_b00_w);
50
0
  const __m128i v_d01_w = _mm_sub_epi16(v_a01_w, v_b01_w);
51
0
  *sum = _mm_add_epi32(*sum, _mm_madd_epi16(v_d00_w, v_d00_w));
52
0
  *sum = _mm_add_epi32(*sum, _mm_madd_epi16(v_d01_w, v_d01_w));
53
0
}
54
55
static inline void sse4x2_sse4_1(const uint8_t *a, int a_stride,
56
0
                                 const uint8_t *b, int b_stride, __m128i *sum) {
57
0
  const __m128i v_a0 = xx_loadl_32(a);
58
0
  const __m128i v_a1 = xx_loadl_32(a + a_stride);
59
0
  const __m128i v_b0 = xx_loadl_32(b);
60
0
  const __m128i v_b1 = xx_loadl_32(b + b_stride);
61
0
  const __m128i v_a_w = _mm_cvtepu8_epi16(_mm_unpacklo_epi32(v_a0, v_a1));
62
0
  const __m128i v_b_w = _mm_cvtepu8_epi16(_mm_unpacklo_epi32(v_b0, v_b1));
63
0
  const __m128i v_d_w = _mm_sub_epi16(v_a_w, v_b_w);
64
0
  *sum = _mm_add_epi32(*sum, _mm_madd_epi16(v_d_w, v_d_w));
65
0
}
66
67
static inline void sse8_sse4_1(const uint8_t *a, const uint8_t *b,
68
0
                               __m128i *sum) {
69
0
  const __m128i v_a0 = xx_loadl_64(a);
70
0
  const __m128i v_b0 = xx_loadl_64(b);
71
0
  const __m128i v_a_w = _mm_cvtepu8_epi16(v_a0);
72
0
  const __m128i v_b_w = _mm_cvtepu8_epi16(v_b0);
73
0
  const __m128i v_d_w = _mm_sub_epi16(v_a_w, v_b_w);
74
0
  *sum = _mm_add_epi32(*sum, _mm_madd_epi16(v_d_w, v_d_w));
75
0
}
76
77
int64_t aom_sse_sse4_1(const uint8_t *a, int a_stride, const uint8_t *b,
78
0
                       int b_stride, int width, int height) {
79
0
  int y = 0;
80
0
  int64_t sse = 0;
81
0
  __m128i sum = _mm_setzero_si128();
82
0
  switch (width) {
83
0
    case 4:
84
0
      do {
85
0
        sse4x2_sse4_1(a, a_stride, b, b_stride, &sum);
86
0
        a += a_stride << 1;
87
0
        b += b_stride << 1;
88
0
        y += 2;
89
0
      } while (y < height);
90
0
      sse = summary_all_sse4(&sum);
91
0
      break;
92
0
    case 8:
93
0
      do {
94
0
        sse8_sse4_1(a, b, &sum);
95
0
        a += a_stride;
96
0
        b += b_stride;
97
0
        y += 1;
98
0
      } while (y < height);
99
0
      sse = summary_all_sse4(&sum);
100
0
      break;
101
0
    case 16:
102
0
      do {
103
0
        sse_w16_sse4_1(&sum, a, b);
104
0
        a += a_stride;
105
0
        b += b_stride;
106
0
        y += 1;
107
0
      } while (y < height);
108
0
      sse = summary_all_sse4(&sum);
109
0
      break;
110
0
    case 32:
111
0
      do {
112
0
        sse_w16_sse4_1(&sum, a, b);
113
0
        sse_w16_sse4_1(&sum, a + 16, b + 16);
114
0
        a += a_stride;
115
0
        b += b_stride;
116
0
        y += 1;
117
0
      } while (y < height);
118
0
      sse = summary_all_sse4(&sum);
119
0
      break;
120
0
    case 64:
121
0
      do {
122
0
        sse_w16_sse4_1(&sum, a, b);
123
0
        sse_w16_sse4_1(&sum, a + 16 * 1, b + 16 * 1);
124
0
        sse_w16_sse4_1(&sum, a + 16 * 2, b + 16 * 2);
125
0
        sse_w16_sse4_1(&sum, a + 16 * 3, b + 16 * 3);
126
0
        a += a_stride;
127
0
        b += b_stride;
128
0
        y += 1;
129
0
      } while (y < height);
130
0
      sse = summary_all_sse4(&sum);
131
0
      break;
132
0
    case 128:
133
0
      do {
134
0
        sse_w16_sse4_1(&sum, a, b);
135
0
        sse_w16_sse4_1(&sum, a + 16 * 1, b + 16 * 1);
136
0
        sse_w16_sse4_1(&sum, a + 16 * 2, b + 16 * 2);
137
0
        sse_w16_sse4_1(&sum, a + 16 * 3, b + 16 * 3);
138
0
        sse_w16_sse4_1(&sum, a + 16 * 4, b + 16 * 4);
139
0
        sse_w16_sse4_1(&sum, a + 16 * 5, b + 16 * 5);
140
0
        sse_w16_sse4_1(&sum, a + 16 * 6, b + 16 * 6);
141
0
        sse_w16_sse4_1(&sum, a + 16 * 7, b + 16 * 7);
142
0
        a += a_stride;
143
0
        b += b_stride;
144
0
        y += 1;
145
0
      } while (y < height);
146
0
      sse = summary_all_sse4(&sum);
147
0
      break;
148
0
    default:
149
0
      if (width & 0x07) {
150
0
        do {
151
0
          int i = 0;
152
0
          do {
153
0
            sse8_sse4_1(a + i, b + i, &sum);
154
0
            sse8_sse4_1(a + i + a_stride, b + i + b_stride, &sum);
155
0
            i += 8;
156
0
          } while (i + 4 < width);
157
0
          sse4x2_sse4_1(a + i, a_stride, b + i, b_stride, &sum);
158
0
          a += (a_stride << 1);
159
0
          b += (b_stride << 1);
160
0
          y += 2;
161
0
        } while (y < height);
162
0
      } else {
163
0
        do {
164
0
          int i = 0;
165
0
          do {
166
0
            sse8_sse4_1(a + i, b + i, &sum);
167
0
            i += 8;
168
0
          } while (i < width);
169
0
          a += a_stride;
170
0
          b += b_stride;
171
0
          y += 1;
172
0
        } while (y < height);
173
0
      }
174
0
      sse = summary_all_sse4(&sum);
175
0
      break;
176
0
  }
177
178
0
  return sse;
179
0
}
180
181
#if CONFIG_AV1_HIGHBITDEPTH
182
static inline void highbd_sse_w4x2_sse4_1(__m128i *sum, const uint16_t *a,
183
                                          int a_stride, const uint16_t *b,
184
0
                                          int b_stride) {
185
0
  const __m128i v_a0 = xx_loadl_64(a);
186
0
  const __m128i v_a1 = xx_loadl_64(a + a_stride);
187
0
  const __m128i v_b0 = xx_loadl_64(b);
188
0
  const __m128i v_b1 = xx_loadl_64(b + b_stride);
189
0
  const __m128i v_a_w = _mm_unpacklo_epi64(v_a0, v_a1);
190
0
  const __m128i v_b_w = _mm_unpacklo_epi64(v_b0, v_b1);
191
0
  const __m128i v_d_w = _mm_sub_epi16(v_a_w, v_b_w);
192
0
  *sum = _mm_add_epi32(*sum, _mm_madd_epi16(v_d_w, v_d_w));
193
0
}
194
195
static inline void highbd_sse_w8_sse4_1(__m128i *sum, const uint16_t *a,
196
0
                                        const uint16_t *b) {
197
0
  const __m128i v_a_w = xx_loadu_128(a);
198
0
  const __m128i v_b_w = xx_loadu_128(b);
199
0
  const __m128i v_d_w = _mm_sub_epi16(v_a_w, v_b_w);
200
0
  *sum = _mm_add_epi32(*sum, _mm_madd_epi16(v_d_w, v_d_w));
201
0
}
202
203
int64_t aom_highbd_sse_sse4_1(const uint8_t *a8, int a_stride,
204
                              const uint8_t *b8, int b_stride, int width,
205
0
                              int height) {
206
0
  int32_t y = 0;
207
0
  int64_t sse = 0;
208
0
  uint16_t *a = CONVERT_TO_SHORTPTR(a8);
209
0
  uint16_t *b = CONVERT_TO_SHORTPTR(b8);
210
0
  __m128i sum = _mm_setzero_si128();
211
0
  switch (width) {
212
0
    case 4:
213
0
      do {
214
0
        highbd_sse_w4x2_sse4_1(&sum, a, a_stride, b, b_stride);
215
0
        a += a_stride << 1;
216
0
        b += b_stride << 1;
217
0
        y += 2;
218
0
      } while (y < height);
219
0
      sse = summary_all_sse4(&sum);
220
0
      break;
221
0
    case 8:
222
0
      do {
223
0
        highbd_sse_w8_sse4_1(&sum, a, b);
224
0
        a += a_stride;
225
0
        b += b_stride;
226
0
        y += 1;
227
0
      } while (y < height);
228
0
      sse = summary_all_sse4(&sum);
229
0
      break;
230
0
    case 16:
231
0
      do {
232
0
        int l = 0;
233
0
        __m128i sum32 = _mm_setzero_si128();
234
0
        do {
235
0
          highbd_sse_w8_sse4_1(&sum32, a, b);
236
0
          highbd_sse_w8_sse4_1(&sum32, a + 8, b + 8);
237
0
          a += a_stride;
238
0
          b += b_stride;
239
0
          l += 1;
240
0
        } while (l < 64 && l < (height - y));
241
0
        summary_32_sse4(&sum32, &sum);
242
0
        y += 64;
243
0
      } while (y < height);
244
0
      xx_storel_64(&sse, _mm_add_epi64(sum, _mm_srli_si128(sum, 8)));
245
0
      break;
246
0
    case 32:
247
0
      do {
248
0
        int l = 0;
249
0
        __m128i sum32 = _mm_setzero_si128();
250
0
        do {
251
0
          highbd_sse_w8_sse4_1(&sum32, a, b);
252
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 1, b + 8 * 1);
253
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 2, b + 8 * 2);
254
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 3, b + 8 * 3);
255
0
          a += a_stride;
256
0
          b += b_stride;
257
0
          l += 1;
258
0
        } while (l < 32 && l < (height - y));
259
0
        summary_32_sse4(&sum32, &sum);
260
0
        y += 32;
261
0
      } while (y < height);
262
0
      xx_storel_64(&sse, _mm_add_epi64(sum, _mm_srli_si128(sum, 8)));
263
0
      break;
264
0
    case 64:
265
0
      do {
266
0
        int l = 0;
267
0
        __m128i sum32 = _mm_setzero_si128();
268
0
        do {
269
0
          highbd_sse_w8_sse4_1(&sum32, a, b);
270
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 1, b + 8 * 1);
271
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 2, b + 8 * 2);
272
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 3, b + 8 * 3);
273
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 4, b + 8 * 4);
274
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 5, b + 8 * 5);
275
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 6, b + 8 * 6);
276
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 7, b + 8 * 7);
277
0
          a += a_stride;
278
0
          b += b_stride;
279
0
          l += 1;
280
0
        } while (l < 16 && l < (height - y));
281
0
        summary_32_sse4(&sum32, &sum);
282
0
        y += 16;
283
0
      } while (y < height);
284
0
      xx_storel_64(&sse, _mm_add_epi64(sum, _mm_srli_si128(sum, 8)));
285
0
      break;
286
0
    case 128:
287
0
      do {
288
0
        int l = 0;
289
0
        __m128i sum32 = _mm_setzero_si128();
290
0
        do {
291
0
          highbd_sse_w8_sse4_1(&sum32, a, b);
292
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 1, b + 8 * 1);
293
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 2, b + 8 * 2);
294
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 3, b + 8 * 3);
295
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 4, b + 8 * 4);
296
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 5, b + 8 * 5);
297
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 6, b + 8 * 6);
298
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 7, b + 8 * 7);
299
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 8, b + 8 * 8);
300
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 9, b + 8 * 9);
301
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 10, b + 8 * 10);
302
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 11, b + 8 * 11);
303
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 12, b + 8 * 12);
304
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 13, b + 8 * 13);
305
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 14, b + 8 * 14);
306
0
          highbd_sse_w8_sse4_1(&sum32, a + 8 * 15, b + 8 * 15);
307
0
          a += a_stride;
308
0
          b += b_stride;
309
0
          l += 1;
310
0
        } while (l < 8 && l < (height - y));
311
0
        summary_32_sse4(&sum32, &sum);
312
0
        y += 8;
313
0
      } while (y < height);
314
0
      xx_storel_64(&sse, _mm_add_epi64(sum, _mm_srli_si128(sum, 8)));
315
0
      break;
316
0
    default:
317
0
      if (width & 0x7) {
318
0
        do {
319
0
          __m128i sum32 = _mm_setzero_si128();
320
0
          int i = 0;
321
0
          do {
322
0
            highbd_sse_w8_sse4_1(&sum32, a + i, b + i);
323
0
            highbd_sse_w8_sse4_1(&sum32, a + i + a_stride, b + i + b_stride);
324
0
            i += 8;
325
0
          } while (i + 4 < width);
326
0
          highbd_sse_w4x2_sse4_1(&sum32, a + i, a_stride, b + i, b_stride);
327
0
          a += (a_stride << 1);
328
0
          b += (b_stride << 1);
329
0
          y += 2;
330
0
          summary_32_sse4(&sum32, &sum);
331
0
        } while (y < height);
332
0
      } else {
333
0
        do {
334
0
          int l = 0;
335
0
          __m128i sum32 = _mm_setzero_si128();
336
0
          do {
337
0
            int i = 0;
338
0
            do {
339
0
              highbd_sse_w8_sse4_1(&sum32, a + i, b + i);
340
0
              i += 8;
341
0
            } while (i < width);
342
0
            a += a_stride;
343
0
            b += b_stride;
344
0
            l += 1;
345
0
          } while (l < 8 && l < (height - y));
346
0
          summary_32_sse4(&sum32, &sum);
347
0
          y += 8;
348
0
        } while (y < height);
349
0
      }
350
0
      xx_storel_64(&sse, _mm_add_epi64(sum, _mm_srli_si128(sum, 8)));
351
0
      break;
352
0
  }
353
0
  return sse;
354
0
}
355
#endif  // CONFIG_AV1_HIGHBITDEPTH