blob: 8ebffb5f9a2b0fe26215a8c6f9c964ace443516a [file] [log] [blame]
Yaowu Xuc27fc142016-08-22 16:08:15 -07001/*
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Yaowu Xuc27fc142016-08-22 16:08:15 -07003 *
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07004 * 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.
Yaowu Xuc27fc142016-08-22 16:08:15 -070010 */
11
12#include <arm_neon.h>
13#include <assert.h>
14
Yaowu Xuf883b422016-08-30 14:01:10 -070015#include "./aom_config.h"
16#include "./aom_dsp_rtcd.h"
17#include "aom/aom_integer.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070018#include "aom_ports/mem.h"
19
20static INLINE int32x4_t MULTIPLY_BY_Q0(int16x4_t dsrc0, int16x4_t dsrc1,
21 int16x4_t dsrc2, int16x4_t dsrc3,
22 int16x4_t dsrc4, int16x4_t dsrc5,
23 int16x4_t dsrc6, int16x4_t dsrc7,
24 int16x8_t q0s16) {
25 int32x4_t qdst;
26 int16x4_t d0s16, d1s16;
27
28 d0s16 = vget_low_s16(q0s16);
29 d1s16 = vget_high_s16(q0s16);
30
31 qdst = vmull_lane_s16(dsrc0, d0s16, 0);
32 qdst = vmlal_lane_s16(qdst, dsrc1, d0s16, 1);
33 qdst = vmlal_lane_s16(qdst, dsrc2, d0s16, 2);
34 qdst = vmlal_lane_s16(qdst, dsrc3, d0s16, 3);
35 qdst = vmlal_lane_s16(qdst, dsrc4, d1s16, 0);
36 qdst = vmlal_lane_s16(qdst, dsrc5, d1s16, 1);
37 qdst = vmlal_lane_s16(qdst, dsrc6, d1s16, 2);
38 qdst = vmlal_lane_s16(qdst, dsrc7, d1s16, 3);
39 return qdst;
40}
41
Yaowu Xuf883b422016-08-30 14:01:10 -070042void aom_convolve8_horiz_neon(const uint8_t *src, ptrdiff_t src_stride,
Yaowu Xuc27fc142016-08-22 16:08:15 -070043 uint8_t *dst, ptrdiff_t dst_stride,
44 const int16_t *filter_x, int x_step_q4,
45 const int16_t *filter_y, // unused
46 int y_step_q4, // unused
47 int w, int h) {
48 int width;
49 const uint8_t *s, *psrc;
50 uint8_t *d, *pdst;
51 uint8x8_t d2u8, d3u8, d24u8, d25u8, d26u8, d27u8, d28u8, d29u8;
52 uint32x2_t d2u32, d3u32, d28u32, d29u32, d30u32, d31u32;
53 uint8x16_t q12u8, q13u8, q14u8, q15u8;
54 int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d22s16, d23s16;
55 int16x4_t d24s16, d25s16, d26s16, d27s16;
56 uint16x4_t d2u16, d3u16, d4u16, d5u16, d16u16, d17u16, d18u16, d19u16;
57 int16x8_t q0s16;
58 uint16x8_t q1u16, q2u16, q8u16, q9u16, q10u16, q11u16, q12u16, q13u16;
59 int32x4_t q1s32, q2s32, q14s32, q15s32;
60 uint16x8x2_t q0x2u16;
61 uint8x8x2_t d0x2u8, d1x2u8;
62 uint32x2x2_t d0x2u32;
63 uint16x4x2_t d0x2u16, d1x2u16;
64 uint32x4x2_t q0x2u32;
65
66 assert(x_step_q4 == 16);
67
Urvang Joshid71a2312016-07-14 12:33:48 -070068 (void)x_step_q4;
69 (void)y_step_q4;
70 (void)filter_y;
71
Yaowu Xuc27fc142016-08-22 16:08:15 -070072 q0s16 = vld1q_s16(filter_x);
73
74 src -= 3; // adjust for taps
75 for (; h > 0; h -= 4, src += src_stride * 4,
76 dst += dst_stride * 4) { // loop_horiz_v
77 s = src;
78 d24u8 = vld1_u8(s);
79 s += src_stride;
80 d25u8 = vld1_u8(s);
81 s += src_stride;
82 d26u8 = vld1_u8(s);
83 s += src_stride;
84 d27u8 = vld1_u8(s);
85
86 q12u8 = vcombine_u8(d24u8, d25u8);
87 q13u8 = vcombine_u8(d26u8, d27u8);
88
89 q0x2u16 =
90 vtrnq_u16(vreinterpretq_u16_u8(q12u8), vreinterpretq_u16_u8(q13u8));
91 d24u8 = vreinterpret_u8_u16(vget_low_u16(q0x2u16.val[0]));
92 d25u8 = vreinterpret_u8_u16(vget_high_u16(q0x2u16.val[0]));
93 d26u8 = vreinterpret_u8_u16(vget_low_u16(q0x2u16.val[1]));
94 d27u8 = vreinterpret_u8_u16(vget_high_u16(q0x2u16.val[1]));
95 d0x2u8 = vtrn_u8(d24u8, d25u8);
96 d1x2u8 = vtrn_u8(d26u8, d27u8);
97
98 __builtin_prefetch(src + src_stride * 4);
99 __builtin_prefetch(src + src_stride * 5);
100 __builtin_prefetch(src + src_stride * 6);
101
102 q8u16 = vmovl_u8(d0x2u8.val[0]);
103 q9u16 = vmovl_u8(d0x2u8.val[1]);
104 q10u16 = vmovl_u8(d1x2u8.val[0]);
105 q11u16 = vmovl_u8(d1x2u8.val[1]);
106
107 d16u16 = vget_low_u16(q8u16);
108 d17u16 = vget_high_u16(q8u16);
109 d18u16 = vget_low_u16(q9u16);
110 d19u16 = vget_high_u16(q9u16);
111 q8u16 = vcombine_u16(d16u16, d18u16); // vswp 17 18
112 q9u16 = vcombine_u16(d17u16, d19u16);
113
114 d20s16 = vreinterpret_s16_u16(vget_low_u16(q10u16));
115 d23s16 = vreinterpret_s16_u16(vget_high_u16(q10u16)); // vmov 23 21
116 for (width = w, psrc = src + 7, pdst = dst; width > 0;
117 width -= 4, psrc += 4, pdst += 4) { // loop_horiz
118 s = psrc;
119 d28u32 = vld1_dup_u32((const uint32_t *)s);
120 s += src_stride;
121 d29u32 = vld1_dup_u32((const uint32_t *)s);
122 s += src_stride;
123 d31u32 = vld1_dup_u32((const uint32_t *)s);
124 s += src_stride;
125 d30u32 = vld1_dup_u32((const uint32_t *)s);
126
127 __builtin_prefetch(psrc + 64);
128
129 d0x2u16 =
130 vtrn_u16(vreinterpret_u16_u32(d28u32), vreinterpret_u16_u32(d31u32));
131 d1x2u16 =
132 vtrn_u16(vreinterpret_u16_u32(d29u32), vreinterpret_u16_u32(d30u32));
133 d0x2u8 = vtrn_u8(vreinterpret_u8_u16(d0x2u16.val[0]), // d28
134 vreinterpret_u8_u16(d1x2u16.val[0])); // d29
135 d1x2u8 = vtrn_u8(vreinterpret_u8_u16(d0x2u16.val[1]), // d31
136 vreinterpret_u8_u16(d1x2u16.val[1])); // d30
137
138 __builtin_prefetch(psrc + 64 + src_stride);
139
140 q14u8 = vcombine_u8(d0x2u8.val[0], d0x2u8.val[1]);
141 q15u8 = vcombine_u8(d1x2u8.val[1], d1x2u8.val[0]);
142 q0x2u32 =
143 vtrnq_u32(vreinterpretq_u32_u8(q14u8), vreinterpretq_u32_u8(q15u8));
144
145 d28u8 = vreinterpret_u8_u32(vget_low_u32(q0x2u32.val[0]));
146 d29u8 = vreinterpret_u8_u32(vget_high_u32(q0x2u32.val[0]));
147 q12u16 = vmovl_u8(d28u8);
148 q13u16 = vmovl_u8(d29u8);
149
150 __builtin_prefetch(psrc + 64 + src_stride * 2);
151
152 d16s16 = vreinterpret_s16_u16(vget_low_u16(q8u16));
153 d17s16 = vreinterpret_s16_u16(vget_high_u16(q8u16));
154 d18s16 = vreinterpret_s16_u16(vget_low_u16(q9u16));
155 d19s16 = vreinterpret_s16_u16(vget_high_u16(q9u16));
156 d22s16 = vreinterpret_s16_u16(vget_low_u16(q11u16));
157 d24s16 = vreinterpret_s16_u16(vget_low_u16(q12u16));
158 d25s16 = vreinterpret_s16_u16(vget_high_u16(q12u16));
159 d26s16 = vreinterpret_s16_u16(vget_low_u16(q13u16));
160 d27s16 = vreinterpret_s16_u16(vget_high_u16(q13u16));
161
162 q1s32 = MULTIPLY_BY_Q0(d16s16, d17s16, d20s16, d22s16, d18s16, d19s16,
163 d23s16, d24s16, q0s16);
164 q2s32 = MULTIPLY_BY_Q0(d17s16, d20s16, d22s16, d18s16, d19s16, d23s16,
165 d24s16, d26s16, q0s16);
166 q14s32 = MULTIPLY_BY_Q0(d20s16, d22s16, d18s16, d19s16, d23s16, d24s16,
167 d26s16, d27s16, q0s16);
168 q15s32 = MULTIPLY_BY_Q0(d22s16, d18s16, d19s16, d23s16, d24s16, d26s16,
169 d27s16, d25s16, q0s16);
170
171 __builtin_prefetch(psrc + 60 + src_stride * 3);
172
173 d2u16 = vqrshrun_n_s32(q1s32, 7);
174 d3u16 = vqrshrun_n_s32(q2s32, 7);
175 d4u16 = vqrshrun_n_s32(q14s32, 7);
176 d5u16 = vqrshrun_n_s32(q15s32, 7);
177
178 q1u16 = vcombine_u16(d2u16, d3u16);
179 q2u16 = vcombine_u16(d4u16, d5u16);
180
181 d2u8 = vqmovn_u16(q1u16);
182 d3u8 = vqmovn_u16(q2u16);
183
184 d0x2u16 = vtrn_u16(vreinterpret_u16_u8(d2u8), vreinterpret_u16_u8(d3u8));
185 d0x2u32 = vtrn_u32(vreinterpret_u32_u16(d0x2u16.val[0]),
186 vreinterpret_u32_u16(d0x2u16.val[1]));
187 d0x2u8 = vtrn_u8(vreinterpret_u8_u32(d0x2u32.val[0]),
188 vreinterpret_u8_u32(d0x2u32.val[1]));
189
190 d2u32 = vreinterpret_u32_u8(d0x2u8.val[0]);
191 d3u32 = vreinterpret_u32_u8(d0x2u8.val[1]);
192
193 d = pdst;
194 vst1_lane_u32((uint32_t *)d, d2u32, 0);
195 d += dst_stride;
196 vst1_lane_u32((uint32_t *)d, d3u32, 0);
197 d += dst_stride;
198 vst1_lane_u32((uint32_t *)d, d2u32, 1);
199 d += dst_stride;
200 vst1_lane_u32((uint32_t *)d, d3u32, 1);
201
202 q8u16 = q9u16;
203 d20s16 = d23s16;
204 q11u16 = q12u16;
205 q9u16 = q13u16;
206 d23s16 = vreinterpret_s16_u16(vget_high_u16(q11u16));
207 }
208 }
209 return;
210}
211
Yaowu Xuf883b422016-08-30 14:01:10 -0700212void aom_convolve8_vert_neon(const uint8_t *src, ptrdiff_t src_stride,
Yaowu Xuc27fc142016-08-22 16:08:15 -0700213 uint8_t *dst, ptrdiff_t dst_stride,
214 const int16_t *filter_x, // unused
215 int x_step_q4, // unused
216 const int16_t *filter_y, int y_step_q4, int w,
217 int h) {
218 int height;
219 const uint8_t *s;
220 uint8_t *d;
221 uint32x2_t d2u32, d3u32;
222 uint32x2_t d16u32, d18u32, d20u32, d22u32, d24u32, d26u32;
223 int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d21s16, d22s16;
224 int16x4_t d24s16, d25s16, d26s16, d27s16;
225 uint16x4_t d2u16, d3u16, d4u16, d5u16;
226 int16x8_t q0s16;
227 uint16x8_t q1u16, q2u16, q8u16, q9u16, q10u16, q11u16, q12u16, q13u16;
228 int32x4_t q1s32, q2s32, q14s32, q15s32;
229
230 assert(y_step_q4 == 16);
231
Urvang Joshid71a2312016-07-14 12:33:48 -0700232 (void)x_step_q4;
233 (void)y_step_q4;
234 (void)filter_x;
235
Yaowu Xuc27fc142016-08-22 16:08:15 -0700236 src -= src_stride * 3;
237 q0s16 = vld1q_s16(filter_y);
238 for (; w > 0; w -= 4, src += 4, dst += 4) { // loop_vert_h
239 s = src;
240 d16u32 = vld1_lane_u32((const uint32_t *)s, d16u32, 0);
241 s += src_stride;
242 d16u32 = vld1_lane_u32((const uint32_t *)s, d16u32, 1);
243 s += src_stride;
244 d18u32 = vld1_lane_u32((const uint32_t *)s, d18u32, 0);
245 s += src_stride;
246 d18u32 = vld1_lane_u32((const uint32_t *)s, d18u32, 1);
247 s += src_stride;
248 d20u32 = vld1_lane_u32((const uint32_t *)s, d20u32, 0);
249 s += src_stride;
250 d20u32 = vld1_lane_u32((const uint32_t *)s, d20u32, 1);
251 s += src_stride;
252 d22u32 = vld1_lane_u32((const uint32_t *)s, d22u32, 0);
253 s += src_stride;
254
255 q8u16 = vmovl_u8(vreinterpret_u8_u32(d16u32));
256 q9u16 = vmovl_u8(vreinterpret_u8_u32(d18u32));
257 q10u16 = vmovl_u8(vreinterpret_u8_u32(d20u32));
258 q11u16 = vmovl_u8(vreinterpret_u8_u32(d22u32));
259
260 d18s16 = vreinterpret_s16_u16(vget_low_u16(q9u16));
261 d19s16 = vreinterpret_s16_u16(vget_high_u16(q9u16));
262 d22s16 = vreinterpret_s16_u16(vget_low_u16(q11u16));
263 d = dst;
264 for (height = h; height > 0; height -= 4) { // loop_vert
265 d24u32 = vld1_lane_u32((const uint32_t *)s, d24u32, 0);
266 s += src_stride;
267 d26u32 = vld1_lane_u32((const uint32_t *)s, d26u32, 0);
268 s += src_stride;
269 d26u32 = vld1_lane_u32((const uint32_t *)s, d26u32, 1);
270 s += src_stride;
271 d24u32 = vld1_lane_u32((const uint32_t *)s, d24u32, 1);
272 s += src_stride;
273
274 q12u16 = vmovl_u8(vreinterpret_u8_u32(d24u32));
275 q13u16 = vmovl_u8(vreinterpret_u8_u32(d26u32));
276
277 d16s16 = vreinterpret_s16_u16(vget_low_u16(q8u16));
278 d17s16 = vreinterpret_s16_u16(vget_high_u16(q8u16));
279 d20s16 = vreinterpret_s16_u16(vget_low_u16(q10u16));
280 d21s16 = vreinterpret_s16_u16(vget_high_u16(q10u16));
281 d24s16 = vreinterpret_s16_u16(vget_low_u16(q12u16));
282 d25s16 = vreinterpret_s16_u16(vget_high_u16(q12u16));
283 d26s16 = vreinterpret_s16_u16(vget_low_u16(q13u16));
284 d27s16 = vreinterpret_s16_u16(vget_high_u16(q13u16));
285
286 __builtin_prefetch(d);
287 __builtin_prefetch(d + dst_stride);
288 q1s32 = MULTIPLY_BY_Q0(d16s16, d17s16, d18s16, d19s16, d20s16, d21s16,
289 d22s16, d24s16, q0s16);
290 __builtin_prefetch(d + dst_stride * 2);
291 __builtin_prefetch(d + dst_stride * 3);
292 q2s32 = MULTIPLY_BY_Q0(d17s16, d18s16, d19s16, d20s16, d21s16, d22s16,
293 d24s16, d26s16, q0s16);
294 __builtin_prefetch(s);
295 __builtin_prefetch(s + src_stride);
296 q14s32 = MULTIPLY_BY_Q0(d18s16, d19s16, d20s16, d21s16, d22s16, d24s16,
297 d26s16, d27s16, q0s16);
298 __builtin_prefetch(s + src_stride * 2);
299 __builtin_prefetch(s + src_stride * 3);
300 q15s32 = MULTIPLY_BY_Q0(d19s16, d20s16, d21s16, d22s16, d24s16, d26s16,
301 d27s16, d25s16, q0s16);
302
303 d2u16 = vqrshrun_n_s32(q1s32, 7);
304 d3u16 = vqrshrun_n_s32(q2s32, 7);
305 d4u16 = vqrshrun_n_s32(q14s32, 7);
306 d5u16 = vqrshrun_n_s32(q15s32, 7);
307
308 q1u16 = vcombine_u16(d2u16, d3u16);
309 q2u16 = vcombine_u16(d4u16, d5u16);
310
311 d2u32 = vreinterpret_u32_u8(vqmovn_u16(q1u16));
312 d3u32 = vreinterpret_u32_u8(vqmovn_u16(q2u16));
313
314 vst1_lane_u32((uint32_t *)d, d2u32, 0);
315 d += dst_stride;
316 vst1_lane_u32((uint32_t *)d, d2u32, 1);
317 d += dst_stride;
318 vst1_lane_u32((uint32_t *)d, d3u32, 0);
319 d += dst_stride;
320 vst1_lane_u32((uint32_t *)d, d3u32, 1);
321 d += dst_stride;
322
323 q8u16 = q10u16;
324 d18s16 = d22s16;
325 d19s16 = d24s16;
326 q10u16 = q13u16;
327 d22s16 = d25s16;
328 }
329 }
330 return;
331}