Assembly 组件x86-64-带-O3的movupd
我正在做一个关于x86-64汇编的练习,所以我使用-O3选项用GCC生成了汇编代码 用C编写的原始代码:Assembly 组件x86-64-带-O3的movupd,assembly,gcc,x86-64,Assembly,Gcc,X86 64,我正在做一个关于x86-64汇编的练习,所以我使用-O3选项用GCC生成了汇编代码 用C编写的原始代码: double dotprod(double *a, double *b, unsigned long long n) { double d1 = 0.0; double d2 = 0.0; for (unsigned long long i = 0; i < n; i += 2) { d1 += a[i] * b[i]; d2 += a[i + 1] *
double dotprod(double *a, double *b, unsigned long long n)
{
double d1 = 0.0;
double d2 = 0.0;
for (unsigned long long i = 0; i < n; i += 2) {
d1 += a[i] * b[i];
d2 += a[i + 1] * b[i + 1];
}
return (d1 + d2);
}
我想知道我们可以在一些指令中读取的int值是多少,例如
movupd 16(%rdi,%rax),%xmm1
“我们可以在一些指令中读取的int值是多少,例如movupd 16(%rdi,%rax),%xmm1”位移。请参阅“英特尔手册”中的第3.7.5节“指定偏移量”。它不是加载一个int
,而是加载两个双精度。这就是为什么GCC使用pd
指令,而不是movdqu
或更紧凑的movups
,后者在这里是更好的选择。但奇怪的是,下一条指令与movlpd
合并到该负载的低一半。IDK如果GCC想要在XMM1中获得2个非连续的双精度,那么首先进行16字节加载的意义是,与movsd
/movhpd
相比。GCC搞得一团糟。这是一个严重的错过优化/反优化。GCC7和更早的版本只使用标量,这可能比GCC8和更高版本(如您所示)的性能差。GCC-ffast math
正确,但简单的向量化已经按照源代码顺序进行了操作。我想知道GCC是否基本上是在分别对d1
和d2
进行向量化,而不是将这些C变量映射到单个向量的两半?报告如下
.L4:
movupd (%rdi,%rax), %xmm3
movupd (%rsi,%rax), %xmm2
movupd 16(%rdi,%rax), %xmm1
movlpd 8(%rdi,%rax), %xmm1
movhpd 16(%rdi,%rax), %xmm3
movhpd 16(%rsi,%rax), %xmm2
mulpd %xmm3, %xmm2
addsd %xmm2, %xmm4
unpckhpd %xmm2, %xmm2
addsd %xmm2, %xmm4
movupd 16(%rsi,%rax), %xmm2
movlpd 8(%rsi,%rax), %xmm2
addq $32, %rax
mulpd %xmm2, %xmm1
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm1
addsd %xmm0, %xmm2
movapd %xmm1, %xmm0
addsd %xmm2, %xmm0
cmpq %rdx, %rax
jne .L4
movq %rcx, %rdx
andq $-2, %rdx
leaq (%rdx,%rdx), %rax
cmpq %rcx, %rdx
je .L5