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, ' switchyi (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<<errNumbermov / shift ile yapar . ifSü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 leaiş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_eventher yerde mevcuttur ve bir derleyici hatasıdır .)
rep retAMD 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 errNumberbitlerle 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ş btson Intel (2 UOPs yerine 1 ve Vardiyam ihtiyacı olduğunu her şeyi yapmaz) üzerinde.