GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 247 / 0 / 247
Functions: 100.0% 17 / 0 / 17
Branches: 79.4% 54 / 0 / 68

filters/intel/turn_sse.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 /*
36 ** Turn. version 0.1
37 ** (c) 2003 - Ernst Peché
38 **
39 */
40
41 #include "../turn.h"
42 #include "turn_sse.h"
43
44 // Intrinsics base header + really required extension headers
45 #if defined(_MSC_VER)
46 #include <intrin.h> // MSVC
47 #else
48 #include <x86intrin.h> // GCC/MinGW/Clang/LLVM
49 #endif
50 #include <tmmintrin.h> // SSSE3
51
52 #include <cstdint>
53
54
55 static AVS_FORCEINLINE __m128i movehl(const __m128i& x)
56 {
57 128 __m128 ps = _mm_castsi128_ps(x);
58 128 return _mm_castps_si128(_mm_movehl_ps(ps, ps));
59 }
60
61
62 // This pattern seems faster than the others.
63 static AVS_FORCEINLINE void transpose_8x8x8_sse2(const BYTE* AVS_RESTRICT srcp, BYTE* AVS_RESTRICT dstp, int src_pitch, int dst_pitch)
64 {
65 16 __m128i a07 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 0)); //a0 a1 a2 a3 a4 a5 a6 a7
66 16 __m128i b07 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 1)); //b0 b1 b2 b3 b4 b5 b6 b7
67 16 __m128i c07 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 2)); //c0 c1 c2 c3 c4 c5 c6 c7
68 16 __m128i d07 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 3)); //d0 d1 d2 d3 d4 d5 d6 d7
69 16 __m128i e07 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 4)); //e0 e1 e2 e3 e4 e5 e6 e7
70 16 __m128i f07 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 5)); //f0 f1 f2 f3 f4 f5 f6 f7
71 16 __m128i g07 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 6)); //g0 g1 g2 g3 g4 g5 g6 g7
72 32 __m128i h07 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 7)); //h0 h1 h2 h3 h4 h5 h6 h7
73
74 16 __m128i ea07 = _mm_unpacklo_epi8(e07, a07); //e0 a0 e1 a1 e2 a2 e3 a3 e4 a4 e5 a5 e6 a6 e7 a7
75 16 __m128i fb07 = _mm_unpacklo_epi8(f07, b07); //f0 b0 f1 b1 f2 b2 f3 b3 f4 b4 f5 b5 f6 b6 f7 b7
76 16 __m128i gc07 = _mm_unpacklo_epi8(g07, c07); //g0 c0 g1 c1 g2 c2 g3 c3 g4 c4 g5 c5 g6 c6 g7 c7
77 16 __m128i hd07 = _mm_unpacklo_epi8(h07, d07); //h0 d0 h1 d1 h2 d2 h3 d3 h4 d4 h5 d5 h6 d6 h7 d7
78
79 16 __m128i geca03 = _mm_unpacklo_epi8(gc07, ea07); //g0 e0 c0 a0 g1 e1 c1 a1 g2 e2 c2 a2 g3 e3 c3 a3
80 16 __m128i geca47 = _mm_unpackhi_epi8(gc07, ea07); //g4 e4 c4 a4 g5 e5 c5 a5 g6 e6 c6 a6 g7 e7 c7 a7
81 16 __m128i hfdb03 = _mm_unpacklo_epi8(hd07, fb07); //h0 f0 d0 b0 h1 f1 d1 b1 h2 f2 d2 b2 h3 f3 d3 b3
82 16 __m128i hfdb47 = _mm_unpackhi_epi8(hd07, fb07); //h4 f4 d4 b4 h5 f5 d5 b5 h6 f6 d6 b6 h7 f7 d7 b7
83
84 16 __m128i hgfedcba01 = _mm_unpacklo_epi8(hfdb03, geca03); //h0 g0 f0 e0 d0 c0 b0 a0 h1 g1 f1 e1 d1 c1 b1 a1
85 16 __m128i hgfedcba23 = _mm_unpackhi_epi8(hfdb03, geca03); //h2 g2 f2 e2 d2 c2 b2 a2 h3 g3 f3 e3 d3 c3 b3 a3
86 16 __m128i hgfedcba45 = _mm_unpacklo_epi8(hfdb47, geca47); //h4 g4 f4 e4 d4 c4 b4 a4 h5 g5 f5 e5 d5 c5 b5 a5
87 16 __m128i hgfedcba67 = _mm_unpackhi_epi8(hfdb47, geca47); //h6 g6 f6 e6 d6 c6 b6 a6 h7 g7 f7 e7 d7 c7 b7 a7
88
89 16 _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + dst_pitch * 0), hgfedcba01);
90 16 _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + dst_pitch * 1), movehl(hgfedcba01));
91 16 _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + dst_pitch * 2), hgfedcba23);
92 16 _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + dst_pitch * 3), movehl(hgfedcba23));
93 16 _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + dst_pitch * 4), hgfedcba45);
94 16 _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + dst_pitch * 5), movehl(hgfedcba45));
95 16 _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + dst_pitch * 6), hgfedcba67);
96 16 _mm_storel_epi64(reinterpret_cast<__m128i*>(dstp + dst_pitch * 7), movehl(hgfedcba67));
97 16 }
98
99
100 2 void turn_right_plane_8_sse2(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
101 {
102 2 const BYTE* s0 = srcp;
103 2 int w = src_rowsize & ~7;
104 2 int h = src_height & ~7;
105
106
2/2
✓ Branch 120 → 3 taken 4 times.
✓ Branch 120 → 121 taken 2 times.
6 for (int y = 0; y < h; y += 8)
107 {
108 4 BYTE* d0 = dstp + src_height - 8 - y;
109
2/2
✓ Branch 118 → 4 taken 16 times.
✓ Branch 118 → 119 taken 4 times.
20 for (int x = 0; x < w; x += 8)
110 {
111 16 transpose_8x8x8_sse2(s0 + x, d0, src_pitch, dst_pitch);
112 16 d0 += dst_pitch * 8;
113 }
114 4 s0 += src_pitch * 8;
115 }
116
117
1/2
✓ Branch 121 → 122 taken 2 times.
✗ Branch 121 → 123 not taken.
2 if (src_rowsize != w)
118 {
119 2 turn_right_plane_8_c(srcp + w, dstp + w * dst_pitch, src_rowsize - w, src_height, src_pitch, dst_pitch);
120 }
121
122
1/2
✓ Branch 123 → 124 taken 2 times.
✗ Branch 123 → 125 not taken.
2 if (src_height != h)
123 {
124 2 turn_right_plane_8_c(srcp + h * src_pitch, dstp, src_rowsize, src_height - h, src_pitch, dst_pitch);
125 }
126 2 }
127
128
129 1 void turn_left_plane_8_sse2(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
130 {
131 1 turn_right_plane_8_sse2(srcp + (src_height - 1) * src_pitch, dstp + (src_rowsize - 1) * dst_pitch, src_rowsize, src_height, -src_pitch, -dst_pitch);
132 1 }
133
134
135
136 static AVS_FORCEINLINE void transpose_16x4x8_sse2(const BYTE* AVS_RESTRICT srcp, BYTE* AVS_RESTRICT dstp, const int src_pitch, const int dst_pitch)
137 {
138 16 __m128i a03 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 0)); //a0 a1 a2 a3
139 16 __m128i b03 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 1)); //b0 b1 b2 b3
140 16 __m128i c03 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 2)); //c0 c1 c2 c3
141 16 __m128i d03 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 3)); //d0 d1 d2 d3
142 16 __m128i e03 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 4)); //e0 e1 e2 e3
143 16 __m128i f03 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 5)); //f0 f1 f2 f3
144 16 __m128i g03 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 6)); //g0 g1 g2 g3
145 32 __m128i h03 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(srcp + src_pitch * 7)); //h0 h1 h2 h3
146
147 16 __m128i ae03 = _mm_unpacklo_epi16(a03, e03); //a0 e0 a1 e1 a2 e2 a3 e3
148 16 __m128i bf03 = _mm_unpacklo_epi16(b03, f03); //b0 f0 b1 f1 b2 f2 b3 f3
149 16 __m128i cg03 = _mm_unpacklo_epi16(c03, g03); //c0 g0 c1 g1 c2 g2 c3 g3
150 16 __m128i dh03 = _mm_unpacklo_epi16(d03, h03); //d0 h0 d1 h1 d2 h2 d3 h3
151
152 16 __m128i aceg01 = _mm_unpacklo_epi16(ae03, cg03); //a0 c0 e0 g0 a1 c1 e1 g1
153 16 __m128i aceg23 = _mm_unpackhi_epi16(ae03, cg03); //a2 c2 e2 g2 a3 c3 e3 g3
154 16 __m128i bdfh01 = _mm_unpacklo_epi16(bf03, dh03); //b0 d0 f0 h0 b1 d1 f1 h1
155 16 __m128i bdfh23 = _mm_unpackhi_epi16(bf03, dh03); //b2 d2 f2 h2 b3 d3 f3 h3
156
157 16 __m128i abcdefgh0 = _mm_unpacklo_epi16(aceg01, bdfh01); //a0 b0 c0 d0 e0 f0 g0 h0
158 16 __m128i abcdefgh1 = _mm_unpackhi_epi16(aceg01, bdfh01); //a1 b1 c1 d1 e1 f1 g1 h1
159 16 __m128i abcdefgh2 = _mm_unpacklo_epi16(aceg23, bdfh23); //a2 b2 c2 d2 e2 f2 g2 h2
160 16 __m128i abcdefgh3 = _mm_unpackhi_epi16(aceg23, bdfh23); //a3 b3 c3 d3 e3 f3 g3 h3
161
162 _mm_store_si128(reinterpret_cast<__m128i*>(dstp + dst_pitch * 0), abcdefgh0);
163 16 _mm_store_si128(reinterpret_cast<__m128i*>(dstp + dst_pitch * 1), abcdefgh1);
164 16 _mm_store_si128(reinterpret_cast<__m128i*>(dstp + dst_pitch * 2), abcdefgh2);
165 16 _mm_store_si128(reinterpret_cast<__m128i*>(dstp + dst_pitch * 3), abcdefgh3);
166 16 }
167
168
169 2 void turn_right_plane_16_sse2(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
170 {
171 2 const BYTE* s0 = srcp + src_pitch * (src_height - 1);
172 2 int w = src_rowsize & ~7;
173 2 int h = src_height & ~7;
174
175
2/2
✓ Branch 84 → 3 taken 4 times.
✓ Branch 84 → 85 taken 2 times.
6 for (int y = 0; y < h; y += 8)
176 {
177 4 BYTE* d0 = dstp + y * 2;
178
2/2
✓ Branch 82 → 4 taken 16 times.
✓ Branch 82 → 83 taken 4 times.
20 for (int x = 0; x < w; x += 8)
179 {
180 16 transpose_16x4x8_sse2(s0 + x, d0, -src_pitch, dst_pitch);
181 16 d0 += 4 * dst_pitch;
182 }
183 4 s0 -= 8 * src_pitch;
184 }
185
1/2
✓ Branch 85 → 86 taken 2 times.
✗ Branch 85 → 87 not taken.
2 if (src_rowsize != w)
186 {
187 2 turn_right_plane_16_c(srcp + w, dstp + dst_pitch * w / 2, src_rowsize - w, src_height, src_pitch, dst_pitch);
188 }
189
190
1/2
✓ Branch 87 → 88 taken 2 times.
✗ Branch 87 → 89 not taken.
2 if (src_height != h)
191 {
192 2 turn_right_plane_16_c(srcp, dstp + h * 2, src_rowsize, src_height - h, src_pitch, dst_pitch);
193 }
194 2 }
195
196
197 1 void turn_left_plane_16_sse2(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
198 {
199 1 turn_right_plane_16_sse2(srcp + src_pitch * (src_height - 1), dstp + dst_pitch * (src_rowsize / 2 - 1), src_rowsize, src_height, -src_pitch, -dst_pitch);
200 1 }
201
202
203
204 static AVS_FORCEINLINE void transpose_32x4x4_sse2(const BYTE* AVS_RESTRICT srcp, BYTE* AVS_RESTRICT dstp, const int src_pitch, const int dst_pitch)
205 {
206 16 __m128i a03 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp + src_pitch * 0)); //a0 a1 a2 a3
207 16 __m128i b03 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp + src_pitch * 1)); //b0 b1 b2 b3
208 16 __m128i c03 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp + src_pitch * 2)); //c0 c1 c2 c3
209 32 __m128i d03 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(srcp + src_pitch * 3)); //d0 d1 d2 d3
210
211 16 __m128i ac01 = _mm_unpacklo_epi32(a03, c03); //a0 c0 a1 c1
212 16 __m128i ac23 = _mm_unpackhi_epi32(a03, c03); //a2 c2 a3 c3
213 16 __m128i bd01 = _mm_unpacklo_epi32(b03, d03); //b0 d0 b1 d1
214 16 __m128i bd23 = _mm_unpackhi_epi32(b03, d03); //b2 d2 b3 d3
215
216 16 __m128i abcd0 = _mm_unpacklo_epi32(ac01, bd01); //a0 b0 c0 d0
217 16 __m128i abcd1 = _mm_unpackhi_epi32(ac01, bd01); //a1 b1 c1 d1
218 16 __m128i abcd2 = _mm_unpacklo_epi32(ac23, bd23); //a2 b2 c2 d2
219 16 __m128i abcd3 = _mm_unpackhi_epi32(ac23, bd23); //a3 b3 c3 d3
220
221 _mm_storeu_si128(reinterpret_cast<__m128i*>(dstp + dst_pitch * 0), abcd0);
222 16 _mm_storeu_si128(reinterpret_cast<__m128i*>(dstp + dst_pitch * 1), abcd1);
223 16 _mm_storeu_si128(reinterpret_cast<__m128i*>(dstp + dst_pitch * 2), abcd2);
224 16 _mm_storeu_si128(reinterpret_cast<__m128i*>(dstp + dst_pitch * 3), abcd3);
225 16 }
226
227
228 4 void turn_right_plane_32_sse2(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
229 {
230 4 const BYTE* s0 = srcp + src_pitch * (src_height - 1);
231 4 int w = src_rowsize & ~15;
232 4 int h = src_height & ~3;
233
234
2/2
✓ Branch 36 → 3 taken 8 times.
✓ Branch 36 → 37 taken 4 times.
12 for (int y = 0; y < h; y += 4)
235 {
236 8 BYTE* d0 = dstp + y * 4;
237
2/2
✓ Branch 34 → 4 taken 16 times.
✓ Branch 34 → 35 taken 8 times.
24 for (int x = 0; x < w; x += 16)
238 {
239 16 transpose_32x4x4_sse2(s0 + x, d0, -src_pitch, dst_pitch);
240 16 d0 += 4 * dst_pitch;
241 }
242 8 s0 -= 4 * src_pitch;
243 }
244
245
1/2
✓ Branch 37 → 38 taken 4 times.
✗ Branch 37 → 39 not taken.
4 if (src_rowsize != w)
246 {
247 4 turn_right_plane_32_c(srcp + w, dstp + w / 4 * dst_pitch, src_rowsize - w, src_height, src_pitch, dst_pitch);
248 }
249
250
1/2
✓ Branch 39 → 40 taken 4 times.
✗ Branch 39 → 41 not taken.
4 if (src_height != h)
251 {
252 4 turn_right_plane_32_c(srcp, dstp + h * 4, src_rowsize, src_height - h, src_pitch, dst_pitch);
253 }
254 4 }
255
256 2 void turn_left_plane_32_sse2(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
257 {
258 2 turn_right_plane_32_sse2(srcp + src_pitch * (src_height - 1), dstp + dst_pitch * (src_rowsize / 4 - 1), src_rowsize, src_height, -src_pitch, -dst_pitch);
259 2 }
260
261
262 // on RGB, TurnLeft and TurnRight are reversed.
263
264 1 void turn_left_rgb32_sse2(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
265 {
266 1 turn_right_plane_32_sse2(srcp, dstp, src_rowsize, src_height, src_pitch, dst_pitch);
267 1 }
268
269
270 1 void turn_right_rgb32_sse2(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
271 {
272 1 turn_left_plane_32_sse2(srcp, dstp, src_rowsize, src_height, src_pitch, dst_pitch);
273 1 }
274
275
276
277
278 2 static inline void turn_right_plane_64_sse2(const BYTE* AVS_RESTRICT srcp, BYTE* AVS_RESTRICT dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
279 {
280 2 const BYTE* s0 = srcp + src_pitch * (src_height - 1);
281 2 int w = src_rowsize & ~15;
282 2 int h = src_height & ~1;
283
284
2/2
✓ Branch 17 → 3 taken 6 times.
✓ Branch 17 → 18 taken 2 times.
8 for (int y = 0; y < h; y += 2)
285 {
286 6 BYTE* d0 = dstp + y * 8;
287
2/2
✓ Branch 15 → 4 taken 12 times.
✓ Branch 15 → 16 taken 6 times.
18 for (int x = 0; x < w; x += 16)
288 {
289 12 __m128i a01 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s0 + x)); // a0 a1
290 24 __m128i b01 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s0 + x - src_pitch)); // b0 b1
291 12 __m128i ab0 = _mm_unpacklo_epi64(a01, b01); // a0 b0
292 12 __m128i ab1 = _mm_unpackhi_epi64(a01, b01); // a1 b1
293 _mm_storeu_si128(reinterpret_cast<__m128i*>(d0), ab0);
294 12 _mm_storeu_si128(reinterpret_cast<__m128i*>(d0 + dst_pitch), ab1);
295 12 d0 += 2 * dst_pitch;
296 }
297 6 s0 -= 2 * src_pitch;
298 }
299
300
1/2
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 20 not taken.
2 if (src_rowsize != w)
301 {
302 2 turn_right_plane_c<uint64_t>(srcp + w, dstp + w / 8 * dst_pitch, 8, src_height, src_pitch, dst_pitch);
303 }
304
305
1/2
✓ Branch 20 → 21 taken 2 times.
✗ Branch 20 → 22 not taken.
2 if (src_height != h)
306 {
307 2 turn_right_plane_c<uint64_t>(srcp, dstp + h * 8, src_rowsize, 1, src_pitch, dst_pitch);
308 }
309 2 }
310
311
312 1 void turn_left_rgb64_sse2(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
313 {
314 1 turn_right_plane_64_sse2(srcp, dstp, src_rowsize, src_height, src_pitch, dst_pitch);
315 1 }
316
317
318 1 void turn_right_rgb64_sse2(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
319 {
320 1 turn_right_plane_64_sse2(srcp + src_pitch * (src_height - 1), dstp + dst_pitch * (src_rowsize / 8 - 1), src_rowsize, src_height, -src_pitch, -dst_pitch);
321 1 }
322
323
324
325
326
327 template <typename T>
328 4 void turn_180_plane_sse2(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
329 {
330 4 const BYTE* AVS_RESTRICT s0 = srcp;
331 4 BYTE* AVS_RESTRICT d0 = dstp + dst_pitch * (src_height - 1) + src_rowsize - 16;
332 4 const int w = src_rowsize & ~15;
333
334
8/8
void turn_180_plane_sse2<unsigned char>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 16 → 3 taken 9 times.
✓ Branch 16 → 17 taken 1 time.
void turn_180_plane_sse2<unsigned int>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 10 → 3 taken 7 times.
✓ Branch 10 → 11 taken 1 time.
void turn_180_plane_sse2<unsigned long>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 10 → 3 taken 7 times.
✓ Branch 10 → 11 taken 1 time.
void turn_180_plane_sse2<unsigned short>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 10 → 3 taken 7 times.
✓ Branch 10 → 11 taken 1 time.
34 for (int y = 0; y < src_height; ++y)
335 {
336
8/8
void turn_180_plane_sse2<unsigned char>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 14 → 4 taken 18 times.
✓ Branch 14 → 15 taken 9 times.
void turn_180_plane_sse2<unsigned int>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 8 → 4 taken 14 times.
✓ Branch 8 → 9 taken 7 times.
void turn_180_plane_sse2<unsigned long>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 8 → 4 taken 14 times.
✓ Branch 8 → 9 taken 7 times.
void turn_180_plane_sse2<unsigned short>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 8 → 4 taken 14 times.
✓ Branch 8 → 9 taken 7 times.
90 for (int x = 0; x < w; x += 16)
337 {
338 60 __m128i src = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s0 + x));
339 if constexpr (sizeof(T) == 8) // RGB64
340 14 src = _mm_shuffle_epi32(src, _MM_SHUFFLE(1, 0, 3, 2));
341 else if constexpr (sizeof(T) == 4) // RGB32
342 14 src = _mm_shuffle_epi32(src, _MM_SHUFFLE(0, 1, 2, 3));
343 else { // uint16_t, uint8_t
344 32 src = _mm_shuffle_epi32(src, _MM_SHUFFLE(0, 1, 2, 3));
345 32 src = _mm_shufflelo_epi16(src, _MM_SHUFFLE(2, 3, 0, 1));
346 32 src = _mm_shufflehi_epi16(src, _MM_SHUFFLE(2, 3, 0, 1));
347
348 if constexpr (sizeof(T) == 1)
349 36 src = _mm_or_si128(_mm_srli_epi16(src, 8), _mm_slli_epi16(src, 8));
350 }
351 60 _mm_storeu_si128(reinterpret_cast<__m128i*>(d0 - x), src);
352 }
353 30 s0 += src_pitch;
354 30 d0 -= dst_pitch;
355 }
356
357
4/8
void turn_180_plane_sse2<unsigned char>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 19 not taken.
void turn_180_plane_sse2<unsigned int>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 13 not taken.
void turn_180_plane_sse2<unsigned long>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 13 not taken.
void turn_180_plane_sse2<unsigned short>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 13 not taken.
4 if (src_rowsize != w)
358 {
359 4 turn_180_plane_c<T>(srcp + w, dstp, src_rowsize - w, src_height, src_pitch, dst_pitch);
360 }
361 4 }
362
363 // instantiate
364 template void turn_180_plane_sse2<uint8_t>(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch);
365 template void turn_180_plane_sse2<uint16_t>(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch);
366 template void turn_180_plane_sse2<uint32_t>(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch);
367 template void turn_180_plane_sse2<uint64_t>(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch);
368
369
370 template <typename T>
371 #if defined(GCC) || defined(CLANG)
372 __attribute__((__target__("ssse3")))
373 #endif
374 2 void turn_180_plane_ssse3(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch)
375 {
376 2 const BYTE* s0 = srcp;
377 2 BYTE* d0 = dstp + dst_pitch * (src_height - 1) + src_rowsize - 16;
378 2 const int w = src_rowsize & ~15;
379
380
4/4
void turn_180_plane_ssse3<unsigned char>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 14 → 3 taken 9 times.
✓ Branch 14 → 15 taken 1 time.
void turn_180_plane_ssse3<unsigned short>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 14 → 3 taken 7 times.
✓ Branch 14 → 15 taken 1 time.
18 for (int y = 0; y < src_height; ++y)
381 {
382
4/4
void turn_180_plane_ssse3<unsigned char>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 12 → 4 taken 18 times.
✓ Branch 12 → 13 taken 9 times.
void turn_180_plane_ssse3<unsigned short>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 12 → 4 taken 14 times.
✓ Branch 12 → 13 taken 7 times.
48 for (int x = 0; x < w; x += 16)
383 {
384 64 __m128i src = _mm_loadu_si128(reinterpret_cast<const __m128i*>(s0 + x));
385 if constexpr (sizeof(T) == 8) // RGB64
386 src = _mm_shuffle_epi32(src, _MM_SHUFFLE(1, 0, 3, 2));
387 else if constexpr (sizeof(T) == 4) // RGB32
388 src = _mm_shuffle_epi32(src, _MM_SHUFFLE(0, 1, 2, 3));
389 else { // uint16_t, uint8_t
390 // SSSE3
391 __m128i pshufb_mask;
392 if constexpr (sizeof(T) == 1)
393 18 pshufb_mask = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
394 else if constexpr (sizeof(T) == 2)
395 14 pshufb_mask = _mm_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14);
396
397 32 src = _mm_shuffle_epi8(src, pshufb_mask);
398 }
399 32 _mm_storeu_si128(reinterpret_cast<__m128i*>(d0 - x), src);
400 }
401 16 s0 += src_pitch;
402 16 d0 -= dst_pitch;
403 }
404
405
2/4
void turn_180_plane_ssse3<unsigned char>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 17 not taken.
void turn_180_plane_ssse3<unsigned short>(unsigned char const*, unsigned char*, int, int, int, int):
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 17 not taken.
2 if (src_rowsize != w)
406 {
407 2 turn_180_plane_c<T>(srcp + w, dstp, src_rowsize - w, src_height, src_pitch, dst_pitch);
408 }
409 2 }
410
411 // instantiate
412 template void turn_180_plane_ssse3<uint8_t>(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch);
413 template void turn_180_plane_ssse3<uint16_t>(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch);
414