diff --git a/lib/Transforms/Utils/LowerSwitch.cpp b/lib/Transforms/Utils/LowerSwitch.cpp index 3b447098af1..0e47626ce53 100644 --- a/lib/Transforms/Utils/LowerSwitch.cpp +++ b/lib/Transforms/Utils/LowerSwitch.cpp @@ -78,7 +78,7 @@ namespace { 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 @@ FunctionPass *llvm::createLowerSwitchPass() { 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 @@ unsigned LowerSwitch::Clusterify(CaseVector& Cases, SwitchInst *SI) { // 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 @@ void LowerSwitch::processSwitchInst(SwitchInst *SI) { 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); } diff --git a/test/Transforms/LowerSwitch/delete-default-block-crash.ll b/test/Transforms/LowerSwitch/delete-default-block-crash.ll new file mode 100644 index 00000000000..23588d56c33 --- /dev/null +++ b/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 +}