12

SSE を利用するために、(C/C++ コードで) インライン アセンブラを実装しようとしています。値を (XMM レジスターまたはメモリから) 別の XMM レジスターにコピーおよび複製したいと考えています。たとえば、メモリに値 {1, 2, 3, 4} があるとします。これらの値をコピーして、xmm1 に {1, 1, 1, 1}、xmm2 に {2, 2, 2, 2} などを入力するようにします。

Intel のリファレンス マニュアルを調べたところ、これを行うための説明が見つかりませんでした。繰り返される MOVSS とローテーションの組み合わせを (PSHUFD 経由で) 使用する必要がありますか?

4

3 に答える 3

15

次の 2 つの方法があります。

  1. shufps排他的に使用:

    __m128 first = ...;
    __m128 xxxx = _mm_shuffle_ps(first, first, 0x00); // _MM_SHUFFLE(0, 0, 0, 0)
    __m128 yyyy = _mm_shuffle_ps(first, first, 0x55); // _MM_SHUFFLE(1, 1, 1, 1)
    __m128 zzzz = _mm_shuffle_ps(first, first, 0xAA); // _MM_SHUFFLE(2, 2, 2, 2)
    __m128 wwww = _mm_shuffle_ps(first, first, 0xFF); // _MM_SHUFFLE(3, 3, 3, 3)
    
  2. _mm_set1_psとを使用してコンパイラに最適な方法を選択させます_mm_cvtss_f32

    __m128 first = ...;
    __m128 xxxx = _mm_set1_ps(_mm_cvtss_f32(first));
    

ここで説明されているように、2 番目の方法は MSVC で恐ろしいコードを生成し、最初のオプションとは異なり、結果として「xxxx」のみを生成することに注意してください。

SSE を利用するためにインライン アセンブラを (C/C++ コードで) 実装しようとしています。

これは非常に移植性がありません。組み込み関数を使用します。

于 2010-01-06T20:07:24.440 に答える
6

ソースを宛先レジスタに移動します。「shufps」を使用し、新しい dest レジスタを 2 回使用してから、適切なマスクを選択します。

次の例では、XMM2.x の値を XMM0.xyzw にブロードキャストします。

MOVAPS XMM0, XMM2
SHUFPS XMM0, XMM0, 0x00
于 2010-01-06T20:05:34.733 に答える
2

値がメモリ内で 16 バイトにアラインされている場合:

movdqa    (mem),    %xmm1
pshufd    $0xff,    %xmm1,    %xmm4
pshufd    $0xaa,    %xmm1,    %xmm3
pshufd    $0x55,    %xmm1,    %xmm2
pshufd    $0x00,    %xmm1,    %xmm1

そうでない場合は、アラインされていないロード、または 4 つのスカラー ロードを実行できます。新しいプラットフォームでは、アラインされていないロードが高速になるはずです。古いプラットフォームでは、スカラー ロードが優先される場合があります。

他の人が指摘したように、 も使用できますshufps

于 2010-01-06T20:08:45.623 に答える