Skalare Optimierung

Wir gehen vom Programm linalg in der Version 2.1 aus und übersetzen es mit -cxdb und -O1. Nach dem Start des Debuggers setzen wir die Schrittweite auf ''expression'', setzen einen Breakpoint an den Beginn der Routine GETVEC und lassen das Programm bis dahin laufen:
     set step expression
     break routine getvec
     run
Wir sehen uns nun den Wert von I mit ''print I'' an und bekommen die erstaunliche Meldung ''Variable's storage is not available.''. Genauere Informationen über I erhalten wir mit
     info expression I ,
nämlich u.a.:
     used to create 1 synthesized variable(s):
     1. <INDV>    ?i0 = (loc(R)+-8)+(8*(I-1))
Da keine Gültigkeitsbereiche (''liveness ranges'') angegeben werden, ist die Variable I vollständig wegoptimiert worden; sie kommt im Object-Code nicht vor. Dafür wurde eine Variable ?i0 vom Optimierer erzeugt, die auf die angegebene Weise mit I zusammenhängt. Der Grund für diese Ersetzung ist klar: Statt bei jeder Iteration die Größe I zu erhöhen und dann die Stelle R(I) zu suchen, wird gleich ein Pointer in das Array hinein verwendet, der bei jeder Iteration um 8 Byte (Größe eines Elements von R) weiter zeigt. Weitere Informationen zu der synthetischen Variablen ?i0 erhält man mit
     info expression \?i0 .
Als nächstes sehen wir uns mit
     info line 20
die Source-Units an, die in Zeile 20 beginnen und bekommen u.a.:
       Id    Address Boundaries    Start       End     Kind
   2. (  3)         0:       0    20 x 13    20 x 17  <STMT>  I = 1
   3. (  5)  80001cfe:80001d02    20 x 20    20 x 20  <EXPR>  N
             80001cf6:80001cfa
             80001ce8:80001cf0
Zeile 2 zeigt, daß das Statement ''I $=$ 1'' im Source-Code im Object-Code keine Entsprechnug hat, und wissen inzwischen auch, warum. Die nächste Zeile zeigt, daß der simple Ausdruck ''N'' im Objekt-Code an drei Stellen auftaucht. Mit
     info expression N
sehen wir uns das genauer an:
   object type: Fortran identifier
      location: @(@($ap+4)) <0x8008c6a8>
          size: 4 bytes
          type: INTEGER*4
         value: 100
          used to create 1 synthesized variable(s):
            1. <SEXP>    ?c1 = (loc(R)+-8)+(8*N)
          3 liveness ranges:
                  Start      End         Location
            1.  0x80001cf0:0x80001cf6 - register s0
            2.  0x80001d02:0x80001d08 - register a5
            3.  0x80001ce4:0x80001d44 - @(@($ap+4))
Man erkennt, daß die Variable N nicht direkt in den Speicher geladen wird, sondern daß sie über den Argumentpointer $ap angesprochen und zusätzlich in Registern gehalten wird. Außerdem wird sie noch an anderer Stelle durch den Pointer ?c1 ersetzt, der auf das Ende des Arrays R zeigt. Um zu sehen, was passiert, wenn wir auf diese vielfältige Source-Unit ''N'' einen Breakpoint setzen, öffnen wir nun ein Disassemble-Fenster (Menü ''ProcessWindows'' im Source-Fenster) und setzen den Breakpoint auf die Source-Unit 5 (vgl. ''info line 20 '' -Ausgabe von oben):
     break source 5 .
Tatsächlich erscheinen im Disassembler-Listing drei Breakpoints, von denen der erste an der gleichen Stelle sitzt wie der schon vorher an den Anfang der Routine GETVEC gesetzte. Diese Doppelbelegung wird durch einen ''*'' im Listing angezeigt.

previous    contents     next

Peter Junglas 18.10.1993