2012-11-12 96 views
1

我有一個遺留的C++應用程序,它構造了一個C++對象樹。我想使用LLVM調用類構造函數來創建所述樹。生成的LLVM代碼是相當直接的,看起來像的重複序列:LLVM JIT性能差

; ... 
%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++的構造函數,例如:

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::addGlobalMapping()添加到使用中的ExecutionEngine

當這段代碼被JIT調用時,JIT本身的性能非常差。我使用kcachegrind生成call-graph。我不明白所有的數字(這個PDF似乎不包括逗號),但是如果你看左邊的叉子,底部的兩個橢圓,Schedule...被稱爲16K倍,而setHeightToAtLeas...被稱爲37K倍。在右側的叉子上,RAGreed...被稱爲35K次。

這些太多的電話什麼什麼是call LLVM指令的簡單序列。有些東西似乎是可怕的錯誤。

關於如何提高JIT'ing性能的任何想法?

+0

這將是一個很好的問題到LLVM郵件列表我已經問LLv郵件列表llvmdev郵件列表 –

+0

。最初只有1個人回覆,但經過繼續討論後,停止了回覆。 –

+0

你有沒有機會用-o3編譯?另外,值得看看生成的代碼。您提到的功能 - 調度和寄存器分配(RAGreed) - 是LLVM IR已經降低並且不再像原始版本很長時間之後的代碼階段的一部分。 – Oak

回答

0

如果沒有JIT的工作方式或查看您試圖進行JIT的特定呼叫的巨大變化,另一個數量級不太可能發生。您可以在llc -O0上啓用-fast-isel-verbose(例如llc -O0 -fast-isel-verbose mymodule。[ll,bc]),並讓它告訴你它是否回落到用於生成指令的選擇dag。您可能需要再次分析並查看當前的熱點情況。

+0

當前的分析是[here](https://dl.dropbox.com/u/46791180/perf.png)。 –