[llvm] r367037 - [SimplifyCFG] avoid crashing after simplifying a switch (PR42737)
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 25 10:01:13 PDT 2019
Author: spatel
Date: Thu Jul 25 10:01:12 2019
New Revision: 367037
URL: http://llvm.org/viewvc/llvm-project?rev=367037&view=rev
Log:
[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.
Modified:
llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
llvm/trunk/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll
Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=367037&r1=367036&r2=367037&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Thu Jul 25 10:01:12 2019
@@ -4276,6 +4276,17 @@ static bool CasesAreContiguous(SmallVect
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(Swit
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(Swi
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;
}
Modified: llvm/trunk/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll?rev=367037&r1=367036&r2=367037&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll (original)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll Thu Jul 25 10:01:12 2019
@@ -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
+}
More information about the llvm-commits
mailing list