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