2017-06-12 201 views
0

我試圖刪除一系列指令(在[startIns,endIns之間指定))。 endIns可能與開始時不在同一個基本塊中。刪除llvm中的一系列指令

我不斷收到試圖刪除最後一個指令時,下面的錯誤 - 參考LLVM :: ilist_iterator,假的,假> ::運算符*()const的[OptionsT = LLVM :: ilist_detail :: node_options,IsReverse = false,IsConst = false]:聲明`!NodePtr-> isKnownSentinel()'失敗。

以下是我的C++代碼 -

//刪除之間的[開始所有指令,結束)

// startInst是在下面IR "%res = alloca i8 "

// endInst是"%resclone0 = alloca i10"在下面IR。

void deleteAllInstructionsInRange(Instruction* startInst,Instruction* endInst) 
    { 
     BasicBlock::iterator it(startInst); 
     BasicBlock::iterator it_end(endInst); 

     Instruction* currentInst ; 

     while(it != it_end) 
     { 
      currentInst = &*it; 

      ++it; 


      if (!currentInst->use_empty()) 
      { 
       currentInst->replaceAllUsesWith(UndefValue::get(currentInst->getType())); 
      } 

      currentInst->eraseFromParent(); 

     } 



    } 

以下是相關的IR

define i32 @test2() { 
entry: 
    %calltmp = call i32 @UInt() 
    %datasize = alloca i32 
    switch i32 %calltmp, label %sw.bb.0 [ 
    i32 1, label %sw.bb.1 
    i32 2, label %sw.bb.2 
    i32 3, label %sw.bb.3 
    ] 
; %res = alloca i8      ===> deleted 
    ;store i8 0, i8* %res     ===> deleted 
    ;%datasize1 = load i32, i32* %datasize ===> deleted 

    ret i32 %datasize1      ===> UNABLE to delete 

sw.bb.0:           ; preds = %entry 
    %resclone0 = alloca i10 
    store i10 0, i10* %resclone0 
    %datasize1clone0 = load i32, i32* %datasize 

任何幫助將不勝感激。

謝謝。

回答

0

首先看看this答案,以瞭解什麼是KnownSentinel()的意思。

我的猜測是,由於您在修改基本塊的同時迭代它,這是不安全的,並且您正在收到錯誤。

+0

我已經知道什麼是定點的LLVM,和你有關的事實,我修改了正確的BB,同時迭代。因此我簡單地將指令存儲在一個向量中,並在稍後刪除它們。 – mal

0

我的猜測是ret終止符並刪除它會使IR無效。 引用this question

每個基本塊必須以終止符結束。

我建議用uncondicional跳代替終止指令到下一個塊(未測試):

if (currentInst->isTerminator()) { 
    // works only if block has only one successor 
    currentInst->replaceAllUsesWith(
     builder->CreateBr(
      builder->GetInsertBlock()->getSingleSuccessor())); 
}