如何在不使用任何SSE指令的情况下设置__m128i? [英] How can I set __m128i without using of any SSE instruction?
问题描述
我有很多函数使用相同的常量__m128i值. 例如:
I have many function which use the same constant __m128i values. For example:
const __m128i K8 = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
const __m128i K16 = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8);
const __m128i K32 = _mm_setr_epi32(1, 2, 3, 4);
所以我想将所有这些常量存储在一个地方. 但是有一个问题:我在运行时检查现有的CPU扩展. 如果CPU不支持SSE(或AVX),则在常量初始化期间将导致程序崩溃.
So I want to store all these constants in an one place. But there is a problem: I perform checking of existed CPU extension in run time. If the CPU doesn't support for example SSE (or AVX) than will be a program crash during constants initialization.
那么不使用SSE就可以初始化这些常量吗?
So is it possible to initialize these constants without using of SSE?
推荐答案
可以在不使用SSE指令的情况下初始化__m128i向量,但这取决于编译器定义__m128i的方式.
Initialization of __m128i vector without using SSE instructions is possible but it depends on how to compiler defines __m128i.
对于Microsoft Visual Studio,您可以定义下一个宏(它将__m128i定义为char [16]):
For Microsoft Visual Studio you can define next macros (it defines __m128i as char[16]):
template <class T> inline char GetChar(T value, size_t index)
{
return ((char*)&value)[index];
}
#define AS_CHAR(a) char(a)
#define AS_2CHARS(a) \
GetChar(int16_t(a), 0), GetChar(int16_t(a), 1)
#define AS_4CHARS(a) \
GetChar(int32_t(a), 0), GetChar(int32_t(a), 1), \
GetChar(int32_t(a), 2), GetChar(int32_t(a), 3)
#define _MM_SETR_EPI8(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af) \
{AS_CHAR(a0), AS_CHAR(a1), AS_CHAR(a2), AS_CHAR(a3), \
AS_CHAR(a4), AS_CHAR(a5), AS_CHAR(a6), AS_CHAR(a7), \
AS_CHAR(a8), AS_CHAR(a9), AS_CHAR(aa), AS_CHAR(ab), \
AS_CHAR(ac), AS_CHAR(ad), AS_CHAR(ae), AS_CHAR(af)}
#define _MM_SETR_EPI16(a0, a1, a2, a3, a4, a5, a6, a7) \
{AS_2CHARS(a0), AS_2CHARS(a1), AS_2CHARS(a2), AS_2CHARS(a3), \
AS_2CHARS(a4), AS_2CHARS(a5), AS_2CHARS(a6), AS_2CHARS(a7)}
#define _MM_SETR_EPI32(a0, a1, a2, a3) \
{AS_4CHARS(a0), AS_4CHARS(a1), AS_4CHARS(a2), AS_4CHARS(a3)}
对于GCC,它将是(将__m128i定义为long long [2]):
For GCC it will be (it defines __m128i as long long[2]):
#define CHAR_AS_LONGLONG(a) (((long long)a) & 0xFF)
#define SHORT_AS_LONGLONG(a) (((long long)a) & 0xFFFF)
#define INT_AS_LONGLONG(a) (((long long)a) & 0xFFFFFFFF)
#define LL_SETR_EPI8(a, b, c, d, e, f, g, h) \
CHAR_AS_LONGLONG(a) | (CHAR_AS_LONGLONG(b) << 8) | \
(CHAR_AS_LONGLONG(c) << 16) | (CHAR_AS_LONGLONG(d) << 24) | \
(CHAR_AS_LONGLONG(e) << 32) | (CHAR_AS_LONGLONG(f) << 40) | \
(CHAR_AS_LONGLONG(g) << 48) | (CHAR_AS_LONGLONG(h) << 56)
#define LL_SETR_EPI16(a, b, c, d) \
SHORT_AS_LONGLONG(a) | (SHORT_AS_LONGLONG(b) << 16) | \
(SHORT_AS_LONGLONG(c) << 32) | (SHORT_AS_LONGLONG(d) << 48)
#define LL_SETR_EPI32(a, b) \
INT_AS_LONGLONG(a) | (INT_AS_LONGLONG(b) << 32)
#define _MM_SETR_EPI8(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af) \
{LL_SETR_EPI8(a0, a1, a2, a3, a4, a5, a6, a7), LL_SETR_EPI8(a8, a9, aa, ab, ac, ad, ae, af)}
#define _MM_SETR_EPI16(a0, a1, a2, a3, a4, a5, a6, a7) \
{LL_SETR_EPI16(a0, a1, a2, a3), LL_SETR_EPI16(a4, a5, a6, a7)}
#define _MM_SETR_EPI32(a0, a1, a2, a3) \
{LL_SETR_EPI32(a0, a1), LL_SETR_EPI32(a2, a3)}
因此在您的代码中,__ m128i常量的初始化将类似于:
So in your code initialization of __m128i constant will be look like:
const __m128i K8 = _MM_SETR_EPI8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
const __m128i K16 = _MM_SETR_EPI16(1, 2, 3, 4, 5, 6, 7, 8);
const __m128i K32 = _MM_SETR_EPI32(1, 2, 3, 4);
这篇关于如何在不使用任何SSE指令的情况下设置__m128i?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!