gpt4 book ai didi

c - 静态分支预测/GCC 优化

转载 作者:太空狗 更新时间:2023-10-29 17:12:31 24 4
gpt4 key购买 nike

考虑以下 C 程序:

void bar();
void baz();

void foo( int a ) {
if ( a ) {
bar();
}
else {
baz();
}
}

在我的基于 x86-64 的计算机上,GCC 生成的具有 -O1 优化级别的指令给出:

 0: sub    $0x8,%rsp
4: test %edi,%edi
6: je 14 <foo+0x14>
8: mov $0x0,%eax
d: callq 12 <foo+0x12> # relocation to bar
12: jmp 1e <foo+0x1e>
14: mov $0x0,%eax
19: callq 1e <foo+0x1e> # relocation to baz
1e: add $0x8,%rsp
22: retq

而添加 -freorder-blocks 优化参数(包含在 -O2 中)会将代码变为:

 0: sub    $0x8,%rsp
4: test %edi,%edi
6: jne 17 <foo+0x17>
8: mov $0x0,%eax
d: callq 12 <foo+0x12> # relocation to baz
12: add $0x8,%rsp
16: retq
17: mov $0x0,%eax
1c: callq 21 <foo+0x21> # relocation to bar
21: add $0x8,%rsp
25: retq

主要是从jump equalsjump not equals 的变化。我知道在 Pentium 4 之前,条件前向分支上的静态分支预测被认为没有被处理器采用(似乎静态预测在更多的英特尔处理器上变得随机),因此我想这个优化正在处理这个问题。

假设并引用 jne 优化版本,这意味着 else block 实际上被认为比 if< 更有可能执行/em> 程序流中的 block 。

但这到底是什么意思呢?由于编译器没有对 foo 函数中的 a 值进行假设,因此这种概率仅依赖于程序员的写作(实际上谁可以使用 if ( !a ) 而不是 if ( a ) 和反向函数调用)。

这是否意味着将 if 条件 block 视为异常(exception)情况(而不是正常执行流程)应被视为一种良好做法?

即:

if ( !cond ) {
// exceptional code
}
else {
// normal continuation
}

代替:

if ( cond ) {
// normal continuation
}
else {
// exceptional code
}

(当然,人们可能更喜欢在相关 block 中使用 return 语句来限制缩进大小)。

最佳答案

我曾经在 ARM(7,9) 上进行了大量的性能优化操作。它是普通的 C,足够愚蠢的编译器(SDT AFAIR)。节省一些 CPU 资源的方法之一是分析 if 分支并重写 if 条件,以便正常流程不会破坏线性指令序列。这具有积极的效果,因为 CPU 预测 block 使用效率更高,代码段内存缓存使用效率更高。

我认为这里我们看到了非常接近的优化。在第一个代码片段中,两个分支都导致正常序列被破坏(一个分支的 lavel 6 和另一个分支的 12 行)。在第二个片段中,一个分支指令被排序到 retq 并且其他分支序列具有单跳转(不比第一个片段差)。请注意2个retq指令。

因此,正如我所看到的,这不是 jejne 的问题,而是 block 重新排序的问题,因此分支是线性指令序列,其中一个没有任何输入jump 并节省了完整的预测 block 功率。

关于“为什么 GCC 更喜欢一个分支而不是另一个分支”...我在文档中看到这可能是静态分支预测的结果(基于翻译单元内部的调用?)。无论如何,我建议使用 __builtin_expect 以获得更详细的答案。

关于c - 静态分支预测/GCC 优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18560561/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com