[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / Transforms / SimplifyCFG / switch-dead-default.ll
blob7f713182fde7abb393c01a706e90778a001ff436
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -S -passes='simplify-cfg<switch-to-lookup>' | FileCheck %s
3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4 declare void @foo(i32)
6 define void @test(i1 %a) {
7 ; CHECK-LABEL: @test(
8 ; CHECK-NEXT:    [[A_OFF:%.*]] = add i1 [[A:%.*]], true
9 ; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i1 [[A_OFF]], true
10 ; CHECK-NEXT:    br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]]
11 ; CHECK:       true:
12 ; CHECK-NEXT:    call void @foo(i32 1)
13 ; CHECK-NEXT:    ret void
14 ; CHECK:       false:
15 ; CHECK-NEXT:    call void @foo(i32 3)
16 ; CHECK-NEXT:    ret void
18   switch i1 %a, label %default [i1 1, label %true
19   i1 0, label %false]
20 true:
21   call void @foo(i32 1)
22   ret void
23 false:
24   call void @foo(i32 3)
25   ret void
26 default:
27   call void @foo(i32 2)
28   ret void
31 define void @test2(i2 %a) {
32 ; CHECK-LABEL: @test2(
33 ; CHECK-NEXT:    switch i2 [[A:%.*]], label [[DEFAULT1:%.*]] [
34 ; CHECK-NEXT:    i2 0, label [[CASE0:%.*]]
35 ; CHECK-NEXT:    i2 1, label [[CASE1:%.*]]
36 ; CHECK-NEXT:    i2 -2, label [[CASE2:%.*]]
37 ; CHECK-NEXT:    i2 -1, label [[CASE3:%.*]]
38 ; CHECK-NEXT:    ]
39 ; CHECK:       case0:
40 ; CHECK-NEXT:    call void @foo(i32 0)
41 ; CHECK-NEXT:    ret void
42 ; CHECK:       case1:
43 ; CHECK-NEXT:    call void @foo(i32 1)
44 ; CHECK-NEXT:    ret void
45 ; CHECK:       case2:
46 ; CHECK-NEXT:    call void @foo(i32 2)
47 ; CHECK-NEXT:    ret void
48 ; CHECK:       case3:
49 ; CHECK-NEXT:    call void @foo(i32 3)
50 ; CHECK-NEXT:    ret void
51 ; CHECK:       default1:
52 ; CHECK-NEXT:    unreachable
54   switch i2 %a, label %default [i2 0, label %case0
55   i2 1, label %case1
56   i2 2, label %case2
57   i2 3, label %case3]
58 case0:
59   call void @foo(i32 0)
60   ret void
61 case1:
62   call void @foo(i32 1)
63   ret void
64 case2:
65   call void @foo(i32 2)
66   ret void
67 case3:
68   call void @foo(i32 3)
69   ret void
70 default:
71   call void @foo(i32 4)
72   ret void
75 ; This one is a negative test - we know the value of the default,
76 ; but that's about it
77 define void @test3(i2 %a) {
78 ; CHECK-LABEL: @test3(
79 ; CHECK-NEXT:    switch i2 [[A:%.*]], label [[DEFAULT:%.*]] [
80 ; CHECK-NEXT:    i2 0, label [[CASE0:%.*]]
81 ; CHECK-NEXT:    i2 1, label [[CASE1:%.*]]
82 ; CHECK-NEXT:    i2 -2, label [[CASE2:%.*]]
83 ; CHECK-NEXT:    ]
84 ; CHECK:       case0:
85 ; CHECK-NEXT:    call void @foo(i32 0)
86 ; CHECK-NEXT:    ret void
87 ; CHECK:       case1:
88 ; CHECK-NEXT:    call void @foo(i32 1)
89 ; CHECK-NEXT:    ret void
90 ; CHECK:       case2:
91 ; CHECK-NEXT:    call void @foo(i32 2)
92 ; CHECK-NEXT:    ret void
93 ; CHECK:       default:
94 ; CHECK-NEXT:    call void @foo(i32 0)
95 ; CHECK-NEXT:    ret void
97   switch i2 %a, label %default [i2 0, label %case0
98   i2 1, label %case1
99   i2 2, label %case2]
101 case0:
102   call void @foo(i32 0)
103   ret void
104 case1:
105   call void @foo(i32 1)
106   ret void
107 case2:
108   call void @foo(i32 2)
109   ret void
110 default:
111   call void @foo(i32 0)
112   ret void
115 ; Negative test - check for possible overflow when computing
116 ; number of possible cases.
117 define void @test4(i128 %a) {
118 ; CHECK-LABEL: @test4(
119 ; CHECK-NEXT:    switch i128 [[A:%.*]], label [[DEFAULT:%.*]] [
120 ; CHECK-NEXT:    i128 0, label [[CASE0:%.*]]
121 ; CHECK-NEXT:    i128 1, label [[CASE1:%.*]]
122 ; CHECK-NEXT:    ]
123 ; CHECK:       case0:
124 ; CHECK-NEXT:    call void @foo(i32 0)
125 ; CHECK-NEXT:    ret void
126 ; CHECK:       case1:
127 ; CHECK-NEXT:    call void @foo(i32 1)
128 ; CHECK-NEXT:    ret void
129 ; CHECK:       default:
130 ; CHECK-NEXT:    call void @foo(i32 0)
131 ; CHECK-NEXT:    ret void
133   switch i128 %a, label %default [i128 0, label %case0
134   i128 1, label %case1]
136 case0:
137   call void @foo(i32 0)
138   ret void
139 case1:
140   call void @foo(i32 1)
141   ret void
142 default:
143   call void @foo(i32 0)
144   ret void
147 ; All but one bit known zero
148 define void @test5(i8 %a) {
149 ; CHECK-LABEL: @test5(
150 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[A:%.*]], 2
151 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
152 ; CHECK-NEXT:    [[A_OFF:%.*]] = add i8 [[A]], -1
153 ; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1
154 ; CHECK-NEXT:    br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]]
155 ; CHECK:       true:
156 ; CHECK-NEXT:    call void @foo(i32 1)
157 ; CHECK-NEXT:    ret void
158 ; CHECK:       false:
159 ; CHECK-NEXT:    call void @foo(i32 3)
160 ; CHECK-NEXT:    ret void
162   %cmp = icmp ult i8 %a, 2
163   call void @llvm.assume(i1 %cmp)
164   switch i8 %a, label %default [i8 1, label %true
165   i8 0, label %false]
166 true:
167   call void @foo(i32 1)
168   ret void
169 false:
170   call void @foo(i32 3)
171   ret void
172 default:
173   call void @foo(i32 2)
174   ret void
177 ;; All but one bit known one
178 define void @test6(i8 %a) {
179 ; CHECK-LABEL: @test6(
180 ; CHECK-NEXT:    [[AND:%.*]] = and i8 [[A:%.*]], -2
181 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], -2
182 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
183 ; CHECK-NEXT:    [[A_OFF:%.*]] = add i8 [[A]], 1
184 ; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1
185 ; CHECK-NEXT:    br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]]
186 ; CHECK:       true:
187 ; CHECK-NEXT:    call void @foo(i32 1)
188 ; CHECK-NEXT:    ret void
189 ; CHECK:       false:
190 ; CHECK-NEXT:    call void @foo(i32 3)
191 ; CHECK-NEXT:    ret void
193   %and = and i8 %a, 254
194   %cmp = icmp eq i8 %and, 254
195   call void @llvm.assume(i1 %cmp)
196   switch i8 %a, label %default [i8 255, label %true
197   i8 254, label %false]
198 true:
199   call void @foo(i32 1)
200   ret void
201 false:
202   call void @foo(i32 3)
203   ret void
204 default:
205   call void @foo(i32 2)
206   ret void
209 ; Check that we can eliminate both dead cases and dead defaults
210 ; within a single run of simplify-cfg
211 define void @test7(i8 %a) {
212 ; CHECK-LABEL: @test7(
213 ; CHECK-NEXT:    [[AND:%.*]] = and i8 [[A:%.*]], -2
214 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], -2
215 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
216 ; CHECK-NEXT:    [[A_OFF:%.*]] = add i8 [[A]], 1
217 ; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1
218 ; CHECK-NEXT:    br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]]
219 ; CHECK:       true:
220 ; CHECK-NEXT:    call void @foo(i32 1)
221 ; CHECK-NEXT:    ret void
222 ; CHECK:       false:
223 ; CHECK-NEXT:    call void @foo(i32 3)
224 ; CHECK-NEXT:    ret void
226   %and = and i8 %a, 254
227   %cmp = icmp eq i8 %and, 254
228   call void @llvm.assume(i1 %cmp)
229   switch i8 %a, label %default [i8 255, label %true
230   i8 254, label %false
231   i8 0, label %also_dead]
232 true:
233   call void @foo(i32 1)
234   ret void
235 false:
236   call void @foo(i32 3)
237   ret void
238 also_dead:
239   call void @foo(i32 5)
240   ret void
241 default:
242   call void @foo(i32 2)
243   ret void
246 declare void @llvm.assume(i1)