1

转换然后移位然后按位或'ing是从两个转换__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_pi32在 x64 上不受支持。

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

4

1 回答 1

2

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

您当前的代码编译为可怕的 asm 的风险很高。如果它编译为向量移位和 OR,则它已经编译为次优代码。(更新:这不是它编译成的,IDK 你有这个想法的地方。)

使用 2x _mm_cvtpd_epi32在每个向量的低 2 个元素中获取两个__m128i向量,其中包含您想要的整数。使用_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 几乎完全没用;只是避免它。有关一些指南,请参阅标签 wiki。

于 2016-09-15T04:32:29.000 回答