如何在MSVC中有效地将两个__m128d转换为一个__m128i?

2023-12-15

转换然后移位然后按位或是从两个转换的唯一方法__m128d到一个单一的__m128i?

这对于 x64 构建中的 Xcode 来说是完全可以接受的

m128d v2dHi = ....
m128d v2dLo = ....
__m128i v4i = _mm_set_epi64(_mm_cvtpd_pi32(v2dHi), _mm_cvtpd_pi32(v2dLo))

反汇编显示_mm_cvtpd_pi32正在使用。但是,Visual Studio 无法编译它,并报告链接器错误。 VS 文档支持这一点,说_mm_cvtpd_pi32x64 上不支持。

我不太担心它不可用,但是两次转换,一次移位,然后按位还是最快的方法?


如果出现链接器错误,您可能会忽略有关未声明的内部函数的警告。

您当前的代码很有可能编译成糟糕的 asm。如果它编译为向量移位和 OR,则它已经编译为次优代码。 (更新:这不是它编译的结果,我不知道你是从哪里得到这个想法的。)

Use 2x _mm_cvtpd_epi32得到两个__m128i每个向量的后 2 个元素都包含您想要的整数。使用_mm_unpacklo_epi64将这两个低半部分组合成一个向量,其中包含您想要的所有 4 个元素。


编译器输出来自Godbolt 编译器资源管理器上的 clang3.8.1。 (我认为 Xcode 默认使用 clang)。

#include <immintrin.h>

// the good version
__m128i pack_double_to_int(__m128d a, __m128d b) {
    return _mm_unpacklo_epi64(_mm_cvtpd_epi32(a), _mm_cvtpd_epi32(b));
}
    cvtpd2dq        xmm0, xmm0
    cvtpd2dq        xmm1, xmm1
    punpcklqdq      xmm0, xmm1      # xmm0 = xmm0[0],xmm1[0]
    ret

// the original
__m128i pack_double_to_int_badMMX(__m128d a, __m128d b) {
    return _mm_set_epi64(_mm_cvtpd_pi32(b), _mm_cvtpd_pi32(a));
}
    cvtpd2pi        mm0, xmm1
    cvtpd2pi        mm1, xmm0
    movq2dq xmm1, mm0
    movq2dq xmm0, mm1
    punpcklqdq      xmm0, xmm1      # xmm0 = xmm0[0],xmm1[0]
      # note the lack of EMMS, because of not using the intrinsic for it
    ret

当SSE2及更高版本可用时,MMX几乎完全没有用;只是避免它。请参阅sse标记 wiki 以获得一些指南。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在MSVC中有效地将两个__m128d转换为一个__m128i? 的相关文章

随机推荐