(注意:虽然这个问题是关于"存储"的,但"加载"情况具有相同的问题并且是完全对称的.)
SSE内在函数提供_mm_storeu_pd具有以下签名的函数:
void _mm_storeu_pd (double *p, __m128d a);
Run Code Online (Sandbox Code Playgroud)
所以,如果我有两个双精度矢量,并且我想将它存储到两个双精度数组中,我可以使用这个内在函数.
但是,我的矢量不是两个双打; 它是两个64位整数,我想将它存储到两个64位整数的数组中.也就是说,我想要一个具有以下签名的函数:
void _mm_storeu_epi64 (int64_t *p, __m128i a);
Run Code Online (Sandbox Code Playgroud)
但内在函数没有提供这样的功能.他们最接近的是_mm_storeu_si128:
void _mm_storeu_si128 (__m128i *p, __m128i a);
Run Code Online (Sandbox Code Playgroud)
问题是这个函数需要一个指针__m128i,而我的数组是一个数组int64_t.通过错误类型的指针写入对象违反了严格的别名,并且肯定是未定义的行为.我担心我的编译器现在或将来会重新排序或以其他方式优化存储,从而以奇怪的方式破坏我的程序.
要清楚,我想要的是一个我可以这样调用的函数:
__m128i v = _mm_set_epi64x(2,1);
int64_t ra[2];
_mm_storeu_epi64(&ra[0], v); // does not exist, so I want to implement it
Run Code Online (Sandbox Code Playgroud)
以下是创建此类功能的六次尝试.
void _mm_storeu_epi64(int64_t *p, __m128i a) {
_mm_storeu_si128(reinterpret_cast<__m128i *>(p), a);
}
Run Code Online (Sandbox Code Playgroud)
这似乎有我担心的严格别名问题.
void _mm_storeu_epi64(int64_t *p, __m128i a) {
_mm_storeu_si128(static_cast<__m128i *>(static_cast<void *>(p)), a);
}
Run Code Online (Sandbox Code Playgroud)