AOベンチの生成コードを見てみた
AOベンチをyarv2llvmでコンパイルした結果を見てみました。1万行以上になっていてびっくりです。
かなり悲しいコードが生成されていました。
%80 = load i32* %50 ; <i32> [#uses=1] %81 = inttoptr i32 %80 to { { i32, i32 }, double }* ; <{ { i32, i32 }, double }*> [#uses=1] %82 = getelementptr { { i32, i32 }, double }* %81, i64 0, i32 1 ; <double*> [#uses=1] %83 = load double* %82 ; <double> [#uses=1] %84 = call i32 @rb_float_new(double %83) ; <i32> [#uses=1]
わかりづらいですが、%80〜%83まででBOX化されたdoubleデータ(Rubyの内部表現)をUNBOX化してdoubleの生表現を取り出して、%84でその結果をRubyの内部表現にBOX化しています。つまり、結果的には何もしていないのですが、キャッシュを汚し、メモリをとってGCの起動を早めています。
何とか対策したいのですが、実は%80〜%83と%84は別関数でLLVMレベルの最適化の結果でくっついているだけです。なので、yarv2llvmレベルで対策しようとすると、関数間で解析しないといけなくてなかなか面倒です。勉強会までに解決方法が見つかればいいネタになるのですが、見つからなかった場合は見なかったことにしたいと思います 涙)。
追記
力任せで汚いけど解決の目処が立ちました。詳細はLLVM勉強会かソースで。