Следующие два фрагмента кода создают точно такой же ассемблерный код, даже несмотря на то, что ветви заключены в разные прогнозы ветвлений.
Допустим, у нас есть test0.c
#define likely(x) __builtin_expect((x), 1)
#define unlikely(x) __builtin_expect((x), 0)
int bar0();
int bar1();
int bar2();
int bar3();
int foo(int arg0) {
if (likely(arg0 > 100)) {
return bar0();
} else if (likely(arg0 < -100)) {
return bar1();
} else if (likely(arg0 > 0)) {
return bar2();
} else {
return bar3();
}
}
и test1.c
#define likely(x) __builtin_expect((x), 1)
#define unlikely(x) __builtin_expect((x), 0)
int bar0();
int bar1();
int bar2();
int bar3();
int foo(int arg0) {
if (unlikely(arg0 > 100)) {
return bar0();
} else if (unlikely(arg0 < -100)) {
return bar1();
} else if (unlikely(arg0 > 0)) {
return bar2();
} else {
return bar3();
}
}
Как вы можете видеть, сравнивая два фрагмента, эти два имеют разные предсказания ветвления для каждой ветви (вероятно() против маловероятно()).
Однако, когда он скомпилирован из Linux-окна (ubuntu 12.04 32bit, gcc 4.6.3). Эти два источника дают практически одинаковый результат.
$gcc -c -S -o test0.s test0.c
$gcc -c -S -o test1.s test1.c
$ diff test0.s test1.s
1c1
< .file "test0.c"
---
> .file "test1.c"
Если кто-нибудь может объяснить это, это будет большая помощь. Заранее спасибо за помощь!