【发布时间】:2021-02-06 03:55:11
【问题描述】:
谁能解释一下clang的行为?
Array4Complex64 f1(Array4Complex64 a, Array4Complex64 b){
return a * b;
}
此函数计算 a 和 b 中的每个元素的复数乘积。我编译了两次,一次对 Array4Complex64 类型有对齐限制,一次没有。结果如下:
对齐:
f1(Array4Complex64, Array4Complex64): # @f1(Array4Complex64, Array4Complex64)
push rbp
mov rbp, rsp
and rsp, -32
sub rsp, 32
mov rax, rdi
vmovapd ymm0, ymmword ptr [rbp + 80]
vmovapd ymm1, ymmword ptr [rbp + 112]
vmovapd ymm2, ymmword ptr [rbp + 16]
vmovapd ymm3, ymmword ptr [rbp + 48]
vmulpd ymm4, ymm1, ymm3
vfmsub231pd ymm4, ymm0, ymm2 # ymm4 = (ymm0 * ymm2) - ymm4
vmovapd ymmword ptr [rdi], ymm4
vmulpd ymm0, ymm3, ymm0
vfmadd231pd ymm0, ymm1, ymm2 # ymm0 = (ymm1 * ymm2) + ymm0
vmovapd ymmword ptr [rdi + 32], ymm0
mov rsp, rbp
pop rbp
vzeroupper
ret
没有:
f1(Array4Complex64, Array4Complex64): # @f1(Array4Complex64, Array4Complex64)
mov rax, rdi
vmovupd ymm0, ymmword ptr [rsp + 72]
vmovupd ymm1, ymmword ptr [rsp + 104]
vmovupd ymm2, ymmword ptr [rsp + 8]
vmovupd ymm3, ymmword ptr [rsp + 40]
vmulpd ymm4, ymm1, ymm3
vfmsub231pd ymm4, ymm0, ymm2 # ymm4 = (ymm0 * ymm2) - ymm4
vmovupd ymmword ptr [rdi], ymm4
vmulpd ymm0, ymm3, ymm0
vfmadd231pd ymm0, ymm1, ymm2 # ymm0 = (ymm1 * ymm2) + ymm0
vmovupd ymmword ptr [rdi + 32], ymm0
vzeroupper
ret
结果是一样的,但是地址的计算方式不同:一次是相对于rbp,一次是相对于rsp。它不限于乘法,适用于任何计算。一个版本比另一个更好吗?
【问题讨论】:
-
您是如何提供这些对齐限制的?这只是一个简单的
alignas吗?我也对大会有点困惑。您标记为具有对齐限制的那个我会假设是未对齐的那个,因为前几条指令似乎计算了一个 32 位偏移对齐边界。
标签: c++ clang x86-64 memory-alignment avx