xref: /llvm-project/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll (revision 394e321a2ea021194891cf5b0c5747a901fb7915)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
3
4define i32 @test_unreachable_default(i32 noundef %num) {
5; CHECK-LABEL: define i32 @test_unreachable_default(
6; CHECK-SAME: i32 noundef [[NUM:%.*]]) {
7; CHECK-NEXT:  entry:
8; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[NUM]], -120
9; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[SUB]], 3
10; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2
11; CHECK-NEXT:    switch i32 [[COND]], label [[DEFAULT_UNREACHABLE:%.*]] [
12; CHECK-NEXT:      i32 0, label [[SW_BB:%.*]]
13; CHECK-NEXT:      i32 1, label [[SW_BB2:%.*]]
14; CHECK-NEXT:      i32 2, label [[SW_BB4:%.*]]
15; CHECK-NEXT:    ]
16; CHECK:       sw.bb:
17; CHECK-NEXT:    [[CALL:%.*]] = call i32 @call0()
18; CHECK-NEXT:    br label [[CLEANUP:%.*]]
19; CHECK:       sw.bb2:
20; CHECK-NEXT:    [[CALL3:%.*]] = call i32 @call1()
21; CHECK-NEXT:    br label [[CLEANUP]]
22; CHECK:       sw.bb4:
23; CHECK-NEXT:    [[CALL5:%.*]] = call i32 @call2()
24; CHECK-NEXT:    br label [[CLEANUP]]
25; CHECK:       default.unreachable:
26; CHECK-NEXT:    unreachable
27; CHECK:       sw.default:
28; CHECK-NEXT:    [[CALL6:%.*]] = call i32 @call3()
29; CHECK-NEXT:    br label [[CLEANUP]]
30; CHECK:       cleanup:
31; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CALL6]], [[SW_DEFAULT:%.*]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ]
32; CHECK-NEXT:    ret i32 [[RETVAL_0]]
33;
34entry:
35  %sub = add i32 %num, -120
36  %cmp = icmp ult i32 %sub, 3
37  %cond = select i1 %cmp, i32 %sub, i32 2
38  switch i32 %cond, label %sw.default [
39  i32 0, label %sw.bb
40  i32 1, label %sw.bb2
41  i32 2, label %sw.bb4
42  ]
43
44sw.bb:
45  %call = call i32 @call0()
46  br label %cleanup
47
48sw.bb2:
49  %call3 = call i32 @call1()
50  br label %cleanup
51
52sw.bb4:
53  %call5 = call i32 @call2()
54  br label %cleanup
55
56sw.default:
57  %call6 = call i32 @call3()
58  br label %cleanup
59
60cleanup:
61  %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ]
62  ret i32 %retval.0
63}
64
65define i32 @test_unreachable_default_shared_edge(i32 noundef %num) {
66; CHECK-LABEL: define i32 @test_unreachable_default_shared_edge(
67; CHECK-SAME: i32 noundef [[NUM:%.*]]) {
68; CHECK-NEXT:  entry:
69; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[NUM]], -120
70; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[SUB]], 3
71; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2
72; CHECK-NEXT:    switch i32 [[COND]], label [[DEFAULT_UNREACHABLE:%.*]] [
73; CHECK-NEXT:      i32 0, label [[SW_BB:%.*]]
74; CHECK-NEXT:      i32 1, label [[SW_BB2:%.*]]
75; CHECK-NEXT:      i32 2, label [[SW_BB4:%.*]]
76; CHECK-NEXT:    ]
77; CHECK:       sw.bb:
78; CHECK-NEXT:    [[CALL:%.*]] = call i32 @call0()
79; CHECK-NEXT:    br label [[CLEANUP:%.*]]
80; CHECK:       sw.bb2:
81; CHECK-NEXT:    [[CALL3:%.*]] = call i32 @call1()
82; CHECK-NEXT:    br label [[CLEANUP]]
83; CHECK:       default.unreachable:
84; CHECK-NEXT:    unreachable
85; CHECK:       sw.bb4:
86; CHECK-NEXT:    [[CALL5:%.*]] = call i32 @call4(i32 [[SUB]])
87; CHECK-NEXT:    br label [[CLEANUP]]
88; CHECK:       cleanup:
89; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ]
90; CHECK-NEXT:    ret i32 [[RETVAL_0]]
91;
92entry:
93  %sub = add i32 %num, -120
94  %cmp = icmp ult i32 %sub, 3
95  %cond = select i1 %cmp, i32 %sub, i32 2
96  switch i32 %cond, label %sw.bb4 [
97  i32 0, label %sw.bb
98  i32 1, label %sw.bb2
99  i32 2, label %sw.bb4
100  ]
101
102sw.bb:
103  %call = call i32 @call0()
104  br label %cleanup
105
106sw.bb2:
107  %call3 = call i32 @call1()
108  br label %cleanup
109
110sw.bb4:
111  %val = phi i32 [ %sub, %entry ], [ %sub, %entry ]
112  %call5 = call i32 @call4(i32 %val)
113  br label %cleanup
114
115cleanup:
116  %retval.0 = phi i32 [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ]
117  ret i32 %retval.0
118}
119
120; Negative tests
121
122define i32 @test_reachable_default(i32 noundef %num) {
123; CHECK-LABEL: define i32 @test_reachable_default(
124; CHECK-SAME: i32 noundef [[NUM:%.*]]) {
125; CHECK-NEXT:  entry:
126; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[NUM]], -120
127; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[SUB]], 3
128; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 4
129; CHECK-NEXT:    switch i32 [[COND]], label [[SW_DEFAULT:%.*]] [
130; CHECK-NEXT:      i32 0, label [[SW_BB:%.*]]
131; CHECK-NEXT:      i32 1, label [[SW_BB2:%.*]]
132; CHECK-NEXT:      i32 2, label [[SW_BB4:%.*]]
133; CHECK-NEXT:    ]
134; CHECK:       sw.bb:
135; CHECK-NEXT:    [[CALL:%.*]] = call i32 @call0()
136; CHECK-NEXT:    br label [[CLEANUP:%.*]]
137; CHECK:       sw.bb2:
138; CHECK-NEXT:    [[CALL3:%.*]] = call i32 @call1()
139; CHECK-NEXT:    br label [[CLEANUP]]
140; CHECK:       sw.bb4:
141; CHECK-NEXT:    [[CALL5:%.*]] = call i32 @call2()
142; CHECK-NEXT:    br label [[CLEANUP]]
143; CHECK:       sw.default:
144; CHECK-NEXT:    [[CALL6:%.*]] = call i32 @call3()
145; CHECK-NEXT:    br label [[CLEANUP]]
146; CHECK:       cleanup:
147; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CALL6]], [[SW_DEFAULT]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ]
148; CHECK-NEXT:    ret i32 [[RETVAL_0]]
149;
150entry:
151  %sub = add i32 %num, -120
152  %cmp = icmp ult i32 %sub, 3
153  %cond = select i1 %cmp, i32 %sub, i32 4
154  switch i32 %cond, label %sw.default [
155  i32 0, label %sw.bb
156  i32 1, label %sw.bb2
157  i32 2, label %sw.bb4
158  ]
159
160sw.bb:
161  %call = call i32 @call0()
162  br label %cleanup
163
164sw.bb2:
165  %call3 = call i32 @call1()
166  br label %cleanup
167
168sw.bb4:
169  %call5 = call i32 @call2()
170  br label %cleanup
171
172sw.default:
173  %call6 = call i32 @call3()
174  br label %cleanup
175
176cleanup:
177  %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ]
178  ret i32 %retval.0
179}
180
181define i32 @test_unreachable_default_cond_may_be_undef(i32 %num) {
182; CHECK-LABEL: define i32 @test_unreachable_default_cond_may_be_undef(
183; CHECK-SAME: i32 [[NUM:%.*]]) {
184; CHECK-NEXT:  entry:
185; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[NUM]], -120
186; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[SUB]], 3
187; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2
188; CHECK-NEXT:    switch i32 [[COND]], label [[SW_DEFAULT:%.*]] [
189; CHECK-NEXT:      i32 0, label [[SW_BB:%.*]]
190; CHECK-NEXT:      i32 1, label [[SW_BB2:%.*]]
191; CHECK-NEXT:      i32 2, label [[SW_BB4:%.*]]
192; CHECK-NEXT:    ]
193; CHECK:       sw.bb:
194; CHECK-NEXT:    [[CALL:%.*]] = call i32 @call0()
195; CHECK-NEXT:    br label [[CLEANUP:%.*]]
196; CHECK:       sw.bb2:
197; CHECK-NEXT:    [[CALL3:%.*]] = call i32 @call1()
198; CHECK-NEXT:    br label [[CLEANUP]]
199; CHECK:       sw.bb4:
200; CHECK-NEXT:    [[CALL5:%.*]] = call i32 @call2()
201; CHECK-NEXT:    br label [[CLEANUP]]
202; CHECK:       sw.default:
203; CHECK-NEXT:    [[CALL6:%.*]] = call i32 @call3()
204; CHECK-NEXT:    br label [[CLEANUP]]
205; CHECK:       cleanup:
206; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CALL6]], [[SW_DEFAULT]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ]
207; CHECK-NEXT:    ret i32 [[RETVAL_0]]
208;
209entry:
210  %sub = add i32 %num, -120
211  %cmp = icmp ult i32 %sub, 3
212  %cond = select i1 %cmp, i32 %sub, i32 2
213  switch i32 %cond, label %sw.default [
214  i32 0, label %sw.bb
215  i32 1, label %sw.bb2
216  i32 2, label %sw.bb4
217  ]
218
219sw.bb:
220  %call = call i32 @call0()
221  br label %cleanup
222
223sw.bb2:
224  %call3 = call i32 @call1()
225  br label %cleanup
226
227sw.bb4:
228  %call5 = call i32 @call2()
229  br label %cleanup
230
231sw.default:
232  %call6 = call i32 @call3()
233  br label %cleanup
234
235cleanup:
236  %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ]
237  ret i32 %retval.0
238}
239
240define i32 @test_default_is_already_unreachable(i32 %num) {
241; CHECK-LABEL: define i32 @test_default_is_already_unreachable(
242; CHECK-SAME: i32 [[NUM:%.*]]) {
243; CHECK-NEXT:  entry:
244; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[NUM]], -120
245; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[SUB]], 3
246; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2
247; CHECK-NEXT:    switch i32 [[COND]], label [[SW_DEFAULT:%.*]] [
248; CHECK-NEXT:      i32 0, label [[SW_BB:%.*]]
249; CHECK-NEXT:      i32 1, label [[SW_BB2:%.*]]
250; CHECK-NEXT:      i32 2, label [[SW_BB4:%.*]]
251; CHECK-NEXT:    ]
252; CHECK:       sw.bb:
253; CHECK-NEXT:    [[CALL:%.*]] = call i32 @call0()
254; CHECK-NEXT:    br label [[CLEANUP:%.*]]
255; CHECK:       sw.bb2:
256; CHECK-NEXT:    [[CALL3:%.*]] = call i32 @call1()
257; CHECK-NEXT:    br label [[CLEANUP]]
258; CHECK:       sw.bb4:
259; CHECK-NEXT:    [[CALL5:%.*]] = call i32 @call2()
260; CHECK-NEXT:    br label [[CLEANUP]]
261; CHECK:       sw.default:
262; CHECK-NEXT:    unreachable
263; CHECK:       cleanup:
264; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ]
265; CHECK-NEXT:    ret i32 [[RETVAL_0]]
266;
267entry:
268  %sub = add i32 %num, -120
269  %cmp = icmp ult i32 %sub, 3
270  %cond = select i1 %cmp, i32 %sub, i32 2
271  switch i32 %cond, label %sw.default [
272  i32 0, label %sw.bb
273  i32 1, label %sw.bb2
274  i32 2, label %sw.bb4
275  ]
276
277sw.bb:
278  %call = call i32 @call0()
279  br label %cleanup
280
281sw.bb2:
282  %call3 = call i32 @call1()
283  br label %cleanup
284
285sw.bb4:
286  %call5 = call i32 @call2()
287  br label %cleanup
288
289sw.default:
290  unreachable
291
292cleanup:
293  %retval.0 = phi i32 [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ]
294  ret i32 %retval.0
295}
296
297declare i32 @call0()
298declare i32 @call1()
299declare i32 @call2()
300declare i32 @call3()
301declare i32 @call4(i32)
302