本文介绍了MSVC编译器生成mov ecx,看起来没用的ecx的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些 C++ 代码正在使用 MSVC 编译器 v14.24 编译为以下程序集:

I have some C++ code that is being compiled to the following assembly using MSVC compiler 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)

如你所见,编译器添加了两个

As you can see, the compiler added two

mov         ecx,ecx

对我来说没有任何意义的指令,因为它们将数据从同一个寄存器移入移出.

instructions that don't make any sense to me, because they move data from and to the same register.

有什么我遗漏的吗?

这是一个小型的 Godbolt 复制器:https://godbolt.org/z/UFo2qe

Here is a small Godbolt reproducer: 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 到不同的寄存器 因此消除移动可以工作.

That's an inefficient way to zero-extend ECX into RCX. More efficient would be mov into a different register so mov-elimination could work.

重复:

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

But your specific test-case needs zero-extension for a slightly non-obvious reason:

x86 只有 FP 和 signed 整数之间的转换(直到 AVX512).通过执行 FP -> int64_t 然后将低 32 位作为 unsigned int,FP -> unsigned int 在 x86-64 上是有效的.

x86 only has conversion between FP and signed integers (until AVX512). FP -> unsigned int is efficiently possible on x86-64 by doing FP -> int64_t and then taking the low 32 bits as unsigned int.

这就是这个序列的作用:

This is what this sequence is doing:

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

这篇关于MSVC编译器生成mov ecx,看起来没用的ecx的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-21 09:34