Scheme Compiler の勉強(39) - コンパイル速度の向上

自作 Scheme コンパイラもどきの続き。

一つめ。今まで labels だけ特別に扱ってたので、let の中に labels がある場合にコンパイルできなかった。だいぶ構成をいじって、コンパイルできるように修正。

二つめ。現在 (test-all) としてユニットテストを走らせると 700 秒くらい掛かっていた。これは長過ぎ。まだ Writing a Compiler in 24 small steps の 9 番目のステップにすぎないので、今後もっとテストは増え時間が掛かることを考えると、コンパイル速度を向上させたくなった。

今までのソースレベルでの構成。

  • compiler.scm コンパイラ本体。1300行。
  • llvmgen.scm S式で LLVM IR を書くためのライブラリ。300行。llvm-module クラスを提供。
  • tests-*.scm gauche.test を使ったユニットテスト。現在13種類。(ステップの9 より数が多いのはより細かくしているため)

今までのコンパイルと実行。単純で取り扱いやすい長所もあるのだけど、毎回全てをコンパイルしていた。

構成を変更して、以下のようにした。

  • runtime.ll ランタイム。LLVMScheme とで書かれている。Scheme オブジェクトの表示用関数、ヒープ管理のための変数など。
  • runtime.bc コンパイルされたもの。
  • compile-program, compile-llvm-module は同じ。ただし必要なS式のコンパイルだけになった。runtime.ll の関数を利用するため declare を追加。
  • llvm-as コマンドで .ll を .bc にコンパイル
  • llvm-link コマンドで runtime.bc とコンパイルした .bc とをリンク。
  • lli コマンドで .bc ファイルを実行。

これでユニットテストの実行が 150秒くらいに短縮された。代償として若干構成がややこしくなってしまったが。

今後の予定。まだ 3.9 は完全に終わっておらず、Scheme 側でのコード変換が残っている。3.10 が大きな山になるはず。どこまでいけるかなぁ。3.10 が終わったら、また実行ファイルを生成するようにしてベンチマークを取ってにやにやできるようになる、と嬉しい。
そもそもがコンパイラなんだし LLVM の最適化が効くし少なくともインタプリタには速度的に負けていないはず、と信じたいがさて。

  • 3.9 Closures
  • 3.10 Proper Tail Calls
  • 3.11 Complex Constants
  • 3.12 Assignment
  • 3.13 Extending the Syntax
  • 3.14 Symbols, Libraries, and Separate Combination
  • 3.15 Foreign Functions
  • 3.16 Error Checking and Safe Primitives
  • 3.17 Variable-arity Procedures
  • 3.18 Apply
  • 3.19 Output Ports
  • 3.20 Write and Display
  • 3.21 Input Ports
  • 3.22 Tokenizer
  • 3.23 Reader
  • 3.24 Interpreter