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
3target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4declare void @foo(i32)
5
6define 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
17;
18  switch i1 %a, label %default [i1 1, label %true
19  i1 0, label %false]
20true:
21  call void @foo(i32 1)
22  ret void
23false:
24  call void @foo(i32 3)
25  ret void
26default:
27  call void @foo(i32 2)
28  ret void
29}
30
31define 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
53;
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]
58case0:
59  call void @foo(i32 0)
60  ret void
61case1:
62  call void @foo(i32 1)
63  ret void
64case2:
65  call void @foo(i32 2)
66  ret void
67case3:
68  call void @foo(i32 3)
69  ret void
70default:
71  call void @foo(i32 4)
72  ret void
73}
74
75; This one is a negative test - we know the value of the default,
76; but that's about it
77define 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 3)
95; CHECK-NEXT:    ret void
96;
97  switch i2 %a, label %default [i2 0, label %case0
98  i2 1, label %case1
99  i2 2, label %case2]
100
101case0:
102  call void @foo(i32 0)
103  ret void
104case1:
105  call void @foo(i32 1)
106  ret void
107case2:
108  call void @foo(i32 2)
109  ret void
110default:
111  call void @foo(i32 3)
112  ret void
113}
114
115; Negative test - check for possible overflow when computing
116; number of possible cases.
117define 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 2)
131; CHECK-NEXT:    ret void
132;
133  switch i128 %a, label %default [i128 0, label %case0
134  i128 1, label %case1]
135
136case0:
137  call void @foo(i32 0)
138  ret void
139case1:
140  call void @foo(i32 1)
141  ret void
142default:
143  call void @foo(i32 2)
144  ret void
145}
146
147; All but one bit known zero
148define 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
161;
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]
166true:
167  call void @foo(i32 1)
168  ret void
169false:
170  call void @foo(i32 3)
171  ret void
172default:
173  call void @foo(i32 2)
174  ret void
175}
176
177;; All but one bit known one
178define 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
192;
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]
198true:
199  call void @foo(i32 1)
200  ret void
201false:
202  call void @foo(i32 3)
203  ret void
204default:
205  call void @foo(i32 2)
206  ret void
207}
208
209; Check that we can eliminate both dead cases and dead defaults
210; within a single run of simplify-cfg
211define 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
225;
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]
232true:
233  call void @foo(i32 1)
234  ret void
235false:
236  call void @foo(i32 3)
237  ret void
238also_dead:
239  call void @foo(i32 5)
240  ret void
241default:
242  call void @foo(i32 2)
243  ret void
244}
245
246declare void @llvm.assume(i1)
247
248