Index: llvm/trunk/lib/Transforms/Utils/LowerSwitch.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/LowerSwitch.cpp +++ llvm/trunk/lib/Transforms/Utils/LowerSwitch.cpp @@ -78,7 +78,7 @@ typedef std::vector CaseVector; typedef std::vector::iterator CaseItr; private: - void processSwitchInst(SwitchInst *SI); + void processSwitchInst(SwitchInst *SI, SmallVectorImpl &DeleteList); BasicBlock *switchConvert(CaseItr Begin, CaseItr End, ConstantInt *LowerBound, ConstantInt *UpperBound, @@ -116,16 +116,21 @@ bool LowerSwitch::runOnFunction(Function &F) { bool Changed = false; + SmallVector DeleteList; for (Function::iterator I = F.begin(), E = F.end(); I != E; ) { BasicBlock *Cur = I++; // Advance over block so we don't traverse new blocks if (SwitchInst *SI = dyn_cast(Cur->getTerminator())) { Changed = true; - processSwitchInst(SI); + processSwitchInst(SI, DeleteList); } } + for (BasicBlock* BB: DeleteList) { + DeleteDeadBlock(BB); + } + return Changed; } @@ -397,7 +402,7 @@ // processSwitchInst - Replace the specified switch instruction with a sequence // of chained if-then insts in a balanced binary search. // -void LowerSwitch::processSwitchInst(SwitchInst *SI) { +void LowerSwitch::processSwitchInst(SwitchInst *SI, SmallVectorImpl &DeleteList) { BasicBlock *CurBlock = SI->getParent(); BasicBlock *OrigBlock = CurBlock; Function *F = CurBlock->getParent(); @@ -518,7 +523,7 @@ BasicBlock *OldDefault = SI->getDefaultDest(); CurBlock->getInstList().erase(SI); - // If the Default block has no more predecessors just remove it. + // If the Default block has no more predecessors just add it to DeleteList. if (pred_begin(OldDefault) == pred_end(OldDefault)) - DeleteDeadBlock(OldDefault); + DeleteList.push_back(OldDefault); } Index: llvm/trunk/test/Transforms/LowerSwitch/delete-default-block-crash.ll =================================================================== --- llvm/trunk/test/Transforms/LowerSwitch/delete-default-block-crash.ll +++ llvm/trunk/test/Transforms/LowerSwitch/delete-default-block-crash.ll @@ -0,0 +1,27 @@ +; RUN: opt < %s -lowerswitch -disable-output + +; This test verify -lowerswitch does not crash after deleting the default block. + +declare i32 @f(i32) + +define i32 @unreachable(i32 %x) { + +entry: + switch i32 %x, label %unreachable [ + i32 5, label %a + i32 6, label %a + i32 7, label %a + i32 10, label %b + i32 20, label %b + i32 30, label %b + i32 40, label %b + ] +unreachable: + unreachable +a: + %0 = call i32 @f(i32 0) + ret i32 %0 +b: + %1 = call i32 @f(i32 1) + ret i32 %1 +}