1

__m128d2から1 に変換する唯一の方法は、変換してからシフトしてからビット単位の論理和をとること__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 ではサポートされていません。

利用できないことをあまり心配していませんが、2回の変換、シフト、そしてビットごとの変換が最速の方法ですか?

4

1 に答える 1

2

リンカー エラーが発生した場合は、宣言されていない組み込み関数に関する警告を無視している可能性があります。

現在のコードは、ひどい asm にコンパイルされるリスクが高いです。vector-shift と OR にコンパイルされた場合は、すでに次善のコードにコンパイルされています。(更新:それはそれがコンパイルするものではありません.IDKはあなたがそのアイデアを得た場所です。)

2x _mm_cvtpd_epi32__m128iを使用して、それぞれの下位 2 要素に必要な int を持つ2 つのベクトルを取得します。_mm_unpacklo_epi64を使用して、これら 2 つの下位半分を、必要な 4 つの要素すべてを持つ 1 つのベクトルに結合します。


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 に答える