【问题标题】:MSVC compiler generates mov ecx, ecx that looks useless [duplicate]MSVC编译器生成mov ecx,看起来没用的ecx [重复]
【发布时间】:2020-04-16 07:43:31
【问题描述】:

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

这是一种将 ECX 零扩展为 RCX 的低效方法。更有效的方法是将mov 放入不同的寄存器so mov-elimination could work

重复:

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

x86 仅在 FP 和 有符号 整数之间进行转换(直到 AVX512)。 FP -> unsigned int 在 x86-64 上可以通过执行 FP -> int64_t 然后将低 32 位作为 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

【讨论】:

    猜你喜欢
    • 2016-08-08
    • 2023-03-29
    • 2020-09-11
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多