从llvm ir中删除完整的分支

时间:2016-11-19 18:37:01

标签: c++ llvm

ir中有一个我想完全删除的分支(condtion + branch + true_basic_block + false_basic_block)。它看起来像这样:

%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函数,或者我需要逐个删除指令。我一直在尝试后一种方式,但我已经看到来自&#34的所有错误;主要的基本块没有终结器&#34; to&#34;当def被销毁&#34;时使用遗骸,还有更多..我使用了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;
 }

这是输出:output

1 个答案:

答案 0 :(得分:1)

我不知道任何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);
}

此代码仅处理您显示的简单情况,then和else块无条件地跳转到公共连接块(对于任何更复杂的事情,它将失败并出现断言错误)。更复杂的控制流程要处理起来有点棘手,但您仍然可以使用此代码作为起点。