なお、COINSの概要については、情報処理学会誌のVol.47, No.4(2006年4月号)以 降に 「21世紀のコンパイラ道しるべ ・・COINSをベースにして」と題して連載されてい る。

たとえば、ターゲットマシンを"x86"と指定し、実行環境をウィンドウズマシン の"cygwin"と指定することで、cygwinで実行されるコードを生成するコンパイラ となる。また、いろいろな最適化機能とその適用順序を指定することによって、 種々の最適化の実験をするコンパイラとすることも出来る。
C言語以外の言語のコンパイラは、この標準ドライバのサブクラスを作ることに よって容易に作成出来る。たとえば、Fortranコンパイラのドライバ coins.driver.F77Driverは標準ドライバのサブクラスであり、フロントエンドを 呼び出す部分をオーバライドしているだけである。それだけで、標準ドライバと 同じオプション指定機能を持ったドライバとなっている。
コンパイル過程の種々の情報を出力するためのオプション指定もある。
現在、SPARC, x86, ARM, MIPS, SH-4, PowerPC, Alpha, MicroBlaze, Thumb(ARMの16ビット命令系) の各マシンのコード生成部が 出来ている。それらのマシンの仕様は、 TMD(Target Machine Description)言語で、 2,000〜4,000行で書かれている。
hirOpt=cf/cpf/dce
とすれば"cf", "cpf", "dce"がこの順で実行される。
CoCo(COINS based Coarse-grain Parallelizing Compiler)はそのような 粗粒度並列化コンパイラである。
それを実現するために、まず、SIMD命令の仕様を、LIRを拡張したSIRで 厳密に記述した。それらはこれらは、COINSのソースアーカイブの d oc-ja/coins/instDesc 以下にテスト系や結果と共に置かれている。詳しくは、各記述中のコメントと、 README.TXT を参照されたい。
SIMD並列化は、以下のような手順で行われる。
なお、C言語などの「汎整数拡張(たとえば、char型のデータでも演算に使う時は int型に拡張する)」 の規則を遵守するとSIMD並列化が困難になるので、 遵守しなくても済むデータであるかどうかを判定するアルゴリズムを実装してあ る。
SIMD並列化はまだ完全な実用化のレベルには達していないが、x86/SSE2については、 いくつかの例題について成功しており、gccの5倍以上の性能が得られているものも ある。
命令選択に当たっては、TMDファイルには各命令のコストが記載されているので、 そのコストの和が最小になるような命令列をダイナミック・プログラミングで 選択している。
レジスタ割り付けアルゴリズムは、Graph Coloringアルゴリズムの改良型である George and AppelのIterated Register Coalescingをベースにしている。 さらに、SPARCの浮動小数点レジスタやintel x86のeax/ah,alレジスタを扱うため、 ペアレジスタを含むレジスタセットを効率よく割り付けられるよう拡張している。
レジスタに割り付けられない場合のspill候補を選ぶ基準としては、 新たに妨害指数(Disturbance Factor)を使う方法を考案した。 妨害指数とは、その変数の生存範囲において、参照・定義されている変数がいくつ あるかを示す数である。
また、バックエンドでは、最初から最後までLIR形式が保たれているので、 その機能をマシン独立な形で記述することも出来る。
現在は、レジスタ割り付け前と後の両方で命令スケジューリングをする機能と、 通常はメモリに割り付けられている大域変数をレジスタに割り付ける、 簡単なレジ スタプロモーションの機能、および、単純なループ(if文や関数呼び出しがないル ープ) に対するソフトウェア・パイプライニングの機能が実現されている。
図1-2と図1-3は、フリーのコンパイラで性能的にも定評のあるgccの最適化レベル2と COINSのCコンパイラとで目的コードの実行時間を比較したものである。 いずれの図もCOINSで最適化を何も指定しない場合の実行時間を1とした相対値で表 している。
図1-2は、SPECベンチマークで比較したものであり、マシンはx86 (Pentium 4)である。 COINSのバックエンドのレジスタ割り付けとそれに関連した基本最適化だけですでに 相当 良い性能が出ている。


図1-4は、ソースプログラムmatmult.cからHIRが生成された時の様子をCoVisで 表示したものである。図の左上は制御フローグラフ、左下は制御フローグラフに 関する情報、右上はHIR、右下はソースプログラムである。それぞれ赤や青の色 のついた部分が 対応している。この図の中央上のボタンが示すように、(1)HIRが生成された時、 (2)HIRでの最適化後、(3)LIRが生成された時、(4)LIRでの最適化後、 の4つの時点でこのような表示をすることが出来る。

