GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 161 / 0 / 161
Functions: 100.0% 8 / 0 / 8
Branches: 100.0% 44 / 0 / 44

convert/intel/convert_audio_avx2.cpp
Line Branch Exec Source
1 // Avisynth+
2 // https://avs-plus.net
3 //
4 // This file is part of Avisynth+ which is released under GPL2+ with exception.
5
6 // Convert Audio helper functions (AVX2)
7 // Copyright (c) 2020 Xinyue Lu, (c) 2021 pinterf
8
9 #include <avs/types.h>
10 #include <avs/config.h>
11
12 // Intrinsics base header + really required extension headers
13 #if defined(_MSC_VER)
14 #include <intrin.h> // MSVC
15 #else
16 #include <x86intrin.h> // GCC/MinGW/Clang/LLVM
17 #endif
18 #include <immintrin.h> // AVX2
19
20
21 // Easy: 32-16, 16-32
22 // Float: 8/16/32-FLT, FLT-8/16/32
23
24 6 void convert32To16_AVX2(void *inbuf, void *outbuf, int count) {
25 6 auto in = reinterpret_cast<int32_t *>(inbuf);
26 6 auto in16 = reinterpret_cast<int16_t *>(inbuf);
27 6 auto out = reinterpret_cast<int16_t *>(outbuf);
28
29 6 const int c_loop = count & ~15;
30
31
2/2
✓ Branch 4 → 3 taken 40 times.
✓ Branch 4 → 5 taken 6 times.
46 for (int i = c_loop; i < count; i++)
32 40 out[i] = in16[i * 2 + 1];
33
34
2/2
✓ Branch 18 → 6 taken 2 times.
✓ Branch 18 → 19 taken 6 times.
8 for (int i = 0; i < c_loop; i += 16) {
35 2 __m256i in32a = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(in)); in += 8;
36 2 __m256i in32b = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(in)); in += 8;
37 2 __m256i in16a = _mm256_srai_epi32(in32a, 16);
38 2 __m256i in16b = _mm256_srai_epi32(in32b, 16);
39 2 __m256i out16 = _mm256_packs_epi32(in16a, in16b);
40 2 out16 = _mm256_permute4x64_epi64(out16, 216);
41 2 _mm256_storeu_si256(reinterpret_cast<__m256i *>(out), out16); out += 16;
42 }
43 6 }
44
45 6 void convert16To32_AVX2(void *inbuf, void *outbuf, int count) {
46 6 auto in = reinterpret_cast<int16_t *>(inbuf);
47 6 auto out = reinterpret_cast<int32_t *>(outbuf);
48 6 auto out16 = reinterpret_cast<int16_t *>(outbuf);
49
50 6 const int c_loop = count & ~15;
51
52
2/2
✓ Branch 4 → 3 taken 40 times.
✓ Branch 4 → 5 taken 6 times.
46 for (int i = c_loop; i < count; i++) {
53 40 out16[i * 2] = 0;
54 40 out16[i * 2 + 1] = in[i];
55 }
56
57 6 __m256i zero = _mm256_set1_epi16(0);
58
2/2
✓ Branch 19 → 10 taken 2 times.
✓ Branch 19 → 20 taken 6 times.
8 for (int i = 0; i < c_loop; i += 16) {
59 2 __m256i in16 = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(in)); in += 16;
60 2 in16 = _mm256_permute4x64_epi64(in16, 216);
61 2 __m256i out32a = _mm256_unpacklo_epi16(zero, in16);
62 2 __m256i out32b = _mm256_unpackhi_epi16(zero, in16);
63 2 _mm256_storeu_si256(reinterpret_cast<__m256i *>(out), out32a); out += 8;
64 2 _mm256_storeu_si256(reinterpret_cast<__m256i *>(out), out32b); out += 8;
65 }
66 6 }
67
68 9 void convert8ToFLT_AVX2(void* inbuf, void* outbuf, int count) {
69 9 auto in = reinterpret_cast<uint8_t*>(inbuf);
70 9 auto out = reinterpret_cast<SFLOAT*>(outbuf);
71 9 constexpr float divisor = 1.0f / 128.f; // 1 << 7
72
73 9 const int c_loop = count & ~7;
74
75
2/2
✓ Branch 4 → 3 taken 28 times.
✓ Branch 4 → 5 taken 9 times.
37 for (int i = c_loop; i < count; i++)
76 28 out[i] = (in[i] - 128) * divisor;
77
78 9 __m256 divv = _mm256_set1_ps(divisor);
79
2/2
✓ Branch 26 → 8 taken 7 times.
✓ Branch 26 → 27 taken 9 times.
16 for (int i = 0; i < c_loop; i += 8) {
80 7 __m128i src = _mm_loadl_epi64(reinterpret_cast<__m128i*>(in)); in += 8;
81 7 __m256i in32 = _mm256_cvtepu8_epi32(src);
82 14 in32 = _mm256_sub_epi32(in32, _mm256_set1_epi32(128));
83 7 __m256 infl = _mm256_cvtepi32_ps(in32);
84 7 __m256 outfl = _mm256_mul_ps(infl, divv);
85 7 _mm256_storeu_ps(out, outfl); out += 8;
86 }
87 9 }
88
89 10 void convertFLTTo8_AVX2(void* inbuf, void* outbuf, int count) {
90 10 auto in = reinterpret_cast<SFLOAT*>(inbuf);
91 10 auto out = reinterpret_cast<uint8_t*>(outbuf);
92 10 constexpr float multiplier = 128.f;
93 10 constexpr float max8 = 127.f;
94 10 constexpr float min8 = -128.f;
95
96 10 const int c_loop = count & ~15;
97
98
2/2
✓ Branch 9 → 3 taken 53 times.
✓ Branch 9 → 10 taken 10 times.
63 for (int i = c_loop; i < count; i++) {
99 53 float val = in[i] * multiplier;
100 uint8_t result;
101
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 51 times.
53 if (val >= max8) result = 255;
102
2/2
✓ Branch 5 → 6 taken 14 times.
✓ Branch 5 → 7 taken 37 times.
51 else if (val <= min8) result = 0;
103 37 else result = static_cast<int8_t>(val) + 128;
104 53 out[i] = result;
105 }
106
107 10 __m256 mulv = _mm256_set1_ps(multiplier);
108 10 __m256 maxv = _mm256_set1_ps(max8);
109 10 __m256 minv = _mm256_set1_ps(min8);
110
2/2
✓ Branch 51 → 17 taken 3 times.
✓ Branch 51 → 52 taken 10 times.
13 for (int i = 0; i < c_loop; i += 16) {
111 3 __m256 infl_lo = _mm256_loadu_ps(in); in += 8;
112 3 __m256 infl_hi = _mm256_loadu_ps(in); in += 8;
113 9 __m256 outfl_lo = _mm256_max_ps(minv, _mm256_min_ps(maxv, _mm256_mul_ps(infl_lo, mulv)));
114 9 __m256 outfl_hi = _mm256_max_ps(minv, _mm256_min_ps(maxv, _mm256_mul_ps(infl_hi, mulv)));
115 3 __m256i out32_lo = _mm256_cvttps_epi32(outfl_lo);
116 3 __m256i out32_hi = _mm256_cvttps_epi32(outfl_hi);
117 3 __m256i out16 = _mm256_packs_epi32(out32_lo, out32_hi);
118
119 3 out16 = _mm256_permute4x64_epi64(out16, (0 << 0) | (2 << 2) | (1 << 4) | (3 << 6));
120 3 __m128i out16_lo = _mm256_castsi256_si128(out16);
121 3 __m128i out16_hi = _mm256_extractf128_si256(out16, 1);
122 3 __m128i out8 = _mm_packs_epi16(out16_lo, out16_hi);
123 6 out8 = _mm_add_epi8(out8, _mm_set1_epi8(-128)); // 128
124 3 _mm_storeu_si128(reinterpret_cast<__m128i*>(out), out8); out += 16;
125 }
126 10 }
127
128 10 void convert16ToFLT_AVX2(void* inbuf, void* outbuf, int count) {
129 10 auto in = reinterpret_cast<int16_t*>(inbuf);
130 10 auto out = reinterpret_cast<SFLOAT*>(outbuf);
131 10 constexpr float divisor = 1.0f / 32768.f; // 1 << 15
132
133 10 const int c_loop = count & ~7;
134
135
2/2
✓ Branch 4 → 3 taken 32 times.
✓ Branch 4 → 5 taken 10 times.
42 for (int i = c_loop; i < count; i++)
136 32 out[i] = in[i] * divisor;
137
138 10 __m256 divv = _mm256_set1_ps(divisor);
139
2/2
✓ Branch 18 → 8 taken 7 times.
✓ Branch 18 → 19 taken 10 times.
17 for (int i = 0; i < c_loop; i += 8) {
140 7 __m128i src = _mm_loadu_si128(reinterpret_cast<__m128i*>(in)); in += 8;
141 7 __m256i in32 = _mm256_cvtepi16_epi32(src);
142 7 __m256 infl = _mm256_cvtepi32_ps(in32);
143 7 __m256 outfl = _mm256_mul_ps(infl, divv);
144 7 _mm256_storeu_ps(out, outfl); out += 8;
145 }
146 10 }
147
148 12 void convertFLTTo16_AVX2(void* inbuf, void* outbuf, int count) {
149 12 auto in = reinterpret_cast<SFLOAT*>(inbuf);
150 12 auto out = reinterpret_cast<int16_t*>(outbuf);
151 12 constexpr float multiplier = 32768.f;
152 12 constexpr float max16 = 32767.f;
153 12 constexpr float min16 = -32768.f;
154
155 12 const int c_loop = count & ~7;
156
157
2/2
✓ Branch 9 → 3 taken 37 times.
✓ Branch 9 → 10 taken 12 times.
49 for (int i = c_loop; i < count; i++) {
158 37 float val = in[i] * multiplier;
159 int16_t result;
160
2/2
✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 5 taken 33 times.
37 if (val >= max16) result = 32767;
161
2/2
✓ Branch 5 → 6 taken 10 times.
✓ Branch 5 → 7 taken 23 times.
33 else if (val <= min16) result = (int16_t)-32768;
162 23 else result = static_cast<int16_t>(val);
163 37 out[i] = result;
164 }
165
166 12 __m256 mulv = _mm256_set1_ps(multiplier);
167 12 __m256 maxv = _mm256_set1_ps(max16);
168 12 __m256 minv = _mm256_set1_ps(min16);
169
2/2
✓ Branch 33 → 17 taken 9 times.
✓ Branch 33 → 34 taken 12 times.
21 for (int i = 0; i < c_loop; i += 8) {
170 9 __m256 infl = _mm256_loadu_ps(in); in += 8;
171 27 __m256 outfl = _mm256_max_ps(minv, _mm256_min_ps(maxv, _mm256_mul_ps(infl, mulv)));
172 9 __m256i out32 = _mm256_cvttps_epi32(outfl);
173 9 __m256i out16 = _mm256_packs_epi32(out32, out32);
174
175 9 out16 = _mm256_permute4x64_epi64(out16, (0 << 0) | (2 << 2) | (1 << 4) | (3 << 6));
176
177 9 _mm_storeu_si128(reinterpret_cast<__m128i*>(out), _mm256_castsi256_si128(out16)); out += 8;
178 }
179 12 }
180
181
182
183 21 void convert32ToFLT_AVX2(void *inbuf, void *outbuf, int count) {
184 21 auto in = reinterpret_cast<int32_t *>(inbuf);
185 21 auto out = reinterpret_cast<SFLOAT *>(outbuf);
186 21 const float divisor = 1.0f/2147483648.0f;
187
188 21 const int c_loop = count & ~7;
189
190
2/2
✓ Branch 4 → 3 taken 68 times.
✓ Branch 4 → 5 taken 21 times.
89 for (int i = c_loop; i < count; i++)
191 68 out[i] = in[i] * divisor;
192
193 21 __m256 divv = _mm256_set1_ps(divisor);
194
2/2
✓ Branch 16 → 8 taken 17 times.
✓ Branch 16 → 17 taken 21 times.
38 for (int i = 0; i < c_loop; i += 8) {
195 17 __m256i in32 = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(in)); in += 8;
196 17 __m256 infl = _mm256_cvtepi32_ps(in32);
197 17 __m256 outfl = _mm256_mul_ps(infl, divv);
198 17 _mm256_storeu_ps(out, outfl); out += 8;
199 }
200 21 }
201
202 22 void convertFLTTo32_AVX2(void *inbuf, void *outbuf, int count) {
203 22 auto in = reinterpret_cast<SFLOAT *>(inbuf);
204 22 auto out = reinterpret_cast<int32_t *>(outbuf);
205 22 const float multiplier = 2147483648.0f;
206 22 const float max32 = 2147483647.0f; // 2147483648.0f in reality
207 22 const float min32 = -2147483648.0f;
208
209 22 const int c_loop = count & ~7;
210
211
2/2
✓ Branch 9 → 3 taken 69 times.
✓ Branch 9 → 10 taken 22 times.
91 for (int i = c_loop; i < count; i++) {
212 69 float val = in[i] * multiplier;
213 int32_t result;
214
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 5 taken 66 times.
69 if (val >= max32) result = 0x7FFFFFFF; // 2147483647
215
2/2
✓ Branch 5 → 6 taken 20 times.
✓ Branch 5 → 7 taken 46 times.
66 else if (val <= min32) result = 0x80000000; // -2147483648
216 46 else result = static_cast<int32_t>(val);
217 69 out[i] = result;
218 }
219
220 22 __m256 mulv = _mm256_set1_ps(multiplier);
221 22 __m256 maxv = _mm256_set1_ps(max32);
222 22 __m256 minv = _mm256_set1_ps(min32);
223 22 __m256i maxv_i = _mm256_set1_epi32(0x7FFFFFFF); // 2147483647
224 22 __m256i minv_i = _mm256_set1_epi32(0x80000000); // -2147483648
225
2/2
✓ Branch 37 → 21 taken 19 times.
✓ Branch 37 → 38 taken 22 times.
41 for (int i = 0; i < c_loop; i += 8) {
226 19 __m256 infl = _mm256_loadu_ps(in); in += 8;
227 19 __m256 outfl = _mm256_mul_ps(infl, mulv);
228 19 __m256i cmphigh = _mm256_castps_si256(_mm256_cmp_ps(outfl, maxv, _CMP_GE_OS));
229 38 __m256i cmplow = _mm256_castps_si256(_mm256_cmp_ps(minv, outfl, _CMP_GE_OS));
230 19 __m256i out32 = _mm256_cvttps_epi32(outfl);
231 19 out32 = _mm256_blendv_epi8(out32, maxv_i, cmphigh);
232 19 out32 = _mm256_blendv_epi8(out32, minv_i, cmplow);
233
234 19 _mm256_storeu_si256(reinterpret_cast<__m256i *>(out), out32); out += 8;
235 }
236 22 }
237