Version
menu_open
Wwise SDK 2023.1.4
AkSimdAvx.h
Go to the documentation of this file.
1 /*******************************************************************************
2 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
3 released in source code form as part of the SDK installer package.
4 
5 Commercial License Usage
6 
7 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
8 may use this file in accordance with the end user license agreement provided
9 with the software or, alternatively, in accordance with the terms contained in a
10 written agreement between you and Audiokinetic Inc.
11 
12 Apache License Usage
13 
14 Alternatively, this file may be used under the Apache License, Version 2.0 (the
15 "Apache License"); you may not use this file except in compliance with the
16 Apache License. You may obtain a copy of the Apache License at
17 http://www.apache.org/licenses/LICENSE-2.0.
18 
19 Unless required by applicable law or agreed to in writing, software distributed
20 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
21 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
22 the specific language governing permissions and limitations under the License.
23 
24  Copyright (c) 2024 Audiokinetic Inc.
25 *******************************************************************************/
26 
27 // AkSimdAvx.h
28 
29 /// \file
30 /// AKSIMD - AVX implementation
31 
32 #ifndef _AK_SIMD_AVX_H_
33 #define _AK_SIMD_AVX_H_
34 
37 
38 #if defined(AKSIMD_AVX_SUPPORTED)
39 
40 #include <immintrin.h>
41 
42 ////////////////////////////////////////////////////////////////////////
43 /// @name AKSIMD types
44 //@{
45 
46 typedef float AKSIMD_F32; ///< 32-bit float
47 typedef __m256 AKSIMD_V8F32; ///< Vector of 8 32-bit floats
48 typedef __m256d AKSIMD_V4F64; ///< Vector of 4 64-bit floats
49 typedef __m256i AKSIMD_V8I32; ///< Vector of 8 32-bit signed integers
50 typedef AKSIMD_V8F32 AKSIMD_V8COND; ///< Vector of 8 comparison results
51 typedef AKSIMD_V8F32 AKSIMD_V8FCOND; ///< Vector of 8 comparison results
52 typedef AKSIMD_V8I32 AKSIMD_V8ICOND;
53 
54 //@}
55 ////////////////////////////////////////////////////////////////////////
56 
57 
58 ////////////////////////////////////////////////////////////////////////
59 /// @name AKSIMD loading / setting
60 //@{
61 
62 /// Loads eight single-precision floating-point values from memory.
63 /// The address does not need to be 32-byte aligned (see _mm_loadu_ps).
64 /// On every modern x86 processor this performs the same as an aligned load.
65 #define AKSIMD_LOAD_V8F32( __addr__ ) _mm256_loadu_ps( (AkReal32*)(__addr__) )
66 
67 /// Loads a single single-precision, floating-point value, copying it into
68 /// all eight words (see _mm_load1_ps, _mm_load_ps1)
69 #define AKSIMD_LOAD1_V8F32( __scalar__ ) _mm256_broadcast_ss( &(__scalar__) )
70 
71 /// Loads a single double-precision, floating-point value, and copies it into
72 /// all elements of the vector (see _mm_load_pd1)
73 #define AKSIMD_LOAD1_V4F64( __scalar__ ) _mm256_castpd_ps(_mm256_broadcast_sd( &(__scalar__) ))
74 
75 /// Sets the eight single-precision, floating-point values to in_value (see
76 /// _mm_set1_ps, _mm_set_ps1)
77 #define AKSIMD_SET_V8F32( __scalar__ ) _mm256_set1_ps( (__scalar__) )
78 
79 /// Populates the full vector with the 8 floating point values provided
80 #define AKSIMD_SETV_V8F32( _h, _g, _f, _e, _d, _c, _b, _a ) _mm256_set_ps( (_h), (_g), (_f), (_e), (_d), (_c), (_b), (_a) )
81 
82 /// Populates the full vector with the 4 double-prec floating point values provided
83 #define AKSIMD_SETV_V4F64( _d, _c, _b, _a ) _mm256_castpd_ps( _mm256_set_pd( (_d), (_c), (_b), (_a) ) )
84 
85 /// Sets the eight single-precision, floating-point values to zero (see
86 /// _mm_setzero_ps)
87 #define AKSIMD_SETZERO_V8F32() _mm256_setzero_ps()
88 
89 /// Loads a single-precision, floating-point value into the low word
90 /// and clears the upper seven words.
91 /// r0 := *p; r1...r7 := 0.0 (see _mm_load_ss)
92 #define AKSIMD_LOAD_SS_V8F32( __addr__ ) _mm256_zextps128_ps256(_mm_load_ss( (__addr__) ))
93 
94 /// Loads the two m128i's provided into the output m256i a
95 /// Note that this should be utilized instead of, e.g. adding & utilizing a macro "AKSIMD_INSERT_V8I32(m, i, idx)"
96 /// Because there is no direct corresponding instruction for an insert into 256. You should load into 128s
97 /// and use that. Some compilers do not handle _mm256_insert_epi32 (etc) well, or even include them
98 #define AKSIMD_SETV_V2F128( m2, m1) _mm256_set_m128(m2, m1)
99 
100 #define AKSIMD_INSERT_V2F128( a, m128, idx) _mm256_insertf128_ps(a, m128, idx)
101 
102 #define AKSIMD_GETELEMENT_V8F32( __vName, __num__ ) ((AkReal32*)&(__vName))[(__num__)]
103 #define AKSIMD_GETELEMENT_V4F64( __vName, __num__ ) ((AkReal64*)&(__vName))[(__num__)]
104 #define AKSIMD_GETELEMENT_V8I32( __vName, __num__ ) ((AkInt32*)&(__vName))[(__num__)]
105 #define AKSIMD_GETELEMENT_V4I64( __vName, __num__ ) ((AkInt64*)&(__vName))[(__num__)]
106 
107 //@}
108 ////////////////////////////////////////////////////////////////////////
109 
110 
111 ////////////////////////////////////////////////////////////////////////
112 /// @name AKSIMD storing
113 //@{
114 
115 /// Stores eight single-precision, floating-point values.
116 /// The address does not need to be 32-byte aligned (see _mm_storeu_ps).
117 /// On every modern x86 processor this performs the same as an aligned store.
118 #define AKSIMD_STORE_V8F32( __addr__, __vec__ ) _mm256_storeu_ps( (AkReal32*)(__addr__), (__vec__) )
119 
120 /// Stores the lower single-precision, floating-point value.
121 /// *p := a0 (see _mm_store_ss)
122 #define AKSIMD_STORE1_V8F32( __addr__, __vec__ ) _mm_store_ss( (AkReal32*)(__addr__), _mm256_castps256_ps128( (__vec__) ) )
123 
124 //@}
125 ////////////////////////////////////////////////////////////////////////
126 
127 ////////////////////////////////////////////////////////////////////////
128 /// @name AKSIMD shuffling
129 //@{
130 
131 /// Selects eight specific single-precision, floating-point values from
132 /// a and b, based on the mask i within 128-bit lanes (see _mm256_shuffle_ps)
133 /// This means that the AKSIMD_SHUFFLE operand still picks 1 of 4 32b components
134 /// inside of each of the 2 128b lanes.
135 // Usage: AKSIMD_SHUFFLE_V8F32( vec1, vec2, AKSIMD_SHUFFLE( z, y, x, w ) )
136 #define AKSIMD_SHUFFLE_V8F32( a, b, i ) _mm256_shuffle_ps( a, b, i )
137 
138 /// For each 128b lane, Swap the 2 lower floats together and the 2 higher floats together. ( h g f e d c b a -> g h e f c d a b )
139 #define AKSIMD_SHUFFLE_V8_BADC( __a__ ) AKSIMD_SHUFFLE_V8F32( (__a__), (__a__), AKSIMD_SHUFFLE(2,3,0,1))
140 
141 /// For each 128b lane, Swap the 2 lower floats with the 2 higher floats. ( h g f e d c b a -> f e h g b a d c )
142 #define AKSIMD_SHUFFLE_V8_CDAB( __a__ ) AKSIMD_SHUFFLE_V8F32( (__a__), (__a__), AKSIMD_SHUFFLE(1,0,3,2))
143 
144 /// For each 128b lane, barrel-shift all floats by one. ( h g f e d c b a -> e h g f a d c b )
145 #define AKSIMD_SHUFFLE_V8_BCDA( __a__ ) AKSIMD_SHUFFLE_V8F32( (__a__), (__a__), AKSIMD_SHUFFLE(0,3,2,1))
146 
147 /// For each 128b lane, duplicates the odd items into the even items ( h g f e d c b a -> h h f f d d b b )
148 #define AKSIMD_DUP_V8_ODD(__vv) AKSIMD_SHUFFLE_V8F32(__vv, __vv, AKSIMD_SHUFFLE(3,3,1,1))
149 
150 /// For each 128b lane, duplicates the even items into the odd items ( h g f e d c b a -> g g e e c c a a )
151 #define AKSIMD_DUP_V8_EVEN(__vv) AKSIMD_SHUFFLE_V8F32(__vv, __vv, AKSIMD_SHUFFLE(2,2,0,0))
152 
153 /// Shuffle 32-bit integers in a within 128-bit lanes using the control in i, and return the results
154 #define AKSIMD_SHUFFLE_V8I32( a, b, i ) _mm256_castps_si256(_mm256_shuffle_ps( _mm256_castsi256_ps(a), _mm256_castsi256_ps(b), i ))
155 
156 /// single-precision (32-bit) floating-point elements in a within 128-bit lanes using the control in b, and store the results in dst.
157 #define AKSIMD_PERMUTEVAR_V8F32(a, b) _mm256_permutevar_ps(a, b)
158 
159 // Macro for selection parameter for AKSIMD_PERMUTE_2X128_V8F32()
160 #define AKSIMD_PERMUTE128( l1, l0 ) (((l1) << 4) | (l0))
161 
162 /// For each 128b lane, select one of the four input 128b lanes across a and b,
163 /// based on the mask i. AKSIMD_SHUFFLE can still be directly used as a control
164 #define AKSIMD_PERMUTE_2X128_V8F32( a, b, i ) _mm256_permute2f128_ps(a, b, i)
165 
166 /// Selects the lower of each of the 128b lanes in a and b to be the result ( B A ), ( D C ) -> ( C A )
167 #define AKSIMD_DEINTERLEAVELANES_LO_V8F32( a, b ) AKSIMD_PERMUTE_2X128_V8F32(a, b, AKSIMD_PERMUTE128(2, 0))
168 
169 /// Selects the higher of each of the 128b lanes in a and b to be the result ( B A ), ( D C) -> ( D B )
170 #define AKSIMD_DEINTERLEAVELANES_HI_V8F32( a, b ) AKSIMD_PERMUTE_2X128_V8F32(a, b, AKSIMD_PERMUTE128(3, 1))
171 
172 /// Gets the specified 128b lane from a and stores it in the result
173 #define AKSIMD_EXTRACT_V2F128( a, i ) _mm256_extractf128_ps(a, i)
174 
175 /// Rotate the 4x4 vectors in each of the 128b lanes. After rotation:
176 /// A[7:0] = D[4] C[4] B[4] A[4] D[0] C[0] B[0] A[0]
177 /// B[7:0] = D[5] C[5] B[5] A[5] D[1] C[1] B[1] A[1]
178 /// C[7:0] = D[6] C[6] B[6] A[6] D[2] C[2] B[2] A[2]
179 /// D[7:0] = D[7] C[7] B[7] A[7] D[3] C[3] B[3] A[3]
180 AkForceInline void AKSIMD_TRANSPOSE8X4_V8F32(AKSIMD_V8F32& A, AKSIMD_V8F32& B, AKSIMD_V8F32& C, AKSIMD_V8F32& D)
181 {
182  AKSIMD_V8F32 tmp1, tmp2, tmp3, tmp4;
183  tmp1 = AKSIMD_SHUFFLE_V8F32(A, B, AKSIMD_SHUFFLE(1,0,1,0));
184  tmp2 = AKSIMD_SHUFFLE_V8F32(A, B, AKSIMD_SHUFFLE(3,2,3,2));
185  tmp3 = AKSIMD_SHUFFLE_V8F32(C, D, AKSIMD_SHUFFLE(1,0,1,0));
186  tmp4 = AKSIMD_SHUFFLE_V8F32(C, D, AKSIMD_SHUFFLE(3,2,3,2));
187 
188  A = AKSIMD_SHUFFLE_V8F32(tmp1, tmp3, AKSIMD_SHUFFLE(2, 0, 2, 0));
189  B = AKSIMD_SHUFFLE_V8F32(tmp1, tmp3, AKSIMD_SHUFFLE(3, 1, 3, 1));
190  C = AKSIMD_SHUFFLE_V8F32(tmp2, tmp4, AKSIMD_SHUFFLE(2, 0, 2, 0));
191  D = AKSIMD_SHUFFLE_V8F32(tmp2, tmp4, AKSIMD_SHUFFLE(3, 1, 3, 1));
192 }
193 
194 //@}
195 ////////////////////////////////////////////////////////////////////////
196 
197 
198 ////////////////////////////////////////////////////////////////////////
199 /// @name AKSIMD arithmetic
200 //@{
201 
202 /// Subtracts the eight single-precision, floating-point values of
203 /// a and b (a - b) (see _mm_sub_ps)
204 #define AKSIMD_SUB_V8F32( a, b ) _mm256_sub_ps( a, b )
205 
206 /// Subtracts the lower single-precision, floating-point values of a and b.
207 /// The upper three single-precision, floating-point values are passed through from a.
208 /// r0 := a0 - b0 ; r1...r7 := a1...a7 (see _mm_sub_ss)
209 #define AKSIMD_SUB_SS_V8F32( a, b ) _mm256_sub_ps( a, _mm256_and_ps(b, _mm256_setr_epi32( -1, 0, 0, 0, 0, 0, 0, 0 ) ) )
210 
211 /// Adds the eight single-precision, floating-point values of
212 /// a and b (see _mm_add_ps)
213 #define AKSIMD_ADD_V8F32( a, b ) _mm256_add_ps( a, b )
214 
215 /// Performs alternatiing subs and adds of the eight single-precision,
216 /// floating-point values of a and b (see _mm_addsub_ps)
217 #define AKSIMD_ADDSUB_V8F32( a, b ) _mm256_addsub_ps( a, b )
218 
219 /// Adds the lower single-precision, floating-point values of a and b; the
220 /// upper three single-precision, floating-point values are passed through from a.
221 /// r0 := a0 + b0; r1...r7 := a1...a7 (see _mm_add_ss)
222 #define AKSIMD_ADD_SS_V8F32( a, b ) _mm256_add_ps( a, _mm256_and_ps(b, _mm256_setr_epi32( -1, 0, 0, 0, 0, 0, 0, 0 ) ) )
223 
224 /// Multiplies the eight single-precision, floating-point values
225 /// of a and b (see _mm_mul_ps)
226 #define AKSIMD_MUL_V8F32( a, b ) _mm256_mul_ps( a, b )
227 
228 #define AKSIMD_DIV_V8F32( a, b ) _mm256_div_ps( a, b )
229 
230 /// Multiplies the lower single-precision, floating-point values of
231 /// a and b; the upper three single-precision, floating-point values
232 /// are passed through from a.
233 /// r0 := a0 * b0; r1...r7 := a1...a7 (see _mm_mul_ss)
234 #define AKSIMD_MUL_SS_V8F32( a, b ) _mm256_mul_ps( a, _mm256_blend_ps(b, _mm256_set1_ps(1.0f), 0xfe ) )
235 
236 /// Computes the minima of the eight single-precision, floating-point
237 /// values of a and b (see _mm_min_ps)
238 #define AKSIMD_MIN_V8F32( a, b ) _mm256_min_ps( a, b )
239 
240 /// Computes the maximums of the eight single-precision, floating-point
241 /// values of a and b (see _mm_max_ps)
242 #define AKSIMD_MAX_V8F32( a, b ) _mm256_max_ps( a, b )
243 
244 /// Computes the absolute value
245 #define AKSIMD_ABS_V8F32( a ) _mm256_andnot_ps(_mm256_set1_ps(-0.f), a)
246 
247 /// Changes the sign
248 #define AKSIMD_NEG_V8F32( __a__ ) _mm256_xor_ps(_mm256_set1_ps(-0.f), __a__)
249 
250 /// Vector square root aproximation (see _mm_sqrt_ps)
251 #define AKSIMD_SQRT_V8F32( __a__ ) _mm256_sqrt_ps( (__a__) )
252 
253 /// Vector reciprocal square root approximation 1/sqrt(a), or equivalently, sqrt(1/a)
254 #define AKSIMD_RSQRT_V8F32( __a__ ) _mm256_rsqrt_ps( (__a__) )
255 
256 /// Vector reciprocal
257 #define AKSIMD_RECIP_V8F32( __a__ ) _mm256_rcp_ps( (__a__) )
258 
259 /// Vector ceil
260 #define AKSIMD_CEIL_V8F32( __a__ ) _mm256_ceil_ps( (__a__) )
261 
262 #define AKSIMD_XOR_V8F32( a, b ) _mm256_xor_ps(a,b)
263 #define AKSIMD_OR_V8F32( a, b ) _mm256_or_ps(a,b)
264 #define AKSIMD_AND_V8F32( a, b) _mm256_and_ps(a,b)
265 #define AKSIMD_NOT_V8F32( a ) _mm256_xor_ps(a,_mm256_castsi256_ps(_mm256_set1_epi32(~0)))
266 #define AKSIMD_ANDNOT_V8F32( a, b ) _mm256_andnot_ps(a, b)
267 
268 /// horizontal add across the entire vector - vVec will be updated to contain the sum of every input element of vVec
269 /// \akwarning
270 /// Don't expect this to be very efficient.
271 /// \endakwarning
272 static AkForceInline AKSIMD_V8F32 AKSIMD_HORIZONTALADD_V8F32(AKSIMD_V8F32 vVec)
273 {
274  __m256 vAb = _mm256_shuffle_ps(vVec, vVec, 0xB1);
275  __m256 vHaddAb = _mm256_add_ps(vVec, vAb);
276  __m256 vHaddCd = _mm256_shuffle_ps(vHaddAb, vHaddAb, 0x4E);
277  __m256 vHaddAbcd = _mm256_add_ps(vHaddAb, vHaddCd);
278  __m256 vHaddEfgh = _mm256_permute2f128_ps(vHaddAbcd, vHaddAbcd, 0x01);
279  __m256 vHaddAll = _mm256_add_ps(vHaddAbcd, vHaddEfgh);
280  return vHaddAll;
281 }
282 
283 /// Cross-platform SIMD multiplication of 8 complex data elements with interleaved real and imaginary parts
284 static AkForceInline AKSIMD_V8F32 AKSIMD_COMPLEXMUL_V8F32(const AKSIMD_V8F32 cIn1, const AKSIMD_V8F32 cIn2)
285 {
286  __m256 real1Ext = _mm256_moveldup_ps(cIn1); // reals extended (a3, a3, a2, a2, a1, a1, a0, a0)
287  __m256 in2Shuf = _mm256_shuffle_ps(cIn2, cIn2, 0xB1); // shuf multiplicand (c3, d3, c2, d2, c1, d1, c0, d0)
288  __m256 imag1Ext = _mm256_movehdup_ps(cIn1); // multiplier imag (b3, b3, b2, b2, b1, b1, b0, b0)
289  __m256 temp = _mm256_mul_ps(imag1Ext, in2Shuf); // temp (b3c3, b3d3, b2c2, b2d2, b1c1, b1d1, b0c0, b0d0)
290  __m256 mul = _mm256_mul_ps(real1Ext, cIn2); // (a3d3, a3c3, a2d2, a2c2, a1d1, a1c1, a0d0, a0c0)
291  __m256 out = _mm256_addsub_ps(mul, temp); // final (a3d3+b3c3, a3c3-b3d3, a2d2+b2c2, a2c2-b2d2, a1d1+b1c1, a1c1-b1d1, a0d0+b0c0, a0c0-b0d0)
292  return out;
293 }
294 
295 //@}
296 ////////////////////////////////////////////////////////////////////////
297 
298 
299 ////////////////////////////////////////////////////////////////////////
300 /// @name AKSIMD packing / unpacking
301 //@{
302 
303 /// Selects and interleaves the lower two single-precision, floating-point
304 /// values from each 128-bit lane in a and b (see _mm_unpacklo_ps)
305 /// i.e. r0 := a0, r1 := b0, r2 := a1, r3 := b1, r4 := a4, r5 := b4, r6 := a5, r7 := b5
306 #define AKSIMD_UNPACKLO_V8F32( a, b ) _mm256_unpacklo_ps( a, b )
307 
308 /// Selects and interleaves the upper two single-precision, floating-point
309 /// values from each 128-bit lane a and b (see _mm_unpackhi_ps)
310 /// i.e. r0 := a2, r1 := b2, r2 := a3, r3 := b3, r4 := a6, r5 := b6, r6 := a7, r7 := b7
311 #define AKSIMD_UNPACKHI_V8F32( a, b ) _mm256_unpackhi_ps( a, b )
312 
313 //@}
314 ////////////////////////////////////////////////////////////////////////
315 
316 ////////////////////////////////////////////////////////////////////////
317 /// @name AKSIMD vector comparison
318 //@{
319 
320 #define AKSIMD_CMP_CTRLMASKV8 __m256
321 
322 /// Vector "<=" operation (see _mm_cmple_ps)
323 #define AKSIMD_LTEQ_V8F32( __a__, __b__ ) _mm256_cmp_ps( (__a__), (__b__), _CMP_LE_OS )
324 
325 #define AKSIMD_LT_V8F32( __a__, __b__ ) _mm256_cmp_ps( (__a__), (__b__), _CMP_LT_OS )
326 
327 /// Vector ">=" operation (see _mm_cmple_ps)
328 #define AKSIMD_GTEQ_V8F32( __a__, __b__ ) _mm256_cmp_ps( (__a__), (__b__), _CMP_GE_OS )
329 
330 #define AKSIMD_GT_V8F32( __a__, __b__ ) _mm256_cmp_ps( (__a__), (__b__), _CMP_GT_OS )
331 
332 /// Vector "==" operation (see _mm_cmpeq_ps)
333 #define AKSIMD_EQ_V8F32( __a__, __b__ ) _mm256_cmp_ps( (__a__), (__b__), _CMP_EQ_OS )
334 
335 /// Return a when control mask is 0, return b when control mask is non zero, control mask is in c and usually provided by above comparison operations
336 static AkForceInline AKSIMD_V8F32 AKSIMD_VSEL_V8F32( AKSIMD_V8F32 vA, AKSIMD_V8F32 vB, AKSIMD_V8F32 vMask )
337 {
338  return _mm256_blendv_ps(vA, vB, vMask);
339 }
340 
341 // (cond1 >= cond2) ? b : a.
342 #define AKSIMD_SEL_GTEQ_V8F32( __a__, __b__, __cond1__, __cond2__ ) AKSIMD_VSEL_V8F32( __a__, __b__, AKSIMD_GTEQ_V8F32( __cond1__, __cond2__ ) )
343 
344 // a >= 0 ? b : c ... Written, like, you know, the normal C++ operator syntax.
345 #define AKSIMD_SEL_GTEZ_V8F32( __a__, __b__, __c__ ) AKSIMD_VSEL_V8F32( (__c__), (__b__), AKSIMD_GTEQ_V8F32( __a__, _mm256_set1_ps(0) ) )
346 
347 #define AKSIMD_SPLAT_V8F32(var, idx) AKSIMD_SHUFFLE_V8F32(var,var, AKSIMD_SHUFFLE(idx,idx,idx,idx))
348 
349 #define AKSIMD_MASK_V8F32( __a__ ) _mm256_movemask_ps( __a__ )
350 
351 // returns true if every element of the provided vector is zero
352 #define AKSIMD_TESTZERO_V8I32( __a__ ) (_mm256_testz_si256(__a__,__a__) != 0)
353 #define AKSIMD_TESTZERO_V8F32( __a__) AKSIMD_TESTZERO_V8I32(_mm256_castps_si256(__a__))
354 
355 // returns true if every element of the provided vector is one
356 #define AKSIMD_TESTONES_V8I32(__a__) (_mm256_testc_si256(__a__, _mm256_set1_epi32(~0)) != 0)
357 #define AKSIMD_TESTONES_V8F32( __a__) AKSIMD_TESTONES_V8I32(_mm256_castps_si256(__a__))
358 
359 //@}
360 ////////////////////////////////////////////////////////////////////////
361 
362 /// Loads 256-bit value (see _mm_loadu_si128)
363 /// On every modern x86 processor this performs the same as an aligned load.
364 #define AKSIMD_LOAD_V8I32( __addr__ ) _mm256_loadu_si256( (__addr__) )
365 
366 /// Sets the eight 32-bit integer values to zero (see _mm_setzero_si128)
367 #define AKSIMD_SETZERO_V8I32() _mm256_setzero_si256()
368 
369 /// Sets the provided scalar value at the first index of the vector, and zeroes everything else
370 #define AKSIMD_SET_V8I32( __scalar__ ) _mm256_set1_epi32( (__scalar__) )
371 
372 /// Populates the full vector with the 8 values provided
373 #define AKSIMD_SETV_V8I32( _h, _g, _f, _e, _d, _c, _b, _a ) _mm256_set_epi32( (_h), (_g), (_f), (_e), (_d), (_c), (_b), (_a) )
374 
375 /// Loads the two m128i's provided into the output m256i a
376 /// Note that this should be utilized instead of, e.g. adding & utilizing a macro "AKSIMD_INSERT_V8I32(m, i, idx)"
377 /// Because there is no direct corresponding instruction for an insert into 256. You should load into 128s
378 /// and use that. Some compilers do not handle _mm256_insert_epi32 (etc) well, or even include them
379 #define AKSIMD_SET_V2I128(m1, m2) _mm256_setr_m128i(m1, m2)
380 
381 /// Stores eight 32-bit integer values.
382 /// The address does not need to be 32-byte aligned (see _mm_storeu_si128).
383 /// On every modern x86 processor this performs the same as an aligned load.
384 #define AKSIMD_STORE_V8I32( __addr__, __vec__ ) _mm256_storeu_si256( (__addr__), (__vec__) )
385 
386 ////////////////////////////////////////////////////////////////////////
387 /// @name AKSIMD conversion
388 //@{
389 
390 /// Converts the eight signed 32-bit integer values of a to single-precision,
391 /// floating-point values (see _mm_cvtepi32_ps)
392 #define AKSIMD_CONVERT_V8I32_TO_V8F32( __vec__ ) _mm256_cvtepi32_ps( (__vec__) )
393 
394 /// Converts the eight single-precision, floating-point values of a to signed
395 /// 32-bit integer values by rounding (see _mm_cvtps_epi32)
396 #define AKSIMD_ROUND_V8F32_TO_V8I32( __vec__ ) _mm256_cvtps_epi32( (__vec__) )
397 
398 /// Converts the eight single-precision, floating-point values of a to signed
399 /// 32-bit integer values by truncating (see _mm_cvttps_epi32)
400 #define AKSIMD_TRUNCATE_V8F32_TO_V8I32( __vec__ ) _mm256_cvttps_epi32( (__vec__) )
401 
402 /// Converts the eight half-precision floating-point values of vec to
403 /// eight full-precision floating-point values
404 /// WARNING: Using this requires F16C support, which is not guaranteed on AVX
405 #define AKSIMD_CONVERT_V8F16_TO_V8F32( __vec__ ) _mm256_cvtph_ps( (__vec__) )
406 
407 /// Converts the eight single-precision, floating-point values of vec to
408 /// eight half-precision floating-point values
409 /// WARNING: Using this requires F16C support, which is not guaranteed on AVX
410 #define AKSIMD_CONVERT_V8F32_TO_V8F16( __vec__ ) _mm256_cvtps_ph(__vec__, (_MM_FROUND_TO_NEAREST_INT ) )
411 
412 //@}
413 ////////////////////////////////////////////////////////////////////////
414 
415 ////////////////////////////////////////////////////////////////////////
416 /// @name AKSIMD cast
417 //@{
418 
419 /// Cast vector of type AKSIMD_V4F64 to type AKSIMD_V8F32. This intrinsic is only
420 /// used for compilation and does not generate any instructions, thus it has zero latency.
421 #define AKSIMD_CAST_V4F64_TO_V8F32( __vec__ ) _mm256_castpd_ps(__vec__)
422 
423 /// Cast vector of type AKSIMD_V4F64 to type AKSIMD_V8I32. This intrinsic is only
424 /// used for compilation and does not generate any instructions, thus it has zero latency.
425 #define AKSIMD_CAST_V4F64_TO_V8I32( __vec__ ) _mm256_castpd_si256(__vec__)
426 
427 /// Cast vector of type AKSIMD_V8F32 to type AKSIMD_V4F64. This intrinsic is only
428 /// used for compilation and does not generate any instructions, thus it has zero latency.
429 #define AKSIMD_CAST_V8F32_TO_V4F64( __vec__ ) _mm256_castps_pd(__vec__)
430 
431 /// Cast vector of type AKSIMD_V8F32 to type AKSIMD_V8I32. This intrinsic is only
432 /// used for compilation and does not generate any instructions, thus it has zero latency.
433 #define AKSIMD_CAST_V8F32_TO_V8I32( __vec__ ) _mm256_castps_si256(__vec__)
434 
435 /// Cast vector of type AKSIMD_V8I32 to type AKSIMD_V4F64. This intrinsic is only
436 /// used for compilation and does not generate any instructions, thus it has zero latency.
437 #define AKSIMD_CAST_V8I32_TO_V4F64( __vec__ ) _mm256_castsi256_pd(__vec__)
438 
439 /// Cast vector of type AKSIMD_V8I32 to type AKSIMD_V8F32. This intrinsic is only
440 /// used for compilation and does not generate any instructions, thus it has zero latency.
441 #define AKSIMD_CAST_V8I32_TO_V8F32( __vec__ ) _mm256_castsi256_ps(__vec__)
442 
443 /// Cast vector of type AKSIMD_V8COND to AKSIMD_V8F32.
444 #define AKSIMD_CAST_V8COND_TO_V8F32( __vec__ ) (__vec__)
445 
446 /// Cast vector of type AKSIMD_V8F32 to AKSIMD_V8COND.
447 #define AKSIMD_CAST_V8F32_TO_V8COND( __vec__ ) (__vec__)
448 
449 /// Cast vector of type AKSIMD_V8COND to AKSIMD_V8I32.
450 #define AKSIMD_CAST_V8COND_TO_V8I32( __vec__ ) _mm256_castps_si256(__vec__)
451 
452 /// Cast vector of type AKSIMD_V8I32 to AKSIMD_V8COND.
453 #define AKSIMD_CAST_V8I32_TO_V8COND( __vec__ ) _mm256_castsi256_ps(__vec__)
454 
455 //@}
456 ////////////////////////////////////////////////////////////////////////
457 #endif //_AK_SIMD_AVX_H_
458 #endif
#define AKSIMD_SHUFFLE(fp3, fp2, fp1, fp0)
Definition: AkSimd.h:508
#define AkForceInline
Definition: AkTypes.h:63
float32_t AKSIMD_F32
32-bit float
Definition: AkSimdTypes.h:60

Was this page helpful?

Need Support?

Questions? Problems? Need more info? Contact us, and we can help!

Visit our Support page

Tell us about your project. We're here to help.

Register your project and we'll help you get started with no strings attached!

Get started with Wwise