Derleyiciler optimizasyonda gerçekten iyidir switch
. Son gcc aynı zamanda bir grup koşulu optimize etmekte de iyidir.if
.
Godbolt üzerinde bazı test senaryoları yaptım .
Ne zaman case
değerleri birbirine yakın gruplanmış, gcc, çınlama ve icc bir değer özel olanlardan biri olup olmadığını kontrol etmek için bir bit eşlem kullanmak için tüm akıllı yeterlidir.
örneğin gcc 5.2-O3, ' switch
yi (ve if
çok benzer bir şeyi) derler :
errhandler_switch(errtype): # gcc 5.2 -O3
cmpl $32, %edi
ja .L5
movabsq $4301325442, %rax # highest set bit is bit 32 (the 33rd bit)
btq %rdi, %rax
jc .L10
.L5:
rep ret
.L10:
jmp fire_special_event()
Bitmap'in hemen veri olduğuna dikkat edin, bu nedenle ona erişen herhangi bir veri önbelleği kaçırması veya bir atlama tablosu yoktur.
gcc 4.9.2-O3 switch
, bir bitmap'i derler , ancak 1U<<errNumber
mov / shift ile yapar . if
Sürümü şube serisine derler .
errhandler_switch(errtype): # gcc 4.9.2 -O3
leal -1(%rdi), %ecx
cmpl $31, %ecx # cmpl $32, %edi wouldn't have to wait an extra cycle for lea's output.
# However, register read ports are limited on pre-SnB Intel
ja .L5
movl $1, %eax
salq %cl, %rax # with -march=haswell, it will use BMI's shlx to avoid moving the shift count into ecx
testl $2150662721, %eax
jne .L10
.L5:
rep ret
.L10:
jmp fire_special_event()
1'den errNumber
( çıkarma lea
işlemini bir hareketle birleştirmek için) nasıl çıkardığına dikkat edin. Bu, bitmap'i 32bit acil duruma sığdırır ve 64bit acil durumdan kaçınırmovabsq
daha fazla talimat baytı alan .
Daha kısa (makine kodunda) bir dizi şöyle olur:
cmpl $32, %edi
ja .L5
mov $2150662721, %eax
dec %edi # movabsq and btq is fewer instructions / fewer Intel uops, but this saves several bytes
bt %edi, %eax
jc fire_special_event
.L5:
ret
(Kullanılamaması jc fire_special_event
her yerde mevcuttur ve bir derleyici hatasıdır .)
rep ret
AMD K8 ve K10'un (Buldozer öncesi) yararına şube hedeflerinde ve aşağıdaki koşullu dallarda kullanılır: `` ret ret` ne demektir? . Bu olmadan, şube tahmini bu eski CPU'larda da işe yaramaz.
bt
(bit testi) register arg ile hızlıdır. Bir 1'i errNumber
bitlerle sola kaydırma ve a yapma işini birleştirir test
, ancak yine de 1 döngü gecikmesi ve sadece tek bir Intel uop'dur. CISC yolu semantiği nedeniyle bir bellek argümanıyla yavaştır: "bit dizesi" için bir bellek işleneni ile, test edilecek baytın adresi diğer argümana (8'e bölünür) dayalı olarak hesaplanır ve bellek işleneninin işaret ettiği 1, 2, 4 veya 8 bayt yığınla sınırlı değildir.
Gönderen Agner Fog'un talimat tabloları , değişken sayımı kaydırma talimatı bir daha yavaş bt
son Intel (2 UOPs yerine 1 ve Vardiyam ihtiyacı olduğunu her şeyi yapmaz) üzerinde.