Dzisiejsze komputery mają potoki, złożone z wielu etapów (od 12 do 22), dlatego bardzo ważne aby przy skokach, rozgałęzieniach czy wywołaniach funkcji nie trzeba było czekać na następną instrukcję do chwili gdy będzie wiadomo jaki jest jej adres.
Dlatego rozwijane są specjalne jednostki odpowiedzialne za przewidywanie, która z możliwych gałęzi zostanie wybrana. Obecnie używają one bardzo zaawansowanych algorytmów do przewidywania.
Pomyłka w przewidywaniu kosztuje od 12 do 50 cykli zegara.
Rozgałęzienia są przeważnie dobrze przewidywane w następujących przypadkach
Spraw aby skoki warunkowe były rzadko wykonywane
cmp eax,567 je L1 ; częstsza gałąź ret L1: ; rzadko wykonywana gałąź ret
Jeżeli wywołanie funkcji jest bezpośrednio przed RET można zastąpić skokiem
Func1: ... call Func2 ret | Func1: ... jmp Func2 |
Należy pamiętać o wcześniejszym posprzątaniu stosu i ewentualnym odtworzeniu ebp.
Func1: enter 32 ... call Func2 leave ret | Func1: enter 32 ... leave jmp Func2 |
Funkcja: push ebp mov ebp, esp mov ecx, [iloscElementow] lea edx, [adresTablicy] mov eax, [wartoscProgowa] Loop1: ; początek pętli cmp eax, [edx+4*ecx-4] ; if-else ja ElseBranch ... ; pierwsza gałąź jmp EndIf ElseBranch: .... ; druga gałąź EndIf: sub ecx, 1 ; epilog pętli jnz Loop1 mov esp, ebp ; epilog funkcji pop ebp ret
Przez powielenie epilogu pętli mozemy wyeliminować skok do EndIf
Funkcja: push ebp mov ebp, esp mov ecx, [iloscElementow] lea edx, [adresTablicy] mov eax, [wartoscProgowa] Loop1: ; początek pętli cmp eax, [edx+4*ecx-4] ; if-else ja ElseBranch ... ; pierwsza gałąź sub ecx, 1 ; epilog pętli 1 jnz Loop1 jmp EndLoop ElseBranch: .... ; druga gałąź sub ecx, 1 ; epilog pętli 2 jnz Loop1 EndLoop: mov esp, ebp ; epilog funkcji pop ebp ret
Przez powielenie epilogu funkcji mozemy wyeliminować skok do EndLoop (tutaj zysk prędkości jest już niewielki).
Funkcja: push ebp mov ebp, esp mov ecx, [iloscElementow] lea edx, [adresTablicy] mov eax, [wartoscProgowa] Loop1: ; początek pętli cmp eax, [edx+4*ecx-4] ; if-else ja ElseBranch ... ; pierwsza gałąź sub ecx, 1 ; epilog pętli 1 jnz Loop1 mov esp, ebp ; epilog funkcji 1 pop ebp ret ElseBranch: .... ; druga gałąź sub ecx, 1 ; epilog pętli 2 jnz Loop1 mov esp, ebp ; epilog funkcji 2 pop ebp ret
Skoki warunkowe często mogą zostać wyeliminowane przy użyciu warunkowych CMOVxx. Instrukcja MOV zostanie wykonana tylko jeżeli spełniony jest warunek xx np. cmovb, cmovae, cmovnz, cmovle.
a = b > c ? d : e ;
mov eax, [b] cmp eax, [c] jng L1 mov eax, [d] jmp L2 L1: mov eax, [e] L2: mov [a], eax | mov eax, [b] cmp eax, [c] mov eax, [d] cmovng eax, [e] mov [a], eax |
int b, c; bool a = b > c;
; wynik 8 - bitowy mov eax, [b] cmp eax, [c] setg al mov [a], al | ; wynik 32-bitowy mov eax, [b] ; zerujemy rejestr przed cmp ; aby uniknąć zmian flag xor ebx, ebx cmp eax, [c] setg bl mov [a], ebx |
Obliczanie wartości bezwzględnej
cdq ; wypełnia edx bitem znaku eax xor eax, edx ; odwraca bity jeżeli eax < 0 sub eax, edx ; dodaje 1 jeżeli eax < 0
Obliczanie minimum dwóch liczb bez znaku b = min (a , b)
sub eax, ebx ; = a-b sbb edx, edx ; = (b > a) ? 0xFFFFFFFF : 0 and edx, eax ; = (b > a) ? a-b : 0 add ebx, edx ; = (b > a) ? a : b