LLVMとの連携方法

他のコンパイラやVMが、LLVMを利用する方法をまとめます。

俺が読んだ範囲だと、
GHC、ISPC、ART、OpenJDK Sharkを紹介。
NVやAMDの方面はよくわからんです。

GHCとLLVMとの連携方法


概要:
GHCはLLVMのopt/llcコマンドをGHCから直接起動し、bitcodeのtext形式をpipeで流し込んで、アセンブラを生成するために利用する。

目的:
GHCが対応していないarchのアセンブラを出力したい。LLVMの最適化を利用した性能向上、ベクトル最適化を利用しGHCからSIMDコードを生成したい。

連携方法:
optやllcのコマンドをGHCから直接叩いて起動する。入出力はpipeを使う。

LLVMの改造および独自追加PASS:
LLVMのバックエンドを改造し、GHC向けの独自calling conventionであるcc10を追加している。LLVM本家にmerge済み。

LLVMのインターフェース経由の拡張:
LLVMのMetadataを使用し、TBAA(TypeBaseAliasAnalysis)の補助情報を与え、AliasAnlysisの精度を向上。
Metadataではデバッグ情報も設定可能だが、GHCからはデバッグ情報を設定していないため、LLVMを経由するとデバッグ不可能、今後の課題らしい。

入出力:
GHCのCmm形式からbitcodeのtext形式に変換し、opt | llcでpipe経由で流し、アセンブラを生成する。
入力の前処理として、Cmmからbitcodeのtext形式に変換する。
出力の後処理として、アセンブラのtext形式を、GHCのLLVM専用mangling処理に掛ける。その後object形式に変換する。

その他:
optとllcには、PATHが通ってないとコケる。
bitcodeのheaderはGHC内にハードコードされており、今のところARM専用として利用可能。

ISPCとLLVMとの連携方法


概要:
LLVMをISPCのバックエンドとして利用している。ISPCから直接アセンブラやオブジェクト生成まで行いたい場合に利用する。
ISPCがベクトル化したのち、LLVMのbitcodeの機種非依存のvector命令を生成する。LLVMはvector命令からx86/x64/ARM向けのコードを生成する。

目的:
LLVMを中間表現の最適化、アセンブラ、オブジェクト生成に利用したい。
ベクトル化はISPCが行い、それ以外の最適化と、ベクトル最適化、vector命令のコード生成に利用する。

連携方法:
LLVMのAPIを通して、PassManager経由で操作。独自PASSを5-6個定義。

LLVMの改造:
特になし。

LLVMのインターフェース経由の拡張:
ISPCの独自最適化PASSを5-6個追加し、PassManagerをISPCオリジナルの順番に組んで実行している。
SIMDのISAごとにintrinsicsを多数定義し、そのすべてがllファイルでハンドコーディングされている。
そのため、LLVMでの最適化時にllのintrinsicsはinline展開されているはず。
llファイルは、ISPCのmake時にある程度自動生成する。
ISPCのデバッグ情報をMetadata経由で設定しているため、ISPC->LLVMでコード生成したコードはデバッグ可能。

入出力:
ISPCのASTから、LLVMのBitcodeへ変換している。PassManager経由で、最適化とコード生成を行い、アセンブラもしくはオブジェクトを生成する。
入力の前処理として、ISPCのフロントエンドが走り、ベクトル化されたコードを、bitcodeへ変換する
出力の後処理は特になし。

その他:
様々なSIMD命令に対応しており、
NEON,SSE4,AVX1,2,XeonPhiの512bit SIMD、KnoghtLandingにも対応している。
ISPC専用のlibcやmathlibが定義されている。
XeonPhi系はLLVMが対応していないため、LLVMで最適化したのち、Intel Compiler向けのC++コードを逆生成する。

ARTとLLVMとの連携方法


概要:
ARTのportableコンパイラのバックエンドとして利用する。

目的:
LLVMの最適化、コード生成を利用して、x86/ARM/Mips向けに高速なコードを生成したい。
ARTをDalvik VMに置き換えたい。

LLVMの改造:
特になし。

LLVMのインターフェース経由の拡張:
独自最適化PASSであるGBCExpanderを定義している。Metadata経由で、TBAAの情報を与えて、AliasAnlysisの精度を向上。
BranchWeightを設定して分岐を改善可能。
デバッグ情報は設定していない。LLVMの生成したコードから、trampolineでARTのインタプリタに状態遷移すればデバッグ可能であるため不要。

入出力:
Dex形式からMIRに変換、MIR最適化ののち、bitcodeに変換し、オブジェクト生成まで行う。
入力の前処理として、MIRからbitcodeに変換し、GBCExpanderパスでintrinsicsの展開やruntime callへの置き換えを行う。
出力の後処理は特になし。

その他:
ShadowFrameやGCやSafePoint向けの処理は見どころだと思うが、まだよくわからん。

OpenJDK SharkとLLVMとの連携方法


概要:
OpenJDK HotSpotのJITコンパイラの一つとしてLLVMを利用する。

目的:
HotSpotにはClient/Serverコンパイラが存在するが、第3のJITコンパイラとしてShark(LLVMを利用)を定義し、HotSpotが未対応のarchでも動くようにする。
HotSpotからアセンブラ定義を取り除き、多数のArchへ対応する、Zeroプロジェクトの一環なのかな?

LLVMの改造:
特になし。

LLVMのインターフェース経由の拡張:
ちゃんと読んでない。たぶんない。

入出力:
JavaのBytecodeをメソッド単位でBitcodeに変換し、LLVMで最適化、コード生成、アセンブラを生成する。
入力の前処理としてBytecodeからbitcodeに変換するが、その間に色々やる。
簡単な脱仮想化(C1と同等、CHAあり)、exceptionの埋め込み、HotSpotのintrinsicsをLLVMのintrinsicsに変換、
safepoint用命令の挿入、GC向けには他に何かあったかな?
出力の後処理は特になし。

その他:
実はARTのモデルになったプロジェクトなのでは?


  • 最終更新:2013-12-23 15:17:50

このWIKIを編集するにはパスワード入力が必要です

認証パスワード