[PATCH] D11995: [SimplifyCFG] Prune code from a provably unreachable switch default

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 12 15:09:42 PDT 2015


reames created this revision.
reames added reviewers: sanjoy, chenli, hans.
reames added a subscriber: llvm-commits.

As Sanjoy pointed out over in http://reviews.llvm.org/D11819, a switch on an icmp should always be able to become a branch instruction.  This patch generalizes that notion slightly to prove that the default case of a switch is unreachable if the cases completely cover all possible bit patterns in the condition.  Once that's done, the switch to branch conversion kicks in just fine.  

Note: Duplicate case values are disallowed by the LangRef and verifier.  

http://reviews.llvm.org/D11995

Files:
  lib/Transforms/Utils/SimplifyCFG.cpp
  test/Transforms/SimplifyCFG/switch-dead-default.ll

Index: test/Transforms/SimplifyCFG/switch-dead-default.ll
===================================================================
--- test/Transforms/SimplifyCFG/switch-dead-default.ll
+++ test/Transforms/SimplifyCFG/switch-dead-default.ll
@@ -0,0 +1,66 @@
+; RUN: opt %s -S -simplifycfg | FileCheck %s
+declare void @foo(i32)
+
+define void @test(i1 %a) {
+; CHECK-LABEL @test
+; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
+  switch i1 %a, label %default [i1 1, label %true
+                                i1 0, label %false]
+true:
+  call void @foo(i32 1)
+  ret void
+false:
+  call void @foo(i32 3)
+  ret void
+default:
+  call void @foo(i32 2)
+  ret void
+}  
+
+define void @test2(i2 %a) {
+; CHECK-LABEL @test2
+  switch i2 %a, label %default [i2 1, label %case1
+                                i2 2, label %case2
+                                i2 3, label %case3
+                                i2 4, label %case4]
+case1:
+  call void @foo(i32 1)
+  ret void
+case2:
+  call void @foo(i32 2)
+  ret void
+case3:
+  call void @foo(i32 3)
+  ret void
+case4:
+  call void @foo(i32 4)
+  ret void
+default:
+; CHECK-LABEL: default1:
+; CHECK-NEXT: unreachable
+  call void @foo(i32 0)
+  ret void
+}  
+
+; This one is a negative test - we know the value of the default,
+; but that's about it
+define void @test3(i2 %a) {
+; CHECK-LABEL @test3
+  switch i2 %a, label %default [i2 1, label %case1
+                                i2 2, label %case2
+                                i2 4, label %case4]
+case1:
+  call void @foo(i32 1)
+  ret void
+case2:
+  call void @foo(i32 2)
+  ret void
+case4:
+  call void @foo(i32 4)
+  ret void
+default:
+; CHECK-LABEL: default:
+; CHECK-NEXT: call void @foo
+  call void @foo(i32 0)
+  ret void
+}  
Index: lib/Transforms/Utils/SimplifyCFG.cpp
===================================================================
--- lib/Transforms/Utils/SimplifyCFG.cpp
+++ lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3248,6 +3248,23 @@
     }
   }
 
+  // If we can prove that the cases must cover all possible values, the 
+  // default destination becomes dead and we can remove it.
+  bool HasDefault =
+    !isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
+  if (HasDefault && DeadCases.empty() && 
+      SI->getNumCases() >= pow(2,Bits)) {
+    DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
+    BasicBlock *NewDefault = SplitBlockPredecessors(SI->getDefaultDest(),
+                                                    SI->getParent(), "");
+    SI->setDefaultDest(NewDefault);
+    SplitBlock(NewDefault, NewDefault->begin());
+    auto *OldTI = NewDefault->getTerminator();
+    new UnreachableInst(SI->getContext(), OldTI);
+    EraseTerminatorInstAndDCECond(OldTI);
+    return true;
+  }
+
   SmallVector<uint64_t, 8> Weights;
   bool HasWeight = HasBranchWeights(SI);
   if (HasWeight) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D11995.31988.patch
Type: text/x-patch
Size: 2879 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150812/98872fd7/attachment.bin>


More information about the llvm-commits mailing list