这可能是一个愚蠢的问题,出于无知而问。
这是一个描述分支预测的链接。看起来这在哑 CPU 上效率不高,为什么编译器不能只生成一个二元素跳转表?看看下面的代码:
int main(){
bool c = true;
if(c); /* do something here. */
else; /* do else something here. */
}
使用编译器资源管理器,这会生成以下机器代码 (-O0):
main: # @main
push rbp
mov rbp, rsp
mov dword ptr [rbp - 4], 0
mov byte ptr [rbp - 5], 1
test byte ptr [rbp - 5], 1
je .LBB0_2
jmp .LBB0_3
.LBB0_2:
jmp .LBB0_3
.LBB0_3:
mov eax, dword ptr [rbp - 4]
pop rbp
ret
这当然有一个分支,而以下代码:
int main(){
bool c = true;
using jmptable_t = void(*)();
jmptable_t jmptable[2] = {nullptr, nullptr};
jmptable[c];
}
生成:
main: # @main
push rbp
mov rbp, rsp
sub rsp, 32
mov byte ptr [rbp - 1], 1
lea rdi, [rbp - 32]
xor esi, esi
mov edx, 16
call memset@PLT
xor eax, eax
add rsp, 32
pop rbp
ret
其中大部分是为设置跳转表而生成的。这里没有分店。 在这里,我将两种方法的速度与 -O0 进行比较。跳转表始终比 if 语句快,这让我感到惊讶,因为我认为跳转表的优化程度较低。
也许我的测试不准确?
问题:
- 在一般环境中哪个更快,优化可能是 O1 或 O2?
- 当我将优化设置为 O3 时,if 语句变得非常快。为什么是这样?编译器做了哪些优化?