相关疑难解决方法(0)

Clang 和 GCC 对 movzx 的奇怪使用

我知道这movzx可以用于打破依赖关系,但我偶然发现了movzxClang 和 GCC 的一些用途,我真的看不出它们有什么用处。这是我在 Godbolt 编译器浏览器上尝试的一个简单示例:

#include <stdint.h>

int add2bytes(uint8_t* a, uint8_t* b) {
    return uint8_t(*a + *b);
}
Run Code Online (Sandbox Code Playgroud)

与海湾合作委员会 12 -O3

add2bytes(unsigned char*, unsigned char*):
        movzx   eax, BYTE PTR [rsi]
        add     al, BYTE PTR [rdi]
        movzx   eax, al
        ret
Run Code Online (Sandbox Code Playgroud)

如果我理解正确的话,这里的第一个movzx打破了对先前eax值的依赖,但第二个是什么movzx做什么?我认为它不会破坏任何依赖关系,也不应该影响结果。

使用 clang 14 -O3,情况更加奇怪:

add2bytes(unsigned char*, unsigned char*):                       # @add2bytes(unsigned char*, unsigned char*)
        mov     al, byte ptr [rsi]
        add     al, byte ptr [rdi]
        movzx   eax, al
        ret …
Run Code Online (Sandbox Code Playgroud)

c++ x86 assembly gcc clang

53
推荐指数
2
解决办法
3028
查看次数

为什么添加 xorps 指令使这个函数使用 cvtsi2ss 并添加 ~5x 快?

我正在使用 Google Benchmark 优化一个函数,并遇到了我的代码在某些情况下意外变慢的情况。我开始试验它,查看编译后的程序集,并最终想出了一个最小的测试用例来展示这个问题。这是我想出的展示这种放缓的程序集:

    .text
test:
    #xorps  %xmm0, %xmm0
    cvtsi2ss    %edi, %xmm0
    addss   %xmm0, %xmm0
    addss   %xmm0, %xmm0
    addss   %xmm0, %xmm0
    addss   %xmm0, %xmm0
    addss   %xmm0, %xmm0
    addss   %xmm0, %xmm0
    addss   %xmm0, %xmm0
    addss   %xmm0, %xmm0
    retq
    .global test
Run Code Online (Sandbox Code Playgroud)

此函数遵循 GCC/Clang 的 x86-64 函数声明调用约定extern "C" float test(int);注意注释掉的xorps指令。取消注释此指令可显着提高函数的性能。用我的机器有i7-8700K,谷歌基准测试显示的功能测试它,而不xorps指令需要8.54ns(CPU),而功能xorps指令需要1.48ns。我已经在具有不同操作系统、处理器、处理器世代和不同处理器制造商(英特尔和 AMD)的多台计算机上对此进行了测试,它们都表现出类似的性能差异。重复addss指令使减速更加明显(在某种程度上),并且这种减速仍然使用此处的其他指令(例如mulss)或什至混合指令发生,只要它们都%xmm0以某种方式依赖于值。值得指出的是,只调用xorps 每个函数调用会导致性能提升。使用循环对性能进行采样(如 Google Benchmark 所做的那样)和xorps循环外的调用仍然显示出较慢的性能。

由于这是一种专门添加指令可以提高性能的情况,因此这似乎是由 CPU 中的一些非常低级的东西引起的。由于它发生在各种 CPU …

sse x86-64 cpu-architecture clang microbenchmark

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

标签 统计

clang ×2

assembly ×1

c++ ×1

cpu-architecture ×1

gcc ×1

microbenchmark ×1

sse ×1

x86 ×1

x86-64 ×1