C++ _用于高阶浮点的mm_cvtsd_f64模拟

C++ _用于高阶浮点的mm_cvtsd_f64模拟,c++,c,performance,simd,intrinsics,C++,C,Performance,Simd,Intrinsics,我在玩弄SIMD,想知道为什么没有类似于_mm_cvtsd_f64的函数从u_m128d中提取高阶浮点 GCC 4.6+有一个扩展,可以很好地实现这一点: __m128d a = ...; double d1 = a[0]; double d2 = a[1]; 但在较旧的GCC(即4.4)上,我能够做到这一点的唯一方法是使用u内置u ia32 vec ext_v2df定义我自己的analogon函数,即: extern __inline double __attribute__((__gnu_

我在玩弄SIMD,想知道为什么没有类似于_mm_cvtsd_f64的函数从u_m128d中提取高阶浮点

GCC 4.6+有一个扩展,可以很好地实现这一点:

__m128d a = ...;
double d1 = a[0];
double d2 = a[1];
但在较旧的GCC(即4.4)上,我能够做到这一点的唯一方法是使用u内置u ia32 vec ext_v2df定义我自己的analogon函数,即:

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);
真的是这样吗?有没有不使用潜在编译器特定内置内容的替代方案?再说一遍,为什么没有_mm_cvtsd_f64_h或类似的预定义

顺便说一句,我可以想出的替代方案要慢得多:

_mm_cvtsd_f64_h(__m128d __A) {
    double d[2];
    _mm_store_pd(d, __A);
    return d[1];
}

您可以使用一个联合体:

union {
    __m128d v;
    double a[2];
} U;

将您的_m128d分配给U.v并读回U.a[0]或U.a[1]。任何合适的编译器都会优化冗余存储和加载。

我建议您使用以下代码:

inline static _mm_cvtsd_f64_h(__m128d x) {
    return _mm_cvtsd_f64(_mm_unpackhi_pd(x, x));
}

这可能是获取
xmm
寄存器上半部分的最快方法,它与MSVC/icc/gcc/clang兼容。

MOVHPD,\u mm\u storeh\u pd()内在的应该可以工作。我用MS和gcc编译器测试了Hans suggestion,它生成了我认为最简单的代码。我也在我的代码中测试了它,但似乎慢了几个百分点,也就是说,在下面被接受的答案之间,但比我上面糟糕的方法更快。谢谢你-工作起来很有魅力,速度和我上面发布的内置版本一样快!明显的UB@SeverinPappadeux:理论上是的,但实际上这是一种非常普遍的用法,编译器倾向于为它生成正确的代码(或者尽可能完全优化它)。@SeverinAppadeux:另请参见,特别是下面的评论。