Compiler-Techniken für superskalare Prozessoren

Warum neue Technologien für Compiler?

Traditionelle Compiler-Technologien beruhen im Allgemeinen auf folgenden Optimierungsstrategien:

  • Der Compiler eliminiert nicht durchlaufene Codebereiche (Dead Code Elimination, minimiert die Programmgröße).

  • Er löscht unnötige Codebereiche, die zwar durchlaufen, aber nicht benötigt werden, da sie keinen Nettoeffekt erzeugen (beschleunigt das Programm).

  • Er legt Variablen, die häufig oder nur für Zwischenergebnisse benötigt werden, in (Highspeed-) Registern ab, um auf langsame Speicherzugriffe verzichten zu können (beschleunigt das Programm).

Diese Optimierungen sind weiterhin sinnvoll, da sie auch bei Instruktionsparallelismus Erfolge zeigen. Zusätzliche Optimierungen, bei denen die Parallelisierbarkeit im Vordergrund steht, sind jedoch dringend notwendig. Immerhin ist bei einem Prozessor, der die vierfache parallele Ausführung von Instruktionen ermöglicht, eine Performance-Steigerung um den gleichen Faktor theoretisch möglich. Eine Grundvoraussetzung dafür ist, dass der Compiler das Programm auch parallelisierbar übersetzt. Der mögliche Leistungsgewinn ist eine hohe Motivation für neue Compiler-Technologien, wie die folgenden Abschnitte zeigen.

Der folgende Beitrag stellt zunächst die Verfahren zur Optimierung von kompiliertem Code im Einzelnen vor. Hierunter fallen einige Basiskonzepte wie das Formen von Superblöcken zur Vergrößerung der unterbrechungsfreien Instruktionsblöcke, das Einfügen von bedingten Instruktionen mit Steuerungs-Flags, Register Renaming zur Compile-Zeit und das Loop Unrolling.

Der zweite Teil geht auf einen Hauptbestandteil der Technologien ein, die bedingten Befehle mit Steuerungs-Flags. Im dritten Teil folgt dann die Analyse von Speicherabhängigkeiten. Die in Teil zwei und drei beschriebenen neueren Technologien dürften Bestandteil der zukünftigen Compiler-Generationen sein.