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