[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