likelyとunlikely
likelyは条件が通常は真で、unlikelyは条件が通常は偽であるケースで、if文のパフォーマンス向上のために使用します。これらのマクロは、__builtin_expectで実装されgccマターとなります。
次実行コードのインストラクションポインタIPをインクリメントするのでなく、jmpは次実行コードをキャッシュメモリから取得し、それをipに設定する負荷のかかる仕組みが必要と、CPUマターであるにしても想像できます。
gcc依存と思いますが、私の環境では、最適化オプションO2以降でないと__builtin_expectが有効となりませんでした。
カーネル3ではgccの変更にともない、カーネルオプションにより、__builtin_expect以外による展開がされるようになっています。
# define likely(x) __builtin_expect(!!(x), 1) # define unlikely(x) __builtin_expect(!!(x), 0)__builtin_expectは第1引数が第二引数1(真)なら、else処理はjmpとし、第1引数が0(偽)なら、then処理がjmpする様に展開されます。
次実行コードのインストラクションポインタIPをインクリメントするのでなく、jmpは次実行コードをキャッシュメモリから取得し、それをipに設定する負荷のかかる仕組みが必要と、CPUマターであるにしても想像できます。
void likely(int a)
{
if (__builtin_expect(!!(a == 2), 1)) {
printf("%d\n", a);
}
}
void unlikely(int a)
{
if (__builtin_expect(!!(a == 2), 0)) {
printf("%d\n", a);
}
}
likely:
.LFB13:
.cfi_startproc
subl $28, %esp
.cfi_def_cfa_offset 32
cmpl $2, 32(%esp)
jne .L5 <- elseはjmp .L5
movl $2, 4(%esp)
movl $.LC0, (%esp)
call printf
.L5:
addl $28, %esp
.cfi_def_cfa_offset 4
ret
unlikely:
.LFB14:
.cfi_startproc
subl $28, %esp
.cfi_def_cfa_offset 32
cmpl $2, 32(%esp)
je .L9 <- thenはjmp .L9
.L7:
addl $28, %esp
.cfi_remember_state
.cfi_def_cfa_offset 4
ret
.L9:
.cfi_restore_state
movl $2, 4(%esp)
movl $.LC0, (%esp)
call printf
jmp .L7
***追記
__builtin_expect(!!(x), 1)で、!!(x)とするのは、ポインタとする変数がNULLかそうでないか等のケースを想定しての実装です。なお、(a == 2)等の真偽を問うケースでは、!!は無視されます。gcc依存と思いますが、私の環境では、最適化オプションO2以降でないと__builtin_expectが有効となりませんでした。
カーネル3ではgccの変更にともない、カーネルオプションにより、__builtin_expect以外による展開がされるようになっています。