図1-5は、コード生成過程のトレース表示をしたものである。左の欄にはトレース情報 をとった時点の名前が入っている。右上にはソースプログラム、右下には ある時点でのトレース情報が表示されている。右下の下半分あたりにLIRと マシン命令記述とのパターンマッチングの様子が示されている。 右下の上半分あたりには、そのパターンマッチングの前の時点での ある基本ブロックの中のLIRの列が表示されている。
そこにある[<<]をクリックすると、その基本ブロックが一つ前の時点で どうなっていたかを見ることが出来る。また、[>>]をクリックすると、 その基本ブロックが一つ後の時点でどうなるかを見ることが出来る。

COINSの一部を変更したり、新しいマシン記述を追加したりしたときに、 Cコンパイラが正常に働くかどうかをテストするためのテスト・スーツ が用意されている。 それはCOINSの"test/c"ディレクトリにあり、約1000個 (COINSのバージョン1.4.1以前は約700個)の小さな Cプログラムからなる。それらは Assign, Exp, If, Loopなどの多くのサブ・ディレクトリに 分けられている。 (testディレクトリにあるREADME.xxxファイルを参照)
これらのディレクトリには、 各テストプログラムをgccで実行した結果を示すファイルも 入っており、それを使って自動テストをする スクリプトも用意されている。
ただし、自動テストに適さないプログラムもある。 それは、構文エラーをチェックしたり、実装依存の機能をテストする ものであり、 ディレクトリ"test/c/unsupported"と "test/c-result-may-differ"に入っている。
なお、アーカイブファイルの
doc-en/README.testPrograms.en.txt
も参照されたい。
test/c/testdriver.shである。 これはテスト・スーツの中のプログラムを次々にコンパイル・実行し 期待される結果(gccでの結果)と一致するかをチェックし、 それらの情報をファイルに出力するスクリプトである。
cd ./classes -- COINSのルートディレクトリで、これをタイプする ../test/c/testdriver.sh -v ../test/c/*/*.c ../test/c/testdriver.sh -v ../test/c/*/*/*.c
最初のtestdriver.shの呼び出しにより、../test/cの直下の サブディレクトリにあるテストプログラムがテストされ、 次の呼び出しでは、もう1段下のサブディレクトリにあるものがテストされる。
テストの結果のファイルは、 COINSのルートディレクトリの直下に作られるディレクトリ
testdriver-yymmdd-hhmmss
の中に作られる。
ファイルtestdriver.shの中には、以下のような行がある。
if ! java coins.driver.Driver -coins:${TARGET}preprocessor=
'cpp -I../lang/c/include' -S -o $CCCOUT $i &>$CCCLOG
これがCOINSのDriverを呼び出すための行であるから、 この行を書き換えて任意のオプション指定をすることが出来る。
テスト・スーツのある1つのサブディレクトリだけを指定して テストをすることも出来る。たとえば、
../test/c/testdriver.sh -v ../test/c/Loop/*.c
として、Loopに関するテストだけをすることが出来る。
test/c/unsupportedと test/c-result-may-differサブディレクトリ以下のプログラム ではエラーとなる場合があるかも知れないが、それが エラーとなることをチェックするプログラムなら、正常な結果である。
テスト結果が"OK"となっても、さらに調べる必要があるものもある。 たとえばtest/c/Optやtest/c/OptAdd、test/c/TestSsaには最適化をテストする プログラムがあるから、最適化が行われているかどうかをチェックするには 生成されたコードを調べる必要がある。
sparcマシン以外でもテスト・スーツを使うためには
../test/c/testdriver.sh -v ../test/c/*/*.cの代わりに
../test/c/testdriver.sh -v -t x86-cygwin ../test/c/*/*.c
としたり、 testdriver.shの中でDriverを呼び出している行 のオプション指定で、マシンを指定すれば良い。
しかし、cygwinでは、環境によってはtestdriver.shが正常に 働かない場合があるので、 その代わりにcygwin専用に(COINSのバージョン1.4.2以降で)用意してある test/c/testdriverw.sh を使う方が無難である。 使い方はtestdriver.shと同じである。 コンパイラのオプションを変更するには
CLASS="coins.driver.Driver -S -b x86-cygwin
で始まる行で指定すれば良い。
現在、期待される結果として用意されているデータは、次のコマンドによって sparcのgccで得られたものである。
cd ./classes ../test/c/testprepare.sh ../test/c/*/*.c ../test/c/testprepare.sh ../test/c/*/*/*.c
テストプログラムを変更したり、追加した場合には このコマンドによってデータを更新しておく必要がある。
Sparcマシン以外でテストする場合は、そのマシンの gccコンパイラなどを使って、期待される結果のデータを置き換えておいた方が良い。 マシン依存の機能については、マシンによって結果が違う場合があるからである。
x86-cygwinマシンの場合は、test/c/testpreparew.shを使って 期待される結果のデータを置き換えておいた方が良い。 その使い方はtestdprepare.shと同じである。
その他のマシンについては、そのマシン用にtestprepare.sh の内容を変更して使う必要がある。