xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll (revision 6b9952759f66c8bc62ef4c6700f586053f009296)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
3
4; int foo1_with_default(int a) {
5;   switch(a) {
6;     case 10:
7;       return 10;
8;     case 20:
9;       return 2;
10;   }
11;   return 4;
12; }
13
14define i32 @foo1_with_default(i32 %a) {
15; CHECK-LABEL: @foo1_with_default(
16; CHECK-NEXT:  entry:
17; CHECK-NEXT:    [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[A:%.*]], 20
18; CHECK-NEXT:    [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP]], i32 2, i32 4
19; CHECK-NEXT:    [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 [[A]], 10
20; CHECK-NEXT:    [[SWITCH_SELECT2:%.*]] = select i1 [[SWITCH_SELECTCMP1]], i32 10, i32 [[SWITCH_SELECT]]
21; CHECK-NEXT:    ret i32 [[SWITCH_SELECT2]]
22;
23entry:
24  switch i32 %a, label %sw.epilog [
25  i32 10, label %sw.bb
26  i32 20, label %sw.bb1
27  ]
28
29sw.bb:
30  br label %return
31
32sw.bb1:
33  br label %return
34
35sw.epilog:
36  br label %return
37
38return:
39  %retval.0 = phi i32 [ 4, %sw.epilog ], [ 2, %sw.bb1 ], [ 10, %sw.bb ]
40  ret i32 %retval.0
41}
42
43; Same as above, but both cases have the same value.
44define i32 @same_value(i32 %a) {
45; CHECK-LABEL: @same_value(
46; CHECK-NEXT:  entry:
47; CHECK-NEXT:    [[SWITCH_SELECTCMP_CASE1:%.*]] = icmp eq i32 [[A:%.*]], 10
48; CHECK-NEXT:    [[SWITCH_SELECTCMP_CASE2:%.*]] = icmp eq i32 [[A]], 20
49; CHECK-NEXT:    [[SWITCH_SELECTCMP:%.*]] = or i1 [[SWITCH_SELECTCMP_CASE1]], [[SWITCH_SELECTCMP_CASE2]]
50; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[SWITCH_SELECTCMP]], i32 10, i32 4
51; CHECK-NEXT:    ret i32 [[TMP0]]
52;
53entry:
54  switch i32 %a, label %sw.epilog [
55  i32 10, label %sw.bb
56  i32 20, label %sw.bb
57  ]
58
59sw.bb:
60  br label %return
61
62sw.epilog:
63  br label %return
64
65return:
66  %retval.0 = phi i32 [ 4, %sw.epilog ], [ 10, %sw.bb ]
67  ret i32 %retval.0
68}
69
70define i1 @switch_to_select_same2_case_results_different_default(i8 %0) {
71; CHECK-LABEL: @switch_to_select_same2_case_results_different_default(
72; CHECK-NEXT:    [[SWITCH_AND:%.*]] = and i8 [[TMP0:%.*]], -5
73; CHECK-NEXT:    [[SWITCH_SELECTCMP:%.*]] = icmp eq i8 [[SWITCH_AND]], 0
74; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[SWITCH_SELECTCMP]], i1 true, i1 false
75; CHECK-NEXT:    ret i1 [[TMP2]]
76;
77  switch i8 %0, label %2 [
78  i8 4, label %3
79  i8 0, label %3
80  ]
81
822:
83  br label %3
84
853:
86  %4 = phi i1 [ false, %2 ], [ true, %1 ], [ true, %1 ]
87  ret i1 %4
88}
89
90define i1 @switch_to_select_same2_case_results_different_default_and_positive_offset_for_case(i8 %0) {
91; CHECK-LABEL: @switch_to_select_same2_case_results_different_default_and_positive_offset_for_case(
92; CHECK-NEXT:    [[TMP2:%.*]] = sub i8 [[TMP0:%.*]], 43
93; CHECK-NEXT:    [[SWITCH_AND:%.*]] = and i8 [[TMP2]], -3
94; CHECK-NEXT:    [[SWITCH_SELECTCMP:%.*]] = icmp eq i8 [[SWITCH_AND]], 0
95; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[SWITCH_SELECTCMP]], i1 true, i1 false
96; CHECK-NEXT:    ret i1 [[TMP3]]
97;
98  switch i8 %0, label %2 [
99  i8 43, label %3
100  i8 45, label %3
101  ]
102
1032:
104  br label %3
105
1063:
107  %4 = phi i1 [ false, %2 ], [ true, %1 ], [ true, %1 ]
108  ret i1 %4
109}
110
111define i8 @switch_to_select_same2_case_results_different_default_and_negative_offset_for_case(i32 %i) {
112; CHECK-LABEL: @switch_to_select_same2_case_results_different_default_and_negative_offset_for_case(
113; CHECK-NEXT:  entry:
114; CHECK-NEXT:    [[TMP0:%.*]] = sub i32 [[I:%.*]], -5
115; CHECK-NEXT:    [[SWITCH_AND:%.*]] = and i32 [[TMP0]], -3
116; CHECK-NEXT:    [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[SWITCH_AND]], 0
117; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[SWITCH_SELECTCMP]], i8 3, i8 42
118; CHECK-NEXT:    ret i8 [[TMP1]]
119;
120entry:
121  switch i32 %i, label %default [
122  i32 -3, label %end
123  i32 -5, label %end
124  ]
125
126default:
127  br label %end
128
129end:
130  %t0 = phi i8 [ 42, %default ], [ 3, %entry ], [ 3, %entry ]
131  ret i8 %t0
132}
133
134define i1 @switch_to_select_same4_case_results_different_default(i32 %i) {
135; CHECK-LABEL: @switch_to_select_same4_case_results_different_default(
136; CHECK-NEXT:  entry:
137; CHECK-NEXT:    [[SWITCH_AND:%.*]] = and i32 [[I:%.*]], -7
138; CHECK-NEXT:    [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[SWITCH_AND]], 0
139; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[SWITCH_SELECTCMP]], i1 true, i1 false
140; CHECK-NEXT:    ret i1 [[TMP0]]
141;
142entry:
143  switch i32 %i, label %lor.rhs [
144  i32 0, label %lor.end
145  i32 2, label %lor.end
146  i32 4, label %lor.end
147  i32 6, label %lor.end
148  ]
149
150lor.rhs:
151  br label %lor.end
152
153lor.end:
154  %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ], [ true, %entry ]
155  ret i1 %0
156}
157
158define i1 @switch_to_select_same4_case_results_different_default_alt_bitmask(i32 %i) {
159; CHECK-LABEL: @switch_to_select_same4_case_results_different_default_alt_bitmask(
160; CHECK-NEXT:  entry:
161; CHECK-NEXT:    [[SWITCH_AND:%.*]] = and i32 [[I:%.*]], -11
162; CHECK-NEXT:    [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[SWITCH_AND]], 0
163; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[SWITCH_SELECTCMP]], i1 true, i1 false
164; CHECK-NEXT:    ret i1 [[TMP0]]
165;
166entry:
167  switch i32 %i, label %lor.rhs [
168  i32 0, label %lor.end
169  i32 2, label %lor.end
170  i32 8, label %lor.end
171  i32 10, label %lor.end
172  ]
173
174lor.rhs:
175  br label %lor.end
176
177lor.end:
178  %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ], [ true, %entry ]
179  ret i1 %0
180}
181
182define i1 @switch_to_select_same4_case_results_different_default_positive_offset(i32 %i) {
183; CHECK-LABEL: @switch_to_select_same4_case_results_different_default_positive_offset(
184; CHECK-NEXT:  entry:
185; CHECK-NEXT:    [[TMP0:%.*]] = sub i32 [[I:%.*]], 2
186; CHECK-NEXT:    [[SWITCH_AND:%.*]] = and i32 [[TMP0]], -11
187; CHECK-NEXT:    [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[SWITCH_AND]], 0
188; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[SWITCH_SELECTCMP]], i1 true, i1 false
189; CHECK-NEXT:    ret i1 [[TMP1]]
190;
191entry:
192  switch i32 %i, label %lor.rhs [
193  i32 2, label %lor.end
194  i32 4, label %lor.end
195  i32 10, label %lor.end
196  i32 12, label %lor.end
197  ]
198
199lor.rhs:
200  br label %lor.end
201
202lor.end:
203  %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ], [ true, %entry ]
204  ret i1 %0
205}
206
207define i1 @switch_to_select_invalid_mask(i32 %i) {
208; CHECK-LABEL: @switch_to_select_invalid_mask(
209; CHECK-NEXT:  entry:
210; CHECK-NEXT:    switch i32 [[I:%.*]], label [[LOR_RHS:%.*]] [
211; CHECK-NEXT:      i32 1, label [[LOR_END:%.*]]
212; CHECK-NEXT:      i32 4, label [[LOR_END]]
213; CHECK-NEXT:      i32 10, label [[LOR_END]]
214; CHECK-NEXT:      i32 12, label [[LOR_END]]
215; CHECK-NEXT:    ]
216; CHECK:       lor.rhs:
217; CHECK-NEXT:    br label [[LOR_END]]
218; CHECK:       lor.end:
219; CHECK-NEXT:    [[TMP0:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[LOR_RHS]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ]
220; CHECK-NEXT:    ret i1 [[TMP0]]
221;
222entry:
223  switch i32 %i, label %lor.rhs [
224  i32 1, label %lor.end
225  i32 4, label %lor.end
226  i32 10, label %lor.end
227  i32 12, label %lor.end
228  ]
229
230lor.rhs:
231  br label %lor.end
232
233lor.end:
234  %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ], [ true, %entry ]
235  ret i1 %0
236}
237
238define i1 @switch_to_select_nonpow2_cases(i32 %i) {
239; CHECK-LABEL: @switch_to_select_nonpow2_cases(
240; CHECK-NEXT:  entry:
241; CHECK-NEXT:    switch i32 [[I:%.*]], label [[LOR_RHS:%.*]] [
242; CHECK-NEXT:      i32 0, label [[LOR_END:%.*]]
243; CHECK-NEXT:      i32 2, label [[LOR_END]]
244; CHECK-NEXT:      i32 4, label [[LOR_END]]
245; CHECK-NEXT:    ]
246; CHECK:       lor.rhs:
247; CHECK-NEXT:    br label [[LOR_END]]
248; CHECK:       lor.end:
249; CHECK-NEXT:    [[TMP0:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[LOR_RHS]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ]
250; CHECK-NEXT:    ret i1 [[TMP0]]
251;
252entry:
253  switch i32 %i, label %lor.rhs [
254  i32 0, label %lor.end
255  i32 2, label %lor.end
256  i32 4, label %lor.end
257  ]
258
259lor.rhs:
260  br label %lor.end
261
262lor.end:
263  %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ]
264  ret i1 %0
265}
266
267; TODO: we can produce the optimal code when there is no default also
268define i8 @switch_to_select_two_case_results_no_default(i32 %i) {
269; CHECK-LABEL: @switch_to_select_two_case_results_no_default(
270; CHECK-NEXT:  entry:
271; CHECK-NEXT:    switch i32 [[I:%.*]], label [[DEFAULT:%.*]] [
272; CHECK-NEXT:      i32 0, label [[END:%.*]]
273; CHECK-NEXT:      i32 2, label [[END]]
274; CHECK-NEXT:      i32 4, label [[CASE3:%.*]]
275; CHECK-NEXT:      i32 6, label [[CASE3]]
276; CHECK-NEXT:    ]
277; CHECK:       case3:
278; CHECK-NEXT:    br label [[END]]
279; CHECK:       default:
280; CHECK-NEXT:    unreachable
281; CHECK:       end:
282; CHECK-NEXT:    [[T0:%.*]] = phi i8 [ 44, [[CASE3]] ], [ 42, [[ENTRY:%.*]] ], [ 42, [[ENTRY]] ]
283; CHECK-NEXT:    ret i8 [[T0]]
284;
285entry:
286  switch i32 %i, label %default [
287  i32 0, label %case1
288  i32 2, label %case2
289  i32 4, label %case3
290  i32 6, label %case4
291  ]
292
293case1:
294  br label %end
295
296case2:
297  br label %end
298
299case3:
300  br label %end
301
302case4:
303  br label %end
304
305default:
306  unreachable
307
308end:
309  %t0 = phi i8 [ 42, %case1 ], [ 42, %case2 ], [ 44, %case3 ], [ 44, %case4 ]
310  ret i8 %t0
311}
312