我有一些 C++ 代码正在使用 MSVC 编译器 v14.24 编译为以下程序集:
00007FF798252D4C vmulsd xmm1,xmm1,xmm7
00007FF798252D50 vcvttsd2si rcx,xmm1
00007FF798252D55 vmulsd xmm1,xmm7,mmword ptr [rbx+28h]
00007FF798252D5A mov ecx,ecx
00007FF798252D5C imul rdx,rcx,0BB8h
00007FF798252D63 vcvttsd2si rcx,xmm1
00007FF798252D68 mov ecx,ecx
00007FF798252D6A add rdx,rcx
00007FF798252D6D add rdx,rdx
00007FF798252D70 cmp byte ptr [r14+rdx*8+8],0
00007FF798252D76 je applyActionMovements+15Dh (07FF798252D8Dh)
正如你所看到的,编译器添加了两个
mov ecx,ecx
这些指令对我来说没有任何意义,因为它们将数据从同一个寄存器移入或移入同一个寄存器。
我有什么遗漏的吗?
这是一个小型的 Godbolt 再现器:https://godbolt.org/z/UFo2qe
int arr[4000][3000];
inline int foo(double a, double b) {
return arr[static_cast<unsigned int>(a * 100)][static_cast<unsigned int>(b * 100)];
}
int bar(double a, double b) {
if (foo(a, b)) {
return 0;
}
return 1;
}
最佳答案
这是将 ECX 零扩展为 RCX 的低效方法。更有效的方法是 mov
到不同的寄存器 so mov-elimination could work .
重复项:
- Why did GCC generate mov %eax,%eax and what does it mean?
- Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?
但是您的特定测试用例需要零扩展,原因有点不明显:
x86 仅具有 FP 和有符号整数之间的转换(直到 AVX512)。通过执行 FP -> int64_t
然后将低 32 位作为 unsigned int
,FP -> unsigned int
可以在 x86-64 上高效地实现。
这就是这个序列正在做的事情:
vcvttsd2si rcx,xmm1 ; double -> int64_t, unsigned int result in ECX
mov ecx,ecx ; zero-extend to promote unsigned to ptrdiff_t for indexing
add rdx,rcx ; 64-bit integer math on the zero-extended result
关于c++ - MSVC编译器生成mov ecx, ecx看起来没什么用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59482079/