Line data Source code
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 : #ifndef AOM_DSP_X86_TXFM_COMMON_AVX2_H
13 : #define AOM_DSP_X86_TXFM_COMMON_AVX2_H
14 :
15 : #include <immintrin.h>
16 :
17 : #include "aom_dsp/txfm_common.h"
18 :
19 : #define pair256_set_epi16(a, b) \
20 : _mm256_set_epi16((int16_t)(b), (int16_t)(a), (int16_t)(b), (int16_t)(a), \
21 : (int16_t)(b), (int16_t)(a), (int16_t)(b), (int16_t)(a), \
22 : (int16_t)(b), (int16_t)(a), (int16_t)(b), (int16_t)(a), \
23 : (int16_t)(b), (int16_t)(a), (int16_t)(b), (int16_t)(a))
24 :
25 : #define pair256_set_epi32(a, b) \
26 : _mm256_set_epi32((int)(b), (int)(a), (int)(b), (int)(a), (int)(b), (int)(a), \
27 : (int)(b), (int)(a))
28 :
29 0 : static INLINE void mm256_reverse_epi16(__m256i *u) {
30 0 : const __m256i control = _mm256_set_epi16(
31 : 0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0B0A, 0x0D0C, 0x0F0E, 0x0100,
32 : 0x0302, 0x0504, 0x0706, 0x0908, 0x0B0A, 0x0D0C, 0x0F0E);
33 0 : __m256i v = _mm256_shuffle_epi8(*u, control);
34 0 : *u = _mm256_permute2x128_si256(v, v, 1);
35 0 : }
36 :
37 : // Note: in and out could have the same value
38 0 : static INLINE void mm256_transpose_16x16(const __m256i *in, __m256i *out) {
39 0 : __m256i tr0_0 = _mm256_unpacklo_epi16(in[0], in[1]);
40 0 : __m256i tr0_1 = _mm256_unpackhi_epi16(in[0], in[1]);
41 0 : __m256i tr0_2 = _mm256_unpacklo_epi16(in[2], in[3]);
42 0 : __m256i tr0_3 = _mm256_unpackhi_epi16(in[2], in[3]);
43 0 : __m256i tr0_4 = _mm256_unpacklo_epi16(in[4], in[5]);
44 0 : __m256i tr0_5 = _mm256_unpackhi_epi16(in[4], in[5]);
45 0 : __m256i tr0_6 = _mm256_unpacklo_epi16(in[6], in[7]);
46 0 : __m256i tr0_7 = _mm256_unpackhi_epi16(in[6], in[7]);
47 :
48 0 : __m256i tr0_8 = _mm256_unpacklo_epi16(in[8], in[9]);
49 0 : __m256i tr0_9 = _mm256_unpackhi_epi16(in[8], in[9]);
50 0 : __m256i tr0_a = _mm256_unpacklo_epi16(in[10], in[11]);
51 0 : __m256i tr0_b = _mm256_unpackhi_epi16(in[10], in[11]);
52 0 : __m256i tr0_c = _mm256_unpacklo_epi16(in[12], in[13]);
53 0 : __m256i tr0_d = _mm256_unpackhi_epi16(in[12], in[13]);
54 0 : __m256i tr0_e = _mm256_unpacklo_epi16(in[14], in[15]);
55 0 : __m256i tr0_f = _mm256_unpackhi_epi16(in[14], in[15]);
56 :
57 : // 00 10 01 11 02 12 03 13 08 18 09 19 0a 1a 0b 1b
58 : // 04 14 05 15 06 16 07 17 0c 1c 0d 1d 0e 1e 0f 1f
59 : // 20 30 21 31 22 32 23 33 28 38 29 39 2a 3a 2b 3b
60 : // 24 34 25 35 26 36 27 37 2c 3c 2d 3d 2e 3e 2f 3f
61 : // 40 50 41 51 42 52 43 53 48 58 49 59 4a 5a 4b 5b
62 : // 44 54 45 55 46 56 47 57 4c 5c 4d 5d 4e 5e 4f 5f
63 : // 60 70 61 71 62 72 63 73 68 78 69 79 6a 7a 6b 7b
64 : // 64 74 65 75 66 76 67 77 6c 7c 6d 7d 6e 7e 6f 7f
65 :
66 : // 80 90 81 91 82 92 83 93 88 98 89 99 8a 9a 8b 9b
67 : // 84 94 85 95 86 96 87 97 8c 9c 8d 9d 8e 9e 8f 9f
68 : // a0 b0 a1 b1 a2 b2 a3 b3 a8 b8 a9 b9 aa ba ab bb
69 : // a4 b4 a5 b5 a6 b6 a7 b7 ac bc ad bd ae be af bf
70 : // c0 d0 c1 d1 c2 d2 c3 d3 c8 d8 c9 d9 ca da cb db
71 : // c4 d4 c5 d5 c6 d6 c7 d7 cc dc cd dd ce de cf df
72 : // e0 f0 e1 f1 e2 f2 e3 f3 e8 f8 e9 f9 ea fa eb fb
73 : // e4 f4 e5 f5 e6 f6 e7 f7 ec fc ed fd ee fe ef ff
74 :
75 0 : __m256i tr1_0 = _mm256_unpacklo_epi32(tr0_0, tr0_2);
76 0 : __m256i tr1_1 = _mm256_unpackhi_epi32(tr0_0, tr0_2);
77 0 : __m256i tr1_2 = _mm256_unpacklo_epi32(tr0_1, tr0_3);
78 0 : __m256i tr1_3 = _mm256_unpackhi_epi32(tr0_1, tr0_3);
79 0 : __m256i tr1_4 = _mm256_unpacklo_epi32(tr0_4, tr0_6);
80 0 : __m256i tr1_5 = _mm256_unpackhi_epi32(tr0_4, tr0_6);
81 0 : __m256i tr1_6 = _mm256_unpacklo_epi32(tr0_5, tr0_7);
82 0 : __m256i tr1_7 = _mm256_unpackhi_epi32(tr0_5, tr0_7);
83 :
84 0 : __m256i tr1_8 = _mm256_unpacklo_epi32(tr0_8, tr0_a);
85 0 : __m256i tr1_9 = _mm256_unpackhi_epi32(tr0_8, tr0_a);
86 0 : __m256i tr1_a = _mm256_unpacklo_epi32(tr0_9, tr0_b);
87 0 : __m256i tr1_b = _mm256_unpackhi_epi32(tr0_9, tr0_b);
88 0 : __m256i tr1_c = _mm256_unpacklo_epi32(tr0_c, tr0_e);
89 0 : __m256i tr1_d = _mm256_unpackhi_epi32(tr0_c, tr0_e);
90 0 : __m256i tr1_e = _mm256_unpacklo_epi32(tr0_d, tr0_f);
91 0 : __m256i tr1_f = _mm256_unpackhi_epi32(tr0_d, tr0_f);
92 :
93 : // 00 10 20 30 01 11 21 31 08 18 28 38 09 19 29 39
94 : // 02 12 22 32 03 13 23 33 0a 1a 2a 3a 0b 1b 2b 3b
95 : // 04 14 24 34 05 15 25 35 0c 1c 2c 3c 0d 1d 2d 3d
96 : // 06 16 26 36 07 17 27 37 0e 1e 2e 3e 0f 1f 2f 3f
97 : // 40 50 60 70 41 51 61 71 48 58 68 78 49 59 69 79
98 : // 42 52 62 72 43 53 63 73 4a 5a 6a 7a 4b 5b 6b 7b
99 : // 44 54 64 74 45 55 65 75 4c 5c 6c 7c 4d 5d 6d 7d
100 : // 46 56 66 76 47 57 67 77 4e 5e 6e 7e 4f 5f 6f 7f
101 :
102 : // 80 90 a0 b0 81 91 a1 b1 88 98 a8 b8 89 99 a9 b9
103 : // 82 92 a2 b2 83 93 a3 b3 8a 9a aa ba 8b 9b ab bb
104 : // 84 94 a4 b4 85 95 a5 b5 8c 9c ac bc 8d 9d ad bd
105 : // 86 96 a6 b6 87 97 a7 b7 8e ae 9e be 8f 9f af bf
106 : // c0 d0 e0 f0 c1 d1 e1 f1 c8 d8 e8 f8 c9 d9 e9 f9
107 : // c2 d2 e2 f2 c3 d3 e3 f3 ca da ea fa cb db eb fb
108 : // c4 d4 e4 f4 c5 d5 e5 f5 cc dc ef fc cd dd ed fd
109 : // c6 d6 e6 f6 c7 d7 e7 f7 ce de ee fe cf df ef ff
110 :
111 0 : tr0_0 = _mm256_unpacklo_epi64(tr1_0, tr1_4);
112 0 : tr0_1 = _mm256_unpackhi_epi64(tr1_0, tr1_4);
113 0 : tr0_2 = _mm256_unpacklo_epi64(tr1_1, tr1_5);
114 0 : tr0_3 = _mm256_unpackhi_epi64(tr1_1, tr1_5);
115 0 : tr0_4 = _mm256_unpacklo_epi64(tr1_2, tr1_6);
116 0 : tr0_5 = _mm256_unpackhi_epi64(tr1_2, tr1_6);
117 0 : tr0_6 = _mm256_unpacklo_epi64(tr1_3, tr1_7);
118 0 : tr0_7 = _mm256_unpackhi_epi64(tr1_3, tr1_7);
119 :
120 0 : tr0_8 = _mm256_unpacklo_epi64(tr1_8, tr1_c);
121 0 : tr0_9 = _mm256_unpackhi_epi64(tr1_8, tr1_c);
122 0 : tr0_a = _mm256_unpacklo_epi64(tr1_9, tr1_d);
123 0 : tr0_b = _mm256_unpackhi_epi64(tr1_9, tr1_d);
124 0 : tr0_c = _mm256_unpacklo_epi64(tr1_a, tr1_e);
125 0 : tr0_d = _mm256_unpackhi_epi64(tr1_a, tr1_e);
126 0 : tr0_e = _mm256_unpacklo_epi64(tr1_b, tr1_f);
127 0 : tr0_f = _mm256_unpackhi_epi64(tr1_b, tr1_f);
128 :
129 : // 00 10 20 30 40 50 60 70 08 18 28 38 48 58 68 78
130 : // 01 11 21 31 41 51 61 71 09 19 29 39 49 59 69 79
131 : // 02 12 22 32 42 52 62 72 0a 1a 2a 3a 4a 5a 6a 7a
132 : // 03 13 23 33 43 53 63 73 0b 1b 2b 3b 4b 5b 6b 7b
133 : // 04 14 24 34 44 54 64 74 0c 1c 2c 3c 4c 5c 6c 7c
134 : // 05 15 25 35 45 55 65 75 0d 1d 2d 3d 4d 5d 6d 7d
135 : // 06 16 26 36 46 56 66 76 0e 1e 2e 3e 4e 5e 6e 7e
136 : // 07 17 27 37 47 57 67 77 0f 1f 2f 3f 4f 5f 6f 7f
137 :
138 : // 80 90 a0 b0 c0 d0 e0 f0 88 98 a8 b8 c8 d8 e8 f8
139 : // 81 91 a1 b1 c1 d1 e1 f1 89 99 a9 b9 c9 d9 e9 f9
140 : // 82 92 a2 b2 c2 d2 e2 f2 8a 9a aa ba ca da ea fa
141 : // 83 93 a3 b3 c3 d3 e3 f3 8b 9b ab bb cb db eb fb
142 : // 84 94 a4 b4 c4 d4 e4 f4 8c 9c ac bc cc dc ef fc
143 : // 85 95 a5 b5 c5 d5 e5 f5 8d 9d ad bd cd dd ed fd
144 : // 86 96 a6 b6 c6 d6 e6 f6 8e ae 9e be ce de ee fe
145 : // 87 97 a7 b7 c7 d7 e7 f7 8f 9f af bf cf df ef ff
146 :
147 0 : out[0] = _mm256_permute2x128_si256(tr0_0, tr0_8, 0x20); // 0010 0000
148 0 : out[8] = _mm256_permute2x128_si256(tr0_0, tr0_8, 0x31); // 0011 0001
149 0 : out[1] = _mm256_permute2x128_si256(tr0_1, tr0_9, 0x20);
150 0 : out[9] = _mm256_permute2x128_si256(tr0_1, tr0_9, 0x31);
151 0 : out[2] = _mm256_permute2x128_si256(tr0_2, tr0_a, 0x20);
152 0 : out[10] = _mm256_permute2x128_si256(tr0_2, tr0_a, 0x31);
153 0 : out[3] = _mm256_permute2x128_si256(tr0_3, tr0_b, 0x20);
154 0 : out[11] = _mm256_permute2x128_si256(tr0_3, tr0_b, 0x31);
155 :
156 0 : out[4] = _mm256_permute2x128_si256(tr0_4, tr0_c, 0x20);
157 0 : out[12] = _mm256_permute2x128_si256(tr0_4, tr0_c, 0x31);
158 0 : out[5] = _mm256_permute2x128_si256(tr0_5, tr0_d, 0x20);
159 0 : out[13] = _mm256_permute2x128_si256(tr0_5, tr0_d, 0x31);
160 0 : out[6] = _mm256_permute2x128_si256(tr0_6, tr0_e, 0x20);
161 0 : out[14] = _mm256_permute2x128_si256(tr0_6, tr0_e, 0x31);
162 0 : out[7] = _mm256_permute2x128_si256(tr0_7, tr0_f, 0x20);
163 0 : out[15] = _mm256_permute2x128_si256(tr0_7, tr0_f, 0x31);
164 0 : }
165 :
166 0 : static INLINE __m256i butter_fly(const __m256i *a0, const __m256i *a1,
167 : const __m256i *cospi) {
168 0 : const __m256i dct_rounding = _mm256_set1_epi32(DCT_CONST_ROUNDING);
169 0 : __m256i y0 = _mm256_madd_epi16(*a0, *cospi);
170 0 : __m256i y1 = _mm256_madd_epi16(*a1, *cospi);
171 :
172 0 : y0 = _mm256_add_epi32(y0, dct_rounding);
173 0 : y1 = _mm256_add_epi32(y1, dct_rounding);
174 0 : y0 = _mm256_srai_epi32(y0, DCT_CONST_BITS);
175 0 : y1 = _mm256_srai_epi32(y1, DCT_CONST_BITS);
176 :
177 0 : return _mm256_packs_epi32(y0, y1);
178 : }
179 :
180 0 : static INLINE void txfm_scaling16_avx2(const int16_t c, __m256i *in) {
181 0 : const __m256i zero = _mm256_setzero_si256();
182 0 : const __m256i sqrt2_epi16 = _mm256_set1_epi16(c);
183 0 : const __m256i dct_const_rounding = _mm256_set1_epi32(DCT_CONST_ROUNDING);
184 : __m256i u0, u1;
185 0 : int i = 0;
186 :
187 0 : while (i < 16) {
188 0 : in[i] = _mm256_slli_epi16(in[i], 1);
189 :
190 0 : u0 = _mm256_unpacklo_epi16(zero, in[i]);
191 0 : u1 = _mm256_unpackhi_epi16(zero, in[i]);
192 :
193 0 : u0 = _mm256_madd_epi16(u0, sqrt2_epi16);
194 0 : u1 = _mm256_madd_epi16(u1, sqrt2_epi16);
195 :
196 0 : u0 = _mm256_add_epi32(u0, dct_const_rounding);
197 0 : u1 = _mm256_add_epi32(u1, dct_const_rounding);
198 :
199 0 : u0 = _mm256_srai_epi32(u0, DCT_CONST_BITS);
200 0 : u1 = _mm256_srai_epi32(u1, DCT_CONST_BITS);
201 0 : in[i] = _mm256_packs_epi32(u0, u1);
202 0 : i++;
203 : }
204 0 : }
205 :
206 : #endif // AOM_DSP_X86_TXFM_COMMON_AVX2_H
|