Skip to content

Commit 98a2dab

Browse files
committed
[SimplifyCFG] Prune code from a provably unreachable switch default
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. Differential Revision: http://reviews.llvm.org/D11995 llvm-svn: 246125
1 parent a06c7e6 commit 98a2dab

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3248,6 +3248,23 @@ static bool EliminateDeadSwitchCases(SwitchInst *SI, AssumptionCache *AC,
32483248
}
32493249
}
32503250

3251+
// If we can prove that the cases must cover all possible values, the
3252+
// default destination becomes dead and we can remove it.
3253+
bool HasDefault =
3254+
!isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
3255+
if (HasDefault && Bits < 64 /* avoid overflow */ &&
3256+
SI->getNumCases() == (1ULL << Bits)) {
3257+
DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
3258+
BasicBlock *NewDefault = SplitBlockPredecessors(SI->getDefaultDest(),
3259+
SI->getParent(), "");
3260+
SI->setDefaultDest(NewDefault);
3261+
SplitBlock(NewDefault, NewDefault->begin());
3262+
auto *OldTI = NewDefault->getTerminator();
3263+
new UnreachableInst(SI->getContext(), OldTI);
3264+
EraseTerminatorInstAndDCECond(OldTI);
3265+
return true;
3266+
}
3267+
32513268
SmallVector<uint64_t, 8> Weights;
32523269
bool HasWeight = HasBranchWeights(SI);
32533270
if (HasWeight) {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
; RUN: opt %s -S -simplifycfg | FileCheck %s
2+
declare void @foo(i32)
3+
4+
define void @test(i1 %a) {
5+
; CHECK-LABEL @test
6+
; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
7+
switch i1 %a, label %default [i1 1, label %true
8+
i1 0, label %false]
9+
true:
10+
call void @foo(i32 1)
11+
ret void
12+
false:
13+
call void @foo(i32 3)
14+
ret void
15+
default:
16+
call void @foo(i32 2)
17+
ret void
18+
}
19+
20+
define void @test2(i2 %a) {
21+
; CHECK-LABEL @test2
22+
switch i2 %a, label %default [i2 0, label %case0
23+
i2 1, label %case1
24+
i2 2, label %case2
25+
i2 3, label %case3]
26+
case0:
27+
call void @foo(i32 0)
28+
ret void
29+
case1:
30+
call void @foo(i32 1)
31+
ret void
32+
case2:
33+
call void @foo(i32 2)
34+
ret void
35+
case3:
36+
call void @foo(i32 3)
37+
ret void
38+
default:
39+
; CHECK-LABEL: default1:
40+
; CHECK-NEXT: unreachable
41+
call void @foo(i32 4)
42+
ret void
43+
}
44+
45+
; This one is a negative test - we know the value of the default,
46+
; but that's about it
47+
define void @test3(i2 %a) {
48+
; CHECK-LABEL @test3
49+
switch i2 %a, label %default [i2 0, label %case0
50+
i2 1, label %case1
51+
i2 2, label %case2]
52+
53+
case0:
54+
call void @foo(i32 0)
55+
ret void
56+
case1:
57+
call void @foo(i32 1)
58+
ret void
59+
case2:
60+
call void @foo(i32 2)
61+
ret void
62+
default:
63+
; CHECK-LABEL: default:
64+
; CHECK-NEXT: call void @foo
65+
call void @foo(i32 0)
66+
ret void
67+
}
68+
69+
; Negative test - check for possible overflow when computing
70+
; number of possible cases.
71+
define void @test4(i128 %a) {
72+
; CHECK-LABEL @test4
73+
switch i128 %a, label %default [i128 0, label %case0
74+
i128 1, label %case1]
75+
76+
case0:
77+
call void @foo(i32 0)
78+
ret void
79+
case1:
80+
call void @foo(i32 1)
81+
ret void
82+
default:
83+
; CHECK-LABEL: default:
84+
; CHECK-NEXT: call void @foo
85+
call void @foo(i32 0)
86+
ret void
87+
}

0 commit comments

Comments
 (0)