_mm_cvtsd_f64用于高阶浮点的模拟

时间:2013-10-14 11:38:37

标签: c++ c performance simd intrinsics

我正在玩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];
}

2 个答案:

答案 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]。任何体面的编译器都会优化冗余存储和加载。