我有一个遗留的 C++ 应用程序,它构造了一个 C++ 对象树。我想使用 LLVM 调用类构造函数来创建所述树。生成的 LLVM 代码相当简单,看起来像以下重复序列:
; ...
%11 = getelementptr [11 x i8*]* %Value_array1, i64 0, i64 1
%12 = call i8* @T_string_M_new_A_2Pv(i8* %heap, i8* getelementptr inbounds ([10 x i8]* @0, i64 0, i64 0))
%13 = call i8* @T_QueryLoc_M_new_A_2Pv4i(i8* %heap, i8* %12, i32 1, i32 1, i32 4, i32 5)
%14 = call i8* @T_GlobalEnvironment_M_getItemFactory_A_Pv(i8* %heap)
%15 = call i8* @T_xs_integer_M_new_A_Pvl(i8* %heap, i64 2)
%16 = call i8* @T_ItemFactory_M_createInteger_A_3Pv(i8* %heap, i8* %14, i8* %15)
%17 = call i8* @T_SingletonIterator_M_new_A_4Pv(i8* %heap, i8* %2, i8* %13, i8* %16)
store i8* %17, i8** %11, align 8
; ...
其中每个T_
函数都是调用某些 C++ 构造函数的 C“thunk”,例如:
void* T_string_M_new_A_2Pv( void *v_value ) {
string *const value = static_cast<string*>( v_value );
return new string( value );
}
当然,thunk 是必要的,因为 LLVM 对 C++ 一无所知。这些T_
功能通过添加到ExecutionEngine
使用中ExecutionEngine::addGlobalMapping()
。
当这段代码是 JIT'd 时,JIT'ing 本身的性能很差。我已经使用. kcachegrind
我不明白所有的数字(而且这个 PDF 似乎没有在它应该包含逗号的地方包含逗号),但是如果你看一下左叉,底部的两个椭圆,Schedule...
被称为 16K 次,setHeightToAtLeas...
被称为 37K 次。在右分叉上,RAGreed...
被调用了 35K 次。
对于大多数简单的LLVM 指令序列来说,这些调用太多了。call
似乎有些不对劲。
关于如何提高 JIT'ing 性能的任何想法?