xref: /llvm-project/llvm/test/Transforms/InstCombine/masked-merge-add.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
4; https://bugs.llvm.org/show_bug.cgi?id=6773
5
6; Patterns:
7;   (x & m) | (y & ~m)
8;   (x & m) ^ (y & ~m)
9;   (x & m) + (y & ~m)
10; Should be transformed into:
11;   (x & m) | (y & ~m)
12; And then into:
13;   ((x ^ y) & m) ^ y
14
15; ============================================================================ ;
16; Most basic positive tests
17; ============================================================================ ;
18
19define i32 @p(i32 %x, i32 %y, i32 noundef %m) {
20; CHECK-LABEL: @p(
21; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
22; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
23; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]
24; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]
25; CHECK-NEXT:    ret i32 [[RET]]
26;
27  %and = and i32 %x, %m
28  %neg = xor i32 %m, -1
29  %and1 = and i32 %neg, %y
30  %ret = add i32 %and, %and1
31  ret i32 %ret
32}
33
34define <2 x i32> @p_splatvec(<2 x i32> %x, <2 x i32> %y, <2 x i32> noundef %m) {
35; CHECK-LABEL: @p_splatvec(
36; CHECK-NEXT:    [[AND:%.*]] = and <2 x i32> [[X:%.*]], [[M:%.*]]
37; CHECK-NEXT:    [[NEG:%.*]] = xor <2 x i32> [[M]], splat (i32 -1)
38; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i32> [[Y:%.*]], [[NEG]]
39; CHECK-NEXT:    [[RET:%.*]] = or disjoint <2 x i32> [[AND]], [[AND1]]
40; CHECK-NEXT:    ret <2 x i32> [[RET]]
41;
42  %and = and <2 x i32> %x, %m
43  %neg = xor <2 x i32> %m, <i32 -1, i32 -1>
44  %and1 = and <2 x i32> %neg, %y
45  %ret = add <2 x i32> %and, %and1
46  ret <2 x i32> %ret
47}
48
49define <3 x i32> @p_vec_undef(<3 x i32> %x, <3 x i32> %y, <3 x i32> noundef %m) {
50; CHECK-LABEL: @p_vec_undef(
51; CHECK-NEXT:    [[AND:%.*]] = and <3 x i32> [[X:%.*]], [[M:%.*]]
52; CHECK-NEXT:    [[NEG:%.*]] = xor <3 x i32> [[M]], <i32 -1, i32 undef, i32 -1>
53; CHECK-NEXT:    [[AND1:%.*]] = and <3 x i32> [[NEG]], [[Y:%.*]]
54; CHECK-NEXT:    [[RET:%.*]] = add <3 x i32> [[AND]], [[AND1]]
55; CHECK-NEXT:    ret <3 x i32> [[RET]]
56;
57  %and = and <3 x i32> %x, %m
58  %neg = xor <3 x i32> %m, <i32 -1, i32 undef, i32 -1>
59  %and1 = and <3 x i32> %neg, %y
60  %ret = add <3 x i32> %and, %and1
61  ret <3 x i32> %ret
62}
63
64define <3 x i32> @p_vec_poison(<3 x i32> %x, <3 x i32> %y, <3 x i32> noundef %m) {
65; CHECK-LABEL: @p_vec_poison(
66; CHECK-NEXT:    [[AND:%.*]] = and <3 x i32> [[X:%.*]], [[M:%.*]]
67; CHECK-NEXT:    [[NEG:%.*]] = xor <3 x i32> [[M]], <i32 -1, i32 poison, i32 -1>
68; CHECK-NEXT:    [[AND1:%.*]] = and <3 x i32> [[Y:%.*]], [[NEG]]
69; CHECK-NEXT:    [[RET:%.*]] = or disjoint <3 x i32> [[AND]], [[AND1]]
70; CHECK-NEXT:    ret <3 x i32> [[RET]]
71;
72  %and = and <3 x i32> %x, %m
73  %neg = xor <3 x i32> %m, <i32 -1, i32 poison, i32 -1>
74  %and1 = and <3 x i32> %neg, %y
75  %ret = add <3 x i32> %and, %and1
76  ret <3 x i32> %ret
77}
78
79; ============================================================================ ;
80; Constant mask.
81; ============================================================================ ;
82
83define i32 @p_constmask(i32 %x, i32 %y) {
84; CHECK-LABEL: @p_constmask(
85; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 65280
86; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], -65281
87; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]
88; CHECK-NEXT:    ret i32 [[RET]]
89;
90  %and = and i32 %x, 65280
91  %and1 = and i32 %y, -65281
92  %ret = add i32 %and, %and1
93  ret i32 %ret
94}
95
96define <2 x i32> @p_constmask_splatvec(<2 x i32> %x, <2 x i32> %y) {
97; CHECK-LABEL: @p_constmask_splatvec(
98; CHECK-NEXT:    [[AND:%.*]] = and <2 x i32> [[X:%.*]], splat (i32 65280)
99; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i32> [[Y:%.*]], splat (i32 -65281)
100; CHECK-NEXT:    [[RET:%.*]] = or disjoint <2 x i32> [[AND]], [[AND1]]
101; CHECK-NEXT:    ret <2 x i32> [[RET]]
102;
103  %and = and <2 x i32> %x, <i32 65280, i32 65280>
104  %and1 = and <2 x i32> %y, <i32 -65281, i32 -65281>
105  %ret = add <2 x i32> %and, %and1
106  ret <2 x i32> %ret
107}
108
109define <2 x i32> @p_constmask_vec(<2 x i32> %x, <2 x i32> %y) {
110; CHECK-LABEL: @p_constmask_vec(
111; CHECK-NEXT:    [[AND:%.*]] = and <2 x i32> [[X:%.*]], <i32 65280, i32 16776960>
112; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i32> [[Y:%.*]], <i32 -65281, i32 -16776961>
113; CHECK-NEXT:    [[RET:%.*]] = add <2 x i32> [[AND]], [[AND1]]
114; CHECK-NEXT:    ret <2 x i32> [[RET]]
115;
116  %and = and <2 x i32> %x, <i32 65280, i32 16776960>
117  %and1 = and <2 x i32> %y, <i32 -65281, i32 -16776961>
118  %ret = add <2 x i32> %and, %and1
119  ret <2 x i32> %ret
120}
121
122define <3 x i32> @p_constmask_vec_undef(<3 x i32> %x, <3 x i32> %y) {
123; CHECK-LABEL: @p_constmask_vec_undef(
124; CHECK-NEXT:    [[AND:%.*]] = and <3 x i32> [[X:%.*]], <i32 65280, i32 undef, i32 65280>
125; CHECK-NEXT:    [[AND1:%.*]] = and <3 x i32> [[Y:%.*]], <i32 -65281, i32 undef, i32 -65281>
126; CHECK-NEXT:    [[RET:%.*]] = add <3 x i32> [[AND]], [[AND1]]
127; CHECK-NEXT:    ret <3 x i32> [[RET]]
128;
129  %and = and <3 x i32> %x, <i32 65280, i32 undef, i32 65280>
130  %and1 = and <3 x i32> %y, <i32 -65281, i32 undef, i32 -65281>
131  %ret = add <3 x i32> %and, %and1
132  ret <3 x i32> %ret
133}
134
135; ============================================================================ ;
136; Constant mask with no common bits set, but common unset bits.
137; ============================================================================ ;
138
139define i32 @p_constmask2(i32 %x, i32 %y) {
140; CHECK-LABEL: @p_constmask2(
141; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 61440
142; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], -65281
143; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]
144; CHECK-NEXT:    ret i32 [[RET]]
145;
146  %and = and i32 %x, 61440
147  %and1 = and i32 %y, -65281
148  %ret = add i32 %and, %and1
149  ret i32 %ret
150}
151
152define <2 x i32> @p_constmask2_splatvec(<2 x i32> %x, <2 x i32> %y) {
153; CHECK-LABEL: @p_constmask2_splatvec(
154; CHECK-NEXT:    [[AND:%.*]] = and <2 x i32> [[X:%.*]], splat (i32 61440)
155; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i32> [[Y:%.*]], splat (i32 -65281)
156; CHECK-NEXT:    [[RET:%.*]] = or disjoint <2 x i32> [[AND]], [[AND1]]
157; CHECK-NEXT:    ret <2 x i32> [[RET]]
158;
159  %and = and <2 x i32> %x, <i32 61440, i32 61440>
160  %and1 = and <2 x i32> %y, <i32 -65281, i32 -65281>
161  %ret = add <2 x i32> %and, %and1
162  ret <2 x i32> %ret
163}
164
165define <2 x i32> @p_constmask2_vec(<2 x i32> %x, <2 x i32> %y) {
166; CHECK-LABEL: @p_constmask2_vec(
167; CHECK-NEXT:    [[AND:%.*]] = and <2 x i32> [[X:%.*]], <i32 61440, i32 16711680>
168; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i32> [[Y:%.*]], <i32 -65281, i32 -16776961>
169; CHECK-NEXT:    [[RET:%.*]] = add <2 x i32> [[AND]], [[AND1]]
170; CHECK-NEXT:    ret <2 x i32> [[RET]]
171;
172  %and = and <2 x i32> %x, <i32 61440, i32 16711680>
173  %and1 = and <2 x i32> %y, <i32 -65281, i32 -16776961>
174  %ret = add <2 x i32> %and, %and1
175  ret <2 x i32> %ret
176}
177
178define <3 x i32> @p_constmask2_vec_undef(<3 x i32> %x, <3 x i32> %y) {
179; CHECK-LABEL: @p_constmask2_vec_undef(
180; CHECK-NEXT:    [[AND:%.*]] = and <3 x i32> [[X:%.*]], <i32 61440, i32 undef, i32 61440>
181; CHECK-NEXT:    [[AND1:%.*]] = and <3 x i32> [[Y:%.*]], <i32 -65281, i32 undef, i32 -65281>
182; CHECK-NEXT:    [[RET:%.*]] = add <3 x i32> [[AND]], [[AND1]]
183; CHECK-NEXT:    ret <3 x i32> [[RET]]
184;
185  %and = and <3 x i32> %x, <i32 61440, i32 undef, i32 61440>
186  %and1 = and <3 x i32> %y, <i32 -65281, i32 undef, i32 -65281>
187  %ret = add <3 x i32> %and, %and1
188  ret <3 x i32> %ret
189}
190
191; ============================================================================ ;
192; Commutativity.
193; ============================================================================ ;
194
195; Used to make sure that the IR complexity sorting does not interfere.
196declare i32 @gen32()
197
198define i32 @p_commutative0(i32 %x, i32 %y, i32 noundef %m) {
199; CHECK-LABEL: @p_commutative0(
200; CHECK-NEXT:    [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
201; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
202; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]
203; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]
204; CHECK-NEXT:    ret i32 [[RET]]
205;
206  %and = and i32 %m, %x ; swapped order
207  %neg = xor i32 %m, -1
208  %and1 = and i32 %neg, %y
209  %ret = add i32 %and, %and1
210  ret i32 %ret
211}
212
213define i32 @p_commutative1(i32 %x, i32 noundef %m) {
214; CHECK-LABEL: @p_commutative1(
215; CHECK-NEXT:    [[Y:%.*]] = call i32 @gen32()
216; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
217; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
218; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
219; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]
220; CHECK-NEXT:    ret i32 [[RET]]
221;
222  %y = call i32 @gen32()
223  %and = and i32 %x, %m
224  %neg = xor i32 %m, -1
225  %and1 = and i32 %y, %neg; swapped order
226  %ret = add i32 %and, %and1
227  ret i32 %ret
228}
229
230define i32 @p_commutative2(i32 %x, i32 %y, i32 noundef %m) {
231; CHECK-LABEL: @p_commutative2(
232; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
233; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
234; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]
235; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND1]], [[AND]]
236; CHECK-NEXT:    ret i32 [[RET]]
237;
238  %and = and i32 %x, %m
239  %neg = xor i32 %m, -1
240  %and1 = and i32 %neg, %y
241  %ret = add i32 %and1, %and ; swapped order
242  ret i32 %ret
243}
244
245define i32 @p_commutative3(i32 %x, i32 noundef %m) {
246; CHECK-LABEL: @p_commutative3(
247; CHECK-NEXT:    [[Y:%.*]] = call i32 @gen32()
248; CHECK-NEXT:    [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
249; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
250; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
251; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]
252; CHECK-NEXT:    ret i32 [[RET]]
253;
254  %y = call i32 @gen32()
255  %and = and i32 %m, %x ; swapped order
256  %neg = xor i32 %m, -1
257  %and1 = and i32 %y, %neg; swapped order
258  %ret = add i32 %and, %and1
259  ret i32 %ret
260}
261
262define i32 @p_commutative4(i32 %x, i32 %y, i32 noundef %m) {
263; CHECK-LABEL: @p_commutative4(
264; CHECK-NEXT:    [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
265; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
266; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]
267; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND1]], [[AND]]
268; CHECK-NEXT:    ret i32 [[RET]]
269;
270  %and = and i32 %m, %x ; swapped order
271  %neg = xor i32 %m, -1
272  %and1 = and i32 %neg, %y
273  %ret = add i32 %and1, %and ; swapped order
274  ret i32 %ret
275}
276
277define i32 @p_commutative5(i32 %x, i32 noundef %m) {
278; CHECK-LABEL: @p_commutative5(
279; CHECK-NEXT:    [[Y:%.*]] = call i32 @gen32()
280; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
281; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
282; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
283; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND1]], [[AND]]
284; CHECK-NEXT:    ret i32 [[RET]]
285;
286  %y = call i32 @gen32()
287  %and = and i32 %x, %m
288  %neg = xor i32 %m, -1
289  %and1 = and i32 %y, %neg; swapped order
290  %ret = add i32 %and1, %and ; swapped order
291  ret i32 %ret
292}
293
294define i32 @p_commutative6(i32 %x, i32 noundef %m) {
295; CHECK-LABEL: @p_commutative6(
296; CHECK-NEXT:    [[Y:%.*]] = call i32 @gen32()
297; CHECK-NEXT:    [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
298; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
299; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
300; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND1]], [[AND]]
301; CHECK-NEXT:    ret i32 [[RET]]
302;
303  %y = call i32 @gen32()
304  %and = and i32 %m, %x ; swapped order
305  %neg = xor i32 %m, -1
306  %and1 = and i32 %y, %neg; swapped order
307  %ret = add i32 %and1, %and ; swapped order
308  ret i32 %ret
309}
310
311define i32 @p_constmask_commutative(i32 %x, i32 %y) {
312; CHECK-LABEL: @p_constmask_commutative(
313; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 65280
314; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], -65281
315; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND1]], [[AND]]
316; CHECK-NEXT:    ret i32 [[RET]]
317;
318  %and = and i32 %x, 65280
319  %and1 = and i32 %y, -65281
320  %ret = add i32 %and1, %and ; swapped order
321  ret i32 %ret
322}
323
324; ============================================================================ ;
325; Negative tests. Should not be folded.
326; ============================================================================ ;
327
328; One use only.
329
330declare void @use32(i32)
331
332define i32 @n0_oneuse(i32 %x, i32 %y, i32 noundef %m) {
333; CHECK-LABEL: @n0_oneuse(
334; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
335; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
336; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]
337; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]
338; CHECK-NEXT:    call void @use32(i32 [[AND]])
339; CHECK-NEXT:    call void @use32(i32 [[NEG]])
340; CHECK-NEXT:    call void @use32(i32 [[AND1]])
341; CHECK-NEXT:    ret i32 [[RET]]
342;
343  %and = and i32 %x, %m
344  %neg = xor i32 %m, -1
345  %and1 = and i32 %neg, %y
346  %ret = add i32 %and, %and1
347  call void @use32(i32 %and)
348  call void @use32(i32 %neg)
349  call void @use32(i32 %and1)
350  ret i32 %ret
351}
352
353define i32 @n0_constmask_oneuse(i32 %x, i32 %y) {
354; CHECK-LABEL: @n0_constmask_oneuse(
355; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 65280
356; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], -65281
357; CHECK-NEXT:    [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]
358; CHECK-NEXT:    call void @use32(i32 [[AND]])
359; CHECK-NEXT:    call void @use32(i32 [[AND1]])
360; CHECK-NEXT:    ret i32 [[RET]]
361;
362  %and = and i32 %x, 65280
363  %and1 = and i32 %y, -65281
364  %ret = add i32 %and, %and1
365  call void @use32(i32 %and)
366  call void @use32(i32 %and1)
367  ret i32 %ret
368}
369
370; Bad xor constant
371
372define i32 @n1_badxor(i32 %x, i32 %y, i32 %m) {
373; CHECK-LABEL: @n1_badxor(
374; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
375; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], 1
376; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]
377; CHECK-NEXT:    [[RET:%.*]] = add i32 [[AND]], [[AND1]]
378; CHECK-NEXT:    ret i32 [[RET]]
379;
380  %and = and i32 %x, %m
381  %neg = xor i32 %m, 1 ; not -1
382  %and1 = and i32 %neg, %y
383  %ret = add i32 %and, %and1
384  ret i32 %ret
385}
386
387; Different mask is used
388
389define i32 @n2_badmask(i32 %x, i32 %y, i32 %m1, i32 %m2) {
390; CHECK-LABEL: @n2_badmask(
391; CHECK-NEXT:    [[AND:%.*]] = and i32 [[M1:%.*]], [[X:%.*]]
392; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M2:%.*]], -1
393; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]
394; CHECK-NEXT:    [[RET:%.*]] = add i32 [[AND]], [[AND1]]
395; CHECK-NEXT:    ret i32 [[RET]]
396;
397  %and = and i32 %m1, %x
398  %neg = xor i32 %m2, -1 ; different mask, not %m1
399  %and1 = and i32 %neg, %y
400  %ret = add i32 %and, %and1
401  ret i32 %ret
402}
403
404; Different const mask is used
405
406define i32 @n3_constmask_badmask(i32 %x, i32 %y) {
407; CHECK-LABEL: @n3_constmask_badmask(
408; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 65280
409; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], -65280
410; CHECK-NEXT:    [[RET:%.*]] = add i32 [[AND]], [[AND1]]
411; CHECK-NEXT:    ret i32 [[RET]]
412;
413  %and = and i32 %x, 65280
414  %and1 = and i32 %y, -65280 ; not -65281, so they have one common bit set
415  %ret = add i32 %and, %and1
416  ret i32 %ret
417}
418
419define i32 @n3_constmask_samemask(i32 %x, i32 %y) {
420; CHECK-LABEL: @n3_constmask_samemask(
421; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 65280
422; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y:%.*]], 65280
423; CHECK-NEXT:    [[RET:%.*]] = add nuw nsw i32 [[AND]], [[AND1]]
424; CHECK-NEXT:    ret i32 [[RET]]
425;
426  %and = and i32 %x, 65280
427  %and1 = and i32 %y, 65280 ; both masks are the same
428  %ret = add i32 %and, %and1
429  ret i32 %ret
430}
431