我正在尝试在C/C++代码中实现一些内联汇编,以利用SSE。我想复制和复制值(从XMM寄存器或存储器)到另一个XMM寄存器。例如,假设我有一些值{1, 2, 3, 4}在存储器中。我想将这些值复制,使得xmm1被填充为{1, 1, 1, 1},xmm2为{2, 2, 2, 2},等等。
查阅英特尔参考手册,我没有找到可用于此的指令。我是否只需要使用重复的MOVSS和旋转(通过PSHUFD)的组合?
我正在尝试在C/C++代码中实现一些内联汇编,以利用SSE。我想复制和复制值(从XMM寄存器或存储器)到另一个XMM寄存器。例如,假设我有一些值{1, 2, 3, 4}在存储器中。我想将这些值复制,使得xmm1被填充为{1, 1, 1, 1},xmm2为{2, 2, 2, 2},等等。
查阅英特尔参考手册,我没有找到可用于此的指令。我是否只需要使用重复的MOVSS和旋转(通过PSHUFD)的组合?
有两种方法:
仅使用 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)
让编译器使用_mm_set1_ps
和_mm_cvtss_f32
来选择最佳方法: __m128 first = ...;
__m128 xxxx = _mm_set1_ps(_mm_cvtss_f32(first));
请注意,第二种方法在MSVC上会产生可怕的代码,如此讨论,并且只会产生'xxxx'作为结果,不像第一种选项。
我正在尝试在C/C++代码中实现一些内联汇编以利用SSE。
这是高度不可移植的。使用内置函数。
将源寄存器移动到目标寄存器。使用“shufps”,只需两次使用新的目标寄存器,然后选择适当的掩码。
下面的示例将XMM2.x的值广播到XMM0.xyzw
MOVAPS XMM0, XMM2
SHUFPS XMM0, XMM0, 0x00
如果您的值在内存中是16字节对齐的:
movdqa (mem), %xmm1
pshufd $0xff, %xmm1, %xmm4
pshufd $0xaa, %xmm1, %xmm3
pshufd $0x55, %xmm1, %xmm2
pshufd $0x00, %xmm1, %xmm1
如果不行,您可以进行非对齐加载,或者进行四个标量加载。在较新的平台上,非对齐加载应该更快;在旧平台上,标量加载可能会更快。
正如其他人所指出的那样,您还可以使用shufps
。
pshufd
是SSE2指令。 - LiraNuna