Sun Studio 12 Update 1: Fortran ユーザーズガイド

3.4.131 –xipo[={ 0|1|2}]

相互手続きの最適化を実行します。

内部手続き解析パスを呼び出すことにより、プログラム全体の最適化を実行します。-xcrossfile と異なり、-xipo はリンク処理においてすべてのオブジェクトファイルに最適化を実行します。コンパイルコマンドのソースファイルだけに限定されません。

-xipo は、大きなマルチファイルアプリケーションをコンパイルおよびリンクする際に便利です。このフラグでコンパイルされたオブジェクトファイルは、それらのファイル内でコンパイルされた解析情報を保持します。これらの解析情報は、ソースおよびコンパイル前のプログラムファイルで内部手続き解析を可能にします。ただし、解析と最適化は、-xipo でコンパイルされたオブジェクトファイルに限られ、ライブラリのオブジェクトファイルまで拡張できません。

-xipo=0 は内部手続き解析を無効にし、-xipo=1 は有効にします。-xipo=2 は、キャッシュのパフォーマンスを向上させるために、手続き間の別名付けの解析、および記憶域割り当てとレイアウトの最適化を追加します。デフォルトは -xipo=0 で、-xipo が値なしで指定された場合は、-xipo=1 が使用されます。

-xipo=2 を付けてコンパイルすると、-xipo=2 を付けずにコンパイルされた関数やサブルーチン (たとえばライブラリ) から -xipo=2 を付けてコンパイルされた関数やサブルーチンへの呼び出しがあるべきではありません。

一例として、malloc() の置き換えとして、-xipo=2 を付けてコンパイルした独自のバージョンの malloc() を使用する場合は、作成したコードとリンクするライブラリ内の malloc() を参照するすべての関数も -xipo=2 を付けてコンパイルする必要があります。ただし、システムライブラリに対してこのようなことを行うのは不可能な場合があるため、この独自のバージョンの malloc のコンパイルに -xipo=2 を使うべきではありません。

コンパイルとリンクを個別に実行する場合、-xipo をコンパイルとリンクの両方で指定しなければなりません。

単一のコンパイル/リンク処理での -xipo の使用例:


demo% f95 -xipo -xO4 -o prog  part1.f part2.f part3.f

オプティマイザは 3 つのすべてのソースファイル間でファイル間のインライン化を実行します。これは最終的なリンク手順で実行されるため、すべてのソースファイルのコンパイルを単一のコンパイル処理で実行する必要はありません。-xipo を随時指定することにより、個別のコンパイルが多数発生してもかまいません。

個別のコンパイル/リンク処理での -xipo の使用例:


demo% f95 -xipo -xO4 -c part1.f part2.f
demo% f95 -xipo -xO4 -c part3.f
demo% f95 -xipo -xO4 -o prog  part1.o part2.o part3.o

コンパイルステップで作成されるオブジェクトファイルは、それらのファイル内でコンパイルされる追加の分析情報を保持します。そのため、リンクステップにおいてファイル相互の最適化を実行できます。

ここでの制限事項は、-xipo でコンパイルを実行しても、ライブラリがファイル相互の内部手続き解析に含まれない点です。次の例を参照してください。


demo% f95 -xipo -xO4 one.f two.f three.f
demo% ar -r mylib.a one.o two.o three.o
...
demo% f95 -xipo -xO4 -o myprog main.f four.f mylib.a

ここで、one.ftwo.f、および three.f の間、および main.ffour.f の間で相互手続きの最適化が実行されますが、main.f または four.f と、mylib.a のルーチンの間では相互手続きの最適化が実行されません。最初のコンパイルは未定義のシンボルに関する警告を生成する場合がありますが、相互手続きの最適化は、コンパイル手順でありしかもリンク手順であるために実行されます。

-xipo に関するそのほかの重要な情報を次に示します。

コンパイルに -xipo を使用すべきでないケース

内部手続き解析では、コンパイラは、リンクステップでオブジェクトファイル群を操作しながら、プログラム全体の解析と最適化を試みます。このとき、コンパイラは、このオブジェクトファイル群に定義されているすべての foo() 関数 (またはサブルーチン) に関して次の 2 つのことを仮定します。

(1) 実行時、このオブジェクトファイル群の外部で定義されている別のルーチンによって foo() が明示的に呼び出されない。

(2) オブジェクトファイル群内のルーチンから呼び出される foo() が、そのオブジェクトファイル群の外部に定義されている別のバージョンの foo() によって置き換えられることがない。

アプリケーションに対して仮定 (1) が当てはまらない場合は、-xipo=2 でコンパイルしないでください。仮定 (2) が当てはまらない場合は、-xipo=1 および -xipo=2 でコンパイルしないでください。

一例として、独自のソースバージョンの malloc() で関数 -xipo=2 を置き換えるケースを考えてみましょう。その独自のコードとリンクされる malloc() を参照するライブラリのすべての関数も -xipo=2 でコンパイルする必要があり、リンク手順でそれらのオブジェクトファイルが必要になります。しかしながら、システムライブラリでは、このことが不可能なことがあり、このため、独自のバージョンの malloc のコンパイルに -xipo=2 を使うべきではありません。

もう 1 つの例として、別々のソースファイルにある foo() および bar() という 2 つの外部呼び出しを含む共有ライブラリを構築するケースを考えてみましょう。bar() はその本体内で foo() を呼び出します。関数呼び出し foo() が実行時に割り込み処理される場合、foo() または bar() いずれのソースファイルも -xipo=1 または-xipo=2 でコンパイルしません。foo() bar() 内にインライン化され、-xipo でコンパイルした場合に不正な結果になる可能性があります。