我正在玩SIMD,并想知道为什么没有类似于_mm_cvtsd_f64的模拟来从__m128d提取高阶浮点。
GCC 4.6+有一个扩展,可以很好地实现这一目标:
__m128d a = ...;
double d1 = a[0];
double d2 = a[1];
但是对于较旧的GCC(即4.4。),我能够设法得到这个的唯一方法是使用__builtin_ia32_vec_ext_v2df定义我自己的模拟函数,即:
extern __inline double __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_cvtsd_f64_h (__m128d __A)
{
return __builtin_ia32_vec_ext_v2df (__A, 1);
}
__m128d a = ...;
double d1 = _mm_cvtsd_f64(a);
double d2 = _mm_cvtsd_f64_h(a);
这真的是要走的路吗?是否有任何替代方案不使用潜在的特定于编译器的__builtin东西?再次 - 为什么没有_mm_cvtsd_f64_h或类似的预定义?
我想出的另一种选择是btw慢得多:
_mm_cvtsd_f64_h(__m128d __A) {
double d[2];
_mm_store_pd(d, __A);
return d[1];
}
答案 0 :(得分:2)
我建议您使用以下代码:
inline static _mm_cvtsd_f64_h(__m128d x) {
return _mm_cvtsd_f64(_mm_unpackhi_pd(x, x));
}
这可能是获得xmm
寄存器上半部分的最快方法,并且它与MSVC / icc / gcc / clang兼容。
答案 1 :(得分:0)
你可以使用联盟:
union {
__m128d v;
double a[2];
} U;
将__m128d分配给U.v并回读U.a [0]或U.a [1]。任何体面的编译器都会优化冗余存储和加载。