2010-3-20[土] LLVMで Cに変換してみるLLVM (llc) には Cソースコードを生成する機能があり、 C++ソースをCソースにすることができる模様。 ただし C++ から C への直接変換するのではなく、 一旦.ll/.bc(llvm用アセンブラソース,ビットコード)にしたものを、 llc.exe で(ターゲットCPU用アセンブラソースのかわりに) Cソースへ変換するというもの。 普通のアセンブラソースをCに変換した場合 オーバーヘッドは当然あり、 全体として問題になることはそうないかもだが (昔アセンブラソースからCに変換しての移植作業を何本かやったときの印象)、 何割(何倍)か遅くなっていてもおかしくない。 が llvmの .ll/.bc は、 普通のアセンブラソース/オブジェファイルでなく、 それより情報の多い中間コードなわけだし、 llvm-gcc & llc でオプティマイズしているため、 Cソースになっても元よりも速くなる可能性もありそう。 ということで、ちょっと、試してみた。 3/12にしたテストの1つ目。 C++でなく Cソースだけど。 (32bit色640x480→1920x1080拡大の50回生成の平均時間を求める奴. 実行環境は前回同様) llvm-gcc で llvm-gcc -S -o tmp.ll -emit-llvm -O2 -DNDEBUG test.c llvm-as -f -o tmp.bc tmp.ll llc -march=c -f -o test_dst.c tmp.bc
として test_dst.c を生成。
ヘッダ込みでコンパイルされた結果を C化してるのだから、
とりあえずstderrやwin-apiを使わないようにして(外部はC標準関数だけにして)回避。 ついでに 一旦 ldでまとめたものを.llに戻してから llc したものも試す。 llvm-gcc -S -o tmp.ll -emit-llvm -O2 -DNDEBUG test.c llvm-as -f -o tmp.ll.bc tmp.ll llvm-ld -o tmp.ll.exe tmp.ll.bc llvm-dis -f -o tmp.2.ll tmp.ll.exe.bc llvm-as -f -o tmp.2.bc tmp.2.ll llc -march=c -f -o test_dst.c tmp.2.bc 変換後のソースは、 これ。 前者の変換後ソースには元の関数を維持しているが、 後者の変換後ソースでは関数はmain()だけになっている。
が失敗したモノもあり、 実行できたものについての結果は以下 (単位:ミリ秒)
測定したタイミングによっては10,20ぐらいの差がでたりするかもで、 ざっくりとした感じに受け止めてもらうとして。 LLVMのツールであるllvm-gccではあまり差はないようだが、 他のコンパイラでの結果は、多少なりとも llc で変換したソースのほうが速くなってる雰囲気。 ただ前者と後者の変換については、モノによって多少違うも、 測定誤差でありえる範囲の差で、あまり違いはなさそうに思う (関数の分割具合の違いによるオプティマイズの トレードオフはあるだろうで、それが微妙に出てる可能性もあるけれど) 他のソースも試すべきたんだろうが、面倒で挫折... 他の例でも速くなるのか遅くなるのかどうかは結局ソースしだいと思うが、 それでも元のソースよりも速くなる例ができたわけだから (元ソースがヘボいのだろう、というのは置いといて)、 他の例でもそう酷く遅くなるようなことはないんじゃないかと期待.
C++ → C
で、 肝心の c++ → c . が、g++(clang)側のライブラリ(.a)に実体がある関数や機能を使った場合は、 コンパイルできても当然リンクが行えない状態。 bad_alloc みたいなライブラリものもそうだけれど、 virtual使ったり 例外を使った場合もそう。その他諸々。 C++らしい組み方をしてるとまずその手のものは使われてるだろうで... 足りてないリンク物の代用品をターゲット環境用にも用意できれば なんとかなるかもだが、大仕事だろう。(あるいはターゲット対応をllcに施すとか... どちらにしろ個人がチョロですむ作業ではなく)
I/Oを含まずtemplateを使ったような処理をベターCの範囲で書いてCに持ってくる、くらいなら...と思うも、やっぱ面倒だなあ.
あと、llc は c だけじゃなく c++ ソースも生成できる。
なんかすごい、というか、目が点になる、というか。
※と、まあ、発展途上のllvmを使っての感想なんで今後どうなっていくか、わからないけれど
他のC++ → C トランスレータついでのメモ。 元祖のC++実装の cfront は、Cソースへのトランスレータとして実装されている。 例外が実装されずに開発は終わっているが、 こちら でR3.0.3等いくつかのバージョンのソースが公開されている模様。 (使えるかどうかはしらない) 現行のC++をサポートしているだろうトランスレータとしては Comeau C/C++。 有料だけど低価格($50)。 面倒がって未購入だけど。 他環境向けのCソース生成ならこちらのほうがよい?(夢見てるかも)... といっても、ターゲット環境ごとの個別対応は必要だろうで、 Comeauのサイトで対応と書かれているのは比較的メジャーな環境のみのよう。 |