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/highbd_subtract_sse2.c
Line
Count
Source
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 <assert.h>
13
#include <emmintrin.h>
14
#include <stddef.h>
15
16
#include "config/aom_config.h"
17
#include "config/aom_dsp_rtcd.h"
18
19
typedef void (*SubtractWxHFuncType)(int16_t *diff, ptrdiff_t diff_stride,
20
                                    const uint16_t *src, ptrdiff_t src_stride,
21
                                    const uint16_t *pred,
22
                                    ptrdiff_t pred_stride);
23
24
static void subtract_4x4(int16_t *diff, ptrdiff_t diff_stride,
25
                         const uint16_t *src, ptrdiff_t src_stride,
26
0
                         const uint16_t *pred, ptrdiff_t pred_stride) {
27
0
  __m128i u0, u1, u2, u3;
28
0
  __m128i v0, v1, v2, v3;
29
0
  __m128i x0, x1, x2, x3;
30
0
  int64_t *store_diff = (int64_t *)(diff + 0 * diff_stride);
31
32
0
  u0 = _mm_loadl_epi64((__m128i const *)(src + 0 * src_stride));
33
0
  u1 = _mm_loadl_epi64((__m128i const *)(src + 1 * src_stride));
34
0
  u2 = _mm_loadl_epi64((__m128i const *)(src + 2 * src_stride));
35
0
  u3 = _mm_loadl_epi64((__m128i const *)(src + 3 * src_stride));
36
37
0
  v0 = _mm_loadl_epi64((__m128i const *)(pred + 0 * pred_stride));
38
0
  v1 = _mm_loadl_epi64((__m128i const *)(pred + 1 * pred_stride));
39
0
  v2 = _mm_loadl_epi64((__m128i const *)(pred + 2 * pred_stride));
40
0
  v3 = _mm_loadl_epi64((__m128i const *)(pred + 3 * pred_stride));
41
42
0
  x0 = _mm_sub_epi16(u0, v0);
43
0
  x1 = _mm_sub_epi16(u1, v1);
44
0
  x2 = _mm_sub_epi16(u2, v2);
45
0
  x3 = _mm_sub_epi16(u3, v3);
46
47
0
  _mm_storel_epi64((__m128i *)store_diff, x0);
48
0
  store_diff = (int64_t *)(diff + 1 * diff_stride);
49
0
  _mm_storel_epi64((__m128i *)store_diff, x1);
50
0
  store_diff = (int64_t *)(diff + 2 * diff_stride);
51
0
  _mm_storel_epi64((__m128i *)store_diff, x2);
52
0
  store_diff = (int64_t *)(diff + 3 * diff_stride);
53
0
  _mm_storel_epi64((__m128i *)store_diff, x3);
54
0
}
55
56
static void subtract_4x8(int16_t *diff, ptrdiff_t diff_stride,
57
                         const uint16_t *src, ptrdiff_t src_stride,
58
0
                         const uint16_t *pred, ptrdiff_t pred_stride) {
59
0
  __m128i u0, u1, u2, u3, u4, u5, u6, u7;
60
0
  __m128i v0, v1, v2, v3, v4, v5, v6, v7;
61
0
  __m128i x0, x1, x2, x3, x4, x5, x6, x7;
62
0
  int64_t *store_diff = (int64_t *)(diff + 0 * diff_stride);
63
64
0
  u0 = _mm_loadl_epi64((__m128i const *)(src + 0 * src_stride));
65
0
  u1 = _mm_loadl_epi64((__m128i const *)(src + 1 * src_stride));
66
0
  u2 = _mm_loadl_epi64((__m128i const *)(src + 2 * src_stride));
67
0
  u3 = _mm_loadl_epi64((__m128i const *)(src + 3 * src_stride));
68
0
  u4 = _mm_loadl_epi64((__m128i const *)(src + 4 * src_stride));
69
0
  u5 = _mm_loadl_epi64((__m128i const *)(src + 5 * src_stride));
70
0
  u6 = _mm_loadl_epi64((__m128i const *)(src + 6 * src_stride));
71
0
  u7 = _mm_loadl_epi64((__m128i const *)(src + 7 * src_stride));
72
73
0
  v0 = _mm_loadl_epi64((__m128i const *)(pred + 0 * pred_stride));
74
0
  v1 = _mm_loadl_epi64((__m128i const *)(pred + 1 * pred_stride));
75
0
  v2 = _mm_loadl_epi64((__m128i const *)(pred + 2 * pred_stride));
76
0
  v3 = _mm_loadl_epi64((__m128i const *)(pred + 3 * pred_stride));
77
0
  v4 = _mm_loadl_epi64((__m128i const *)(pred + 4 * pred_stride));
78
0
  v5 = _mm_loadl_epi64((__m128i const *)(pred + 5 * pred_stride));
79
0
  v6 = _mm_loadl_epi64((__m128i const *)(pred + 6 * pred_stride));
80
0
  v7 = _mm_loadl_epi64((__m128i const *)(pred + 7 * pred_stride));
81
82
0
  x0 = _mm_sub_epi16(u0, v0);
83
0
  x1 = _mm_sub_epi16(u1, v1);
84
0
  x2 = _mm_sub_epi16(u2, v2);
85
0
  x3 = _mm_sub_epi16(u3, v3);
86
0
  x4 = _mm_sub_epi16(u4, v4);
87
0
  x5 = _mm_sub_epi16(u5, v5);
88
0
  x6 = _mm_sub_epi16(u6, v6);
89
0
  x7 = _mm_sub_epi16(u7, v7);
90
91
0
  _mm_storel_epi64((__m128i *)store_diff, x0);
92
0
  store_diff = (int64_t *)(diff + 1 * diff_stride);
93
0
  _mm_storel_epi64((__m128i *)store_diff, x1);
94
0
  store_diff = (int64_t *)(diff + 2 * diff_stride);
95
0
  _mm_storel_epi64((__m128i *)store_diff, x2);
96
0
  store_diff = (int64_t *)(diff + 3 * diff_stride);
97
0
  _mm_storel_epi64((__m128i *)store_diff, x3);
98
0
  store_diff = (int64_t *)(diff + 4 * diff_stride);
99
0
  _mm_storel_epi64((__m128i *)store_diff, x4);
100
0
  store_diff = (int64_t *)(diff + 5 * diff_stride);
101
0
  _mm_storel_epi64((__m128i *)store_diff, x5);
102
0
  store_diff = (int64_t *)(diff + 6 * diff_stride);
103
0
  _mm_storel_epi64((__m128i *)store_diff, x6);
104
0
  store_diff = (int64_t *)(diff + 7 * diff_stride);
105
0
  _mm_storel_epi64((__m128i *)store_diff, x7);
106
0
}
107
108
static void subtract_8x4(int16_t *diff, ptrdiff_t diff_stride,
109
                         const uint16_t *src, ptrdiff_t src_stride,
110
0
                         const uint16_t *pred, ptrdiff_t pred_stride) {
111
0
  __m128i u0, u1, u2, u3;
112
0
  __m128i v0, v1, v2, v3;
113
0
  __m128i x0, x1, x2, x3;
114
115
0
  u0 = _mm_loadu_si128((__m128i const *)(src + 0 * src_stride));
116
0
  u1 = _mm_loadu_si128((__m128i const *)(src + 1 * src_stride));
117
0
  u2 = _mm_loadu_si128((__m128i const *)(src + 2 * src_stride));
118
0
  u3 = _mm_loadu_si128((__m128i const *)(src + 3 * src_stride));
119
120
0
  v0 = _mm_loadu_si128((__m128i const *)(pred + 0 * pred_stride));
121
0
  v1 = _mm_loadu_si128((__m128i const *)(pred + 1 * pred_stride));
122
0
  v2 = _mm_loadu_si128((__m128i const *)(pred + 2 * pred_stride));
123
0
  v3 = _mm_loadu_si128((__m128i const *)(pred + 3 * pred_stride));
124
125
0
  x0 = _mm_sub_epi16(u0, v0);
126
0
  x1 = _mm_sub_epi16(u1, v1);
127
0
  x2 = _mm_sub_epi16(u2, v2);
128
0
  x3 = _mm_sub_epi16(u3, v3);
129
130
0
  _mm_storeu_si128((__m128i *)(diff + 0 * diff_stride), x0);
131
0
  _mm_storeu_si128((__m128i *)(diff + 1 * diff_stride), x1);
132
0
  _mm_storeu_si128((__m128i *)(diff + 2 * diff_stride), x2);
133
0
  _mm_storeu_si128((__m128i *)(diff + 3 * diff_stride), x3);
134
0
}
135
136
static void subtract_8x8(int16_t *diff, ptrdiff_t diff_stride,
137
                         const uint16_t *src, ptrdiff_t src_stride,
138
0
                         const uint16_t *pred, ptrdiff_t pred_stride) {
139
0
  __m128i u0, u1, u2, u3, u4, u5, u6, u7;
140
0
  __m128i v0, v1, v2, v3, v4, v5, v6, v7;
141
0
  __m128i x0, x1, x2, x3, x4, x5, x6, x7;
142
143
0
  u0 = _mm_loadu_si128((__m128i const *)(src + 0 * src_stride));
144
0
  u1 = _mm_loadu_si128((__m128i const *)(src + 1 * src_stride));
145
0
  u2 = _mm_loadu_si128((__m128i const *)(src + 2 * src_stride));
146
0
  u3 = _mm_loadu_si128((__m128i const *)(src + 3 * src_stride));
147
0
  u4 = _mm_loadu_si128((__m128i const *)(src + 4 * src_stride));
148
0
  u5 = _mm_loadu_si128((__m128i const *)(src + 5 * src_stride));
149
0
  u6 = _mm_loadu_si128((__m128i const *)(src + 6 * src_stride));
150
0
  u7 = _mm_loadu_si128((__m128i const *)(src + 7 * src_stride));
151
152
0
  v0 = _mm_loadu_si128((__m128i const *)(pred + 0 * pred_stride));
153
0
  v1 = _mm_loadu_si128((__m128i const *)(pred + 1 * pred_stride));
154
0
  v2 = _mm_loadu_si128((__m128i const *)(pred + 2 * pred_stride));
155
0
  v3 = _mm_loadu_si128((__m128i const *)(pred + 3 * pred_stride));
156
0
  v4 = _mm_loadu_si128((__m128i const *)(pred + 4 * pred_stride));
157
0
  v5 = _mm_loadu_si128((__m128i const *)(pred + 5 * pred_stride));
158
0
  v6 = _mm_loadu_si128((__m128i const *)(pred + 6 * pred_stride));
159
0
  v7 = _mm_loadu_si128((__m128i const *)(pred + 7 * pred_stride));
160
161
0
  x0 = _mm_sub_epi16(u0, v0);
162
0
  x1 = _mm_sub_epi16(u1, v1);
163
0
  x2 = _mm_sub_epi16(u2, v2);
164
0
  x3 = _mm_sub_epi16(u3, v3);
165
0
  x4 = _mm_sub_epi16(u4, v4);
166
0
  x5 = _mm_sub_epi16(u5, v5);
167
0
  x6 = _mm_sub_epi16(u6, v6);
168
0
  x7 = _mm_sub_epi16(u7, v7);
169
170
0
  _mm_storeu_si128((__m128i *)(diff + 0 * diff_stride), x0);
171
0
  _mm_storeu_si128((__m128i *)(diff + 1 * diff_stride), x1);
172
0
  _mm_storeu_si128((__m128i *)(diff + 2 * diff_stride), x2);
173
0
  _mm_storeu_si128((__m128i *)(diff + 3 * diff_stride), x3);
174
0
  _mm_storeu_si128((__m128i *)(diff + 4 * diff_stride), x4);
175
0
  _mm_storeu_si128((__m128i *)(diff + 5 * diff_stride), x5);
176
0
  _mm_storeu_si128((__m128i *)(diff + 6 * diff_stride), x6);
177
0
  _mm_storeu_si128((__m128i *)(diff + 7 * diff_stride), x7);
178
0
}
179
180
#define STACK_V(h, fun)                                                        \
181
0
  do {                                                                         \
182
0
    fun(diff, diff_stride, src, src_stride, pred, pred_stride);                \
183
0
    fun(diff + diff_stride * h, diff_stride, src + src_stride * h, src_stride, \
184
0
        pred + pred_stride * h, pred_stride);                                  \
185
0
  } while (0)
