golangをLLVMで実装(go2llvm)してみる(No:0 ミニマムスタート)

Googleが開発したgolang。特にCSP(Communicating Sequential Processes)に基づいたgoroutine等、マルチコア環境でのスケールなど、将来性があって楽しみ。


ハロー、goroutine!(1/2)- @IT


ただ残念ながらパフォーマンスが出ないという話が挙がってるらしい。


一例:コードによってはC言語のコードのパフォーマンスの1/6程度になってしまう。


http://shootout.alioth.debian.org/u64q/benchmark.php?test=mandelbrot&lang=all&box=1


おそらくチューニングが不十分な点もあると思う。んじゃあ最適化に強みをもつバックエンド(例LLVM等)を採用すればよいんじゃないと、単純に思ってしまった。


実際、golang開発チームは話題のLLVMの採用も検討した事もあるみたいだけど、メリットが見いだせず採用しなかったらしい。

我々は6gにLLVMを使うことも考えましたが、LLVMは大きすぎて遅く、パフォーマンス目標を達せそうにありませんでした。

FAQ - golang.jp
この一文だけでは何がネックになったのかは正直わからない。


でも、clang(LLVM)もFreeBSDコンパイラーに採用されたりAppleも力を入れ始めているから、LLVM自体の将来的な伸びしろは十分ある気がする。


それに、clangの最適化改善はLLVMを利用するコンパイラー全体に恩恵をもたらす事を考えると、LLVM利用は悪くない選択肢だと思う。


んじゃあgolangLLVMの勉強がてらLLVMを使ってgolangコンパイラー(go2llvm)を実装してみる事にした。


最初の目標はとにかく最小限のコードをコンパイルできる事。


そこまでたどり着けば「言語の機能のサポート」と「最適化処理の適用」をバランス見合いでやっていけばいつかは完成するはず(とっても楽観観測&日和見)


さて、相当問題あり(メモリモデル、並列処理、変数や配列...etcも無視)だけど、何とかgolang向け(go2llvm)試作版が完成したのでミニマムコード*1コンパイルテスト。

package main

func main() {
    return;
}

まずは、上記コードをpure golangコンパイル•実行してみる。

$ ./8g main.go 
$ ./8l -omain main.8
$ ./main ;echo $?;
0

OK。次にLLVMチュートリアル等を参考にして開発したgo2llvm(goソースをコンパイルしてLLVMバイトコードを生成)でコンパイルし実行してみる。

$./go2llvm 
; ModuleID = 'golang with llvm'

define i32 @main() {
entry:
  ret i32 0
}
$llc h.bc -o h 
$gcc h.s
$./a.out ; echo $?;
0

あ動いた、なんとかコンパイル通って、実行コードまで生成できた。


しかし最低限の実装時間で作るために、決め打ちコードと竹に木を継ぐをやってしまった。


さすがに竹に木を接いでる部分なんとかしないと、恥ずかしすぎて公開できない...。

*1:コレだけだと他言語のコンパイラーでも通るかも、とか突っ込みは無しの方向で