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