从llvm删除完整分支ir
问题描述:
在ir中有一个分支我想完全删除(condtion + branch + true_basic_block + false_basic_block)。它看起来像这样:从llvm删除完整分支ir
%4 = icmp sge i32 %2, %3
br i1 %4, label %5, label %7
; <label>:5 ; preds = %0
%6 = load i32* %x, align 4
store i32 %6, i32* %z, align 4
br label %9
; <label>:7 ; preds = %0
%8 = load i32* %y, align 4
store i32 %8, i32* %z, align 4
br label %9
; <label>:9 ; preds = %7, %5
%10 = call dereferenceable(140) %"class.std::basic_ostream"*@_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"class.std::basic_ostream"* dereferenceable(140) @_ZSt4cout, i8* getelementptr inbounds ([5 x i8]* @.str, i32 0, i32 0))
%11 = load i32* %z, align 4
%12 = call dereferenceable(140) %"class.std::basic_ostream"* @_ZNSolsEi(%"class.std::basic_ostream"* %10, i32 %11)
%13 = call dereferenceable(140) %"class.std::basic_ostream"* @_ZNSolsEPFRSoS_E(%"class.std::basic_ostream"* %12, %"class.std::basic_ostream"* (%"class.std::basic_ostream"*)* @_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_)
ret i32 0
现在把它删除,是否有removeBranch功能,或者我需要删除的指令一个接一个。我一直在尝试后一种方式,但我已经看到从“基本块在主没有终止符”的每个错误“使用仍然当def被破坏”,以及更多..我使用了erasefromparent,replaceinstwithvalue,replaceinstwithinst,removefromparent等
任何人都可以足以指出我在正确的方向吗?
这是我function_pass:
bool runOnFunction(Function &F) override {
for (auto& B : F)
for (auto& I : B)
if(auto* brn = dyn_cast<BranchInst>(&I))
if(brn->isConditional()){
Instruction* cond = dyn_cast<Instruction>(brn->getCondition());
if(cond->getOpcode() == Instruction::ICmp){
branch_vector.push_back(brn);
//removeConditionalBranch(dyn_cast<BranchInst>(brn));
}
}
/*For now just delete the branches in the vector.*/
for(auto b : branch_vector)
removeConditionalBranch(dyn_cast<BranchInst>(b));
return true;
}
答
我不知道任何RemoveBranch
实用功能的,但这样的事情应该工作。这个想法是删除分支指令,然后删除任何因此而死的东西,然后将初始块与连接块合并。
// for DeleteDeadBlock, MergeBlockIntoPredecessor
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
// for RecursivelyDeleteTriviallyDeadInstructions
#include "llvm/Transforms/Utils/Local.h"
void removeConditionalBranch(BranchInst *Branch) {
assert(Branch &&
Branch->isConditional() &&
Branch->getNumSuccessors() == 2);
BasicBlock *Parent = Branch->getParent();
BasicBlock *ThenBlock = Branch->getSuccessor(0);
BasicBlock *ElseBlock = Branch->getSuccessor(1);
BasicBlock *ThenSuccessor = ThenBlock->getUniqueSuccessor();
BasicBlock *ElseSuccessor = ElseBlock->getUniqueSuccessor();
assert(ThenSuccessor && ElseSuccessor && ThenSuccessor == ElseSuccessor);
Branch->eraseFromParent();
RecursivelyDeleteTriviallyDeadInstructions(Branch->getCondition());
DeleteDeadBlock(ThenBlock);
DeleteDeadBlock(ElseBlock);
IRBuilder<> Builder(Parent);
Builder.CreateBr(ThenSuccessor);
bool Merged = MergeBlockIntoPredecessor(ThenSuccessor);
assert(Merged);
}
此代码只处理您已经证明了简单的情况下,与当时和else块都无条件地转移到共同的跳跃加入块(它将失败,对任何事情更复杂的断言错误)。更复杂的控制流将会有点棘手,但您仍应该能够使用此代码作为起点。
我应该在遍历指令时还是在迭代循环之外调用removeConditionalBranch(在迭代过程中将其存储在向量中)?我在两种方法中都遇到了分段错误... –
@GauravSharma一般来说,在迭代它们时,不应该添加/删除指令。我只是测试了这个,我没有收到段错误,所以你必须提供更多的信息。 –
@ Ismail Badawi:我已经添加了pass和它的输出...请参阅.... –