golangをLLVMで実装(go2llvm)してみる(No:0 ミニマムスタート)
Googleが開発したgolang。特にCSP(Communicating Sequential Processes)に基づいたgoroutine等、マルチコア環境でのスケールなど、将来性があって楽しみ。
ただ残念ながらパフォーマンスが出ないという話が挙がってるらしい。
一例:コードによっては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利用は悪くない選択肢だと思う。
んじゃあgolangとLLVMの勉強がてら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
あ動いた、なんとかコンパイル通って、実行コードまで生成できた。
しかし最低限の実装時間で作るために、決め打ちコードと竹に木を継ぐをやってしまった。
さすがに竹に木を接いでる部分なんとかしないと、恥ずかしすぎて公開できない...。