(57)【要約】【課題】単一の関数内で関数コールにまたがるコード移動を行うことで、プログラムの最適化を図る。【解決手段】関数コール間移動可能コード検出処理（１４２，１４３）と、関数コール間コード移動処理（１４４）と、コード生成処理（１４６）とをコンピュータ（２）が実行する。上記関数コール間移動可能コード検出処理は、与えられたプログラム中の関数内から同じ関数内にその関数の関数コールにまたがって移動可能なコードを検出する。上記関数コール間コード移動処理は、上記関数コール間移動可能コード検出処理によって検出されたコードを上記関数の関数コールにまたがって同じ関数内に移動する。このような移動が行われることで、関数の実行時間の短縮を図る。【選択図】図１
2014109849.tif 000002
【特許請求の範囲】
【請求項１】
入力されたプログラム中の関数内から同じ関数内にその関数の関数コールにまたがるコード移動が可能となるコードを検出する関数コール間移動可能コード検出処理と、
上記関数コール間移動可能コード検出処理によって検出されたコードを、上記関数の関数コールにまたがって同じ関数内に移動する関数コール間コード移動処理と、
上記関数コール間コード移動処理後のプログラムに基づいてオブジェクトコードを生成するコード生成処理と、をコンピュータが実行するオブジェクトコード生成方法。
【請求項２】
上記関数コール間コード移動処理は、上記関数コール間移動可能コード検出処理によって検出されたコードを、上記関数の関数コールにまたがって同じ関数内におけるプログラムの空きサイクルに移動する請求項１記載のオブジェクトコード生成方法。
【請求項３】
上記関数は、割り込み関数とされる請求項２記載のオブジェクトコード生成方法。
【請求項４】
上記関数コール間移動可能コード検出処理は、上記関数コールにまたがって移動可能な条件を満たす変数の集合である関数コール間移動可能変数集合を検出する関数コール間移動可能変数集合検出処理と、
上記関数コール間移動可能変数集合検出処理で検出された関数コール間移動可能変数集合における関数中に変数を定義するコードを見つけ、上記コードの全てのオペランドが、上記関数コール間移動可能変数集合に含まれる変数又は定数である場合に、上記コードによって上記関数コール間移動可能変数集合を更新する変数値変更コード検出処理と、を含む請求項３記載のオブジェクトコード生成方法。
【請求項５】
上記関数コール間移動可能変数集合検出処理は、スタティックで第１関数中に定義がある変数を参照する処理が、初期化コード、終了処理コード、上記第１関数内のコード、又は上記第１関数と同期を取る第２関数内で、上記第１関数内の変数を参照する区間が実行中のときに実行されるコードとされる場合に、上記第１関数中に定義がある変数の集合を関数コール間移動可能変数集合として検出する請求項４記載のオブジェクトコード生成方法。
【請求項６】
上記関数コール間移動可能変数集合検出処理は、与えられた関数内のローカルなスタティック変数の集合を関数コール間移動可能変数集合として検出する、請求項４記載のオブジェクトコード生成方法。
【請求項７】
上記コンピュータが実行する処理として、関数外コード修正処理を含み、
上記関数外コード修正処理は、上記関数コール間コード移処理によって移動されたコードである第１コードと、与えられた関数に対する最初の関数コールよりも前に実行される第１プログラム部分との両方で参照される第１変数集合に対して、上記第１変数集合に含まれる変数を参照する上記第１プログラム部分のうちの最後の第１位置を検出し、
上記第１コードの移動方向が関数の入口方向ならば、上記第１位置の直後に上記第１コードのコピーを追加し、
上記第１コードの移動方向が関数の出口方向ならば、上記第１位置の直後に上記第１コード内の全ての変数値の変更を打ち消すコードを追加し、
上記第１コードと、与えられた関数に対する最後の関数コールがある場合、それよりも後に実行される第２プログラム部分との両方で参照される第２変数集合に対して、上記第２変数集合に含まれる変数を参照する上記第２プログラム部分のうちの最初の第２位置を検出し、
上記第１コードの移動方向が関数の入口方向ならば、上記第２位置の直前に上記第１コード内の全ての変数値の変更を打ち消すコードを追加し、
上記第１コードの移動方向が関数の出口方向ならば、上記第２位置の直前に上記第１コードのコピーを追加する請求項４記載のオブジェクトコード生成方法。
【請求項８】
上記コンピュータが実行する処理として、関数内初期化コード修正処理を含み、
上記関数内初期化コード修正処理は、上記関数コール間コード移動処理によって移動される第１コードと、
上記第１コードで定義される第１変数に対する第１初期化コードを検出し、
上記第１コードの移動方向が関数の入口方向ならば、上記第１初期化コードの直後に上記第１コードを置いた結果得られる上記第１変数の値を初期値とする第２初期化コードで上記第１初期化コードを置き換え、
上記第１コードの移動方向が関数の出口方向ならば、上記第１コードの直後における第１変数の値が上記第１初期化コードの直後における上記第１変数の値になるような上記コードの直前における上記第１変数の値を初期値とする第２初期化コードで上記第１初期化コードを置き換える請求項４記載のオブジェクトコード生成方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明はオブジェクトコード生成方法に関し、特に、ソースプログラムに基づいてオブジェクトプログラムを生成するコンパイラに好適に利用できるものである。
【背景技術】
【０００２】
特許文献１には、ソースプログラムを解析してオブジェクトプログラムを生成するコンパイラが記載されている。このコンパイラは、ループ分割により生成されたループのうち、分割を生じせしめた手続き呼び出しのみを含むループのループくり返し処理を該手続きの写しの内部に移動することを特徴とする。
【０００３】
非特許文献１には、関数コールにまたがるコード移動に関しては、ある関数から別の関数にコードを移動する技術が記載されている。
【先行技術文献】
【特許文献】
【０００４】
【特許文献１】特開平１−１２１９３８号公報
【非特許文献】
【０００５】
【非特許文献１】Mary W. Hall, et al. Interprocedural transformations for parallel code generation. In Proc. of the 1991 ACM/IEEE conference on Supercomputing, pp. 424-434, 1991.
【発明の概要】
【発明が解決しようとする課題】
【０００６】
特許文献１の技術によれば、ループ分割により生成されたループのうち、分割を生じせしめた手続き呼び出しのみを含むループのループくり返し処理を該手続きの写しの内部に移動することについては記載されているものの、関数コールにまたがるコード移動に関しては記載されていない。
【０００７】
非特許文献１の技術に従えば、関数コールにまたがるコード移動に関しては、ある関数から別の関数にコードを移動するものだけである。呼び出す側の関数から呼び出される側の関数へのコード移動は次のように行われる。
【０００８】
例えば図３４における（Ａ），（Ｃ）にはコード移動前の状態が示される。図３４において、関数Ｐ内の文の集まり（図３４における（Ａ）の行４、（Ｃ）の破線で囲まれた部分）は、関数コールを超えて関数Ｓ内に文の集まりが移動される。図３４における（Ｂ），（Ｄ）には、コード移動後の状態が示される。
【０００９】
更に逆方向へのコード移動も可能とされる。
【００１０】
例えば図３５における（Ａ），（Ｃ）にはコード移動前の状態が示される。関数Ｐ内の文の集まり（図３５における（Ａ）の行１１、（Ｃ）の破線で囲まれた部分）は関数コールを超えて関数P内に移動される。図３５における（Ｂ），（Ｄ）には、コード移動後の状態が示される。
【００１１】
このように非特許文献１の技術によれば、関数コールにまたがるコード移動に関しては、ある関数から別の関数にコードを移動するようにしており、単一の関数内で関数コールにまたがるコード移動については考慮されていない。
【００１２】
その他の課題と新規な特徴は、本明細書の記述及び添付図面から明らかになるであろう。
【課題を解決するための手段】
【００１３】
課題を解決するための手段のうち代表的なものの概要を簡単に説明すれば下記の通りである。
【００１４】
すなわち、関数コール間移動可能コード検出処理と、関数コール間コード移動処理とをコンピュータが実行する。上記関数コール間移動可能コード検出処理は、与えられたプログラム中の関数内から同じ関数内にその関数の関数コールにまたがって移動可能なコードを検出する。上記関数コール間コード移動処理は、上記関数コール間移動可能コード検出処理によって検出されたコードを上記関数の関数コールにまたがって同じ関数内に移動する。
【発明の効果】
【００１５】
課題を解決するための手段のうち代表的なものによって得られる効果を簡単に説明すれば下記の通りである。
【００１６】
すなわち、関数コールにまたがるコード移動によりプログラムの最適化を図ることができる。
【図面の簡単な説明】
【００１７】
【図１】マイコン開発システムの構成例ブロック図である。
【図２】プログラムの最適化処理の説明図である。
【図３】ソースプログラムの元になる逐次プログラムの説明図である。
【図４】バリア同期の機能説明図である。
【図５】最適化前のソースプログラムの説明図である。
【図６】最適化後のソースプログラムの説明図である。
【図７】最適化前のプログラムの実行の様子の説明図である。
【図８】最適化後のプログラムの実行の様子の説明図である。
【図９】関数コール間移動可能変数集合検出アルゴリズムのフローチャートである。
【図１０】変数値変更コード検出処理のアルゴリズムのフローチャートである。
【図１１】関数コール間コード移動処理のアルゴリズムのフローチャートである。
【図１２】図５に示されるソースプログラムに対する変数の定義及び使用情報（d/u情報）の説明図である。
【図１３】関数コール間移動可能変数集合情報（FVCD情報）を保持するためのテーブル構造の説明図である。
【図１４】図５のソースプログラムに対するFVCD情報を保持するためのテーブル構造の説明図である。
【図１５】関数外コード修正処理のアルゴリズムのフローチャートである。
【図１６】ソースプログラムの元になる逐次プログラムの説明図である。
【図１７】最適化前のソースプログラムの説明図である。
【図１８】最適化後のソースプログラムの説明図である。
【図１９】最適化前のプログラムの実行の様子の説明図である。
【図２０】最適化前のプログラムの実行の様子の説明図である。
【図２１】関数コール間移動可能変数集合検出処理のアルゴリズムの説明図である。
【図２２】関数コール間コード移動及び関数外コード修正アルゴリズムの説明図である。
【図２３】コンパイラに入力されるソースプログラムの説明図である。
【図２４】最適化前のアセンブラコードの説明図である。
【図２５】最適化後のアセンブラコードの説明図である。
【図２６】最適化前のプログラムの実行の様子の説明図である。
【図２７】最適化後のプログラムの実行の様子の説明図である。
【図２８】コンパイラに入力されるソースプログラムの説明図である。
【図２９】最適化前のアセンブラコードの説明図である。
【図３０】最適化後のアセンブラコードの説明図である。
【図３１】コード生成部直後のアセンブラコードの説明図である。
【図３２】最適化前のプログラムの実行の様子の説明図である。
【図３３】最適化後のプログラムの実行の様子の説明図である。
【図３４】非特許文献１の技術に従ったコード移動の説明図である。
【図３５】非特許文献１の技術に従ったコード移動の説明図である。
【発明を実施するための形態】
【００１８】
１．実施の形態の概要
先ず、本願において開示される代表的な実施の形態について概要を説明する。代表的な実施の形態についての概要説明で括弧を付して参照する図面中の参照符号はそれが付された構成要素の概念に含まれるものを例示するに過ぎない。
【００１９】
〔１〕代表的な実施の形態に係るプログラム最適化方法は、関数コール間移動可能コード検出処理と、関数コール間コード移動処理と、コード生成処理とをコンピュータが実行する。
【００２０】
上記関数コール間移動可能コード検出処理は、与えられたプログラム中の関数内から同じ関数内にその関数の関数コールにまたがって移動可能なコードを検出する。
【００２１】
上記関数コール間コード移動処理は、上記関数コール間移動可能コード検出処理によって検出されたコードを上記関数の関数コールにまたがって同じ関数内に移動する。
【００２２】
上記コード生成処理は、上記関数コール間コード移動処理後のプログラムに基づいてオブジェクトコードを生成する。
【００２３】
図２の（Ａ）には、割込み関数によって関数Ｐが実行される場合が示される。破線で囲まれた部分はコードの集まりである。図２の（Ｂ）には、コードの集まりが、関数コールにまたがって移動した場合が示される。この場合の移動方向は、関数の入口方向とされる。尚、関数の出口方向（入口方向とは逆の方向）に移動することも可能である。
【００２４】
このようなコード移動が行われることで、関数１回あたりの実行時間の短縮を図ることができる。
【００２５】
例えば図２の（Ａ）に示されるように、割込みによって関数Ｐが実行され、破線で囲まれた部分が文の集まりである場合に、図２の（Ｂ）に示されるように、文の集まりを関数入り口方向へ、関数コールにまたがって移動することができる。このような処理によれば図７と図８で示されるように処理の高速化を期待できる。
【００２６】
図７には、１つの割込み関数内のコードを２つのＣＰＵで並列実行するように分割したコードの並列実行の様子が示され、図８には、図７のコードに対してこのプログラム最適化方法を適用した結果、得られたコードの実行の様子が示される。図７では、B1とC1（又は、B2とC2）は２つのＣＰＵ（中央処理装置）で同時に実行されるが、A1とD1（又は、A2とD2）はどちらか一方のＣＰＵでしか実行されない。結局、割込み関数を並列実行した時の実行時間は、A1+B1+D1（又は、A1+C1+D1、A2+B2+D2など）となる。
【００２７】
一方、図８では、B1とC1、及び、A1とD1が同時に実行される。結局、割込み関数を並列実行した時の実行時間は、B1+D1（又は、C1+D1、B2+D2など）となり、図７の場合よりも、関数１回あたりの実行時間が短縮されることにより、演算処理が高速になる。
【００２８】
関数コールにまたがるコード移動による演算処理の高速化は、マイクロコンピュータがマルチコアチップの場合でもシングルチップの場合でも期待できる。
【００２９】
特にモータの回転を制御するためのプログラムなどでは、同一関数が何度もコールされる場合が多い。そのようなプログラムのコンパイルにおいて、単一の関数内で関数コールにまたがるコード移動が行われた場合には、処理の高速化が顕著になる。
【００３０】
〔２〕上記関数コール間コード移動処理では、上記関数コール間移動可能コード検出処理によって検出されたコードが、上記関数の関数コールにまたがって同じ関数内におけるプログラムの空きサイクルに移動される。これにより、空きサイクルの有効利用を図ることができる。
【００３１】
〔３〕上記関数を割り込み関数とすることができる。尚、上記関数として、割込み関数とは別の関数を適用してもよい。
【００３２】
〔４〕上記関数コール間移動可能コード検出処理には、関数コール間移動可能変数集合検出処理と、変数値変更コード検出処理とを含めることができる。関数コール間移動可能変数集合検出処理は、上記関数コールにまたがって移動可能な条件を満たす変数の集合である関数コール間移動可能変数集合を検出する。変数値変更コード検出処理は、上記関数コール間移動可能変数集合検出処理で検出された関数コール間移動可能変数集合における関数中に変数を定義するコードを見つけ、上記コードの全てのオペランドが、上記関数コール間移動可能変数集合に含まれる変数又は定数である場合に、上記コードによって上記関数コール間移動可能変数集合を更新する。
【００３３】
この関数コール間移動可能変数集合検出処理と、変数値変更コード検出処理とが行われることで、プログラム中の関数内から同じ関数内にその関数の関数コールにまたがって移動可能なコードを容易に検出することができる。
【００３４】
〔５〕上記関数コール間移動可能変数集合検出処理は、所定の条件下で、スタティックで第１関数中に定義がある変数の集合を関数コール間移動可能変数集合として検出することができる。例えばスタティックで第１関数中に定義がある変数を参照する処理が、初期化コード、終了処理コード、上記第１関数内のコード、又は上記第１関数と同期を取る第２関数内で、上記第１関数内の変数を参照する区間が実行中のときに実行されるコードとされる場合に、上記第１関数中に定義がある変数の集合を関数コール間移動可能変数集合として検出する。
【００３５】
〔６〕上記関数コール間移動可能変数集合検出処理は、与えられた関数内のローカルなスタティック変数の集合を関数コール間移動可能変数集合として容易に検出することができる。
【００３６】
〔７〕上記コンピュータが実行する処理として、関数外コード修正処理を含めることができる。
【００３７】
上記関数外コード修正処理では、上記関数コール間コード移処理によって移動されたコードである第１コードと、与えられた関数に対する最初の関数コールよりも前に実行される第１プログラム部分との両方で参照される第１変数集合に対して、上記第１変数集合に含まれる変数を参照する上記第１プログラム部分のうちの最後の第１位置が検出される。
【００３８】
上記関数外コード修正処理では、上記第１コードの移動方向が関数の入口方向ならば、上記第１位置の直後に上記第１コードのコピーが追加され、上記第１コードの移動方向が関数の出口方向ならば、上記第１位置の直後に上記第１コード内の全ての変数値の変更を打ち消すコードが追加される。
【００３９】
上記関数外コード修正処理では、上記第１コードと、与えられた関数に対する最後の関数コールがある場合、それよりも後に実行される第２プログラム部分との両方で参照される第２変数集合に対して、上記第２変数集合に含まれる変数を参照する上記第２プログラム部分のうちの最初の第２位置が検出される。
【００４０】
上記関数外コード修正処理では、上記第１コードの移動方向が関数の入口方向ならば、上記第２位置の直前に上記第１コード内の全ての変数値の変更を打ち消すコードが追加され、上記第１コードの移動方向が関数の出口方向ならば、上記第２位置の直前に上記第１コードのコピーが追加される。
【００４１】
このように関数外コード修正処理では、上記第１コードの移動方向が関数の入口方向の場合と、上記第１コードの移動方向が関数の入口方向の場合との双方に対応することができ、オブジェクトコード生成に用いられるプログラムの最適化に有効とされる。
【００４２】
〔８〕上記コンピュータが実行する処理として、関数内初期化コード修正処理を含めることができる。
【００４３】
上記関数内初期化コード修正処理では、上記関数コール間コード移動処理によって移動される第１コードと、上記第１コードで定義される第１変数に対する第１初期化コードが検出される。
【００４４】
上記関数内初期化コード修正処理では、上記第１コードの移動方向が関数の入口方向ならば、上記第１初期化コードの直後に上記第１コードを置いた結果得られる上記第１変数の値を初期値とする第２初期化コードで上記第１初期化コードを置き換えられる。
【００４５】
上記関数内初期化コード修正処理では、上記第１コードの移動方向が関数の出口方向ならば、上記第１コードの直後における第１変数の値が上記第１初期化コードの直後における上記第１変数の値になるような上記コードの直前における上記第１変数の値を初期値とする第２初期化コードで上記第１初期化コードを置き換えられる。
【００４６】
このように関数内初期化コード修正処理では、上記第１コードの移動方向が関数の入口方向の場合と、上記第１コードの移動方向が関数の出口方向の場合の双方に対応することができ、オブジェクトコード生成に用いられるプログラムの最適化に有効とされる。
【００４７】
２．実施の形態の詳細
実施の形態について更に詳述する。
【００４８】
《実施の形態１》
図１には、マイクロコンピュータ（「マイコン」と略記する）の開発支援を行うためのマイコン開発システムが示される。
【００４９】
図１に示されるマイコン開発システム１は、パーソナルコンピュータ（ＰＣ）本体２、キーボード３、ディスプレイ４、ＲＯＭライタ５、及びマイコンチップ６を含む。キーボード３、ディスプレイ４、ＲＯＭライタ５は、ＰＣ本体２に接続される。マイコンチップ６は、ＲＯＭライタ５に結合される。
【００５０】
ＰＣ本体２は、ＣＰＵ（中央処理装置）１１、ハードディスク（ＨＤＤ）装置１２、ＲＡＭ（ランダムアクセスメモリ）１３を含む。ＣＰＵ１１は、演算処理のための所定のプログラムを実行する。ハードディスク装置１２には、上記ＣＰＵ１１で実行されるプログラムや、上記プログラムの実行において参照される各種情報などが格納されている。ＲＡＭ１３には、ハードディスク装置１２内の各種プログラムや各種情報が転送される。ＲＡＭ１３には、例えばコンパイラ１４、ソースプログラム１５、変数の定義及び使用情報（「d/u情報」という）１６、中間語１７、関数コール間移動可能変数集合情報（「FVCD情報」という）１８、オブジェクトコード１９、ロードモジュール２０、リンカ２１が格納される。
【００５１】
コンパイラ１４は、構文解析部１４１、関数コール間移動可能変数集合検出部１４２、変数値変更コード検出部１４３、関数コール間コード移動部１４４、関数外コード修正部１４５、コード生成部１４６を含む。
【００５２】
構文解析部１４１は、ソースプログラム１５を入力してd/u情報１６と中間語１７とを出力する。関数コール間移動可能変数集合検出部１４２は、d/u情報１６と中間語１７とを入力してFVCD情報１８を出力する。変数値変更コード検出部１４３は、中間語、d/u情報、及びFVCD情報１８を入力してFVCD情報１８を更新する。関数コール間コード移動部１４４は、中間語とFVCD情報を入力して中間語とFVCD情報を更新する。関数外コード修正部１４５は、中間語１７とFVCD情報１８を入力して中間語を更新する。コード生成部１４６は、中間語１７を入力してオブジェクトコードを出力する。リンカ２１は、オブジェクトコード１に基づいてロードモジュール２を形成する。
【００５３】
マイコンチップ６は、マルチコアチップとされ、二つのＣＰＵコア６１，６２を有する。また、マイコンチップ６には、ＲＯＭ６４、ＲＡＭ６５が設けられる。ＣＰＵコア６１，６２、ＲＯＭ６４、ＲＡＭ６５は、バス６３を介して互いに信号のやり取り可能に結合されている。リンカ２１によって形成されたロードモジュール２０は、ＲＯＭライタ５によってＲＯＭ６４へ書き込まれるようになっている。ＲＡＭ６５は、ＣＰＵコア６１やＣＰＵコア６２で演算処理が行われる際の作業領域などに使用される。ＣＰＵコア６１は、ＣＰＵ１とＬＭ（ローカルメモリ）１を含む。ＣＰＵコア６１は、ＣＰＵ２とＬＭ２を含む。
【００５４】
図３には、コンパイラ１４に入力されるソースプログラムの元になる逐次プログラムの一例が示される。
【００５５】
行１は変数の定義、行２は関数funcが割込み関数であることを示すプラグマである。行３から行９は関数funcの定義を表す。行６、７は変数ｘを引数とする関数コールを表す。
【００５６】
本プログラムにおいて、行６の関数ｆと行７の関数ｇは、この順に実行しても、異なるＣＰＵ上で同時並列的に実行しても実行結果は変わらない、と仮定する。例えば、関数ｆとgの中では引数ｘの値を変更することはなく、さらに、変数ｙ、ｚ、ｗの値も変えない、と仮定する。
【００５７】
次に、バリア同期関数について説明する。
【００５８】
バリア同期関数とは、複数のＣＰＵ上で動作するプログラム間で同期を取るための一つの関数である。
【００５９】
図４の（Ａ）には、ＣＰＵ１及びＣＰＵ２で実行されているプログラムにおいて、ＣＰＵ１とＣＰＵ２の間でバリア同期が成立する前の、各ＣＰＵにおけるプログラムカウンタ（「ＰＣ」と略記する）の位置が示される。
【００６０】
ＣＰＵ１における１２行目はバリア同期関数をコールしていることを示している。
【００６１】
引数のbは、複数のＣＰＵが同じバリア同期に参加することを示すバリア同期変数を表す。すなわち、複数のＣＰＵで同じバリア同期変数を引数としてバリア同期関数をコールすることによって、それらのＣＰＵの、それらのバリア同期関数コールの位置で、お互いにバリア同期を取ることを示す。
【００６２】
ＣＰＵ２における１７行目は、ＣＰＵ１における１２行目と同じバリア同期変数を引数にしており、これら２つの行の間でバリア同期がとられることが分かる。ＣＰＵ１において、ＰＣがバリア同期関数を指している。
【００６３】
図４の（ｂ）には、ＣＰＵ１とＣＰＵ２の間でバリア同期が成立したときの各ＰＣの位置が示される。
【００６４】
ＣＰＵ１とＣＰＵ２における両方のＰＣがバリア同期関数を指している。
【００６５】
図４の（Ｃ）には、ＣＰＵ１とＣＰＵ２との間でバリア同期が成立した直後の各ＰＣの位置が示される。ＣＰＵ１とＣＰＵ２における両方のＰＣがバリア同期関数の直後の処理を指している。
【００６６】
図５には、コンパイラ１４に入力されるソースプログラムの一例が示される。
【００６７】
このソースプログラムにおいて、行１から行３は変数の定義、行４は関数funcが割込み関数であることを示すプラグマ、行６から行９はバリア同期の初期化のための関数initializeの定義、行１０から行１６はＣＰＵ１で実行する割込み関数func1の定義、行１８から行２６はＣＰＵ２で実行する関数func2の定義である。
【００６８】
行８において、関数barrier_initは、バリア同期変数を初期化する関数である。引数ｂはバリア同期変数である。引数２はバリア同期が２つのＣＰＵ間で実施されることを示す。
【００６９】
関数initializeは、関数func1やfunc2よりも先にＣＰＵ１で実行される。関数func1は、ＣＰＵ１にある種の割込みが入った時に実行される。関数func2は、ＣＰＵ２が起動されて、ＣＰＵ１で関数initializeが実行された後に実行される。
【００７０】
このようにして関数をＣＰＵ１とＣＰＵ２で実行させた時のプログラムの実行結果は、図３のプログラムをＣＰＵ１で実行した時の実行結果と等しくなる。それは、次の理由による。
【００７１】
まず、initializeがＣＰＵ１で実行され、バリア同期変数が初期化される。
【００７２】
次に、行１２がＣＰＵ１で実行される。
【００７３】
次に、行１３と行２１の間でバリア同期が取られる。
【００７４】
次に、行１４と行２２が各々ＣＰＵ１とＣＰＵ２とで同時並列的に実行される。
【００７５】
図３を参照して説明したように、行１４の関数ｆと行２２の関数ｇはこの順に実行しても、複数のＣＰＵで同時並列的に実行しても結果は同じである。
【００７６】
関数ｆとｇの実行が終了した後、行１５と行２３の間で再びバリア同期が取られる。
【００７７】
次に、関数ｆは実行を終了し、関数ｇでは行２４がＣＰＵ２において実行され、次に、行２０、行２１に戻り、行２１のバリア同期を実行する。そして、次にＣＰＵ１が行１３のバリア同期を実行するまで待機する。
【００７８】
以上により、図５において関数initializeと関数ｆをＣＰＵ１で、関数ｇをＣＰＵ２で実行させた時のプログラムの実行結果は、図５のプログラムをＣＰＵ１で実行した時の実行結果と等しくなる。
【００７９】
図６には、最適化後のコードをソースプログラムで表現したものが示される。各行の意味、及び、各ＣＰＵでの実行手順は、図５に示さる場合と同じである。図６の出力コードが、図５に示されるのと相違するのは、図５における１２行目のX=X+1が１５行目に移動されている点である。
【００８０】
図７には、最適化前のプログラムの実行の様子が示される。
【００８１】
図７における縦方向の矢印は時刻の経過（時間）を示している。
【００８２】
上から順に、初期化の時刻、１回目の割込みが発生した時刻、２回目の割込みが発生した時刻を表す。矩形A0、A1、B1、A2、B2は、ＣＰＵ１で実行される処理を模式的に表している。矩形C1、D1、C2、D2は、ＣＰＵ２で実行される処理を模式的に表している。
【００８３】
A0は初期化処理で、図５の行１に対応する。
【００８４】
A1とB1は１回目の割り込みで実行される処理で、図５におけるfunc1に対応する。A2とB2は２回目の割り込みで実行される処理で、これも図５におけるfunc1に対応する。A1及びA2は、図５における行１２に対応する。B1及びB2は、図５における行１４に対応する。C1とD1は１回目の割り込みで実行される処理で、図５におけるfunc2に対応する。C2とD2は２回目の割り込みで実行される処理で、これも図５におけるfunc2に対応する。C1及びC2は、図５にける行２２に対応する。D1及びD2は、図５における行２４に対応する。B1とC1を表す矩形の上側を結ぶ破線は、バリア同期の成立を模式的に示したものであり、図５の行１３と行２１においてＣＰＵ１とＣＰＵ２の間でバリア同期が取られていることを示す。
【００８５】
B1とC1を表す矩形の下側を結ぶ破線は、バリア同期の成立を模式的に示したものであり、図５の行１５と行２３においてＣＰＵ１とＣＰＵ２の間でバリア同期が取られていることを示す。
【００８６】
尚、B2とC2を表す矩形の上側及び下側を結ぶ破線は、B1とC1を表す矩形の上側及び下側を結ぶ破線と同様である。
【００８７】
図８には、最適化後のプログラムの実行の様子が示される。
【００８８】
縦方向の矢印、初期化、割込み、矩形とそれを実行するＣＰＵ１とＣＰＵ２の関係、及び破線は、それぞれ、図７に示されるのと同様である。
【００８９】
A0は初期化処理で、図６の行１に対応する。A1とB1は、１回目の割り込みで実行される処理で、図６におけるfunc1に対応する。A2とB2は、２回目の割り込みで実行される処理で、これも図６におけるfunc1に対応する。A1及びA2は、図６における行１５に対応する。B1及びB2は、図６における行１３に対応する。C1とD1は、１回目の割り込みで実行される処理で、図６におけるfunc2に対応する。C2とD2は、２回目の割り込みで実行される処理で、これも図６におけるfunc2に対応する。C1及びC2は、図６における行２２に対応する。D1及びD2は、図６における行２４に対応する。B１とC１を表す矩形の上側を結ぶ破線は、図６における行１２と行２１においてＣＰＵ１とＣＰＵ２の間でバリア同期が取られていることを示す。同様に、B２とC２を表す矩形の下側を結ぶ破線は、図６の行１４と行２３においてＣＰＵ１とＣＰＵ２の間でバリア同期が取られていることを示す。
【００９０】
尚、B2とC2を表す矩形の上側及び下側を結ぶ破線の意味は、B1とC1を表す矩形の上側及び下側を結ぶ破線と同様である。
【００９１】
図１２には、図５に示されるソースプログラムに対する変数の定義及び使用情報（d/u情報）が示される。
【００９２】
１行目の"def"は"define"を省略したもので、この行より後の行に書かれた情報が変数の定義（definition）情報、すなわち、変数名、及び、その変数の値が変更されるプログラム中の位置を表している。
【００９３】
２行目から６行目は変数の定義情報を表す。例えば、２行目は変数xが図５のソースプログラム中の１行目と１２行目で定義されていることを示している。実際、1行目では"x=0"によって変数ｘの値は0に変更されており、１２行目では"x=x+1"の左辺において変数ｘの値は直前の値に１を加えた値に変更される。７行目は、この行より後の行に書かれた情報が変数の使用（use）情報、すなわち、変数名、及び、その変数の値が使われるプログラム中の位置を表す情報であることを示す。８行目から９行目は変数の使用情報を表している。例えば、8行目は変数ｘが、図５のソースプログラム中の１２行目、１４行目、及び、２２目で使用されていることを表している。実際、１２行目では"x=x+1"の右辺において変数ｘの値が使用され、１４行目では"y=f(x)"の右辺中の関数fの引数として変数ｘが使用され、２２行目では"z=g(x)"の右辺中の関数gの引数として変数ｘが使用される。
【００９４】
図１３には、FVCD情報を保持するためのテーブル構造が示される。
【００９５】
図１３中の各矩形は、各種のテーブルを示している。そしてこのテーブル間を接続する矢印は、ポインタを示している。これらのうち、f1,f2,f3は、関数を表すテーブルである。v11,v12,v21,v31は、変数を表すテーブルである。c111〜c312は、プログラム中のコードを表すテーブルである。d111〜d312は、テーブルc111〜c312中に書かれるフラグを示している。
【００９６】
ある関数（例えば、f1）中で定義のある変数（例えば、v11）を見つける処理の場合、図１３に示されるテーブルf1とテーブルv11を作成し、テーブルf1からテーブルv11へポインタを設定する。
【００９７】
また、関数（例えばf1）と変数（例えばv11）に対して関数f1中に変数v11を定義するコード（例えばc111）を見つける処理の場合、図１３において、テーブルc111を作成し、テーブルv11からテーブルc111へポインタを設定する。
【００９８】
同じ関数と同じ変数に対して上記と同様なコードc112が他に見つかれば、図１３においてテーブルc112を作成するが、関数と変数は上記のものを再利用すれば良いので、新たにこれらのテーブルは作成せず、また、すでに作成したコード用のテーブルc111と同じ属性のテーブルなので、テーブルc111からテーブルc112へポインタを設定する。これによって、同じ関数と同じ変数に対して、メモリを過大に消費することなく、複数のコード用テーブルを保持することができる。
【００９９】
同様な考え方によって、図１３のテーブルv12は、テーブルv11からリンクを設定することができる。また、アルゴリズム中において、関数情報を順番にたどれるように、関数テーブルf1,f2,f3の間にポインタを設定することができる。
【０１００】
さらに、関数（例えばf1）、変数（例えばv11）、コード（例えばc111）に対してフラグ（例えばd111）を設定する処理の場合、図１３において、テーブルc111の中のフィールドにd111の値を設定する。
【０１０１】
図１４には、図５のソースプログラムに対するFVCD情報を保持するためのテーブル構造が示される。
【０１０２】
図１４において、（Ａ）は、図９のアルゴリズム適用後のFVCD情報を保持するためのテーブル構造、（Ｂ）は、図１０のアルゴリズム適用後のFVCD情報を保持するためのテーブル構造、（Ｃ）は、図１１のアルゴリズム適用後のFVCD情報を保持するためのテーブル構造である。Func1，func2は、関数を表すテーブルである。X，Y，Z，Wは、変数を表すテーブルである。
【０１０３】
次に、上記構成のマイコン開発システム１の動作について説明する。
【０１０４】
先ず、コンパイラ１４の動作について説明する。
【０１０５】
構文解析部１４１は、図５のソースプログラムを入力して中間語と、図１２のd/u情報を出力する。ここで、中間語はコンパイラ１４内部で扱うデータ形式であり、本例ではこの中間語をソースプログラム形式で示している。すなわち、図５のソースプログラムに対する中間語は、図５のソースプログラムに等しくなる。
【０１０６】
関数コール間移動可能変数集合検出部１４２は、図５の中間語と、図１２のd/u情報を入力してFVCD情報を出力する。
【０１０７】
図９には、関数コール間移動可能変数集合検出部１４２で実行される関数コール間移動可能変数集合検出アルゴリズムが示される。
【０１０８】
本例では、中間語から関数ｆが探索され（Ｓ９１）、その関数ｆ内で変数ｖが探索される（Ｓ９２）。そして、変数ｖはスタティックで関数ｆ中に定義があるか否かの判別が行われる（Ｓ９３）。換言すれば、変数ｖは、グローバルな変数で、関数ｆ中で書き換えられる可能性があるか否かの判別が行われる。このステップＳ９３の判別において、変数ｖはスタティックで関数ｆ中に定義がある（ｙｅｓ）と判断された場合、変数ｖを参照する処理は、初期化コード、終了処理コード、関数ｆ内のコード、又は関数ｆと同期を取る関数ｇ内で関数ｆ内の変数ｖを参照する区間が実行中のときのみ実行されるコードであるか否かの判別が行われる（Ｓ９４）。上記ステップＳ９４の判別において、変数ｖを参照する処理は、初期化コード、終了処理コード、関数ｆ内のコード、又は関数ｆと同期を取る関数ｇ内で関数ｆ内の変数ｖを参照する区間が実行中のときのみ実行されるコードである（ｙｅｓ）と判断された場合、{ｆ，ｖ，φ，φ}がFVCD情報に登録される（Ｓ９５）。そして、関数ｆ中に変数は未だあるか否かの判別が行われる（Ｓ９６）。尚、上記ステップＳ９４の判別において、変数ｖを参照する処理は、初期化コード、終了処理コード、関数ｆ内のコード、又は関数ｆと同期を取る関数ｇ内で関数ｆ内の変数ｖを参照する区間が実行中のときのみ実行されるコードではない（ｎｏ）と判断された場合には、上記ステップＳ９５の登録が行われることなく、上記ステップＳ９６の判別が行われる。そして、上記ステップＳ９６の判別において、関数ｆ中に変数は未だある（ｙｅｓ）と判断された場合には、上記ステップＳ９２の処理に戻る。また、上記ステップＳ９６の判別において、関数ｆ中に変数は無い（ｎｏ）と判断された場合には、関数は未だあるか否かの判別が行われる（Ｓ９７）。この判別において、関数は未だある（ｙｅｓ）と判断された場合には、上記ステップ９１の処理に戻る。このようにして、全ての関数及び全ての変数についての探索が行われ、FVCD情報への登録が行われる。
【０１０９】
図５の中間語の場合には、次のように関数コール間移動可能変数集合検出が行われる。
【０１１０】
まず、関数initializeの探索が行われる。しかし、initialize中で値が定義される変数はないので、次の関数が探索され、関数func1が見つけられる。図５の中間語において、関数func1の範囲は１１行目から１６行目であり、図１４のd/u情報において、この範囲に定義を持つ変数として、ｘ（定義行は１２）とｙ（定義行は１４）が検出される。図１４のd/u情報において、変数ｘの全ての定義行は１と１２であり、１は図７より初期値代入文、１２は関数func1内の定義行なので、{func1,x,φ,φ}がFVCD情報として登録される。ここで、φは空集合を表し、FVCD情報のうち、コードテーブルは登録しないことを表す。一方、ｙは他に参照がないので、{func1,y,φ,φ}がFVCD情報に登録される。同様にして、関数func2、及び、staticかつ関数func2内で定義を持つ変数z、ｗが見つけられる。変数ｚは行２２と２４でのみ参照され、変数ｗは他で参照されないので、両方ともFVCD情報に登録される。
【０１１１】
このように関数コール間移動可能変数集合検出アルゴリズムが実行されることにより、図１４の（Ａ）に示されようなFVCD情報のテーブルがＲＡＭ１３内に形成される。
【０１１２】
変数値変更コード検出部１４３は、図５の中間語、図１２のd/u情報、及び図１４における（Ａ）のFVCD情報を取り込んで、FVCD情報を更新する。
【０１１３】
図１０には、変数値変更コード検出部１４３で実行される変数値変更コード検出処理のアルゴリズムが示される。
【０１１４】
この変数値変更コード検出処理では、先ず、FVCD情報から関数ｆと変数ｖとが探索される（Ｓ１０１）。そして、その関数ｆ中に変数ｖを定義するコードｃが見つけられる（Ｓ１０２）。次に、コードＣの全てのオペランドは、FVCD情報に含まれる変数又は定数か否かの判別が行われる（Ｓ１０３）。この判別において、コードｃの全てのオペランドは、FVCD情報に含まれる変数又は定数である（ｙｅｓ）と判断された場合には、FVCD情報中の（ｆ，ｖ，φ，φ）を（ｆ，ｖ，ｃ，φ）に更新する（Ｓ１０４）。そして、関数ｆ中に変数ｖを定義するコードは未だあるか否かの判別が行われる（Ｓ１０５）。この判別において、関数ｆ中に変数ｖを定義するコードは未だある（ｙｅｓ）と判断された場合には、上記ステップＳ１０２の処理に戻る。尚、上記ステップＳ１０３の判別において、コードＣの全てのオペランドは、FVCD情報に含まれる変数又は定数ではない（ｎｏ）と判断された場合にも、上記ステップＳ１０５の判別が行われる。上記Ｓ１０５の判別において、関数ｆ中に変数ｖを定義するコードは無い（ｎｏ）と判断された場合には、FVCD情報中に関数ｆと変数ｖは、未だあるか否かの判別が行われる（Ｓ１０６）。この判別において、FVCD情報中に関数ｆと変数ｖは未だある（ｙｅｓ）と判断された場合には、上記ステップＳ１０１の処理に戻る。上記ステップＳ１０６の判別において、FVCD情報中に関数ｆと変数ｖは無い（ｎｏ）と判断された場合にはこの変数値変更コード検出アルゴリズムが終了される。
【０１１５】
図１０のアルゴリズムに従えば、図１４の（Ａ）に示されるFVCD情報より、関数func1と変数xとが、次のように探索される。
【０１１６】
図７の中間語において変数ｘを定義するコード"x=x+1"（１２行目）を見つける。
【０１１７】
コード"x=x+1"に現れるオペランドはFVCD情報に含まれる変数ｘと定数１なので、FVCD情報に、{func1,x,x=x+1,φ}が登録される。
【０１１８】
同様にして、図１４の（Ａ）に示されるFVCD情報より、関数func1と変数ｙ、関数func2と変数ｚとｗを見つける。これらの変数の値を書き換える式は関数内にあるので、その詳細は図７のみでは不明だが、それぞれの関数の中身も解析することにより、各式の全てのオペランドはFVCD情報に含まれる変数又は定数と仮定する。よって、FVCD情報には、図１４の（Ｂ）に示されるように、{func1,y,y=f(x),φ}、{func2,z,z=g(x),φ}、{func2,w,w=h(z),φ}が登録される。
【０１１９】
関数コール間コード移動部１４４は、図５の中間語と図１４（Ｂ）のFVCD情報を取り込んで中間語を更新する。
【０１２０】
図１１には、関数コール間コード移動部１４４で実行される関数コール間コード移動処理のアルゴリズムが示される。
【０１２１】
この関数コール間コード移動処理では、先ず、図１４の（Ｂ）に示されるFVCD情報に基づいて、関数ｆと変数ｖとコードｃが探索される（Ｓ１１１）。そして、コードｃは、関数ｆの入口まで移動可能か否かの判別が行われる（Ｓ１１２）。
【０１２２】
上記ステップＳ１１２の判別において、コードｃは、関数ｆの入口まで移動可能である（ｙｅｓ）と判断された場合、（１）「コードｃ中の右辺の全変数」に対する関数ｆ内の最後の行と、（２）上記全変数に対する、図９における関数ｇ内の最後の参照行より後にある関数ｇ側の同期に対応する関数ｆ側の同期との二つの情報が求められる（Ｓ１１３）。そして、上記（１）と（２）のうち、より関数ｆの出口に近いほうと、関数ｆの出口との間に、コードｃを移動すると、コードの性能が改善されるか否かの判別が行われる（Ｓ１１４）。つまり、上記移動によって処理速度が向上するか否かの判別が行われる。この判別において、関数（ｃ）の移動によりコードの性能が改善される（ｙｅｓ）と判断された場合には、コードｃが上記範囲内の適当な位置へ移動され、（ｆ，ｖ，ｃ，φ）が（ｆ，ｖ，ｃ，ｅ）に変更される（Ｓ１１５）。そして、FVCD情報中に関数ｆと変数ｖとコードｃは未だあるか否かの判別が行われる（Ｓ１２０）。この判別において、FVCD情報中に関数ｆと変数ｖとコードｃは未だある（ｙｅｓ）と判断された場合には、上記ステップＳ１１１の処理に戻る。上記ステップＳ１２０の処理で、FVCD情報中に関数ｆと変数ｖとコードｃは無い（ｎｏ）と判断された場合には、この関数コール間コード移動処理が終了される。
【０１２３】
また、上記ステップＳ１１２の判別において、コードｃは関数ｆの入口まで移動できない（ｎｏ）と判断された場合には、コードｃは関数ｆの出口まで移動可能か否かの判別が行われる（Ｓ１１６）。このステップＳ１１６の判別において、コードｃは関数ｆの出口まで移動可能である（ｙｅｓ）と判断された場合には、（１）「コードｃ中の右辺の全変数」に対する関数ｆ内の最後の行と、（２）上記全変数に対する、図９における関数ｇ内の最後の参照行より後にある関数ｇ側の同期に対応する関数ｆ側の同期との二つの情報が求められる（Ｓ１１７）。そして、上記（１）と（２）のうち、より関数ｆの入口に近いほうと、関数ｆの入口との間に、コードｃを移動すると、コードの性能が改善されるか否かの判別が行われる（Ｓ１１８）。この判別において、関数（ｃ）の移動によりコードの性能が改善される（ｙｅｓ）と判断された場合には、コードｃが上記範囲内の適当な位置へ移動され、（ｆ，ｖ，ｃ，φ）が（ｆ，ｖ，ｃ，ｔ）に変更される（Ｓ１１９）。
【０１２４】
上記の処理は、FVCD情報中の関数ｆと変数ｖとコードｃの全てについて行われる（Ｓ１２０）。
【０１２５】
図１１のアルゴリズムに従えば、先ず、図１４の（Ｂ）のFVCD情報より、関数func1、変数x、コード"x=x+1"が探索される。コード"x=x+1はfunc1の入口にあるので、当然、入口まで移動可能である。
【０１２６】
次に、上記ステップＳ１１３における（１）として、コード"x=x+1"中の右辺の変数ｘの最後の使用行は１４行目である。
【０１２７】
また、上記ステップＳ１１３における（２）として、func2内のｘの最後の参照行は２２行目であり、それより後にあるfunc2側の同期は行１５であり、その同期に対応するfunc1の同期は行１５である。よって、上記（１）と（２）のうち、func1の出口により近いのは（２）の行１５である。その行１５とfunc1の出口である行１６との間にコード"x=x+1"を移動すると、コードの性能が改善されると判断したと仮定する。よって、コード"x=x+1"を行１５と行１６の間に移動し、{func1,x,"x=x+1",φ}を{func1,x,"x=x+1",e}に変更する。
【０１２８】
次に、図１４における（Ｂ）のFVCD情報より、関数func1、変数y、コード"y=f(x)"が探索される。
【０１２９】
コード"y=f(x)"は、行1３のバリア同期を超えることはできないので、入口まで移動できない。また、行１５のバリア同期を越えることもできないので、出口まで移動できない。
【０１３０】
次に、図１４の（Ｂ）のFVCD情報より、関数func2、変数z、コード"z=g(x)"を見つける。これもコード"y=f(x)"と同様にして、入口へも出口へも移動できない。
【０１３１】
次に、図１４の（Ｂ）のFVCD情報より、関数func2、変数w、コード"w=h(z)"を見つける。このコードも、while文を超えることができないので、入口へも出口へも移動できない。
【０１３２】
以上により、関数コール間コード移動処理が終了され、それにより、図１４における（ｃ）に示されるようなFVCD情報が得られる。
【０１３３】
図１５には、関数外コード修正部１４５で実行される関数外コード修正処理のアルゴリズムが示される。
【０１３４】
この関数外コード修正処理では、先ず、FVCD情報から関数ｆ、変数ｖ、コードｃ、フラグ（ｄ）を探索する（Ｓ１５１）。そして、関数ｆより前に実行され、変数ｖを参照するコードＩが探索される（Ｓ１５２）。このコードＩ中で変数ｖを参照する最後の位置が「Ｌｉ」とされる。
【０１３５】
次に、フラグ（ｄ）の値は「ｅ」か否かの判別が行われる（Ｓ１５３）。この判別において、フラグ（ｄ）の値は「ｅ」である（ｙｅｓ）と判断された場合には、コードｃが位置Ｌｉ直後にコピーされる（Ｓ１５４）。
【０１３６】
また、上記ステップＳ１５３の判別において、フラグ（ｄ）の値は「ｅ」ではない（ｎｏ）と判断された場合には、コードｃ内の全ての変数値変更を打ち消すコードが位置Ｌｉ直後にコピーされる（Ｓ１５５）。
【０１３７】
そして、関数ｆより前に実行され、変数ｖを参照するコードはまだあるか否かの判別が行われる（Ｓ１５６）。この判別において、変数ｖを参照するコードはまだある（ｙｅｓ）と判断された場合には、上記ステップＳ１５２の処理に戻される。また、上記ステップＳ１５６の判別において、変数ｖを参照するコードはない（ｎｏ）と判断された場合には、関数ｆより後で実行され、変数ｖを参照するコードｏが探索される（Ｓ１５７）。このコードｏ中で、変数ｖを参照する最後の位置を「Ｌｏ」とする。
【０１３８】
そして、フラグ（ｄ）の値は「ｔ」か否かの判別が行われる（Ｓ１５８）。この判別において、フラグ（ｄ）の値は「ｔ」である（ｙｅｓ）と判断された場合には、コードｃが位置Ｌｏ直後にコピーされる（Ｓ１５９）。
【０１３９】
また、上記ステップＳ１５８の判別において、フラグ（ｄ）の値は「ｔ」ではない（ｎｏ）と判断された場合には、コードｃ内の全ての変数値変更を打ち消すコードを位置Ｌｏ直前にコピーされる（Ｓ１６０）。
【０１４０】
そして、関数ｆより後で実行され、変数ｖを参照するコードはまだあるか否かの判別が行われる（Ｓ１６１）。この判別において、変数ｖを参照するコードはまだある（ｙｅｓ）と判断された場合には、上記ステップＳ１５７の処理に戻される。また、上記ステップＳ１６２の判別において、変数ｖを参照するコードはない（ｎｏ）と判断された場合には、この関数外コード修正アルゴリズムが終了される。
【０１４１】
図１５のアルゴリズムに従えば、図５の中間語と図１４における（Ｃ）のFVCD情報が関数外コード修正部１４５に取り込まれて、中間語が更新される。そして、図１４における（Ｃ）のFVCD情報より、関数func1、変数x、コード"x=x+1"、フラグeが探索される。図５において、関数func1より前に実行され、xを参照するコードIとして行１が見つけられる。このコードI中でｘを参照する最後の位置Ｌｉは行１となる。フラグ（ｄ）の値は「e」なので、"x=x+1"が行１直後にコピーされる。関数func1より前に実行され、xを参照するコードは他にないので、次に、関数ｆより後で実行され、変数ｖを参照するコードｏが探索される。しかし、そのようなコードは無いので、関数外コード修正アルゴリズムが終了される。
【０１４２】
以上の処理により、図６に示されるような中間語（最適化後のコード）が得られる。図６における行１５はコード"x=x+1"を図５の行１２から移動した結果であり、行１は図５における行１のｘに対する初期化コード"x=0"と初期化処理の出口との間にコード"x=x+1"を移動し、これら２行を使ってｘの値を計算した結果得られるコードである。初期値が０から１に変化しているのがわかる。
【０１４３】
実施の形態１によれば、図７（最適化前）においてA1及びA2で示したコード"x=x+1"は、図８（最適化後）においてA1及びA2の位置に移動する。図７において関数func1の1回あたりの実行時間はA1+C1+D1であるのに対して、図８において同時間はC1+D1となり、A1に対する処理時間が減っている。
【０１４４】
《実施の形態２》
実施の形態２では、関数内で定義される静的な変数（以下、「ローカルなスタティック変数」と呼ぶ）を有する場合の最適化について説明する。
【０１４５】
実施の形態２においても、図１に示されるマイコン開発システム１が用いられる。ただし、コンパイラ１４に入力されるソースプログラム１５は、実施の形態１の場合と相違する。
【０１４６】
図１６には、コンパイラ１４に入力されるソースプログラムの元になる逐次プログラムが示される。
【０１４７】
行１はグローバル変数の定義、行２は関数funcが割込み関数であることを示すプラグマ、行３から行１０は関数funcの定義を表す。行５は関数func1に含まれるローカルなスタティック変数ｘの定義を表す。行７と８は変数ｘを引数とする関数コールを表す。
【０１４８】
本プログラムでは、行７の関数ｆと行８の関数ｇはこの順に実行しても、同時並列的に異なるＣＰＵ上で実行しても実行結果は変わらないと仮定する。例えば、関数ｆとgの中では引数ｘの値を変更することはなく、さらに、変数ｙ、ｚ、ｗの値も変えない、と仮定する。
【０１４９】
図１７は、コンパイラ１４に入力されるソースプログラムの一例が示される。
【０１５０】
このソースプログラムにおいて、行１から行３はグローバルなスタティック変数の定義、行４は関数funcが割込み関数であることを示すプラグマである。行６から行９はバリア同期の初期化のための関数initializeの定義、行１０から行１８はＣＰＵ１で実行する割込み関数func1の定義である。行２０から行２８はＣＰＵ２で実行する関数func2の定義である。
【０１５１】
行８において、関数barrier_initはバリア同期変数を初期化する関数、引数ｂはバリア同期変数、引数２はバリア同期が２つのＣＰＵ間で実施されることを示す。
【０１５２】
行１２はローカルなスタティック変数ｘの定義を表す。
【０１５３】
行１３はローカルな変数ｘの値をグローバルな変数ｘ２に代入する文である。これは関数func1で更新した変数ｘの値を関数func2で参照するためには、グローバルな変数を使う必要があるからである。
【０１５４】
行２４の引数ｘ２は関数func1で定義したx2の値を関数func2で使用するためにｘをｘ２へ書き換えた結果を表す。
【０１５５】
関数initializeは関数func1やfunc2よりも前にＣＰＵ１で実行され、関数func1はＣＰＵ１にある種の割込みが入った時に実行され、func2はＣＰＵ２が起動後、ＣＰＵ１で関数initializeが実行された後に実行される。
【０１５６】
このようにして関数をＣＰＵ１とＣＰＵ２で実行させた時のプログラムの実行結果は、実施の形態１の場合と同様に、図１６のプログラムをＣＰＵ１で実行した時の実行結果と等しくなる。
【０１５７】
図１８には、出力コード（最適化後のコード）をソースプログラムで表現したものが示される。
【０１５８】
図１８における各行の説明、及び、各ＣＰＵでの実行方法は、図１７の場合と同じである。
【０１５９】
図１９には、最適化前のプログラムの実行の様子が示される。
【０１６０】
図２０には、最適化後のプログラムの実行の様子が示される。
【０１６１】
コンパイラ１４の動作について説明する。
【０１６２】
構文解析部１４１は、図１７に示されるソースプログラムを取り込んで、中間語を出力する。
【０１６３】
関数コール間移動可能変数集合検出部１４２は、中間語を入力してFVCD情報を出力する。
【０１６４】
図２１には、関数コール間移動可能変数集合検出部１４２で実行される関数コール間移動可能変数集合検出処理のアルゴリズムが示される。
【０１６５】
本例では、中間語から関数ｆが探索され（Ｓ２１１）、その関数ｆ内で、ローカルなスタティック変数ｖが探索される（Ｓ２１２）。そして、変数ｖは関数ｆ中に定義があるか否かの判別が行われる（Ｓ２１３）。このステップＳ２１３の判別において、変数ｖは関数ｆ中に定義がある（ｙｅｓ）と判断された場合、{ｆ，ｖ，φ，φ}がFVCD情報に登録される（Ｓ２１４）。そして、関数ｆ中に変数は未だあるか否かの判別が行われる（Ｓ２１５）。そして、上記ステップＳ９６の判別において、関数ｆ中に変数は未だある（ｙｅｓ）と判断された場合には、上記ステップＳ２１２の処理に戻る。また、上記ステップＳ２１５の判別において、関数ｆ中に変数は無い（ｎｏ）と判断された場合には、関数は未だあるか否かの判別が行われる（Ｓ２１６）。この判別において、関数は未だある（ｙｅｓ）と判断された場合には、上記ステップＳ２１１の処理に戻る。このようにして、全ての関数及び全ての変数についての探索が行われ、FVCD情報への登録が行われる。
【０１６６】
図１７の中間語の場合には、次のように関数コール間移動可能変数集合検出が行われる。
【０１６７】
図１７の中間語において、関数func1中にローカルなスタティック変数としてｘ（定義行は１２）が検出される。
【０１６８】
変数ｘの行１と１２に定義を持つので、{func1,x,φ,φ}がFVCD情報に登録される。
【０１６９】
関数func1中にはローカルなスタティック変数は他になく、プログラム中に他にローカルなスタティック変数を持つ関数は他にないので、関数コール間移動可能変数集合処理は、これで終了する。
【０１７０】
変数値変更コード検出部１４３は、図１７の中間語と上記FVCD={func1,x,φ,φ}を入力してFVCD情報を{func1,x,"x=x+1",φ}と更新する。この処理は、実施の形態１の場合と同様に、図１２のアルゴリズムを用いて行われる。
【０１７１】
関数コール間コード移動部１４４は、図１７の中間語と、図１４の（Ｂ）に示されるFVCD情報を入力して中間語を更新する。
【０１７２】
図２２には、関数コール間コード移動及び関数外コード修正アルゴリズムが示される。
【０１７３】
この関数コール間コード移動及び関数外コード修正アルゴリズムにおいて、先ず、FVCD情報から関数ｆと変数ｖとコードｃが探索される（Ｓ２１１）。そして、コードｃは、関数ｆの入口まで移動可能か否かの判別が行われる（Ｓ２２２）。この判別において、コードｃは、関数ｆの入口まで移動可能である（ｙｅｓ）と判断された場合には、「コードｃ中の右辺の全変数」に対する関数ｆ内の最後の参照行と関数ｆの出口との間にコードｃを移動すると、コードの性能が改善されるか否かの判別が行われる（Ｓ２２３）。この判別において、コードｃの移動により、コードの性能が改善される（ｙｅｓ）と判断された場合には、コードｃが上記範囲内の適当な位置へ移動される（Ｓ２２４）。そして、変数ｖの初期化コードの中の初期値を入力として、コードｃを計算した結果の値を初期化コードの初期値とされる（Ｓ２２５）。そして、FVCD情報中に、関数ｆと変数ｖとコードｃは未だあるか否かの判別が行われる（Ｓ２２６）。また、上記ステップＳ２２２の判別において、コードｃは関数ｆの入口まで移動できない（ｎｏ）と判断された場合や、上記ステップＳ２２３の判別において、コードｃの移動により、コードの性能が改善されない（ｎｏ）と判断された場合にも、上記ステップＳ２２６の判別が行われる。上記ステップＳ２２６の判別において、関数ｆと変数ｖとコードｃは未だある（ｙｅｓ）と判断された場合には、上記ステップＳ２２１の処理に戻る。また、上記ステップＳ２２６の判別において、関数ｆと変数ｖとコードｃは無い（ｎｏ）と判断された場合には、関数コール間コード移動及び関数外コード修正処理が終了される。
【０１７４】
図２２のアルゴリズムに従って、FVCD={func1,x,"x=x+1",φ}より、関数func1、変数x、コード"x=x+1"が探索される場合について説明する。
【０１７５】
図１８の中間語においてコード"x=x+1"はfunc1の入口にあるので、入口まで移動可能である。func1の出口（１８行目）とコード"x=x+1"中の右辺の変数ｘの最後の使用行（１６行目）のの間へコード"x=x+1"を移動するとコードの性能が改善されると判断したと仮定する。
【０１７６】
次に、コード"x=x+1"を行１７と１８の間に移動する。尚、行１６と１７の間に移動することも可能であるが、ここでは行１７と１８の間と仮定する。
【０１７７】
ｘの初期化コード中の初期値は０である。これを入力としてコード"x=x+1"を計算した結果は１となるので、ｘの初期化コード中の初期値を１とする。
【０１７８】
図１８は、この結果得られた中間語をソースプログラム形式で表現したものである。
【０１７９】
コード"x=x+1"は１７行目に移動し、１２行目の初期化コードは初期値１を設定しているのがわかる。FVCD情報中にｆとｖは他にないので、図２３の関数コール間コード移動及び関数外コード修正アルゴリズムはこれで終了する。
【０１８０】
尚、コード生成部１４６、リンカ２１、ＲＯＭライタ５の処理は、実施の形態１の場合と同じである。
【０１８１】
図１９には、最適化前の図１７のプログラムの実行の様子が示され、図２０には、最適化後の図１８のプログラムの実行の様子が示される。
【０１８２】
図１９においてA1及びA2で示したコード"x=x+1"は図２１においてA1及びA2の位置に移動する。図１９において関数func1の1回あたりの実行時間はA1+C1+D1であるのに対して、図２０において同時間はa1+C1+D1となり、a’1に対する処理時間が減っている。
【０１８３】
《実施の形態３》
実施の形態３では、図１におけるマイコンチップ６がシングルコアとされる場合を想定し、シングルコア向けのプログラムの最適化について説明する。
【０１８４】
図２３には、コンパイラ１４に入力されるソースプログラムが示される。
【０１８５】
このソースプログラムにおいて、行１はグローバル変数xとzの定義、行２はグローバル変数ｙの定義を表す。説明の都合上、変数yはvolatileと宣言した。この宣言は変数yに対して最適化を適用してはならないということをコンパイラ１４に教えるものである。
【０１８６】
行３は関数funcが割込み関数であることを示すプラグマであり、行４から行９は関数funcの定義を表す。行７は変数ｘを引数とする関数コールを表す。
【０１８７】
図２４には、最適化する前のアセンブラコードが示される。
【０１８８】
行１から３が図２４の行６に対応し、同様にして、行４から６が行７に、行７から９が行８に対応する。行１は変数ｘの値をレジスタr1にロードすることを示す。行２はレジスタr1と定数値１を加算した結果をレジスタr1に格納することを表す。行３はレジスタr1を変数ｘに格納することを表す。行４はレジスタr1の値をレジスタr5に移動することを表す。ここで、レジスタr5は関数呼び出しにおける第1引数を置くレジスタと仮定している。
【０１８９】
行５は関数ｆを呼び出すことを表す。行４と行５によって、関数ｆに引数ｘを渡すことができる。行６はレジスタr10の値を変数ｙに格納することを表す。ここで、レジスタr10は関数呼び出しにおける返値を格納するレジスタと仮定している。
【０１９０】
すなわち、図２４の行５によってレジスタr10に関数ｆの返値が格納され、この値は図２３の行７に従って変数yに格納される。行７から行９は各々、行１、行２、行３の説明と同様である。
【０１９１】
この図２４において、破線で包囲される、行１から３が後のアルゴリズムにおいて移動対象コードとなる。
【０１９２】
行７のコードと変数yのvolatile宣言との関係について説明する。
【０１９３】
行６を見ると、行６の実行後にはr10とyには同じ値が格納されていることがわかる。この時、コンパイラによる通常の最適化では行７は"move r10,r5"となる。レジスタ間データ移動の方がメモリ−レジスタ間データ移動よりも高速なためである。
【０１９４】
しかしながら、変数yがvolatile宣言されているため、行７には最適化は適用されず、メモリ上の変数ｙの領域からレジスタr5に値がロードされる。この時、行６と７の間には、ハザードと呼ばれる空きサイクルが生じる。これは行６でメモリに値が格納されるのを待って、行７で再びメモリからその値をレジスタにロードするためである。
【０１９５】
図２５には、最適化後のアセンブラコードが示される。
【０１９６】
図２５では、図２４の行１から３が行４から６に移動している。また、図２５の行１から３は、図２４の行４から６に対応している。行７から９は同じ行７から９に対応している。図２４の行４ではレジスタr1上に変数ｘの値があるので、その値をレジスタr5に移動しているが、本図の行１は開始行なので、レジスタr1には何の値がのっているか不明である。従って、変数ｘからレジスタr5に値をロードする命令に変更した。
【０１９７】
図２３のソースプログラムから図２５のアセンブラコードを得るアルゴリズムは、実施の形態１の場合と同様であるので、その説明を省略する。
【０１９８】
尚、図２４の行４でレジスタr1を使うmove命令が、図２５の行１では変数xを使うload命令になっているが、これは元々、コンパイラの処理途中ではどちらにおいても図２５の行１のようになっているのが、図２４ではそのコードに通常の最適化が適用されたためであり、これに関する特別な処理を追加する必要はない。
【０１９９】
図２６には、最適化前のプログラムの実行の様子がアセンブラコードを用いて示される。
【０２００】
図２６において、左の数字は実行サイクル数を示したものである。図２６において、右の命令列はアセンブラコードであり、各々の命令が実行されるサイクルの位置に命令を配置したものである。ただし、関数ｆの処理サイクルは１サイクルと仮定している。
【０２０１】
図２６より、行１と２の間にはロードにかかる時間に対する１サイクルの空きが、行６と７の間にはハザードに伴う３サイクルの空きがあることがわかる。
【０２０２】
以上によりこれらのコードの合計実行サイクルは、左の数字より１３サイクルであることがわかる。
【０２０３】
図２７には、最適化後のプログラムの実行の様子がアセンブラコードを用いて示される。
【０２０４】
左の数字は実行サイクル数を示したものである。右の命令列はアセンブラコードであり、各々の命令が実行されるサイクルの位置に命令を配置したものである。行４から６までの４サイクル分のコードを、行３と７の間の、ハザードによる３サイクル分の空きサイクルに移動したため、行４から６までの４サイクルが削減され、行３と７の間は元々３サイクルであったのが４サイクルとなり、１サイクルだけ増加される。結局、それらの差の３サイクルが削減されている。
【０２０５】
以上によりこれらのコードの合計実行サイクルは、左の数字より１０サイクルである。
【０２０６】
図２６と図２７より、本例の最適化によって、プログラムの実行サイクル数が３サイクルだけ減って、プログラム実行が高速になる。
【０２０７】
《実施の形態４》
実施の形態４では、関数の出口方向にコードを移動する場合について、シングルコアチップ向けのプログラムを使って説明する。尚、マルチコアチップ向けのプログラムにおいても同様に行い得る。
【０２０８】
図２８には、コンパイラ１４に入力されるソースプログラムが示される。
【０２０９】
行１はグローバル変数xとzの定義、行２はグローバル変数ｙの定義を表す。
【０２１０】
説明の都合上、変数yはvolatileと宣言した。この宣言は変数yに対しては最適化を適用してはならないということをコンパイラ１４に教えるものである。それ以降は、各関数の定義が示される。実施の形態１〜３までとの違いはどの関数も割込み関数ではない点である。
【０２１１】
図２９には、最適化前のアセンブラコードが示される。
【０２１２】
図２９の（Ａ）には、関数initに対するアセンブラコードが示される。
【０２１３】
本例では、レジスタr0に常に値0が格納されているアーキテクチャを仮定している。そのため、行１で変数ｘを0に初期化することができる。
【０２１４】
図２９の（Ｂ）には、関数funcに対するアセンブラコードが示される。
【０２１５】
行１から３が、図２８の行１６に対応する。同様にして、行４から１７が行７に、行８から１０が行１８に対応する。
【０２１６】
本例では、レジスタr5は関数呼び出しにおける第１引数を置くレジスタ、レジスタr6は関数呼び出しにおける第２引数を置くレジスタと仮定している。従って、行４から６は変数ｙを第２引数に、変数ｘを第１引数において関数ｆをコールすることを示す。
【０２１７】
図２９の（Ｂ）において、破線で包囲される、行８から１０が移動対象コードとなる。
【０２１８】
図２９の（Ｃ）には、関数finalに対するアセンブラコードが示される。
【０２１９】
図３０には、最適化後のアセンブラコードが示される。
【０２２０】
図３０の（Ａ）には、関数initに対するアセンブラコードが示される。
【０２２１】
図３０の（Ａ）において、行２から４が挿入されたコードである。これらは図２９の（Ｂ）における行８から１０のコードによる、変数ｘの値の変更を打ち消すコードである。すなわち、図２９の（Ｂ）における行８から１０のコードが変数ｘの値を１だけ増加させるコードであるのに対して、行２から４のコードは変数ｘの値を１だけ減少させるコードである。
【０２２２】
図３０の（Ｂ）には、関数funcに対するアセンブラコードが示される。
【０２２３】
図２９の（Ｂ）における行８から１０のコードが行４から６に移動している。
【０２２４】
図３０の（Ｃ）には、関数finalに対するアセンブラコードが示される。
【０２２５】
これらは、図２９の（Ｂ）における行８から１０のコードである。
【０２２６】
図３１には、コード生成部１４６直後のアセンブラコードが示される。
【０２２７】
図３１の（Ａ）には、関数initに対するアセンブラコードが示される。
【０２２８】
図３１の（Ａ）における行１には、図３１の（Ａ）における行１から３までをコンパイラが最適化した結果が示される。
【０２２９】
図３１の（Ｂ）には、関数funcに対するアセンブラコードが示される。
【０２３０】
このコードは、図３０の（Ｂ）におけるコードと同じである。
【０２３１】
図３１の（Ｃ）には、関数finalに対するアセンブラコードが示される。
【０２３２】
図３１の（Ｃ）における行２から３には、図３０の（Ａ）における行２から４までをコンパイラが最適化した結果が示される。
【０２３３】
先ず、コンパイラの動作について説明する。
【０２３４】
構文解析部１４１は、図２８のソースプログラムを取り込んで中間語を出力する。ここで、中間語は同じ図２８のソースプログラムで表される。
【０２３５】
関数コール間移動可能変数集合検出部１４２は、図２８の中間語を取り込んでFVCD情報を出力する。
【０２３６】
関数コール間移動可能変数集合検出処理のアルゴリズムは、図９に示されるものを適用することができる。
【０２３７】
図２８の中間語において、init、、func、finalが関数として検出される。
【０２３８】
関数initについては、スタティック変数ｘがあり、関数init中で定義されているが、変数ｘを処理するコードは、関数init、初期化コード（関数init自身）、終了コード（関数final）以外に関数funcがあるのでFVCD情報には登録されない。関数finalについては、スタティック変数ｘがあり、関数init中で定義されていないのでFVCD情報には登録されない。関数funcについては、スタティック変数ｘがあり、関数init中で定義されており、変数ｘを処理するコードは、関数func、初期化コード（関数init）、終了コード（関数final）以外にないので{func,x,φ,φ}がFVCD情報に登録される。他に該当する関数や変数はないので、図９の関数コール間移動可能変数集合検出処理のアルゴリズムはこれで終了する。
【０２３９】
変数値変更コード検出部１４３は、図２８の中間語とFVCD={func,x,φ,φ}を入力してFVCD情報を更新する。この処理には、図１０に示されるアルゴリズムを適用することができる。この結果、FVCD={func,x,"x=x+1",φ}となる。
【０２４０】
関数コール間コード移動部１４４は、図２８の中間語とFVCD={func,x,"x=x+1",φ}を入力して中間語を更新する。
【０２４１】
関数コール間コード移動部１４４での処理には、図１１に示されるアルゴリズムを用いることができる。
【０２４２】
まず、FVCD={func,x,"x=x+1",φ}より、関数func1、変数x、コード"x=x+1"を見つける。
【０２４３】
次に、図２８において、行１７で変数ｘを参照しているので、行１８のコード"x=x+1"はこれ以上、入口方向へ移動することができない。
【０２４４】
従って、入口方向へ移動可能か否かの判別処理では、移動不可能と判断される。
【０２４５】
次に、出口方向への移動可能性を判定する。行１８のコード"x=x+1"は関数funcの出口にあるので、出口まで移動可能である。
【０２４６】
次に、関数funcにおいて、その入口からたどって最初に変数ｘを参照するのは行１７である。従って、行１８のコード"x=x+1"は、関数funcの入口から行１７の直前までの間に移動可能である。
【０２４７】
次に、移動することによって、コードの性能が改善されるか否かを判定する。
【０２４８】
図２８の行１６と１７の間には、図２４を参照して説明したように、変数ｙに関するハザードがあるので、空きサイクルがある。従って、ここにコード"x=x+1"を移動することによって、空きサイクルが有効利用され、コード性能が改善される。
【０２４９】
よって、コード"x=x+1"を行１６と１７の間に移動し、FVCD情報を{func,x,"x=x+1",t}に変更する。これで関数コール間コード移動処理を終了する。
【０２５０】
関数外コード修正部１４５は、図２８における関数initとfinalに対する中間語とFVCD={func,x,"x=x+1",t}を入力してこれらの中間語を更新する。
【０２５１】
関数外コード修正処理には、図１５に示されるアルゴリズムを用いることができる。
【０２５２】
先ず、FVCD={func,x,"x=x+1",t}より、関数func1、変数x、コード"x=x+1"、フラグtを見つける。
【０２５３】
次に、funcより前に実行され、ｘを参照するコードIとして、関数init中の行１２を見つける。I中でｘを参照する最後の位置Liは図２９の行１２である。フラグの値はtであり、eでないので、"x=x+1"内の変数ｘの変更を打ち消すコード"x=x-1"を行１２直後へコピーする。
【０２５４】
関数funcより前に実行され、ｘを変更するコードは他にないので、次の処理へ進む。
【０２５５】
次に、funcより後で実行され、ｘを参照するコードOとして、関数finalを見つける。O中でｘを参照する最後の位置Loは図２８の行２２である。
【０２５６】
フラグの値はtなので、"x=x+1"を行２２直前へコピーする。
【０２５７】
関数funcより後で実行され、ｘを変更するコードは他にないので、次の処理へ進む。FVCD情報中に他のデータはないので、これで関数外コード修正処理を終了する。
【０２５８】
図３２には、図２９の（Ｂ）に示した、最適化前のプログラムの実行の様子がアセンブラコードを用いて示される。
【０２５９】
左の数字は実行サイクル数を示したものである。右の命令列はアセンブラコードであり、各々の命令が実行されるサイクルの位置に命令を配置したものである。ただし、関数ｆの処理サイクルは本説明と無関係なので、1サイクルと仮定している。
【０２６０】
図３２より、行1と２の間にはロードにかかる時間に対する１サイクルの空きが、行３と４の間にはハザードに伴う３サイクルの空きがあることがわかる。
【０２６１】
以上によりこれらのコードの合計実行サイクルは、左欄の数字より１５サイクルであることがわかる。
【０２６２】
図３３には、図３１の（Ｂ）に示した、最適化後のプログラムの実行の様子がアセンブラコードを用いて示される。
【０２６３】
行４から６までの４サイクル分のコードを、行３と７の間の、ハザードによる３サイクル分の空きサイクルに移動したため、行４から６までの４サイクルが削減され、行３と７の間は元々３サイクルであったのが４サイクルとなり、１サイクルだけ増加した。結局、それらの差の３サイクルが削減されているのがわかる。
【０２６４】
以上によりこれらのコードの合計実行サイクルは、左の数字より１２サイクルであることがわかる。
【０２６５】
図３２と図３３より、最適化によって、プログラムの実行サイクル数が３サイクルだけ減って、プログラム実行が高速になることがわかる。
【０２６６】
以上本発明者によってなされた発明を実施の形態に基づき具体的に説明したが、本発明は前記実施の形態に限定されるものではなく、その要旨を逸脱しない範囲で種々変更可能であることは言うまでもない。
【符号の説明】
【０２６７】
１  マイコン開発システム
２  パーソナルコンピュータ（ＰＣ）本体
３  キーボード
４  ディスプレイ
５  ＲＯＭライタ
６  マイコンチップ
１１  ＣＰＵ
１２  ハードディスク装置
１３  ＲＡＭ
１４  コンパイラ
１５  ソースプログラム
１６  変数の定義及び使用（d/u）情報
１７  中間語
１８  関数コール間移動可能変数集合（FVCD）情報
１９  オブジェクトコード
２０  ロードモジュール
２１  リンカ
６１  ＣＰＵコア
６２  ＣＰＵコア
６３  バス
６４  ＲＯＭ
６５  ＲＡＭ
１４１  構文解析部
１４２  関数コール間移動可能変数集合検出部
１４３  変数値変更コード検出部
１４４  関数コール間コード移動部
１４５  関数外コード修正部
１４６  コード生成部
【図１】
2014109849.tif 000003
【図２】
2014109849.tif 000004
【図３】
2014109849.tif 000005
【図４】
2014109849.tif 000006
【図５】
2014109849.tif 000007
【図６】
2014109849.tif 000008
【図７】
2014109849.tif 000009
【図８】
2014109849.tif 000010
【図９】
2014109849.tif 000011
【図１０】
2014109849.tif 000012
【図１１】
2014109849.tif 000013
【図１２】
2014109849.tif 000014
【図１３】
2014109849.tif 000015
【図１４】
2014109849.tif 000016
【図１５】
2014109849.tif 000017
【図１６】
2014109849.tif 000018
【図１７】
2014109849.tif 000019
【図１８】
2014109849.tif 000020
【図１９】
2014109849.tif 000021
【図２０】
2014109849.tif 000022
【図２１】
2014109849.tif 000023
【図２２】
2014109849.tif 000024
【図２３】
2014109849.tif 000025
【図２４】
2014109849.tif 000026
【図２５】
2014109849.tif 000027
【図２６】
2014109849.tif 000028
【図２７】
2014109849.tif 000029
【図２８】
2014109849.tif 000030
【図２９】
2014109849.tif 000031
【図３０】
2014109849.tif 000032
【図３１】
2014109849.tif 000033
【図３２】
2014109849.tif 000034
【図３３】
2014109849.tif 000035
【図３４】
2014109849.tif 000036
【図３５】
2014109849.tif 000037