Line data Source code
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 : #ifndef AV1_COMMON_X86_AV1_TXFM_COMMON_AVX2_H_
12 : #define AV1_COMMON_X86_AV1_TXFM_COMMON_AVX2_H_
13 :
14 : #include <immintrin.h>
15 : #include <stdint.h>
16 : #include "EbTransforms.h"
17 :
18 : #ifdef __cplusplus
19 : extern "C" {
20 : #endif
21 :
22 : #define pair_set_epi16(a, b) \
23 : _mm_set1_epi32((int32_t)(((uint16_t)(a)) | (((uint32_t)(b)) << 16)))
24 :
25 : // Reverse the 8 16 bit words in __m128i
26 32348200 : static INLINE __m128i mm_reverse_epi16(const __m128i x) {
27 32348200 : const __m128i a = _mm_shufflelo_epi16(x, 0x1b);
28 32348200 : const __m128i b = _mm_shufflehi_epi16(a, 0x1b);
29 32348200 : return _mm_shuffle_epi32(b, 0x4e);
30 : }
31 :
32 540630000 : static INLINE __m256i pair_set_w16_epi16(int16_t a, int16_t b) {
33 540630000 : return _mm256_set1_epi32(
34 540630000 : (int32_t)(((uint16_t)(a)) | (((uint32_t)(b)) << 16)));
35 : }
36 :
37 387674000 : static INLINE void btf_16_w16_avx2(const __m256i w0, const __m256i w1,
38 : __m256i *in0, __m256i *in1, const __m256i _r,
39 : const int32_t cos_bit) {
40 387674000 : __m256i t0 = _mm256_unpacklo_epi16(*in0, *in1);
41 775347000 : __m256i t1 = _mm256_unpackhi_epi16(*in0, *in1);
42 387674000 : __m256i u0 = _mm256_madd_epi16(t0, w0);
43 387674000 : __m256i u1 = _mm256_madd_epi16(t1, w0);
44 387674000 : __m256i v0 = _mm256_madd_epi16(t0, w1);
45 387674000 : __m256i v1 = _mm256_madd_epi16(t1, w1);
46 :
47 387674000 : __m256i a0 = _mm256_add_epi32(u0, _r);
48 387674000 : __m256i a1 = _mm256_add_epi32(u1, _r);
49 387674000 : __m256i b0 = _mm256_add_epi32(v0, _r);
50 387674000 : __m256i b1 = _mm256_add_epi32(v1, _r);
51 :
52 387674000 : __m256i c0 = _mm256_srai_epi32(a0, cos_bit);
53 387674000 : __m256i c1 = _mm256_srai_epi32(a1, cos_bit);
54 387674000 : __m256i d0 = _mm256_srai_epi32(b0, cos_bit);
55 387674000 : __m256i d1 = _mm256_srai_epi32(b1, cos_bit);
56 :
57 387674000 : *in0 = _mm256_packs_epi32(c0, c1);
58 387674000 : *in1 = _mm256_packs_epi32(d0, d1);
59 387674000 : }
60 :
61 649374000 : static INLINE void btf_16_adds_subs_avx2(__m256i *in0, __m256i *in1) {
62 649374000 : const __m256i _in0 = *in0;
63 649374000 : const __m256i _in1 = *in1;
64 649374000 : *in0 = _mm256_adds_epi16(_in0, _in1);
65 649374000 : *in1 = _mm256_subs_epi16(_in0, _in1);
66 649374000 : }
67 :
68 : static INLINE void btf_32_add_sub_avx2(__m256i *in0, __m256i *in1) {
69 : const __m256i _in0 = *in0;
70 : const __m256i _in1 = *in1;
71 : *in0 = _mm256_add_epi32(_in0, _in1);
72 : *in1 = _mm256_sub_epi32(_in0, _in1);
73 : }
74 :
75 207182000 : static INLINE void btf_16_adds_subs_out_avx2(__m256i *out0, __m256i *out1,
76 : __m256i in0, __m256i in1) {
77 207182000 : const __m256i _in0 = in0;
78 207182000 : const __m256i _in1 = in1;
79 207182000 : *out0 = _mm256_adds_epi16(_in0, _in1);
80 207182000 : *out1 = _mm256_subs_epi16(_in0, _in1);
81 207182000 : }
82 :
83 : static INLINE void btf_32_add_sub_out_avx2(__m256i *out0, __m256i *out1,
84 : __m256i in0, __m256i in1) {
85 : const __m256i _in0 = in0;
86 : const __m256i _in1 = in1;
87 : *out0 = _mm256_add_epi32(_in0, _in1);
88 : *out1 = _mm256_sub_epi32(_in0, _in1);
89 : }
90 :
91 : static INLINE __m256i load_16bit_to_16bit_avx2(const int16_t *a) {
92 : return _mm256_load_si256((const __m256i *)a);
93 : }
94 :
95 : static INLINE void load_buffer_16bit_to_16bit_avx2(const int16_t *in,
96 : int stride, __m256i *out,
97 : int out_size) {
98 : for (int i = 0; i < out_size; ++i) {
99 : out[i] = load_16bit_to_16bit_avx2(in + i * stride);
100 : }
101 : }
102 :
103 : static INLINE void load_buffer_16bit_to_16bit_flip_avx2(const int16_t *in,
104 : int stride,
105 : __m256i *out,
106 : int out_size) {
107 : for (int i = 0; i < out_size; ++i) {
108 : out[out_size - i - 1] = load_16bit_to_16bit_avx2(in + i * stride);
109 : }
110 : }
111 :
112 179014000 : static INLINE __m256i load_32bit_to_16bit_w16_avx2(const int32_t *a) {
113 179016000 : const __m256i a_low = _mm256_lddqu_si256((const __m256i *)a);
114 358032000 : const __m256i a_high = _mm256_lddqu_si256((const __m256i *)(a + 8));
115 179016000 : const __m256i b = _mm256_packs_epi32(a_low, a_high);
116 179016000 : return _mm256_permute4x64_epi64(b, 0xD8);
117 : }
118 :
119 10764000 : static INLINE void load_buffer_32bit_to_16bit_w16_avx2(const int32_t *in,
120 : int stride, __m256i *out,
121 : int out_size) {
122 182650000 : for (int i = 0; i < out_size; ++i) {
123 171896000 : out[i] = load_32bit_to_16bit_w16_avx2(in + i * stride);
124 : }
125 10753900 : }
126 :
127 23133100 : static INLINE void transpose_16bit_16x16_avx2(const __m256i *const in,
128 : __m256i *const out) {
129 : // Unpack 16 bit elements. Goes from:
130 : // in[0]: 00 01 02 03 08 09 0a 0b 04 05 06 07 0c 0d 0e 0f
131 : // in[1]: 10 11 12 13 18 19 1a 1b 14 15 16 17 1c 1d 1e 1f
132 : // in[2]: 20 21 22 23 28 29 2a 2b 24 25 26 27 2c 2d 2e 2f
133 : // in[3]: 30 31 32 33 38 39 3a 3b 34 35 36 37 3c 3d 3e 3f
134 : // in[4]: 40 41 42 43 48 49 4a 4b 44 45 46 47 4c 4d 4e 4f
135 : // in[5]: 50 51 52 53 58 59 5a 5b 54 55 56 57 5c 5d 5e 5f
136 : // in[6]: 60 61 62 63 68 69 6a 6b 64 65 66 67 6c 6d 6e 6f
137 : // in[7]: 70 71 72 73 78 79 7a 7b 74 75 76 77 7c 7d 7e 7f
138 : // in[8]: 80 81 82 83 88 89 8a 8b 84 85 86 87 8c 8d 8e 8f
139 : // to:
140 : // a0: 00 10 01 11 02 12 03 13 04 14 05 15 06 16 07 17
141 : // a1: 20 30 21 31 22 32 23 33 24 34 25 35 26 36 27 37
142 : // a2: 40 50 41 51 42 52 43 53 44 54 45 55 46 56 47 57
143 : // a3: 60 70 61 71 62 72 63 73 64 74 65 75 66 76 67 77
144 : // ...
145 : __m256i a[16];
146 208076000 : for (int i = 0; i < 16; i += 2) {
147 184943000 : a[i / 2 + 0] = _mm256_unpacklo_epi16(in[i], in[i + 1]);
148 369887000 : a[i / 2 + 8] = _mm256_unpackhi_epi16(in[i], in[i + 1]);
149 : }
150 : __m256i b[16];
151 208094000 : for (int i = 0; i < 16; i += 2) {
152 184961000 : b[i / 2 + 0] = _mm256_unpacklo_epi32(a[i], a[i + 1]);
153 369922000 : b[i / 2 + 8] = _mm256_unpackhi_epi32(a[i], a[i + 1]);
154 : }
155 : __m256i c[16];
156 208100000 : for (int i = 0; i < 16; i += 2) {
157 184967000 : c[i / 2 + 0] = _mm256_unpacklo_epi64(b[i], b[i + 1]);
158 369934000 : c[i / 2 + 8] = _mm256_unpackhi_epi64(b[i], b[i + 1]);
159 : }
160 23133100 : out[0 + 0] = _mm256_permute2x128_si256(c[0], c[1], 0x20);
161 23133100 : out[1 + 0] = _mm256_permute2x128_si256(c[8], c[9], 0x20);
162 23133100 : out[2 + 0] = _mm256_permute2x128_si256(c[4], c[5], 0x20);
163 23133100 : out[3 + 0] = _mm256_permute2x128_si256(c[12], c[13], 0x20);
164 :
165 23133100 : out[0 + 8] = _mm256_permute2x128_si256(c[0], c[1], 0x31);
166 23133100 : out[1 + 8] = _mm256_permute2x128_si256(c[8], c[9], 0x31);
167 23133100 : out[2 + 8] = _mm256_permute2x128_si256(c[4], c[5], 0x31);
168 23133100 : out[3 + 8] = _mm256_permute2x128_si256(c[12], c[13], 0x31);
169 :
170 23133100 : out[4 + 0] = _mm256_permute2x128_si256(c[0 + 2], c[1 + 2], 0x20);
171 23133100 : out[5 + 0] = _mm256_permute2x128_si256(c[8 + 2], c[9 + 2], 0x20);
172 23133100 : out[6 + 0] = _mm256_permute2x128_si256(c[4 + 2], c[5 + 2], 0x20);
173 23133100 : out[7 + 0] = _mm256_permute2x128_si256(c[12 + 2], c[13 + 2], 0x20);
174 :
175 23133100 : out[4 + 8] = _mm256_permute2x128_si256(c[0 + 2], c[1 + 2], 0x31);
176 23133100 : out[5 + 8] = _mm256_permute2x128_si256(c[8 + 2], c[9 + 2], 0x31);
177 23133100 : out[6 + 8] = _mm256_permute2x128_si256(c[4 + 2], c[5 + 2], 0x31);
178 23133100 : out[7 + 8] = _mm256_permute2x128_si256(c[12 + 2], c[13 + 2], 0x31);
179 23133100 : }
180 :
181 : static INLINE void transpose_16bit_16x8_avx2(const __m256i *const in,
182 : __m256i *const out) {
183 : const __m256i a0 = _mm256_unpacklo_epi16(in[0], in[1]);
184 : const __m256i a1 = _mm256_unpacklo_epi16(in[2], in[3]);
185 : const __m256i a2 = _mm256_unpacklo_epi16(in[4], in[5]);
186 : const __m256i a3 = _mm256_unpacklo_epi16(in[6], in[7]);
187 : const __m256i a4 = _mm256_unpackhi_epi16(in[0], in[1]);
188 : const __m256i a5 = _mm256_unpackhi_epi16(in[2], in[3]);
189 : const __m256i a6 = _mm256_unpackhi_epi16(in[4], in[5]);
190 : const __m256i a7 = _mm256_unpackhi_epi16(in[6], in[7]);
191 :
192 : const __m256i b0 = _mm256_unpacklo_epi32(a0, a1);
193 : const __m256i b1 = _mm256_unpacklo_epi32(a2, a3);
194 : const __m256i b2 = _mm256_unpacklo_epi32(a4, a5);
195 : const __m256i b3 = _mm256_unpacklo_epi32(a6, a7);
196 : const __m256i b4 = _mm256_unpackhi_epi32(a0, a1);
197 : const __m256i b5 = _mm256_unpackhi_epi32(a2, a3);
198 : const __m256i b6 = _mm256_unpackhi_epi32(a4, a5);
199 : const __m256i b7 = _mm256_unpackhi_epi32(a6, a7);
200 :
201 : out[0] = _mm256_unpacklo_epi64(b0, b1);
202 : out[1] = _mm256_unpackhi_epi64(b0, b1);
203 : out[2] = _mm256_unpacklo_epi64(b4, b5);
204 : out[3] = _mm256_unpackhi_epi64(b4, b5);
205 : out[4] = _mm256_unpacklo_epi64(b2, b3);
206 : out[5] = _mm256_unpackhi_epi64(b2, b3);
207 : out[6] = _mm256_unpacklo_epi64(b6, b7);
208 : out[7] = _mm256_unpackhi_epi64(b6, b7);
209 : }
210 :
211 93146 : static INLINE void flip_buf_avx2(__m256i *in, __m256i *out, int size) {
212 1583490 : for (int i = 0; i < size; ++i) {
213 1490340 : out[size - i - 1] = in[i];
214 : }
215 93146 : }
216 :
217 33257 : static INLINE void round_shift_16bit_w16_avx2(__m256i *in, int size, int bit) {
218 33257 : if (bit < 0) {
219 33257 : bit = -bit;
220 33257 : __m256i round = _mm256_set1_epi16(1 << (bit - 1));
221 565369 : for (int i = 0; i < size; ++i) {
222 532112 : in[i] = _mm256_adds_epi16(in[i], round);
223 1064220 : in[i] = _mm256_srai_epi16(in[i], bit);
224 : }
225 0 : } else if (bit > 0) {
226 0 : for (int i = 0; i < size; ++i) {
227 0 : in[i] = _mm256_slli_epi16(in[i], bit);
228 : }
229 : }
230 33257 : }
231 :
232 : static INLINE __m256i av1_round_shift_32_avx2(__m256i vec, int bit) {
233 : __m256i tmp, round;
234 : round = _mm256_set1_epi32(1 << (bit - 1));
235 : tmp = _mm256_add_epi32(vec, round);
236 : return _mm256_srai_epi32(tmp, bit);
237 : }
238 :
239 5769050 : static INLINE void av1_round_shift_array_32_avx2(__m256i *input,
240 : __m256i *output,
241 : const int32_t size,
242 : const int32_t bit) {
243 : int32_t i;
244 5769050 : if (bit > 0) {
245 2342300 : const __m256i round = _mm256_set1_epi32(1 << (bit - 1));
246 : __m256i r0;
247 541997000 : for (i = 0; i < size; i++) {
248 539655000 : r0 = _mm256_add_epi32(input[i], round);
249 1079310000 : output[i] = _mm256_srai_epi32(r0, bit);
250 : }
251 : } else {
252 441610000 : for (i = 0; i < size; i++)
253 876367000 : output[i] = _mm256_slli_epi32(input[i], -bit);
254 : }
255 5769050 : }
256 :
257 50397200 : static INLINE void av1_round_shift_rect_array_32_avx2(__m256i *input,
258 : __m256i *output,
259 : const int32_t size,
260 : const int32_t bit,
261 : const int32_t val) {
262 50397200 : const __m256i sqrt2 = _mm256_set1_epi32(val);
263 50397200 : const __m256i round2 = _mm256_set1_epi32(1 << (NewSqrt2Bits - 1));
264 : int32_t i;
265 50397200 : if (bit > 0) {
266 1070600 : const __m256i round1 = _mm256_set1_epi32(1 << (bit - 1));
267 : __m256i r0, r1, r2, r3;
268 274389000 : for (i = 0; i < size; i++) {
269 546638000 : r0 = _mm256_add_epi32(input[i], round1);
270 273319000 : r1 = _mm256_srai_epi32(r0, bit);
271 273319000 : r2 = _mm256_mullo_epi32(sqrt2, r1);
272 273319000 : r3 = _mm256_add_epi32(r2, round2);
273 546638000 : output[i] = _mm256_srai_epi32(r3, NewSqrt2Bits);
274 : }
275 : }
276 : else {
277 : __m256i r0, r1, r2;
278 500101000 : for (i = 0; i < size; i++) {
279 901548000 : r0 = _mm256_slli_epi32(input[i], -bit);
280 450774000 : r1 = _mm256_mullo_epi32(sqrt2, r0);
281 450774000 : r2 = _mm256_add_epi32(r1, round2);
282 901548000 : output[i] = _mm256_srai_epi32(r2, NewSqrt2Bits);
283 : }
284 : }
285 50397200 : }
286 :
287 : static INLINE __m256i scale_round_avx2(const __m256i a, const int scale) {
288 : const __m256i scale_rounding =
289 : pair_set_w16_epi16(scale, 1 << (NewSqrt2Bits - 1));
290 : const __m256i b = _mm256_madd_epi16(a, scale_rounding);
291 : return _mm256_srai_epi32(b, NewSqrt2Bits);
292 : }
293 :
294 : static INLINE void store_rect_16bit_to_32bit_w8_avx2(const __m256i a,
295 : int32_t *const b) {
296 : const __m256i one = _mm256_set1_epi16(1);
297 : const __m256i a_lo = _mm256_unpacklo_epi16(a, one);
298 : const __m256i a_hi = _mm256_unpackhi_epi16(a, one);
299 : const __m256i b_lo = scale_round_avx2(a_lo, NewSqrt2);
300 : const __m256i b_hi = scale_round_avx2(a_hi, NewSqrt2);
301 : const __m256i temp = _mm256_permute2f128_si256(b_lo, b_hi, 0x31);
302 : _mm_store_si128((__m128i *)b, _mm256_castsi256_si128(b_lo));
303 : _mm_store_si128((__m128i *)(b + 4), _mm256_castsi256_si128(b_hi));
304 : _mm256_store_si256((__m256i *)(b + 64), temp);
305 : }
306 :
307 : static INLINE void store_rect_buffer_16bit_to_32bit_w8_avx2(
308 : const __m256i *const in, int32_t *const out, const int stride,
309 : const int out_size) {
310 : for (int i = 0; i < out_size; ++i) {
311 : store_rect_16bit_to_32bit_w8_avx2(in[i], out + i * stride);
312 : }
313 : }
314 :
315 : static INLINE void pack_reg(const __m128i *in1, const __m128i *in2,
316 : __m256i *out) {
317 : out[0] = _mm256_insertf128_si256(_mm256_castsi128_si256(in1[0]), in2[0], 0x1);
318 : out[1] = _mm256_insertf128_si256(_mm256_castsi128_si256(in1[1]), in2[1], 0x1);
319 : out[2] = _mm256_insertf128_si256(_mm256_castsi128_si256(in1[2]), in2[2], 0x1);
320 : out[3] = _mm256_insertf128_si256(_mm256_castsi128_si256(in1[3]), in2[3], 0x1);
321 : out[4] = _mm256_insertf128_si256(_mm256_castsi128_si256(in1[4]), in2[4], 0x1);
322 : out[5] = _mm256_insertf128_si256(_mm256_castsi128_si256(in1[5]), in2[5], 0x1);
323 : out[6] = _mm256_insertf128_si256(_mm256_castsi128_si256(in1[6]), in2[6], 0x1);
324 : out[7] = _mm256_insertf128_si256(_mm256_castsi128_si256(in1[7]), in2[7], 0x1);
325 : }
326 :
327 : static INLINE void extract_reg(const __m256i *in, __m128i *out1) {
328 : out1[0] = _mm256_castsi256_si128(in[0]);
329 : out1[1] = _mm256_castsi256_si128(in[1]);
330 : out1[2] = _mm256_castsi256_si128(in[2]);
331 : out1[3] = _mm256_castsi256_si128(in[3]);
332 : out1[4] = _mm256_castsi256_si128(in[4]);
333 : out1[5] = _mm256_castsi256_si128(in[5]);
334 : out1[6] = _mm256_castsi256_si128(in[6]);
335 : out1[7] = _mm256_castsi256_si128(in[7]);
336 :
337 : out1[8] = _mm256_extracti128_si256(in[0], 0x01);
338 : out1[9] = _mm256_extracti128_si256(in[1], 0x01);
339 : out1[10] = _mm256_extracti128_si256(in[2], 0x01);
340 : out1[11] = _mm256_extracti128_si256(in[3], 0x01);
341 : out1[12] = _mm256_extracti128_si256(in[4], 0x01);
342 : out1[13] = _mm256_extracti128_si256(in[5], 0x01);
343 : out1[14] = _mm256_extracti128_si256(in[6], 0x01);
344 : out1[15] = _mm256_extracti128_si256(in[7], 0x01);
345 : }
346 : #ifdef __cplusplus
347 : }
348 : #endif
349 :
350 : #endif // AV1_COMMON_X86_AV1_TXFM_COMMON_AVX2_H_
|