summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp12
-rw-r--r--test/Transforms/SimplifyCFG/switch-dead-default.ll100
2 files changed, 105 insertions, 7 deletions
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp
index e00a96161cd..b02d2923b8e 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3423,11 +3423,17 @@ static bool EliminateDeadSwitchCases(SwitchInst *SI, AssumptionCache *AC,
}
// If we can prove that the cases must cover all possible values, the
- // default destination becomes dead and we can remove it.
+ // default destination becomes dead and we can remove it. If we know some
+ // of the bits in the value, we can use that to more precisely compute the
+ // number of possible unique case values.
bool HasDefault =
!isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
- if (HasDefault && Bits < 64 /* avoid overflow */ &&
- SI->getNumCases() == (1ULL << Bits)) {
+ const unsigned NumUnknownBits = Bits -
+ (KnownZero.Or(KnownOne)).countPopulation();
+ assert(0 <= NumUnknownBits && NumUnknownBits <= Bits);
+ if (HasDefault && DeadCases.empty() &&
+ NumUnknownBits < 64 /* avoid overflow */ &&
+ SI->getNumCases() == (1ULL << NumUnknownBits)) {
DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
BasicBlock *NewDefault = SplitBlockPredecessors(SI->getDefaultDest(),
SI->getParent(), "");
diff --git a/test/Transforms/SimplifyCFG/switch-dead-default.ll b/test/Transforms/SimplifyCFG/switch-dead-default.ll
index b54ea881d8b..e5c2ef65b31 100644
--- a/test/Transforms/SimplifyCFG/switch-dead-default.ll
+++ b/test/Transforms/SimplifyCFG/switch-dead-default.ll
@@ -2,7 +2,7 @@
declare void @foo(i32)
define void @test(i1 %a) {
-; CHECK-LABEL @test
+; CHECK-LABEL: @test
; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
switch i1 %a, label %default [i1 1, label %true
i1 0, label %false]
@@ -18,7 +18,7 @@ default:
}
define void @test2(i2 %a) {
-; CHECK-LABEL @test2
+; CHECK-LABEL: @test2
switch i2 %a, label %default [i2 0, label %case0
i2 1, label %case1
i2 2, label %case2
@@ -45,7 +45,7 @@ default:
; 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
+; CHECK-LABEL: @test3
switch i2 %a, label %default [i2 0, label %case0
i2 1, label %case1
i2 2, label %case2]
@@ -69,7 +69,7 @@ default:
; Negative test - check for possible overflow when computing
; number of possible cases.
define void @test4(i128 %a) {
-; CHECK-LABEL @test4
+; CHECK-LABEL: @test4
switch i128 %a, label %default [i128 0, label %case0
i128 1, label %case1]
@@ -85,3 +85,95 @@ default:
call void @foo(i32 0)
ret void
}
+
+; All but one bit known zero
+define void @test5(i8 %a) {
+; CHECK-LABEL: @test5
+; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
+ %cmp = icmp ult i8 %a, 2
+ call void @llvm.assume(i1 %cmp)
+ switch i8 %a, label %default [i8 1, label %true
+ i8 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
+}
+
+;; All but one bit known one
+define void @test6(i8 %a) {
+; CHECK-LABEL: @test6
+; CHECK: @llvm.assume
+; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
+ %and = and i8 %a, 254
+ %cmp = icmp eq i8 %and, 254
+ call void @llvm.assume(i1 %cmp)
+ switch i8 %a, label %default [i8 255, label %true
+ i8 254, 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
+}
+
+; Check that we can eliminate both dead cases and dead defaults
+; within a single run of simplify-cfg
+define void @test7(i8 %a) {
+; CHECK-LABEL: @test7
+; CHECK: @llvm.assume
+; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
+ %and = and i8 %a, 254
+ %cmp = icmp eq i8 %and, 254
+ call void @llvm.assume(i1 %cmp)
+ switch i8 %a, label %default [i8 255, label %true
+ i8 254, label %false
+ i8 0, label %also_dead]
+true:
+ call void @foo(i32 1)
+ ret void
+false:
+ call void @foo(i32 3)
+ ret void
+also_dead:
+ call void @foo(i32 5)
+ ret void
+default:
+ call void @foo(i32 2)
+ ret void
+}
+
+;; All but one bit known undef
+;; Note: This is currently testing an optimization which doesn't trigger. The
+;; case this is protecting against is that a bit could be assumed both zero
+;; *or* one given we know it's undef. ValueTracking doesn't do this today,
+;; but it doesn't hurt to confirm.
+define void @test8(i8 %a) {
+; CHECK-LABEL: @test8(
+; CHECK: switch i8
+ %and = and i8 %a, 254
+ %cmp = icmp eq i8 %and, undef
+ call void @llvm.assume(i1 %cmp)
+ switch i8 %a, label %default [i8 255, label %true
+ i8 254, 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
+}
+
+declare void @llvm.assume(i1)