Der Optimierer analysiert den ARM-Code und übersetzt ihn in den CPU-nativen Mikrocode (Micro-Ops). Jeder ARM-Befehl wird im Schnitt in 1,8 Mikro-Ops umgewandelt. ARMs eigene CPUs verwenden auch eigenen Mikrocode, erzeugen jedoch etwa 1,1 oder 1,2 Mikro-Ops pro Befehl. Denvers Mikro-Ops sind einfacher und allgemeiner gehalten als in ARMs Designs. Die Denver-Mikro-Ops haben eine variable Länge, durchschnittlich etwa 5,7 Byte. Unter Berücksichtigung der Thumb-Codierungen enthält der durchschnittliche ARM-Befehl 3,1 Byte und wird in 10,3 Byte Micro-Ops gewandelt, was eine Erhöhung der Codegröße um Faktor 3,3 bedeutet (diese Zahlen basieren auf dem Benchmark SPECint2000 und können je nach Anwendung etwas variieren).
Wie in einem VLIW-Design werden Mikrobefehle derart gruppiert, daß alle Mikrobefehle in einem Bündel in dem gleichen Taktzyklus ausgeführt werden. Um die Code-Expansion zu minimieren unterdrückt der Optimierer alle nicht belegten Plätze, so dass die Ausführungsbündel eine variable Länge haben. Jedes Bündel kann bis zu sieben Mikrobefehle enthalten und ist auf 32 Byte begrenzt. Aufgrund dieser Kappung enthält auch eine maximal großes Bündel typischerweise fünf oder sechs Micro-Ops. Die durchschnittliche Paketgröße beinhaltet drei oder vier Mikrobefehle (18 bis 24 Bytes).
Gemäß seines Namens tut der Optimierer weit mehr als eine einfache Übersetzung. Um die Slots in einem Bündel bestmöglich zu nutzen, ordnet er Mikro-Ops um und benennt Register um, um Abhängigkeiten zu umgehen. Anstatt einfach einen Basisblock zu optimieren, rollt er Schleifen aus und arbeitet auch Code nach Verzweigungen unter Verwendung von Informationen von der Sprungvorhersage ab, um die wahrscheinlichste Richtung jeder Verzweigung zu bestimmen. Er kann sogar Unterprogramme in Inline-Code konvertieren.
Eine optimierte Routine kann bis zu 1.000 ARM-Anweisungen beinhalten - ein weit größeres Fenster als alle in Hardware implementierte Out-of-Order-Scheduler haben. Der Optimierer kann jedoch auch früher beenden werden, wenn er in Ressourcen-Limits von Umbenennungs-Registern oder Speicher-Puffereinträgen läuft. Es muss auch aufhören, wenn er auf eine Anweisung tritt, die die Berechtigungsstufe ändert oder andere Systemfunktionen wie z.B. das Löschen des Cache ausführt.
Der übersetzte Mikrocode wird in einem reservierten Bereich des 128 MB großen Hauptspeicher, den Nvidia Optimierungs-Cache nennt, gespeichert. Die Instruktions-Fetch-Einheit beinhaltet eine Übersetzungstabelle, welche die Adresse der ARM-Routine in die Adresse der entsprechenden Mikrocode-Routine umwandelt. Jedes Mal, wenn sie auf das übersetzte Programm trifft, holt die CPU statt den ursprünglichen ARM-Code automatisch Code aus dem Optimierungs-Cache. Da im Laufe der Programmausführung immer mehr Routinen übersetzt werden, kann sie der Optimierer miteinander verknüpfen, so dass die CPU direkt aus einer Mikrocode-Routine in eine andere springen kann.
Der Optimierungs-Cache ist geschützt, so dass ihn nur Mikrocode-Routinen beschreiben können – dies passiert zur Gewährleistung der Sicherheit gegen bösartigen oder schlecht geschrieben Code, der versucht, den Optimierer oder optimierte Codesequenzen zu überschreiben. Aus diesem Grund und um die Rechenleistung zu verbessern, wird der Optimierer selbst in Mikrocode konvertiert und im Optimierungs-Cache gespeichert. Im Gegensatz zu Prozessoren, die Befehls-Scheduling in Hardware durchzuführen, ermöglicht dieser Ansatz Nvidia, den Optimierer leicht zu aktualisieren, um die Leistung zu verbessern oder Fehler zu beheben.
Bild 2 zeigt ein Profil eines typischen Programms, das auf einer Denver-CPU läuft. Wenn das Programm gestartet wird, führt die CPU hauptsächlich ARM-Anweisungen (die gelben Balken) aus, aber es erkennt relativ schnell „heiße“ Routinen und beginnt deren Umsetzung in Mikrocode, der später direkt ausgeführt wird (die grünen Balken). Nach nur 2 % der Gesamtausführungszeit sieht man bereits eine weitestgehende CPU-Microcode-Ausführung. Während der Programmausführung setzt dieses spezielle Programm eine Reihe von neuen Routinen frei, was zu einem kurzen Anstieg der ARM-Anweisungen führt. Erneut werden aber diese Anweisungen schnell in Mikrocode übersetzt. Die CPU führt dann nahezu 100 % Mikrocode aus, bis es am Ende des Programms auf eine Abschlussroutine trifft.
Die roten Balken zeigen den Overhead des Optimierers selbst. Selbst in den wenigen Perioden mit umfangreicher Übersetzung verbraucht der Optimierer weniger als 20 % der Taktzyklen. Die meiste Zeit braucht er weniger als 10 % und verschwindet ganz für mehr als die Hälfte des Tests. Im Laufe des Gesamtprogramms beträgt der Optimierungsaufwand nur 3,2 % aller Taktzyklen. Für stark repetitive Programme, einschließlich einiger SPECfp2000-Komponenten, ist der Optimierungsaufwand für das gesamte Programm fast Null. Andererseits erzeugen komplexe Programme mit vielen Funktionen deutlich mehr Overhead.
Selbst nach der Übersetzung einer Routine kann die CPU wieder den Optimierer aufrufen, wenn sich das Verhalten von einer Verzweigung über die Zeit ändert. Diese Situation kann eintreten, wenn sich während der Ausführung eines Programms Bedingungen ändern (z.B. wenn sich die Szene in einem Spielprogramm von Tag zu Nacht ändert). Insbesondere wenn die Sprungvorhersage die Vorhersage für eine Verzweigung ändert, wird der Optimierer aufgerufen. Dieser bestimmt, welche optimierte Routine die Verzweigung enthält und erstellt für die Routine neuen Mikrocode. Diese Art von Reoptimierung kann den kleinen Ausbruch der Optimierer-Aktivität etwa auf halbem Weg durch den Benchmark-Durchlauf in Bild 2 verursacht haben.