xref: /llvm-project/llvm/test/Transforms/InstCombine/icmp-select.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4declare void @use(i8)
5declare void @use.i1(i1)
6declare i8 @llvm.umin.i8(i8, i8)
7
8define i1 @icmp_select_const(i8 %x, i8 %y) {
9; CHECK-LABEL: @icmp_select_const(
10; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
11; CHECK-NEXT:    [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], 0
12; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
13; CHECK-NEXT:    ret i1 [[CMP2]]
14;
15  %cmp1 = icmp eq i8 %x, 0
16  %sel = select i1 %cmp1, i8 0, i8 %y
17  %cmp2 = icmp eq i8 %sel, 0
18  ret i1 %cmp2
19}
20
21define i1 @icmp_select_var(i8 %x, i8 %y, i8 %z) {
22; CHECK-LABEL: @icmp_select_var(
23; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
24; CHECK-NEXT:    [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[Z:%.*]]
25; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
26; CHECK-NEXT:    ret i1 [[CMP2]]
27;
28  %cmp1 = icmp eq i8 %x, 0
29  %sel = select i1 %cmp1, i8 %z, i8 %y
30  %cmp2 = icmp eq i8 %sel, %z
31  ret i1 %cmp2
32}
33
34define i1 @icmp_select_var_commuted(i8 %x, i8 %y, i8 %_z) {
35; CHECK-LABEL: @icmp_select_var_commuted(
36; CHECK-NEXT:    [[Z:%.*]] = udiv i8 42, [[_Z:%.*]]
37; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
38; CHECK-NEXT:    [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[Z]]
39; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
40; CHECK-NEXT:    ret i1 [[CMP2]]
41;
42  %z = udiv i8 42, %_z ; thwart complexity-based canonicalization
43  %cmp1 = icmp eq i8 %x, 0
44  %sel = select i1 %cmp1, i8 %z, i8 %y
45  %cmp2 = icmp eq i8 %z, %sel
46  ret i1 %cmp2
47}
48
49define i1 @icmp_select_var_select(i8 %x, i8 %y, i1 %c) {
50; CHECK-LABEL: @icmp_select_var_select(
51; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
52; CHECK-NEXT:    [[CMP212:%.*]] = icmp eq i8 [[X]], [[Y:%.*]]
53; CHECK-NEXT:    [[NOT_C:%.*]] = xor i1 [[C:%.*]], true
54; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[CMP1]], i1 true, i1 [[NOT_C]]
55; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[CMP212]]
56; CHECK-NEXT:    ret i1 [[CMP2]]
57;
58  %z = select i1 %c, i8 %x, i8 %y
59  %cmp1 = icmp eq i8 %x, 0
60  %sel = select i1 %cmp1, i8 %z, i8 %y
61  %cmp2 = icmp eq i8 %z, %sel
62  ret i1 %cmp2
63}
64
65define i1 @icmp_select_var_both_fold(i8 %x, i8 %y, i8 %_z) {
66; CHECK-LABEL: @icmp_select_var_both_fold(
67; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
68; CHECK-NEXT:    ret i1 [[CMP1]]
69;
70  %z = or i8 %_z, 1
71  %cmp1 = icmp eq i8 %x, 0
72  %sel = select i1 %cmp1, i8 %z, i8 2
73  %cmp2 = icmp eq i8 %sel, %z
74  ret i1 %cmp2
75}
76
77define i1 @icmp_select_var_extra_use(i8 %x, i8 %y, i8 %z) {
78; CHECK-LABEL: @icmp_select_var_extra_use(
79; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
80; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i8 [[Z:%.*]], i8 [[Y:%.*]]
81; CHECK-NEXT:    call void @use(i8 [[SEL]])
82; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[SEL]], [[Z]]
83; CHECK-NEXT:    ret i1 [[CMP2]]
84;
85  %cmp1 = icmp eq i8 %x, 0
86  %sel = select i1 %cmp1, i8 %z, i8 %y
87  call void @use(i8 %sel)
88  %cmp2 = icmp eq i8 %sel, %z
89  ret i1 %cmp2
90}
91
92define i1 @icmp_select_var_both_fold_extra_use(i8 %x, i8 %y, i8 %_z) {
93; CHECK-LABEL: @icmp_select_var_both_fold_extra_use(
94; CHECK-NEXT:    [[Z:%.*]] = or i8 [[_Z:%.*]], 1
95; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
96; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i8 [[Z]], i8 2
97; CHECK-NEXT:    call void @use(i8 [[SEL]])
98; CHECK-NEXT:    ret i1 [[CMP1]]
99;
100  %z = or i8 %_z, 1
101  %cmp1 = icmp eq i8 %x, 0
102  %sel = select i1 %cmp1, i8 %z, i8 2
103  call void @use(i8 %sel)
104  %cmp2 = icmp eq i8 %sel, %z
105  ret i1 %cmp2
106}
107
108define i1 @icmp_select_var_pred_ne(i8 %x, i8 %y, i8 %z) {
109; CHECK-LABEL: @icmp_select_var_pred_ne(
110; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0
111; CHECK-NEXT:    [[CMP21:%.*]] = icmp ne i8 [[Y:%.*]], [[Z:%.*]]
112; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false
113; CHECK-NEXT:    ret i1 [[CMP2]]
114;
115  %cmp1 = icmp eq i8 %x, 0
116  %sel = select i1 %cmp1, i8 %z, i8 %y
117  %cmp2 = icmp ne i8 %sel, %z
118  ret i1 %cmp2
119}
120
121define i1 @icmp_select_var_pred_ult(i8 %x, i8 %y, i8 %z) {
122; CHECK-LABEL: @icmp_select_var_pred_ult(
123; CHECK-NEXT:    [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2
124; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
125; CHECK-NEXT:    [[CMP21:%.*]] = icmp ult i8 [[Y:%.*]], [[Z1]]
126; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
127; CHECK-NEXT:    ret i1 [[CMP2]]
128;
129  %z1 = add nuw i8 %z, 2
130  %cmp1 = icmp eq i8 %x, 0
131  %sel = select i1 %cmp1, i8 %z, i8 %y
132  %cmp2 = icmp ult i8 %sel, %z1
133  ret i1 %cmp2
134}
135
136define i1 @icmp_select_var_pred_uge(i8 %x, i8 %y, i8 %z) {
137; CHECK-LABEL: @icmp_select_var_pred_uge(
138; CHECK-NEXT:    [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2
139; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0
140; CHECK-NEXT:    [[CMP21:%.*]] = icmp uge i8 [[Y:%.*]], [[Z1]]
141; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false
142; CHECK-NEXT:    ret i1 [[CMP2]]
143;
144  %z1 = add nuw i8 %z, 2
145  %cmp1 = icmp eq i8 %x, 0
146  %sel = select i1 %cmp1, i8 %z, i8 %y
147  %cmp2 = icmp uge i8 %sel, %z1
148  ret i1 %cmp2
149}
150
151define i1 @icmp_select_var_pred_uge_commuted(i8 %x, i8 %y, i8 %z) {
152; CHECK-LABEL: @icmp_select_var_pred_uge_commuted(
153; CHECK-NEXT:    [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2
154; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
155; CHECK-NEXT:    [[CMP21:%.*]] = icmp ule i8 [[Y:%.*]], [[Z1]]
156; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
157; CHECK-NEXT:    ret i1 [[CMP2]]
158;
159  %z1 = add nuw i8 %z, 2
160  %cmp1 = icmp eq i8 %x, 0
161  %sel = select i1 %cmp1, i8 %z, i8 %y
162  %cmp2 = icmp uge i8 %z1, %sel
163  ret i1 %cmp2
164}
165
166define i1 @icmp_select_implied_cond(i8 %x, i8 %y) {
167; CHECK-LABEL: @icmp_select_implied_cond(
168; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
169; CHECK-NEXT:    [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[X]]
170; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
171; CHECK-NEXT:    ret i1 [[CMP2]]
172;
173  %cmp1 = icmp eq i8 %x, 0
174  %sel = select i1 %cmp1, i8 0, i8 %y
175  %cmp2 = icmp eq i8 %sel, %x
176  ret i1 %cmp2
177}
178
179define i1 @icmp_select_implied_cond_ne(i8 %x, i8 %y) {
180; CHECK-LABEL: @icmp_select_implied_cond_ne(
181; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0
182; CHECK-NEXT:    [[CMP21:%.*]] = icmp ne i8 [[Y:%.*]], [[X]]
183; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false
184; CHECK-NEXT:    ret i1 [[CMP2]]
185;
186  %cmp1 = icmp eq i8 %x, 0
187  %sel = select i1 %cmp1, i8 0, i8 %y
188  %cmp2 = icmp ne i8 %sel, %x
189  ret i1 %cmp2
190}
191
192define i1 @icmp_select_implied_cond_swapped_select(i8 %x, i8 %y) {
193; CHECK-LABEL: @icmp_select_implied_cond_swapped_select(
194; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
195; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[Y:%.*]], 0
196; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[TMP1]], i1 false
197; CHECK-NEXT:    ret i1 [[CMP2]]
198;
199  %cmp1 = icmp eq i8 %x, 0
200  %sel = select i1 %cmp1, i8 %y, i8 0
201  %cmp2 = icmp eq i8 %sel, %x
202  ret i1 %cmp2
203}
204
205define i1 @icmp_select_implied_cond_swapped_select_with_inv_cond(i8 %x, i8 %y) {
206; CHECK-LABEL: @icmp_select_implied_cond_swapped_select_with_inv_cond(
207; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0
208; CHECK-NEXT:    call void @use.i1(i1 [[CMP1]])
209; CHECK-NEXT:    [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[X]]
210; CHECK-NEXT:    [[NOT_CMP1:%.*]] = xor i1 [[CMP1]], true
211; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[NOT_CMP1]], i1 true, i1 [[CMP21]]
212; CHECK-NEXT:    ret i1 [[CMP2]]
213;
214  %cmp1 = icmp ne i8 %x, 0
215  call void @use.i1(i1 %cmp1)
216  %sel = select i1 %cmp1, i8 %y, i8 0
217  %cmp2 = icmp eq i8 %sel, %x
218  ret i1 %cmp2
219}
220
221define i1 @icmp_select_implied_cond_relational(i8 %x, i8 %y) {
222; CHECK-LABEL: @icmp_select_implied_cond_relational(
223; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 [[X:%.*]], 10
224; CHECK-NEXT:    [[CMP21:%.*]] = icmp ult i8 [[Y:%.*]], [[X]]
225; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
226; CHECK-NEXT:    ret i1 [[CMP2]]
227;
228  %cmp1 = icmp ugt i8 %x, 10
229  %sel = select i1 %cmp1, i8 10, i8 %y
230  %cmp2 = icmp ult i8 %sel, %x
231  ret i1 %cmp2
232}
233
234define i1 @icmp_select_implied_cond_relational_off_by_one(i8 %x, i8 %y) {
235; CHECK-LABEL: @icmp_select_implied_cond_relational_off_by_one(
236; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 [[X:%.*]], 10
237; CHECK-NEXT:    call void @use.i1(i1 [[CMP1]])
238; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i8 11, i8 [[Y:%.*]]
239; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 [[SEL]], [[X]]
240; CHECK-NEXT:    ret i1 [[CMP2]]
241;
242  %cmp1 = icmp ugt i8 %x, 10
243  call void @use.i1(i1 %cmp1)
244  %sel = select i1 %cmp1, i8 11, i8 %y
245  %cmp2 = icmp ult i8 %sel, %x
246  ret i1 %cmp2
247}
248
249define i1 @umin_seq_comparison(i8 %x, i8 %y) {
250; CHECK-LABEL: @umin_seq_comparison(
251; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
252; CHECK-NEXT:    [[CMP21:%.*]] = icmp ule i8 [[X]], [[Y:%.*]]
253; CHECK-NEXT:    [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
254; CHECK-NEXT:    ret i1 [[CMP2]]
255;
256  %min = call i8 @llvm.umin.i8(i8 %x, i8 %y)
257  %cmp1 = icmp eq i8 %x, 0
258  %sel = select i1 %cmp1, i8 0, i8 %min
259  %cmp2 = icmp eq i8 %sel, %x
260  ret i1 %cmp2
261}
262
263; ((A ? TC : FC) & (B ? TC : FC)) == 0 --> xor A, B
264
265define i1 @select_constants_and_icmp_eq0(i1 %x, i1 %y) {
266; CHECK-LABEL: @select_constants_and_icmp_eq0(
267; CHECK-NEXT:    [[CMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
268; CHECK-NEXT:    ret i1 [[CMP]]
269;
270  %s1 = select i1 %x, i8 2, i8 1
271  %s2 = select i1 %y, i8 2, i8 1
272  %and = and i8 %s1, %s2
273  %cmp = icmp eq i8 %and, 0
274  ret i1 %cmp
275}
276
277; extra uses on all intermediates are ok
278
279define i1 @select_constants_and_icmp_eq0_uses(i1 %x, i1 %y) {
280; CHECK-LABEL: @select_constants_and_icmp_eq0_uses(
281; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 2, i8 1
282; CHECK-NEXT:    call void @use(i8 [[S1]])
283; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 2, i8 1
284; CHECK-NEXT:    call void @use(i8 [[S2]])
285; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
286; CHECK-NEXT:    call void @use(i8 [[AND]])
287; CHECK-NEXT:    [[CMP:%.*]] = xor i1 [[X]], [[Y]]
288; CHECK-NEXT:    ret i1 [[CMP]]
289;
290  %s1 = select i1 %x, i8 2, i8 1
291  call void @use(i8 %s1)
292  %s2 = select i1 %y, i8 2, i8 1
293  call void @use(i8 %s2)
294  %and = and i8 %s1, %s2
295  call void @use(i8 %and)
296  %cmp = icmp eq i8 %and, 0
297  ret i1 %cmp
298}
299
300; vector splat constants are ok
301
302define <2 x i1> @select_constants_and_icmp_eq0_vec_splat(<2 x i1> %x, <2 x i1> %y) {
303; CHECK-LABEL: @select_constants_and_icmp_eq0_vec_splat(
304; CHECK-NEXT:    [[CMP:%.*]] = xor <2 x i1> [[X:%.*]], [[Y:%.*]]
305; CHECK-NEXT:    ret <2 x i1> [[CMP]]
306;
307  %s1 = select <2 x i1> %x, <2 x i9> <i9 3, i9 3>, <2 x i9> <i9 48, i9 48>
308  %s2 = select <2 x i1> %y, <2 x i9> <i9 3, i9 3>, <2 x i9> <i9 48, i9 48>
309  %and = and <2 x i9> %s1, %s2
310  %cmp = icmp eq <2 x i9> %and, zeroinitializer
311  ret <2 x i1> %cmp
312}
313
314; common bit set - simplified via known bits
315
316define i1 @select_constants_and_icmp_eq0_common_bit(i1 %x, i1 %y) {
317; CHECK-LABEL: @select_constants_and_icmp_eq0_common_bit(
318; CHECK-NEXT:    ret i1 false
319;
320  %s1 = select i1 %x, i8 2, i8 3
321  %s2 = select i1 %y, i8 2, i8 3
322  %and = and i8 %s1, %s2
323  %cmp = icmp eq i8 %and, 0
324  ret i1 %cmp
325}
326
327; negative test - need matching constants
328
329define i1 @select_constants_and_icmp_eq0_no_common_op1(i1 %x, i1 %y) {
330; CHECK-LABEL: @select_constants_and_icmp_eq0_no_common_op1(
331; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3
332; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 24, i8 3
333; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
334; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], 0
335; CHECK-NEXT:    ret i1 [[CMP]]
336;
337  %s1 = select i1 %x, i8 16, i8 3
338  %s2 = select i1 %y, i8 24, i8 3
339  %and = and i8 %s1, %s2
340  %cmp = icmp eq i8 %and, 0
341  ret i1 %cmp
342}
343
344; negative test - need matching constants
345
346define i1 @select_constants_and_icmp_eq0_no_common_op2(i1 %x, i1 %y) {
347; CHECK-LABEL: @select_constants_and_icmp_eq0_no_common_op2(
348; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3
349; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 16, i8 7
350; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
351; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], 0
352; CHECK-NEXT:    ret i1 [[CMP]]
353;
354  %s1 = select i1 %x, i8 16, i8 3
355  %s2 = select i1 %y, i8 16, i8 7
356  %and = and i8 %s1, %s2
357  %cmp = icmp eq i8 %and, 0
358  ret i1 %cmp
359}
360
361; reduces via FoldOpInstSelect, but this could be a simple 'or'
362
363define i1 @select_constants_and_icmp_eq0_zero_tval(i1 %x, i1 %y) {
364; CHECK-LABEL: @select_constants_and_icmp_eq0_zero_tval(
365; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]]
366; CHECK-NEXT:    ret i1 [[TMP1]]
367;
368  %s1 = select i1 %x, i8 0, i8 12
369  %s2 = select i1 %y, i8 0, i8 12
370  %and = and i8 %s1, %s2
371  %cmp = icmp eq i8 %and, 0
372  ret i1 %cmp
373}
374
375; reduces via FoldOpInstSelect, but this could be a simple 'not-of-and'
376
377define i1 @select_constants_and_icmp_eq0_zero_fval(i1 %x, i1 %y) {
378; CHECK-LABEL: @select_constants_and_icmp_eq0_zero_fval(
379; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false
380; CHECK-NEXT:    [[NOT_:%.*]] = xor i1 [[TMP1]], true
381; CHECK-NEXT:    ret i1 [[NOT_]]
382;
383  %s1 = select i1 %x, i8 12, i8 0
384  %s2 = select i1 %y, i8 12, i8 0
385  %and = and i8 %s1, %s2
386  %cmp = icmp eq i8 %and, 0
387  ret i1 %cmp
388}
389
390; TODO: x & y
391
392define i1 @select_constants_and_icmp_eq_tval(i1 %x, i1 %y) {
393; CHECK-LABEL: @select_constants_and_icmp_eq_tval(
394; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 6, i8 1
395; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 6, i8 1
396; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
397; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], 6
398; CHECK-NEXT:    ret i1 [[CMP]]
399;
400  %s1 = select i1 %x, i8 6, i8 1
401  %s2 = select i1 %y, i8 6, i8 1
402  %and = and i8 %s1, %s2
403  %cmp = icmp eq i8 %and, 6
404  ret i1 %cmp
405}
406
407; TODO: ~(x | y)
408
409define i1 @select_constants_and_icmp_eq_fval(i1 %x, i1 %y) {
410; CHECK-LABEL: @select_constants_and_icmp_eq_fval(
411; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 12, i8 3
412; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 12, i8 3
413; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
414; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], 3
415; CHECK-NEXT:    ret i1 [[CMP]]
416;
417  %s1 = select i1 %x, i8 12, i8 3
418  %s2 = select i1 %y, i8 12, i8 3
419  %and = and i8 %s1, %s2
420  %cmp = icmp eq i8 %and, 3
421  ret i1 %cmp
422}
423
424; ((A ? TC : FC) & (B ? TC : FC)) != 0 --> not(xor A, B)
425
426define i1 @select_constants_and_icmp_ne0(i1 %x, i1 %y) {
427; CHECK-LABEL: @select_constants_and_icmp_ne0(
428; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
429; CHECK-NEXT:    [[CMP:%.*]] = xor i1 [[TMP1]], true
430; CHECK-NEXT:    ret i1 [[CMP]]
431;
432  %s1 = select i1 %x, i8 2, i8 1
433  %s2 = select i1 %y, i8 2, i8 1
434  %and = and i8 %s1, %s2
435  %cmp = icmp ne i8 %and, 0
436  ret i1 %cmp
437}
438
439; extra uses on select intermediates are ok
440
441define i1 @select_constants_and_icmp_ne0_uses(i1 %x, i1 %y) {
442; CHECK-LABEL: @select_constants_and_icmp_ne0_uses(
443; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 2, i8 1
444; CHECK-NEXT:    call void @use(i8 [[S1]])
445; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 2, i8 1
446; CHECK-NEXT:    call void @use(i8 [[S2]])
447; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[X]], [[Y]]
448; CHECK-NEXT:    [[CMP:%.*]] = xor i1 [[TMP1]], true
449; CHECK-NEXT:    ret i1 [[CMP]]
450;
451  %s1 = select i1 %x, i8 2, i8 1
452  call void @use(i8 %s1)
453  %s2 = select i1 %y, i8 2, i8 1
454  call void @use(i8 %s2)
455  %and = and i8 %s1, %s2
456  %cmp = icmp ne i8 %and, 0
457  ret i1 %cmp
458}
459
460; negative test - don't create extra instructions
461
462define i1 @select_constants_and_icmp_ne0_all_uses(i1 %x, i1 %y) {
463; CHECK-LABEL: @select_constants_and_icmp_ne0_all_uses(
464; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 2, i8 1
465; CHECK-NEXT:    call void @use(i8 [[S1]])
466; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 2, i8 1
467; CHECK-NEXT:    call void @use(i8 [[S2]])
468; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
469; CHECK-NEXT:    call void @use(i8 [[AND]])
470; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[AND]], 0
471; CHECK-NEXT:    ret i1 [[CMP]]
472;
473  %s1 = select i1 %x, i8 2, i8 1
474  call void @use(i8 %s1)
475  %s2 = select i1 %y, i8 2, i8 1
476  call void @use(i8 %s2)
477  %and = and i8 %s1, %s2
478  call void @use(i8 %and)
479  %cmp = icmp ne i8 %and, 0
480  ret i1 %cmp
481}
482
483; vector splat constants are ok
484
485define <2 x i1> @select_constants_and_icmp_ne0_vec_splat(<2 x i1> %x, <2 x i1> %y) {
486; CHECK-LABEL: @select_constants_and_icmp_ne0_vec_splat(
487; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i1> [[X:%.*]], [[Y:%.*]]
488; CHECK-NEXT:    [[CMP:%.*]] = xor <2 x i1> [[TMP1]], splat (i1 true)
489; CHECK-NEXT:    ret <2 x i1> [[CMP]]
490;
491  %s1 = select <2 x i1> %x, <2 x i9> <i9 3, i9 3>, <2 x i9> <i9 48, i9 48>
492  %s2 = select <2 x i1> %y, <2 x i9> <i9 3, i9 3>, <2 x i9> <i9 48, i9 48>
493  %and = and <2 x i9> %s1, %s2
494  %cmp = icmp ne <2 x i9> %and, zeroinitializer
495  ret <2 x i1> %cmp
496}
497
498; common bit set - simplified via known bits
499
500define i1 @select_constants_and_icmp_ne0_common_bit(i1 %x, i1 %y) {
501; CHECK-LABEL: @select_constants_and_icmp_ne0_common_bit(
502; CHECK-NEXT:    ret i1 true
503;
504  %s1 = select i1 %x, i8 2, i8 3
505  %s2 = select i1 %y, i8 2, i8 3
506  %and = and i8 %s1, %s2
507  %cmp = icmp ne i8 %and, 0
508  ret i1 %cmp
509}
510
511; negative test - need matching constants
512
513define i1 @select_constants_and_icmp_ne0_no_common_op1(i1 %x, i1 %y) {
514; CHECK-LABEL: @select_constants_and_icmp_ne0_no_common_op1(
515; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3
516; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 24, i8 3
517; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
518; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[AND]], 0
519; CHECK-NEXT:    ret i1 [[CMP]]
520;
521  %s1 = select i1 %x, i8 16, i8 3
522  %s2 = select i1 %y, i8 24, i8 3
523  %and = and i8 %s1, %s2
524  %cmp = icmp ne i8 %and, 0
525  ret i1 %cmp
526}
527
528; negative test - need matching constants
529
530define i1 @select_constants_and_icmp_ne0_no_common_op2(i1 %x, i1 %y) {
531; CHECK-LABEL: @select_constants_and_icmp_ne0_no_common_op2(
532; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3
533; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 16, i8 7
534; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
535; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[AND]], 0
536; CHECK-NEXT:    ret i1 [[CMP]]
537;
538  %s1 = select i1 %x, i8 16, i8 3
539  %s2 = select i1 %y, i8 16, i8 7
540  %and = and i8 %s1, %s2
541  %cmp = icmp ne i8 %and, 0
542  ret i1 %cmp
543}
544
545; reduces via FoldOpInstSelect, but this could be a simple 'nor'
546
547define i1 @select_constants_and_icmp_ne0_zero_tval(i1 %x, i1 %y) {
548; CHECK-LABEL: @select_constants_and_icmp_ne0_zero_tval(
549; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]]
550; CHECK-NEXT:    [[NOT_:%.*]] = xor i1 [[TMP1]], true
551; CHECK-NEXT:    ret i1 [[NOT_]]
552;
553  %s1 = select i1 %x, i8 0, i8 12
554  %s2 = select i1 %y, i8 0, i8 12
555  %and = and i8 %s1, %s2
556  %cmp = icmp ne i8 %and, 0
557  ret i1 %cmp
558}
559
560; reduces via FoldOpInstSelect, but this could be a simple 'and'
561
562define i1 @select_constants_and_icmp_ne0_zero_fval(i1 %x, i1 %y) {
563; CHECK-LABEL: @select_constants_and_icmp_ne0_zero_fval(
564; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false
565; CHECK-NEXT:    ret i1 [[TMP1]]
566;
567  %s1 = select i1 %x, i8 12, i8 0
568  %s2 = select i1 %y, i8 12, i8 0
569  %and = and i8 %s1, %s2
570  %cmp = icmp ne i8 %and, 0
571  ret i1 %cmp
572}
573
574; TODO: ~(x & y)
575
576define i1 @select_constants_and_icmp_ne_tval(i1 %x, i1 %y) {
577; CHECK-LABEL: @select_constants_and_icmp_ne_tval(
578; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 6, i8 1
579; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 6, i8 1
580; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
581; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[AND]], 6
582; CHECK-NEXT:    ret i1 [[CMP]]
583;
584  %s1 = select i1 %x, i8 6, i8 1
585  %s2 = select i1 %y, i8 6, i8 1
586  %and = and i8 %s1, %s2
587  %cmp = icmp ne i8 %and, 6
588  ret i1 %cmp
589}
590
591; TODO: (x | y)
592
593define i1 @select_constants_and_icmp_ne_fval(i1 %x, i1 %y) {
594; CHECK-LABEL: @select_constants_and_icmp_ne_fval(
595; CHECK-NEXT:    [[S1:%.*]] = select i1 [[X:%.*]], i8 12, i8 3
596; CHECK-NEXT:    [[S2:%.*]] = select i1 [[Y:%.*]], i8 12, i8 3
597; CHECK-NEXT:    [[AND:%.*]] = and i8 [[S1]], [[S2]]
598; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[AND]], 3
599; CHECK-NEXT:    ret i1 [[CMP]]
600;
601  %s1 = select i1 %x, i8 12, i8 3
602  %s2 = select i1 %y, i8 12, i8 3
603  %and = and i8 %s1, %s2
604  %cmp = icmp ne i8 %and, 3
605  ret i1 %cmp
606}
607
608define i1 @icmp_eq_select(i1 %cond, i32 %a, i32 %b) {
609; CHECK-LABEL: @icmp_eq_select(
610; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
611; CHECK-NEXT:    ret i1 [[RES]]
612;
613  %lhs = select i1 %cond, i32 %a, i32 %b
614  %rhs = select i1 %cond, i32 %b, i32 %a
615  %res = icmp eq i32 %lhs, %rhs
616  ret i1 %res
617}
618
619define i1 @icmp_slt_select(i1 %cond, i32 %a, i32 %b) {
620; CHECK-LABEL: @icmp_slt_select(
621; CHECK-NEXT:    [[LHS:%.*]] = select i1 [[COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]
622; CHECK-NEXT:    [[RHS:%.*]] = select i1 [[COND]], i32 [[B]], i32 [[A]]
623; CHECK-NEXT:    [[RES:%.*]] = icmp slt i32 [[LHS]], [[RHS]]
624; CHECK-NEXT:    ret i1 [[RES]]
625;
626  %lhs = select i1 %cond, i32 %a, i32 %b
627  %rhs = select i1 %cond, i32 %b, i32 %a
628  %res = icmp slt i32 %lhs, %rhs
629  ret i1 %res
630}
631