2016-11-19 3 views
1

В ветке есть ветка, которую я хочу полностью удалить (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; 
} 

Это выход: output

ответ

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); 
} 

Этот код обрабатывает только простой случай, вы показали, с тогдашними и либо еще блоками и прыжками безоговорочно присоединиться к общему блоку (он потерпит неудачу с ошибкой утверждения для чего-то более сложного). Более сложный поток управления будет немного сложнее, но вы все равно сможете использовать этот код в качестве отправной точки.

+0

Должен ли я вызвать removeConditionalBranch во время итерации по инструкциям или за пределами цикла итерации (сохраняя его в векторе во время итерации)? Я получаю ошибку сегментации в обоих направлениях ... –

+0

@GauravSharma В общем, вы не должны добавлять/удалять инструкции, итерации по ним. Я просто проверил это, и у меня нет segfault, поэтому вам нужно будет предоставить дополнительную информацию. –

+0

@ Исмаил Бадави: Я добавил пропуск и его вывод ... см. ... –