在项目中看到了likely、unlikely宏的使用, 一直不是很清楚它们的作用,所以就深究下。
likely表示被测试的表达式大多数情况下为true, unlikely则表示相反。
两个宏定义:
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
这两个宏经常在条件转移的语句中使用,如if, else if等,这些语句生成的汇编代码都带有jmp指令.
根据gcc手册, 所以这两个宏是用来告诉编译器分支的可能走向,从而帮助CPU进行分支预测来增强CPU流水线性能的.
看下下面的代码
int main (char *argv[], int argc) {
int v;
v = atoi(argv[1]);
if (likely(a == 5))
a++;
else
a--;
printf("%d\n", a);
return 0;
}
编译,带上-O2选项,得到的汇编代码:
0000000000400510 <main>:
400510: 48 83 ec 08 sub $0x8,%rsp
400514: 48 8b 7f 08 mov 0x8(%rdi),%rdi
400518: 31 c0 xor %eax,%eax
40051a: e8 f1 fe ff ff callq 400410 <atoi@plt>
40051f: 83 f8 02 cmp $0x2,%eax
400522: 75 18 jne 40053c <main+0x2c> /* likely在这里表示a很有可能是2, 所以将执行a++和printf调用放在一起, 免去了jmp带来的影响 */
400524: be 03 00 00 00 mov $0x3,%esi
400529: bf 48 06 40 00 mov $0x400648,%edi
40052e: 31 c0 xor %eax,%eax
400530: e8 bb fe ff ff callq 4003f0 <printf@plt>
400535: 31 c0 xor %eax,%eax
400537: 48 83 c4 08 add $0x8,%rsp
40053b: c3 retq
40053c: 8d 70 ff lea -0x1(%rax),%esi
40053f: eb e8 jmp 400529 <main+0x19> /* jump到调用printf代码处, 导致cpu flush掉流水线上的内容. */
400541: 90 nop
原文地址:http://blog.csdn.net/zxjcarrot/article/details/46342309