2016-12-13 104 views
2

我試圖執行活性分析以刪除死指令。我知道isInstructionTriviallyDead()存在,但是,我想了解如何使用def-use(或use-def)鏈去除代碼。LLVM - 活性分析以刪除死代碼

我現在正在做的是我遍歷塊中的所有指令(使用inst_iterator),並且對於每條指令,循環遍歷它的所有用途。最終,如果指令已經沒有用了,那麼我認爲它死了,因此可以使用eraseFromParent()

這看起來像其刪除:

for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { 
    bool deadInst = true; 
    Instruction *inst = &*I; 


    for (User* pUser : inst->users()) { 
     // If we enter this loop, we have at least one use, so instruction isn't dead 
     deadInst = false; 
    } 

    // deadInst is true if we didn't enter the loop, so has no uses 
    if (deadInst) { 
     inst->eraseFromParent(); 
    } 
} 

的問題是,返回指令沒有與連結的本用途它(我相信有其他定義沒有用途)。但是,返回指令不應該被刪除,因爲它會導致語義錯誤的代碼。

我的一般方法是通過活性分析刪除說明嗎?我能做些什麼來確保退貨等指示不會被刪除?

任何指針都大加讚賞:)

回答

0

還檢查該指令是否是你提到llvm::isInstructionTriviallyDead終止指令(inst->isTerminator()

+0

嗨。謝謝回覆。你能提供更多的見解嗎?你的意思是諸如「if(deadInst &&!inst-> isTerminator())'嗎?什麼是終結者功能? – user3186023

1

,這是一個良好的開端,以得到什麼可以去掉一些見解,什麼不能。

您已經注意到您不能移除終止符指令。

此外,您不想刪除沒有用途但有副作用的說明。試想一下:

define void @bar()() { 
    call void @foo()() 
    ret void 
} 

你不想刪除call指令,即使它沒有用,因爲它可以,例如,寫入stdout或改變一些全局變量。 store也是一樣。檢查Instruction::mayHaveSideEffects的完整列表。

你的活躍度分析是過於激進:無用途是必要,但不足以條件被認爲是指令死。

如果你不想使用isInstructionTriviallyDead學習之用,我建議你周圍開始另一種方式:考慮當指令是死是肯定的(例如,alloca死時沒有使用,所以不add指令。 ..)然後推廣。

此外,只需循環遍歷所有指令並刪除死亡指令是不夠的。例如:

%2 = add i32 3, %1 
%3 = add i32 3, %2 

當你第一次遇到%2,它在%3一個使用,因此沒有死。但是,在消除%3後,%2也會死機。您可以通過迭代來解決這個問題,直到找不到新的死指令(無效,但很簡單)或某種遞歸過程。

+0

嗨。謝謝回覆。我能否在我的'if(deadInst)''條件中使用諸如'isTerminator()'或'mayHaveSideEffects()'這樣的條件來抵消生存分析的積極性?即我們可以假設,如果變量沒有用處,不是終止指令,也沒有副作用,那麼刪除它也是一樣。或者這仍然過於激進? – user3186023

+1

@ user3186023,將[着陸板](http://llvm.org/docs/LangRef.html#landingpad-instruction)添加到列表中,我認爲它已經足夠了,但是'llvm'也會嘗試保存帶有調試信息的指令,您可能也可能不想保留它們。 – deniss

+0

啊着陸墊 - 我對此瞭解甚少!我在'IsInstructionTriviallyDead()'的源代碼中看到了這個,但是無法理解它做了什麼,我也找不到任何文檔。是否有任何LLVM文檔可以解釋着陸臺是什麼? – user3186023