(57)【特許請求の範囲】
【請求項１】
複数の関数とそれぞれが前記複数の関数の何れかを呼び出す複数の関数呼び出しとを含むコードを記憶する記憶部と、
前記コードに含まれる前記複数の関数それぞれについて、当該関数内のループの繰り返し状況を示す第１の指標値、当該関数のコード量を示す第２の指標値、および、当該関数に含まれる命令のうちパイプライン化されない命令の数を示す第３の指標値を含む複数の指標値を算出し、前記コードに含まれる前記複数の関数呼び出しそれぞれについて、呼び出し先の関数について算出した前記複数の指標値に基づいて評価値を算出し、前記評価値に基づいて前記複数の関数呼び出しの中から１以上の関数呼び出しを選択し、選択した前記１以上の関数呼び出しをインライン展開する変換部と、
を有し、
前記変換部は、前記複数の関数のうちの一の関数に含まれる第１の関数呼び出しをインライン展開すると、前記一の関数について前記複数の指標値を更新し、前記一の関数を呼び出す第２の関数呼び出しについて前記評価値を更新し、更新後の前記評価値に基づいて次にインライン展開する関数呼び出しを選択する情報処理装置。
【請求項２】
前記複数の指標値は、当該関数に対してインライン展開を指示する付加情報が付加されているか否かを示す第４の指標値、および、当該関数に含まれる他の関数呼び出しの数を示す第５の指標値のうちの少なくとも１つを更に含む、
請求項１記載の情報処理装置。
【請求項３】
前記変換部は更に、前記複数の関数呼び出しそれぞれについて、当該関数呼び出しが属するループの繰り返し状況を示す他の指標値を算出し、
前記評価値は、呼び出し先の関数について算出した前記複数の指標値に加えて、当該関数呼び出しについて算出した前記他の指標値に基づいて算出される、
請求項１または２記載の情報処理装置。
【請求項４】
複数の関数とそれぞれが前記複数の関数の何れかを呼び出す複数の関数呼び出しとを含むコードを記憶する記憶部と、
前記コードに含まれる前記複数の関数それぞれについて、当該関数内のループの繰り返し状況を示す第１の指標値および当該関数のコード量を示す第２の指標値を含む複数の指標値を算出し、前記コードに含まれる前記複数の関数呼び出しそれぞれについて、呼び出し先の関数について算出した前記複数の指標値に基づいて評価値を算出し、前記評価値に基づいて前記複数の関数呼び出しの中から１以上の関数呼び出しを選択し、選択した前記１以上の関数呼び出しをインライン展開する変換部と、
を有し、
前記変換部は、前記複数の関数のうちの一の関数に含まれる第１の関数呼び出しをインライン展開すると、前記一の関数について前記複数の指標値を更新し、前記一の関数を呼び出す第２の関数呼び出しについて前記評価値を更新し、更新後の前記評価値に基づいて次にインライン展開する関数呼び出しを選択する情報処理装置。
【請求項５】
コンピュータが実行するコンパイル方法であって、
複数の関数それぞれについて、当該関数内のループの繰り返し状況を示す第１の指標値、当該関数のコード量を示す第２の指標値、および、当該関数に含まれる命令のうちパイプライン化されない命令の数を示す第３の指標値を含む複数の指標値を算出し、
前記複数の関数の何れかを呼び出す複数の関数呼び出しそれぞれについて、呼び出し先の関数について算出した前記複数の指標値に基づいて評価値を算出し、
前記評価値に基づいて前記複数の関数呼び出しの中から１以上の関数呼び出しを選択し、選択した前記１以上の関数呼び出しをインライン展開し、
前記複数の関数のうちの一の関数に含まれる第１の関数呼び出しをインライン展開すると、前記一の関数について前記複数の指標値を更新し、前記一の関数を呼び出す第２の関数呼び出しについて前記評価値を更新し、更新後の前記評価値に基づいて次にインライン展開する関数呼び出しを選択する、
コンパイル方法。
【請求項６】
コンピュータに、
複数の関数それぞれについて、当該関数内のループの繰り返し状況を示す第１の指標値、当該関数のコード量を示す第２の指標値、および、当該関数に含まれる命令のうちパイプライン化されない命令の数を示す第３の指標値を含む複数の指標値を算出し、
前記複数の関数の何れかを呼び出す複数の関数呼び出しそれぞれについて、呼び出し先の関数について算出した前記複数の指標値に基づいて評価値を算出し、
前記評価値に基づいて前記複数の関数呼び出しの中から１以上の関数呼び出しを選択し、選択した前記１以上の関数呼び出しをインライン展開し、
前記複数の関数のうちの一の関数に含まれる第１の関数呼び出しをインライン展開すると、前記一の関数について前記複数の指標値を更新し、前記一の関数を呼び出す第２の関数呼び出しについて前記評価値を更新し、更新後の前記評価値に基づいて次にインライン展開する関数呼び出しを選択する、
処理を実行させるコンパイルプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は情報処理装置、コンパイル方法およびコンパイルプログラムに関する。
【背景技術】
【０００２】
ソフトウェア開発においては、人間が理解容易な高級言語を用いてソースコードを作成し、コンパイラを用いてソースコードを機械可読なオブジェクトコードに変換することが多い。ソースコードを作成する際、再利用性が高くなるように１つの纏まった処理を関数として定義し、関数呼び出しによって関数を繰り返し利用することが行われている。
【０００３】
しかし、関数呼び出しをそのままプロセッサに実行させると、レジスタの値などの内部状態を退避して入れ替えるオーバヘッドが発生する。関数呼び出しが頻繁に実行されると、実行効率が低下するおそれがある。そこで、コンパイラの中には、コンパイラ最適化の１つとして関数呼び出しのインライン展開を行うものがある。関数呼び出しのインライン展開は、関数呼び出し命令を呼び出し先の関数に含まれる命令に置き換えて、オブジェクトコードから関数呼び出し命令を削減する最適化である。関数呼び出しのインライン展開によって、オブジェクトコードの実行効率が向上することがある。
【０００４】
ただし、関数呼び出しをインライン展開すると、呼び出し元のプログラムモジュールでは命令数が増大することが多い。命令数が増大すると、そのプログラムモジュールの命令全体がプロセッサの命令キャッシュに収容されなくなるおそれがあり、命令キャッシュにおける命令の入れ替えが頻発してかえって実行効率が低下するおそれがある。そこで、コンパイラにおいて、ある関数呼び出しをインライン展開した場合のオブジェクトコード量を見積もり、見積もったオブジェクトコード量が命令キャッシュのサイズを超えない場合のみ、当該関数呼び出しをインライン展開する最適化方法が提案されている。
【０００５】
また、関数呼び出し毎にインライン展開の要否を判定するコンパイラが提案されている。提案のコンパイラは、ある関数呼び出しについて、当該関数呼び出しが属するループの実行回数を推定する。コンパイラは、推定したループ回数と、呼び出し先関数のオブジェクトコード量と、ターゲットとするプロセッサの特性とに基づいて、当該関数呼び出しの判定値を算出する。コンパイラは、算出した判定値が所定の閾値を超えている場合に、当該関数呼び出しをインライン展開することを決定する。
【０００６】
また、複数の関数の中から最適化対象とする関数を選択するプログラム変換装置が提案されている。提案のプログラム変換装置は、複数の関数それぞれについて、関数の中で変数にアクセスする命令をカウントする。プログラム変換装置は、カウントした命令数が最も大きい関数を選択し、選択した関数を呼び出す関数呼び出しをインライン展開する。
【先行技術文献】
【特許文献】
【０００７】
【特許文献１】特開平５−１２００２９号公報
【特許文献２】特開平６−２０２８７５号公報
【特許文献３】特開２００１−２８２５４６号公報
【発明の概要】
【発明が解決しようとする課題】
【０００８】
複数の関数呼び出しの中には、インライン展開することによる実行効率の向上の効果が大きいものと小さいものとが存在する。そのため、命令キャッシュのサイズなどの制約のもとで、できる限り実行効率の向上の効果が大きい関数呼び出しを選択してインライン展開することが好ましい。しかし、上記の特許文献２に記載の技術は、インライン展開するか否かを関数呼び出し毎に個別に判定するものであり、複数の関数呼び出しの中からインライン展開するものを選択するものではない。また、上記の特許文献３に記載の技術は、変数にアクセスする命令が多い関数を呼び出し先とする関数呼び出しをインライン展開するものであり、実行効率の向上という点から改善の余地がある。
【０００９】
１つの側面では、本発明は、実行効率の点から適切な関数呼び出しをインライン展開できるようにする情報処理装置、コンパイル方法およびコンパイルプログラムを提供することを目的とする。
【課題を解決するための手段】
【００１０】
１つの態様では、記憶部と変換部とを有する情報処理装置が提供される。記憶部は、複数の関数とそれぞれが複数の関数の何れかを呼び出す複数の関数呼び出しとを含むコードを記憶する。変換部は、コードに含まれる複数の関数それぞれについて、関数内のループの繰り返し状況を示す第１の指標値および関数のコード量を示す第２の指標値を含む複数の指標値を算出する。変換部は、コードに含まれる複数の関数呼び出しそれぞれについて、呼び出し先の関数について算出した複数の指標値に基づいて評価値を算出する。変換部は、評価値に基づいて複数の関数呼び出しの中から１以上の関数呼び出しを選択し、選択した１以上の関数呼び出しをインライン展開する。
【００１１】
また、１つの態様では、コンピュータが実行するコンパイル方法が提供される。また、１つの態様では、コンピュータに実行させるコンパイルプログラムが提供される。
【発明の効果】
【００１２】
１つの側面では、実行効率の点から適切な関数呼び出しをインライン展開できる。
【図面の簡単な説明】
【００１３】
【図１】情報処理装置の例を示す図である。
【図２】コンパイル装置のハードウェア例を示すブロック図である。
【図３】コンパイル装置の機能例を示すブロック図である。
【図４】インライン展開の例を示す図である。
【図５】階層的な関数呼び出しのインライン展開の例を示す図である。
【図６】関数呼び出しグラフの例を示す図である。
【図７】キューおよびスタックの例を示す図である。
【図８】関数データの例を示す図である。
【図９】関数呼び出し指標データと関数指標データの例を示す図である。
【図１０】関数呼び出し指標の抽出例を示す図である。
【図１１】関数指標の抽出例を示す図である。
【図１２】評価基準テーブルの例を示す図である。
【図１３】評価値テーブルの例を示す図である。
【図１４】関数データの更新例を示す図である。
【図１５】評価値の再算出例を示す図である。
【図１６】コンパイルの手順例を示すフローチャートである。
【図１７】順方向関数走査の手順例を示すフローチャートである。
【図１８】関数呼び出し指標抽出の手順例を示すフローチャートである。
【図１９】逆方向関数走査の手順例を示すフローチャートである。
【図２０】関数指標抽出の手順例を示すフローチャートである。
【図２１】インライン展開の手順例を示すフローチャートである。
【発明を実施するための形態】
【００１４】
以下、本実施の形態を図面を参照して説明する。
［第１の実施の形態］
第１の実施の形態を説明する。
【００１５】
図１は、情報処理装置の例を示す図である。
第１の実施の形態の情報処理装置１０は、高級言語で記載されたソースコードをコンパイルし、機械可読なオブジェクトコードを生成する。情報処理装置１０は、コンパイル装置と呼ぶこともできる。情報処理装置１０は、コンピュータであってもよい。例えば、情報処理装置１０は、ソフトウェアとしてのコンパイラを実行する。情報処理装置１０は、ユーザが操作する端末装置（クライアントコンピュータなど）でもよいし、端末装置からアクセスされるサーバ装置（サーバコンピュータなど）であってもよい。
【００１６】
情報処理装置１０は、記憶部１１および変換部１２を有する。記憶部１１は、例えば、ＲＡＭ（Random Access Memory）などの揮発性の記憶装置、または、ＨＤＤ（Hard Disk Drive）やフラッシュメモリなどの不揮発性の記憶装置である。変換部１２は、例えば、ＣＰＵ（Central Processing Unit）やＤＳＰ（Digital Signal Processor）などのプロセッサである。ただし、変換部１２は、ＡＳＩＣ（Application Specific Integrated Circuit）やＦＰＧＡ（Field Programmable Gate Array）などの特定用途の電子回路を含んでもよい。プロセッサは、ＲＡＭなどのメモリに記憶されたプログラムを実行する。例えば、プロセッサは、ソースコードをコンパイルするコンパイルプログラムを実行する。複数のプロセッサの集合（マルチプロセッサ）を「プロセッサ」と呼ぶこともある。
【００１７】
記憶部１１は、コード１３を記憶する。コード１３は、例えば、ソースコードまたはソースコードから変換された中間コードである。コード１３には、関数１４ａ，１４ｂ，１４ｃを含む複数の関数が記載されている。図１の例では、関数１４ａは呼び出されると処理Ａを実行し、関数１４ｂは呼び出されると処理Ｂを実行し、関数１４ｃは呼び出されると処理Ｃを実行する。また、コード１３には、関数呼び出し１５ａ，１５ｂ，１５ｃを含む複数の関数呼び出しが記載されている。各関数呼び出しは、何れかの関数を呼び出す。図１の例では、関数呼び出し１５ａは関数１４ａを呼び出し、関数呼び出し１５ｂは関数１４ｂを呼び出し、関数呼び出し１５ｃは関数１４ｃを呼び出す。
【００１８】
変換部１２は、コード１３に記載された各関数について、指標値１６ａ（第１の指標値）および指標値１６ｂ（第２の指標値）を含む複数の指標値を算出する。指標値１６ａは、関数内のループの繰り返し状況（例えば、ループ回数）を示す。指標値１６ｂは、関数のコード量（例えば、ソースコードの行数や中間コードの命令数など）を示す。
【００１９】
変換部１２が算出する複数の指標値には、第３の指標値、第４の指標値および第５の指標値の少なくとも１つが更に含まれてもよい。第３の指標値は、関数に対してインライン展開を指示する付加情報が付加されているか否かを示す。付加情報は、例えば、ユーザによってソースコードに付加される。第４の指標値は、関数に含まれる他の関数呼び出しの数を示す。第５の指標値は、関数に含まれる命令のうちパイプライン化されない命令の数を示す。パイプライン化されない命令の種類は、ターゲットとするプロセッサに依存し、例えば、ＳＩＭＤ（Single Instruction Multiple Data）命令などである。
【００２０】
変換部１２は、コード１３に記載された各関数呼び出しについて評価値１７を算出する。評価値１７は、呼び出し先の関数について算出した上記の複数の指標値を用いて算出する。例えば、変換部１２は、指標値１６ａ，１６ｂそれぞれに所定の重みをかけて合算した値を評価値１７とする。重みは、ターゲットとするプロセッサに応じて変えてもよい。図１の例では、関数呼び出し１５ａの評価値を、関数１４ａの指標値を用いて算出する。関数呼び出し１５ｂの評価値を、関数１４ｂの指標値を用いて算出する。関数呼び出し１５ｃの評価値を、関数１４ｃの指標値を用いて算出する。
【００２１】
このとき、変換部１２は、関数呼び出しを含むモジュール（例えば、当該関数呼び出しを含む関数）に応じた他の指標値を算出し、呼び出し先の関数の指標値に加えて他の評価値を用いて評価値１７を算出してもよい。他の評価値として、例えば、第６の指標値や第７の指標値を用いることができる。第６の指標値は、関数呼び出しが属するループの繰り返し状況（例えば、ループ回数）を示す。第７の指標値は、関数呼び出しが属するモジュールに含まれる命令のうちパイプライン化されない命令の数を示す。
【００２２】
変換部１２は、評価値１７に基づいて複数の関数呼び出しの中から１以上の関数呼び出しを選択し、選択した関数呼び出しをインライン展開する。すなわち、変換部１２は、選択した関数呼び出しの命令を、呼び出し先の関数に含まれる命令に置き換える。選択する関数呼び出しは、例えば、評価値１７が大きいものを優先する。ただし、インライン展開後の各モジュールのコード量が、ターゲットとするプロセッサの命令キャッシュ（例えば、Ｌ１（レイヤ１）命令キャッシュ）のサイズを超えないことを条件としてもよい。
【００２３】
図１の例では、関数呼び出し１５ａ，１５ｂ，１５ｃがメイン関数に含まれている。関数呼び出し１５ａの評価値が「６０」、関数呼び出し１５ｂの評価値が「１００」、関数呼び出し１５ｃの評価値が「８０」である。この場合、メイン関数のコード量が命令キャッシュのサイズを超えないことを条件として、関数呼び出し１５ａ，１５ｂ，１５ｃのうち関数呼び出し１５ｂが優先的に選択され、次に関数呼び出し１５ｃが選択される。その結果、関数呼び出し１５ｂ，１５ｃがインライン展開され、先頭に記載された関数呼び出し１５ａはインライン展開されないことになる可能性がある。
【００２４】
第１の実施の形態の情報処理装置１０によれば、関数１４ａ，１４ｂ，１４ｃそれぞれについて、関数内のループの繰り返し状況を示す指標値１６ａおよび関数のコード量を示す指標値１６ｂを含む複数の指標値が算出される。関数呼び出し１５ａ，１５ｂ，１５ｃそれぞれについて、呼び出し先の関数について算出した複数の指標値に基づいて評価値１７が算出される。そして、評価値１７に基づいて関数呼び出し１５ａ，１５ｂ，１５ｃの中から１以上の関数呼び出しが選択されてインライン展開される。
【００２５】
これにより、命令キャッシュのサイズなどの制約によって一部の関数呼び出しのみをインライン展開する場合であっても、オブジェクトコードの実行効率向上の効果が大きい関数呼び出しを優先的にインライン展開することができる。すなわち、実行効率の点から適切な関数呼び出しをインライン展開することができる。また、関数呼び出しの全通りの組み合わせについて実行効率向上の効果を直接評価しなくてもよく、コンパイル最適化の負荷を低減しコンパイル時間を短縮することが可能となる。
【００２６】
［第２の実施の形態］
次に、第２の実施の形態を説明する。
第２の実施の形態のコンパイル装置１００は、高級言語で記述されたソースコードをコンパイルし、機械可読なオブジェクトコードを生成する。コンパイル装置１００は、ユーザが操作する端末装置でもよいし、端末装置からアクセスされるサーバ装置でもよい。コンパイル装置１００は、例えば、コンピュータを用いて実装される。その場合、コンパイル装置１００は、ソフトウェアとしてのコンパイラおよびリンカを実行する。
【００２７】
図２は、コンパイル装置のハードウェア例を示すブロック図である。
コンパイル装置１００は、ＣＰＵ１０１、ＲＡＭ１０２、ＨＤＤ１０３、画像信号処理部１０４、入力信号処理部１０５、媒体リーダ１０６および通信インタフェース１０７を有する。上記ユニットはバス１０８に接続される。
【００２８】
ＣＰＵ１０１は、プログラムの命令を実行する演算回路を含むプロセッサである。ＣＰＵ１０１は、ＨＤＤ１０３に記憶されたプログラムやデータの少なくとも一部をＲＡＭ１０２にロードし、プログラムを実行する。なお、ＣＰＵ１０１は複数のプロセッサコアを備えてもよく、コンパイル装置１００は複数のプロセッサを備えてもよく、以下で説明する処理を複数のプロセッサまたはプロセッサコアを用いて並列に実行してもよい。また、複数のプロセッサの集合（マルチプロセッサ）を「プロセッサ」と呼んでもよい。
【００２９】
ＲＡＭ１０２は、ＣＰＵ１０１が実行するプログラムやＣＰＵ１０１が演算に用いるデータを一時的に記憶する揮発性の半導体メモリである。なお、コンパイル装置１００は、ＲＡＭ以外の種類のメモリを備えてもよく、複数個のメモリを備えてもよい。
【００３０】
ＨＤＤ１０３は、ＯＳ（Operating System）やミドルウェアやアプリケーションソフトウェアなどのソフトウェアのプログラム、および、データを記憶する不揮発性の記憶装置である。プログラムには、コンパイルプログラムやリンクプログラムが含まれる。なお、コンパイル装置１００は、フラッシュメモリやＳＳＤ（Solid State Drive）などの他の種類の記憶装置を備えてもよく、複数の不揮発性の記憶装置を備えてもよい。
【００３１】
画像信号処理部１０４は、ＣＰＵ１０１からの命令に従って、コンパイル装置１００に接続されたディスプレイ１１１に画像を出力する。ディスプレイ１１１としては、ＣＲＴ（Cathode Ray Tube）ディスプレイ、液晶ディスプレイ（ＬＣＤ：Liquid Crystal Display）、プラズマディスプレイ（ＰＤＰ：Plasma Display Panel）、有機ＥＬ（ＯＥＬ：Organic Electro-Luminescence）ディスプレイなどを用いることができる。
【００３２】
入力信号処理部１０５は、コンパイル装置１００に接続された入力デバイス１１２から入力信号を取得し、ＣＰＵ１０１に出力する。入力デバイス１１２としては、マウスやタッチパネルやタッチパッドやトラックボールなどのポインティングデバイス、キーボード、リモートコントローラ、ボタンスイッチなどを用いることができる。また、コンパイル装置１００に、複数の種類の入力デバイスが接続されていてもよい。
【００３３】
媒体リーダ１０６は、記録媒体１１３に記録されたプログラムやデータを読み取る読み取り装置である。記録媒体１１３として、例えば、フレキシブルディスク（ＦＤ：Flexible Disk）やＨＤＤなどの磁気ディスク、ＣＤ（Compact Disc）やＤＶＤ（Digital Versatile Disc）などの光ディスク、光磁気ディスク（ＭＯ：Magneto-Optical disk）、半導体メモリなどを使用できる。媒体リーダ１０６は、例えば、記録媒体１１３から読み取ったプログラムやデータをＲＡＭ１０２またはＨＤＤ１０３に格納する。
【００３４】
通信インタフェース１０７は、ネットワーク１１４に接続され、ネットワーク１１４を介して他のコンピュータと通信を行うインタフェースである。通信インタフェース１０７は、スイッチなどの通信装置とケーブルで接続される有線通信インタフェースでもよいし、基地局と無線リンクで接続される無線通信インタフェースでもよい。
【００３５】
なお、コンパイル装置１００は、媒体リーダ１０６を備えていなくてもよく、ユーザが操作する端末装置から制御可能である場合には画像信号処理部１０４や入力信号処理部１０５を備えていなくてもよい。また、ディスプレイ１１１や入力デバイス１１２が、コンパイル装置１００の筐体と一体に形成されていてもよい。
【００３６】
図３は、コンパイル装置の機能例を示すブロック図である。
コンパイル装置１００は、ファイル記憶部１２０、コンパイラ１３０およびリンカ１５０を有する。ファイル記憶部１２０は、例えば、ＲＡＭ１０２またはＨＤＤ１０３に確保した記憶領域として実現される。コンパイラ１３０およびリンカ１５０は、例えば、ＣＰＵ１０１が実行するプログラムのモジュール（コンパイルプログラムおよびリンクプログラム）として実現できる。ただし、コンパイラ１３０およびリンカ１５０の機能の一部または全部を、ソフトウェアでなく電子回路として実現することも可能である。
【００３７】
ファイル記憶部１２０は、ソースファイル１２１、オブジェクトファイル１２２および実行ファイル１２３を記憶する。ソースファイル１２１は、Ｃ＋＋などの高級言語で記述されたソースコードを含む。オブジェクトファイル１２２は、機械可読なオブジェクトコードを含む。実行ファイル１２３は、ターゲットのプロセッサが実行できる形式のファイルであり、生成されたオブジェクトコードとライブラリなどへのリンクを含む。なお、実行ファイル１２３は、ＣＰＵ１０１が実行してもよいし、コンパイル装置１００が備える他のＣＰＵまたはコンパイル装置１００以外のコンピュータのＣＰＵが実行してもよい。
【００３８】
コンパイラ１３０は、ファイル記憶部１２０からソースファイル１２１を読み出し、ソースコードをオブジェクトコードに変換し、オブジェクトファイル１２２をファイル記憶部１２０に格納する。コンパイラ１３０は、入出力制御部１３１、ファイル入力部１３２、中間コード生成部１３３、中間コード記憶部１３４、アセンブリコード生成部１３５、ファイル出力部１３６、最適化部１４０および制御情報記憶部１４３を有する。
【００３９】
入出力制御部１３１は、ファイルの種類に応じた入出力方法を選択し、ファイル入力部１３２およびファイル出力部１３６を制御する。ファイル入力部１３２は、入出力制御部１３１からの指示に応じて、ソースファイル１２１をオープンし、ソースファイル１２１からソースコードを読み出す。中間コード生成部１３３は、ファイル入力部１３２が読み出したソースコードを解析して、コンパイラ１３０の内部で利用される中間言語で記述された中間コードに変換し、中間コードを中間コード記憶部１３４に格納する。ソースコードの解析には、字句解析、構文解析、意味解析などが含まれる。中間コード記憶部１３４は、ＲＡＭ１０２に確保された記憶領域であり、中間コードを記憶する。
【００４０】
アセンブリコード生成部１３５は、最適化部１４０によって最適化された中間コードを、低級言語であるアセンブリ言語で記述されたアセンブリコードに変換する。ファイル出力部１３６は、入出力制御部１３１からの指示に応じて、オブジェクトファイル１２２を生成し、アセンブリコード生成部１３５が生成したアセンブリコードをオブジェクトコードに変換し、オブジェクトファイル１２２に書き込む。
【００４１】
最適化部１４０は、中間コード記憶部１３４に記憶された中間コードを、実行速度が向上するように最適化する。最適化部１４０は、解析部１４１および最適化実行部１４２を有する。解析部１４１は、中間コードを解析して最適化方法を決定する。解析部１４１が行う最適化方法の決定には、関数呼び出しのインライン展開、すなわち、関数呼び出し命令を呼び出し先の関数に含まれる命令に置き換えて関数呼び出しを削減することが含まれる。最適化実行部１４２は、解析部１４１が決定した最適化方法に従って中間コードを最適化する。最適化実行部１４２が行う最適化には、インライン展開が含まれる。
【００４２】
制御情報記憶部１４３は、ＲＡＭ１０２またはＨＤＤ１０３に確保された記憶領域であり、最適化部１４０が最適化処理の中で生成または参照する各種の制御情報を記憶する。制御情報の詳細については後述する。
【００４３】
リンカ１５０は、ファイル記憶部１２０からオブジェクトファイル１２２を読み出し、オブジェクトコードを解析して、参照されている他のオブジェクトファイルやライブラリを検出する。そして、リンカ１５０は、オブジェクトファイル１２２と、検出した他のオブジェクトファイルやライブラリとをリンクし、実行ファイル１２３を生成する。なお、コンパイラ１３０にリンカ１５０の機能が統合されていてもよい。
【００４４】
次に、関数呼び出しのインライン展開について説明する。
図４は、インライン展開の例を示す図である。
ここでは説明を簡単にするため、ソースコードレベルで関数呼び出しのインライン展開について説明する。コンパイル装置１００は、実際には、図４に記載されたソースコードに対応する中間コードに対して関数呼び出しのインライン展開を行う。
【００４５】
ソースコード２１は、ソースファイル１２１に含まれるソースコードの一例である。ソースコード２１は、関数ｍａｉｎと関数ｂｉｇ＿ｓｕｂＡと関数ｂｉｇ＿ｓｕｂＢと関数ｉｎｌｉｎｅ＿ｓｕｂとを含む。関数ｂｉｇ＿ｓｕｂＡには、１９９０行の命令文によって処理Ａが定義されている。関数ｂｉｇ＿ｓｕｂＢには、１９９０行の命令文によって処理Ｂが定義されている。関数ｉｎｌｉｎｅ＿ｓｕｂには、２０行の命令文によって処理Ｃが定義されている。関数ｍａｉｎは、関数ｂｉｇ＿ｓｕｂＡを呼び出す関数呼び出し２１ａと、関数ｂｉｇ＿ｓｕｂＢを呼び出す関数呼び出し２１ｂと、関数ｉｎｌｉｎｅ＿ｓｕｂを呼び出す関数呼び出し２１ｃとを含む。関数呼び出し２１ｃは、ループ回数が１００のループ内に存在する。関数呼び出し２１ａ，２１ｂはループ外に存在する。
【００４６】
ここで、ソースコード２１に対してインライン展開の最適化を行う場合を考える。ただし、Ｌ１命令キャッシュのサイズの制約から、関数ｍａｉｎの行数が４０００を超えないことを条件とする。ここで言う「行数」は、セミコロンで終わる実質的な命令文の数であり、図４に示したソースコード２１における関数ｍａｉｎの行数は５である。インライン展開の方法として、以下の２つの方法が考えられる。
【００４７】
第１の方法は、ソースコード２１の先頭に近い方から順に関数呼び出しをインライン展開する方法である。第１の方法によれば、ソースコード２１がソースコード２２に変換される。すなわち、まず関数呼び出し２１ａが選択される。関数呼び出し２１ａをインライン展開すると、関数ｍａｉｎの行数が１９９４になるため、選択された関数呼び出し２１ａがインライン展開される。次に、関数呼び出し２１ｂが選択される。関数呼び出し２１ｂをインライン展開すると、関数ｍａｉｎの行数が３９８３になるため、選択された関数呼び出し２１ｂがインライン展開される。次に、関数呼び出し２１ｃが選択される。関数呼び出し２１ｃをインライン展開すると、関数ｍａｉｎの行数が４００２になるため、選択された関数呼び出し２１ｃはインライン展開されず最適化が終了する。
【００４８】
しかし、第１の方法によれば、１回しか実行されない関数呼び出し２１ａ，２１ｂがインライン展開され、１００回実行される関数呼び出し２１ｃがインライン展開されない。このため、ソースコード２２に対応するオブジェクトコードには、実行効率に改善の余地がある。そこで、第２の方法は、関数呼び出し２１ａ，２１ｂ，２１ｃを評価し、評価値の大きい関数呼び出しを優先的に選択するようにする。ここでは、評価値に応じて関数呼び出し２１ｃ，２１ａ，２１ｂの順に選択されるものとする。
【００４９】
第２の方法によれば、ソースコード２１がソースコード２３に変換される。すなわち、まず関数呼び出し２１ｃが選択される。関数呼び出し２１ｃをインライン展開すると、関数ｍａｉｎの行数が２４になるため、選択された関数呼び出し２１ｃがインライン展開される。次に、関数呼び出し２１ａが選択される。関数呼び出し２１ａをインライン展開すると、関数ｍａｉｎの行数が２０２３になるため、選択された関数呼び出し２１ａがインライン展開される。次に、関数呼び出し２１ｂが選択される。関数呼び出し２１ｂをインライン展開すると、関数ｍａｉｎの行数が４００２になるため、選択された関数呼び出し２１ｂはインライン展開されず最適化が終了する。
【００５０】
第２の方法によって生成されたソースコード２３に対応するオブジェクトコードは、第１の方法によって生成されたソースコード２２に対応するオブジェクトコードと比べて関数呼び出しの回数が少なくなる。よって、実行効率が向上していると言える。
【００５１】
図５は、階層的な関数呼び出しのインライン展開の例を示す図である。
ここでは、階層的な関数呼び出しの一部をインライン展開する場合について説明する。関数３１（ｒｏｏｔＳｕｂ）は、関数３２（ｓｕｂＡ）を呼び出す関数呼び出しと、関数３３（ｓｕｂＢ）を呼び出す関数呼び出しと、関数３４（ｓｕｂＣ）を呼び出す関数呼び出しとを含む。関数３２は、「Ａ＝Ａ＋１」という命令文を含む。関数３３は、関数３５（ｓｕｂＸ）を呼び出す関数呼び出しと、関数３６（ｓｕｂＹ）を呼び出す関数呼び出しとを含む。関数３４は、関数３７（ｓｕｂＺ）を呼び出す関数呼び出しを含む。関数３５は、「Ｘ＝Ｘ＋２」という命令文を含む。関数３６は、「Ｙ＝Ｙ＊３」という命令文を含む。関数３７は、「Ｚ＝Ｚ／２」という命令文を含む。
【００５２】
ここで、関数３１から関数３２を呼び出す関数呼び出しと、関数３１から関数３４を呼び出す関数呼び出しとをインライン展開するとする。また、関数３３から関数３５を呼び出す関数呼び出しと、関数３３から関数３６を呼び出す関数呼び出しと、関数３４から関数３７を呼び出す関数呼び出しとをインライン展開するとする。一方、関数３１から関数３３を呼び出す関数呼び出しはインライン展開しないとする。
【００５３】
この場合、関数３５の命令文「Ｘ＝Ｘ＋２」が関数３３に組み込まれ、関数３６の命令文「Ｙ＝Ｙ＊３」が関数３３に組み込まれる。また、関数３７の命令文「Ｚ＝Ｚ／２」が関数３４に組み込まれる。また、関数３２の命令文「Ａ＝Ａ＋１」が関数３１に組み込まれる。また、関数３４に組み込まれた命令文「Ｚ＝Ｚ／２」が関数３１に組み込まれる。その結果、関数３１は、命令文「Ａ＝Ａ＋１」と関数３３の関数呼び出しと命令文「Ｚ＝Ｚ／２」とを含むことになる。関数３３は、命令文「Ｘ＝Ｘ＋２」と命令文「Ｙ＝Ｙ＊３」とを含むことになる。なお、関数３２，３４，３５，３６，３７は、他の関数から参照されていない場合にはオブジェクトコードから削除してもよい。
【００５４】
次に、各関数呼び出しの評価に用いるデータ構造について説明する。
図６は、関数呼び出しグラフの例を示す図である。
関数呼び出しグラフ４０は、解析部１４１が中間コード記憶部１３４に記憶された中間コードを解析することで生成する。関数呼び出しグラフ４０は、関数を示すノードと関数呼び出しを示すリンクとを含む。関数呼び出しグラフ４０は、階層的な関数呼び出しを表現したグラフであり、ツリーの形状またはツリーに類似する形状をもつ。具体的には、関数呼び出しグラフ４０は、ルートとなる１つのノードを有する点でツリーと共通する。ただし、関数呼び出しグラフ４０は、同じノード間に複数のリンクが設定され得る点、および、異なる親ノードが同じ子ノードと接続され得る点で、ツリーと異なることがある。
【００５５】
一例として、関数呼び出しグラフ４０は、関数＃１〜＃１２に対応するノードと関数呼び出し＃Ａ〜＃Ｋに対応するリンクとを有する。＃１〜＃１２は、中間コードに含まれる各関数に対して解析部１４１が付与したＩＤである。＃Ａ〜＃Ｍは、中間コードに含まれる各関数呼び出しに対して解析部１４１が付与したＩＤである。
【００５６】
関数＃１２は、関数＃９を呼び出す関数呼び出し＃Ａと、関数＃１０を呼び出す関数呼び出し＃Ｂと、関数＃１１を呼び出す関数呼び出し＃Ｃとを含む。関数＃１１は、関数＃７を呼び出す関数呼び出し＃Ｄと、関数＃８を呼び出す関数呼び出し＃Ｅとを含む。関数＃９は、関数＃５を呼び出す関数呼び出し＃Ｆと、関数＃６を呼び出す関数呼び出し＃Ｇとを含む。関数＃８は、関数＃３を呼び出す関数呼び出し＃Ｈと、関数＃３を呼び出す関数呼び出し＃Ｉと、関数＃４を呼び出す関数呼び出し＃Ｊとを含む。関数＃６は、関数＃１を呼び出す関数呼び出し＃Ｋと、関数＃２を呼び出す関数呼び出し＃Ｌとを含む。関数＃７は、関数＃２を呼び出す関数呼び出し＃Ｍを含む。
【００５７】
以下で説明するように、関数呼び出し＃Ａ〜＃Ｍの評価値は、関数呼び出しグラフ４０に従って関数＃１〜＃１２全体を２回走査することで算出することができる。１回目の走査は、関数呼び出しグラフ４０のルートから葉ノードに向かって幅優先順に関数を走査するものであり、順方向関数走査と言うことができる。すなわち、解析部１４１は、１回目の走査において、関数＃１２，＃１１，＃１０，＃９，＃８，＃７，＃６，＃５，＃４，＃３，＃２，＃１の順に関数＃１〜＃１２を走査する。２回目の走査は、１回目とは逆順に関数を走査するものであり、逆方向関数走査と言うことができる。すなわち、解析部１４１は、２回目の走査において、関数＃１，＃２，＃３，＃４，＃５，＃６，＃７，＃８，＃９，＃１０，＃１１，＃１２の順に関数＃１〜＃１２を走査する。
【００５８】
図７は、キューおよびスタックの例を示す図である。
キュー１６１およびスタック１６２は、制御情報記憶部１４３に形成されている記憶領域である。キュー１６１およびスタック１６２はそれぞれ、関数＃１〜＃１２を識別する関数ＩＤを記憶する。キュー１６１は、先入れ先出し（ＦＩＦＯ：First In First Out）のデータ構造をもち、先に挿入された関数ＩＤから先に抽出することができる。スタック１６２は、後入れ先出し（ＬＩＦＯ：Last In First Out）のデータ構造をもち、後に挿入された関数ＩＤから先に抽出することができる。
【００５９】
解析部１４１は、上記の順方向関数走査において、検出した関数の関数ＩＤをキュー１６１およびスタック１６２に挿入する。キュー１６１に挿入された関数ＩＤは、以降の順方向関数走査に使用される。解析部１４１は、順方向関数走査においてキュー１６１の末尾（入口の逆側）から関数ＩＤを抽出する。スタック１６２に挿入された関数ＩＤは、上記の２回目の走査（逆方向関数走査）に使用される。解析部１４１は、逆方向関数走査においてスタック１６２の先頭（入口）から関数ＩＤを抽出する。
【００６０】
図８は、関数データの例を示す図である。
解析部１４１は、関数ＩＤをキュー１６１およびスタック１６２に挿入したとき、併せて関数データ１６３を生成する。関数データ１６３は、制御情報記憶部１４３に記憶される。関数データ１６３は、各関数に対応するレコードを含む。１つのレコードは、関数ＩＤ、アドレス、呼び出し元および呼び出し先の項目を有する。
【００６１】
アドレスの項目は、当該関数の先頭位置を示す。呼び出し元の項目は、当該関数を呼び出す他の関数のアドレスを示す。呼び出し元の項目には、複数の他の関数のアドレスが含まれることがある。ただし、ルートの関数（図６の例では関数＃１２）に対応するレコードでは、呼び出し元の項目は空となる。呼び出し先の項目は、当該関数から呼び出される他の関数のアドレスと関数呼び出しを識別する関数呼び出しＩＤとを示す。呼び出し先の項目には、複数の他の関数のアドレスおよび複数の関数呼び出しＩＤが含まれることがある。ただし、葉ノードの関数（図６の例では関数＃１，＃２，＃３，＃４，＃５，＃１０）に対応するレコードでは、呼び出し先の項目は空となる。
【００６２】
一例として、関数＃８に対応するレコードは、関数ＩＤ「８」、アドレス「０ｘ０８８８」、呼び出し元「０ｘ１１１１」、呼び出し先「０ｘ０３３３，Ｈ」，「０ｘ０３３３，Ｉ」，「０ｘ０４４４，Ｊ」を含む。「０ｘ１１１１」は関数＃１１のアドレス、「０ｘ０３３３」は関数＃３のアドレス、「０ｘ０４４４」は関数＃４のアドレスである。
【００６３】
図９は、関数呼び出し指標データと関数指標データの例を示す図である。
解析部１４１は、順方向関数走査で、各関数呼び出しについての指標値を中間コードから抽出し、抽出した指標値を含む関数呼び出し指標データ１６４を生成する。関数呼び出し指標データ１６４は、制御情報記憶部１４３に記憶される。関数呼び出し指標データ１６４は、各関数呼び出しに対応するレコードを含む。１つのレコードは、関数呼び出しＩＤ、ループ回数、最内ループフラグおよび非パイプライン命令数の項目を有する。
【００６４】
ループ回数の項目は、当該関数呼び出しが属するループの繰り返し回数を示す。当該関数呼び出しが属するブロック（ひと纏まりのコンパイル単位）にループがない場合、ループ回数は０になる。繰り返し回数が中間コードから不明な場合（例えば、実行時に動的に決まる場合）、ループ回数を０などの所定値とみなしてもよい。
【００６５】
最内ループフラグの項目は、当該関数呼び出しが最内ループに属している（当該関数呼び出しが属するループの内側に他のループが存在しない）か否かを示す。当該関数呼び出しの属するブロックにループがない場合、または、当該関数呼び出しが属するループの内側に他のループが存在しない場合、最内ループフラグはＴｒｕｅになる。非パイプライン命令数の項目は、当該関数呼び出しが属するブロックに含まれる命令のうち、パイプライン化されない命令の数を示す。パイプライン化されない命令は、ターゲットのプロセッサのアーキテクチャに依存する。一例として、ＳＩＭＤ命令が挙げられる。
【００６６】
解析部１４１は、逆方向関数走査で、各関数についての指標値を中間コードから抽出し、抽出した指標値を含む関数指標データ１６５を生成する。関数指標データ１６５は、制御情報記憶部１４３に記憶される。関数指標データ１６５は、各関数に対応するレコードを含む。１つのレコードは、関数ＩＤ、ループ回数、ソースコード行数、中間コード命令数、ユーザ指示フラグ、関数呼び出し数および非パイプライン命令数の項目を有する。
【００６７】
ループ回数の項目は、当該関数に含まれるループの繰り返し回数を示す。当該関数にループがない場合、ループ回数は０になる。繰り返し回数が中間コードから不明な場合（例えば、実行時に動的に決まる場合）、ループ回数を０などの所定値とみなしてもよい。ソースコード行数の項目は、当該関数を定義したソースコードの行数を示す。ただし、「行数」としては実質的な命令文のみをカウントし、関数名や括弧やコメントの行は除外する。中間コード命令数の項目は、当該関数を定義した中間コードの命令数を示す。
【００６８】
ユーザ指示フラグは、当該関数に対してインライン展開を指示する指示文が付加されているか否かを示す。インライン展開の指示文は、ユーザによってソースコードに記載されるものである。インライン展開の指示文が付加されている場合、ユーザ指示フラグがＴｒｕｅになる。関数呼び出し数の項目は、当該関数に含まれる関数呼び出し命令の数を示す。非パイプライン命令数の項目は、当該関数に含まれる命令のうち、パイプライン化されない命令（例えば、ＳＩＭＤ命令など）の数を示す。
【００６９】
図１０は、関数呼び出し指標の抽出例を示す図である。
ソースコード２４は、ソースファイル１２１に含まれるソースコードの一例である。ソースコード２４は、関数＃１１（ｆｕｎｃ１１と表記）を含む。関数＃１１は、関数＃８（ｆｕｎｃ８と表記）を呼び出す関数呼び出し＃Ｅを含む。関数呼び出し＃Ｅは、ループ回数が１００回のループに属している。すなわち、関数＃８が１００回繰り返し呼び出されることになる。ソースコード２４は、中間コード生成部１３３によって中間コード５１に変換される。中間コード５１は、中間コード記憶部１３４に記憶される。
【００７０】
この場合、解析部１４１は、順方向関数走査において、関数呼び出し＃Ｅに対応するレコード１６４ａを生成して関数呼び出し指標データ１６４に追加する。レコード１６４ａは、関数呼び出しＩＤ「Ｅ」を含む。また、関数呼び出し＃Ｅの属するループの繰り返し回数が１００であるため、レコード１６４ａはループ回数「１００」を含む。ループ回数は、例えば、ループ変数の代入文を検索することで中間コード５１から抽出できる。また、関数呼び出し＃Ｅが最内ループに属しているため、レコード１６４ａは最内ループフラグ「Ｔｒｕｅ」を含む。また、関数＃１１にはパイプライン化されない命令が存在しないため、レコード１６４ａは非パイプライン命令数「０」を含む。
【００７１】
図１１は、関数指標の抽出例を示す図である。
ソースコード２５は、ソースファイル１２１に含まれるソースコードの一例である。ソースコード２５は、関数＃８（ｆｕｎｃ８と表記）を含む。関数＃８は、関数＃４（ｆｕｎｃ４と表記）を呼び出す関数呼び出し＃Ｊと、関数＃３（ｆｕｎｃ３と表記）を呼び出す関数呼び出し＃Ｉと、関数＃３を呼び出す関数呼び出し＃Ｈとを含む。関数呼び出し＃Ｊ，＃Ｉは、ループ回数が１０回のループに属している。すなわち、関数＃３，＃４が交互に１０回呼び出される。ソースコード２５は、中間コード生成部１３３によって中間コード５２に変換される。中間コード５１は、中間コード記憶部１３４に記憶される。
【００７２】
この場合、解析部１４１は、逆方向関数走査において、関数＃８に対応するレコード１６５ａを生成して関数指標データ１６５に追加する。レコード１６５ａは、関数ＩＤ「８」を含む。また、関数＃８に１０回繰り返されるループが含まれるため、レコード１６５ａはループ回数「１０」を含む。ループ回数は、例えば、ループ変数の代入文を検索することで中間コード５２から抽出できる。また、ソースコード２５がセミコロンで終わる命令文を４個含むため、レコード１６５ａはソースコード行数「４」を含む。また、中間コード５２がｍｏｖｅ命令２個、ｃａｌｌｐｅ命令３個、ａｄｄ命令１個およびｂｃｔ命令１個含むため、レコード１６５ａは中間コード命令数「７」を含む。
【００７３】
また、ソースコード２５にインライン展開の指示文が付加されていないため、レコード１６５ａはユーザ指示フラグ「Ｆａｌｓｅ」を含む。また、関数＃８が３個の関数呼び出し命令（ｃａｌｌｐｅ命令）を含むため、レコード１６５ａは関数呼び出し数「３」を含む。また、関数＃８にはパイプライン化されない命令が存在しないため、レコード１６５ａは非パイプライン命令数「０」を含む。
【００７４】
図１２は、評価基準テーブルの例を示す図である。
評価基準テーブル１６６は、関数呼び出し指標データ１６４および関数指標データ１６５から各関数呼び出しの評価値を算出する算出方法を示す。評価基準テーブル１６６は、プロセッサのアーキテクチャ毎に予め用意されて制御情報記憶部１４３に記憶されている。アーキテクチャ毎に用意されるのは、命令キャッシュのサイズや命令長がアーキテクチャによって異なり、実行効率が向上するか否かの基準がアーキテクチャに依存するためである。評価基準テーブル１６６は、アーキテクチャ名、Ｌ１命令キャッシュ、命令長、ループ回数、ソースコード行数、中間コード命令数、最内ループフラグ、ユーザ指示フラグ、関数呼び出し数および非パイプライン命令数の項目を有する。
【００７５】
アーキテクチャ名の項目は、プロセッサのアーキテクチャの名称、すなわち、プロセッサの種類を示す。Ｌ１命令キャッシュの項目は、Ｌ１命令キャッシュのサイズを示す。命令長の項目は、オブジェクトコードにおける命令１個当たりのサイズを示す。命令によってサイズが異なる場合、命令長の項目は平均サイズを示す。ここで、係数Ａ＝Ｌ１命令キャッシュ／命令長と定義する。以下では係数Ａを用いて、指標値を評価値に換算する。
【００７６】
ループ回数の項目は、関数呼び出し指標データ１６４および関数指標データ１６５に含まれるループ回数を評価値に換算する換算方法を示す。一例として、ある関数呼び出しのループ回数と当該関数呼び出しによって呼び出される関数のループ回数の合計をＮとすると、当該関数呼び出しの評価値に１０×Ａ×Ｎが加算される。ループ回数が多いほど実行コストが高くインライン展開の効果が大きいため、評価値が高くなる。
【００７７】
ソースコード行数の項目は、関数指標データ１６５に含まれるソースコード行数を評価値に換算する換算方法を示す。一例として、ある関数呼び出しによって呼び出される関数のソースコード行数をＮとすると、当該関数呼び出しの評価値に１０×Ａ×Ｎが加算される。中間コード命令数の項目は、関数指標データ１６５に含まれる中間コード命令数を評価値に換算する換算方法を示す。一例として、ある関数呼び出しによって呼び出される関数の中間コード命令数をＮとすると、当該関数呼び出しの評価値に１００×Ａ−Ｎが加算される。命令数が少ないほど関数呼び出しの相対的なオーバヘッドが大きくなりインライン展開の効果が大きいため、評価値が高くなる。
【００７８】
最内ループフラグの項目は、関数呼び出し指標データ１６４に含まれる最内ループフラグを評価値に換算する換算方法を示す。一例として、ある関数呼び出しの最内ループフラグがＴｒｕｅの場合、当該関数呼び出しの評価値にＡが加算される。最内ループフラグがＦａｌｓｅの場合、当該関数呼び出しの評価値は増加しない。最内ループは最適化の効果が大きいことが多いため、最内ループに属する関数呼び出しの評価値は高くなる。
【００７９】
ユーザ指示フラグの項目は、関数指標データ１６５に含まれるユーザ指示フラグを評価値に換算する換算方法を示す。一例として、ある関数呼び出しによって呼び出される関数のユーザ指示フラグがＴｒｕｅの場合、当該関数呼び出しの評価値に２０×Ａが加算される。ユーザ指示フラグがＦａｌｓｅの場合、当該関数呼び出しの評価値は増加しない。ユーザからの指定がある場合、インライン展開の効果が大きいことが多いためである。
【００８０】
関数呼び出し数の項目は、関数指標データ１６５に含まれる関数呼び出し数を評価値に換算する換算方法を示す。一例として、ある関数呼び出しによって呼び出される関数がもつ他の関数呼び出し（子の関数呼び出し）の数をＮとすると、当該関数呼び出しの評価値からＡ×Ｎが減算される。子の関数呼び出しが多いほどインライン展開を行っても関数呼び出し削減の効果が小さいため、評価値が低くなる。
【００８１】
非パイプライン命令数の項目は、関数呼び出し指標データ１６４および関数指標データ１６５に含まれる非パイプライン命令数を評価値に換算する換算方法を示す。一例として、ある関数呼び出しの非パイプライン命令数と当該関数呼び出しによって呼び出される関数の非パイプライン命令数の合計をＮとすると、当該関数呼び出しの評価値からＡ×Ｎが減算される。非パイプライン命令数が多いほど命令実行の並列化が難しくなり実行効率が低下するおそれがあるため、評価値が低くなる。
【００８２】
図１３は、評価値テーブルの例を示す図である。
解析部１４１は、上記の関数呼び出し指標データ１６４、関数指標データ１６５および評価基準テーブル１６６に基づいて、各関数呼び出しの評価値を算出して評価値テーブル１６７を生成する。評価値テーブル１６７は、制御情報記憶部１４３に記憶される。評価値テーブル１６７は、関数呼び出しＩＤおよび評価値の項目を有する。
【００８３】
関数呼び出しＩＤの項目は、関数呼び出しを識別する。評価値の項目は、当該関数呼び出しについて算出された評価値を示す。解析部１４１は、関数呼び出し＃Ａ〜＃Ｍを評価値の高い順にソートし、評価値の高い方から優先的にインライン展開の候補として選択する。インライン展開しても関数１つ当たりの命令数が閾値を超えない場合、解析部１４１は、選択した関数呼び出しをインライン展開する。例えば、関数呼び出し＃Ａ〜＃Ｍの評価値がそれぞれ、１０，３０，５０，４０，１００，２０，６０，７０，３０，９０，３０，２０，１０と算出されたとする。この場合、解析部１４１は、評価値の最も高い関数呼び出し＃Ｅを最初のインライン展開の候補として選択する。
【００８４】
１つの関数呼び出しがインライン展開されると、関数呼び出しの階層構造が変化する。そこで、解析部１４１は、関数データ１６３を更新する。また、１つの関数呼び出しがインライン展開されると、一部の関数の指標値および一部の他の関数呼び出しの指標値が変化する。そこで、解析部１４１は、関数呼び出し指標データ１６４および関数指標データ１６５を更新し、評価値を再算出する。ただし、インライン展開の影響を受ける関数および関数呼び出しの指標値を更新すればよく、全ての関数および関数呼び出しの指標値を更新しなくてよい。また、更新された指標値の影響を受ける関数呼び出しの評価値を再算出すればよく、全ての評価値を再算出しなくてよい。解析部１４１は、再算出された評価値に基づいて関数呼び出しをソートし、次のインライン展開の候補を選択する。
【００８５】
図１４は、関数データの更新例を示す図である。
レコード１６３ａは、関数＃１１に対応する関数データ１６３のレコードである。レコード１６３ｂは、関数＃８に対応する関数データ１６３のレコードである。関数＃１１から関数＃８を呼び出す関数呼び出し＃Ｅがインライン展開されると、関数＃８の命令が関数＃１１に組み込まれる。関数＃８が有する関数呼び出し＃Ｈ，＃Ｉ，＃Ｊも関数＃１１に組み込まれることになる。そこで、解析部１４１は、関数呼び出し＃Ｅのインライン展開を決定すると、図１４に示すようにレコード１６３ａを更新する。
【００８６】
すなわち、レコード１６３ａの関数ＩＤおよびアドレスは維持される。また、関数＃１１を呼び出す関数呼び出し＃Ｃは変化しないため、レコード１６３ａの呼び出し元の情報は維持される。一方、関数呼び出し＃Ｅはインライン展開によって消滅したため、レコード１６３ａの呼び出し先の情報から関数呼び出し＃Ｅが削除される。また、インライン展開によって関数＃１１は関数＃８の関数呼び出し＃Ｈ，＃Ｉ，＃Ｊを引き継いだため、レコード１６３ａの呼び出し先の情報に関数呼び出し＃Ｈ，＃Ｉ，＃Ｊが追加される。なお、関数＃８の呼び出し元が存在しなくなった場合、レコード１６３ｂを削除してもよい。
【００８７】
図１５は、評価値の再算出例を示す図である。
ここでは、前述の関数呼び出しグラフ４０において、関数呼び出し＃Ｅがインライン展開された場合を考える。関数呼び出し＃Ｅがインライン展開されると、関数＃１１のコードが変化するため、関数＃１１の指標値が変化する。そこで、解析部１４１は、関数指標データ１６５に含まれる関数＃１１のレコードを更新する。また、関数＃１１に組み込まれることで関数呼び出し＃Ｈ，＃Ｉ，＃Ｊの周辺コードが変化するため、関数呼び出し＃Ｈ，＃Ｉ，＃Ｊの指標値が変化する。また、関数呼び出し＃Ｄの周辺コードが変化するため、関数呼び出し＃Ｄの指標値も変化する。そこで、解析部１４１は、関数呼び出し指標データ１６４に含まれる関数呼び出し＃Ｄ，＃Ｈ，＃Ｉ，＃Ｊのレコードを更新する。
【００８８】
関数＃１１の指標値および関数呼び出し＃Ｄ，＃Ｈ，＃Ｉ，＃Ｊの指標値が変化すると、解析部１４１は、その影響を受ける評価値を再算出する。すなわち、関数＃１１の指標値が変化したため、解析部１４１は、関数＃１１を呼び出し先とする関数呼び出し＃Ｃの評価値を再算出する。また、関数呼び出し＃Ｄ，＃Ｈ，＃Ｉ，＃Ｊの指標値が変化したため、解析部１４１は、関数呼び出し＃Ｄ，＃Ｈ，＃Ｉ，＃Ｊの評価値を再算出する。また、関数呼び出し＃Ｅが消滅したため、解析部１４１はその評価値を消去する。関数呼び出し＃Ａ，＃Ｂ，＃Ｆ，＃Ｇ，＃Ｋ，＃Ｌ，＃Ｍについては、関数呼び出し＃Ｅのインライン展開の影響を受けないため、評価値を再算出しなくてよい。
【００８９】
その結果、例えば、関数呼び出し＃Ａ〜＃Ｄ，＃Ｆ〜＃Ｍの評価値がそれぞれ、１０，３０，２０，３０，２０，６０，９０，４０，５０，３０，２０，１０と算出される。解析部１４１は、関数呼び出し＃Ａ〜＃Ｄ，＃Ｆ〜＃Ｍを評価値の高い順にソートし、評価値の最も高い関数呼び出し＃Ｈを次のインライン展開の候補として選択する。
【００９０】
次に、コンパイル装置１００によるコンパイルの手順について説明する。
図１６は、コンパイルの手順例を示すフローチャートである。
（Ｓ１）中間コード生成部１３３は、ソースファイル１２１からソースコードを呼び出し、ソースコードを解析する。ソースコードの解析には、字句解析、構文解析および意味解析が含まれる。そして、中間コード生成部１３３は、ソースコードを中間コードに変換し、中間コードを中間コード記憶部１３４に格納する。
【００９１】
（Ｓ２）解析部１４１は、中間コード記憶部１３４に記憶された中間コードから関数を抽出し、関数を呼び出し元から呼び出し先に向かって（順方向に）走査する。順方向関数走査において、解析部１４１は、関数呼び出し毎に当該関数呼び出しについての指標値を抽出する。順方向関数走査の詳細は後述する。
【００９２】
（Ｓ３）解析部１４１は、ステップＳ２で抽出した関数を呼び出し先から呼び出し元に向かって（ステップＳ２とは逆方向に）走査する。逆方向関数走査において、解析部１４１は、関数毎に当該関数についての指標値を抽出する。また、解析部１４１は、各関数呼び出しについて、当該関数呼び出しの指標値と呼び出し先の関数の指標値から評価値を算出する。逆方向関数走査の詳細は後述する。
【００９３】
（Ｓ４）解析部１４１は、ステップＳ３で算出した評価値に基づいて、インライン展開する関数呼び出しを決定する。最適化実行部１４２は、解析部１４１が決定した関数呼び出しがインライン展開されるように、中間コード記憶部１３４に記憶された中間コードを更新する。インライン展開の詳細は後述する。
【００９４】
（Ｓ５）アセンブリコード生成部１３５は、中間コード記憶部１３４に記憶された最適化後の中間コードをアセンブリコードに変換する。
（Ｓ６）ファイル出力部１３６は、アセンブリコード生成部１３５が生成したアセンブリコードをオブジェクトコードに変換し、オブジェクトファイル１２２に書き込む。
【００９５】
図１７は、順方向関数走査の手順例を示すフローチャートである。
順方向関数走査は、上記のステップＳ２において実行される。
（Ｓ１０）解析部１４１は、中間コードから最初の関数（例えば、メイン関数）を検出し、最初の関数の関数ＩＤをキュー１６１およびスタック１６２に挿入する。
【００９６】
（Ｓ１１）解析部１４１は、キュー１６１が空であるか判断する。キュー１６１が空である場合は順方向関数走査が終了し、空でない場合はステップＳ１２に処理が進む。
（Ｓ１２）解析部１４１は、キュー１６１から関数ＩＤを１つ抽出する。抽出される関数ＩＤは、キュー１６１に記憶されている関数ＩＤのうち最も早く挿入されたものである。図１７において、ここで抽出された関数ＩＤが示す関数を関数Ｆ１と表記する。
【００９７】
（Ｓ１３）解析部１４１は、関数Ｆ１に対応するレコードを生成して関数データ１６３に追加する。生成したレコードの関数ＩＤは、関数Ｆ１に付与した識別情報とする。生成したレコードのアドレスは、中間コードにおける関数Ｆ１の先頭アドレスとする。
【００９８】
（Ｓ１４）解析部１４１は、中間コードを参照して、関数Ｆ１が関数呼び出しを含むか判断する。関数Ｆ１が関数呼び出しを含む場合はステップＳ１５に処理が進み、関数Ｆ１が関数呼び出しを含まない場合はステップＳ１１に処理が進む。前者の場合、図１７において、関数Ｆ１に含まれる関数呼び出しを関数呼び出しＣ１と表記する。なお、関数Ｆ１に複数の関数呼び出しが含まれる場合、関数Ｆ１に含まれる関数呼び出し毎に以下のステップＳ１５〜Ｓ１９の処理が実行される。
【００９９】
（Ｓ１５）解析部１４１は、ステップＳ１３で生成したレコードに、関数呼び出しＣ１の情報を呼び出し先として登録する。すなわち、解析部１４１は、関数呼び出しＣ１の呼び出し先関数のアドレスと、関数呼び出しＣ１に付与した識別情報を登録する。
【０１００】
（Ｓ１６）解析部１４１は、関数呼び出しＣ１についての指標値を抽出し、関数呼び出し指標データ１６４に追加する。関数呼び出し指標抽出の詳細は後述する。
（Ｓ１７）解析部１４１は、関数呼び出しＣ１の呼び出し先関数は検出済であるか、すなわち、呼び出し先関数の関数ＩＤがスタック１６２に存在するか判断する。検出済である場合はステップ１９に処理が進み、未検出である場合はステップＳ１８に処理が進む。図１７において、関数呼び出しＣ１の呼び出し先関数を関数Ｆ２と表記する。
【０１０１】
（Ｓ１８）解析部１４１は、関数Ｆ２の関数ＩＤ（関数呼び出しグラフ４０における子関数の関数ＩＤ）をキュー１６１およびスタック１６２に挿入する。
（Ｓ１９）解析部１４１は、関数Ｆ１のアドレスを、関数Ｆ２の呼び出し元として保存する。関数Ｆ２に対応するレコードが関数データ１６３に存在する場合、解析部１４１は、当該レコードに関数Ｆ１のアドレスを登録する。関数Ｆ２に対応するレコードがまだ関数データ１６３に存在しない場合、解析部１４１は、当該レコードが生成されたときにステップＳ１３において関数Ｆ１のアドレスが登録されるように、関数Ｆ１のアドレスを別途保存しておく。そして、ステップＳ１１に処理が進む。
【０１０２】
図１８は、関数呼び出し指標抽出の手順例を示すフローチャートである。
関数呼び出し指標抽出は、上記のステップＳ１６において実行される。
（Ｓ２０）解析部１４１は、関数呼び出しＣ１（上記のステップＳ１４で関数Ｆ１に含まれていた関数呼び出し）が属するブロックを特定する。ブロックは、ひと纏まりの処理を示す中間コードの単位であり、コンパイル処理の単位である。図１８において、ここで特定されたブロックをブロックＢ１と表記する。
【０１０３】
（Ｓ２１）解析部１４１は、ブロックＢ１がループを含むか判断する。ループを含む場合はステップＳ２２に処理が進み、含まない場合はステップＳ２３に処理が進む。
（Ｓ２２）解析部１４１は、中間コードからループ回数を抽出する。
【０１０４】
（Ｓ２３）解析部１４１は、関数呼び出しＣ１が最内ループの中にあるか判定する。関数呼び出しＣ１がループに属していない場合はＦａｌｓｅと判定する。関数呼び出しＣ１が多重ループでないループ（単一のループ）に属している場合はＴｒｕｅと判定する。ブロックＢ１が多重ループを含み、関数呼び出しＣ１がその最内ループの外にある場合はＦａｌｓｅと判定する。ブロックＢ１が多重ループを含み、関数呼び出しＣ１がその最内ループの中にある場合はＴｒｕｅと判定する。
【０１０５】
（Ｓ２４）解析部１４１は、中間コードにおけるブロックＢ１の命令を１つ選択する。図１８において、ここで選択した命令を命令Ｉ１と表記する。
（Ｓ２５）解析部１４１は、命令Ｉ１がパイプライン化可能であるか判断する。命令Ｉ１がパイプライン化可能か否かは、当該命令を実行するプロセッサのアーキテクチャに依存する。パイプライン化可能な命令の例として、算術演算命令、論理演算命令、メモリアクセス命令などが挙げられる。パイプライン化可能でない命令の例として、ＳＩＭＤ命令などの複合命令が挙げられる。命令Ｉ１がパイプライン化可能である場合はステップＳ２７に処理が進み、パイプライン化可能でない場合はステップＳ２６に処理が進む。
【０１０６】
（Ｓ２６）解析部１４１は、非パイプライン命令数を１だけカウントアップする。
（Ｓ２７）解析部１４１は、ステップＳ２４においてブロックＢ１の全ての命令を選択したか判断する。ブロックＢ１の全ての命令を選択した場合はステップＳ２８に処理が進み、未選択の命令がある場合はステップＳ２４に処理が進む。
【０１０７】
（Ｓ２８）解析部１４１は、関数呼び出しＣ１に対応するレコードを生成する。解析部１４１は、ステップＳ２２で抽出したループ回数と、ステップＳ２３の判定結果を示す最内ループフラグと、ステップＳ２６でカウントした非パイプライン命令数とを、レコードに登録する。解析部１４１は、関数呼び出し指標データ１６４にレコードを追加する。
【０１０８】
図１９は、逆方向関数走査の手順例を示すフローチャートである。
逆方向関数走査は、上記のステップＳ３において実行される。
（Ｓ３０）解析部１４１は、スタック１６２が空であるか判断する。スタック１６２が空である場合は逆方向関数走査が終了し、空でない場合はステップＳ３１に処理が進む。
【０１０９】
（Ｓ３１）解析部１４１は、スタック１６２から関数ＩＤを１つ抽出する。抽出される関数ＩＤは、スタック１６２に記憶されている関数ＩＤのうち最後に挿入されたものである。図１９において、ここで抽出された関数ＩＤが示す関数を関数Ｆ１と表記する。
【０１１０】
（Ｓ３２）解析部１４１は、関数Ｆ１に対応する関数データ１６３のレコードを参照して、関数Ｆ１を呼び出す関数があるか判断する。関数Ｆ１を呼び出す関数がある場合はステップＳ３３に処理が進み、ない場合はステップＳ３０に処理が進む。
【０１１１】
（Ｓ３３）解析部１４１は、関数Ｆ１についての指標値を抽出し、関数指標データ１６５に追加する。関数指標抽出の詳細は後述する。
（Ｓ３４）解析部１４１は、関数Ｆ１に対応する関数データ１６３のレコードを参照して、関数Ｆ１が関数呼び出しを含むか判断する。関数Ｆ１が関数呼び出しを含む場合はステップＳ３５に処理が進み、関数Ｆ１が関数呼び出しを含まない場合はステップＳ３０に処理が進む。前者の場合、図１９において、関数Ｆ１に含まれる関数呼び出しを関数呼び出しＣ１と表記する。なお、関数Ｆ１に複数の関数呼び出しが含まれる場合、関数Ｆ１に含まれる関数呼び出し毎に以下のステップＳ３５〜Ｓ３７の処理が実行される。
【０１１２】
（Ｓ３５）解析部１４１は、関数呼び出し指標データ１６４から関数呼び出しＣ１の指標値を検索する。検索する指標値には、ループ回数、最内ループフラグおよび非パイプライン命令数が含まれる。図１９では、検索された指標値を指標値Ｐ１と表記する。
【０１１３】
（Ｓ３６）解析部１４１は、関数呼び出しＣ１の呼び出し先関数を特定し、関数指標データ１６５から呼び出し先関数の指標値を検索する。検索する指標値には、ループ回数、ソースコード行数、中間コード命令数、ユーザ指示フラグ、関数呼び出し数および非パイプライン命令数が含まれる。図１９では、検索された指標値を指標値Ｐ２と表記する。
【０１１４】
（Ｓ３７）解析部１４１は、検索された指標値Ｐ１，Ｐ２から関数呼び出しＣ１の評価値を算出する。すなわち、解析部１４１は、検索された指標値Ｐ１，Ｐ２を、評価基準テーブル１６６に基づいて評価値に換算する。複数の評価基準テーブルが制御情報記憶部１４３に記憶されている場合、解析部１４１は、ターゲットのプロセッサのアーキテクチャに対応する評価基準テーブルを選択する。解析部１４１は、算出した評価値を評価値テーブル１６７に登録する。そして、ステップＳ３０に処理が進む。
【０１１５】
図２０は、関数指標抽出の手順例を示すフローチャートである。
関数指標抽出は、上記のステップＳ３３において実行される。
（Ｓ４０）解析部１４１は、関数Ｆ１（上記のステップＳ３１の関数）のソースコードを検索する。解析部１４１は、検索したソースコードに含まれる実質的な命令文（セミコロンで終わる行）をカウントすることで、関数Ｆ１のソースコード行数を算出する。
【０１１６】
（Ｓ４１）解析部１４１は、関数Ｆ１に対応する関数データ１６３のレコードを参照して、関数Ｆ１の中間コードを検索する。解析部１４１は、検索した中間コードに含まれる命令をカウントすることで、関数Ｆ１の中間コード命令数を算出する。
【０１１７】
（Ｓ４２）解析部１４１は、関数Ｆ１のソースコードにインライン展開指示文（インライン展開を指示する制御用の付加情報）が付加されていたか判定する。
（Ｓ４３）解析部１４１は、関数Ｆ１がループを含むか判断する。ループを含む場合はステップＳ４４に処理が進み、含まない場合はステップＳ４５に処理が進む。
【０１１８】
（Ｓ４４）解析部１４１は、中間コードからループ回数を抽出する。
（Ｓ４５）解析部１４１は、中間コードにおける関数Ｆ１の命令を１つ選択する。図２０において、ここで選択した命令を命令Ｉ１と表記する。
【０１１９】
（Ｓ４６）解析部１４１は、命令Ｉ１がパイプライン化可能であるか判断する。命令Ｉ１がパイプライン化可能である場合はステップＳ４８に処理が進み、パイプライン化可能でない場合はステップＳ４７に処理が進む。
【０１２０】
（Ｓ４７）解析部１４１は、非パイプライン命令数を１だけカウントアップする。
（Ｓ４８）解析部１４１は、命令Ｉ１が関数呼び出し命令（図１１のｃａｌｌｐｅ命令に相当）であるか判断する。関数呼び出し命令である場合はステップＳ４９に処理が進み、それ以外の場合はステップＳ５０に処理が進む。
【０１２１】
（Ｓ４９）解析部１４１は、関数呼び出し数を１だけカウントアップする。
（Ｓ５０）解析部１４１は、ステップＳ４５において関数Ｆ１の全ての命令を選択したか判断する。関数Ｆ１の全ての命令を選択した場合はステップＳ５１に処理が進み、未選択の命令がある場合はステップＳ４５に処理が進む。
【０１２２】
（Ｓ５１）解析部１４１は、関数Ｆ１に対応するレコードを生成する。解析部１４１は、ステップＳ４４で抽出したループ回数と、ステップＳ４０，Ｓ４１で算出したソースコード行および中間コード命令数と、ステップＳ４２の判定結果を示すユーザ指示フラグとを、レコードに登録する。また、解析部１４１は、ステップＳ４０でカウントした関数呼び出し数と、ステップＳ４７でカウントした非パイプライン命令数とを、レコードに登録する。解析部１４１は、関数指標データ１６５にレコードを追加する。
【０１２３】
図２１は、インライン展開の手順例を示すフローチャートである。
インライン展開は、上記のステップＳ４において実行される。
（Ｓ６０）解析部１４１は、算出した評価値を登録した評価値テーブル１６７に基づいて、関数呼び出しを評価値の高い順にソートする。
【０１２４】
（Ｓ６１）解析部１４１は、未選択の関数呼び出しの中で最も評価値の高い関数呼び出しを選択する。ただし、既にインライン展開された関数呼び出しは除外される。また、選択済であるという状態は、後述するステップＳ６９においてインライン展開されていない関数呼び出しが再ソートされることで取り消される。図２１において、ここで選択された関数呼び出しを関数呼び出しＣ１、関数呼び出しＣ１の呼び出し元関数を関数Ｆ１、関数呼び出しＣ１の呼び出し先関数を関数Ｆ２と表記する。
【０１２５】
（Ｓ６２）解析部１４１は、関数Ｆ１の命令数と関数Ｆ２の命令数の合計が閾値以下であるか判断する。関数Ｆ１，Ｆ２の命令数は、関数Ｆ１，Ｆ２に対応する関数指標データ１６５のレコードを参照することで特定できる。閾値は、例えば、Ｌ１命令キャッシュに格納可能な命令数＝Ｌ１命令キャッシュのサイズ／命令長とする。合計命令数が閾値以下の場合はステップＳ６３に処理が進み、それ以外の場合はステップＳ７０に処理が進む。
【０１２６】
（Ｓ６３）解析部１４１は、関数呼び出しＣ１をインライン展開すると決定する。最適化実行部１４２は、中間コード記憶部１３４に記憶された中間コードに対して、解析部１４１が決定した関数呼び出しＣ１をインライン展開する更新を行う。
【０１２７】
（Ｓ６４）解析部１４１は、関数Ｆ１に対応する関数データ１６３のレコードを更新する。すなわち、解析部１４１は、関数Ｆ１に対応するレコードから関数呼び出しＣ１の情報（アドレスおよび関数呼び出しＩＤ）を削除する。また、解析部１４１は、関数Ｆ１に対応するレコードに、関数Ｆ２が有する関数呼び出しの情報を登録する。
【０１２８】
（Ｓ６５）解析部１４１は、更新後の関数Ｆ１の中間コードに基づいて、関数Ｆ１についての指標値を再抽出する。再抽出する指標値には、ループ回数、ソースコード行数、中間コード命令数、ユーザ指示フラグ、関数コール数および非パイプライン命令数が含まれる。解析部１４１は、関数Ｆ１に対応する関数指標データ１６５のレコードを更新する。
【０１２９】
（Ｓ６６）解析部１４１は、ステップＳ６４で更新した関数Ｆ１に対応する関数データ１６３のレコードを参照して、関数Ｆ１が関数呼び出しを含むか判断する。関数Ｆ１が関数呼び出しを含む場合はステップＳ６７に処理が進み、関数Ｆ１が関数呼び出しを含まない場合はステップＳ６９に処理が進む。前者の場合、図２１において、関数Ｆ１に含まれる関数呼び出しを関数呼び出しＣ２と表記する。なお、関数Ｆ１に複数の関数呼び出しが含まれる場合、関数呼び出し毎に以下のステップＳ６７，Ｓ６８の処理が実行される。
【０１３０】
（Ｓ６７）解析部１４１は、更新後の関数Ｆ１の中間コードに基づいて、関数呼び出しＣ２についての指標値を抽出する。抽出する指標値には、ループ回数、最内フープフラグおよび非パイプライン命令数が含まれる。解析部１４１は、関数呼び出しＣ２に対応する関数呼び出し指標データ１６４のレコードを更新する。
【０１３１】
（Ｓ６８）解析部１４１は、関数呼び出し指標データ１６４から関数呼び出しＣ２の指標値を検索する。また、解析部１４１は、関数指標データ１６５から呼び出し先関数の指標値を検索する。解析部１４１は、検索された指標値と評価基準テーブル１６６とに基づいて、関数呼び出しＣ２の評価値を算出する。解析部１４１は、評価値テーブル１６７に含まれる関数呼び出しＣ２の評価値を更新する。
【０１３２】
（Ｓ６９）解析部１４１は、関数データ１６３を参照して、関数Ｆ１を呼び出し先とする関数呼び出しを検索する。図２１において、ここで検索された関数呼び出しを関数呼び出しＣ３と表記する。解析部１４１は、関数呼び出し指標データ１６４から関数呼び出しＣ３の指標値を検索する。また、解析部１４１は、関数指標データ１６５から関数Ｆ１の指標値を検索する。解析部１４１は、検索された指標値と評価基準テーブル１６６とに基づいて、関数呼び出しＣ３の評価値を再算出する。解析部１４１は、評価値テーブル１６７に含まれる関数呼び出しＣ３の評価値を更新する。そして、解析部１４１は、評価値テーブル１６７に基づいて、関数呼び出しを評価値の高い順に再ソートする。
【０１３３】
（Ｓ７０）解析部１４１は、ステップＳ６１において選択可能な全ての関数呼び出しを選択したか判断する。全ての関数呼び出しを選択した場合はインライン展開が終了し、未選択の関数呼び出しがある場合はステップＳ６１に処理が進む。
【０１３４】
第２の実施の形態のコンパイル装置１００によれば、呼び出し元の関数のコードから、ループ回数、最内ループフラグおよび非パイプライン命令数が抽出される。また、呼び出し先の関数のコードから、ループ回数、ソースコード行、中間コード命令数、ユーザ指示フラグ、関数呼び出し数および非パイプライン命令数が抽出される。そして、これらの指標値に基づいて関数呼び出しの評価値が算出され、評価値の高い関数呼び出しが優先的にインライン展開される。これにより、インライン展開の効果が大きい関数呼び出しから優先的に選択することができ、コードの先頭から順に選択する方法や階層構造の末端から順に選択する方法と比べて、オブジェクトコードの実行効率を向上できる。
【０１３５】
また、関数呼び出し毎に評価値を算出すればよいため、全ての関数呼び出しの組み合わせについて網羅的にインライン展開の効果を評価する方法と比べて、コンパイラ最適化の負荷を低減しコンパイル時間を短縮することができる。また、関数のコードの走査は順方向および逆方向に２回だけ行えばよいため、コンパイラ最適化の中でインライン展開を行うことによる負荷の増大を抑制することができる。
【０１３６】
なお、前述のように、第１の実施の形態の情報処理は、情報処理装置１０にプログラムを実行させることで実現することができる。第２の実施の形態の情報処理は、コンパイル装置１００にプログラムを実行させることで実現することができる。
【０１３７】
プログラムは、コンピュータ読み取り可能な記録媒体（例えば、記録媒体１１３）に記録しておくことができる。記録媒体としては、例えば、磁気ディスク、光ディスク、光磁気ディスク、半導体メモリなどを使用できる。磁気ディスクには、ＦＤおよびＨＤＤが含まれる。光ディスクには、ＣＤ、ＣＤ−Ｒ（Recordable）／ＲＷ（Rewritable）、ＤＶＤおよびＤＶＤ−Ｒ／ＲＷが含まれる。プログラムは、可搬型の記録媒体に記録されて配布されることがある。その場合、可搬型の記録媒体からＨＤＤなどの他の記録媒体（例えば、ＨＤＤ１０３）にプログラムをコピーして（インストールして）実行してもよい。
【符号の説明】
【０１３８】
１０  情報処理装置
１１  記憶部
１２  変換部
１３  コード
１４ａ，１４ｂ，１４ｃ  関数
１５ａ，１５ｂ，１５ｃ  関数呼び出し
１６ａ，１６ｂ  指標値
１７  評価値
【図１】
0006572610.tif 000002
【図２】
0006572610.tif 000003
【図３】
0006572610.tif 000004
【図４】
0006572610.tif 000005
【図５】
0006572610.tif 000006
【図６】
0006572610.tif 000007
【図７】
0006572610.tif 000008
【図８】
0006572610.tif 000009
【図９】
0006572610.tif 000010
【図１０】
0006572610.tif 000011
【図１１】
0006572610.tif 000012
【図１２】
0006572610.tif 000013
【図１３】
0006572610.tif 000014
【図１４】
0006572610.tif 000015
【図１５】
0006572610.tif 000016
【図１６】
0006572610.tif 000017
【図１７】
0006572610.tif 000018
【図１８】
0006572610.tif 000019
【図１９】
0006572610.tif 000020
【図２０】
0006572610.tif 000021
【図２１】
0006572610.tif 000022