GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 92.9% 183 / 0 / 197
Functions: 100.0% 4 / 0 / 4
Branches: 87.5% 28 / 0 / 32

filters/intel/focus_avx2.cpp
Line Branch Exec Source
1 // Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al.
2 // http://avisynth.nl
3
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
17 // http://www.gnu.org/copyleft/gpl.html .
18 //
19 // Linking Avisynth statically or dynamically with other modules is making a
20 // combined work based on Avisynth. Thus, the terms and conditions of the GNU
21 // General Public License cover the whole combination.
22 //
23 // As a special exception, the copyright holders of Avisynth give you
24 // permission to link Avisynth with independent modules that communicate with
25 // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
26 // terms of these independent modules, and to copy and distribute the
27 // resulting combined work under terms of your choice, provided that
28 // every copy of the combined work is accompanied by a complete copy of
29 // the source code of Avisynth (the version of Avisynth used to produce the
30 // combined work), being distributed under the terms of the GNU General
31 // Public License plus this exception. An independent module is a module
32 // which is not derived from or based on Avisynth, such as 3rd-party filters,
33 // import and export plugins, or graphical user interfaces.
34
35 #include <avs/config.h>
36 #include <avs/types.h>
37 #include <cstdint>
38 #include <type_traits>
39 #include "../core/internal.h"
40
41 // Intrinsics base header + really required extension headers
42 #if defined(_MSC_VER)
43 #include <intrin.h> // MSVC
44 #else
45 #include <x86intrin.h> // GCC/MinGW/Clang/LLVM
46 #endif
47 #include <immintrin.h>
48
49 #if !defined(__FMA__)
50 // Assume that all processors that have AVX2 also have FMA3
51 #if defined (__GNUC__) && ! defined (__INTEL_COMPILER) && ! defined (__clang__)
52 // Prevent error message in g++ when using FMA intrinsics with avx2:
53 #pragma message "It is recommended to specify also option -mfma when using -mavx2 or higher"
54 #else
55 #define __FMA__ 1
56 #endif
57 #endif
58 // FMA3 instruction set
59 #if defined (__FMA__) && (defined(__GNUC__) || defined(__clang__)) && ! defined (__INTEL_COMPILER)
60 #include <fmaintrin.h>
61 #endif // __FMA__
62
63
64 #ifndef _mm256_set_m128i
65 #define _mm256_set_m128i(v0, v1) _mm256_insertf128_si256(_mm256_castsi128_si256(v1), (v0), 1)
66 #endif
67
68 #ifndef _mm256_set_m128
69 #define _mm256_set_m128(v0, v1) _mm256_insertf128_ps(_mm256_castps128_ps256(v1), (v0), 1)
70 #endif
71
72 #ifndef _mm256_cvtsi256_si32
73 // int _mm256_cvtsi256_si32 (__m256i a)
74 #define _mm256_cvtsi256_si32(a) (_mm_cvtsi128_si32(_mm256_castsi256_si128(a)))
75 #endif
76
77 static AVS_FORCEINLINE __m256i af_blend_avx2(__m256i &upper, __m256i &center, __m256i &lower, __m256i &center_weight, __m256i &outer_weight, __m256i &round_mask) {
78 244 __m256i outer_tmp = _mm256_add_epi16(upper, lower);
79 122 __m256i center_tmp = _mm256_mullo_epi16(center, center_weight);
80
81 244 outer_tmp = _mm256_mullo_epi16(outer_tmp, outer_weight);
82
83 122 __m256i result = _mm256_adds_epi16(center_tmp, outer_tmp);
84 122 result = _mm256_adds_epi16(result, center_tmp);
85 244 result = _mm256_adds_epi16(result, round_mask);
86 122 return _mm256_srai_epi16(result, 7);
87 }
88
89 static AVS_FORCEINLINE __m256i af_blend_uint16_t_avx2(__m256i &upper, __m256i &center, __m256i &lower, __m256i &center_weight, __m256i &outer_weight, __m256i &round_mask) {
90 244 __m256i outer_tmp = _mm256_add_epi32(upper, lower);
91 __m256i center_tmp;
92 122 center_tmp = _mm256_mullo_epi32(center, center_weight);
93 244 outer_tmp = _mm256_mullo_epi32(outer_tmp, outer_weight);
94
95 122 __m256i result = _mm256_add_epi32(center_tmp, outer_tmp);
96 122 result = _mm256_add_epi32(result, center_tmp);
97 244 result = _mm256_add_epi32(result, round_mask);
98 122 return _mm256_srai_epi32(result, 7);
99 }
100
101 static AVS_FORCEINLINE __m256i af_unpack_blend_avx2(__m256i &left, __m256i &center, __m256i &right, __m256i &center_weight, __m256i &outer_weight, __m256i &round_mask, __m256i &zero) {
102 54 __m256i left_lo = _mm256_unpacklo_epi8(left, zero);
103 27 __m256i left_hi = _mm256_unpackhi_epi8(left, zero);
104 27 __m256i center_lo = _mm256_unpacklo_epi8(center, zero);
105 27 __m256i center_hi = _mm256_unpackhi_epi8(center, zero);
106 27 __m256i right_lo = _mm256_unpacklo_epi8(right, zero);
107 54 __m256i right_hi = _mm256_unpackhi_epi8(right, zero);
108
109 27 __m256i result_lo = af_blend_avx2(left_lo, center_lo, right_lo, center_weight, outer_weight, round_mask);
110 27 __m256i result_hi = af_blend_avx2(left_hi, center_hi, right_hi, center_weight, outer_weight, round_mask);
111
112 54 return _mm256_packus_epi16(result_lo, result_hi);
113 }
114
115 static AVS_FORCEINLINE __m256i af_unpack_blend_uint16_t_avx2(__m256i &left, __m256i &center, __m256i &right, __m256i &center_weight, __m256i &outer_weight, __m256i &round_mask, __m256i &zero) {
116 54 __m256i left_lo = _mm256_unpacklo_epi16(left, zero);
117 27 __m256i left_hi = _mm256_unpackhi_epi16(left, zero);
118 27 __m256i center_lo = _mm256_unpacklo_epi16(center, zero);
119 27 __m256i center_hi = _mm256_unpackhi_epi16(center, zero);
120 27 __m256i right_lo = _mm256_unpacklo_epi16(right, zero);
121 54 __m256i right_hi = _mm256_unpackhi_epi16(right, zero);
122
123 27 __m256i result_lo = af_blend_uint16_t_avx2(left_lo, center_lo, right_lo, center_weight, outer_weight, round_mask);
124 27 __m256i result_hi = af_blend_uint16_t_avx2(left_hi, center_hi, right_hi, center_weight, outer_weight, round_mask);
125 54 return _mm256_packus_epi32(result_lo, result_hi);
126 }
127
128 3 void af_vertical_uint16_t_avx2(BYTE* line_buf, BYTE* dstp, int height, int pitch, int row_size, int amount) {
129 // amount was: half_amount (32768). Full: 65536 (2**16)
130 // now it becomes 2**(16-9)=2**7 scale
131 3 int t = (amount + 256) >> 9; // 16-9 = 7 -> shift in
132 3 __m256i center_weight = _mm256_set1_epi32(t);
133 6 __m256i outer_weight = _mm256_set1_epi32(64 - t);
134 3 __m256i round_mask = _mm256_set1_epi32(0x40);
135 3 __m256i zero = _mm256_setzero_si256();
136
137
2/2
✓ Branch 69 → 11 taken 14 times.
✓ Branch 69 → 70 taken 3 times.
17 for (int y = 0; y < height - 1; ++y) {
138
2/2
✓ Branch 67 → 12 taken 28 times.
✓ Branch 67 → 68 taken 14 times.
42 for (int x = 0; x < row_size; x += 32) {
139 28 __m256i upper = _mm256_load_si256(reinterpret_cast<const __m256i*>(line_buf + x));
140 28 __m256i center = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp + x));
141 28 __m256i lower = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp + pitch + x));
142 28 _mm256_store_si256(reinterpret_cast<__m256i*>(line_buf + x), center);
143
144 28 __m256i upper_lo = _mm256_unpacklo_epi16(upper, zero);
145 28 __m256i upper_hi = _mm256_unpackhi_epi16(upper, zero);
146 28 __m256i center_lo = _mm256_unpacklo_epi16(center, zero);
147 28 __m256i center_hi = _mm256_unpackhi_epi16(center, zero);
148 28 __m256i lower_lo = _mm256_unpacklo_epi16(lower, zero);
149 28 __m256i lower_hi = _mm256_unpackhi_epi16(lower, zero);
150
151 28 __m256i result_lo = af_blend_uint16_t_avx2(upper_lo, center_lo, lower_lo, center_weight, outer_weight, round_mask);
152 28 __m256i result_hi = af_blend_uint16_t_avx2(upper_hi, center_hi, lower_hi, center_weight, outer_weight, round_mask);
153
154 28 __m256i result = _mm256_packus_epi32(result_lo, result_hi);
155
156 28 _mm256_store_si256(reinterpret_cast<__m256i*>(dstp + x), result);
157 }
158 14 dstp += pitch;
159 }
160
161 //last line
162
2/2
✓ Branch 119 → 71 taken 6 times.
✓ Branch 119 → 120 taken 3 times.
9 for (int x = 0; x < row_size; x += 32) {
163 6 __m256i upper = _mm256_load_si256(reinterpret_cast<const __m256i*>(line_buf + x));
164 12 __m256i center = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp + x));
165
166 6 __m256i upper_lo = _mm256_unpacklo_epi16(upper, zero);
167 6 __m256i upper_hi = _mm256_unpackhi_epi16(upper, zero);
168 6 __m256i center_lo = _mm256_unpacklo_epi16(center, zero);
169 6 __m256i center_hi = _mm256_unpackhi_epi16(center, zero);
170
171 6 __m256i result_lo = af_blend_uint16_t_avx2(upper_lo, center_lo, center_lo, center_weight, outer_weight, round_mask);
172 6 __m256i result_hi = af_blend_uint16_t_avx2(upper_hi, center_hi, center_hi, center_weight, outer_weight, round_mask);
173
174 __m256i result;
175 6 result = _mm256_packus_epi32(result_lo, result_hi);
176
177 6 _mm256_store_si256(reinterpret_cast<__m256i*>(dstp + x), result);
178 }
179 3 }
180
181 3 void af_vertical_avx2(BYTE* line_buf, BYTE* dstp, int height, int pitch, int width, int amount) {
182 3 short t = (amount + 256) >> 9;
183 3 __m256i center_weight = _mm256_set1_epi16(t);
184 6 __m256i outer_weight = _mm256_set1_epi16(64 - t);
185 3 __m256i round_mask = _mm256_set1_epi16(0x40);
186 3 __m256i zero = _mm256_setzero_si256();
187
188
2/2
✓ Branch 75 → 17 taken 14 times.
✓ Branch 75 → 76 taken 3 times.
17 for (int y = 0; y < height - 1; ++y) {
189
2/2
✓ Branch 73 → 18 taken 28 times.
✓ Branch 73 → 74 taken 14 times.
42 for (int x = 0; x < width; x += 32) {
190 28 __m256i upper = _mm256_load_si256(reinterpret_cast<const __m256i*>(line_buf + x));
191 28 __m256i center = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp + x));
192 28 __m256i lower = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp + pitch + x));
193 28 _mm256_store_si256(reinterpret_cast<__m256i*>(line_buf + x), center);
194
195 28 __m256i upper_lo = _mm256_unpacklo_epi8(upper, zero);
196 28 __m256i upper_hi = _mm256_unpackhi_epi8(upper, zero);
197 28 __m256i center_lo = _mm256_unpacklo_epi8(center, zero);
198 28 __m256i center_hi = _mm256_unpackhi_epi8(center, zero);
199 28 __m256i lower_lo = _mm256_unpacklo_epi8(lower, zero);
200 28 __m256i lower_hi = _mm256_unpackhi_epi8(lower, zero);
201
202 28 __m256i result_lo = af_blend_avx2(upper_lo, center_lo, lower_lo, center_weight, outer_weight, round_mask);
203 28 __m256i result_hi = af_blend_avx2(upper_hi, center_hi, lower_hi, center_weight, outer_weight, round_mask);
204
205 28 __m256i result = _mm256_packus_epi16(result_lo, result_hi);
206
207 28 _mm256_store_si256(reinterpret_cast<__m256i*>(dstp + x), result);
208 }
209 14 dstp += pitch;
210 }
211
212 //last line
213
2/2
✓ Branch 125 → 77 taken 6 times.
✓ Branch 125 → 126 taken 3 times.
9 for (int x = 0; x < width; x += 32) {
214 6 __m256i upper = _mm256_load_si256(reinterpret_cast<const __m256i*>(line_buf + x));
215 12 __m256i center = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp + x));
216
217 6 __m256i upper_lo = _mm256_unpacklo_epi8(upper, zero);
218 6 __m256i upper_hi = _mm256_unpackhi_epi8(upper, zero);
219 6 __m256i center_lo = _mm256_unpacklo_epi8(center, zero);
220 6 __m256i center_hi = _mm256_unpackhi_epi8(center, zero);
221
222 6 __m256i result_lo = af_blend_avx2(upper_lo, center_lo, center_lo, center_weight, outer_weight, round_mask);
223 6 __m256i result_hi = af_blend_avx2(upper_hi, center_hi, center_hi, center_weight, outer_weight, round_mask);
224
225 6 __m256i result = _mm256_packus_epi16(result_lo, result_hi);
226
227 6 _mm256_store_si256(reinterpret_cast<__m256i*>(dstp + x), result);
228 }
229 3 }
230
231 // -------------------------------------
232 // Blur/Sharpen Horizontal YV12 C++ Code
233 // -------------------------------------
234
235 template<typename pixel_t>
236 static AVS_FORCEINLINE void af_horizontal_planar_process_line_c(pixel_t left, BYTE *dstp8, size_t row_size, int center_weight, int outer_weight) {
237 size_t x;
238 17 pixel_t* dstp = reinterpret_cast<pixel_t *>(dstp8);
239 typedef typename std::conditional < sizeof(pixel_t) == 1, int, int64_t>::type weight_t; // for calling the right ScaledPixelClip()
240 17 size_t width = row_size / sizeof(pixel_t);
241
2/2
✓ Branch 218 → 214 taken 160 times.
✓ Branch 218 → 219 taken 17 times.
177 for (x = 0; x < width-1; ++x) {
242 160 pixel_t temp = ScaledPixelClip((weight_t)(dstp[x] * (weight_t)center_weight + (left + dstp[x+1]) * (weight_t)outer_weight));
243 160 left = dstp[x];
244 160 dstp[x] = temp;
245 }
246 // ScaledPixelClip has 2 overloads: BYTE/uint16_t (int/int64 i)
247 17 dstp[x] = ScaledPixelClip((weight_t)(dstp[x] * (weight_t)center_weight + (left + dstp[x]) * (weight_t)outer_weight));
248 17 }
249
250 static AVS_FORCEINLINE void af_horizontal_planar_process_line_uint16_c(uint16_t left, BYTE *dstp8, size_t row_size, int center_weight, int outer_weight, int bits_per_pixel) {
251 size_t x;
252 typedef uint16_t pixel_t;
253 17 pixel_t* dstp = reinterpret_cast<pixel_t *>(dstp8);
254 17 const int max_pixel_value = (1 << bits_per_pixel) - 1; // clamping on 10-12-14-16 bitdepth
255 typedef std::conditional < sizeof(pixel_t) == 1, int, int64_t>::type weight_t; // for calling the right ScaledPixelClip()
256 17 size_t width = row_size / sizeof(pixel_t);
257
2/2
✓ Branch 212 → 208 taken 90 times.
✓ Branch 212 → 213 taken 17 times.
107 for (x = 0; x < width-1; ++x) {
258 90 pixel_t temp = (pixel_t)ScaledPixelClipEx((weight_t)(dstp[x] * (weight_t)center_weight + (left + dstp[x+1]) * (weight_t)outer_weight), max_pixel_value);
259 90 left = dstp[x];
260 90 dstp[x] = temp;
261 }
262 // ScaledPixelClip has 2 overloads: BYTE/uint16_t (int/int64 i)
263 17 dstp[x] = ScaledPixelClipEx((weight_t)(dstp[x] * (weight_t)center_weight + (left + dstp[x]) * (weight_t)outer_weight), max_pixel_value);
264 17 }
265
266 3 void af_horizontal_planar_avx2(BYTE* dstp, size_t height, size_t pitch, size_t width, size_t amount) {
267 3 size_t mod32_width = (width / 32) * 32;
268
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 3 times.
3 size_t sse_loop_limit = width == mod32_width ? mod32_width - 32 : mod32_width;
269 3 int center_weight_c = int(amount*2);
270 3 int outer_weight_c = int(32768-amount);
271
272 3 short t = short((amount + 256) >> 9);
273 3 __m256i center_weight = _mm256_set1_epi16(t);
274 6 __m256i outer_weight = _mm256_set1_epi16(64 - t);
275 3 __m256i round_mask = _mm256_set1_epi16(0x40);
276 3 __m256i zero = _mm256_setzero_si256();
277
278 3 __m128i left_mask_128 = _mm_set_epi32(0, 0, 0, 0xFF);
279 3 __m128i right_mask_128 = _mm_set_epi8((char)0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
280
281 __m256i left;
282
283
2/2
✓ Branch 225 → 24 taken 17 times.
✓ Branch 225 → 226 taken 3 times.
20 for (size_t y = 0; y < height; ++y) {
284 //left border
285 17 __m256i center = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp));
286 17 __m256i right = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(dstp+1));
287 17 __m128i center_lo128 = _mm256_extractf128_si256(center, 0);
288 34 __m128i left_lo128 = _mm_or_si128(_mm_and_si128(center_lo128, left_mask_128), _mm_slli_si128(center_lo128, 1));
289 17 __m128i left_hi128 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(dstp + 16 - 1));
290 34 left = _mm256_set_m128i(left_hi128, left_lo128);
291
292 17 __m256i result = af_unpack_blend_avx2(left, center, right, center_weight, outer_weight, round_mask, zero);
293 34 left = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(dstp+32-1));
294 _mm256_store_si256(reinterpret_cast<__m256i*>(dstp), result);
295
296 //main processing loop
297
2/2
✓ Branch 146 → 89 taken 10 times.
✓ Branch 146 → 147 taken 17 times.
27 for (size_t x = 32; x < sse_loop_limit; x+= 32) {
298 10 center = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp+x));
299 20 right = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(dstp+x+1));
300
301 10 result = af_unpack_blend_avx2(left, center, right, center_weight, outer_weight, round_mask, zero);
302
303 10 left = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(dstp+x+32-1)); // read ahead to prevent overwrite
304
305 10 _mm256_store_si256(reinterpret_cast<__m256i*>(dstp+x), result);
306 }
307
308 //right border
309
1/2
✗ Branch 147 → 148 not taken.
✓ Branch 147 → 209 taken 17 times.
17 if(mod32_width == width) { //width is mod32, process with simd
310 center = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp + mod32_width - 32));
311
312 __m128i right_lo128 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(dstp + mod32_width - 32 + 1));
313 __m128i center_hi128 = _mm256_extractf128_si256(center, 1); // get high 128bit, really right! ptr+16
314 __m128i right_hi128 = _mm_or_si128(_mm_and_si128(center_hi128, right_mask_128), _mm_srli_si128(center_hi128, 1));
315 right = _mm256_set_m128i(right_hi128, right_lo128);
316
317 result = af_unpack_blend_avx2(left, center, right, center_weight, outer_weight, round_mask, zero);
318
319 _mm256_store_si256(reinterpret_cast<__m256i*>(dstp+mod32_width-32), result);
320 } else { //some stuff left
321 34 BYTE l = _mm256_cvtsi256_si32(left) & 0xFF;
322 17 af_horizontal_planar_process_line_c<uint8_t>(l, dstp+mod32_width, width-mod32_width, center_weight_c, outer_weight_c);
323
324 }
325
326 17 dstp += pitch;
327 }
328 3 }
329
330 3 void af_horizontal_planar_uint16_t_avx2(BYTE* dstp, size_t height, size_t pitch, size_t row_size, size_t amount, int bits_per_pixel) {
331 3 size_t mod32_width = (row_size / 32) * 32;
332
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 3 times.
3 size_t sse_loop_limit = row_size == mod32_width ? mod32_width - 32 : mod32_width;
333 3 int center_weight_c = int(amount * 2);
334 3 int outer_weight_c = int(32768 - amount);
335
336 3 int t = int((amount + 256) >> 9);
337 3 __m256i center_weight = _mm256_set1_epi32(t);
338 6 __m256i outer_weight = _mm256_set1_epi32(64 - t);
339 3 __m256i round_mask = _mm256_set1_epi32(0x40);
340 3 __m256i zero = _mm256_setzero_si256();
341
342 3 __m128i left_mask_128 = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, (short)0xFFFF); // 0, 0, 0, 0, 0, 0, 0, FFFF
343 3 __m128i right_mask_128 = _mm_set_epi16((short)0xFFFF, 0, 0, 0, 0, 0, 0, 0);
344
345 __m256i left;
346
347
2/2
✓ Branch 219 → 18 taken 17 times.
✓ Branch 219 → 220 taken 3 times.
20 for (size_t y = 0; y < height; ++y) {
348 //left border
349 17 __m256i center = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp));
350 17 __m256i right = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(dstp + sizeof(uint16_t)));
351 17 __m128i center_lo128 = _mm256_extractf128_si256(center, 0);
352 34 __m128i left_lo128 = _mm_or_si128(_mm_and_si128(center_lo128, left_mask_128), _mm_slli_si128(center_lo128, sizeof(uint16_t)));
353 17 __m128i left_hi128 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(dstp + 16 - sizeof(uint16_t)));
354 34 left = _mm256_set_m128i(left_hi128, left_lo128);
355
356 17 __m256i result = af_unpack_blend_uint16_t_avx2(left, center, right, center_weight, outer_weight, round_mask, zero);
357 34 left = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(dstp + (32 - sizeof(uint16_t))));
358 _mm256_store_si256(reinterpret_cast<__m256i*>(dstp), result);
359
360 //main processing loop
361
2/2
✓ Branch 140 → 83 taken 10 times.
✓ Branch 140 → 141 taken 17 times.
27 for (size_t x = 32; x < sse_loop_limit; x += 32) {
362 10 center = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp + x));
363 20 right = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(dstp + x + sizeof(uint16_t)));
364
365 10 result = af_unpack_blend_uint16_t_avx2(left, center, right, center_weight, outer_weight, round_mask, zero);
366
367 10 left = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(dstp + x + (32 - sizeof(uint16_t)))); // read ahead to prevent overwrite
368
369 10 _mm256_store_si256(reinterpret_cast<__m256i*>(dstp + x), result);
370 }
371
372 //right border
373
1/2
✗ Branch 141 → 142 not taken.
✓ Branch 141 → 203 taken 17 times.
17 if (mod32_width == row_size) { //width is mod32, process with simd
374 center = _mm256_load_si256(reinterpret_cast<const __m256i*>(dstp + mod32_width - 32));
375 __m128i right_lo128 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(dstp + mod32_width - 32 + sizeof(uint16_t)));
376 __m128i center_hi128 = _mm256_extractf128_si256(center, 1); // get high 128bit, really right! ptr+16
377 __m128i right_hi128 = _mm_or_si128(_mm_and_si128(center_hi128, right_mask_128), _mm_srli_si128(center_hi128, sizeof(uint16_t)));
378 right = _mm256_set_m128i(right_hi128, right_lo128);
379
380 result = af_unpack_blend_uint16_t_avx2(left, center, right, center_weight, outer_weight, round_mask, zero);
381
382 _mm256_store_si256(reinterpret_cast<__m256i*>(dstp + mod32_width - 32), result);
383 }
384 else { //some stuff left
385 34 uint16_t l = _mm256_cvtsi256_si32(left) & 0xFFFF;
386 17 af_horizontal_planar_process_line_uint16_c(l, dstp + mod32_width, row_size - mod32_width, center_weight_c, outer_weight_c, bits_per_pixel);
387 }
388
389 17 dstp += pitch;
390 }
391 3 }
392