Manuelle Kontrollmöglichkeiten des Application-Compilers
Zwar arbeitet der Application-Compiler normalerweise automatisch, es kann
aber Fälle geben, wo man mehr oder weniger Funktionen inlinen oder klonen
möchte. Insbesondere wenn man a priori Informationen über die Häufigkeit
eines Routinen-Aufrufs hat, kann es sinnvoll sein, in den
Optimierungsprozeß einzugreifen.
Um global die Häufigkeit des Inlining zu beeinflußen, kann man die
Kostengrenze verändern, die der Application-Compiler bei der Auswahl von
Funktionen zum Inlinen benutzt. Dazu gibt es eine Option des
''build''-Kommandos:
build -inline DEGREE ,
wobei DEGREE die Werte ''none'', ''low'', ''medium'' und ''high'' annehmen kann.
Der Standardwert ist ''medium''. In unserem Beispielprogramm ''linalg'' wird
bei ''low'' die Funktion GETVEC, die nur einmal aufgerufen wird, nicht mehr
eingefügt, wie sonst bei ''medium''. Die Option ''high'' bewirkt hier keine
Veränderungen.
Man kann auch angeben, daß bestimmte Funktionen immer oder nie eingebaut
werden sollen, indem man entweder im Buildfile eine Zeile
inline(FUNKTION1 [, ...])
bzw.
no_inline(FUNKTION1 [, ...])
vorsieht, oder direkt in den Sourcecode die Compilerdirektive INLINE bzw.
NO_INLINE einfügt:
Fortran:
C$DIR INLINE
nach der SUBROUTINE- bzw. FUNCTION-Zeile
C:
/*$dir inline*/
nach der Deklaration von lokalen Variablen.
Mit der Direktive NO_INLINE_CALL bzw. INLINE_CALL im Source-Code direkt vor
einem Funktionsaufruf kann man auch ganz spezifisch für diesen Aufruf ein
Inlinen verhindern oder erzwingen.
Auch das Erzeugen von Routinen-Klons kann man steuern: Mit der Build-Option
''-clone none'' verhindert man das Klonen völlig, mit ''-clone all'' wird für
jede Routine, in die eine Konstante hineingezogen werden kann, ein eigener
Klon erzeugt. Für einzelne Routinen kann man, wie beim Inlinen, entweder
mit einer Buildfile-Zeile
clone(FUNKTION1 [,...])
no_clone(FUNKTION2 [,...])
oder mit einer Compiler-Direktive CLONE / NO_CLONE im Source-Code hinter
der Deklaration das Klonen beeinflußen. Darüberhinaus gibt es noch die
Möglichkeit, die Direktive CLONE in der Form
C$DIR CLONE(ARG1 [,...]) bzw. /*$dir clone(ARG1 [,...])*/
zu verwenden, wobei die Parameter Argumente der Routine sind. Dies bewirkt,
daß immer dann ein Klon angelegt wird, wenn für eines oder mehrere der
angegebenen Argumente eine Konstante in die Funktion hineingezogen werden
kann.
Außerdem gibt es noch die Möglichkeit, das Verhalten des
Application-Compilers indirekt zu steuern, indem man ihn mit zusätzlichen
Informationen versieht. Um beispielweise abzuschätzen, wie oft eine
Routine aufgerufen wird, nimmt er bei einer IF-Anweisung an, daß beide
Zweige gleich wahrscheinlich sind (falls die Bedingung nicht schon zur
Compilezeit ausgewertet werden kann). Wenn man dagegen schon weiß, daß
die Zweige sehr unterschiedlich oft ausgeführt werden, kann man dies durch
eine Compiler-Direktive mitteilen:
condition_true(NN) (Syntax fuer C bzw. Fortran analog zu oben)
wobei NN, eine ganze Zahl zwischen 1 und 99, die Wahrscheinlichkeit dafür
angibt, daß die Bedingung wahr ist. Die Direktive muß in der Zeile direkt
vor der IF-Anweisung stehen. Eine ähnliche Direktive ist
estimated_trips(NN) ,
die vor einer Schleife stehen kann und angibt, wie oft die Schleife im
Mittel ausgeführt wird. Bei beiden Direktiven ist schon eine grobe
Schätzung hilfreich; nützlich sind auch die Werte, die der CXpa liefert.
Schließlich gibt es noch die Möglichkeit, dem Application-Compiler auf
die Sprünge zu helfen, wenn er trotz seiner globalen Analysen
fälschlicherweise annimmt, daß für einige Variable ein Alias vorliegt
(d.h. eine Überlappung von Arraybereichen, s.o.). Dazu fügt man in das
Buildfile Zeilen der Art
no_alias(VAR1, VAR2)
ein, wobei VAR1 und VAR2 die beiden Variablen mit dem Pseudo-Alias sind.
Sind es Funktionsargumente, so werden sie angegeben als
''funktionsname:variable'' , wobei in FORTRAN alles groß zu schreiben ist.
Eine Fortran-COMMON-Block-Variable bezeichnet man mit
''/COMMONBLOCK/VARIABLE'' bzw. ''//VARIABLE'' für den unbenannten
COMMON-Block. Mit
no_alias(BLOCKNAME)
kann man pauschal angeben, daß kein Alias zwischen einer Variable aus dem
Common-Block BLOCKNAME und irgendeiner anderen Variablen vorliegt.

Peter Junglas 18.10.1993