(57)【要約】【課題】コンパイルの際の最適化処理を効率化する。【解決手段】コンパイル装置１０は、コード１３（第１のコード）に含まれる複数の命令の間の依存関係を示す依存ツリー１５を生成する。コンパイル装置１０は、依存ツリー１５から、第１の命令と第２の命令と第１および第２の命令の演算結果に依存する第３の命令とを含む部分ツリーを検出し、１命令によって複数の演算を含む複合演算をプロセッサに実行させる複合命令を用いて部分ツリーを書き換える。コンパイル装置１０は、複合命令を含む依存ツリー１５ａに基づいてコード１４（第２のコード）を生成する。【選択図】図１
2015143939.tif 000002
【特許請求の範囲】
【請求項１】
第１のコードを第２のコードに変換するコンパイルプログラムであって、
コンピュータに、
前記第１のコードに含まれる複数の命令の間の依存関係を示す依存ツリーを生成し、
前記依存ツリーから、第１の命令と第２の命令と前記第１および第２の命令の演算結果に依存する第３の命令とを含む部分ツリーを検出し、１命令によって複数の演算を含む複合演算をプロセッサに実行させる複合命令を用いて前記部分ツリーを書き換え、
前記複合命令を含む依存ツリーに基づいて前記第２のコードを生成する、
処理を実行させるコンパイルプログラム。
【請求項２】
前記第２のコードの生成では、前記複合命令を含む依存ツリーと前記複合命令を含む他の依存ツリーとの間の比較に応じて、前記複数の命令の少なくとも一部を、１命令によって２以上の複合演算をプロセッサに並列実行させる並列化命令に変換する、
請求項１記載のコンパイルプログラム。
【請求項３】
前記部分ツリーの書き換えでは、前記第１、第２および第３の命令の演算の種類に応じた変換規則を用いて、前記部分ツリーを２以上の複合命令の組み合わせに変換する、
請求項１または２記載のコンパイルプログラム。
【請求項４】
前記部分ツリーの検出の前に、前記依存ツリーから、前記第１の命令と前記第１の命令の演算結果に依存する第４の命令と前記第４の命令の演算結果に依存する第５の命令とを含み所定条件を満たす命令集合を検出し、前記命令集合を前記部分ツリーに整形する、
請求項１乃至３の何れか一項に記載のコンパイルプログラム。
【請求項５】
第１のコードを第２のコードに変換するコンパイル方法であって、
コンピュータが、
前記第１のコードに含まれる複数の命令の間の依存関係を示す依存ツリーを生成し、
前記依存ツリーから、第１の命令と第２の命令と前記第１および第２の命令の演算結果に依存する第３の命令とを含む部分ツリーを検出し、１命令によって複数の演算を含む複合演算をプロセッサに実行させる複合命令を用いて前記部分ツリーを書き換え、
前記複合命令を含む依存ツリーに基づいて前記第２のコードを生成する、
コンパイル方法。
【請求項６】
第１のコードと前記第１のコードから変換される第２のコードとを記憶する記憶部と、
前記第１のコードに含まれる複数の命令の間の依存関係を示す依存ツリーを生成し、
前記依存ツリーから、第１の命令と第２の命令と前記第１および第２の命令の演算結果に依存する第３の命令とを含む部分ツリーを検出し、１命令によって複数の演算を含む複合演算をプロセッサに実行させる複合命令を用いて前記部分ツリーを書き換え、
前記複合命令を含む依存ツリーに基づいて前記第２のコードを生成する、演算部と、
を有するコンパイル装置。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明はコンパイルプログラム、コンパイル方法およびコンパイル装置に関する。
【背景技術】
【０００２】
コンピュータソフトウェアを開発する場合、開発者はプログラミング言語としてＣ言語などの高級言語を使用することが多い。高級言語を用いて記述されたソースコードは、コンパイラを用いて、ＣＰＵ（Central Processing Unit）などのプロセッサが実行可能なオブジェクトコードに変換することができる。コンパイラの中には、実行効率の高いオブジェクトコードが生成されるように（例えば、実行時間やメモリ使用量が小さくなるように）、いわゆる最適化処理を行うものがある。最適化処理には、加算・減算・乗算・除算・ロード・ストアなどの基本的命令を２以上組み合わせて、同等の演算を実現できる１つの命令に変換し、オブジェクトコードの命令数を削減することが含まれ得る。
【０００３】
プロセッサの中には、ＳＩＭＤ（Single Instruction Multiple Data）命令を実行できるものがある。ＳＩＭＤ命令を受け付けたプロセッサは、異なるデータに対して同じ種類の演算を並列に実行する。例えば、ＳＩＭＤレジスタｓ１にデータＡ１とデータＡ２を格納し、ＳＩＭＤレジスタｓ２にデータＢ１とデータＢ２を格納しておく。ｓ１＋ｓ２というＳＩＭＤ命令が入力されると、プロセッサは、Ａ１＋Ｂ１およびＡ２＋Ｂ２という２つの加算を並列に実行することになる。このプロセッサで実行されるオブジェクトコードを生成する場合、コンパイラは最適化処理として、演算の種類が同じであり並列に実行可能な２以上の命令を組み合わせてＳＩＭＤ命令に変換することがある。
【０００４】
また、プロセッサの中には、ＦＭＡ（Fused Multiply and Add または Floating point Multiply and Add）命令を実行できるものがある。ＦＭＡ命令を受け付けたプロセッサは、データＡ，Ｂ，Ｃに対して、乗算と加算を組み合わせたＡ×Ｂ＋Ｃという演算を実行する。このプロセッサで実行されるオブジェクトコードを生成する場合、コンパイラは最適化処理として、乗算の命令とその乗算結果を参照する加算の命令とを組み合わせてＦＭＡ命令に変換することがある。また、プロセッサの中には、ＳＩＭＤとＦＭＡを組み合わせたＳＩＭＤ−ＦＭＡ命令を実行できるものがある。例えば、ＳＩＭＤレジスタｓ１にデータＡ１とデータＡ２を格納し、ＳＩＭＤレジスタｓ２にデータＢ１とデータＢ２を格納し、ＳＩＭＤレジスタｓ３にデータＣ１とデータＣ２を格納しておく。ｓ１×ｓ２＋ｓ３というＳＩＭＤ−ＦＭＡ命令が入力されると、プロセッサは、Ａ１×Ｂ１＋Ｃ１およびＡ２×Ｂ２＋Ｃ２という２つの演算を並列に実行することになる。
【０００５】
最適化処理を行うにあたり、複数の命令の間の依存関係を示すトレース依存性ツリーを用いるコンピュータシステムが提案されている。このコンピュータシステムは、トレース依存性ツリーの中から演算の種類が同じであり同一のレベルに属する２以上の命令を検索し、検索された２以上の命令を１つのＳＩＭＤ命令にマージする。
【先行技術文献】
【特許文献】
【０００６】
【特許文献１】国際公開第２００６／００７１９３号
【発明の概要】
【発明が解決しようとする課題】
【０００７】
最適化前のコードに含まれる命令の依存関係を示す依存ツリーは、加算・減算・乗算・除算・ロード・ストアなどの様々な種類の基本的命令を含み、その規模も大きくなることがある。このような依存ツリーから直接、ＳＩＭＤ命令などの他の種類の命令に変換可能な２以上の命令の組み合わせを探索しようとすると、計算量が大きくなり最適化処理に長時間を要するという問題がある。例えば、依存ツリーの同じレベルに同じ種類の演算の命令が多数配置されていると、ＳＩＭＤ命令に変換する命令の組み合わせの候補が多くなり、実行効率が高くなる変換パターンを探索する計算量が大きくなってしまう。
【０００８】
１つの側面では、本発明は、コンパイルの際の最適化処理を効率化できるコンパイルプログラム、コンパイル方法およびコンパイル装置を提供することを目的とする。
【課題を解決するための手段】
【０００９】
１つの態様では、第１のコードを第２のコードに変換するコンパイルプログラムが提供される。コンパイルプログラムは、コンピュータに以下の処理を実行させる。第１のコードに含まれる複数の命令の間の依存関係を示す依存ツリーを生成する。依存ツリーから、第１の命令と第２の命令と第１および第２の命令の演算結果に依存する第３の命令とを含む部分ツリーを検出し、１命令によって複数の演算を含む複合演算をプロセッサに実行させる複合命令を用いて部分ツリーを書き換える。複合命令を含む依存ツリーに基づいて第２のコードを生成する。
【００１０】
また、１つの態様では、第１のコードを第２のコードに変換するコンパイル方法が提供される。
また、１つの態様では、記憶部と演算部とを有するコンパイル装置が提供される。記憶部は、第１のコードと第１のコードから変換される第２のコードとを記憶する。演算部は、第１のコードに含まれる複数の命令の間の依存関係を示す依存ツリーを生成する。演算部は、依存ツリーから、第１の命令と第２の命令と第１および第２の命令の演算結果に依存する第３の命令とを含む部分ツリーを検出し、１命令によって複数の演算を含む複合演算をプロセッサに実行させる複合命令を用いて部分ツリーを書き換える。演算部は、複合命令を含む依存ツリーに基づいて第２のコードを生成する。
【発明の効果】
【００１１】
１つの側面では、コンパイルの際の最適化処理を効率化できる。
【図面の簡単な説明】
【００１２】
【図１】第１の実施の形態のコンパイル装置の例を示す図である。
【図２】端末装置が備えるハードウェア例を示すブロック図である。
【図３】端末装置で実行されるソフトウェア例を示すブロック図である。
【図４】ＳＩＭＤ命令とＳＩＭＤレジスタの関係例を示す図である。
【図５】ＳＩＭＤレジスタの実装例を示す図である。
【図６】ＳＩＭＤ化とＦＭＡ化の組み合わせ例を示す図である。
【図７】加算と乗算を含む命令列の例を示す図である。
【図８】命令列に対応する依存ツリーの例を示す図である。
【図９】ＳＩＭＤ−ＦＭＡ化した命令列の例を示す図である。
【図１０】ＦＭＡ正規化した依存ツリーの例を示す図である。
【図１１】ＳＩＭＤ−ＦＭＡ化した命令列の他の例を示す図である。
【図１２】ＳＩＭＤ最適化の手順例を示すフローチャートである。
【図１３】加算と乗算を含む中間コードの例を示す図である。
【図１４】中間コードに対応する依存ツリーの例を示す図である。
【図１５】命令データと依存データの例を示す図である。
【図１６】依存解析の手順例を示すフローチャートである。
【図１７】依存ツリーに対するＦＭＡ正規化の前調整の例を示す図である。
【図１８】ＦＭＡ前調整の手順例を示すフローチャートである。
【図１９】変形前の依存ツリーの例を示す図である。
【図２０】依存ツリーの第１の変形例を示す図である。
【図２１】依存ツリーの第２の変形例を示す図である。
【図２２】依存ツリーの第３の変形例を示す図である。
【図２３】高さ調整の手順例を示すフローチャートである。
【図２４】ノード入替の手順例を示すフローチャートである。
【図２５】変換規則テーブルの例を示す図である。
【図２６】ＦＭＡ正規化パターンの例を示す図である。
【図２７】ＦＭＡ正規化の手順例を示すフローチャートである。
【図２８】依存ツリーの分割例を示す図である。
【図２９】基点データの例を示す図である。
【図３０】基点選択の手順例を示すフローチャートである。
【図３１】レベル算出のサブルーチンの手順例を示すフローチャートである。
【図３２】符号テーブルの例を示す図である。
【図３３】符号化の手順例を示すフローチャートである。
【図３４】エッジデータとパックデータの例を示す図である。
【図３５】候補算出の手順例を示すフローチャートである。
【図３６】エッジデータ設定のサブルーチンの手順例を示すフローチャートである。
【図３７】エッジデータ生成の流れの例を示す図である。
【図３８】パックデータの候補の例を示す図である。
【図３９】符号データからスコアを算出する例を示す図である。
【図４０】ＳＩＭＤ化判定の手順例を示すフローチャートである。
【図４１】パックデータ設定のサブルーチンの手順例を示すフローチャートである。
【図４２】スコア算出の手順例を示すフローチャートである。
【図４３】パックデータ生成の流れの例を示す図である。
【発明を実施するための形態】
【００１３】
以下、本実施の形態を図面を参照して説明する。
［第１の実施の形態］
図１は、第１の実施の形態のコンパイル装置の例を示す図である。
【００１４】
コンパイル装置１０は、Ｃ言語などの高級言語を用いて記述されたソースコードを、プロセッサが実行可能なオブジェクトコードに変換（コンパイル）する。コンパイル装置１０は、コンパイルを行うソフトウェアを実行するコンピュータであってもよい。コンパイル装置１０またはコンパイルを行うソフトウェアを「コンパイラ」と呼んでもよい。また、コンパイル装置１０は、ユーザが操作する端末装置としてのクライアント装置であってもよいし、クライアント装置からアクセスされるサーバ装置であってもよい。また、生成されたオブジェクトコードを実行するプロセッサは、コンパイル装置１０が備えるプロセッサでもよいし、他のコンピュータが備えるプロセッサでもよい。
【００１５】
コンパイル装置１０は、記憶部１１および演算部１２を有する。記憶部１１は、ＲＡＭ（Random Access Memory）などの揮発性の記憶装置でもよいし、ＨＤＤ（Hard Disk Drive）などの不揮発性の記憶装置でもよい。演算部１２は、例えば、プロセッサである。プロセッサは、ＣＰＵやＤＳＰ（Digital Signal Processor）であってもよく、ＡＳＩＣ（Application Specific Integrated Circuit）やＦＰＧＡ（Field Programmable Gate Array）などの特定用途の集積回路を含んでもよい。プロセッサは、ＲＡＭなどの記憶装置（例えば、記憶部１１）に記憶されたプログラムを実行するものであってもよい。また、２以上のプロセッサの集合（マルチプロセッサ）を「プロセッサ」と呼んでもよい。
【００１６】
記憶部１１は、コード１３（第１のコード）およびコード１４（第２のコード）を記憶する。コード１３は、例えば、ソースコード、または、ソースコードから字句解析・構文解析などのフロンドエンド処理を通じて生成される中間コードである。コード１４は、例えば、コード１３に対応するアセンブリコードまたはオブジェクトコードである。
【００１７】
演算部１２は、記憶部１１からコード１３を取得し、コード１３に対して最適化処理を含むバックエンド処理を行い、コード１３に対応するコード１４を生成して記憶部１１に格納する。最適化処理において、演算部１２は、コード１３に含まれる複数の命令の間の依存関係を示す依存ツリー１５を生成する。依存ツリー１５に含まれる命令は、例えば、加算・減算・乗算・除算・ロード・ストアなどの基本的命令である。
【００１８】
依存ツリー１５が生成されると、演算部１２は、依存ツリー１５の中から所定条件を満たす部分ツリーを検出する。所定条件を満たす部分ツリーは、命令＃１（第１の命令）と命令＃２（第２の命令）と命令＃１，＃２の演算結果に依存する命令＃３（第３の命令）とを含む。命令＃１，＃２は、例えば、それぞれ２以上の参照オペランドを有し、加算・減算・乗算・除算などの四則演算を行う命令である。命令＃３は、例えば、命令＃１，＃２の演算結果を参照する参照オペランドを有し、加算・減算・乗算・除算などの四則演算を行う命令である。検出する部分ツリーは、三角形状の部分ツリーと言うこともできる。
【００１９】
部分ツリーが検出されると、演算部１２は、検出した部分ツリーを複合命令を用いて書き換えることで、依存ツリー１５を依存ツリー１５ａに変換する。複合命令は、１命令によって複数の演算（例えば、異なる種類の演算）を含む複合演算をプロセッサに実行させるものである。複合命令の一例として、参照オペランドＡ，Ｂ，Ｃに対して乗算と加算を組み合わせたＡ×Ｂ＋Ｃを算出するＦＭＡ命令が挙げられる。なお、ＦＭＡ命令に類する命令群に、乗算と減算を組み合わせたＡ×Ｂ−Ｃを算出する命令なども含まれ得る。
【００２０】
部分ツリーは、１つの複合命令または２以上の複合命令の組み合わせへと書き換えられる。好ましくは、書き換え後の複合命令の数は、書き換え前の部分ツリーに含まれる命令の数以下になる。また、好ましくは、ルートノードからの深さが同じ命令が少なくなるように部分ツリーが書き換えられる。また、好ましくは、書き換え前の部分ツリーに種類の異なる演算の命令が混在していても、書き換え後は１種類の複合命令によって部分ツリーの演算が表現される。部分ツリーを書き換えるにあたり、演算部１２は、命令＃１，＃２，＃３の演算の種類に応じた変換規則を用いてもよい。
【００２１】
例えば、命令＃１，＃２が乗算であり命令＃３が加算である、すなわち、データＡ，Ｂ，Ｃ，Ｄに対して（Ａ×Ｂ）＋（Ｃ×Ｄ）を算出する部分ツリーを検出したとする。すると、演算部１２は、例えば、Ａ×Ｂ＋（Ｃ×Ｄ＋０）＝ＦＭＡ（Ａ，Ｂ，ＦＭＡ（Ｃ，Ｄ，０））のように２つのＦＭＡ命令を用いて部分ツリーを書き換える。この変換規則によれば、命令数が書き換え前よりも減少し、同じ深さに配置される命令の数も減少し（２つの命令が異なる深さに属し）、命令の種類がＦＭＡ命令のみに統一される。
【００２２】
依存ツリー１５が依存ツリー１５ａに変換されると、演算部１２は、複合命令を含む依存ツリー１５ａに基づいてコード１４を生成する。演算部１２は、命令＃１，＃２，＃３に代えて複合命令を含むコード１４を生成してもよい。また、演算部１２は、依存ツリー１５ａを、依存ツリー１５ａと依存関係がなく複合命令を含む他の依存ツリーと比較し、依存ツリー１５ａに含まれる複合命令と他の依存ツリーに含まれる複合命令とを並列化命令に変換してもよい。この並列化命令は、１命令によって２以上の複合演算をプロセッサに並列実行させるものである。並列化命令は、例えば、ＳＩＭＤ−ＦＭＡ命令である。
【００２３】
例えば、依存ツリー１５の部分ツリーがＦＭＡ（Ａ０，Ｂ０，ＦＭＡ（Ｃ０，Ｄ０，０））と変換され、他の依存ツリーの部分ツリーがＦＭＡ（Ａ１，Ｂ１，ＦＭＡ（Ｃ１，Ｄ１，０））と変換されたとする。すると、演算部１２は、ＦＭＡ（Ｃ０，Ｄ０，０）＝Ｘ０とＦＭＡ（Ｃ１，Ｄ１，０）＝Ｘ１とをＳＩＭＤ−ＦＭＡ命令に変換し、ＦＭＡ（Ａ０，Ｂ０，Ｘ０）とＦＭＡ（Ａ１，Ｂ１，Ｘ１）とをＳＩＭＤ−ＦＭＡ命令に変換する。
【００２４】
第１の実施の形態のコンパイル装置１０によれば、依存ツリー１５から三角形状の命令＃１，＃２，＃３を含む部分ツリーが検出され、この部分ツリーが複合命令を用いて書き換えられる。そして、複合命令を含む依存ツリー１５ａを用いてＦＭＡ化やＳＩＭＤ化などの最適化処理が行われる。これにより、依存ツリー１５ａの同じ深さに配置された命令の数が依存ツリー１５よりも少なくなることが期待でき、命令の組み合わせのパターンが減少し得る。また、依存ツリー１５ａに含まれる命令の多くが同じ種類の複合命令になると期待でき、命令の種類に応じて実行サイクル数が異なる場合であっても命令スケジューリングが容易になる。よって、依存ツリー１５ａを探索することで、依存ツリー１５を探索する場合と比べて最適化処理の計算量を抑制でき処理時間を短縮できる。
【００２５】
また、コード１３に含まれる多くの命令を複合命令に変換することで、コード１４の命令数を削減することができる。また、多くの命令を同じ種類の複合命令に変換することで、それらの同じ種類の複合命令を空き時間が少なくなるように高密度にスケジューリングできる。よって、コード１４の実行効率を向上させることができる。
【００２６】
［第２の実施の形態］
図２は、端末装置が備えるハードウェア例を示すブロック図である。
第２の実施の形態の端末装置１００は、高級言語で記述されたソースコードをコンパイルして、機械可読なオブジェクトコードを生成する。また、端末装置１００は、複数のオブジェクトコードをリンクして、端末装置１００または他のコンピュータに実行させる実行コードを生成する。ただし、第２の実施の形態で説明するコンパイルおよびリンクは、端末装置１００からアクセスされるサーバコンピュータで実行することもできる。
【００２７】
端末装置１００は、ＣＰＵ１０１、ＲＡＭ１０２、ＨＤＤ１０３、画像信号処理部１０４、入力信号処理部１０５、ディスクドライブ１０６および通信インタフェース１０７を有する。ＣＰＵ１０１は、第１の実施の形態の演算部１２の一例であり、ＲＡＭ１０２またはＨＤＤ１０３は、第１の実施の形態の記憶部１１の一例である。
【００２８】
ＣＰＵ１０１は、プログラムの命令を実行する演算器を含むプロセッサである。ＣＰＵ１０１は、ＨＤＤ１０３に記憶されているプログラムやデータの少なくとも一部をＲＡＭ１０２にロードし、プログラムを実行する。なお、ＣＰＵ１０１は複数のプロセッサコアを備えてもよく、端末装置１００は複数のプロセッサを備えてもよく、以下で説明する処理を複数のプロセッサまたはプロセッサコアを用いて並列実行してもよい。
【００２９】
ＲＡＭ１０２は、ＣＰＵ１０１が実行するプログラムや計算に用いられるデータを一時的に記憶する揮発性メモリである。なお、端末装置１００は、ＲＡＭ以外の種類のメモリを備えてもよく、複数のメモリを備えてもよい。
【００３０】
ＨＤＤ１０３は、ＯＳ（Operating System）やファームウェアやアプリケーションソフトウェアなどのソフトウェアのプログラム、および、データを記憶する不揮発性記憶装置である。なお、端末装置１００は、フラッシュメモリやＳＳＤ（Solid State Drive）などの他の種類の記憶装置を備えてもよく、複数の記憶装置を備えてもよい。
【００３１】
画像信号処理部１０４は、ＣＰＵ１０１からの命令に従って、端末装置１００に接続されたディスプレイ２１に画像を出力する。ディスプレイ２１としては、ＣＲＴ（Cathode Ray Tube）ディスプレイや液晶ディスプレイなどを用いることができる。
【００３２】
入力信号処理部１０５は、端末装置１００に接続された入力デバイス２２から入力信号を取得し、ＣＰＵ１０１に通知する。入力デバイス２２としては、マウスやタッチパネルなどのポインティングデバイス、キーボードなどを用いることができる。
【００３３】
ディスクドライブ１０６は、記録媒体２３に記録されたプログラムやデータを読み取る駆動装置である。記録媒体２３として、例えば、フレキシブルディスク（ＦＤ：Flexible Disk）やＨＤＤなどの磁気ディスク、ＣＤ（Compact Disc）やＤＶＤ（Digital Versatile Disc）などの光ディスク、光磁気ディスク（ＭＯ：Magneto-Optical disk）を使用できる。ディスクドライブ１０６は、例えば、ＣＰＵ１０１からの命令に従って、記録媒体２３から読み取ったプログラムやデータをＲＡＭ１０２またはＨＤＤ１０３に格納する。
【００３４】
通信インタフェース１０７は、ネットワーク２４を介して他のコンピュータと通信を行えるインタフェースである。通信インタフェース１０７は、有線網に接続する有線インタフェースでもよいし、無線網に接続する無線インタフェースでもよい。
【００３５】
図３は、端末装置で実行されるソフトウェア例を示すブロック図である。
端末装置１００は、ファイル記憶部１１０、コンパイラ１２０およびリンカ１３０を有する。ファイル記憶部１１０は、例えば、ＲＡＭ１０２またはＨＤＤ１０３に確保した記憶領域として実現することができる。コンパイラ１２０およびリンカ１３０は、例えば、ＣＰＵ１０１が実行するプログラムのモジュールとして実現することができる。
【００３６】
ファイル記憶部１１０は、ソースファイル１１１、オブジェクトファイル１１２および実行ファイル１１３を記憶する。ソースファイル１１１は、高級言語で記述されたソースコードを記憶する。オブジェクトファイル１１２は、ＳＩＭＤ命令やＦＭＡ命令やＳＩＭＤ−ＦＭＡ命令を含み得る機械可読なオブジェクトコードを記憶する。実行ファイル１１３は、ＳＩＭＤ命令やＦＭＡ命令やＳＩＭＤ−ＦＭＡ命令を解釈できるアーキテクチャのプロセッサが実行する実行形式のファイルである。なお、ＣＰＵ１０１は、実行ファイル１１３を実行可能であってもよいし実行可能でなくてもよい。
【００３７】
コンパイラ１２０は、ファイル記憶部１１０からソースファイル１１１を読み出し、ソースコードをオブジェクトコードに変換して、オブジェクトファイル１１２をファイル記憶部１１０に格納する。コンパイラ１２０は、入出力制御部１２１、ファイル入力部１２２、中間コード生成部１２３、中間コード記憶部１２４、最適化部１２５、アセンブリコード生成部１２８およびファイル出力部１２９を有する。
【００３８】
入出力制御部１２１は、ファイルの種類に応じた入出力方法を選択し、ファイル入力部１２２およびファイル出力部１２９を制御する。ファイル入力部１２２は、入出力制御部１２１からの指示に応じて、ソースファイル１１１をオープンし、ソースファイル１１１からソースコードを読み出す。中間コード生成部１２３は、ファイル入力部１２２が読み出したソースコードを解析して、コンパイラ１２０の内部で利用される中間言語で記述された中間コードに変換し、中間コードを中間コード記憶部１２４に格納する。ソースコードの解析には、字句解析、構文解析、意味解析などが含まれる。中間コード記憶部１２４は、例えば、ＲＡＭ１０２に確保された記憶領域であり、中間コードを記憶する。
【００３９】
最適化部１２５は、中間コード記憶部１２４に記憶された中間コードを、実行効率が上がる（例えば、実行速度が上がる）ように最適化する。最適化部１２５は、解析部１２６および最適化実行部１２７を有する。解析部１２６は、中間コードを解析して最適化方法を決定する。解析部１２６が行う最適化方法の決定には、中間コードに含まれる命令の中でＳＩＭＤ命令、ＦＭＡ命令またはＳＩＭＤ−ＦＭＡに変換する命令の組み合わせを決定することを含む。最適化実行部１２７は、解析部１２６が決定した最適化方法に従って中間コードを最適化する。最適化実行部１２７が行う最適化には、中間コードに含まれる命令をＳＩＭＤ命令、ＦＭＡ命令またはＳＩＭＤ−ＦＭＡ命令に変換することを含む。
【００４０】
中間コードに含まれる非ＳＩＭＤ命令をＳＩＭＤ命令に変換することは「ＳＩＭＤ化」と言うことができる。中間コードに含まれる非ＦＭＡ命令をＦＭＡ命令に変換することは「ＦＭＡ化」と言うことができる。ＳＩＭＤ−ＦＭＡ命令に変換することは、ＳＩＭＤ化かつＦＭＡ化を実行することであり、「ＳＩＭＤ−ＦＭＡ化」と言うこともできる。
【００４１】
アセンブリコード生成部１２８は、最適化された中間コードを、低級言語であるアセンブリ言語で記述されたアセンブリコードに変換する。ファイル出力部１２９は、入出力制御部１２１からの指示に応じて、オブジェクトファイル１１２を生成する。そして、ファイル出力部１２９は、アセンブリコード生成部１２８が生成したアセンブリコードをオブジェクトコードに変換し、オブジェクトファイル１１２に書き込む。
【００４２】
リンカ１３０は、ファイル記憶部１１０からオブジェクトファイル１１２を読み出し、オブジェクトコードを解析して、参照されている他のオブジェクトファイルやライブラリを検出する。そして、リンカ１３０は、オブジェクトファイル１１２と、検出した他のオブジェクトファイルやライブラリとをリンクし、実行ファイル１１３を生成する。なお、コンパイラ１２０にリンカ１３０の機能が統合されていてもよい。
【００４３】
次に、ＳＩＭＤ命令やＳＩＭＤ−ＦＭＡ命令の実行方法について説明する。
図４は、ＳＩＭＤ命令とＳＩＭＤレジスタの関係例を示す図である。
ＳＩＭＤ命令を解釈できるプロセッサは、並列に処理するデータを組み合わせて格納するＳＩＭＤレジスタを備える。各ＳＩＭＤレジスタは、プロセッサのアーキテクチャによって決まる並列度（並列に実行できる同じ種類の演算の数）に相当する数のサブレジスタを含む。図４の例は、並列度が２の場合を示している。
【００４４】
例えば、図４に示すように、Ａ＝Ｂ＋Ｃ，Ｅ＝Ｆ＋Ｇという２つの命令を１つのＳＩＭＤ命令ｓ１＝ｓ２＋ｓ３に変換した場合を考える。この場合、ＳＩＭＤレジスタｓ２のサブレジスタ１にデータＢ、ＳＩＭＤレジスタｓ２のサブレジスタ２にデータＦ、ＳＩＭＤレジスタｓ３のサブレジスタ１にデータＣ、ＳＩＭＤレジスタｓ３のサブレジスタ２にデータＧを格納しておく。すると、ＳＩＭＤ命令によって、２つの加算が並列に実行されてデータＡ，Ｅが算出され、ＳＩＭＤレジスタｓ１のサブレジスタ１にデータＡ、ＳＩＭＤレジスタｓ１のサブレジスタ２にデータＥが格納されることになる。
【００４５】
なお、同じ位置にあるサブレジスタの集合をスロットと呼ぶ。すなわち、ＳＩＭＤレジスタｓ１，ｓ２，ｓ３の各サブレジスタ１はスロット１に属し、ＳＩＭＤレジスタｓ１，ｓ２，ｓ３の各サブレジスタ２はスロット２に属する。ＳＩＭＤ命令では、同じスロットに属する複数のサブレジスタを用いて１つの演算が行われることになる。
【００４６】
図５は、ＳＩＭＤレジスタの実装例を示す図である。
プロセッサ内にＳＩＭＤレジスタを実装する方式としては、例えば、図５に示すような（Ａ）分割方式または（Ｂ）結合方式を用いることができる。
【００４７】
分割方式では、１つの大きな物理レジスタを論理的に均等な大きさに分割して、複数のサブレジスタを形成する。並列度２の場合は物理レジスタの記憶領域を２等分し、並列度４の場合は物理レジスタの記憶領域を４等分する。物理レジスタの大きさを一定とすると、並列度が高いほど、各サブレジスタのビット数は小さくなる。分割方式では、ＳＩＭＤレジスタは物理的なレジスタを指し、サブレジスタは論理的なレジスタを指す。
【００４８】
一方、結合方式では、ビット数が等しい複数の物理レジスタをグルーピングし、各物理レジスタをサブレジスタとして用いてＳＩＭＤレジスタを形成する。並列度２の場合は２個の物理レジスタの集合をＳＩＭＤレジスタとして扱い、並列度４の場合は４個の物理レジスタの集合をＳＩＭＤレジスタとして扱う。物理レジスタの大きさを一定とすると、並列度が高いほど、ＳＩＭＤレジスタのビット数は大きくなる。分割方式では、ＳＩＭＤレジスタは論理的なレジスタを指し、サブレジスタは物理的なレジスタを指す。
【００４９】
図６は、ＳＩＭＤ化とＦＭＡ化の組み合わせ例を示す図である。
ＦＭＡ命令を解釈できるプロセッサは、１つのＦＭＡ命令に基づいて積和演算、すなわち、乗算とその乗算結果を用いた加算とを実行する。例えば、Ｘ＝Ｂ×Ｃ，Ａ＝Ｘ＋Ｄという２つの命令を１つのＦＭＡ命令に変換すると、プロセッサは１命令としてＡ＝Ｂ×Ｃ＋Ｄを算出する。また、Ｙ＝Ｆ×Ｇ，Ｅ＝Ｙ＋Ｈという２つの命令を１つのＦＭＡ命令に変換すると、プロセッサは１命令としてＥ＝Ｆ×Ｇ＋Ｈを算出する。
【００５０】
また、ＳＩＭＤ−ＦＭＡ命令を解釈できるプロセッサは、２以上の積和演算を並列に実行することができる。すなわち、２以上のＦＭＡ命令がＳＩＭＤ化される。例えば、ＳＩＭＤ−ＦＭＡ命令を解釈できるプロセッサは、アーキテクチャによって決まる並列度に相当する数の算術演算器を備える。図６の例は、並列度が２の場合を示している。
【００５１】
例えば、図６に示すように、Ａ＝Ｂ×Ｃ＋Ｄ，Ｅ＝Ｆ×Ｇ＋Ｈという２つのＦＭＡ命令を１つのＳＩＭＤ−ＦＭＡ命令ｓ１＝ｓ２×ｓ３＋ｓ４に変換した場合を考える。この場合、ＳＩＭＤレジスタｓ２のサブレジスタ１にデータＢ、ＳＩＭＤレジスタｓ２のサブレジスタ２にデータＦを格納しておく。また、ＳＩＭＤレジスタｓ３のサブレジスタ１にデータＣ、ＳＩＭＤレジスタｓ３のサブレジスタ２にデータＧ、ＳＩＭＤレジスタｓ４のサブレジスタ１にデータＤ、ＳＩＭＤレジスタｓ４のサブレジスタ２にデータＨを格納しておく。すると、ＳＩＭＤ−ＦＭＡ命令によって、２つの積和演算が並列に実行されてデータＡ，Ｅが算出され、ＳＩＭＤレジスタｓ１のサブレジスタ１にデータＡ、ＳＩＭＤレジスタｓ１のサブレジスタ２にデータＥが格納されることになる。
【００５２】
次に、ＳＩＭＤ命令でもＦＭＡ命令でもない基本的命令を組み合わせてＳＩＭＤ−ＦＭＡ命令に変換する（ＳＩＭＤ−ＦＭＡ化する）最適化処理について説明する。
図７は、加算と乗算を含む命令列の例を示す図である。
【００５３】
ここでは理解を容易にするため、ソースコード形式で記述された命令と最適化処理との関係について説明する。コード１４１は、ソースファイル１１１に含まれている。コード１４１の１つの翻訳単位に、図７に示すような命令１〜１４が含まれているとする。翻訳単位は、コンパイラ１２０が一度に処理するコード範囲を示す。コンパイラ１２０による最適化処理は、同じ翻訳単位に属する命令の間で行われる。
【００５４】
命令１〜８，１３，１４では２つのオペランドに対して乗算（×）が行われ、命令９〜１２では２つのオペランドに対して加算（＋）が行われる。命令１〜８は依存関係がなく並列に実行可能であり、命令９〜１２は依存関係がなく並列に実行可能であり、命令１３，１４は依存関係がなく並列に実行可能である。一方、命令９は命令１，５の加算結果を参照し、命令１０は命令２，６の加算結果を参照し、命令１１は命令３，７の加算結果を参照し、命令１２は命令４，８の加算結果を参照する。命令１３は命令９，１１の乗算結果を参照し、命令１４は命令１０，１２の乗算結果を参照する。
【００５５】
図８は、命令列に対応する依存ツリーの例を示す図である。
コンパイラ１２０は、図７に示した命令１〜１４から、命令１〜１４の間の依存関係を示す依存ツリー３１，３２を生成する。依存ツリー３１は、命令１，３，５，７，９，１１，１３を含む。上記のように、命令１，３，５，７，１３は乗算（ＭＵＬＴ）の命令であり、命令９，１１は加算（ＡＤＤ）の命令である。命令９は命令１，５に依存し、命令１１は命令３，７に依存し、命令１３は命令９，１１に依存する。
【００５６】
依存ツリー３２は、命令２，４，６，８，１０，１２，１４を含む。上記のように、命令２，４，６，８，１４は乗算（ＭＵＬＴ）の命令であり、命令１０，１２は加算（ＡＤＤ）の命令である。命令１０は命令２，６に依存し、命令１２は命令４，８に依存し、命令１４は命令１０，１２に依存する。依存ツリー３１に属する命令と依存ツリー３２に属する命令とは、互いに依存関係がなく並列に実行することが可能である。
【００５７】
図９は、ＳＩＭＤ−ＦＭＡ化した命令列の例を示す図である。
コンパイラ１２０は、依存ツリー３１，３２を直接探索して命令１〜１４を最適化する場合、例えば、次のような手順でＳＩＭＤ−ＦＭＡ命令を生成することが考えられる。
【００５８】
まず、コンパイラ１２０は、依存ツリー３１と依存ツリー３２とを比較して、ＳＩＭＤ命令に変換可能な依存ツリー３１の命令と依存ツリー３２の命令との組み合わせのパターンを探索する。ＳＩＭＤ命令に変換可能な命令の組は、演算の種類が同じであり、各依存ツリーのルートからの深さが同じ命令の組である。なお、命令１３，１４の深さは１、命令９〜１２の深さは２、命令１〜８の深さは３である。
【００５９】
ここでは、コンパイラ１２０は、命令１，２を組み合わせて乗算のＳＩＭＤ命令Ａ０｜Ａ１＝Ｂ０｜Ｂ１×Ｃ０｜Ｃ１を生成する。Ａ０｜Ａ１は、同じＳＩＭＤレジスタにデータＡ０とデータＡ１が格納されることを示す。同様に、コンパイラ１２０は、命令３，４を組み合わせて乗算のＳＩＭＤ命令、命令５，６を組み合わせて乗算のＳＩＭＤ命令、命令７，８を組み合わせて乗算のＳＩＭＤ命令を生成する。また、コンパイラ１２０は、命令９，１０を組み合わせて加算のＳＩＭＤ命令、命令１１，１２を組み合わせて加算のＳＩＭＤ命令、命令１３，１４を組み合わせて乗算のＳＩＭＤ命令を生成する。これにより、７個のＳＩＭＤ命令を含むコード１４２が生成される。
【００６０】
次に、コンパイラ１２０は、ＳＩＭＤ−ＦＭＡ命令に変換可能な乗算のＳＩＭＤ命令と加算のＳＩＭＤ命令との組み合わせのパターンを、コード１４２から探索する。ＳＩＭＤ−ＦＭＡ命令に変換可能なＳＩＭＤ命令の組は、一方のＳＩＭＤ命令の乗算結果（乗算のＳＩＭＤ命令が定義したデータ）を他方のＳＩＭＤ命令が参照しているものである。
【００６１】
ここでは、コンパイラ１２０は、コード１４２の１，５番目のＳＩＭＤ命令を組み合わせてＳＩＭＤ−ＦＭＡ命令Ｘ０｜Ｘ１＝Ｂ０｜Ｂ１×Ｃ０｜Ｃ１＋Ａ４｜Ａ５を生成する。また、コンパイラ１２０は、コード１４２の２，６番目のＳＩＭＤ命令を組み合わせてＳＩＭＤ−ＦＭＡ命令Ｘ２｜Ｘ３＝Ｂ２｜Ｂ３×Ｃ２｜Ｃ３＋Ａ６｜Ａ７を生成する。コード１４２の３，４，７番目のＳＩＭＤ命令はそのまま維持される。これにより、２個のＳＩＭＤ−ＦＭＡ命令と３個のＳＩＭＤ命令を含むコード１４３が生成される。
【００６２】
しかし、このようなＳＩＭＤ−ＦＭＡ化には次のような課題がある。
２つの依存ツリーの同じ深さに同じ種類の演算の命令がｎ個ずつ存在するとき、その深さにおける命令の組み合わせパターンはnＰn通りになる。依存ツリー全体の組み合わせパターン数は、各深さの組み合わせパターン数の合計となる。図８に示した依存ツリー３１，３２の場合、深さ３に４個の乗算命令があり、深さ２に２個の加算命令があり、深さ１に１個の乗算命令があるため、4Ｐ4＋2Ｐ2＋1Ｐ1＝２４＋２＋１＝２７通りの組み合わせパターンが存在する。この探索方法は、依存ツリーの規模が大きくなると計算量や使用するメモリ領域が急激に増大し、長時間を要する可能性がある。
【００６３】
また、最適化によって生成されたコード１４３には、ＦＭＡ化された２個の命令（ＳＩＭＤ−ＦＭＡ命令）とＦＭＡ化されていない３個の命令（ＳＩＭＤ命令）とが混在している。コード１４３に含まれる命令のうちＦＭＡ化されている命令の割合（ＦＭＡ化率）は４０％である。これに対し、命令は演算の種類に応じて実行サイクル数（その命令の実行に要するプロセッサのクロック数）が異なる可能性がある。演算の種類のばらつきが大きい、すなわち、命令の実行サイクル数のばらつきが大きいと、空き時間が少なくなるように高密度に命令をスケジューリングすることが容易でなくなる。また、パイプライン処理化などに際して適切なスケジュールを探索するのに時間を要することになる。
【００６４】
そこで、第２の実施の形態では、変形した依存ツリーを用いて最適化処理を行う。
図１０は、ＦＭＡ正規化した依存ツリーの例を示す図である。
コンパイラ１２０は、前述の依存ツリー３１を変形して依存ツリー３３を生成し、前述の依存ツリー３２を変形して依存ツリー３４を生成する。依存ツリー３１，３２に含まれていた命令は、全て１種類の命令（ＦＭＡ命令）に変換されている。
【００６５】
依存ツリー３３は、積和演算（ＦＭＡＤＤ）を示す５個のＦＭＡ命令を含む。命令５はＦＭＡ命令Ａ４＝Ｂ４×Ｃ４＋０に変換され、命令７はＦＭＡ命令Ａ６＝Ｂ６×Ｃ６＋０に変換されている。命令１，９はＦＭＡ命令Ｘ０＝Ｂ０×Ｃ０＋Ａ４に変換され、命令３，１１はＦＭＡ命令Ｘ２＝Ｂ２×Ｃ２＋Ａ６に変換されている。命令１３はＦＭＡ命令Ｚ０＝Ｘ０×Ｘ２＋０に変換されている。依存ツリー３４は、５個のＦＭＡ命令を含む。命令６はＦＭＡ命令Ａ５＝Ｂ５×Ｃ５＋０に変換され、命令８はＦＭＡ命令Ａ７＝Ｂ７×Ｃ７＋０に変換されている。命令２，１０はＦＭＡ命令Ｘ１＝Ｂ１×Ｃ１＋Ａ５に変換され、命令４，１２はＦＭＡ命令Ｘ３＝Ｂ３×Ｃ３＋Ａ７に変換されている。命令１４はＦＭＡ命令Ｚ１＝Ｘ１×Ｘ３＋０に変換されている。
【００６６】
すなわち、乗算の命令１とその乗算結果を参照する加算の命令９の組は、そのまま１つのＦＭＡ命令に変換することができる。命令２，１０の組、命令３，１１の組、命令４，１２の組も、そのまま１つのＦＭＡ命令に変換することができる。一方、余った乗算の命令５については、ダミーの加算として乗算結果に０を加えることで、演算結果を変えないようにＦＭＡ命令に変換できる。命令６〜８，１３，１４も、ダミーの加算を追加することでＦＭＡ命令に変換することができる。なお、余った加算の命令については、ダミーの乗算として一方のオペランドに１をかけることでＦＭＡ命令に変換することができる。
【００６７】
図１１は、ＳＩＭＤ−ＦＭＡ化した命令列の他の例を示す図である。
依存ツリー３１，３２から依存ツリー３３，３４に変換することは、コード１４１から図１１に示すようなコード１４４に変換することを実質的に意味する。コード１４４は、依存ツリー３３，３４に表したように１０個のＦＭＡ命令を含む。コンパイラ１２０は、依存ツリー３３と依存ツリー３４とを比較して、ＳＩＭＤ化可能な依存ツリー３３の命令と依存ツリー３４の命令との組み合わせのパターンを探索する。ＳＩＭＤ化可能な命令の組は、演算の種類および深さが同じ命令の組である。ただし、依存ツリー３３，３４の命令では、演算の種類が積和演算（ＦＭＡＤＤ）に統一されている。
【００６８】
ここでは、コンパイラ１２０は、深さ３のＦＭＡ命令を組み合わせて、ＳＩＭＤ−ＦＭＡ命令Ａ４｜Ａ５＝Ｂ４｜Ｂ５×Ｃ４｜Ｃ５＋０｜０およびＳＩＭＤ−ＦＭＡ命令Ａ６｜Ａ７＝Ｂ６｜Ｂ７×Ｃ６｜Ｃ７＋０｜０を生成する。また、コンパイラ１２０は、深さ２のＦＭＡ命令を組み合わせて、ＳＩＭＤ−ＦＭＡ命令Ｘ０｜Ｘ１＝Ｂ０｜Ｂ１×Ｃ０｜Ｃ１＋Ａ４｜Ａ５およびＳＩＭＤ−ＦＭＡ命令Ｘ２｜Ｘ３＝Ｂ２｜Ｂ３×Ｃ２｜Ｃ３＋Ａ６｜Ａ７を生成する。また、コンパイラ１２０は、深さ１のＦＭＡ命令を組み合わせて、ＳＩＭＤ−ＦＭＡ命令Ｚ０｜Ｚ１＝Ｘ０｜Ｘ１×Ｘ２｜Ｘ３＋０｜０を生成する。これにより、５個のＳＩＭＤ−ＦＭＡ命令を含むコード１４５が生成される。
【００６９】
変形した依存ツリー３３，３４を用いて最適化処理を行う場合、深さ３に２個のＦＭＡ命令があり、深さ２に２個のＦＭＡ命令があり、深さ１に１個のＦＭＡ命令があるため、2Ｐ2＋2Ｐ2＋1Ｐ1＝２＋２＋１＝５通りの組み合わせパターンが存在する。よって、変形前の依存ツリー３１，３２を用いる場合と比べて計算量や使用するメモリ領域が低減され、コンパイラ１２０が高速に最適化処理を行うことができる。
【００７０】
また、最適化によって生成されたコード１４５には、５個のＳＩＭＤ−ＦＭＡ命令が含まれ、他の種類の演算を行う命令は含まれない。コード１４５のＦＭＡ化率は１００％である。よって、演算の種類に応じて実行サイクル数が異なる場合であっても、命令間の実行サイクル数のばらつきは小さくなり、空き時間が少なくなるように高密度に命令をスケジューリングすることが容易となる。また、命令のスケジューリングが簡潔になり、適切なスケジュールを探索するのに要する時間を短縮できる。
【００７１】
次に、コンパイラ１２０によるＳＩＭＤ最適化の手順の一例を説明する。
図１２は、ＳＩＭＤ最適化の手順例を示すフローチャートである。
（Ｓ１）解析部１２６は、中間コード記憶部１２４から１つの翻訳単位の中間コードを読み出し、読み出した中間コードに含まれる命令の間の依存関係を解析する。そして、解析部１２６は、命令間の依存関係を示す複数の依存ツリーを生成する。
【００７２】
（Ｓ２）解析部１２６は、ステップＳ１で生成した依存ツリーの少なくとも１つを、命令の組み合わせパターンの探索が容易になるように変形する。ステップＳ２は、以下のステップＳ２ａ，Ｓ２ｂ，Ｓ２ｃ，Ｓ２ｄを含む。
【００７３】
（２ａ）解析部１２６は、依存ツリーそれぞれに対して、後述するステップＳ３で行うＦＭＡ正規化の前調整を行う。ＦＭＡ正規化の前調整では、解析部１２６は、ステップＳ３においてＦＭＡ命令を用いて書き換え可能な部分ツリーを多く検出できるように、演算の意味を変えない範囲で依存ツリーを変形する。（Ｓ２ｂ）解析部１２６は、少なくとも１つの依存ツリーに疑似命令を挿入することで、複数の依存ツリーの高さが同じになるように調整する。（Ｓ２ｃ）解析部１２６は、依存ツリー毎に、演算の種類に応じて同じ深さにある命令をソートする。（Ｓ２ｄ）解析部１２６は、依存ツリー毎に、読み込むデータの変数名に応じて同じ深さにあるロード命令をソートする。
【００７４】
（Ｓ３）解析部１２６は、各依存ツリーに対してＦＭＡ正規化を行う。ＦＭＡ正規化では、解析部１２６は、ＦＭＡの形状になっている２つの命令（乗算の命令とその乗算結果を参照する加算の命令）を依存ツリーから検出し、検出した２つの命令を１つのＦＭＡ命令に書き換える。また、解析部１２６は、２以上のＦＭＡ命令の組み合わせとして表現できる部分ツリー（後述する三角の部分ツリー）を依存ツリーから検出し、変換規則を適用して、検出した部分ツリーを２以上のＦＭＡ命令を用いて書き換える。
【００７５】
（Ｓ４）解析部１２６は、依存ツリー同士の比較を容易にするため、依存ツリーの中から１またはそれ以上の基点となる命令を選択し、選択した基点がルートノードになるように依存ツリーを分割する（レベル管理）。第２の実施の形態では、解析部１２６は、ＲＡＭにデータを書き込むストア命令を基点の命令として用いる。
【００７６】
（Ｓ５）解析部１２６は、依存ツリー間での命令の比較を効率的に行えるように、各依存ツリーを符号化する。すなわち、解析部１２６は、依存ツリー毎に、演算の種類を示す符号を当該依存ツリーの構造に従って並べた符号データを生成する。
【００７７】
（Ｓ６）解析部１２６は、依存ツリーの組の候補を全通り算出する。１つの組に属する依存ツリーの数は、ＳＩＭＤの並列度に一致させる。例えば、並列度が２である場合、解析部１２６は、所定の条件（例えば、基点のレベルが同じである、互いに依存関係がないなどの条件）を満たす２つの依存ツリーの組を全通り算出する。なお、ステップＳ５の処理とステップＳ６の処理は、逆順で行ってもよいし並列に行ってもよい。
【００７８】
（Ｓ７）解析部１２６は、ステップＳ６で算出した依存ツリーの組の候補について、ステップＳ５で生成した符号データ同士を比較して、命令の一致度を示すスコアを算出する（スコアリング）。スコアリングでは、複数の依存ツリーの間の対応するノードに、同じ種類の演算を行う命令が存在するか評価される。解析部１２６は、算出したスコアに基づいて依存ツリーの組を決定し、組み合わせた複数の依存ツリーの対応するノードにある命令同士を組み合わせてＳＩＭＤ化することを決定する。
【００７９】
以下では、図１２に示した処理手順の実装例について説明する。まず、中間コードから命令間の依存関係を解析して依存ツリーを生成する手順について説明する。
図１３は、加算と乗算を含む中間コードの例を示す図である。
【００８０】
中間コード１４６は、中間コード記憶部１２４に記憶される。中間コード１４６の１つの翻訳単位に、命令１〜１３が含まれている。命令１，２，４，６，７，９はロード命令（ＬＯＡＤ）であり、命令１２，１３はストア命令（ＳＴＯＲＥ）である。命令３，８は乗算命令（ＭＵＬＴ）であり、命令５，１０，１１は加算命令（ＡＤＤ）である。
【００８１】
命令３は命令１，２でロードされたデータを参照し、命令５は命令３で算出されたデータと命令４でロードされたデータを参照し、命令８は命令６，７でロードされたデータを参照している。命令１０は命令８で算出されたデータと命令９でロードされたデータを参照し、命令１１は命令５，１０で算出されたデータを参照している。命令１２は命令１１で算出されたデータを参照している。命令１３は命令１〜１２でロードまたは算出されたデータの何れも参照していない。なお、図１３に記載したＲ０１〜Ｒ１２は、論理的なレジスタを示す。ｍｅｍ０１〜ｍｅｍ０８は、ＲＡＭ上の論理的な記憶領域を示す。
【００８２】
図１４は、中間コードに対応する依存ツリーの例を示す図である。
依存ツリー４１は、図１３に示した命令１〜１２から生成される。命令１〜１２と依存関係がない命令１３は、依存ツリー４１に属さない。依存ツリー４１では、一方の命令が他方の命令に依存しているとき、一方の命令が親ノードに対応付けられ、他方の命令が子ノードに対応付けられる。依存ツリー４１のリーフノードからルートノードに向かって演算が進行することになる。図１４に示すように、命令３は命令１，２に依存し、命令５は命令３，４に依存し、命令８は命令６，７に依存し、命令１０は命令８，９に依存し、命令１１は命令５，１０に依存し、命令１２は命令１１に依存している。
【００８３】
図１５は、命令データと依存データの例を示す図である。
依存関係の解析を通じて、命令データ１５１および依存データ１５２が生成される。
命令データ１５１は、命令毎に、命令番号、解析済フラグ、命令名、定義オペランドおよび参照オペランドの項目を含む。命令番号は、各命令を識別するための番号である。解析済フラグは、依存関係の解析などの処理の際に、その命令が解析済か否かを識別するために利用されるフラグである。解析済フラグの初期値はＯＦＦに設定される。命令名は、演算の種類を示す名称（ＡＤＤ，ＳＵＢ，ＭＵＬＴ，ＤＩＶ，ＬＯＡＤ，ＳＴＯＲＥ、ＦＭＡＤＤなど）である。定義オペランドの項目には、中間コード１４６で使用されている論理的なレジスタまたはＲＡＭの記憶領域を示す識別子であって、データの格納先を示す識別子が設定される。参照オペランドの項目には、参照するデータが格納されている１または２以上の論理的なレジスタまたはＲＡＭの記憶領域を示す識別子が設定される。
【００８４】
依存データ１５２は、定義命令の命令番号と参照命令の命令番号の組を１つ以上含む。定義命令は、定義オペランドであるレジスタまたはＲＡＭ領域が、他の命令によって参照される命令である。参照命令は、他の命令が定義オペランドとして定義したレジスタまたはＲＡＭの記憶領域を、参照オペランドとして参照している命令である。
【００８５】
図１６は、依存解析の手順例を示すフローチャートである。
このフローチャートが示す処理は、前述のステップＳ１において実行される。
（Ｓ１１１）解析部１２６は、翻訳単位に含まれる命令を、先頭から優先的に１つ選択する。（Ｓ１１２）解析部１２６は、選択した命令から命令名、定義オペランドおよび参照オペランドを抽出し、命令番号を付与して命令データ１５１にその命令を登録する。（Ｓ１１３）解析部１２６は、ステップＳ１１１で翻訳単位の末尾まで全ての命令を選択したか判断する。全て選択した場合は処理をステップＳ１１４に進め、未選択の命令がある場合は処理をステップＳ１１１に進める。
【００８６】
（Ｓ１１４）解析部１２６は、翻訳単位に含まれる命令を、末尾から優先的に１つ選択する。（Ｓ１１５）解析部１２６は、選択した命令が依存ツリーに含めるべき命令か判断する。条件を満たす場合は処理をステップＳ１１６に進め、条件を満たさない場合は処理をステップＳ１２３に進める。（Ｓ１１６）解析部１２６は、選択した命令の解析済フラグがＯＮであるか（解析済であるか）判断する。ＯＮの場合は処理をステップＳ１２３に進め、ＯＦＦの場合は処理をステップＳ１１７に進める。
【００８７】
（Ｓ１１７）解析部１２６は、ステップＳ１１４で選択した命令の参照オペランドを１つ選択する。（Ｓ１１８）解析部１２６は、翻訳単位から、選択した参照オペランドに対応する定義オペランドをもつ命令（定義命令）を検索する。（Ｓ１１９）解析部１２６は、検索した定義命令が、現在の翻訳単位の依存ツリーに属するべきものか（例えば、他の翻訳単位の命令でないか）判断する。条件を満たす場合は処理をステップＳ１２０に進め、条件を満たさない場合は処理をステップＳ１２１に進める。（Ｓ１２０）解析部１２６は、ステップＳ１１８で検索した定義命令からステップＳ１１４で選択した命令（参照命令）への依存関係を、依存データ１５２に登録する。
【００８８】
（Ｓ１２１）解析部１２６は、ステップＳ１１７で、選択した命令に含まれる全ての参照オペランドを選択したか判断する。全て選択した場合は処理をステップＳ１２２に進め、未選択の参照オペランドがある場合は処理をステップＳ１１７に進める。（Ｓ１２２）解析部１２６は、ステップＳ１１４で選択した命令の解析済フラグをＯＮに設定する。（Ｓ１２３）解析部１２６は、ステップＳ１１４で翻訳単位の先頭まで全ての命令を選択したか判断する。全て選択した場合は処理を終了し、未選択の命令がある場合は処理をステップＳ１１４に進める。
【００８９】
次に、ＦＭＡ正規化の前調整による依存ツリーの変形について説明する。
図１７は、依存ツリーに対するＦＭＡ正規化の前調整の例を示す図である。
解析部１２６は、三角の部分ツリーが多く検出されるように前調整を行う。
【００９０】
ここでは、図１７に示す命令１〜７を含む依存ツリー４２を考える。命令１〜４はロード命令であり、命令５は加算命令であり、命令６，７は乗算命令である。命令５は命令１，２に依存し、命令６は命令３，５に依存し、命令７は命令４，６に依存する。依存ツリー４２は、演算の実質的な意味を変えず依存ツリー４３のように変形することができる。依存ツリー４３は、命令１〜５，６ａ，７ａを含む。命令６ａ，７ａは乗算命令である。命令７ａは命令３，４に依存し、命令６ａは命令５，７ａに依存する。
【００９１】
依存ツリー４２は、命令７を命令６と命令３の間に移動し、命令７を命令３，４に依存させ、命令６を命令５，７に依存させることで、依存ツリー４３に変形することができる。依存ツリー４２は、命令５の加算結果に命令３でロードされた値をかけ、その乗算結果に対して更に命令４でロードされた値をかけることを示すものである。これに対し、依存ツリー４３は、命令３でロードされた値と命令４でロードされた値をかけ、その乗算結果に対して命令５の加算結果をかけることを示すものである。乗算には結合則が成立するため、依存ツリー４２と依存ツリー４３の最終的な演算結果は一致する。
【００９２】
依存ツリーを変形するにあたり、解析部１２６は、次の条件を満たす第１・第２・第３の命令を依存ツリーから検出する。第１の命令は、乗算命令または加算命令であり、２つの子命令（第１の命令から見た定義命令）のうちの一方の子命令としてロード命令などの非演算命令に依存し、他方の子命令として第２の命令に依存する。第２の命令は、第１の命令と演算の種類が同じ（乗算または加算）であり、２つの子命令（第２の命令から見た定義命令）のうちの一方の子命令として非演算命令に依存し、他方の子命令として第３の命令に依存する。第３の命令は、乗算命令または加算命令である。
【００９３】
上記の条件を満たす第１・第２・第３の命令が検出されると、解析部１２６は、第１の命令を、第２の命令と第２の命令の子命令である非演算命令との間に移動する。第２の命令の子命令である非演算命令は、第１の命令に依存させる。これにより、第１・第２・第３の命令を含む三角形状の部分ツリーを形成することができる。なお、変形後の第２の命令は部分ツリーの「頂点」、第１・第３の命令は「依存点」と言うこともできる。
【００９４】
図１８は、ＦＭＡ前調整の手順例を示すフローチャートである。
このフローチャートが示す処理は、前述のステップＳ２ａにおいて実行される。
（Ｓ１３１）解析部１２６は、依存ツリーのルートノードに近い命令から優先的に、乗算命令または加算命令である命令Ｍ（第１の命令）を１つ選択する。（Ｓ１３２）解析部１２６は、第１の命令から見て子ノードに相当する２つの子命令のうち、一方（第２の命令）のみが乗算命令や加算命令などの演算命令であり、他方がロード命令などの非演算命令であるか判断する。一方の子命令のみ演算命令である場合は処理をステップＳ１３３に進め、それ以外の場合は処理をステップＳ１３６に進める。
【００９５】
（Ｓ１３３）解析部１２６は、第２の命令の演算が第１の命令と同じ種類であるか判断する。第１・第２の命令の演算の種類が同じ場合は処理をステップＳ１３４に進め、演算の種類が異なる場合は処理をステップＳ１３６に進める。（Ｓ１３４）解析部１２６は、第２の命令から見て子ノードに相当する２つの子命令（第１の命令から見たときの孫命令）のうち、一方がロード命令などの非演算命令であり、他方（第３の命令）が乗算命令または加算命令であるか判断する。この条件を満たす場合は処理をステップＳ１３５に進め、それ以外の場合は処理をステップＳ１３６に進める。
【００９６】
（Ｓ１３５）解析部１２６は、第２の命令とその子命令である非演算命令との間に、ステップＳ１３１で選択した第１の命令を移動する。（Ｓ１３６）解析部１２６は、ステップＳ１３１で依存ツリーに含まれる全ての命令を選択したか判断する。全ての命令を選択した場合は処理を終了し、未選択の命令がある場合は処理をステップＳ１３１に進める。
【００９７】
次に、他の依存ツリーの変形について説明する。
図１９は、変形前の依存ツリーの例を示す図である。
依存ツリー４４，４５は、中間コードに含まれる命令間の依存関係を示す。ここでは、コンパイラ１２０が１度に処理するコード範囲（翻訳単位）に、命令１〜１６が含まれているとする。命令１，２，４，５，８，１０，１１，１３，１４はロード命令であり、命令３，７，１５は乗算命令であり、命令６，９，１２，１６は加算命令である。命令１はデータＡ（Ｉ）、命令２はデータＣ（Ｉ）、命令４はデータＢ（Ｉ）、命令５はデータＤ（Ｉ）をロードする。命令１０はデータＤ（Ｉ＋１）、命令１１はデータＢ（Ｉ＋１）、命令１３はデータＣ（Ｉ＋１）、命令１４はデータＡ（Ｉ＋１）をロードする。データＡ（Ｉ）とＡ（Ｉ＋１）、データＢ（Ｉ）とＢ（Ｉ＋１）、データＣ（Ｉ）とＣ（Ｉ＋１）、データＤ（Ｉ）とＤ（Ｉ＋１）は、ＲＡＭ上に隣接して配置される可能性が高い。
【００９８】
命令３は命令１，２に依存し、命令６は命令４，５に依存し、命令７は命令３，６に依存し、命令９は命令７，８に依存する。命令１２は命令１０，１１に依存し、命令１５は命令１３，１４に依存し、命令１６は命令１２，１５に依存する。依存ツリー４４は命令１〜９を含み、依存ツリー４４は命令１０〜１６を含む。すなわち、命令１〜９の集合と命令１０〜１６の集合とは、互いに依存関係がなく並列に実行できる。
【００９９】
解析部１２６は、依存ツリー４４の命令と依存ツリー４５の命令を組み合わせてＳＩＭＤ化することが考えられる。しかし、依存ツリー４４，４５は形状が異なるため、そのままではＳＩＭＤ化できる命令組を探索することが容易でない。例えば、深さが同じ命令の間で演算の種類が同じ命令を探すだけでは、深さ２にある命令７，１５の組と深さ１にある命令９，１６の組しか検出されない。そこで、解析部１２６は、依存ツリー４４，４５の形状が互いに近くなるように依存ツリー４４，４５を変形する。
【０１００】
図２０は、依存ツリーの第１の変形例を示す図である。
依存ツリー４４の高さ（ルートノードから最も深いリーフノードまでに並んだノードの数）は４である一方、依存ツリー４５の高さは３である。そこで、解析部１２６は、高さの小さい依存ツリー４５を、疑似命令を挿入することで依存ツリー４６に変形する。
【０１０１】
疑似命令は、演算前のデータと演算後のデータが同じになる命令である。疑似加算命令（疑似ＡＤＤ）は入力値に０を加えるものであり、疑似減算命令（疑似ＳＵＢ）は入力値から０を引くものであり、疑似乗算命令（疑似ＭＵＬＴ）は入力値に１をかけるものであり、疑似除算命令（疑似ＤＩＶ）は入力値を１で割るものである。疑似ロード命令はレジスタのデータが変化しないように同じデータを再度読み込むものであり、疑似ストア命令はＲＡＭのデータが変化しないように同じデータをＲＡＭに上書きするものである。
【０１０２】
依存ツリー４６は、命令１０〜１６を含む依存ツリー４５に対して、命令１７，１８を挿入したものである。命令１７は、依存ツリー４４の命令９に対応するように挿入された疑似加算命令である。命令１８は、依存ツリー４４の命令８に対応するように挿入された疑似ロード命令である。命令１７は命令１６，１８に依存する。命令１７，１８が挿入されることで、依存ツリー４６の高さは依存ツリー４４と同じになっている。解析部１２６は、依存ツリー４４と高さが同じになり、かつ、できる限り同じ深さに同じ種類の演算を行う命令がくるように、依存ツリー４５に疑似命令を挿入する。
【０１０３】
図２１は、依存ツリーの第２の変形例を示す図である。
解析部１２６は、依存ツリー４４，４６の対応する位置に、同じ種類の演算を行う命令が存在する確率を高くするため、順序を入れ替え可能な命令を演算の種類に応じてソートする。演算順序の入れ替えは、依存ツリー４４，４６それぞれに対して行う。図２１は、依存ツリー４６を、演算順序を入れ替えて依存ツリー４７に変形する例を示している。
【０１０４】
命令をソートするにあたり、解析部１２６は、演算の優先順位を予め定めておく。例えば、四則演算については、乗算（ＭＵＬＴ）＞除算（ＤＩＶ）＞加算（ＡＤＤ）＞減算（ＳＵＢ）のように優先順位を定める。この場合、命令１６と依存関係のある命令１２，１５が入れ替え可能な命令の組として検出され、演算の優先順位に従って、乗算命令である命令１５が加算命令である命令１２よりも依存ツリー上で左側に移動する。一方、上記の演算の優先順位を採用した場合、依存ツリー４４は変形しなくてよい。
【０１０５】
図２２は、依存ツリーの第３の変形例を示す図である。
解析部１２６は、ロード命令の組をＳＩＭＤ化するとき、複数のロード命令ができる限りＲＡＭの近い記憶領域にアクセスするよう、変数名に応じてロード命令をソートする。変数名の入れ替えは、依存ツリー４４，４７それぞれに対して行う。図２２は、依存ツリー４７を、変数名を入れ替えて依存ツリー４８に変形する例を示している。
【０１０６】
例えば、変数名の優先順位をＡ＞Ｂ＞Ｃ＞Ｄのように定める。この場合、命令１２と依存関係のある命令１０，１１が入れ替え可能なロード命令の組として検出され、変数名に従って、命令１１が命令１０よりも依存ツリー上で左側に移動する。また、命令１５と依存関係のある命令１３，１４が入れ替え可能なロード命令の組として検出され、変数名に従って、命令１４が命令１３よりも依存ツリー上で左側に移動する。変数名の情報は、中間コード記憶部１２４に記憶された中間コードに含まれている。
【０１０７】
なお、図２２では命令の内容と共に命令番号も移動しているが、後述するように、解析部１２６の内部処理では命令の内容のみを入れ替えて命令番号は入れ替えない。このため、例えば、命令番号１２の命令が、ＡＤＤ命令からＭＵＬＴ命令に変換されることになる。同様に、図２２ではロードするデータの変数名と共に命令番号も移動しているが、解析部１２６の内部処理では変数名のみを入れ替えて命令番号は入れ替えない。このため、例えば、命令番号１３の命令でロードされるデータの変数名が、Ｃ（Ｉ＋１）からＡ（Ｉ＋１）に変換されることになる。また、図２１で説明した演算順序の入れ替えと図２２で説明した変数名の入れ替えは、何れを先に実行してもよい。
【０１０８】
図２３は、高さ調整の手順例を示すフローチャートである。
このフローチャートが示す処理は、前述のステップＳ２ｂにおいて実行される。この処理は、複数の依存ツリーのうち最も高いもの以外の各依存ツリーに対して行われる。
【０１０９】
（Ｓ１４１）解析部１２６は、依存ツリーの中で疑似命令を挿入できる位置を列挙する。例えば、依存ツリー４５の場合、７つの位置、すなわち、命令１０〜１６に対応する各ノードから１つ上位の（深さが小さくなる方向の）位置が選択される。（Ｓ１４２）解析部１２６は、ステップＳ１４１で列挙された位置のべき集合（位置の組み合わせのパターン全て）を算出する。例えば、７つの位置が列挙された場合、Φ（空集合），｛位置１｝，｛位置１，２｝，｛位置１，２，３｝，・・・，｛位置６｝，｛位置６，７｝，｛位置７｝のように、位置の組み合わせを全パターン算出する。
【０１１０】
（Ｓ１４３）解析部１２６は、ステップＳ１４２で算出された位置の組み合わせのうち１つを選択する。（Ｓ１４４）解析部１２６は、選択した組み合わせの各位置に疑似命令を挿入することで、依存ツリーの高さが、対比する他の依存ツリーと同じになるか判断する。高さが同じになる場合は処理をステップＳ１４５に進める。高さが同じにならない場合は処理をステップＳ１４７に進める。
【０１１１】
（Ｓ１４５）解析部１２６は、ステップＳ１４３で選択した組み合わせの各位置に疑似命令を挿入する。このとき、解析部１２６は、疑似命令を挿入する依存ツリーと、対比する他の依存ツリーとの間で、同じ深さにできる限り同じ種類の演算を指定した命令がくるように、疑似命令の演算の種類を選択する。（Ｓ１４６）解析部１２６は、疑似命令を挿入した依存ツリーと他の依存ツリーとの間で、同じ深さにある命令を比較してＳＩＭＤ化可能な命令組を検出し、疑似命令を挿入した依存ツリーのＳＩＭＤ化率（または、ＳＩＭＤ化される命令の数（ＳＩＭＤ化数））を算出する。
【０１１２】
（Ｓ１４７）解析部１２６は、ステップＳ１４３で全ての組み合わせを選択したか判断する。全て選択した場合は処理をステップＳ１４８に進める。未選択の組み合わせがある場合は、疑似命令の挿入を取り消して依存ツリーを元に戻し、処理をステップＳ１４３に進める。（Ｓ１４８）解析部１２６は、ステップＳ１４６で算出されたＳＩＭＤ化率（またはＳＩＭＤ化数）が最大になる位置の組み合わせを判定し、判定された組み合わせに従って依存ツリーに疑似命令を挿入する。
【０１１３】
図２４は、ノード入替の手順例を示すフローチャートである。
このフローチャートが示す処理は、前述のステップＳ２ｃ，Ｓ２ｄにおいて実行される。この処理は、図２３の処理の後に各依存ツリーに対して行われる。
【０１１４】
（Ｓ１５１）解析部１２６は、依存ツリーのうちルートノードに近い命令から優先的に、命令を１つ選択する。（Ｓ１５２）解析部１２６は、選択した命令から見て子ノードに相当する命令が２つ以上存在するか判断する。存在する場合は処理をステップＳ１５３に進め、存在しない場合は処理をステップＳ１５８に進める。
【０１１５】
（Ｓ１５３）解析部１２６は、依存ツリーの左側から順に、子ノードに相当する命令の命令番号を、ＲＡＭ１０２に確保した記憶領域であるスタックＡに格納する。（Ｓ１５４）解析部１２６は、命令番号に対応する順序で、子ノードに相当する命令のデータを、ＲＡＭ１０２に確保した他の記憶領域であるスタックＢに格納する。例えば、ステップＳ１５１で依存ツリー４６の命令１６を選択した場合、命令番号１２，１５がスタックＡに格納され、命令１２，１５のデータがスタックＢに格納される。
【０１１６】
（Ｓ１５５）解析部１２６は、各命令の命令名に基づいて、スタックＢの中で命令のデータをソートする。例えば、命令１２，１５の順にデータがスタックＢに格納されている場合、命令１５，１２の順にデータが入れ替えられる。（Ｓ１５６）解析部１２６は、スタックＢに２以上のロード命令のデータが格納されているとき、各ロード命令に対応する変数名を、中間コード１４６を参照して確認する。そして、解析部１２６は、変数名に基づいて、スタックＢの中でロード命令のデータをソートする。
【０１１７】
（Ｓ１５７）解析部１２６は、命令データ１５１におけるスタックＡの命令番号が示す位置に、スタックＢに格納された命令のデータを上書きする。スタックＡの命令番号はソート前の順序で並んでいるため、命令番号と命令の内容との対応関係が更新されることになる。例えば、命令１５のデータが命令番号１２の位置に上書きされ、命令１２のデータが命令番号１５の位置に上書きされる。（Ｓ１５８）解析部１２６は、ステップＳ１５１で全ての命令を選択したか判断する。全て選択した場合は処理を終了し、未選択の命令がある場合は処理をステップＳ１５１に進める。
【０１１８】
次に、依存ツリーのＦＭＡ正規化について説明する。
図２５は、変換規則テーブルの例を示す図である。
変換規則テーブル１５３は、ＲＡＭ１０２またはＨＤＤ１０３に格納されている。解析部１２６は、依存ツリーに含まれる三角の部分ツリーをＦＭＡ命令を用いて書き換える（ＦＭＡ正規化を行う）とき、変換規則テーブル１５３を参照する。変換規則テーブル１５３は、ルール番号、変換前の式および変換後の式の項目を含む。ルール番号の項目には、各変換規則に付与された番号が登録される。変換前の式の項目には、部分ツリーに含まれる３つの命令の演算の種類を示す式が登録される。変換後の式の項目には、変換前の部分ツリーを２以上のＦＭＡ命令の組み合わせとして表現した式が登録される。変換前の式は変換規則の適用条件に相当し、変換後の式は適用される変換規則に相当する。
【０１１９】
変換前の式および変換後の式において、Ａは左側依存点が参照する１番目のデータを示し、Ｂは左側依存点が参照する２番目のデータを示し、Ｃは右側依存点が参照する１番目のデータを示し、Ｄは右側依存点が参照する２番目のデータを示す。
【０１２０】
変換規則１は、頂点と２つの依存点の何れも加算命令である部分ツリーに対して適用される。この部分ツリーは、（（Ａ×１＋Ｂ）×１＋Ｃ）×１＋Ｄ＝ＦＭＡ（ＦＭＡ（ＦＭＡ（Ａ，１，Ｂ），１，Ｃ），１，Ｄ）のように３つのＦＭＡ命令を用いて書き換えられる。変換規則２は、頂点と左側依存点が加算命令であり右側依存点が乗算命令である部分ツリーに対して適用される。この部分ツリーは、（Ｃ×Ｄ＋Ａ）×１＋Ｂ＝ＦＭＡ（ＦＭＡ（Ｃ，Ｄ，Ａ），１，Ｂ）のように２つのＦＭＡ命令を用いて書き換えられる。ただし、前述のステップＳ２ｃの演算入れ替えによって、変換規則２が適用されるべき部分ツリーは変換規則５が適用される部分ツリーへと変形されている。
【０１２１】
変換規則３は、頂点が乗算命令であり２つの依存点が加算命令である部分ツリーに対して適用される。この部分ツリーは、（Ａ×１＋Ｂ）×（Ｃ×１＋Ｄ）＋０＝ＦＭＡ（ＦＭＡ（Ａ，１，Ｂ），ＦＭＡ（Ｃ，１，Ｄ），０）のように３つのＦＭＡ命令を用いて書き換えられる。変換規則４は、頂点と右側依存点が乗算命令であり左側依存点が加算命令である部分ツリーに対して適用される。この部分ツリーは、（（Ａ×１＋Ｂ）×Ｃ＋０）×Ｄ＋０＝ＦＭＡ（ＦＭＡ（ＦＭＡ（Ａ，１，Ｂ），Ｃ，０），Ｄ，０）のように３つのＦＭＡ命令を用いて書き換えられる。ただし、ステップＳ２ｃによって、変換規則４が適用されるべき部分ツリーは変換規則７が適用される部分ツリーへと変形されている。
【０１２２】
変換規則５は、頂点と右側依存点が加算命令であり左側依存点が乗算命令である部分ツリーに対して適用される。この部分ツリーは、（Ａ×Ｂ＋Ｃ）×１＋Ｄ＝ＦＭＡ（ＦＭＡ（Ａ，Ｂ，Ｃ），１，Ｄ）のように２つのＦＭＡ命令を用いて書き換えられる。変換規則６は、頂点が加算命令であり２つの依存点が乗算命令である部分ツリーに対して適用される。この部分ツリーは、Ａ×Ｂ＋（Ｃ×Ｄ＋０）＝ＦＭＡ（Ａ，Ｂ，ＦＭＡ（Ｃ，Ｄ，０））のように２つのＦＭＡ命令を用いて書き換えられる。
【０１２３】
変換規則７は、頂点と左側依存点が乗算命令であり右側依存点が加算命令である部分ツリーに対して適用される。この部分ツリーは、（（Ｃ×１＋Ｄ）×Ａ＋０）×Ｂ＋０＝ＦＭＡ（ＦＭＡ（ＦＭＡ（Ｃ，１，Ｄ），Ａ，０），Ｂ，０）のように３つのＦＭＡ命令を用いて書き換えられる。変換規則８は、頂点および２つの依存点の何れも乗算命令である部分ツリーに対して適用される。この部分ツリーは、（（Ａ×Ｂ＋０）×Ｃ＋０）×Ｄ＋０）＝ＦＭＡ（ＦＭＡ（ＦＭＡ（Ａ，Ｂ，０），Ｃ，０），Ｄ，０）のように３つのＦＭＡ命令を用いて書き換えられる。
【０１２４】
なお、中間コードに含まれる減算命令（ＳＵＢ）は、参照オペランドの符号を反転することで加算命令（ＡＤＤ）に置き換えることができる。また、除算命令（ＤＩＶ）は、関数に置き換えることができ、また、除算命令以外の複数の命令を用いて書き換えることもできる。よって、第２の実施の形態のＦＭＡ正規化においては、依存ツリーに減算命令や除算命令が含まれていないものとして取り扱っている。
【０１２５】
図２６は、ＦＭＡ正規化パターンの例を示す図である。
変換規則を定義するにあたり、同じ部分ツリーに対して複数の変換パターンが考えられる場合もある。例えば、頂点と左側依存点が乗算命令であり右側依存点が加算命令である部分ツリー（変換規則７）に対しては、図２６のようにパターン１，２が考えられる。
【０１２６】
パターン１によれば、依存ツリーが、（Ａ×Ｂ＋０）×（Ｃ×１＋Ｄ）＋０＝ＦＭＡ（ＦＭＡ（Ａ，Ｂ，０），ＦＭＡ（Ｃ，１，Ｄ），０）を含む依存ツリー５１に書き換えられる。パターン２は、図２５の変換規則７に示したものと同じである。パターン２によれば、依存ツリーが、（（Ｃ×１＋Ｄ）×Ａ＋０）×Ｂ＋０＝ＦＭＡ（ＦＭＡ（ＦＭＡ（Ｃ，１，Ｄ），Ａ，０），Ｂ，０）を含む依存ツリー５２に書き換えられる。
【０１２７】
ただし、依存ツリー５１では深さ２に２つのＦＭＡ命令が存在するのに対し、依存ツリー５２では各深さに１つずつＦＭＡ命令が存在する。同じ深さに存在する命令の数が多くなるほど、ＳＩＭＤ化可能な命令の組み合わせパターンが多くなってしまう。このため、依存ツリー５１への変形よりも依存ツリー５２への変形の方が好ましい。
【０１２８】
図２７は、ＦＭＡ正規化の手順例を示すフローチャートである。
このフローチャートが示す処理は、前述のステップＳ３において実行される。
（Ｓ１６１）解析部１２６は、依存ツリーから積和形式の部分ツリー、すなわち、乗算命令とその乗算結果を参照する加算命令との組を抽出する。そして、解析部１２６は、抽出した部分ツリーを１つのＦＭＡ命令に書き換える。（Ｓ１６２）解析部１２６は、依存ツリーから三角の部分ツリー、すなわち、変換規則テーブル１５３に登録された変換規則１〜８の何れかの適用条件に該当する部分ツリーを抽出する。この部分ツリーは、乗算命令または加算命令である１つの頂点Ｐと、それぞれが乗算命令または加算命令である２つの依存点Ｃ１，Ｃ２とを含むものである。（Ｓ１６３）解析部１２６は、ステップＳ１６２で抽出した三角の部分ツリーのうちの１つを選択する。
【０１２９】
（Ｓ１６４）解析部１２６は、３つの命令のうち依存点Ｃ１，Ｃ２の一方のみが乗算命令（ＭＵＬＴ）であるか判断する。すなわち、解析部１２６は、三角の部分ツリーが変換規則５を適用すべきものであるか判断する。条件を満たす場合は処理をステップＳ１６５に進め、条件を満たさない場合は処理をステップＳ１６６に進める。（Ｓ１６５）解析部１２６は、三角の部分ツリーを、２つのＦＭＡ命令を用いて（Ａ×Ｂ＋Ｃ）×１＋Ｄ＝ＦＭＡ（ＦＭＡ（Ａ，Ｂ，Ｃ），１，Ｄ）に変換する。
【０１３０】
（Ｓ１６６）解析部１２６は、３つの命令のうち依存点Ｃ１，Ｃ２の一方のみが加算命令（ＡＤＤ）であるか判断する。すなわち、解析部１２６は、三角の部分ツリーが変換規則７を適用すべきものであるか判断する。条件を満たす場合は処理をステップＳ１６７に進め、条件を満たさない場合は処理をステップＳ１６８に進める。（Ｓ１６７）解析部１２６は、三角の部分ツリーを、３つのＦＭＡ命令を用いて（（Ｃ×１＋Ｄ）×Ａ＋０）×Ｂ＋０＝ＦＭＡ（ＦＭＡ（ＦＭＡ（Ｃ，１，Ｄ），Ａ，０），Ｂ，０）に変換する。
【０１３１】
（Ｓ１６８）解析部１２６は、３つの命令の全てが加算命令（ＡＤＤ）であるか判断する。すなわち、解析部１２６は、三角の部分ツリーが変換規則１を適用すべきものであるか判断する。条件を満たす場合は処理をステップＳ１６９に進め、条件を満たさない場合は処理をステップＳ１７０に進める。（Ｓ１６９）解析部１２６は、三角の部分ツリーを、３つのＦＭＡ命令を用いて（（Ａ×１＋Ｂ）×１＋Ｃ）×１＋Ｄ＝ＦＭＡ（ＦＭＡ（ＦＭＡ（Ａ，１，Ｂ），１，Ｃ），１，Ｄ）に変換する。
【０１３２】
（Ｓ１７０）解析部１２６は、３つの命令の全てが積算命令（ＭＵＬＴ）であるか判断する。すなわち、解析部１２６は、三角の部分ツリーが変換規則８を適用すべきものであるか判断する。条件を満たす場合は処理をステップＳ１７１に進め、条件を満たさない場合は処理をステップＳ１７２に進める。（Ｓ１７１）解析部１２６は、三角の部分ツリーを、３つのＦＭＡ命令を用いて（（Ａ×Ｂ＋０）×Ｃ＋０）×Ｄ＋０）＝ＦＭＡ（ＦＭＡ（ＦＭＡ（Ａ，Ｂ，０），Ｃ，０），Ｄ，０）に変換する。
【０１３３】
（Ｓ１７２）解析部１２６は、３つの命令のうち頂点Ｐのみ加算命令（ＡＤＤ）であるか判断する。すなわち、解析部１２６は、三角の部分ツリーが変換規則６を適用すべきものであるか判断する。条件を満たす場合は処理をステップＳ１７３に進め、条件を満たさない場合は処理をステップＳ１７４に進める。（Ｓ１７３）解析部１２６は、三角の部分ツリーを、２つのＦＭＡ命令を用いてＡ×Ｂ＋（Ｃ×Ｄ＋０）＝ＦＭＡ（Ａ，Ｂ，ＦＭＡ（Ｃ，Ｄ，０））に変換する。
【０１３４】
（Ｓ１７４）解析部１２６は、３つの命令のうち頂点Ｐのみ乗算命令（ＭＵＬＴ）であるか判断する。すなわち、解析部１２６は、三角の部分ツリーが変換規則３を適用すべきものであるか判断する。条件を満たす場合は処理をステップＳ１７５に進め、条件を満たさない場合は処理をステップＳ１７６に進める。（Ｓ１７５）解析部１２６は、三角の部分ツリーを、３つのＦＭＡ命令を用いて（Ａ×１＋Ｂ）×（Ｃ×１＋Ｄ）＋０＝ＦＭＡ（ＦＭＡ（Ａ，１，Ｂ），ＦＭＡ（Ｃ，１，Ｄ），０）に変換する。
【０１３５】
（Ｓ１７６）解析部１２６は、ステップＳ１６３において全ての三角の部分ツリーを選択したか判断する。全ての三角の部分ツリーを選択した場合は処理を終了し、未選択の三角の部分ツリーがある場合は処理をステップＳ１６３に進める。
【０１３６】
なお、ステップＳ１６５，Ｓ１６７，Ｓ１６９，Ｓ１７１，Ｓ１７３，Ｓ１７５の変換は、次の４つの関数を用いて纏めることができる。ｆ１（ｘ１，ｘ２，ｘ３，ｘ４，ｘ５）＝（ｘ１×ｘ２＋ｘ３）×ｘ４＋ｘ５。ｆ２（ｘ１，ｘ２，ｘ３，ｘ４，ｘ５，ｘ６，ｘ７）＝（（ｘ１×ｘ２＋ｘ３）×ｘ４＋ｘ５）×ｘ６＋ｘ７。ｆ３（ｘ１，ｘ２，ｘ３，ｘ４，ｘ５）＝ｘ１×ｘ２＋（ｘ３×ｘ４＋ｘ５）。ｆ４（ｘ１，ｘ２，ｘ３，ｘ４，ｘ５，ｘ６，ｘ７）＝（ｘ１×ｘ２＋ｘ３）×（ｘ４×ｘ５＋ｘ６）＋ｘ７。
【０１３７】
ステップＳ１６５はｆ１（Ａ，Ｂ，Ｃ，１，Ｄ）として実装できる。ステップＳ１６７はｆ２（Ｃ，１，Ｄ，Ａ，０，Ｂ，０）、ステップＳ１６９はｆ２（Ａ，１，Ｂ，１，Ｃ，１，Ｄ）、ステップＳ１７１はｆ２（Ａ，Ｂ，０，Ｃ，０，Ｄ，０）として実装できる。ステップＳ１７３はｆ３（Ａ，Ｂ，Ｃ，Ｄ，０）として実装できる。ステップＳ１７４はｆ４（Ａ，１，Ｂ，Ｃ，１，Ｄ，０）として実装できる。
【０１３８】
次に、基点命令の選択および依存ツリーの分割（レベル管理）について説明する。
図２８は、依存ツリーの分割例を示す図である。
ここでは、図２８に示す命令１〜１４を含む依存ツリー５３が生成された場合を考える。命令３，９は乗算命令であり、命令５，１１，１３は加算命令である。命令１，２，４，７，８，１０はロード命令であり、命令６，１２，１４はストア命令である。命令３は命令１，２に依存し、命令５は命令３，４に依存し、命令６は命令５に依存している。命令９は命令７，８に依存し、命令１１は命令９，１０に依存し、命令１２は命令１１に依存している。命令１３は命令６，１２に依存し、命令１４は命令１３に依存している。
【０１３９】
第２の実施の形態では、依存ツリー間の比較を容易にするため、ストア命令である命令６，１２，１４を基点にして、依存ツリー５３を３つの小さな依存ツリーに分割する。すなわち、解析部１２６は、依存ツリー５３を、命令６が基点命令（ルートの命令）であり命令１〜６を含む依存ツリーと、命令１２が基点命令であり命令７〜１２を含む依存ツリーと、命令１４が基点命令であり命令１３，１４を含む依存ツリーとに分割する。
【０１４０】
このとき、解析部１２６は、各基点命令についてレベルを算出しておく。基点命令のレベルは、分割前の依存ツリー５３において、基点命令のノードとそのノードの配下にある各リーフノードとの間のパスのうち、最長のパス上に並ぶノードの数である。例えば、命令６のレベルは、命令６と命令１（または命令２）とを結ぶパス上に４個のノードが並ぶことから、４である。命令１２のレベルは、命令１２と命令７（または命令８）とを結ぶパス上に４個のノードが並ぶことから、４である。命令１４のレベルは、命令１４と命令１（または命令２，７，８）とを結ぶパス上に６個のノードが並ぶことから、６である。
【０１４１】
図２９は、基点データの例を示す図である。
解析部１２６は、基点命令を選択して依存ツリー５３を分割すると、基点データ１５４を生成する。基点データ１５４は、分割後の依存ツリー毎に、ツリーＩＤ（Identifier）、基点番号、レベルおよび命令番号の項目を含む。ツリーＩＤは、分割後の各依存ツリーを識別するための識別子である。基点番号は、基点命令の命令番号である。レベルは、上記のように算出された基点命令のレベルである。命令番号の項目には、分割後の依存ツリーに含まれる命令の命令番号が列挙される。
【０１４２】
図３０は、基点選択の手順例を示すフローチャートである。
このフローチャートが示す処理は、前述のステップＳ４において実行される。
（Ｓ１８１）解析部１２６は、ルートノードに近い命令から優先的に、依存ツリーに含まれる命令を１つ選択する。（Ｓ１８２）解析部１２６は、選択した命令がストア命令（ＳＴＯＲＥ）であるか判断する。選択した命令がストア命令である場合、その命令を基点命令に採用し、処理をステップＳ１８３に進める。選択した命令がストア命令でない場合は、その命令を基点命令に採用せず、処理をステップＳ１８６に進める。
【０１４３】
（Ｓ１８３）解析部１２６は、カウンタＣ＝０，レベルＬ＝０に初期化する。（Ｓ１８４）解析部１２６は、後述するサブルーチンを用いて、基点命令のレベルを算出する。（Ｓ１８５）解析部１２６は、採用した基点命令をルートノードとする依存ツリーの情報を基点データ１５４に登録する。（Ｓ１８６）解析部１２６は、ステップＳ１８１で全ての命令を選択したか判断する。全ての命令を選択した場合は処理を終了し、未選択の命令がある場合は処理をステップＳ１８１に進める。
【０１４４】
図３１は、レベル算出のサブルーチンの手順例を示すフローチャートである。
このサブルーチンは、パラメータとしてカウンタＣとレベルＬを受け取る。このサブルーチンは、上記のステップＳ１８４において呼び出される。
【０１４５】
（Ｓ１９１）解析部１２６は、カウンタＣをインクリメント（値を１だけ加算）する。（Ｓ１９２）解析部１２６は、現在のレベルＬの値がカウンタＣの値よりも小さいか判断する。レベルＬの値がカウンタＣの値より小さい場合は処理をステップＳ１９３に進め、それ以外の場合は処理をステップＳ１９４に進める。（Ｓ１９３）解析部１２６は、レベルＬにカウンタＣの値を代入する。
【０１４６】
（Ｓ１９４）解析部１２６は、現在着目している命令の子ノードに相当する命令が、次のステップＳ１９５で全て選択されたか判断する。全て選択された場合は処理をステップＳ１９７に進め、未選択の命令がある場合は処理をステップＳ１９５に進める。（Ｓ１９５）解析部１２６は、子ノードに相当する命令を１つ選択する。（Ｓ１９６）解析部１２６は、ステップＳ１９５で選択した子ノードに相当する命令について、この時点のレベルＬとカウンタＣをパラメータとして渡して、図３１のサブルーチンを再帰的に呼び出す。その後、処理をステップＳ１９４に進める。（Ｓ１９７）解析部１２６は、カウンタＣをデクリメント（値を１だけ減算）する。
【０１４７】
次に、依存ツリーの符号化について説明する。
図３２は、符号テーブルの例を示す図である。
符号テーブル１５５は、演算の種類と符号との対応関係を示す。符号テーブル１５５は、ＲＡＭ１０２またはＨＤＤ１０３に格納されている。解析部１２６は、依存ツリーを符号化するとき（ステップＳ５）、符号テーブル１５５を参照する。
【０１４８】
図３２の例によれば、乗算命令（ＭＵＬＴ）は「１」に変換され、除算命令（ＤＩＶ）は「２」に変換され、加算命令（ＡＤＤ）は「３」に変換され、減算命令（ＳＵＢ）は「４」に変換される。ロード（ＬＯＡＤ）命令は「５」に変換され、ストア（ＳＴＯＲＥ）命令は「６」に変換される。
【０１４９】
また、積和演算の命令（ＦＭＡＤＤ）は「７」に変換され、負の積和演算の命令（ＦＮＭＡＤＤ）は「８」に変換され、積差演算の命令（ＦＭＳＵＢ）は「９」に変換され、負の積差演算の命令（ＦＮＭＳＵＢ）は「１０」に変換される。ＦＮＭＡＤＤは、データＡ，Ｂ，Ｃに対して−（Ａ×Ｂ＋Ｃ）を算出する演算である。ＦＭＳＵＢは、データＡ，Ｂ，Ｃに対してＡ×Ｂ−Ｃを算出する演算である。ＦＮＭＳＵＢは、データＡ，Ｂ，Ｃに対して−（Ａ×Ｂ−Ｃ）を算出する演算である。ＦＮＭＡＤＤ，ＦＭＳＵＢ，ＦＮＭＳＵＢの命令は、ＦＭＡ命令に類する命令群に属すると言うこともできる。
【０１５０】
図３３は、符号化の手順例を示すフローチャートである。
このフローチャートが示す処理は、前述のステップＳ５において実行される。
（Ｓ２１１）解析部１２６は、基点データ１５４を参照して、ステップＳ４で分割された依存ツリーを１つ選択する。（Ｓ２１２）解析部１２６は、選択した依存ツリーに含まれる命令の数に相当する大きさの配列を、符号データとして生成する。
【０１５１】
（Ｓ２１３）解析部１２６は、ステップＳ２１１で選択した依存ツリーから、木構造に応じた順序で、命令を１つ選択する。例えば、解析部１２６は、帰り掛け深さ優先探索により、依存ツリーを探索して命令を選択する。図２８に示した命令６を基点とする依存ツリーの場合、命令１，２，３，４，５，６の順に選択していく。（Ｓ２１４）解析部１２６は、符号テーブル１５５から、選択した命令で行われる演算の種類に対応する符号を検索し、検索した符号を配列に格納する。ステップＳ２１３でｉ個目の命令を選択すると、その命令に対応する符号は配列のｉ番目に格納される。例えば、図２８に示した命令６を基点とする依存ツリーの場合、この依存ツリーに対応する符号データとして、５，５，１，５，３，６という符号列の符号データが生成される。
【０１５２】
（Ｓ２１５）解析部１２６は、ステップＳ２１３で全ての命令を選択したか判断する。全て選択した場合は処理をステップＳ２１６に進め、未選択の命令がある場合は処理をステップＳ２１３に進める。（Ｓ２１６）解析部１２６は、ステップＳ２１１で全ての依存ツリーを選択したか判断する。全て選択した場合は処理を終了し、未選択の依存ツリーがある場合は処理をステップＳ２１１に進める。
【０１５３】
次に、依存ツリーの組の候補の算出および依存ツリーの組の決定について説明する。
図３４は、エッジデータとパックデータの例を示す図である。
解析部１２６は、依存ツリーの組の候補を算出してエッジデータ１５６を生成する。また、解析部１２６は、依存ツリーの組を決定してパックデータ１５７を生成する。
【０１５４】
エッジデータ１５６は、依存ツリーの組毎に、エッジ番号および２以上の基点番号の項目を含む。エッジ番号は、エッジ（依存ツリーの組）を識別するための番号である。基点番号［Ｓ］（Ｓ＝１，２，・・・）の項目には、依存ツリーの基点命令の命令番号が設定される。基点番号の個数は、ＳＩＭＤの並列度に一致する。ＳＩＭＤ化の際は、基点番号［Ｓ］に対応する依存ツリーの命令に、Ｓ番目のスロットが割り当てられることになる。すなわち、基点番号［１］に対応する依存ツリーの命令にスロット１が割り当てられ、基点番号［２］に対応する依存ツリーの命令にスロット２が割り当てられる。
【０１５５】
パックデータ１５７は、エッジデータ１５６に登録された依存ツリーの組のうち、ＳＩＭＤ命令を生成するために採用する１またはそれ以上の依存ツリーの組の集合（パック）を示す。パックデータ１５７は、１またはそれ以上のエッジ番号の項目を含む。エッジデータ１５６とパックデータ１５７とは、エッジ番号によって関連付けられる。
【０１５６】
図３５は、候補算出の手順例を示すフローチャートである。
このフローチャートが示す処理は、前述のステップＳ６において実行される。
（Ｓ２２１）解析部１２６は、１つのエッジ分のデータを格納するための空のフレームＥ0を生成する。フレームＥ0に含まれる基点番号の項目の数は、ＳＩＭＤの並列度に一致させる。（Ｓ２２２）解析部１２６は、変数として基点Ｋ，スロットＳを定義し、基点Ｋ＝１，スロットＳ＝１に初期化する。
【０１５７】
（Ｓ２２３）解析部１２６は、後述するサブルーチンを用いて、フレームＥ0およびフレームＥ0からコピーされたフレームに、基点番号を設定していく。このとき、解析部１２６は、フレームＥ0，基点Ｋ，スロットＳを、パラメータとしてサブルーチンに渡す。（Ｓ２２４）解析部１２６は、基点Ｋをインクリメント（値を１だけ加算）する。（Ｓ２２５）解析部１２６は、基点Ｋの値が、基点命令の総数（生成された依存ツリーの総数）以下であるか判断する。条件を満たす場合は処理をステップＳ２２３に進め、条件を満たさない場合は処理を終了する。
【０１５８】
図３６は、エッジデータ設定のサブルーチンの手順例を示すフローチャートである。
このサブルーチンは、パラメータとしてフレームＥ，基点Ｋ，スロットＳを受け取る。このサブルーチンは、上記のステップＳ２２３において呼び出される。
【０１５９】
（Ｓ２３１）解析部１２６は、スロットＳの値がＳＩＭＤの並列度以下であるか、すなわち、フレームＥの基点番号の項目にまだ空の項目が存在するか判断する。空の基点番号の項目がある場合は処理をステップＳ２３２に進め、基点番号の項目が全て埋まった場合は処理をステップＳ２３８に進める。（Ｓ２３２）解析部１２６は、フレームＥの基点番号［Ｓ］の項目に、Ｋ番目の基点命令の命令番号を設定する。（Ｓ２３３）解析部１２６は、スロットＳの値をインクリメント（値を１だけ加算）する。また、解析部１２６は、変数として基点Ｃを定義し、Ｃ＝１に初期化する。
【０１６０】
（Ｓ２３４）解析部１２６は、フレームＥのデータをコピーしてフレームＥｃを生成する。フレームＥからフレームＥｃへは、設定済の基点番号が引き継がれる。（Ｓ２３５）解析部１２６は、現在のフレームＥｃ，基点Ｃ，スロットＳをパラメータとして渡して、図３６のサブルーチンを再帰的に呼び出す。（Ｓ２３６）解析部１２６は、基点Ｃをインクリメントする。（Ｓ２３７）解析部１２６は、基点Ｃの値が、基点命令の総数以下であるか判断する。条件を満たす場合は処理をステップＳ２３４に進め、条件を満たさない場合はサブルーチンを終了する。
【０１６１】
（Ｓ２３８）解析部１２６は、フレームＥに、重複する命令番号が基点番号として含まれているか判断する。同じ命令番号が含まれる場合は処理をステップＳ２４３に進め、それ以外の場合は処理をステップＳ２３９に進める。（Ｓ２３９）解析部１２６は、フレームＥに含まれる基点番号が示す基点命令の「レベル」が全て同じであるか判断する。レベルが同じ場合は処理をステップＳ２４０に進め、レベルが異なる場合は処理をステップＳ２４３に進める。（Ｓ２４０）解析部１２６は、フレームＥが示す複数の依存ツリーの間に、依存関係があるか判断する。依存関係がある場合は処理をステップＳ２４３に進め、依存関係がない場合は処理をステップＳ２４１に進める。
【０１６２】
（Ｓ２４１）解析部１２６は、フレームＥが示す複数の依存ツリーに属する命令を組み合わせることが、プロセッサのアーキテクチャに反するか判断する。アーキテクチャ違反の例としては、メモリ割り当ての制約を満たさない、データの型（整数型や浮動小数点型など）がＳＩＭＤ命令で扱うことができない型である、などが挙げられる。アーキテクチャに反する場合は処理をステップＳ２４３に進め、それ以外の場合は処理をステップＳ２４２に進める。（Ｓ２４２）解析部１２６は、フレームＥのデータをエッジデータ１５６に登録し、サブルーチンを終了する。（Ｓ２４３）解析部１２６は、フレームＥのデータを破棄し、サブルーチンを終了する。
【０１６３】
図３７は、エッジデータ生成の流れの例を示す図である。
図３６のサブルーチンを再帰的に実行していくことで、基点番号［１］，基点番号［２］，…の順に、基点命令の命令番号がフレームＥに１つずつ設定されていく。そして、全ての基点番号の項目が埋まると、フレームＥが示す複数の依存ツリーを組み合わせ可能か判定され、組み合わせ不可な複数の依存ツリーを示すデータは破棄される。例えば、基点番号［１］＝６，基点番号［２］＝６というデータは破棄される。また、複数の基点命令のレベルが全て同じか判定され、レベルが異なる基点命令の組を示すデータは破棄される。例えば、基点番号＝６の基点命令のレベルと基点番号＝１４の基点命令のレベルとが異なるとき、基点番号［１］＝６，基点番号［２］＝１４というデータは破棄される。
【０１６４】
図３８は、パックデータの候補の例を示す図である。
解析部１２６は、複数のエッジのべき集合をパックの集合として算出し、各パックをＳＩＭＤ化できる命令の数の観点から評価することで、パックを１つ選択する。例えば、互いに独立なエッジ１，２が存在するとき、エッジ１のみを採用したパック１と、エッジ２のみを採用したパック２と、エッジ１，２の両方を採用したパック３とが評価される。
【０１６５】
図３９は、符号データからスコアを算出する例を示す図である。
パックを評価するために、解析部１２６は、各パックのスコアを算出する。スコアの高いパックほど、ＳＩＭＤ化できる命令が多いパックであることを示している。解析部１２６は、エッジ毎に、複数の依存ツリーの間で符号データを比較して、対応する位置にある命令の組であって演算の種類が同じ命令の組の数を、エッジのスコアとして算出する。そして、解析部１２６は、エッジ毎のスコアを合算してパックのスコアとする。
【０１６６】
図４０は、ＳＩＭＤ化判定の手順例を示すフローチャートである。
このフローチャートが示す処理は、前述のステップＳ７において実行される。
（Ｓ２５１）解析部１２６は、変数としてエッジｅとパックＰを定義し、エッジｅ＝０，パックＰ＝Φ（空集合）に初期化する。（Ｓ２５２）解析部１２６は、変数として最大スコアＺを定義し、最大スコアＺ＝−１に初期化する。（Ｓ２５３）解析部１２６は、後述するサブルーチンを用いて、スコアが最大となるパックを探索する。
【０１６７】
（Ｓ２５４）解析部１２６は、最大スコアＺの値が初期値＝−１のままであるか、すなわち、パックを１つも発見できなかったか判断する。最大スコアＺ＝−１の場合は処理をステップＳ２５６に進め、それ以外の場合は処理をステップＳ２５５に進める。（Ｓ２５５）解析部１２６は、パックデータ１５７からＳＩＭＤ化する命令組を決定する。組み合わせる命令は、同じエッジに含まれる複数の依存ツリーの間の対応する位置にある命令同士である。（Ｓ２５６）解析部１２６は、中間コード１４６における現在の翻訳単位に含まれる命令をＳＩＭＤ化することを中止する。
【０１６８】
図４１は、パックデータ設定のサブルーチンの手順例を示すフローチャートである。
このサブルーチンは、パラメータとしてエッジｅ，パックＰを受け取る。このサブルーチンは、上記のステップＳ２５３において呼び出される。
【０１６９】
（Ｓ２６１）解析部１２６は、後述する方法によって、符号データを用いてパックＰのスコアを算出する。（Ｓ２６２）解析部１２６は、エッジｅをインクリメント（値を１だけ加算）する。（Ｓ２６３）解析部１２６は、エッジｅの値が、最大のエッジ番号以下であるか判断する。条件を満たす場合は処理をステップＳ２６４に進め、条件を満たさない場合はサブルーチンを終了する。
【０１７０】
（Ｓ２６４）解析部１２６は、ｅ番目のエッジ（エッジ番号ｅのエッジ）を含むパックを評価するか判断する。次の３つの条件の少なくとも１つに該当するとき、ｅ番目のエッジを含むパックを評価しなくてよいと判断する。（１）ｅ番目のエッジの依存ツリーが、パックＰに既に含まれている。（２）ｅ番目のエッジの依存ツリーが、パックＰに既に含まれている何れかの依存ツリーと依存関係にある。（３）現時点のパックＰのスコアが、計算済の他のパックのスコアの最大値よりも所定差以上下回っており、パックＰにｅ番目のエッジを追加しても最良のパックになる見込みがない。ｅ番目のエッジを含むパックを評価する場合、処理をステップＳ２６５に進め、そのようなパックを評価しなくてよい場合、処理をステップＳ２６８に進める。
【０１７１】
（Ｓ２６５）解析部１２６は、ｅ番目のエッジをパックＰに追加する。（Ｓ２６６）解析部１２６は、ｅ番目のエッジを含むパックＰとエッジｅをパラメータとして渡し、図４１に示すサブルーチンを再帰的に呼び出す。（Ｓ２６７）解析部１２６は、ステップＳ２６５で追加したｅ番目のエッジをパックＰから削除する。（Ｓ２６８）解析部１２６は、ｅ番目のエッジを含まないパックＰとエッジｅをパラメータとして渡し、図４１に示すサブルーチンを再帰的に呼び出す。
【０１７２】
図４２は、スコア算出の手順例を示すフローチャートである。
このフローチャートが示す処理は、上記のステップＳ２６１において実行される。
（Ｓ２７１）解析部１２６は、パックに含まれるエッジを１つ選択する。（Ｓ２７２）解析部１２６は、配列に含まれる符号を特定するためのインデックスｐの値を１つ選択する。インデックスｐの値は、１から、エッジに属する複数の依存ツリーに対応する複数の配列の中で最も長い配列の配列長まで変化する。（Ｓ２７３）解析部１２６は、変数としてスロットＳを定義し、スロットＳ＝１に初期化する。
【０１７３】
（Ｓ２７４）解析部１２６は、ステップＳ２７１で選択したエッジの基点番号［Ｓ］に対応する依存ツリーを選択し、その依存ツリーに対応する符号データである配列を取得する。そして、解析部１２６は、ＲＡＭ１０２に確保した記憶領域であるスタックＸに、取得した配列に含まれるｐ番目の符号を格納する。なお、取得した配列の配列長がｐより小さいときは、命令が無いことを示す所定の符号（例えば「０」）をスタックＸに格納する。（Ｓ２７５）解析部１２６は、スロットＳをインクリメント（値を１だけ加算）する。（Ｓ２７６）解析部１２６は、スロットＳの値がＳＩＭＤの並列度以下であるか判断する。スロットＳの値が並列度以下の場合は処理をステップＳ２７４に進め、並列度より大きい場合は処理をステップＳ２７７に進める。
【０１７４】
（Ｓ２７７）解析部１２６は、スタックＸに格納された符号が全て同じであるか、すなわち、対応する位置にある命令間で演算の種類が全て同じか判断する。全て同じ場合は処理をステップＳ２７８に進め、同じでない場合は処理をステップＳ２７９に進める。（Ｓ２７８）解析部１２６は、パックのスコアをインクリメントする。
【０１７５】
（Ｓ２７９）解析部１２６は、ステップＳ２７２で全てのインデックスｐの値を選択したか判断する。全て選択した場合は処理をステップＳ２８０に進め、未選択のインデックスｐの値がある場合は処理をステップＳ２７２に進める。（Ｓ２８０）解析部１２６は、ステップＳ２７１で全てのエッジを選択したか判断する。全て選択した場合は処理をステップＳ２８１に進め、未選択のエッジがある場合は処理をステップＳ２７１に進める。（Ｓ２８１）解析部１２６は、ステップＳ２７８の処理を通じて算出されたパックのスコアが、現在の最大スコアＺより大きいか判断し、現在の最大スコアＺより大きい場合は、最大スコアＺを算出されたスコアに置き換える。
【０１７６】
図４３は、パックデータ生成の流れの例を示す図である。
図４１のサブルーチンが再帰的に呼び出されることで、スコア評価の処理が、ｅ番目のエッジをパックＰに含めるときの処理と含めないときの処理とに分岐する。まず、１番目のエッジをパックＰに含めるか否かによって、処理が２つに分岐する。次に、２番目のエッジをパックＰに含めるか否かによって、処理が更に２つずつに分岐し、合計で処理が４つに分岐することになる。以下、エッジの数に応じて処理の分岐が発生する。
【０１７７】
第２の実施の形態の端末装置１００によれば、依存ツリーからＦＭＡ命令を用いて書き換え可能な部分ツリーが検出され、ＦＭＡ命令を含む依存ツリーに変換される。そして、ＦＭＡ命令を含む依存ツリーに基づいて、中間コードのＦＭＡ化やＳＩＭＤ化などの最適化処理が行われる。これにより、依存ツリーの同じ深さに配置された命令の数が減少し、ＳＩＭＤ化において探索される命令の組み合わせパターンが減少する。また、依存ツリーに含まれる命令の多くがＦＭＡ命令に変換されるため、命令の種類に応じて実行サイクル数が異なる場合であっても命令スケジューリングが容易になる。よって、変形した依存ツリーを探索することで、最適化処理の計算量を抑制でき処理時間を短縮できる。
【０１７８】
また、ＦＭＡ正規化の前に変換規則に合致するような部分ツリーが多く現れるように、依存ツリーを整形することで、依存ツリーに含まれる多くの命令をＦＭＡ命令に書き換えることができる。また、ＦＭＡ正規化にあたって、同じ深さにあるＦＭＡ命令が少なくなるように変換規則が作成される。これにより、ＳＩＭＤ化の負荷が軽減される。
【０１７９】
また、中間コードに含まれる多くの命令をＦＭＡ命令やＳＩＭＤ−ＦＭＡ命令に変換することで、オブジェクトコードの命令数を削減することができる。また、多くの命令をＦＭＡ命令やＳＩＭＤ−ＦＭＡ命令に変換することで、それら少数の種類の命令を空き時間が少なくなるように高密度にスケジューリングできる。よって、コンパイラ１２０が生成するオブジェクトコードの実行効率を向上させることができる。
【０１８０】
なお、前述のように、第１の実施の形態の情報処理は、コンパイル装置１０にプログラムを実行させることで実現でき、第２の実施の形態の情報処理は、端末装置１００にプログラムを実行させることで実現できる。プログラムは、コンピュータ読み取り可能な記録媒体（例えば、記録媒体２３）に記録しておくことができる。記録媒体としては、例えば、磁気ディスク、光ディスク、光磁気ディスク、半導体メモリなどを使用できる。磁気ディスクには、ＦＤおよびＨＤＤが含まれる。光ディスクには、ＣＤ、ＣＤ−Ｒ（Recordable）／ＲＷ（Rewritable）、ＤＶＤおよびＤＶＤ−Ｒ／ＲＷが含まれる。
【０１８１】
プログラムを流通させる場合、例えば、当該プログラムを記録した可搬記録媒体が提供される。コンピュータは、例えば、可搬記録媒体に記録されたプログラムを記憶装置（例えば、ＨＤＤ１０３）にコピーし、当該記憶装置からプログラムを読み込んで実行する。ただし、可搬記録媒体から読み込んだプログラムを直接実行してもよい。
【符号の説明】
【０１８２】
１０  コンパイル装置
１１  記憶部
１２  演算部
１３，１４  コード
１５，１５ａ  依存ツリー
【図１】
2015143939.tif 000003
【図２】
2015143939.tif 000004
【図３】
2015143939.tif 000005
【図４】
2015143939.tif 000006
【図５】
2015143939.tif 000007
【図６】
2015143939.tif 000008
【図７】
2015143939.tif 000009
【図８】
2015143939.tif 000010
【図９】
2015143939.tif 000011
【図１０】
2015143939.tif 000012
【図１１】
2015143939.tif 000013
【図１２】
2015143939.tif 000014
【図１３】
2015143939.tif 000015
【図１４】
2015143939.tif 000016
【図１５】
2015143939.tif 000017
【図１６】
2015143939.tif 000018
【図１７】
2015143939.tif 000019
【図１８】
2015143939.tif 000020
【図１９】
2015143939.tif 000021
【図２０】
2015143939.tif 000022
【図２１】
2015143939.tif 000023
【図２２】
2015143939.tif 000024
【図２３】
2015143939.tif 000025
【図２４】
2015143939.tif 000026
【図２５】
2015143939.tif 000027
【図２６】
2015143939.tif 000028
【図２７】
2015143939.tif 000029
【図２８】
2015143939.tif 000030
【図２９】
2015143939.tif 000031
【図３０】
2015143939.tif 000032
【図３１】
2015143939.tif 000033
【図３２】
2015143939.tif 000034
【図３３】
2015143939.tif 000035
【図３４】
2015143939.tif 000036
【図３５】
2015143939.tif 000037
【図３６】
2015143939.tif 000038
【図３７】
2015143939.tif 000039
【図３８】
2015143939.tif 000040
【図３９】
2015143939.tif 000041
【図４０】
2015143939.tif 000042
【図４１】
2015143939.tif 000043
【図４２】
2015143939.tif 000044
【図４３】
2015143939.tif 000045