4.11. GHCのバックエンド

GHCは複数のコードジェネレータをバックエンドとして使うことができる。これは、GHCが使う中間表現のなかで最後のもの(Cmmと呼ばれる、単純でC風な言語)を取って、それを実行可能コードにコンパイルする。GHCは以下に述べるバックエンドに対応している。

4.11.1. ネイティブコード生成器(-fasm)

GHCのデフォルトのバックエンド。Cmmからアセンブリコードまでコンパイルするネイティブコード生成器である。最速のバックエンドであり、一般的に良いパフォーマンスのコードを生成する。共有ライブラリをコンパイルすることに最も良く対応している。-fasmフラグで選択できる。

4.11.2. LLVMコード生成器(-fllvm)

これはLLVMコンパイラを使って実行可能コードを生成する大体バックエンドである。一般的にはネイティブコード生成器とパフォーマンスで同等のコードを生成するが、場合によってはずっと速いコードを生成する。これは特に、vectorのようなパッケージを使った、数値的で配列を多用するコードについて真である。欠点は、コンパイル時間が有意に増えることである。LLVMバックエンドは-fllvmで選択できる。現在LLVM 2.8以降に対応している。

LLVMコード生成器が動作するためには、LLVMをインストールしてPATHに置かなければならない。具体的にはGHCはoptllcツールを呼ぶ必要がある。第二に、Mac OS XをLLVM 3.0以降と共に使っているなら、Clang c compilerコンパイラもPATHに置かなければならない。OS X 10.6以降にはデフォルトでclangとLLVMがどちらも含まれている。

LLVMとClangをインストールする方法。

  • Linux: パッケージ管理ツールを使う。
  • Mac OS X: 10.6ではLLVMとClangがデフォルトで含まれている。10.5では、OS XのためのパッケージマネージャであるHomebrewをインストールする。LLVMとClangのバイナリをここからダウンロードすることもできる。
  • Windows: LLVMとClangのバイナリをここからダウンロードする。

4.11.3. Cコード生成器(-fvia-C)

これはGHCの最古のコード生成器であり、GHC 7.0で非推奨化され、一般にはもはや含まれていない。-fvia-Cフラグで選択する。

Cコード生成器は、GHCが非レジスタ化モードでビルドされている場合にのみ対応されている。このモードは、GHCを新しいプラットフォームに移植することを助けるために、「ポータブルな」CコードをGHCが生成するモードである。しかしこのモードは普通よりずっと遅いコードを生成するので、あなたのGHCがこの方法でビルドされている可能性は低い。もしそうなら、おそらくネイティブコード生成器は利用不能である。ghc --infoを呼ぶことでこの情報を確認できる。

4.11.4. 非レジスタ化コンパイル

「非レジスタ化」という用語は実際には「純粋なCを介してコンパイルする」ということを意味している。つまり、通常GHCがプログラムを速くするために使うプラットフォーム固有の技を一部使わないということである。非レジスタ化コンパイルするときは、GHCは単純にgccでコンパイルできるCファイルを生成する。

GHCが非レジスタ化モードでコンパイルされている場合、LLVMおよびCコード生成器のみが利用可能である。ネイティブコード生成器は使えない。非レジスタ化モードにおいて、通常、LLVMにはCバックエンドに比べてかなり大きな性能上の恩恵がある。

非レジスタ化コンパイルはGHCを新しい機械に移植するときに便利である。これを使うと、予め必要なツールはgccasldだけになるし、さらに、非レジスタ化コンパイルが動作するようにするために書かなければならないプラットフォーム固有のコードは通常かなり少ないからである。

コンパイルの段階で非レジスタ化コンパイルを選ぶことはできない。GHCをビルドするときに適切なオプションを設定する必要があるのだ。詳細はGHCのビルドの手引きを参照せよ。

ghc --infoを呼ぶことで、GHCが非レジスタ化版かどうか確かめることができる。