我有一個外部(C)函數,我在LLVM IR中調用。 IR獲得JIT並且一切正常,但生成的代碼是性能敏感的,並且如果可能的話,我想刪除對我的外部函數的重複調用。該功能沒有副作用。是否有一個FunctionPass可以消除對該函數的多餘調用?有什麼我必須做的標記功能沒有副作用?LLVM標記函數爲const並刪除重複調用
謝謝!
我有一個外部(C)函數,我在LLVM IR中調用。 IR獲得JIT並且一切正常,但生成的代碼是性能敏感的,並且如果可能的話,我想刪除對我的外部函數的重複調用。該功能沒有副作用。是否有一個FunctionPass可以消除對該函數的多餘調用?有什麼我必須做的標記功能沒有副作用?LLVM標記函數爲const並刪除重複調用
謝謝!
根據http://llvm.org/docs/LangRef.html#function-attributes您可以指定只讀屬性或readnone的功能:
declare i32 @fn(i32 %i);
declare i32 @readonly_fn(i32 %i) readonly;
declare i32 @readnone_fn(i32 %i) readnone;
readonly
意味着函數不寫內存, readnone
意味着它甚至不讀內存(用於示例sin()可以被讀取)
如果一個函數不寫內存,它應該只返回基於參數的結果,因此是一個純函數(如果全局狀態不變)。在readnone函數的情況下,即使是全局狀態也會改變。
LLVM的優化可以優化呼叫爲只讀並且與EarlyCSE
通(公共子表達式消除)readnone功能,顯示在下面的例子:使用下列測試功能
define i32 @test_no_readonly()
{
%1 = call i32 @fn(i32 0)
%2 = call i32 @fn(i32 0)
%add = add i32 %1, %2
ret i32 %add
}
define i32 @test_readonly()
{
%1 = call i32 @readonly_fn(i32 0)
%2 = call i32 @readonly_fn(i32 0)
%add = add i32 %1, %2
ret i32 %add
}
define i32 @test_readnone()
{
%1 = call i32 @readnone_fn(i32 0)
%2 = call i32 @readnone_fn(i32 0)
%add = add i32 %1, %2
ret i32 %add
}
和運行
opt -early-cse -S readonly_fn.ll > readonly_fn_opt.ll
優化了讀取和讀取函數的第二個呼叫,從而生成
define i32 @test_no_readonly() {
%1 = call i32 @fn(i32 0)
%2 = call i32 @fn(i32 0)
%add = add i32 %1, %2
ret i32 %add
}
define i32 @test_readonly() {
%1 = call i32 @readonly_fn(i32 0)
%add = add i32 %1, %1
ret i32 %add
}
define i32 @test_readnone() {
%1 = call i32 @readnone_fn(i32 0)
%add = add i32 %1, %1
ret i32 %add
}
readonly_fn
和readnone_fn
函數只被調用一次,因此調用冗餘和調用。
通過-functionattrs
也可以將這些屬性添加到定義的功能