2010-03-24 13:31:31 +08:00
|
|
|
/*===---- smmintrin.h - SSE4 intrinsics ------------------------------------===
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*
|
|
|
|
*===-----------------------------------------------------------------------===
|
|
|
|
*/
|
2010-03-04 10:56:19 +08:00
|
|
|
|
|
|
|
#ifndef _SMMINTRIN_H
|
|
|
|
#define _SMMINTRIN_H
|
|
|
|
|
|
|
|
#include <tmmintrin.h>
|
|
|
|
|
2015-06-17 15:09:20 +08:00
|
|
|
/* Define the default attributes for the functions in this file. */
|
2015-06-30 21:36:19 +08:00
|
|
|
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4.1")))
|
2015-06-17 15:09:20 +08:00
|
|
|
|
2010-03-04 10:56:19 +08:00
|
|
|
/* SSE4 Rounding macros. */
|
|
|
|
#define _MM_FROUND_TO_NEAREST_INT 0x00
|
|
|
|
#define _MM_FROUND_TO_NEG_INF 0x01
|
|
|
|
#define _MM_FROUND_TO_POS_INF 0x02
|
|
|
|
#define _MM_FROUND_TO_ZERO 0x03
|
|
|
|
#define _MM_FROUND_CUR_DIRECTION 0x04
|
|
|
|
|
|
|
|
#define _MM_FROUND_RAISE_EXC 0x00
|
|
|
|
#define _MM_FROUND_NO_EXC 0x08
|
|
|
|
|
|
|
|
#define _MM_FROUND_NINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_NEAREST_INT)
|
|
|
|
#define _MM_FROUND_FLOOR (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_NEG_INF)
|
|
|
|
#define _MM_FROUND_CEIL (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_POS_INF)
|
|
|
|
#define _MM_FROUND_TRUNC (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_ZERO)
|
|
|
|
#define _MM_FROUND_RINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_CUR_DIRECTION)
|
2010-03-06 18:31:44 +08:00
|
|
|
#define _MM_FROUND_NEARBYINT (_MM_FROUND_NO_EXC | _MM_FROUND_CUR_DIRECTION)
|
2010-03-04 10:56:19 +08:00
|
|
|
|
|
|
|
#define _mm_ceil_ps(X) _mm_round_ps((X), _MM_FROUND_CEIL)
|
|
|
|
#define _mm_ceil_pd(X) _mm_round_pd((X), _MM_FROUND_CEIL)
|
|
|
|
#define _mm_ceil_ss(X, Y) _mm_round_ss((X), (Y), _MM_FROUND_CEIL)
|
|
|
|
#define _mm_ceil_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_CEIL)
|
|
|
|
|
|
|
|
#define _mm_floor_ps(X) _mm_round_ps((X), _MM_FROUND_FLOOR)
|
|
|
|
#define _mm_floor_pd(X) _mm_round_pd((X), _MM_FROUND_FLOOR)
|
|
|
|
#define _mm_floor_ss(X, Y) _mm_round_ss((X), (Y), _MM_FROUND_FLOOR)
|
|
|
|
#define _mm_floor_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_FLOOR)
|
|
|
|
|
2012-03-30 15:01:17 +08:00
|
|
|
#define _mm_round_ps(X, M) __extension__ ({ \
|
2015-11-10 13:08:05 +08:00
|
|
|
(__m128)__builtin_ia32_roundps((__v4sf)(__m128)(X), (M)); })
|
2012-03-30 15:01:17 +08:00
|
|
|
|
|
|
|
#define _mm_round_ss(X, Y, M) __extension__ ({ \
|
2015-11-10 13:08:05 +08:00
|
|
|
(__m128)__builtin_ia32_roundss((__v4sf)(__m128)(X), \
|
|
|
|
(__v4sf)(__m128)(Y), (M)); })
|
2012-03-30 15:01:17 +08:00
|
|
|
|
|
|
|
#define _mm_round_pd(X, M) __extension__ ({ \
|
2015-11-10 13:08:05 +08:00
|
|
|
(__m128d)__builtin_ia32_roundpd((__v2df)(__m128d)(X), (M)); })
|
2012-03-30 15:01:17 +08:00
|
|
|
|
|
|
|
#define _mm_round_sd(X, Y, M) __extension__ ({ \
|
2015-11-10 13:08:05 +08:00
|
|
|
(__m128d)__builtin_ia32_roundsd((__v2df)(__m128d)(X), \
|
|
|
|
(__v2df)(__m128d)(Y), (M)); })
|
2010-03-04 10:56:19 +08:00
|
|
|
|
|
|
|
/* SSE4 Packed Blending Intrinsics. */
|
2011-11-10 08:11:13 +08:00
|
|
|
#define _mm_blend_pd(V1, V2, M) __extension__ ({ \
|
2015-11-10 13:08:05 +08:00
|
|
|
(__m128d)__builtin_shufflevector((__v2df)(__m128d)(V1), \
|
|
|
|
(__v2df)(__m128d)(V2), \
|
2014-05-13 10:37:02 +08:00
|
|
|
(((M) & 0x01) ? 2 : 0), \
|
|
|
|
(((M) & 0x02) ? 3 : 1)); })
|
2010-03-04 10:56:19 +08:00
|
|
|
|
2011-11-10 08:11:13 +08:00
|
|
|
#define _mm_blend_ps(V1, V2, M) __extension__ ({ \
|
2015-11-10 13:08:05 +08:00
|
|
|
(__m128)__builtin_shufflevector((__v4sf)(__m128)(V1), (__v4sf)(__m128)(V2), \
|
2014-05-13 10:37:02 +08:00
|
|
|
(((M) & 0x01) ? 4 : 0), \
|
|
|
|
(((M) & 0x02) ? 5 : 1), \
|
|
|
|
(((M) & 0x04) ? 6 : 2), \
|
|
|
|
(((M) & 0x08) ? 7 : 3)); })
|
2010-03-04 10:56:19 +08:00
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128d __DEFAULT_FN_ATTRS
|
2010-03-04 10:56:19 +08:00
|
|
|
_mm_blendv_pd (__m128d __V1, __m128d __V2, __m128d __M)
|
|
|
|
{
|
|
|
|
return (__m128d) __builtin_ia32_blendvpd ((__v2df)__V1, (__v2df)__V2,
|
|
|
|
(__v2df)__M);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128 __DEFAULT_FN_ATTRS
|
2010-03-04 10:56:19 +08:00
|
|
|
_mm_blendv_ps (__m128 __V1, __m128 __V2, __m128 __M)
|
|
|
|
{
|
|
|
|
return (__m128) __builtin_ia32_blendvps ((__v4sf)__V1, (__v4sf)__V2,
|
|
|
|
(__v4sf)__M);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-04 10:56:19 +08:00
|
|
|
_mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pblendvb128 ((__v16qi)__V1, (__v16qi)__V2,
|
|
|
|
(__v16qi)__M);
|
|
|
|
}
|
|
|
|
|
2011-11-10 08:11:13 +08:00
|
|
|
#define _mm_blend_epi16(V1, V2, M) __extension__ ({ \
|
2015-11-10 13:08:05 +08:00
|
|
|
(__m128i)__builtin_shufflevector((__v8hi)(__m128i)(V1), \
|
|
|
|
(__v8hi)(__m128i)(V2), \
|
2014-05-13 10:37:02 +08:00
|
|
|
(((M) & 0x01) ? 8 : 0), \
|
|
|
|
(((M) & 0x02) ? 9 : 1), \
|
|
|
|
(((M) & 0x04) ? 10 : 2), \
|
|
|
|
(((M) & 0x08) ? 11 : 3), \
|
|
|
|
(((M) & 0x10) ? 12 : 4), \
|
|
|
|
(((M) & 0x20) ? 13 : 5), \
|
|
|
|
(((M) & 0x40) ? 14 : 6), \
|
|
|
|
(((M) & 0x80) ? 15 : 7)); })
|
2010-03-04 10:56:19 +08:00
|
|
|
|
2010-03-07 14:17:19 +08:00
|
|
|
/* SSE4 Dword Multiply Instructions. */
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-07 14:17:19 +08:00
|
|
|
_mm_mullo_epi32 (__m128i __V1, __m128i __V2)
|
|
|
|
{
|
2010-03-26 08:51:28 +08:00
|
|
|
return (__m128i) ((__v4si)__V1 * (__v4si)__V2);
|
2010-03-07 14:17:19 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-07 14:17:19 +08:00
|
|
|
_mm_mul_epi32 (__m128i __V1, __m128i __V2)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pmuldq128 ((__v4si)__V1, (__v4si)__V2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* SSE4 Floating Point Dot Product Instructions. */
|
2012-03-30 15:01:17 +08:00
|
|
|
#define _mm_dp_ps(X, Y, M) __extension__ ({ \
|
2015-11-10 13:08:05 +08:00
|
|
|
(__m128) __builtin_ia32_dpps((__v4sf)(__m128)(X), \
|
|
|
|
(__v4sf)(__m128)(Y), (M)); })
|
2012-03-30 15:01:17 +08:00
|
|
|
|
|
|
|
#define _mm_dp_pd(X, Y, M) __extension__ ({\
|
2015-11-10 13:08:05 +08:00
|
|
|
(__m128d) __builtin_ia32_dppd((__v2df)(__m128d)(X), \
|
|
|
|
(__v2df)(__m128d)(Y), (M)); })
|
2010-03-07 14:17:19 +08:00
|
|
|
|
2010-03-07 14:29:09 +08:00
|
|
|
/* SSE4 Streaming Load Hint Instruction. */
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2015-10-03 07:29:26 +08:00
|
|
|
_mm_stream_load_si128 (__m128i const *__V)
|
2010-03-07 14:29:09 +08:00
|
|
|
{
|
2015-10-03 07:29:26 +08:00
|
|
|
return (__m128i) __builtin_ia32_movntdqa ((const __v2di *) __V);
|
2010-03-07 14:29:09 +08:00
|
|
|
}
|
|
|
|
|
2010-03-07 15:00:42 +08:00
|
|
|
/* SSE4 Packed Integer Min/Max Instructions. */
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-07 15:00:42 +08:00
|
|
|
_mm_min_epi8 (__m128i __V1, __m128i __V2)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pminsb128 ((__v16qi) __V1, (__v16qi) __V2);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-07 15:00:42 +08:00
|
|
|
_mm_max_epi8 (__m128i __V1, __m128i __V2)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pmaxsb128 ((__v16qi) __V1, (__v16qi) __V2);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-07 15:00:42 +08:00
|
|
|
_mm_min_epu16 (__m128i __V1, __m128i __V2)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pminuw128 ((__v8hi) __V1, (__v8hi) __V2);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-07 15:00:42 +08:00
|
|
|
_mm_max_epu16 (__m128i __V1, __m128i __V2)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pmaxuw128 ((__v8hi) __V1, (__v8hi) __V2);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-07 15:00:42 +08:00
|
|
|
_mm_min_epi32 (__m128i __V1, __m128i __V2)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pminsd128 ((__v4si) __V1, (__v4si) __V2);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-07 15:00:42 +08:00
|
|
|
_mm_max_epi32 (__m128i __V1, __m128i __V2)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pmaxsd128 ((__v4si) __V1, (__v4si) __V2);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-07 15:00:42 +08:00
|
|
|
_mm_min_epu32 (__m128i __V1, __m128i __V2)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pminud128((__v4si) __V1, (__v4si) __V2);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-07 15:00:42 +08:00
|
|
|
_mm_max_epu32 (__m128i __V1, __m128i __V2)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pmaxud128((__v4si) __V1, (__v4si) __V2);
|
|
|
|
}
|
|
|
|
|
2010-03-10 08:50:58 +08:00
|
|
|
/* SSE4 Insertion and Extraction from XMM Register Instructions. */
|
|
|
|
#define _mm_insert_ps(X, Y, N) __builtin_ia32_insertps128((X), (Y), (N))
|
|
|
|
#define _mm_extract_ps(X, N) (__extension__ \
|
2013-01-17 07:08:36 +08:00
|
|
|
({ union { int __i; float __f; } __t; \
|
2015-11-11 11:47:10 +08:00
|
|
|
__v4sf __a = (__v4sf)(__m128)(X); \
|
2013-10-24 04:33:14 +08:00
|
|
|
__t.__f = __a[(N) & 3]; \
|
2013-01-17 07:08:36 +08:00
|
|
|
__t.__i;}))
|
2010-03-10 08:50:58 +08:00
|
|
|
|
|
|
|
/* Miscellaneous insert and extract macros. */
|
|
|
|
/* Extract a single-precision float from X at index N into D. */
|
2010-06-03 00:35:01 +08:00
|
|
|
#define _MM_EXTRACT_FLOAT(D, X, N) (__extension__ ({ __v4sf __a = (__v4sf)(X); \
|
2010-03-10 08:50:58 +08:00
|
|
|
(D) = __a[N]; }))
|
2015-09-12 10:55:19 +08:00
|
|
|
|
2010-03-10 08:50:58 +08:00
|
|
|
/* Or together 2 sets of indexes (X and Y) with the zeroing bits (Z) to create
|
|
|
|
an index suitable for _mm_insert_ps. */
|
|
|
|
#define _MM_MK_INSERTPS_NDX(X, Y, Z) (((X) << 6) | ((Y) << 4) | (Z))
|
2015-09-12 10:55:19 +08:00
|
|
|
|
2010-03-10 08:50:58 +08:00
|
|
|
/* Extract a float from X at index N into the first index of the return. */
|
|
|
|
#define _MM_PICK_OUT_PS(X, N) _mm_insert_ps (_mm_setzero_ps(), (X), \
|
|
|
|
_MM_MK_INSERTPS_NDX((N), 0, 0x0e))
|
2015-09-12 10:55:19 +08:00
|
|
|
|
2010-03-12 07:36:29 +08:00
|
|
|
/* Insert int into packed integer array at index. */
|
2015-11-11 11:47:10 +08:00
|
|
|
#define _mm_insert_epi8(X, I, N) (__extension__ \
|
|
|
|
({ __v16qi __a = (__v16qi)(__m128i)(X); \
|
|
|
|
__a[(N) & 15] = (I); \
|
2016-05-17 11:42:31 +08:00
|
|
|
(__m128i)__a;}))
|
2015-11-11 11:47:10 +08:00
|
|
|
#define _mm_insert_epi32(X, I, N) (__extension__ \
|
|
|
|
({ __v4si __a = (__v4si)(__m128i)(X); \
|
|
|
|
__a[(N) & 3] = (I); \
|
2016-05-17 11:42:31 +08:00
|
|
|
(__m128i)__a;}))
|
2010-03-12 07:36:29 +08:00
|
|
|
#ifdef __x86_64__
|
2015-11-11 11:47:10 +08:00
|
|
|
#define _mm_insert_epi64(X, I, N) (__extension__ \
|
|
|
|
({ __v2di __a = (__v2di)(__m128i)(X); \
|
|
|
|
__a[(N) & 1] = (I); \
|
2016-05-17 11:42:31 +08:00
|
|
|
(__m128i)__a;}))
|
2010-03-12 07:36:29 +08:00
|
|
|
#endif /* __x86_64__ */
|
2010-03-10 08:50:58 +08:00
|
|
|
|
2010-08-21 00:08:33 +08:00
|
|
|
/* Extract int from packed integer array at index. This returns the element
|
|
|
|
* as a zero extended value, so it is unsigned.
|
|
|
|
*/
|
2015-11-11 11:47:10 +08:00
|
|
|
#define _mm_extract_epi8(X, N) (__extension__ \
|
|
|
|
({ __v16qi __a = (__v16qi)(__m128i)(X); \
|
|
|
|
(int)(unsigned char) __a[(N) & 15];}))
|
|
|
|
#define _mm_extract_epi32(X, N) (__extension__ \
|
|
|
|
({ __v4si __a = (__v4si)(__m128i)(X); \
|
|
|
|
(int)__a[(N) & 3];}))
|
2010-03-12 07:50:18 +08:00
|
|
|
#ifdef __x86_64__
|
2015-11-11 11:47:10 +08:00
|
|
|
#define _mm_extract_epi64(X, N) (__extension__ \
|
|
|
|
({ __v2di __a = (__v2di)(__m128i)(X); \
|
|
|
|
(long long)__a[(N) & 1];}))
|
2010-03-12 07:50:18 +08:00
|
|
|
#endif /* __x86_64 */
|
|
|
|
|
2010-03-12 09:22:33 +08:00
|
|
|
/* SSE4 128-bit Packed Integer Comparisons. */
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ int __DEFAULT_FN_ATTRS
|
2010-03-12 09:22:33 +08:00
|
|
|
_mm_testz_si128(__m128i __M, __m128i __V)
|
|
|
|
{
|
|
|
|
return __builtin_ia32_ptestz128((__v2di)__M, (__v2di)__V);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ int __DEFAULT_FN_ATTRS
|
2010-03-12 09:22:33 +08:00
|
|
|
_mm_testc_si128(__m128i __M, __m128i __V)
|
|
|
|
{
|
|
|
|
return __builtin_ia32_ptestc128((__v2di)__M, (__v2di)__V);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ int __DEFAULT_FN_ATTRS
|
2010-03-12 09:22:33 +08:00
|
|
|
_mm_testnzc_si128(__m128i __M, __m128i __V)
|
|
|
|
{
|
|
|
|
return __builtin_ia32_ptestnzc128((__v2di)__M, (__v2di)__V);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define _mm_test_all_ones(V) _mm_testc_si128((V), _mm_cmpeq_epi32((V), (V)))
|
|
|
|
#define _mm_test_mix_ones_zeros(M, V) _mm_testnzc_si128((M), (V))
|
2011-12-15 01:17:16 +08:00
|
|
|
#define _mm_test_all_zeros(M, V) _mm_testz_si128 ((M), (V))
|
2010-03-12 09:22:33 +08:00
|
|
|
|
2010-03-16 07:22:58 +08:00
|
|
|
/* SSE4 64-bit Packed Integer Comparisons. */
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cmpeq_epi64(__m128i __V1, __m128i __V2)
|
|
|
|
{
|
2011-12-20 17:55:26 +08:00
|
|
|
return (__m128i)((__v2di)__V1 == (__v2di)__V2);
|
2010-03-16 07:22:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* SSE4 Packed Integer Sign-Extension. */
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepi8_epi16(__m128i __V)
|
|
|
|
{
|
Fix the SSE4 byte sign extension in a cleaner way, and more thoroughly
test that our intrinsics behave the same under -fsigned-char and
-funsigned-char.
This further testing uncovered that AVX-2 has a broken cmpgt for 8-bit
elements, and has for a long time. This is fixed in the same way as
SSE4 handles the case.
The other ISA extensions currently work correctly because they use
specific instruction intrinsics. As soon as they are rewritten in terms
of generic IR, they will need to add these special casts. I've added the
necessary testing to catch this however, so we shouldn't have to chase
it down again.
I considered changing the core typedef to be signed, but that seems like
a bad idea. Notably, it would be an ABI break if anyone is reaching into
the innards of the intrinsic headers and passing __v16qi on an API
boundary. I can't be completely confident that this wouldn't happen due
to a macro expanding in a lambda, etc., so it seems much better to leave
it alone. It also matches GCC's behavior exactly.
A fun side note is that for both GCC and Clang, -funsigned-char really
does change the semantics of __v16qi. To observe this, consider:
% cat x.cc
#include <smmintrin.h>
#include <iostream>
int main() {
__v16qi a = { 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
__v16qi b = _mm_set1_epi8(-1);
std::cout << (int)(a / b)[0] << ", " << (int)(a / b)[1] << '\n';
}
% clang++ -o x x.cc && ./x
-1, 1
% clang++ -funsigned-char -o x x.cc && ./x
0, 1
However, while this may be surprising, both Clang and GCC agree.
Differential Revision: http://reviews.llvm.org/D13324
llvm-svn: 249097
2015-10-02 07:40:12 +08:00
|
|
|
/* This function always performs a signed extension, but __v16qi is a char
|
|
|
|
which may be signed or unsigned, so use __v16qs. */
|
|
|
|
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1, 2, 3, 4, 5, 6, 7), __v8hi);
|
2010-03-16 07:22:58 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepi8_epi32(__m128i __V)
|
|
|
|
{
|
Fix the SSE4 byte sign extension in a cleaner way, and more thoroughly
test that our intrinsics behave the same under -fsigned-char and
-funsigned-char.
This further testing uncovered that AVX-2 has a broken cmpgt for 8-bit
elements, and has for a long time. This is fixed in the same way as
SSE4 handles the case.
The other ISA extensions currently work correctly because they use
specific instruction intrinsics. As soon as they are rewritten in terms
of generic IR, they will need to add these special casts. I've added the
necessary testing to catch this however, so we shouldn't have to chase
it down again.
I considered changing the core typedef to be signed, but that seems like
a bad idea. Notably, it would be an ABI break if anyone is reaching into
the innards of the intrinsic headers and passing __v16qi on an API
boundary. I can't be completely confident that this wouldn't happen due
to a macro expanding in a lambda, etc., so it seems much better to leave
it alone. It also matches GCC's behavior exactly.
A fun side note is that for both GCC and Clang, -funsigned-char really
does change the semantics of __v16qi. To observe this, consider:
% cat x.cc
#include <smmintrin.h>
#include <iostream>
int main() {
__v16qi a = { 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
__v16qi b = _mm_set1_epi8(-1);
std::cout << (int)(a / b)[0] << ", " << (int)(a / b)[1] << '\n';
}
% clang++ -o x x.cc && ./x
-1, 1
% clang++ -funsigned-char -o x x.cc && ./x
0, 1
However, while this may be surprising, both Clang and GCC agree.
Differential Revision: http://reviews.llvm.org/D13324
llvm-svn: 249097
2015-10-02 07:40:12 +08:00
|
|
|
/* This function always performs a signed extension, but __v16qi is a char
|
|
|
|
which may be signed or unsigned, so use __v16qs. */
|
|
|
|
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1, 2, 3), __v4si);
|
2010-03-16 07:22:58 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepi8_epi64(__m128i __V)
|
|
|
|
{
|
Fix the SSE4 byte sign extension in a cleaner way, and more thoroughly
test that our intrinsics behave the same under -fsigned-char and
-funsigned-char.
This further testing uncovered that AVX-2 has a broken cmpgt for 8-bit
elements, and has for a long time. This is fixed in the same way as
SSE4 handles the case.
The other ISA extensions currently work correctly because they use
specific instruction intrinsics. As soon as they are rewritten in terms
of generic IR, they will need to add these special casts. I've added the
necessary testing to catch this however, so we shouldn't have to chase
it down again.
I considered changing the core typedef to be signed, but that seems like
a bad idea. Notably, it would be an ABI break if anyone is reaching into
the innards of the intrinsic headers and passing __v16qi on an API
boundary. I can't be completely confident that this wouldn't happen due
to a macro expanding in a lambda, etc., so it seems much better to leave
it alone. It also matches GCC's behavior exactly.
A fun side note is that for both GCC and Clang, -funsigned-char really
does change the semantics of __v16qi. To observe this, consider:
% cat x.cc
#include <smmintrin.h>
#include <iostream>
int main() {
__v16qi a = { 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
__v16qi b = _mm_set1_epi8(-1);
std::cout << (int)(a / b)[0] << ", " << (int)(a / b)[1] << '\n';
}
% clang++ -o x x.cc && ./x
-1, 1
% clang++ -funsigned-char -o x x.cc && ./x
0, 1
However, while this may be surprising, both Clang and GCC agree.
Differential Revision: http://reviews.llvm.org/D13324
llvm-svn: 249097
2015-10-02 07:40:12 +08:00
|
|
|
/* This function always performs a signed extension, but __v16qi is a char
|
|
|
|
which may be signed or unsigned, so use __v16qs. */
|
|
|
|
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1), __v2di);
|
2010-03-16 07:22:58 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepi16_epi32(__m128i __V)
|
|
|
|
{
|
2015-09-19 23:12:38 +08:00
|
|
|
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v8hi)__V, (__v8hi)__V, 0, 1, 2, 3), __v4si);
|
2010-03-16 07:22:58 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepi16_epi64(__m128i __V)
|
|
|
|
{
|
2015-09-19 23:12:38 +08:00
|
|
|
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v8hi)__V, (__v8hi)__V, 0, 1), __v2di);
|
2010-03-16 07:22:58 +08:00
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepi32_epi64(__m128i __V)
|
|
|
|
{
|
2015-09-19 23:12:38 +08:00
|
|
|
return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v4si)__V, (__v4si)__V, 0, 1), __v2di);
|
2010-03-16 07:22:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* SSE4 Packed Integer Zero-Extension. */
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepu8_epi16(__m128i __V)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pmovzxbw128((__v16qi) __V);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepu8_epi32(__m128i __V)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pmovzxbd128((__v16qi)__V);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepu8_epi64(__m128i __V)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pmovzxbq128((__v16qi)__V);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepu16_epi32(__m128i __V)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pmovzxwd128((__v8hi)__V);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepu16_epi64(__m128i __V)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pmovzxwq128((__v8hi)__V);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_cvtepu32_epi64(__m128i __V)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_pmovzxdq128((__v4si)__V);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* SSE4 Pack with Unsigned Saturation. */
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-16 07:22:58 +08:00
|
|
|
_mm_packus_epi32(__m128i __V1, __m128i __V2)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_packusdw128((__v4si)__V1, (__v4si)__V2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* SSE4 Multiple Packed Sums of Absolute Difference. */
|
2012-03-30 15:01:17 +08:00
|
|
|
#define _mm_mpsadbw_epu8(X, Y, M) __extension__ ({ \
|
2015-11-10 13:08:05 +08:00
|
|
|
(__m128i) __builtin_ia32_mpsadbw128((__v16qi)(__m128i)(X), \
|
|
|
|
(__v16qi)(__m128i)(Y), (M)); })
|
2010-03-16 07:22:58 +08:00
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2012-03-30 13:41:28 +08:00
|
|
|
_mm_minpos_epu16(__m128i __V)
|
|
|
|
{
|
|
|
|
return (__m128i) __builtin_ia32_phminposuw128((__v8hi)__V);
|
|
|
|
}
|
|
|
|
|
2015-06-17 15:09:32 +08:00
|
|
|
/* Handle the sse4.2 definitions here. */
|
|
|
|
|
2010-03-20 15:43:28 +08:00
|
|
|
/* These definitions are normally in nmmintrin.h, but gcc puts them in here
|
|
|
|
so we'll do the same. */
|
2015-06-17 15:09:32 +08:00
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
#undef __DEFAULT_FN_ATTRS
|
|
|
|
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4.2")))
|
2010-03-20 15:43:28 +08:00
|
|
|
|
|
|
|
/* These specify the type of data that we're comparing. */
|
|
|
|
#define _SIDD_UBYTE_OPS 0x00
|
|
|
|
#define _SIDD_UWORD_OPS 0x01
|
|
|
|
#define _SIDD_SBYTE_OPS 0x02
|
|
|
|
#define _SIDD_SWORD_OPS 0x03
|
|
|
|
|
|
|
|
/* These specify the type of comparison operation. */
|
|
|
|
#define _SIDD_CMP_EQUAL_ANY 0x00
|
|
|
|
#define _SIDD_CMP_RANGES 0x04
|
|
|
|
#define _SIDD_CMP_EQUAL_EACH 0x08
|
|
|
|
#define _SIDD_CMP_EQUAL_ORDERED 0x0c
|
|
|
|
|
|
|
|
/* These macros specify the polarity of the operation. */
|
|
|
|
#define _SIDD_POSITIVE_POLARITY 0x00
|
|
|
|
#define _SIDD_NEGATIVE_POLARITY 0x10
|
|
|
|
#define _SIDD_MASKED_POSITIVE_POLARITY 0x20
|
|
|
|
#define _SIDD_MASKED_NEGATIVE_POLARITY 0x30
|
|
|
|
|
|
|
|
/* These macros are used in _mm_cmpXstri() to specify the return. */
|
|
|
|
#define _SIDD_LEAST_SIGNIFICANT 0x00
|
|
|
|
#define _SIDD_MOST_SIGNIFICANT 0x40
|
|
|
|
|
|
|
|
/* These macros are used in _mm_cmpXstri() to specify the return. */
|
|
|
|
#define _SIDD_BIT_MASK 0x00
|
|
|
|
#define _SIDD_UNIT_MASK 0x40
|
|
|
|
|
|
|
|
/* SSE4.2 Packed Comparison Intrinsics. */
|
2015-11-11 11:47:10 +08:00
|
|
|
#define _mm_cmpistrm(A, B, M) \
|
|
|
|
(__m128i)__builtin_ia32_pcmpistrm128((__v16qi)(__m128i)(A), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(M))
|
|
|
|
#define _mm_cmpistri(A, B, M) \
|
|
|
|
(int)__builtin_ia32_pcmpistri128((__v16qi)(__m128i)(A), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(M))
|
2010-03-20 15:43:28 +08:00
|
|
|
|
|
|
|
#define _mm_cmpestrm(A, LA, B, LB, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(__m128i)__builtin_ia32_pcmpestrm128((__v16qi)(__m128i)(A), (int)(LA), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(LB), \
|
|
|
|
(int)(M))
|
2011-12-09 17:23:55 +08:00
|
|
|
#define _mm_cmpestri(A, LA, B, LB, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(int)__builtin_ia32_pcmpestri128((__v16qi)(__m128i)(A), (int)(LA), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(LB), \
|
|
|
|
(int)(M))
|
2015-09-12 10:55:19 +08:00
|
|
|
|
2010-03-20 15:43:28 +08:00
|
|
|
/* SSE4.2 Packed Comparison Intrinsics and EFlag Reading. */
|
2011-11-08 12:13:51 +08:00
|
|
|
#define _mm_cmpistra(A, B, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(int)__builtin_ia32_pcmpistria128((__v16qi)(__m128i)(A), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(M))
|
2011-11-08 12:13:51 +08:00
|
|
|
#define _mm_cmpistrc(A, B, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(int)__builtin_ia32_pcmpistric128((__v16qi)(__m128i)(A), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(M))
|
2011-11-08 12:13:51 +08:00
|
|
|
#define _mm_cmpistro(A, B, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(int)__builtin_ia32_pcmpistrio128((__v16qi)(__m128i)(A), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(M))
|
2011-11-08 12:13:51 +08:00
|
|
|
#define _mm_cmpistrs(A, B, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(int)__builtin_ia32_pcmpistris128((__v16qi)(__m128i)(A), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(M))
|
2011-11-08 12:13:51 +08:00
|
|
|
#define _mm_cmpistrz(A, B, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(int)__builtin_ia32_pcmpistriz128((__v16qi)(__m128i)(A), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(M))
|
2010-03-20 15:43:28 +08:00
|
|
|
|
|
|
|
#define _mm_cmpestra(A, LA, B, LB, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(int)__builtin_ia32_pcmpestria128((__v16qi)(__m128i)(A), (int)(LA), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(LB), \
|
|
|
|
(int)(M))
|
2010-03-20 15:43:28 +08:00
|
|
|
#define _mm_cmpestrc(A, LA, B, LB, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(int)__builtin_ia32_pcmpestric128((__v16qi)(__m128i)(A), (int)(LA), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(LB), \
|
|
|
|
(int)(M))
|
2010-03-20 15:43:28 +08:00
|
|
|
#define _mm_cmpestro(A, LA, B, LB, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(int)__builtin_ia32_pcmpestrio128((__v16qi)(__m128i)(A), (int)(LA), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(LB), \
|
|
|
|
(int)(M))
|
2010-03-20 15:43:28 +08:00
|
|
|
#define _mm_cmpestrs(A, LA, B, LB, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(int)__builtin_ia32_pcmpestris128((__v16qi)(__m128i)(A), (int)(LA), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(LB), \
|
|
|
|
(int)(M))
|
2010-03-20 15:43:28 +08:00
|
|
|
#define _mm_cmpestrz(A, LA, B, LB, M) \
|
2015-11-11 11:47:10 +08:00
|
|
|
(int)__builtin_ia32_pcmpestriz128((__v16qi)(__m128i)(A), (int)(LA), \
|
|
|
|
(__v16qi)(__m128i)(B), (int)(LB), \
|
|
|
|
(int)(M))
|
2010-03-20 15:43:28 +08:00
|
|
|
|
|
|
|
/* SSE4.2 Compare Packed Data -- Greater Than. */
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ __m128i __DEFAULT_FN_ATTRS
|
2010-03-20 15:43:28 +08:00
|
|
|
_mm_cmpgt_epi64(__m128i __V1, __m128i __V2)
|
|
|
|
{
|
2011-12-20 17:55:26 +08:00
|
|
|
return (__m128i)((__v2di)__V1 > (__v2di)__V2);
|
2010-03-20 15:43:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* SSE4.2 Accumulate CRC32. */
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ unsigned int __DEFAULT_FN_ATTRS
|
2010-03-20 15:43:28 +08:00
|
|
|
_mm_crc32_u8(unsigned int __C, unsigned char __D)
|
|
|
|
{
|
|
|
|
return __builtin_ia32_crc32qi(__C, __D);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ unsigned int __DEFAULT_FN_ATTRS
|
2010-03-20 15:43:28 +08:00
|
|
|
_mm_crc32_u16(unsigned int __C, unsigned short __D)
|
|
|
|
{
|
|
|
|
return __builtin_ia32_crc32hi(__C, __D);
|
|
|
|
}
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ unsigned int __DEFAULT_FN_ATTRS
|
2010-03-20 15:43:28 +08:00
|
|
|
_mm_crc32_u32(unsigned int __C, unsigned int __D)
|
|
|
|
{
|
|
|
|
return __builtin_ia32_crc32si(__C, __D);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __x86_64__
|
2015-06-30 21:36:19 +08:00
|
|
|
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
|
2010-03-20 15:43:28 +08:00
|
|
|
_mm_crc32_u64(unsigned long long __C, unsigned long long __D)
|
|
|
|
{
|
|
|
|
return __builtin_ia32_crc32di(__C, __D);
|
|
|
|
}
|
|
|
|
#endif /* __x86_64__ */
|
|
|
|
|
2015-06-30 21:36:19 +08:00
|
|
|
#undef __DEFAULT_FN_ATTRS
|
2015-06-17 15:09:20 +08:00
|
|
|
|
2011-12-30 00:10:46 +08:00
|
|
|
#ifdef __POPCNT__
|
|
|
|
#include <popcntintrin.h>
|
|
|
|
#endif
|
2010-03-20 15:43:28 +08:00
|
|
|
|
2010-03-04 10:56:19 +08:00
|
|
|
#endif /* _SMMINTRIN_H */
|