1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; https://bugs.llvm.org/show_bug.cgi?id=6773
5
6; Pattern:
7;   (x | ~m) & (y & m)
8; Should be transformed into:
9;   (x & m) | (y & ~m)
10; And then into:
11;   ((x ^ y) & m) ^ y
12
13; ============================================================================ ;
14; Most basic positive tests
15; ============================================================================ ;
16
17define i32 @p(i32 %x, i32 %y, i32 %m) {
18; CHECK-LABEL: @p(
19; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
20; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
21; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
22; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
23; CHECK-NEXT:    ret i32 [[RET]]
24;
25  %neg = xor i32 %m, -1
26  %or = or i32 %neg, %x
27  %or1 = or i32 %y, %m
28  %ret = and i32 %or, %or1
29  ret i32 %ret
30}
31
32define <2 x i32> @p_splatvec(<2 x i32> %x, <2 x i32> %y, <2 x i32> %m) {
33; CHECK-LABEL: @p_splatvec(
34; CHECK-NEXT:    [[NEG:%.*]] = xor <2 x i32> [[M:%.*]], <i32 -1, i32 -1>
35; CHECK-NEXT:    [[OR:%.*]] = or <2 x i32> [[NEG]], [[X:%.*]]
36; CHECK-NEXT:    [[OR1:%.*]] = or <2 x i32> [[Y:%.*]], [[M]]
37; CHECK-NEXT:    [[RET:%.*]] = and <2 x i32> [[OR]], [[OR1]]
38; CHECK-NEXT:    ret <2 x i32> [[RET]]
39;
40  %neg = xor <2 x i32> %m, <i32 -1, i32 -1>
41  %or = or <2 x i32> %neg, %x
42  %or1 = or <2 x i32> %y, %m
43  %ret = and <2 x i32> %or, %or1
44  ret <2 x i32> %ret
45}
46
47define <3 x i32> @p_vec_undef(<3 x i32> %x, <3 x i32> %y, <3 x i32> %m) {
48; CHECK-LABEL: @p_vec_undef(
49; CHECK-NEXT:    [[NEG:%.*]] = xor <3 x i32> [[M:%.*]], <i32 -1, i32 undef, i32 -1>
50; CHECK-NEXT:    [[OR:%.*]] = or <3 x i32> [[NEG]], [[X:%.*]]
51; CHECK-NEXT:    [[OR1:%.*]] = or <3 x i32> [[Y:%.*]], [[M]]
52; CHECK-NEXT:    [[RET:%.*]] = and <3 x i32> [[OR]], [[OR1]]
53; CHECK-NEXT:    ret <3 x i32> [[RET]]
54;
55  %neg = xor <3 x i32> %m, <i32 -1, i32 undef, i32 -1>
56  %or = or <3 x i32> %neg, %x
57  %or1 = or <3 x i32> %y, %m
58  %ret = and <3 x i32> %or, %or1
59  ret <3 x i32> %ret
60}
61
62; ============================================================================ ;
63; Constant mask.
64; ============================================================================ ;
65
66define i32 @p_constmask(i32 %x, i32 %y) {
67; CHECK-LABEL: @p_constmask(
68; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -65281
69; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], 65280
70; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
71; CHECK-NEXT:    ret i32 [[RET]]
72;
73  %or = or i32 %x, -65281
74  %or1 = or i32 %y, 65280
75  %ret = and i32 %or, %or1
76  ret i32 %ret
77}
78
79define <2 x i32> @p_constmask_splatvec(<2 x i32> %x, <2 x i32> %y) {
80; CHECK-LABEL: @p_constmask_splatvec(
81; CHECK-NEXT:    [[OR:%.*]] = or <2 x i32> [[X:%.*]], <i32 -65281, i32 -65281>
82; CHECK-NEXT:    [[OR1:%.*]] = or <2 x i32> [[Y:%.*]], <i32 65280, i32 65280>
83; CHECK-NEXT:    [[RET:%.*]] = and <2 x i32> [[OR]], [[OR1]]
84; CHECK-NEXT:    ret <2 x i32> [[RET]]
85;
86  %or = or <2 x i32> %x, <i32 -65281, i32 -65281>
87  %or1 = or <2 x i32> %y, <i32 65280, i32 65280>
88  %ret = and <2 x i32> %or, %or1
89  ret <2 x i32> %ret
90}
91
92define <2 x i32> @p_constmask_vec(<2 x i32> %x, <2 x i32> %y) {
93; CHECK-LABEL: @p_constmask_vec(
94; CHECK-NEXT:    [[OR:%.*]] = or <2 x i32> [[X:%.*]], <i32 -65281, i32 -16776961>
95; CHECK-NEXT:    [[OR1:%.*]] = or <2 x i32> [[Y:%.*]], <i32 65280, i32 16776960>
96; CHECK-NEXT:    [[RET:%.*]] = and <2 x i32> [[OR]], [[OR1]]
97; CHECK-NEXT:    ret <2 x i32> [[RET]]
98;
99  %or = or <2 x i32> %x, <i32 -65281, i32 -16776961>
100  %or1 = or <2 x i32> %y, <i32 65280, i32 16776960>
101  %ret = and <2 x i32> %or, %or1
102  ret <2 x i32> %ret
103}
104
105define <3 x i32> @p_constmask_vec_undef(<3 x i32> %x, <3 x i32> %y) {
106; CHECK-LABEL: @p_constmask_vec_undef(
107; CHECK-NEXT:    [[OR:%.*]] = or <3 x i32> [[X:%.*]], <i32 -65281, i32 undef, i32 -65281>
108; CHECK-NEXT:    [[OR1:%.*]] = or <3 x i32> [[Y:%.*]], <i32 65280, i32 undef, i32 65280>
109; CHECK-NEXT:    [[RET:%.*]] = and <3 x i32> [[OR]], [[OR1]]
110; CHECK-NEXT:    ret <3 x i32> [[RET]]
111;
112  %or = or <3 x i32> %x, <i32 -65281, i32 undef, i32 -65281>
113  %or1 = or <3 x i32> %y, <i32 65280, i32 undef, i32 65280>
114  %ret = and <3 x i32> %or, %or1
115  ret <3 x i32> %ret
116}
117
118; ============================================================================ ;
119; Commutativity.
120; ============================================================================ ;
121
122; Used to make sure that the IR complexity sorting does not interfere.
123declare i32 @gen32()
124
125define i32 @p_commutative0(i32 %x, i32 %y, i32 %m) {
126; CHECK-LABEL: @p_commutative0(
127; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
128; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
129; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
130; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
131; CHECK-NEXT:    ret i32 [[RET]]
132;
133  %neg = xor i32 %m, -1
134  %or = or i32 %x, %neg ; swapped order
135  %or1 = or i32 %y, %m
136  %ret = and i32 %or, %or1
137  ret i32 %ret
138}
139
140define i32 @p_commutative1(i32 %x, i32 %m) {
141; CHECK-LABEL: @p_commutative1(
142; CHECK-NEXT:    [[Y:%.*]] = call i32 @gen32()
143; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
144; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
145; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y]], [[M]]
146; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
147; CHECK-NEXT:    ret i32 [[RET]]
148;
149  %y = call i32 @gen32()
150  %neg = xor i32 %m, -1
151  %or = or i32 %neg, %x
152  %or1 = or i32 %m, %y; swapped order
153  %ret = and i32 %or, %or1
154  ret i32 %ret
155}
156
157define i32 @p_commutative2(i32 %x, i32 %y, i32 %m) {
158; CHECK-LABEL: @p_commutative2(
159; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
160; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
161; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
162; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR1]], [[OR]]
163; CHECK-NEXT:    ret i32 [[RET]]
164;
165  %neg = xor i32 %m, -1
166  %or = or i32 %neg, %x
167  %or1 = or i32 %y, %m
168  %ret = and i32 %or1, %or ; swapped order
169  ret i32 %ret
170}
171
172define i32 @p_commutative3(i32 %x, i32 %m) {
173; CHECK-LABEL: @p_commutative3(
174; CHECK-NEXT:    [[Y:%.*]] = call i32 @gen32()
175; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
176; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
177; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y]], [[M]]
178; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
179; CHECK-NEXT:    ret i32 [[RET]]
180;
181  %y = call i32 @gen32()
182  %neg = xor i32 %m, -1
183  %or = or i32 %x, %neg ; swapped order
184  %or1 = or i32 %m, %y; swapped order
185  %ret = and i32 %or, %or1
186  ret i32 %ret
187}
188
189define i32 @p_commutative4(i32 %x, i32 %y, i32 %m) {
190; CHECK-LABEL: @p_commutative4(
191; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
192; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
193; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
194; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR1]], [[OR]]
195; CHECK-NEXT:    ret i32 [[RET]]
196;
197  %neg = xor i32 %m, -1
198  %or = or i32 %x, %neg ; swapped order
199  %or1 = or i32 %y, %m
200  %ret = and i32 %or1, %or ; swapped order
201  ret i32 %ret
202}
203
204define i32 @p_commutative5(i32 %x, i32 %m) {
205; CHECK-LABEL: @p_commutative5(
206; CHECK-NEXT:    [[Y:%.*]] = call i32 @gen32()
207; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
208; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
209; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y]], [[M]]
210; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR1]], [[OR]]
211; CHECK-NEXT:    ret i32 [[RET]]
212;
213  %y = call i32 @gen32()
214  %neg = xor i32 %m, -1
215  %or = or i32 %neg, %x
216  %or1 = or i32 %m, %y; swapped order
217  %ret = and i32 %or1, %or ; swapped order
218  ret i32 %ret
219}
220
221define i32 @p_commutative6(i32 %x, i32 %m) {
222; CHECK-LABEL: @p_commutative6(
223; CHECK-NEXT:    [[Y:%.*]] = call i32 @gen32()
224; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
225; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
226; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y]], [[M]]
227; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR1]], [[OR]]
228; CHECK-NEXT:    ret i32 [[RET]]
229;
230  %y = call i32 @gen32()
231  %neg = xor i32 %m, -1
232  %or = or i32 %x, %neg ; swapped order
233  %or1 = or i32 %m, %y; swapped order
234  %ret = and i32 %or1, %or ; swapped order
235  ret i32 %ret
236}
237
238define i32 @p_constmask_commutative(i32 %x, i32 %y) {
239; CHECK-LABEL: @p_constmask_commutative(
240; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -65281
241; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], 65280
242; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR1]], [[OR]]
243; CHECK-NEXT:    ret i32 [[RET]]
244;
245  %or = or i32 %x, -65281
246  %or1 = or i32 %y, 65280
247  %ret = and i32 %or1, %or ; swapped order
248  ret i32 %ret
249}
250
251; ============================================================================ ;
252; Negative tests. Should not be folded.
253; ============================================================================ ;
254
255; One use only.
256
257declare void @use32(i32)
258
259define i32 @n0_oneuse_of_neg_is_ok_0(i32 %x, i32 %y, i32 %m) {
260; CHECK-LABEL: @n0_oneuse_of_neg_is_ok_0(
261; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
262; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
263; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
264; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
265; CHECK-NEXT:    call void @use32(i32 [[NEG]])
266; CHECK-NEXT:    ret i32 [[RET]]
267;
268  %neg = xor i32 %m, -1
269  %or = or i32 %neg, %x
270  %or1 = or i32 %y, %m
271  %ret = and i32 %or, %or1
272  call void @use32(i32 %neg)
273  ret i32 %ret
274}
275
276define i32 @n0_oneuse_1(i32 %x, i32 %y, i32 %m) {
277; CHECK-LABEL: @n0_oneuse_1(
278; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
279; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
280; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
281; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
282; CHECK-NEXT:    call void @use32(i32 [[OR]])
283; CHECK-NEXT:    ret i32 [[RET]]
284;
285  %neg = xor i32 %m, -1
286  %or = or i32 %neg, %x
287  %or1 = or i32 %y, %m
288  %ret = and i32 %or, %or1
289  call void @use32(i32 %or)
290  ret i32 %ret
291}
292
293define i32 @n0_oneuse_2(i32 %x, i32 %y, i32 %m) {
294; CHECK-LABEL: @n0_oneuse_2(
295; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
296; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
297; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
298; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
299; CHECK-NEXT:    call void @use32(i32 [[OR1]])
300; CHECK-NEXT:    ret i32 [[RET]]
301;
302  %neg = xor i32 %m, -1
303  %or = or i32 %neg, %x
304  %or1 = or i32 %y, %m
305  %ret = and i32 %or, %or1
306  call void @use32(i32 %or1)
307  ret i32 %ret
308}
309
310define i32 @n0_oneuse_3(i32 %x, i32 %y, i32 %m) {
311; CHECK-LABEL: @n0_oneuse_3(
312; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
313; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
314; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
315; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
316; CHECK-NEXT:    call void @use32(i32 [[NEG]])
317; CHECK-NEXT:    call void @use32(i32 [[OR]])
318; CHECK-NEXT:    ret i32 [[RET]]
319;
320  %neg = xor i32 %m, -1
321  %or = or i32 %neg, %x
322  %or1 = or i32 %y, %m
323  %ret = and i32 %or, %or1
324  call void @use32(i32 %neg)
325  call void @use32(i32 %or)
326  ret i32 %ret
327}
328
329define i32 @n0_oneuse_4(i32 %x, i32 %y, i32 %m) {
330; CHECK-LABEL: @n0_oneuse_4(
331; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
332; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
333; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
334; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
335; CHECK-NEXT:    call void @use32(i32 [[NEG]])
336; CHECK-NEXT:    call void @use32(i32 [[OR1]])
337; CHECK-NEXT:    ret i32 [[RET]]
338;
339  %neg = xor i32 %m, -1
340  %or = or i32 %neg, %x
341  %or1 = or i32 %y, %m
342  %ret = and i32 %or, %or1
343  call void @use32(i32 %neg)
344  call void @use32(i32 %or1)
345  ret i32 %ret
346}
347
348define i32 @n0_oneuse_5(i32 %x, i32 %y, i32 %m) {
349; CHECK-LABEL: @n0_oneuse_5(
350; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
351; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
352; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
353; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
354; CHECK-NEXT:    call void @use32(i32 [[NEG]])
355; CHECK-NEXT:    call void @use32(i32 [[OR]])
356; CHECK-NEXT:    call void @use32(i32 [[OR1]])
357; CHECK-NEXT:    ret i32 [[RET]]
358;
359  %neg = xor i32 %m, -1
360  %or = or i32 %neg, %x
361  %or1 = or i32 %y, %m
362  %ret = and i32 %or, %or1
363  call void @use32(i32 %neg)
364  call void @use32(i32 %or)
365  call void @use32(i32 %or1)
366  ret i32 %ret
367}
368
369define i32 @n0_oneuse_6(i32 %x, i32 %y, i32 %m) {
370; CHECK-LABEL: @n0_oneuse_6(
371; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], -1
372; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
373; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
374; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
375; CHECK-NEXT:    call void @use32(i32 [[OR]])
376; CHECK-NEXT:    call void @use32(i32 [[OR1]])
377; CHECK-NEXT:    ret i32 [[RET]]
378;
379  %neg = xor i32 %m, -1
380  %or = or i32 %neg, %x
381  %or1 = or i32 %y, %m
382  %ret = and i32 %or, %or1
383  call void @use32(i32 %or)
384  call void @use32(i32 %or1)
385  ret i32 %ret
386}
387
388; One-use with constant mask
389
390define i32 @n0_constmask_oneuse_0(i32 %x, i32 %y) {
391; CHECK-LABEL: @n0_constmask_oneuse_0(
392; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -65281
393; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], 65280
394; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
395; CHECK-NEXT:    call void @use32(i32 [[OR]])
396; CHECK-NEXT:    ret i32 [[RET]]
397;
398  %or = or i32 %x, -65281
399  %or1 = or i32 %y, 65280
400  %ret = and i32 %or, %or1
401  call void @use32(i32 %or)
402  ret i32 %ret
403}
404
405define i32 @n0_constmask_oneuse_1(i32 %x, i32 %y) {
406; CHECK-LABEL: @n0_constmask_oneuse_1(
407; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -65281
408; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], 65280
409; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
410; CHECK-NEXT:    call void @use32(i32 [[OR1]])
411; CHECK-NEXT:    ret i32 [[RET]]
412;
413  %or = or i32 %x, -65281
414  %or1 = or i32 %y, 65280
415  %ret = and i32 %or, %or1
416  call void @use32(i32 %or1)
417  ret i32 %ret
418}
419
420define i32 @n0_constmask_oneuse_2(i32 %x, i32 %y) {
421; CHECK-LABEL: @n0_constmask_oneuse_2(
422; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -65281
423; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], 65280
424; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
425; CHECK-NEXT:    call void @use32(i32 [[OR]])
426; CHECK-NEXT:    call void @use32(i32 [[OR1]])
427; CHECK-NEXT:    ret i32 [[RET]]
428;
429  %or = or i32 %x, -65281
430  %or1 = or i32 %y, 65280
431  %ret = and i32 %or, %or1
432  call void @use32(i32 %or)
433  call void @use32(i32 %or1)
434  ret i32 %ret
435}
436
437; Bad xor constant
438
439define i32 @n1_badxor(i32 %x, i32 %y, i32 %m) {
440; CHECK-LABEL: @n1_badxor(
441; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M:%.*]], 1
442; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
443; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], [[M]]
444; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
445; CHECK-NEXT:    ret i32 [[RET]]
446;
447  %neg = xor i32 %m, 1 ; not -1
448  %or = or i32 %neg, %x
449  %or1 = or i32 %y, %m
450  %ret = and i32 %or, %or1
451  ret i32 %ret
452}
453
454; Different mask is used
455
456define i32 @n2_badmask(i32 %x, i32 %y, i32 %m1, i32 %m2) {
457; CHECK-LABEL: @n2_badmask(
458; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M2:%.*]], -1
459; CHECK-NEXT:    [[OR:%.*]] = or i32 [[NEG]], [[X:%.*]]
460; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[M1:%.*]], [[Y:%.*]]
461; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
462; CHECK-NEXT:    ret i32 [[RET]]
463;
464  %neg = xor i32 %m2, -1 ; different mask, not %m1
465  %or = or i32 %neg, %x
466  %or1 = or i32 %m1, %y
467  %ret = and i32 %or, %or1
468  ret i32 %ret
469}
470
471; Different const mask is used
472
473define i32 @n3_constmask_badmask_set(i32 %x, i32 %y) {
474; CHECK-LABEL: @n3_constmask_badmask_set(
475; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -65281
476; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], 65281
477; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
478; CHECK-NEXT:    ret i32 [[RET]]
479;
480  %or = or i32 %x, -65281
481  %or1 = or i32 %y, 65281 ; not 65280, so they have one common bit
482  %ret = and i32 %or, %or1
483  ret i32 %ret
484}
485
486define i32 @n3_constmask_badmask_unset(i32 %x, i32 %y) {
487; CHECK-LABEL: @n3_constmask_badmask_unset(
488; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -65281
489; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[Y:%.*]], 65024
490; CHECK-NEXT:    [[RET:%.*]] = and i32 [[OR]], [[OR1]]
491; CHECK-NEXT:    ret i32 [[RET]]
492;
493  %or = or i32 %x, -65281
494  %or1 = or i32 %y, 65024 ; not 65280, so they have one common unset bit
495  %ret = and i32 %or, %or1
496  ret i32 %ret
497}
498
499define i32 @n3_constmask_samemask(i32 %x, i32 %y) {
500; CHECK-LABEL: @n3_constmask_samemask(
501; CHECK-NEXT:    [[OR2:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
502; CHECK-NEXT:    [[RET:%.*]] = or i32 [[OR2]], -65281
503; CHECK-NEXT:    ret i32 [[RET]]
504;
505  %or = or i32 %x, -65281
506  %or1 = or i32 %y, -65281 ; both masks are the same
507  %ret = and i32 %or, %or1
508  ret i32 %ret
509}
510