Grundlagen zu Intels Itanium (Teil I)

Predication: Erst rechnen, dann entscheiden

Neben den Allzweck- und den Fließkommaregistern definiert die IA-64 noch 64 Predicate-Register von je einem Bit Breite. Die ersten 16 dieser Register sind statisch, die übrigen werden dynamisch verwaltet und unterstützen das Software-Pipelining durch Rotation. Test- und Vergleichsbefehle setzen die Predicate-Register. Sie berechnen dabei jeweils zwei Predicate-Register, wobei eines für eine erfüllte und das andere für eine nicht erfüllte Bedingung steht.

Bei fast jedem Befehl der IA-64 kann man ein Predicate-Register als Bedingung mit angeben. Ist das Predicate-Register wahr, führt der Itanium den Befehl aus und berechnet das Ergebnis, ansonsten verwirft er es. Der Clou ist nun, dass man zwei Befehle, die sich eventuell wiedersprechen und auch auf dieselben Register zugreifen können, mit zwei komplementären Predicate-Registern versieht. Der Itanium kann dann in seinen Pipelines beide Befehle gleichzeitig abarbeiten, liefert aber am Ende nur das passende Ergebnis.

Durch die Predication kann man einfache Fallunterscheidungen viel eleganter lösen als bei der IA-32. Obwohl bei der IA-64 beide Zweige tatsächlich berechnet werden, ist dieses Vorgehen vielfach schneller als die Verwendung eines bedingten Sprunges. Dieser verursacht nämlich eine massive Störung der Pipeline, falls die Sprungvorhersage sich geirrt hat.

Deutlich wird dies im obigen Beispiel der Berechnung der absoluten Differenz zweier Zahlen. Die IA-32 ermittelt mit dem Befehl cmpGE, welcher der beiden Werte in den Registern r2 und r3 größer ist. Abhängig davon führt sie einen bedingten Sprung zum passenden Codeblock aus. Dieser Sprung bringt jedoch die Pipeline des Prozessors ins Stocken und kostet daher sehr viele Taktzyklen.

Die IA-64 wertet ebenfalls die Bedingung aus und setzt aber damit nur zwei Predicate-Register (p1 und p2) entsprechend. Beide Möglichkeiten der Berechnung werden im Code nun mit Predicate-Registern versehen und auch tatsächlich berechnet. Auf Grund der sechs parallelen Pipelines berechnet die CPU aber sowohl die Werte der Predicate-Register als auch beide Ergebnisse zeitgleich. Am Ende trägt sie jedoch nur den Wert mit passendem Predicate-Flag in das Register r4 zur späteren Weiterverarbeitung ein. Ohne einen einzigen Sprung wird hierbei also das Ergebnis der Fallunterscheidung in nur einem Taktzyklus ermittelt, ohne die Pipeline zu gefährden.