合理使用分支预测
【说明】 通过使用GCC的build-in function _builtinexpect(GCC v2.96版本引入),将最有可能执行的分支告诉编译器,从而触发编译器对生成指令的顺序调整,从而尽可能发挥CPU指令预取的优势,提高指令Cache的命中率来提高程序性能;
一般的用法:
#define LIKELY(x) __builtin_expect(!!(x), 1) // x很可能为真
#define UNLIKELY(x) __builtin_expect(!!(x), 0) // x很可能为假
【注意事项】 由于分支预测机制会影响编译器生成的指令排布,因此,对于场景化的分支需要慎重考虑,避免优化部分场景性能的同时,带来其他场景的恶化;通常地,分支预测机制会用在异常保护、调测功能判决等场景。
【案例】
修改前:将LIKELY修饰“a == 7”判断,
if (LIKELY(a == 7)) {
a += 5;
b++;
} else {
a -= 3;
b--;
}
以Arm GCC 7.3为例,编译器开-O2优化,生成的汇编代码如下,可以看出,更可能执行的加法分支指令排在前面:
cmp w0, #0x7
b.ne 0x4005ac <main+44>
mov w20, #0xa
mov w1, #0xc
...
修改后:将UNLIKELY修饰a == 7判断:
if (UNLIKELY(a == 7)) {
a += 5;
b++;
} else {
a -= 3;
b--;
}
生成的汇编指令如下,可以看出,更可能执行的减法分支指令排在前面:
cmp w0, #0x7
b.eq 0x4005d0 <main+80>
sub w1, w0, #0x3
mov w20, #0x8
...
父主题: 控制语句