186
187
#define STACK_H(w, fun)                                                     \
188
0
  do {                                                                      \
189
0
    fun(diff, diff_stride, src, src_stride, pred, pred_stride);             \
190
0
    fun(diff + w, diff_stride, src + w, src_stride, pred + w, pred_stride); \
191
0
  } while (0)
192
193
#define SUBTRACT_FUN(size)                                               \
194
  static void subtract_##size(int16_t *diff, ptrdiff_t diff_stride,      \
195
                              const uint16_t *src, ptrdiff_t src_stride, \
196
                              const uint16_t *pred, ptrdiff_t pred_stride)
197
198
0
SUBTRACT_FUN(8x16) { STACK_V(8, subtract_8x8); }
199
0
SUBTRACT_FUN(16x8) { STACK_H(8, subtract_8x8); }
200
0
SUBTRACT_FUN(16x16) { STACK_V(8, subtract_16x8); }
201
0
SUBTRACT_FUN(16x32) { STACK_V(16, subtract_16x16); }
202
0
SUBTRACT_FUN(32x16) { STACK_H(16, subtract_16x16); }
203
0
SUBTRACT_FUN(32x32) { STACK_V(16, subtract_32x16); }
204
0
SUBTRACT_FUN(32x64) { STACK_V(32, subtract_32x32); }
205
0
SUBTRACT_FUN(64x32) { STACK_H(32, subtract_32x32); }
206
0
SUBTRACT_FUN(64x64) { STACK_V(32, subtract_64x32); }
207
0
SUBTRACT_FUN(64x128) { STACK_V(64, subtract_64x64); }
208
0
SUBTRACT_FUN(128x64) { STACK_H(64, subtract_64x64); }
209
0
SUBTRACT_FUN(128x128) { STACK_V(64, subtract_128x64); }
210
0
SUBTRACT_FUN(4x16) { STACK_V(8, subtract_4x8); }
211
0
SUBTRACT_FUN(16x4) { STACK_H(8, subtract_8x4); }
212
0
SUBTRACT_FUN(8x32) { STACK_V(16, subtract_8x16); }
213
0
SUBTRACT_FUN(32x8) { STACK_H(16, subtract_16x8); }
214
0
SUBTRACT_FUN(16x64) { STACK_V(32, subtract_16x32); }
215
0
SUBTRACT_FUN(64x16) { STACK_H(32, subtract_32x16); }
216
217
0
static SubtractWxHFuncType getSubtractFunc(int rows, int cols) {
218
0
  if (rows == 4) {
219
0
    if (cols == 4) return subtract_4x4;
220
0
    if (cols == 8) return subtract_8x4;
221
0
    if (cols == 16) return subtract_16x4;
222
0
  }
223
0
  if (rows == 8) {
224
0
    if (cols == 4) return subtract_4x8;
225
0
    if (cols == 8) return subtract_8x8;
226
0
    if (cols == 16) return subtract_16x8;
227
0
    if (cols == 32) return subtract_32x8;
228
0
  }
229
0
  if (rows == 16) {
230
0
    if (cols == 4) return subtract_4x16;
231
0
    if (cols == 8) return subtract_8x16;
232
0
    if (cols == 16) return subtract_16x16;
233
0
    if (cols == 32) return subtract_32x16;
234
0
    if (cols == 64) return subtract_64x16;
235
0
  }
236
0
  if (rows == 32) {
237
0
    if (cols == 8) return subtract_8x32;
238
0
    if (cols == 16) return subtract_16x32;
239
0
    if (cols == 32) return subtract_32x32;
240
0
    if (cols == 64) return subtract_64x32;
241
0
  }
242
0
  if (rows == 64) {
243
0
    if (cols == 16) return subtract_16x64;
244
0
    if (cols == 32) return subtract_32x64;
245
0
    if (cols == 64) return subtract_64x64;
246
0
    if (cols == 128) return subtract_128x64;
247
0
  }
248
0
  if (rows == 128) {
249
0
    if (cols == 64) return subtract_64x128;
250
0
    if (cols == 128) return subtract_128x128;
251
0
  }
252
0
  assert(0);
253
0
  return NULL;
254
0
}
255
256
void aom_highbd_subtract_block_sse2(int rows, int cols, int16_t *diff,
257
                                    ptrdiff_t diff_stride, const uint8_t *src8,
258
                                    ptrdiff_t src_stride, const uint8_t *pred8,
259
0
                                    ptrdiff_t pred_stride) {
260
0
  uint16_t *src = CONVERT_TO_SHORTPTR(src8);
261
0
  uint16_t *pred = CONVERT_TO_SHORTPTR(pred8);
262
0
  SubtractWxHFuncType func;
263
264
0
  func = getSubtractFunc(rows, cols);
265
0
  func(diff, diff_stride, src, src_stride, pred, pred_stride);
266
0
}