← SEARCHABLE ARCHIVE
Assembly · 2026-05-12

Compiler zur Anweisungsoptimierung

Unter welchen Bedingungen optimiert der Compiler For-Anweisungen?

INTERACTIVE READING MODE →

Die in diesem Blog verfassten Artikel wurden mit dem Ziel erstellt, zu unterrichten. Außerdem können die Informationen im Artikel falsch sein, also seien Sie bitte vorsichtig.

Aus Sicht der CPU lautet die in der For-Anweisung verwendete JMP-Anweisung: Da es zu Leistungseinbußen kommt, wenn die Pipeline unterbrochen ist oder die Verzweigungsvorhersage fehlschlägt, Der Compiler versucht, JMP-Anweisungen nicht zu verwenden, wenn die Bedingungen erfüllt sind.

  1. Wenn die Anzahl der Iterationen zur Kompilierungszeit als Konstante bestätigt wird.

Optimierbar: for (int i = 0; i < 4; i++) (in dem Wissen, dass es viermal wiederholt wird) Optimierungsschwierigkeit: for (int i = 0; i < n; i++) (wenn n eine zur Laufzeit bestimmte Variable ist)

//Originalcode
for (int i = 0; i < 3; i++) {
    arr[i] = 0;
}

//Nach der Compileroptimierung
arr[0] = 0;
arr[1] = 0;
arr[2] = 0;

Assemblersprache vor der Optimierung

.L2:
    cmp     DWORD PTR [rbp-4], 2    ;Vergleichen Sie, wenn i < 3
    jg      .L3                     ;Sind die Bedingungen nicht erfüllt, endet die Schleife (Sprung zu L3).
    mov     eax, DWORD PTR [rbp-4]
    cdqe
    mov     DWORD PTR [rbp-32+rax*4], 0 ;arr[i] = 0 Zuweisung
    add     DWORD PTR [rbp-4], 1    ; i++
    jmp     .L2                     ;Unbedingter Rücksprung zum Schleifenstartpunkt (.L2) (JMP)
.L3:

Optimierte Assemblersprache

mov     DWORD PTR [rdi], 0      ; arr[0] = 0
mov     DWORD PTR [rdi+4], 0    ;arr[1] = 0 (+4, weil int 4 Bytes ist)
mov     DWORD PTR [rdi+8], 0    ;arr[2] = 0 (+8, weil int 4 Bytes ist)
  1. Wenn das Endergebnis zur Kompilierungszeit im Voraus berechnet werden kann.

Wenn die Logik innerhalb der Schleife nicht von externen Ein- und Ausgängen abhängt, wird der Ergebniswert durch eine Konstante ersetzt.

//Originalcode
int sum = 0;
for (int i = 1; i <= 100; i++) {
    sum += i;
}
return sum;

//Nach der Compileroptimierung
//JMP führt zur Laufzeit nicht einmal Additionsoperationen durch.
return 5050;

Assemblersprache vor der Optimierung

.L5:
    cmp     DWORD PTR [rbp-4], 100  ;Vergleichen Sie, wenn i <= 100
    jg      .L6                     ;Oder beenden Sie die Schleife
    mov     eax, DWORD PTR [rbp-4]
    add     DWORD PTR [rbp-8], eax  ; sum += i
    add     DWORD PTR [rbp-4], 1    ; i++
    jmp     .L5                     ;Zurück zum Schleifenanfang springen (.L5) (JMP)
.L6:
    mov     eax, DWORD PTR [rbp-8]  ;Bereiten Sie sich auf die Rückgabe von Ergebnissen vor

Assemblersprache nach der Optimierung

mov     eax, 5050                   ;Geben Sie den berechneten Ergebniswert 5050 in das EAX-Register ein.
ret                                 ;sofort zurückkommen
  1. Wenn die Codelänge auch bei Schleifenerweiterung kurz ist.

Das Erweitern einer Schleife wie Code 1 wird als Schleifenerweiterung oder Schleifenabrollen bezeichnet. Wenn die Codelänge aufgrund der Schleifenerweiterung zu lang wird, ist dies eine Verschwendung des Befehls-Cache-Speichers der CPU. Wenn die Codegröße innerhalb der Schleife nicht klein ist, ist Loop Unrolling nicht optimiert.

  1. Wenn innerhalb der Schleife kein komplexer Kontrollfluss vorhanden ist.

Es gibt eine Pause-, Fortsetzungs-, Goto- oder komplexe if-else-Anweisung innerhalb der Schleife oder Wenn ein externer Funktionsaufruf eingebunden ist, erweitert der Compiler die Schleife nicht unachtsam.

Wenn es eine E/A-Funktion wie printf gibt, Da wir die auf dem Bildschirm angezeigten Nebenwirkungen schützen müssen, führen wir JMP ehrlich durch und rufen die Funktion auf, ohne die Schleife auszulassen.

Darüber hinaus muss die Compiler-Optimierungsoption aktiviert sein, um eine Optimierung wie oben durchzuführen.