MSVC编译器生成mov ecx,看起来无用的ecx [重复]

问题描述 投票:0回答:1

我有一些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;
}
c++ assembly visual-c++ x86-64
1个回答
2
投票

这是将ECX零扩展到RCX的低效率方法。更有效的方法是将mov放入另一个寄存器so mov-elimination could work

重复项:

但是您的特定测试用例需要零扩展是出于一个不太明显的原因:

x86仅在FP和signed整数之间进行转换(直到AVX512)。通过执行FP-> unsigned int,然后将低32位用作int64_t,可以在x86-64上有效地实现FP-> unsigned int

此序列正在执行的操作:

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
© www.soinside.com 2019 - 2024. All rights reserved.