Optymalizacja skoków i wywołań funkcji
Przewidywanie rozgałęzień

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.

Przewidywalne rozgałęzienia

Rozgałęzienia są przeważnie dobrze przewidywane w następujących przypadkach

Słabo przewidywalne rozgałęzienia

Eliminacja skoków warunkowych

Spraw aby skoki warunkowe były rzadko wykonywane

  cmp eax,567
  je L1
  ;    częstsza gałąź
  ret
L1:  ;  rzadko wykonywana gałąź
  ret

Eliminacja wywołań funkcji

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

Eliminacja skoków bezwarunkowych

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

Zamiana skoków na warunkowe CMOVxx

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

Zamiana rozgałęzień na warunkowe SETxx

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

Manipulacje na bitach

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
 


Tomasz Kapela, Kraków 2011-2020