xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll (revision 7dc2f6602212bf0a0433c157b70e4fc0d70bb730)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt %s -S -passes='simplifycfg<switch-to-lookup>' -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp | FileCheck %s
3
4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5declare void @foo(i32)
6
7define void @test(i1 %a) {
8; CHECK-LABEL: define void @test(
9; CHECK-SAME: i1 [[A:%.*]]) {
10; CHECK-NEXT:    [[A_OFF:%.*]] = add i1 [[A]], true
11; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i1 [[A_OFF]], true
12; CHECK-NEXT:    br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]]
13; CHECK:       common.ret:
14; CHECK-NEXT:    ret void
15; CHECK:       true:
16; CHECK-NEXT:    call void @foo(i32 1)
17; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
18; CHECK:       false:
19; CHECK-NEXT:    call void @foo(i32 3)
20; CHECK-NEXT:    br label [[COMMON_RET]]
21;
22  switch i1 %a, label %default [i1 1, label %true
23  i1 0, label %false]
24true:
25  call void @foo(i32 1)
26  ret void
27false:
28  call void @foo(i32 3)
29  ret void
30default:
31  call void @foo(i32 2)
32  ret void
33}
34
35define void @test2(i2 %a) {
36; CHECK-LABEL: define void @test2(
37; CHECK-SAME: i2 [[A:%.*]]) {
38; CHECK-NEXT:    switch i2 [[A]], label [[DOTUNREACHABLEDEFAULT:%.*]] [
39; CHECK-NEXT:      i2 0, label [[CASE0:%.*]]
40; CHECK-NEXT:      i2 1, label [[CASE1:%.*]]
41; CHECK-NEXT:      i2 -2, label [[CASE2:%.*]]
42; CHECK-NEXT:      i2 -1, label [[CASE3:%.*]]
43; CHECK-NEXT:    ]
44; CHECK:       common.ret:
45; CHECK-NEXT:    ret void
46; CHECK:       case0:
47; CHECK-NEXT:    call void @foo(i32 0)
48; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
49; CHECK:       case1:
50; CHECK-NEXT:    call void @foo(i32 1)
51; CHECK-NEXT:    br label [[COMMON_RET]]
52; CHECK:       case2:
53; CHECK-NEXT:    call void @foo(i32 2)
54; CHECK-NEXT:    br label [[COMMON_RET]]
55; CHECK:       case3:
56; CHECK-NEXT:    call void @foo(i32 3)
57; CHECK-NEXT:    br label [[COMMON_RET]]
58; CHECK:       .unreachabledefault:
59; CHECK-NEXT:    unreachable
60;
61  switch i2 %a, label %default [i2 0, label %case0
62  i2 1, label %case1
63  i2 2, label %case2
64  i2 3, label %case3]
65case0:
66  call void @foo(i32 0)
67  ret void
68case1:
69  call void @foo(i32 1)
70  ret void
71case2:
72  call void @foo(i32 2)
73  ret void
74case3:
75  call void @foo(i32 3)
76  ret void
77default:
78  call void @foo(i32 4)
79  ret void
80}
81
82; We can replace the default branch with case 3 since it is the only case that is missing.
83define void @test3(i2 %a) {
84; CHECK-LABEL: define void @test3(
85; CHECK-SAME: i2 [[A:%.*]]) {
86; CHECK-NEXT:    switch i2 [[A]], label [[DOTUNREACHABLEDEFAULT:%.*]] [
87; CHECK-NEXT:      i2 0, label [[CASE0:%.*]]
88; CHECK-NEXT:      i2 1, label [[CASE1:%.*]]
89; CHECK-NEXT:      i2 -2, label [[CASE2:%.*]]
90; CHECK-NEXT:      i2 -1, label [[DEFAULT:%.*]]
91; CHECK-NEXT:    ]
92; CHECK:       common.ret:
93; CHECK-NEXT:    ret void
94; CHECK:       case0:
95; CHECK-NEXT:    call void @foo(i32 0)
96; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
97; CHECK:       case1:
98; CHECK-NEXT:    call void @foo(i32 1)
99; CHECK-NEXT:    br label [[COMMON_RET]]
100; CHECK:       case2:
101; CHECK-NEXT:    call void @foo(i32 2)
102; CHECK-NEXT:    br label [[COMMON_RET]]
103; CHECK:       .unreachabledefault:
104; CHECK-NEXT:    unreachable
105; CHECK:       default:
106; CHECK-NEXT:    call void @foo(i32 3)
107; CHECK-NEXT:    br label [[COMMON_RET]]
108;
109  switch i2 %a, label %default [i2 0, label %case0
110  i2 1, label %case1
111  i2 2, label %case2]
112
113case0:
114  call void @foo(i32 0)
115  ret void
116case1:
117  call void @foo(i32 1)
118  ret void
119case2:
120  call void @foo(i32 2)
121  ret void
122default:
123  call void @foo(i32 3)
124  ret void
125}
126
127define void @test3_prof(i2 %a) {
128; CHECK-LABEL: define void @test3_prof(
129; CHECK-SAME: i2 [[A:%.*]]) {
130; CHECK-NEXT:    switch i2 [[A]], label [[DOTUNREACHABLEDEFAULT:%.*]] [
131; CHECK-NEXT:      i2 0, label [[CASE0:%.*]]
132; CHECK-NEXT:      i2 1, label [[CASE1:%.*]]
133; CHECK-NEXT:      i2 -2, label [[CASE2:%.*]]
134; CHECK-NEXT:      i2 -1, label [[DEFAULT:%.*]]
135; CHECK-NEXT:    ], !prof [[PROF0:![0-9]+]]
136; CHECK:       common.ret:
137; CHECK-NEXT:    ret void
138; CHECK:       case0:
139; CHECK-NEXT:    call void @foo(i32 0)
140; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
141; CHECK:       case1:
142; CHECK-NEXT:    call void @foo(i32 1)
143; CHECK-NEXT:    br label [[COMMON_RET]]
144; CHECK:       case2:
145; CHECK-NEXT:    call void @foo(i32 2)
146; CHECK-NEXT:    br label [[COMMON_RET]]
147; CHECK:       .unreachabledefault:
148; CHECK-NEXT:    unreachable
149; CHECK:       default:
150; CHECK-NEXT:    call void @foo(i32 3)
151; CHECK-NEXT:    br label [[COMMON_RET]]
152;
153  switch i2 %a, label %default [i2 0, label %case0
154  i2 1, label %case1
155  i2 2, label %case2], !prof !0
156
157case0:
158  call void @foo(i32 0)
159  ret void
160case1:
161  call void @foo(i32 1)
162  ret void
163case2:
164  call void @foo(i32 2)
165  ret void
166default:
167  call void @foo(i32 3)
168  ret void
169}
170
171; Negative test - check for possible overflow when computing
172; number of possible cases.
173define void @test4(i128 %a) {
174; CHECK-LABEL: define void @test4(
175; CHECK-SAME: i128 [[A:%.*]]) {
176; CHECK-NEXT:    switch i128 [[A]], label [[DEFAULT:%.*]] [
177; CHECK-NEXT:      i128 0, label [[CASE0:%.*]]
178; CHECK-NEXT:      i128 1, label [[CASE1:%.*]]
179; CHECK-NEXT:    ]
180; CHECK:       common.ret:
181; CHECK-NEXT:    ret void
182; CHECK:       case0:
183; CHECK-NEXT:    call void @foo(i32 0)
184; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
185; CHECK:       case1:
186; CHECK-NEXT:    call void @foo(i32 1)
187; CHECK-NEXT:    br label [[COMMON_RET]]
188; CHECK:       default:
189; CHECK-NEXT:    call void @foo(i32 2)
190; CHECK-NEXT:    br label [[COMMON_RET]]
191;
192  switch i128 %a, label %default [i128 0, label %case0
193  i128 1, label %case1]
194
195case0:
196  call void @foo(i32 0)
197  ret void
198case1:
199  call void @foo(i32 1)
200  ret void
201default:
202  call void @foo(i32 2)
203  ret void
204}
205
206; All but one bit known zero
207define void @test5(i8 %a) {
208; CHECK-LABEL: define void @test5(
209; CHECK-SAME: i8 [[A:%.*]]) {
210; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[A]], 2
211; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
212; CHECK-NEXT:    [[A_OFF:%.*]] = add i8 [[A]], -1
213; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1
214; CHECK-NEXT:    br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]]
215; CHECK:       common.ret:
216; CHECK-NEXT:    ret void
217; CHECK:       true:
218; CHECK-NEXT:    call void @foo(i32 1)
219; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
220; CHECK:       false:
221; CHECK-NEXT:    call void @foo(i32 3)
222; CHECK-NEXT:    br label [[COMMON_RET]]
223;
224  %cmp = icmp ult i8 %a, 2
225  call void @llvm.assume(i1 %cmp)
226  switch i8 %a, label %default [i8 1, label %true
227  i8 0, label %false]
228true:
229  call void @foo(i32 1)
230  ret void
231false:
232  call void @foo(i32 3)
233  ret void
234default:
235  call void @foo(i32 2)
236  ret void
237}
238
239;; All but one bit known one
240define void @test6(i8 %a) {
241; CHECK-LABEL: define void @test6(
242; CHECK-SAME: i8 [[A:%.*]]) {
243; CHECK-NEXT:    [[AND:%.*]] = and i8 [[A]], -2
244; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], -2
245; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
246; CHECK-NEXT:    [[A_OFF:%.*]] = add i8 [[A]], 1
247; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1
248; CHECK-NEXT:    br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]]
249; CHECK:       common.ret:
250; CHECK-NEXT:    ret void
251; CHECK:       true:
252; CHECK-NEXT:    call void @foo(i32 1)
253; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
254; CHECK:       false:
255; CHECK-NEXT:    call void @foo(i32 3)
256; CHECK-NEXT:    br label [[COMMON_RET]]
257;
258  %and = and i8 %a, 254
259  %cmp = icmp eq i8 %and, 254
260  call void @llvm.assume(i1 %cmp)
261  switch i8 %a, label %default [i8 255, label %true
262  i8 254, label %false]
263true:
264  call void @foo(i32 1)
265  ret void
266false:
267  call void @foo(i32 3)
268  ret void
269default:
270  call void @foo(i32 2)
271  ret void
272}
273
274; Check that we can eliminate both dead cases and dead defaults
275; within a single run of simplifycfg
276define void @test7(i8 %a) {
277; CHECK-LABEL: define void @test7(
278; CHECK-SAME: i8 [[A:%.*]]) {
279; CHECK-NEXT:    [[AND:%.*]] = and i8 [[A]], -2
280; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], -2
281; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
282; CHECK-NEXT:    [[A_OFF:%.*]] = add i8 [[A]], 1
283; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i8 [[A_OFF]], 1
284; CHECK-NEXT:    br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]]
285; CHECK:       common.ret:
286; CHECK-NEXT:    ret void
287; CHECK:       true:
288; CHECK-NEXT:    call void @foo(i32 1)
289; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
290; CHECK:       false:
291; CHECK-NEXT:    call void @foo(i32 3)
292; CHECK-NEXT:    br label [[COMMON_RET]]
293;
294  %and = and i8 %a, 254
295  %cmp = icmp eq i8 %and, 254
296  call void @llvm.assume(i1 %cmp)
297  switch i8 %a, label %default [i8 255, label %true
298  i8 254, label %false
299  i8 0, label %also_dead]
300true:
301  call void @foo(i32 1)
302  ret void
303false:
304  call void @foo(i32 3)
305  ret void
306also_dead:
307  call void @foo(i32 5)
308  ret void
309default:
310  call void @foo(i32 2)
311  ret void
312}
313
314declare void @llvm.assume(i1)
315
316define zeroext i1 @test8(i128 %a) {
317; We should not transform conditions wider than 64 bit.
318; CHECK-LABEL: define zeroext i1 @test8(
319; CHECK-SAME: i128 [[A:%.*]]) {
320; CHECK-NEXT:  entry:
321; CHECK-NEXT:    [[TMP0:%.*]] = and i128 [[A]], 3894222643901120721397872246915072
322; CHECK-NEXT:    switch i128 [[TMP0]], label [[LOR_RHS:%.*]] [
323; CHECK-NEXT:      i128 1298074214633706907132624082305024, label [[LOR_END:%.*]]
324; CHECK-NEXT:      i128 2596148429267413814265248164610048, label [[LOR_END]]
325; CHECK-NEXT:      i128 3894222643901120721397872246915072, label [[LOR_END]]
326; CHECK-NEXT:    ]
327; CHECK:       lor.rhs:
328; CHECK-NEXT:    br label [[LOR_END]]
329; CHECK:       lor.end:
330; CHECK-NEXT:    [[TMP1:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[LOR_RHS]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ]
331; CHECK-NEXT:    ret i1 [[TMP1]]
332;
333entry:
334  %0 = and i128 %a, 3894222643901120721397872246915072
335  switch i128 %0, label %lor.rhs [
336  i128 1298074214633706907132624082305024, label %lor.end
337  i128 2596148429267413814265248164610048, label %lor.end
338  i128 3894222643901120721397872246915072, label %lor.end
339  ]
340
341lor.rhs:                                          ; preds = %entry
342  br label %lor.end
343
344lor.end:                                          ; preds = %entry, %entry, %entry, %lor.rhs
345  %1 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ]
346  ret i1 %1
347}
348
349!0 = !{!"branch_weights", i32 8, i32 4, i32 2, i32 1}
350;.
351; CHECK: [[PROF0]] = !{!"branch_weights", i32 0, i32 4, i32 2, i32 1, i32 8}
352;.
353