c++ - MSVC编译器生成mov ecx, ecx看起来没什么用

标签 c++ assembly visual-c++ x86-64

我有一些 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 .

重复项:

但是您的特定测试用例需要零扩展,原因有点不明显:

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/

相关文章:

c++ - 使用 bigint 类 C++

c++ - qi::phrase_parse 返回真,即使调用了 qi::on_error

c - 为什么下面的c函数和asm代码一样

c - mmap 替代 malloc

.net - 如何在命令行使用 .NET Framework 编译器编译 C++ 程序?

c++ - 为什么 == 运算符重载枚举在 MSVC 中不明确

c++ - 在定义结构之前如何使用指向结构的指针?

c++ - 在 Eigen 中使用 unaryExpr 进行逐元素运算

assembly - 如何在字符串定义中将 ASCII 字符大写?

visual-c++ - VC++ 内部编译器错误