128ビットのxmm
レジスタを2つの64ビットクワッドワードに分割する方法はありますか?XMM 128ビットレジスタを2つの64ビット整数レジスタに分割する方法は?
私はxmm1
では非常に数が多いとr10
、またはRAX
とRDX
にr9
に高いクワッドワードと下位クワッドワードを取得したいです。
movlpd
またはmovhpd
は、reg to memまたはその逆の場合にのみ機能します。
128ビットのxmm
レジスタを2つの64ビットクワッドワードに分割する方法はありますか?XMM 128ビットレジスタを2つの64ビット整数レジスタに分割する方法は?
私はxmm1
では非常に数が多いとr10
、またはRAX
とRDX
にr9
に高いクワッドワードと下位クワッドワードを取得したいです。
movlpd
またはmovhpd
は、reg to memまたはその逆の場合にのみ機能します。
SSE2(x86-64のベースライン)には、XMMと整数レジスタ間で直接データを移動するための命令があります(メモリをバウンドせずに)。ベクトルの下位要素は簡単です:MOVD or MOVQ。より高い要素を抽出するには、必要な要素をベクトルの下位要素にシャッフルするだけです。
16ビット以外のサイズ(例:PEXTRQ)のSSE4.1も追加されました。 code-size以外はnot actually faster than a separate shuffle and movq on any existing CPUsですが、余分なtmpレジスタは必要ありません。
#SSE4.1
movq rax, xmm0 # low qword
pextrq rdx, xmm0, 1 # high qword
# 128b result in rdx:rax, ready for use with div r64 for example.
# (But watch out for #DE on overflow)
# also ready for returning as a __int128_t in the SystemV x86-64 ABI
#SSE2
movq r10, xmm0
punpckhqdq xmm0, xmm0 # broadcast the high half of xmm0 to both halves
movq r9, xmm0
これを行う最も効率的な方法は、PUNPCKHQDQです。 65nm Core2(Merom/Conroe)のように、64ビットより小さい要素サイズのための遅いシャッフルを持つ古いCPUでも高速です。詳細については、my horizontal sum answerを参照してください。 PUNPCKHQDQは即値オペランドを持たず、SSE2のみであるため、コードサイズはわずか4バイトです。
xmm0の元の値を保持するには、異なる宛先のpshufd
を使用します。あるいは、ハイ・ロー・ハーフをイン・プレースなどに入れ替えることができます。
movlpdまたはmovhpd ...
今までにそれらを使用するにはポイントがありません。代わりにmovlps/movhpsを使用してください。なぜなら、それらがより短く、CPUがfloatとdoubleを気にしないからです。
movhlps xmm1, xmm0
を使用すると、xmm0の上位半分を別のレジスタに抽出できますが、FPシャッフルと整数ベクトル演算を混在させると、一部のCPU(特にIntel Nehalem)でバイパス遅延が発生します。また、xmm1への依存性がレイテンシのボトルネックを引き起こすことに注意してください。
これは一般的にpshufd
を好んでいます。しかし、movhlps
が高速で整数ドメインで実行され、pshufd
が遅いCore2のような特定のCPUをチューニングする場合は、movhlps
を使用できます。
いくつかの提案を得るためにgcc(そしてバージョンが '0')で' long long f(long long __attribute __(vector_size(16)))x){return x [1];} 'をコンパイルしてください... –