您提到的link 使用的是非临时存储。我之前已经多次讨论过这个问题,例如here 和here。我建议您在继续之前阅读这些内容。
但是,如果您真的想在此处提到的链接中生成内联汇编代码,您可以这样做:改用内部函数。
您无法使用 GCC 编译该代码的事实正是创建内部函数的原因之一。对于 32 位和 64 位代码,内联汇编必须以不同的方式编写,并且每个编译器通常具有不同的语法。内在函数解决了所有这些问题。
以下代码应在 32 位和 64 位模式下使用 GCC、Clang、ICC 和 MSVC 编译。
#include "xmmintrin.h"
void X_aligned_memcpy_sse2(char* dest, const char* src, const unsigned long size)
{
for(int i=size/128; i>0; i--) {
__m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
_mm_prefetch(src + 128, _MM_HINT_NTA);
_mm_prefetch(src + 160, _MM_HINT_NTA);
_mm_prefetch(src + 194, _MM_HINT_NTA);
_mm_prefetch(src + 224, _MM_HINT_NTA);
xmm0 = _mm_load_si128((__m128i*)&src[ 0]);
xmm1 = _mm_load_si128((__m128i*)&src[ 16]);
xmm2 = _mm_load_si128((__m128i*)&src[ 32]);
xmm3 = _mm_load_si128((__m128i*)&src[ 48]);
xmm4 = _mm_load_si128((__m128i*)&src[ 64]);
xmm5 = _mm_load_si128((__m128i*)&src[ 80]);
xmm6 = _mm_load_si128((__m128i*)&src[ 96]);
xmm7 = _mm_load_si128((__m128i*)&src[ 112]);
_mm_stream_si128((__m128i*)&dest[ 0], xmm0);
_mm_stream_si128((__m128i*)&dest[ 16], xmm1);
_mm_stream_si128((__m128i*)&dest[ 32], xmm2);
_mm_stream_si128((__m128i*)&dest[ 48], xmm3);
_mm_stream_si128((__m128i*)&dest[ 64], xmm4);
_mm_stream_si128((__m128i*)&dest[ 80], xmm5);
_mm_stream_si128((__m128i*)&dest[ 96], xmm6);
_mm_stream_si128((__m128i*)&dest[ 112], xmm7);
src += 128;
dest += 128;
}
}
请注意,src 和 dest 需要 16 字节对齐,size 需要是 128 的倍数。
但是,我不建议使用此代码。在非临时存储有用的情况下,循环展开是无用的,显式预取很少有用。你可以简单地做
void copy(char *x, char *y, int n)
{
#pragma omp parallel for schedule(static)
for(int i=0; i<n/16; i++) {
_mm_stream_ps((float*)&y[16*i], _mm_load_ps((float*)&x[16*i]));
}
}
更多详情请见here。
这是来自 X_aligned_memcpy_sse2 函数的程序集,它使用带有 GCC -O3 -S -masm=intel 的内部函数。请注意,它与here 基本相同。
shr rdx, 7
test edx, edx
mov eax, edx
jle .L1
.L5:
sub rsi, -128
movdqa xmm6, XMMWORD PTR [rsi-112]
prefetchnta [rsi]
prefetchnta [rsi+32]
prefetchnta [rsi+66]
movdqa xmm5, XMMWORD PTR [rsi-96]
prefetchnta [rsi+96]
sub rdi, -128
movdqa xmm4, XMMWORD PTR [rsi-80]
movdqa xmm3, XMMWORD PTR [rsi-64]
movdqa xmm2, XMMWORD PTR [rsi-48]
movdqa xmm1, XMMWORD PTR [rsi-32]
movdqa xmm0, XMMWORD PTR [rsi-16]
movdqa xmm7, XMMWORD PTR [rsi-128]
movntdq XMMWORD PTR [rdi-112], xmm6
movntdq XMMWORD PTR [rdi-96], xmm5
movntdq XMMWORD PTR [rdi-80], xmm4
movntdq XMMWORD PTR [rdi-64], xmm3
movntdq XMMWORD PTR [rdi-48], xmm2
movntdq XMMWORD PTR [rdi-128], xmm7
movntdq XMMWORD PTR [rdi-32], xmm1
movntdq XMMWORD PTR [rdi-16], xmm0
sub eax, 1
jne .L5
.L1:
rep ret