我只是在cppreference上阅读C++中的属性.他们在那里提到了可能的(真实)属性,现在我想知道它有什么好处.不幸的是,我无法在网上找到更多信息.
这是处理器在执行期间使用的某种分支预测吗?
对,就是这样.它用于为编译器提供有关该if
语句的更多信息,以便它可以根据目标微架构生成最佳代码
虽然每个微架构都有自己了解分支机构可能性的方法,但我们可以从英特尔优化手册中选择一个简单的例子
汇编/编译器编码规则3.(M影响,H一般性)安排代码与静态分支预测算法一致:使条件分支后面的连通代码成为具有前向目标的分支的可能目标,并使条件分支后面的直通代码是具有反向目标的分支的不太可能的目标.
简单地说,前向分支的静态预测不被采用(因此分支之后的代码被推测性地执行,这是可能的路径),而对于后向分支则采用(因此分支之后的代码不是推测性地执行).
考虑GCC的这段代码:
#define probably_true(x) __builtin_expect(!!(x), 1) #define probably_false(x) __builtin_expect(!!(x), 0) int foo(int a, int b, int c) { if (probably_true(a==2)) return a + b*c; else return a*b + 2*c; }
我在哪里使用内置__builtin_expect
来模拟一个[[problably(true)]]
.
这个编译成了
foo(int, int, int): cmp edi, 2 ;Compare a and 2 jne .L2 ;If not equals jumps to .L2 ;This is the likely path (fall-through of a forward branch) ;return a + b*c; .L2: ;This is the unlikely path (target of a forward branch) ;return a*b + 2*c; ret
我在哪里省了一些汇编代码.
如果更换probably_true
用probably_false
的代码变为:
foo(int, int, int): cmp edi, 2 ;Compare a and 2 je .L5 ;If equals jumps to .L5 ;This is the likely path (fall-through of a forward branch) ;return a*b + 2*c; .L5: ;This is the unlikely path (target of a forward branch) ;return a + b*c; ret
您可以在codebolt.org上使用此示例.