16 #ifndef included_vector_avx2_h
17 #define included_vector_avx2_h
20 #include <x86intrin.h>
23 #define foreach_avx2_vec256i \
24 _(i,8,32,epi8) _(i,16,16,epi16) _(i,32,8,epi32) _(i,64,4,epi64)
25 #define foreach_avx2_vec256u \
26 _(u,8,32,epi8) _(u,16,16,epi16) _(u,32,8,epi32) _(u,64,4,epi64)
27 #define foreach_avx2_vec256f \
28 _(f,32,8,ps) _(f,64,4,pd)
30 #define _mm256_set1_epi64 _mm256_set1_epi64x
34 #define _(t, s, c, i) \
35 static_always_inline t##s##x##c \
36 t##s##x##c##_splat (t##s x) \
37 { return (t##s##x##c) _mm256_set1_##i (x); } \
39 static_always_inline t##s##x##c \
40 t##s##x##c##_load_unaligned (void *p) \
41 { return (t##s##x##c) _mm256_loadu_si256 (p); } \
43 static_always_inline void \
44 t##s##x##c##_store_unaligned (t##s##x##c v, void *p) \
45 { _mm256_storeu_si256 ((__m256i *) p, (__m256i) v); } \
47 static_always_inline int \
48 t##s##x##c##_is_all_zero (t##s##x##c x) \
49 { return _mm256_testz_si256 ((__m256i) x, (__m256i) x); } \
51 static_always_inline int \
52 t##s##x##c##_is_equal (t##s##x##c a, t##s##x##c b) \
53 { return t##s##x##c##_is_all_zero (a ^ b); } \
55 static_always_inline int \
56 t##s##x##c##_is_all_equal (t##s##x##c v, t##s x) \
57 { return t##s##x##c##_is_equal (v, t##s##x##c##_splat (x)); } \
59 static_always_inline t##s##x##c \
60 t##s##x##c##_interleave_lo (t##s##x##c a, t##s##x##c b) \
61 { return (t##s##x##c) _mm256_unpacklo_##i ((__m256i) a, (__m256i) b); } \
63 static_always_inline t##s##x##c \
64 t##s##x##c##_interleave_hi (t##s##x##c a, t##s##x##c b) \
65 { return (t##s##x##c) _mm256_unpackhi_##i ((__m256i) a, (__m256i) b); } \
75 return (u32x8) _mm256_permutevar8x32_epi32 ((__m256i) v, (__m256i) idx);
78 #define u64x4_permute(v, m0, m1, m2, m3) \
79 (u64x4) _mm256_permute4x64_epi64 ( \
80 (__m256i) v, ((m0) | (m1) << 2 | (m2) << 4 | (m3) << 6))
86 t2##_extract_lo (t2 v) \
87 { return (t1) _mm256_extracti128_si256 ((__m256i) v, 0); } \
90 t2##_extract_hi (t2 v) \
91 { return (t1) _mm256_extracti128_si256 ((__m256i) v, 1); } \
94 t2##_insert_lo (t2 v1, t1 v2) \
95 { return (t2) _mm256_inserti128_si256 ((__m256i) v1, (__m128i) v2, 0); }\
98 t2##_insert_hi (t2 v1, t1 v2) \
99 { return (t2) _mm256_inserti128_si256 ((__m256i) v1, (__m128i) v2, 1); }\
109 #define _(f, t, fn) \
110 always_inline t t##_pack (f lo, f hi) \
112 return (t) fn ((__m256i) lo, (__m256i) hi); \
115 _ (
i16x16, i8x32, _mm256_packs_epi16)
117 _ (i32x8,
i16x16, _mm256_packs_epi32)
125 return _mm256_movemask_epi8 ((__m256i) v);
131 return _mm256_movemask_epi8 ((__m256i) v);
137 static_always_inline t \
139 { return (t) _mm256_cvt##i ((__m128i) x); }
141 _(
u16x8, u32x8, epu16_epi32)
145 _(
u8x16, u32x8, epu8_epi32)
147 _(
i16x8, i32x8, epi16_epi32)
151 _(i8x16, i32x8, epi8_epi32)
152 _(i8x16,
i64x4, epi8_epi64)
160 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8,
161 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8,
163 return (
u64x4) _mm256_shuffle_epi8 ((__m256i) v, (__m256i) swap);
170 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12,
171 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
173 return (u32x8) _mm256_shuffle_epi8 ((__m256i) v, (__m256i) swap);
180 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14,
181 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14
183 return (
u16x16) _mm256_shuffle_epi8 ((__m256i) v, (__m256i) swap);
189 return (
u8x32) _mm256_shuffle_epi8 ((__m256i) v, (__m256i) m);
192 #define u8x32_align_right(a, b, imm) \
193 (u8x32) _mm256_alignr_epi8 ((__m256i) a, (__m256i) b, imm)
200 return sum8[0] + sum8[4];
206 return (u32x8) _mm256_hadd_epi32 ((__m256i) v1, (__m256i) v2);
212 const u16x16 masks[17] = {
218 {-1, -1, -1, -1, -1},
219 {-1, -1, -1, -1, -1, -1},
220 {-1, -1, -1, -1, -1, -1, -1},
221 {-1, -1, -1, -1, -1, -1, -1, -1},
222 {-1, -1, -1, -1, -1, -1, -1, -1, -1},
223 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
224 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
225 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
226 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
227 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
228 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
229 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
234 return v & masks[16 - n_last];
240 return (f32x8) _mm256_cvtepi32_ps ((__m256i) v);
246 return (u32x8) _mm256_cvttps_epi32 ((__m256) v);
249 #define u32x8_blend(a,b,m) \
250 (u32x8) _mm256_blend_epi32 ((__m256i) a, (__m256i) b, m)
252 #define u16x16_blend(v1, v2, mask) \
253 (u16x16) _mm256_blend_epi16 ((__m256i) (v1), (__m256i) (v2), mask)
265 u32x8_gather (
void *p0,
void *p1,
void *p2,
void *p3,
void *p4,
void *p5,
287 void *p5,
void *p6,
void *p7)
314 return (
u8x32) _mm256_cmpgt_epi8 ((__m256i) v1, (__m256i) v2);
320 return (
u8x32) _mm256_blendv_epi8 ((__m256i) v1, (__m256i) v2,
324 #define u32x8_permute_lanes(a, b, m) \
325 (u32x8) _mm256_permute2x128_si256 ((__m256i) a, (__m256i) b, m)
326 #define u64x4_permute_lanes(a, b, m) \
327 (u64x4) _mm256_permute2x128_si256 ((__m256i) a, (__m256i) b, m)
332 return (u32x8) _mm256_min_epu32 ((__m256i)
a, (__m256i)
b);
339 u32x8_extract_hi (v)));
347 r[0] = (
u64x4) u32x8_interleave_lo (
a[0],
a[1]);
348 r[1] = (
u64x4) u32x8_interleave_hi (
a[0],
a[1]);
349 r[2] = (
u64x4) u32x8_interleave_lo (
a[2],
a[3]);
350 r[3] = (
u64x4) u32x8_interleave_hi (
a[2],
a[3]);
351 r[4] = (
u64x4) u32x8_interleave_lo (
a[4],
a[5]);
352 r[5] = (
u64x4) u32x8_interleave_hi (
a[4],
a[5]);
353 r[6] = (
u64x4) u32x8_interleave_lo (
a[6],
a[7]);
354 r[7] = (
u64x4) u32x8_interleave_hi (
a[6],
a[7]);
356 x = u64x4_interleave_lo (
r[0],
r[2]);
357 y = u64x4_interleave_lo (
r[4],
r[6]);
361 x = u64x4_interleave_hi (
r[0],
r[2]);
362 y = u64x4_interleave_hi (
r[4],
r[6]);
366 x = u64x4_interleave_lo (
r[1],
r[3]);
367 y = u64x4_interleave_lo (
r[5],
r[7]);
371 x = u64x4_interleave_hi (
r[1],
r[3]);
372 y = u64x4_interleave_hi (
r[5],
r[7]);
382 r[0] = u64x4_interleave_lo (
a[0],
a[1]);
383 r[1] = u64x4_interleave_hi (
a[0],
a[1]);
384 r[2] = u64x4_interleave_lo (
a[2],
a[3]);
385 r[3] = u64x4_interleave_hi (
a[2],
a[3]);