Compiler

Computerprogramm, das Quellcode in ausführbare Maschinensprache übersetzt
Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 24. August 2003 um 21:20 Uhr durch Tsor (Diskussion | Beiträge) (Optimierungsmöglichkeiten). Sie kann sich erheblich von der aktuellen Version unterscheiden.

Ein Compiler ist ein Computerprogramm, das einen in einer Programmiersprache geschriebenen Text (Quelltext) in eine maschinennähere Form, oft Assemblersprache oder direkt Maschinensprache übersetzt. Dabei bietet er meist Optionen für verschiedene Optimierungsstufen mit dem Ziel, die Laufzeit des Programms zu verkürzen. Der Compilerbau, also die Programmierung eines Compilers, ist eine eigenständige Disziplin innerhalb der Informatik.

Wenn man die Optimierung einschaltet, dann verändert der Compiler in der Übersetzung ggfls. den Programmcode. Dann ist es kaum noch möglich, mit einem interaktiven Debugger den Programmcode zu verfolgen.

Die Optimierung erfolgt in Abhängigkeit von den Eigenschaften der Hardware, insbesondere wieviele Register der Prozessor zur Verfügung stellt.

Im folgenden betrachten wir einige Optimerungsmöglichkeiten.

Reduzierung von Assemblerinstuktionen

Wenn man zum Beispiel in einer höheren Prgrammiersprache den Inhalt von 2 Variablen vertauscht, dann benötigt man eine Hilfsvariable:


   Programmiersprache                Assembler
                         ohne Optimierung     mit Optimierung

         t = a           a --> Register 1     a --> Register 1
                         Register 1 --> t
         a = b           b --> Register 2     b --> Register 2
                         Register 2 --> a
         b = t           t --> Register 3     Register 1 --> b
                         Register 3 --> b     Register 2 --> a

Mit Optimierung benötigt man nur 4 Assemblerbefehle anstatt 6, ausserdem wird der Speicherplatz für die Hilfsvariable t nicht gebraucht.D.h. diese Vertauschung wird schneller ausgeführt und benötigt weniger Hauptspeicher.


Formelauswertung bereits bei der Compilierung

Die Berechnung des Kreisumfangs mittels

         pi = 3.14
         u  = 2*pi*r

optimiert der Compiler zu "u = 6.28*r". Die Multiplikation "2*pi" wird während der Übersetzung ausgeführt und reduziert so die Laufzeit.


Eliminierung von toten Programmcode

Wenn der Compiler erkennen kann, dass ein Teil des Programmes niemals durchlaufen wird, dann laesst er diesen Teil bei der Übersetzung weg.

  
Beispiel:  ...
           goto 900
  200      k=3
  900      i=7
           ...

Wenn in diesem Programm niemals ein GOTO auf das Label 200 erfolgt, dann kann auf die Anweisung "200 k=3" verzichtet werden.


Erkennung von nicht benötigten Variablen

Wird eine Variable nicht benötigt, dann wird sie auch nicht berechnet.

Beispiel:  subroutine test (a,b)
           b = 2*a
           c = 3.14 * b
           return

Hier wird die Variable c nicht benötigt: Sie steht nicht in der Parameterliste, wird in späteren Berechnungen nicht verwendet und wird auch nciht ausgegeben. Deshalb entfällt die Anweisung "c = 3.14 * b".


Optimierung von Schleifen

Insbesondere Schleifen versucht man zu optimieren, indem man

  • möglichst viele Variablen in Registern hält (z.B. die Schleifenvariable)
  • oder die Schleife komplett auflöst. Die Anweisungen innerhalb der Schleife werden sequentiell hintereinander ausgeführt ohne Verwendung einer Schleife.


Reduzierung von Paging zur Laufzeit

Zusammenhängender Code - z.B. eine Schleife - sollte zur Laufzeit möglichst auf einer Page im Hauptspeicher liegen. Dies kann man evtl. dadurch erreichen, dass man geeignet Leeranweisungen ("NOPs") dem Programmcode hinzufügt. Dadurch wird der Programmcode zwar grösser, aber wegen des reduzierten Pagings wird das Programm schneller ausgeführt.


Bedeutende Compiler:

  • GCC: GNU Compiler Collection