.NETのILの仕様(2)

コンパイラを自作ようと考えたことのある人ならばわかるだろうが、Pentiumアセンブラですら、レジスタ割付はかなり難しい問題だ。まして、レジスタにほとんど直交性のないプロセッサや、パイプラインを考慮した最適化をコンパイラに行なわせるのは結構辛いものがある。そのへんは単に実装が面倒くさいというだけではなく、学術的にも難しい問題だと言えると思う。


こういった部分はバグの温床にもなりやすい。MSC(Microsoft C:VCの前身)なんぞ最適化するとプログラムが動かないことがしょっちゅうであった。特に、定数の畳み込みまわりはバグの温床で、オーバーフローすることとか無視して畳み込みしてあるコードを見て愕然としたのを覚えている。

MSCのマニュアルには「最適化オプションを指定してコンパイルしてうまく動かない時は、最適化オプションを外してください」とかいう趣旨の文言が書かれていた。開発時はデバッグビルド(最適化なし)で行ない、製品リリース時に最適化をオンにしていたのだが*1、いざ製品としてリリースしようと思い最適化を有効にした途端に動かなくなるのだから、これでは一体何のための最適化だかわからない。まあ、天下のMicrosoftがそんな状況だったぐらいなので、コンパイラを趣味で作ってみようかいなってな日曜プログラマコンパイラの最適化についてまともなコードを書けなくとも無理はない。


その結果、コンパイラを自作するとしても「最適化はしなくてもいいか」みたいな方向になりがちである。そして、非常に遅いコードを生成するネイティブコンパイラが完成してしまう。遅いので自分でもほとんど使えないシロモノだ。*2

ところが、.NETのCILのコードを生成するだけならそういった苦労は一切ないのである。純粋にparserと簡単なコード生成部だけを書けばいいのだ。(つづく)

*1:製品としてリリースを行なうなら最適化も有効にしてビルドを行なってテストするのが当然だとか言わないで頂きたい。それはいまだから許されることであって、当時のマシンでMSCの最適化を有効にするとコンパイルに30分や1時間かかることはざらだったのだ。よって、開発段階ではなるべく最適化を無効にしてコンパイルするのが常であった。最適化をオンにするのは、製品リリースの寸前でのテストのみだ。それでひと通りテストして動かなければ、原因究明なんてやってられないので最適化をオフにした状態のバイナリで出荷してしまう、というのは日常茶飯事であった。いまの常識では考えられないことだが。

*2:それが嫌ならC++のコードを生成するようなコンパイラを作って最適化はC++コンパイラに任せるのも一つの方法なのだが、コンパイルするのに別途C++コンパイラが必要になってしまう。