xref: /llvm-project/llvm/test/Transforms/InstCombine/and-or-not.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(i4)
5
6; PR1510
7
8; (a | b) & ~(a & b) --> a ^ b
9
10define i32 @and_to_xor1(i32 %a, i32 %b) {
11; CHECK-LABEL: @and_to_xor1(
12; CHECK-NEXT:    [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
13; CHECK-NEXT:    ret i32 [[AND2]]
14;
15  %or = or i32 %a, %b
16  %and = and i32 %a, %b
17  %not = xor i32 %and, -1
18  %and2 = and i32 %or, %not
19  ret i32 %and2
20}
21
22; ~(a & b) & (a | b) --> a ^ b
23
24define i32 @and_to_xor2(i32 %a, i32 %b) {
25; CHECK-LABEL: @and_to_xor2(
26; CHECK-NEXT:    [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
27; CHECK-NEXT:    ret i32 [[AND2]]
28;
29  %or = or i32 %a, %b
30  %and = and i32 %a, %b
31  %not = xor i32 %and, -1
32  %and2 = and i32 %not, %or
33  ret i32 %and2
34}
35
36; (a | b) & ~(b & a) --> a ^ b
37
38define i32 @and_to_xor3(i32 %a, i32 %b) {
39; CHECK-LABEL: @and_to_xor3(
40; CHECK-NEXT:    [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
41; CHECK-NEXT:    ret i32 [[AND2]]
42;
43  %or = or i32 %a, %b
44  %and = and i32 %b, %a
45  %not = xor i32 %and, -1
46  %and2 = and i32 %or, %not
47  ret i32 %and2
48}
49
50; ~(a & b) & (b | a) --> a ^ b
51
52define i32 @and_to_xor4(i32 %a, i32 %b) {
53; CHECK-LABEL: @and_to_xor4(
54; CHECK-NEXT:    [[AND2:%.*]] = xor i32 [[B:%.*]], [[A:%.*]]
55; CHECK-NEXT:    ret i32 [[AND2]]
56;
57  %or = or i32 %b, %a
58  %and = and i32 %a, %b
59  %not = xor i32 %and, -1
60  %and2 = and i32 %not, %or
61  ret i32 %and2
62}
63
64define <4 x i32> @and_to_xor1_vec(<4 x i32> %a, <4 x i32> %b) {
65; CHECK-LABEL: @and_to_xor1_vec(
66; CHECK-NEXT:    [[AND2:%.*]] = xor <4 x i32> [[A:%.*]], [[B:%.*]]
67; CHECK-NEXT:    ret <4 x i32> [[AND2]]
68;
69  %or = or <4 x i32> %a, %b
70  %and = and <4 x i32> %a, %b
71  %not = xor <4 x i32> %and, < i32 -1, i32 -1, i32 -1, i32 -1 >
72  %and2 = and <4 x i32> %or, %not
73  ret <4 x i32> %and2
74}
75
76; In the next 4 tests, cast instructions are used to thwart operand complexity
77; canonicalizations, so we can test all of the commuted patterns.
78
79; (a | ~b) & (~a | b) --> ~(a ^ b)
80
81define i32 @and_to_nxor1(float %fa, float %fb) {
82; CHECK-LABEL: @and_to_nxor1(
83; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
84; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
85; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A]], [[B]]
86; CHECK-NEXT:    [[AND:%.*]] = xor i32 [[TMP1]], -1
87; CHECK-NEXT:    ret i32 [[AND]]
88;
89  %a = fptosi float %fa to i32
90  %b = fptosi float %fb to i32
91  %nota = xor i32 %a, -1
92  %notb = xor i32 %b, -1
93  %or1 = or i32 %a, %notb
94  %or2 = or i32 %nota, %b
95  %and = and i32 %or1, %or2
96  ret i32 %and
97}
98
99; (a | ~b) & (b | ~a) --> ~(a ^ b)
100
101define i32 @and_to_nxor2(float %fa, float %fb) {
102; CHECK-LABEL: @and_to_nxor2(
103; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
104; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
105; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A]], [[B]]
106; CHECK-NEXT:    [[AND:%.*]] = xor i32 [[TMP1]], -1
107; CHECK-NEXT:    ret i32 [[AND]]
108;
109  %a = fptosi float %fa to i32
110  %b = fptosi float %fb to i32
111  %nota = xor i32 %a, -1
112  %notb = xor i32 %b, -1
113  %or1 = or i32 %a, %notb
114  %or2 = or i32 %b, %nota
115  %and = and i32 %or1, %or2
116  ret i32 %and
117}
118
119; (~a | b) & (a | ~b) --> ~(a ^ b)
120
121define i32 @and_to_nxor3(float %fa, float %fb) {
122; CHECK-LABEL: @and_to_nxor3(
123; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
124; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
125; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[B]], [[A]]
126; CHECK-NEXT:    [[AND:%.*]] = xor i32 [[TMP1]], -1
127; CHECK-NEXT:    ret i32 [[AND]]
128;
129  %a = fptosi float %fa to i32
130  %b = fptosi float %fb to i32
131  %nota = xor i32 %a, -1
132  %notb = xor i32 %b, -1
133  %or1 = or i32 %nota, %b
134  %or2 = or i32 %a, %notb
135  %and = and i32 %or1, %or2
136  ret i32 %and
137}
138
139; (~a | b) & (~b | a) --> ~(a ^ b)
140
141define i32 @and_to_nxor4(float %fa, float %fb) {
142; CHECK-LABEL: @and_to_nxor4(
143; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
144; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
145; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[B]], [[A]]
146; CHECK-NEXT:    [[AND:%.*]] = xor i32 [[TMP1]], -1
147; CHECK-NEXT:    ret i32 [[AND]]
148;
149  %a = fptosi float %fa to i32
150  %b = fptosi float %fb to i32
151  %nota = xor i32 %a, -1
152  %notb = xor i32 %b, -1
153  %or1 = or i32 %nota, %b
154  %or2 = or i32 %notb, %a
155  %and = and i32 %or1, %or2
156  ret i32 %and
157}
158
159; (a & ~b) | (~a & b) --> a ^ b
160
161define i32 @or_to_xor1(float %fa, float %fb) {
162; CHECK-LABEL: @or_to_xor1(
163; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
164; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
165; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[A]], [[B]]
166; CHECK-NEXT:    ret i32 [[OR]]
167;
168  %a = fptosi float %fa to i32
169  %b = fptosi float %fb to i32
170  %nota = xor i32 %a, -1
171  %notb = xor i32 %b, -1
172  %and1 = and i32 %a, %notb
173  %and2 = and i32 %nota, %b
174  %or = or i32 %and1, %and2
175  ret i32 %or
176}
177
178; (a & ~b) | (b & ~a) --> a ^ b
179
180define i32 @or_to_xor2(float %fa, float %fb) {
181; CHECK-LABEL: @or_to_xor2(
182; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
183; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
184; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[A]], [[B]]
185; CHECK-NEXT:    ret i32 [[OR]]
186;
187  %a = fptosi float %fa to i32
188  %b = fptosi float %fb to i32
189  %nota = xor i32 %a, -1
190  %notb = xor i32 %b, -1
191  %and1 = and i32 %a, %notb
192  %and2 = and i32 %b, %nota
193  %or = or i32 %and1, %and2
194  ret i32 %or
195}
196
197; (~a & b) | (~b & a) --> a ^ b
198
199define i32 @or_to_xor3(float %fa, float %fb) {
200; CHECK-LABEL: @or_to_xor3(
201; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
202; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
203; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[B]], [[A]]
204; CHECK-NEXT:    ret i32 [[OR]]
205;
206  %a = fptosi float %fa to i32
207  %b = fptosi float %fb to i32
208  %nota = xor i32 %a, -1
209  %notb = xor i32 %b, -1
210  %and1 = and i32 %nota, %b
211  %and2 = and i32 %notb, %a
212  %or = or i32 %and1, %and2
213  ret i32 %or
214}
215
216; (~a & b) | (a & ~b) --> a ^ b
217
218define i32 @or_to_xor4(float %fa, float %fb) {
219; CHECK-LABEL: @or_to_xor4(
220; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
221; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
222; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[B]], [[A]]
223; CHECK-NEXT:    ret i32 [[OR]]
224;
225  %a = fptosi float %fa to i32
226  %b = fptosi float %fb to i32
227  %nota = xor i32 %a, -1
228  %notb = xor i32 %b, -1
229  %and1 = and i32 %nota, %b
230  %and2 = and i32 %a, %notb
231  %or = or i32 %and1, %and2
232  ret i32 %or
233}
234
235; (a & b) | ~(a | b) --> ~(a ^ b)
236
237define i32 @or_to_nxor1(i32 %a, i32 %b) {
238; CHECK-LABEL: @or_to_nxor1(
239; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
240; CHECK-NEXT:    [[OR2:%.*]] = xor i32 [[TMP1]], -1
241; CHECK-NEXT:    ret i32 [[OR2]]
242;
243  %and = and i32 %a, %b
244  %or = or i32 %a, %b
245  %notor = xor i32 %or, -1
246  %or2 = or i32 %and, %notor
247  ret i32 %or2
248}
249
250; (a & b) | ~(b | a) --> ~(a ^ b)
251
252define i32 @or_to_nxor2(i32 %a, i32 %b) {
253; CHECK-LABEL: @or_to_nxor2(
254; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
255; CHECK-NEXT:    [[OR2:%.*]] = xor i32 [[TMP1]], -1
256; CHECK-NEXT:    ret i32 [[OR2]]
257;
258  %and = and i32 %a, %b
259  %or = or i32 %b, %a
260  %notor = xor i32 %or, -1
261  %or2 = or i32 %and, %notor
262  ret i32 %or2
263}
264
265; ~(a | b) | (a & b) --> ~(a ^ b)
266
267define i32 @or_to_nxor3(i32 %a, i32 %b) {
268; CHECK-LABEL: @or_to_nxor3(
269; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
270; CHECK-NEXT:    [[OR2:%.*]] = xor i32 [[TMP1]], -1
271; CHECK-NEXT:    ret i32 [[OR2]]
272;
273  %and = and i32 %a, %b
274  %or = or i32 %a, %b
275  %notor = xor i32 %or, -1
276  %or2 = or i32 %notor, %and
277  ret i32 %or2
278}
279
280; ~(a | b) | (b & a) --> ~(a ^ b)
281
282define i32 @or_to_nxor4(i32 %a, i32 %b) {
283; CHECK-LABEL: @or_to_nxor4(
284; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[B:%.*]], [[A:%.*]]
285; CHECK-NEXT:    [[OR2:%.*]] = xor i32 [[TMP1]], -1
286; CHECK-NEXT:    ret i32 [[OR2]]
287;
288  %and = and i32 %b, %a
289  %or = or i32 %a, %b
290  %notor = xor i32 %or, -1
291  %or2 = or i32 %notor, %and
292  ret i32 %or2
293}
294
295; (a & b) ^ (a | b) --> a ^ b
296
297define i32 @xor_to_xor1(i32 %a, i32 %b) {
298; CHECK-LABEL: @xor_to_xor1(
299; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
300; CHECK-NEXT:    ret i32 [[XOR]]
301;
302  %and = and i32 %a, %b
303  %or = or i32 %a, %b
304  %xor = xor i32 %and, %or
305  ret i32 %xor
306}
307
308; (a & b) ^ (b | a) --> a ^ b
309
310define i32 @xor_to_xor2(i32 %a, i32 %b) {
311; CHECK-LABEL: @xor_to_xor2(
312; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
313; CHECK-NEXT:    ret i32 [[XOR]]
314;
315  %and = and i32 %a, %b
316  %or = or i32 %b, %a
317  %xor = xor i32 %and, %or
318  ret i32 %xor
319}
320
321; (a | b) ^ (a & b) --> a ^ b
322
323define i32 @xor_to_xor3(i32 %a, i32 %b) {
324; CHECK-LABEL: @xor_to_xor3(
325; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
326; CHECK-NEXT:    ret i32 [[XOR]]
327;
328  %or = or i32 %a, %b
329  %and = and i32 %a, %b
330  %xor = xor i32 %or, %and
331  ret i32 %xor
332}
333
334; (a | b) ^ (b & a) --> a ^ b
335
336define i32 @xor_to_xor4(i32 %a, i32 %b) {
337; CHECK-LABEL: @xor_to_xor4(
338; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[B:%.*]], [[A:%.*]]
339; CHECK-NEXT:    ret i32 [[XOR]]
340;
341  %or = or i32 %a, %b
342  %and = and i32 %b, %a
343  %xor = xor i32 %or, %and
344  ret i32 %xor
345}
346
347; (a | ~b) ^ (~a | b) --> a ^ b
348
349; In the next 8 tests, cast instructions are used to thwart operand complexity
350; canonicalizations, so we can test all of the commuted patterns.
351
352define i32 @xor_to_xor5(float %fa, float %fb) {
353; CHECK-LABEL: @xor_to_xor5(
354; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
355; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
356; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A]], [[B]]
357; CHECK-NEXT:    ret i32 [[XOR]]
358;
359  %a = fptosi float %fa to i32
360  %b = fptosi float %fb to i32
361  %nota = xor i32 %a, -1
362  %notb = xor i32 %b, -1
363  %or1 = or i32 %a, %notb
364  %or2 = or i32 %nota, %b
365  %xor = xor i32 %or1, %or2
366  ret i32 %xor
367}
368
369; (a | ~b) ^ (b | ~a) --> a ^ b
370
371define i32 @xor_to_xor6(float %fa, float %fb) {
372; CHECK-LABEL: @xor_to_xor6(
373; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
374; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
375; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A]], [[B]]
376; CHECK-NEXT:    ret i32 [[XOR]]
377;
378  %a = fptosi float %fa to i32
379  %b = fptosi float %fb to i32
380  %nota = xor i32 %a, -1
381  %notb = xor i32 %b, -1
382  %or1 = or i32 %a, %notb
383  %or2 = or i32 %b, %nota
384  %xor = xor i32 %or1, %or2
385  ret i32 %xor
386}
387
388; (~a | b) ^ (a | ~b) --> a ^ b
389
390define i32 @xor_to_xor7(float %fa, float %fb) {
391; CHECK-LABEL: @xor_to_xor7(
392; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
393; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
394; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[B]], [[A]]
395; CHECK-NEXT:    ret i32 [[XOR]]
396;
397  %a = fptosi float %fa to i32
398  %b = fptosi float %fb to i32
399  %nota = xor i32 %a, -1
400  %notb = xor i32 %b, -1
401  %or1 = or i32 %a, %notb
402  %or2 = or i32 %nota, %b
403  %xor = xor i32 %or2, %or1
404  ret i32 %xor
405}
406
407; (~a | b) ^ (~b | a) --> a ^ b
408
409define i32 @xor_to_xor8(float %fa, float %fb) {
410; CHECK-LABEL: @xor_to_xor8(
411; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
412; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
413; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[B]], [[A]]
414; CHECK-NEXT:    ret i32 [[XOR]]
415;
416  %a = fptosi float %fa to i32
417  %b = fptosi float %fb to i32
418  %nota = xor i32 %a, -1
419  %notb = xor i32 %b, -1
420  %or1 = or i32 %notb, %a
421  %or2 = or i32 %nota, %b
422  %xor = xor i32 %or2, %or1
423  ret i32 %xor
424}
425
426; (a & ~b) ^ (~a & b) --> a ^ b
427
428define i32 @xor_to_xor9(float %fa, float %fb) {
429; CHECK-LABEL: @xor_to_xor9(
430; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
431; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
432; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A]], [[B]]
433; CHECK-NEXT:    ret i32 [[XOR]]
434;
435  %a = fptosi float %fa to i32
436  %b = fptosi float %fb to i32
437  %nota = xor i32 %a, -1
438  %notb = xor i32 %b, -1
439  %and1 = and i32 %a, %notb
440  %and2 = and i32 %nota, %b
441  %xor = xor i32 %and1, %and2
442  ret i32 %xor
443}
444
445; (a & ~b) ^ (b & ~a) --> a ^ b
446
447define i32 @xor_to_xor10(float %fa, float %fb) {
448; CHECK-LABEL: @xor_to_xor10(
449; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
450; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
451; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A]], [[B]]
452; CHECK-NEXT:    ret i32 [[XOR]]
453;
454  %a = fptosi float %fa to i32
455  %b = fptosi float %fb to i32
456  %nota = xor i32 %a, -1
457  %notb = xor i32 %b, -1
458  %and1 = and i32 %a, %notb
459  %and2 = and i32 %b, %nota
460  %xor = xor i32 %and1, %and2
461  ret i32 %xor
462}
463
464; (~a & b) ^ (a & ~b) --> a ^ b
465
466define i32 @xor_to_xor11(float %fa, float %fb) {
467; CHECK-LABEL: @xor_to_xor11(
468; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
469; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
470; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[B]], [[A]]
471; CHECK-NEXT:    ret i32 [[XOR]]
472;
473  %a = fptosi float %fa to i32
474  %b = fptosi float %fb to i32
475  %nota = xor i32 %a, -1
476  %notb = xor i32 %b, -1
477  %and1 = and i32 %a, %notb
478  %and2 = and i32 %nota, %b
479  %xor = xor i32 %and2, %and1
480  ret i32 %xor
481}
482
483; (~a & b) ^ (~b & a) --> a ^ b
484
485define i32 @xor_to_xor12(float %fa, float %fb) {
486; CHECK-LABEL: @xor_to_xor12(
487; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
488; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
489; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[B]], [[A]]
490; CHECK-NEXT:    ret i32 [[XOR]]
491;
492  %a = fptosi float %fa to i32
493  %b = fptosi float %fb to i32
494  %nota = xor i32 %a, -1
495  %notb = xor i32 %b, -1
496  %and1 = and i32 %notb, %a
497  %and2 = and i32 %nota, %b
498  %xor = xor i32 %and2, %and1
499  ret i32 %xor
500}
501
502; https://bugs.llvm.org/show_bug.cgi?id=32830
503; Make sure we're matching operands correctly and not folding things wrongly.
504
505define i64 @PR32830(i64 %a, i64 %b, i64 %c) {
506; CHECK-LABEL: @PR32830(
507; CHECK-NEXT:    [[NOTA:%.*]] = xor i64 [[A:%.*]], -1
508; CHECK-NEXT:    [[NOTB:%.*]] = xor i64 [[B:%.*]], -1
509; CHECK-NEXT:    [[OR1:%.*]] = or i64 [[A]], [[NOTB]]
510; CHECK-NEXT:    [[OR2:%.*]] = or i64 [[C:%.*]], [[NOTA]]
511; CHECK-NEXT:    [[AND:%.*]] = and i64 [[OR1]], [[OR2]]
512; CHECK-NEXT:    ret i64 [[AND]]
513;
514  %nota = xor i64 %a, -1
515  %notb = xor i64 %b, -1
516  %or1 = or i64 %notb, %a
517  %or2 = or i64 %nota, %c
518  %and = and i64 %or1, %or2
519  ret i64 %and
520}
521
522; (~a | b) & (~b | a) --> ~(a ^ b)
523; TODO: this increases instruction count if the pieces have additional users
524define i32 @and_to_nxor_multiuse(float %fa, float %fb) {
525; CHECK-LABEL: @and_to_nxor_multiuse(
526; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
527; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
528; CHECK-NEXT:    [[NOTA:%.*]] = xor i32 [[A]], -1
529; CHECK-NEXT:    [[NOTB:%.*]] = xor i32 [[B]], -1
530; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[NOTA]], [[B]]
531; CHECK-NEXT:    [[OR2:%.*]] = or i32 [[NOTB]], [[A]]
532; CHECK-NEXT:    [[AND:%.*]] = and i32 [[OR1]], [[OR2]]
533; CHECK-NEXT:    [[MUL1:%.*]] = mul i32 [[OR1]], [[OR2]]
534; CHECK-NEXT:    [[MUL2:%.*]] = mul i32 [[MUL1]], [[AND]]
535; CHECK-NEXT:    ret i32 [[MUL2]]
536;
537  %a = fptosi float %fa to i32
538  %b = fptosi float %fb to i32
539  %nota = xor i32 %a, -1
540  %notb = xor i32 %b, -1
541  %or1 = or i32 %nota, %b
542  %or2 = or i32 %notb, %a
543  %and = and i32 %or1, %or2
544  %mul1 = mul i32 %or1, %or2 ; here to increase the use count of the inputs to the and
545  %mul2 = mul i32 %mul1, %and
546  ret i32 %mul2
547}
548
549; (a & b) | ~(a | b) --> ~(a ^ b)
550; TODO: this increases instruction count if the pieces have additional users
551define i32 @or_to_nxor_multiuse(i32 noundef %a, i32 noundef %b) {
552; CHECK-LABEL: @or_to_nxor_multiuse(
553; CHECK-NEXT:    [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
554; CHECK-NEXT:    [[OR:%.*]] = or i32 [[A]], [[B]]
555; CHECK-NEXT:    [[NOTOR:%.*]] = xor i32 [[OR]], -1
556; CHECK-NEXT:    [[OR2:%.*]] = or disjoint i32 [[AND]], [[NOTOR]]
557; CHECK-NEXT:    [[MUL1:%.*]] = mul i32 [[AND]], [[NOTOR]]
558; CHECK-NEXT:    [[MUL2:%.*]] = mul i32 [[MUL1]], [[OR2]]
559; CHECK-NEXT:    ret i32 [[MUL2]]
560;
561  %and = and i32 %a, %b
562  %or = or i32 %a, %b
563  %notor = xor i32 %or, -1
564  %or2 = or i32 %and, %notor
565  %mul1 = mul i32 %and, %notor ; here to increase the use count of the inputs to the or
566  %mul2 = mul i32 %mul1, %or2
567  ret i32 %mul2
568}
569
570; (a | b) ^ (~a | ~b) --> ~(a ^ b)
571define i32 @xor_to_xnor1(float %fa, float %fb) {
572; CHECK-LABEL: @xor_to_xnor1(
573; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
574; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
575; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A]], [[B]]
576; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[TMP1]], -1
577; CHECK-NEXT:    ret i32 [[XOR]]
578;
579  %a = fptosi float %fa to i32
580  %b = fptosi float %fb to i32
581  %nota = xor i32 %a, -1
582  %notb = xor i32 %b, -1
583  %or1 = or i32 %a, %b
584  %or2 = or i32 %nota, %notb
585  %xor = xor i32 %or1, %or2
586  ret i32 %xor
587}
588
589; (a | b) ^ (~b | ~a) --> ~(a ^ b)
590define i32 @xor_to_xnor2(float %fa, float %fb) {
591; CHECK-LABEL: @xor_to_xnor2(
592; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
593; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
594; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A]], [[B]]
595; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[TMP1]], -1
596; CHECK-NEXT:    ret i32 [[XOR]]
597;
598  %a = fptosi float %fa to i32
599  %b = fptosi float %fb to i32
600  %nota = xor i32 %a, -1
601  %notb = xor i32 %b, -1
602  %or1 = or i32 %a, %b
603  %or2 = or i32 %notb, %nota
604  %xor = xor i32 %or1, %or2
605  ret i32 %xor
606}
607
608; (~a | ~b) ^ (a | b) --> ~(a ^ b)
609define i32 @xor_to_xnor3(float %fa, float %fb) {
610; CHECK-LABEL: @xor_to_xnor3(
611; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
612; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
613; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A]], [[B]]
614; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[TMP1]], -1
615; CHECK-NEXT:    ret i32 [[XOR]]
616;
617  %a = fptosi float %fa to i32
618  %b = fptosi float %fb to i32
619  %nota = xor i32 %a, -1
620  %notb = xor i32 %b, -1
621  %or1 = or i32 %nota, %notb
622  %or2 = or i32 %a, %b
623  %xor = xor i32 %or1, %or2
624  ret i32 %xor
625}
626
627; (~a | ~b) ^ (b | a) --> ~(a ^ b)
628define i32 @xor_to_xnor4(float %fa, float %fb) {
629; CHECK-LABEL: @xor_to_xnor4(
630; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
631; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
632; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[B]], [[A]]
633; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[TMP1]], -1
634; CHECK-NEXT:    ret i32 [[XOR]]
635;
636  %a = fptosi float %fa to i32
637  %b = fptosi float %fb to i32
638  %nota = xor i32 %a, -1
639  %notb = xor i32 %b, -1
640  %or1 = or i32 %nota, %notb
641  %or2 = or i32 %b, %a
642  %xor = xor i32 %or1, %or2
643  ret i32 %xor
644}
645
646define i4 @simplify_or_common_op_commute0(i4 %x, i4 %y, i4 %z)  {
647; CHECK-LABEL: @simplify_or_common_op_commute0(
648; CHECK-NEXT:    ret i4 -1
649;
650  %xy = and i4 %x, %y
651  %xyz = and i4 %xy, %z
652  %not_xyz = xor i4 %xyz, -1
653  %r = or i4 %not_xyz, %x
654  ret i4 %r
655}
656
657define i4 @simplify_or_common_op_commute1(i4 %x, i4 %y, i4 %z)  {
658; CHECK-LABEL: @simplify_or_common_op_commute1(
659; CHECK-NEXT:    ret i4 -1
660;
661  %xy = and i4 %y, %x
662  %xyz = and i4 %xy, %z
663  %not_xyz = xor i4 %xyz, -1
664  %r = or i4 %not_xyz, %x
665  ret i4 %r
666}
667
668; The common operand may bubble through multiple instructions.
669
670define i4 @simplify_or_common_op_commute2(i4 %x, i4 %y, i4 %p, i4 %q)  {
671; CHECK-LABEL: @simplify_or_common_op_commute2(
672; CHECK-NEXT:    ret i4 -1
673;
674  %z = mul i4 %p, %p ; thwart complexity-based canonicalization
675  %xy = and i4 %x, %y
676  %xyz = and i4 %z, %xy
677  %xyzq = and i4 %xyz, %q
678  %not_xyzq = xor i4 %xyzq, -1
679  %r = or i4 %not_xyzq, %x
680  ret i4 %r
681}
682
683define <2 x i4> @simplify_or_common_op_commute3(<2 x i4> %x, <2 x i4> %y, <2 x i4> %p)  {
684; CHECK-LABEL: @simplify_or_common_op_commute3(
685; CHECK-NEXT:    ret <2 x i4> splat (i4 -1)
686;
687  %z = mul <2 x i4> %p, %p ; thwart complexity-based canonicalization
688  %xy = and <2 x i4> %y, %x
689  %xyz = and <2 x i4> %z, %xy
690  %not_xyz = xor <2 x i4> %xyz, <i4 -1, i4 -1>
691  %r = or <2 x i4> %x, %not_xyz
692  ret <2 x i4> %r
693}
694
695define i4 @simplify_and_common_op_commute0(i4 %x, i4 %y, i4 %z)  {
696; CHECK-LABEL: @simplify_and_common_op_commute0(
697; CHECK-NEXT:    call void @use(i4 [[X:%.*]])
698; CHECK-NEXT:    ret i4 0
699;
700  %xy = or i4 %x, %y
701  call void @use(i4 %x)
702  %xyz = or i4 %xy, %z
703  %not_xyz = xor i4 %xyz, -1
704  %r = and i4 %not_xyz, %x
705  ret i4 %r
706}
707
708define i4 @simplify_and_common_op_commute1(i4 %x, i4 %y, i4 %z)  {
709; CHECK-LABEL: @simplify_and_common_op_commute1(
710; CHECK-NEXT:    ret i4 0
711;
712  %xy = or i4 %y, %x
713  %xyz = or i4 %xy, %z
714  %not_xyz = xor i4 %xyz, -1
715  %r = and i4 %not_xyz, %x
716  ret i4 %r
717}
718
719; The common operand may bubble through multiple instructions.
720
721define i4 @simplify_and_common_op_commute2(i4 %x, i4 %y, i4 %p, i4 %q)  {
722; CHECK-LABEL: @simplify_and_common_op_commute2(
723; CHECK-NEXT:    ret i4 0
724;
725  %z = mul i4 %p, %p ; thwart complexity-based canonicalization
726  %xy = or i4 %x, %y
727  %xyz = or i4 %z, %xy
728  %xyzq = or i4 %xyz, %q
729  %not_xyzq = xor i4 %xyzq, -1
730  %r = and i4 %not_xyzq, %x
731  ret i4 %r
732}
733
734define <2 x i4> @simplify_and_common_op_commute3(<2 x i4> %x, <2 x i4> %y, <2 x i4> %p)  {
735; CHECK-LABEL: @simplify_and_common_op_commute3(
736; CHECK-NEXT:    ret <2 x i4> zeroinitializer
737;
738  %z = mul <2 x i4> %p, %p ; thwart complexity-based canonicalization
739  %xy = or <2 x i4> %y, %x
740  %xyz = or <2 x i4> %z, %xy
741  %not_xyz = xor <2 x i4> %xyz, <i4 -1, i4 -1>
742  %r = and <2 x i4> %x, %not_xyz
743  ret <2 x i4> %r
744}
745
746define i4 @simplify_and_common_op_use1(i4 %x, i4 %y, i4 %z)  {
747; CHECK-LABEL: @simplify_and_common_op_use1(
748; CHECK-NEXT:    call void @use(i4 [[Y:%.*]])
749; CHECK-NEXT:    ret i4 0
750;
751  %xy = or i4 %x, %y
752  call void @use(i4 %y)
753  %xyz = or i4 %xy, %z
754  %not_xyz = xor i4 %xyz, -1
755  %r = and i4 %not_xyz, %x
756  ret i4 %r
757}
758
759; TODO: This should simplify.
760
761define i4 @simplify_and_common_op_use2(i4 %x, i4 %y, i4 %z)  {
762; CHECK-LABEL: @simplify_and_common_op_use2(
763; CHECK-NEXT:    call void @use(i4 [[Y:%.*]])
764; CHECK-NEXT:    ret i4 0
765;
766  %xy = or i4 %y, %x
767  call void @use(i4 %y)
768  %xyz = or i4 %xy, %z
769  %not_xyz = xor i4 %xyz, -1
770  %r = and i4 %not_xyz, %x
771  ret i4 %r
772}
773
774; TODO: This should simplify.
775
776define i4 @simplify_and_common_op_use3(i4 %x, i4 %y, i4 %z)  {
777; CHECK-LABEL: @simplify_and_common_op_use3(
778; CHECK-NEXT:    call void @use(i4 [[Z:%.*]])
779; CHECK-NEXT:    ret i4 0
780;
781  %xy = or i4 %x, %y
782  %xyz = or i4 %xy, %z
783  call void @use(i4 %z)
784  %not_xyz = xor i4 %xyz, -1
785  %r = and i4 %not_xyz, %x
786  ret i4 %r
787}
788
789define i4 @reduce_xor_common_op_commute0(i4 %x, i4 %y, i4 %z)  {
790; CHECK-LABEL: @reduce_xor_common_op_commute0(
791; CHECK-NEXT:    [[TMP1:%.*]] = xor i4 [[Y:%.*]], [[Z:%.*]]
792; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[X:%.*]]
793; CHECK-NEXT:    ret i4 [[R]]
794;
795  %xy = xor i4 %x, %y
796  %xyz = xor i4 %xy, %z
797  %r = or i4 %xyz, %x
798  ret i4 %r
799}
800
801define i4 @reduce_xor_common_op_commute1(i4 %x, i4 %y, i4 %z)  {
802; CHECK-LABEL: @reduce_xor_common_op_commute1(
803; CHECK-NEXT:    [[TMP1:%.*]] = xor i4 [[Y:%.*]], [[Z:%.*]]
804; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[X:%.*]]
805; CHECK-NEXT:    ret i4 [[R]]
806;
807  %xy = xor i4 %y, %x
808  %xyz = xor i4 %xy, %z
809  %r = or i4 %xyz, %x
810  ret i4 %r
811}
812
813define i4 @annihilate_xor_common_op_commute2(i4 %x, i4 %y, i4 %p, i4 %q)  {
814; CHECK-LABEL: @annihilate_xor_common_op_commute2(
815; CHECK-NEXT:    [[Z:%.*]] = mul i4 [[P:%.*]], [[P]]
816; CHECK-NEXT:    [[TMP1:%.*]] = xor i4 [[Y:%.*]], [[Z]]
817; CHECK-NEXT:    [[TMP2:%.*]] = xor i4 [[TMP1]], [[Q:%.*]]
818; CHECK-NEXT:    ret i4 [[TMP2]]
819;
820  %z = mul i4 %p, %p ; thwart complexity-based canonicalization
821  %xy = xor i4 %x, %y
822  %xyz = xor i4 %z, %xy
823  %xyzq = xor i4 %xyz, %q
824  %r = xor i4 %xyzq, %x
825  ret i4 %r
826}
827
828define <2 x i4> @reduce_xor_common_op_commute3(<2 x i4> %x, <2 x i4> %y, <2 x i4> %p)  {
829; CHECK-LABEL: @reduce_xor_common_op_commute3(
830; CHECK-NEXT:    [[Z:%.*]] = mul <2 x i4> [[P:%.*]], [[P]]
831; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i4> [[Y:%.*]], [[Z]]
832; CHECK-NEXT:    [[R:%.*]] = or <2 x i4> [[X:%.*]], [[TMP1]]
833; CHECK-NEXT:    ret <2 x i4> [[R]]
834;
835  %z = mul <2 x i4> %p, %p ; thwart complexity-based canonicalization
836  %xy = xor <2 x i4> %y, %x
837  %xyz = xor <2 x i4> %z, %xy
838  %r = or <2 x i4> %x, %xyz
839  ret <2 x i4> %r
840}
841