[SimplifyCFG] avoid crashing after simplifying a switch (PR42737)

Later code in TryToSimplifyUncondBranchFromEmptyBlock() assumes that
we have cleaned up unreachable blocks, but that was not happening
with this switch transform.

llvm-svn: 367037
This commit is contained in:
Sanjay Patel 2019-07-25 17:01:12 +00:00
parent c6f2828c49
commit ee79dbb0c4
2 changed files with 55 additions and 8 deletions

View File

@ -4276,6 +4276,17 @@ static bool CasesAreContiguous(SmallVectorImpl<ConstantInt *> &Cases) {
return true;
}
static void createUnreachableSwitchDefault(SwitchInst *Switch) {
LLVM_DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
BasicBlock *NewDefaultBlock =
SplitBlockPredecessors(Switch->getDefaultDest(), Switch->getParent(), "");
Switch->setDefaultDest(&*NewDefaultBlock);
SplitBlock(&*NewDefaultBlock, &NewDefaultBlock->front());
auto *NewTerminator = NewDefaultBlock->getTerminator();
new UnreachableInst(Switch->getContext(), NewTerminator);
EraseTerminatorAndDCECond(NewTerminator);
}
/// Turn a switch with two reachable destinations into an integer range
/// comparison and branch.
static bool TurnSwitchRangeIntoICmp(SwitchInst *SI, IRBuilder<> &Builder) {
@ -4384,6 +4395,11 @@ static bool TurnSwitchRangeIntoICmp(SwitchInst *SI, IRBuilder<> &Builder) {
cast<PHINode>(BBI)->removeIncomingValue(SI->getParent());
}
// Clean up the default block - it may have phis or other instructions before
// the unreachable terminator.
if (!HasDefault)
createUnreachableSwitchDefault(SI);
// Drop the switch.
SI->eraseFromParent();
@ -4428,14 +4444,7 @@ static bool eliminateDeadSwitchCases(SwitchInst *SI, AssumptionCache *AC,
if (HasDefault && DeadCases.empty() &&
NumUnknownBits < 64 /* avoid overflow */ &&
SI->getNumCases() == (1ULL << NumUnknownBits)) {
LLVM_DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
BasicBlock *NewDefault =
SplitBlockPredecessors(SI->getDefaultDest(), SI->getParent(), "");
SI->setDefaultDest(&*NewDefault);
SplitBlock(&*NewDefault, &NewDefault->front());
auto *OldTI = NewDefault->getTerminator();
new UnreachableInst(SI->getContext(), OldTI);
EraseTerminatorAndDCECond(OldTI);
createUnreachableSwitchDefault(SI);
return true;
}

View File

@ -100,3 +100,41 @@ b:
%1 = call i32 @f(i32 1)
ret i32 %1
}
; This would crash because we did not clean up the
; default block of the switch before removing the switch.
define void @PR42737(i32* %a, i1 %c) {
; CHECK-LABEL: @PR42737(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[C:%.*]], true
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT: unreachable
;
entry:
br i1 %c, label %switch, label %else
else:
store i32 2, i32* %a
br label %switch
switch:
%cleanup.dest1 = phi i32 [ 0, %else ], [ 3, %entry ]
switch i32 %cleanup.dest1, label %unreach1 [
i32 0, label %cleanup1
i32 3, label %cleanup2
]
cleanup1:
br label %unreach2
cleanup2:
br label %unreach2
unreach1:
%phi2 = phi i32 [ %cleanup.dest1, %switch ]
unreachable
unreach2:
unreachable
}