相关疑难解决方法(0)

x86的MOV真的可以"免费"吗?为什么我不能重现这个呢?

我一直看到人们声称MOV指令可以在x86中免费,因为寄存器重命名.

对于我的生活,我无法在一个测试用例中验证这一点.每个测试用例我尝试揭穿它.

例如,这是我用Visual C++编译的代码:

#include <limits.h>
#include <stdio.h>
#include <time.h>

int main(void)
{
    unsigned int k, l, j;
    clock_t tstart = clock();
    for (k = 0, j = 0, l = 0; j < UINT_MAX; ++j)
    {
        ++k;
        k = j;     // <-- comment out this line to remove the MOV instruction
        l += j;
    }
    fprintf(stderr, "%d ms\n", (int)((clock() - tstart) * 1000 / CLOCKS_PER_SEC));
    fflush(stderr);
    return (int)(k + j + l);
}
Run Code Online (Sandbox Code Playgroud)

这为循环生成以下汇编代码(随意生成这个你想要的;你显然不需要Visual C++):

LOOP:
    add edi,esi
    mov …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly cpu-registers micro-optimization

23
推荐指数
2
解决办法
2113
查看次数

什么是局部标志失速?

我刚刚查看了彼得·科德斯(Peter Cordes)的回答,他说,

如果读取标志,则部分标志停顿会发生,如果它们确实发生的话。P4永远不会有部分标志停顿,因为它们永远不需要合并。相反,它具有错误的依赖关系。几个答案/评论混淆了术语。它们描述了一个错误的依赖关系,但随后将其称为部分标志停顿。这是由于仅写入一些标志而导致的速度下降,但是术语“部分标志停顿”是指必须合并部分标志写入时在SnB之前的Intel硬件上发生的情况。英特尔SnB系列CPU插入一个额外的uop来合并标志而不会停顿。Nehalem和更早的失速约7个周期。我不确定AMD CPU会受到多大的损失。

我感觉我还不明白什么是“部分国旗摊位”。我怎么知道一个人发生了?除了读取标志的某些时间之外,什么触发事件?合并标志是什么意思?在什么情况下会“写一些标志”,但不会发生部分标志合并?我需要了解哪些有关旗位的知识才能理解它们?

x86 assembly

6
推荐指数
1
解决办法
291
查看次数

imul 然后 mov 与 mov 然后 imul - 有什么区别吗?

如果我编译以下 C++ 程序:

int baz(int x) { return x * x; }
Run Code Online (Sandbox Code Playgroud)

在 clang 15 中,我得到:

baz(int):
        mov     eax, edi
        imul    eax, edi
        ret
Run Code Online (Sandbox Code Playgroud)

而 gcc 12.2 给了我:

baz(int):
        imul    edi, edi
        mov     eax, edi
        ret
Run Code Online (Sandbox Code Playgroud)

(请参阅GodBolt

这两种实现是否完全等同,而只是任意选择的问题?如果它们不等价,它们的差异如何体现或影响我的程序?我的意思是,就 CPU 状态副作用、其他指令的延迟、内联期间的行为等而言。

c++ assembly x86-64 cpu-architecture micro-optimization

3
推荐指数
1
解决办法
142
查看次数