1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; PR1510
5
6; (a | b) & ~(a & b) --> a ^ b
7
8define i32 @and_to_xor1(i32 %a, i32 %b) {
9; CHECK-LABEL: @and_to_xor1(
10; CHECK-NEXT:    [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
11; CHECK-NEXT:    ret i32 [[AND2]]
12;
13  %or = or i32 %a, %b
14  %and = and i32 %a, %b
15  %not = xor i32 %and, -1
16  %and2 = and i32 %or, %not
17  ret i32 %and2
18}
19
20; ~(a & b) & (a | b) --> a ^ b
21
22define i32 @and_to_xor2(i32 %a, i32 %b) {
23; CHECK-LABEL: @and_to_xor2(
24; CHECK-NEXT:    [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
25; CHECK-NEXT:    ret i32 [[AND2]]
26;
27  %or = or i32 %a, %b
28  %and = and i32 %a, %b
29  %not = xor i32 %and, -1
30  %and2 = and i32 %not, %or
31  ret i32 %and2
32}
33
34; (a | b) & ~(b & a) --> a ^ b
35
36define i32 @and_to_xor3(i32 %a, i32 %b) {
37; CHECK-LABEL: @and_to_xor3(
38; CHECK-NEXT:    [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
39; CHECK-NEXT:    ret i32 [[AND2]]
40;
41  %or = or i32 %a, %b
42  %and = and i32 %b, %a
43  %not = xor i32 %and, -1
44  %and2 = and i32 %or, %not
45  ret i32 %and2
46}
47
48; ~(a & b) & (b | a) --> a ^ b
49
50define i32 @and_to_xor4(i32 %a, i32 %b) {
51; CHECK-LABEL: @and_to_xor4(
52; CHECK-NEXT:    [[AND2:%.*]] = xor i32 [[B:%.*]], [[A:%.*]]
53; CHECK-NEXT:    ret i32 [[AND2]]
54;
55  %or = or i32 %b, %a
56  %and = and i32 %a, %b
57  %not = xor i32 %and, -1
58  %and2 = and i32 %not, %or
59  ret i32 %and2
60}
61
62define <4 x i32> @and_to_xor1_vec(<4 x i32> %a, <4 x i32> %b) {
63; CHECK-LABEL: @and_to_xor1_vec(
64; CHECK-NEXT:    [[AND2:%.*]] = xor <4 x i32> [[A:%.*]], [[B:%.*]]
65; CHECK-NEXT:    ret <4 x i32> [[AND2]]
66;
67  %or = or <4 x i32> %a, %b
68  %and = and <4 x i32> %a, %b
69  %not = xor <4 x i32> %and, < i32 -1, i32 -1, i32 -1, i32 -1 >
70  %and2 = and <4 x i32> %or, %not
71  ret <4 x i32> %and2
72}
73
74; In the next 4 tests, cast instructions are used to thwart operand complexity
75; canonicalizations, so we can test all of the commuted patterns.
76
77; (a | ~b) & (~a | b) --> ~(a ^ b)
78
79define i32 @and_to_nxor1(float %fa, float %fb) {
80; CHECK-LABEL: @and_to_nxor1(
81; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
82; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
83; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A]], [[B]]
84; CHECK-NEXT:    [[AND:%.*]] = xor i32 [[TMP1]], -1
85; CHECK-NEXT:    ret i32 [[AND]]
86;
87  %a = fptosi float %fa to i32
88  %b = fptosi float %fb to i32
89  %nota = xor i32 %a, -1
90  %notb = xor i32 %b, -1
91  %or1 = or i32 %a, %notb
92  %or2 = or i32 %nota, %b
93  %and = and i32 %or1, %or2
94  ret i32 %and
95}
96
97; (a | ~b) & (b | ~a) --> ~(a ^ b)
98
99define i32 @and_to_nxor2(float %fa, float %fb) {
100; CHECK-LABEL: @and_to_nxor2(
101; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
102; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
103; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A]], [[B]]
104; CHECK-NEXT:    [[AND:%.*]] = xor i32 [[TMP1]], -1
105; CHECK-NEXT:    ret i32 [[AND]]
106;
107  %a = fptosi float %fa to i32
108  %b = fptosi float %fb to i32
109  %nota = xor i32 %a, -1
110  %notb = xor i32 %b, -1
111  %or1 = or i32 %a, %notb
112  %or2 = or i32 %b, %nota
113  %and = and i32 %or1, %or2
114  ret i32 %and
115}
116
117; (~a | b) & (a | ~b) --> ~(a ^ b)
118
119define i32 @and_to_nxor3(float %fa, float %fb) {
120; CHECK-LABEL: @and_to_nxor3(
121; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
122; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
123; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[B]], [[A]]
124; CHECK-NEXT:    [[AND:%.*]] = xor i32 [[TMP1]], -1
125; CHECK-NEXT:    ret i32 [[AND]]
126;
127  %a = fptosi float %fa to i32
128  %b = fptosi float %fb to i32
129  %nota = xor i32 %a, -1
130  %notb = xor i32 %b, -1
131  %or1 = or i32 %nota, %b
132  %or2 = or i32 %a, %notb
133  %and = and i32 %or1, %or2
134  ret i32 %and
135}
136
137; (~a | b) & (~b | a) --> ~(a ^ b)
138
139define i32 @and_to_nxor4(float %fa, float %fb) {
140; CHECK-LABEL: @and_to_nxor4(
141; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
142; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
143; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[B]], [[A]]
144; CHECK-NEXT:    [[AND:%.*]] = xor i32 [[TMP1]], -1
145; CHECK-NEXT:    ret i32 [[AND]]
146;
147  %a = fptosi float %fa to i32
148  %b = fptosi float %fb to i32
149  %nota = xor i32 %a, -1
150  %notb = xor i32 %b, -1
151  %or1 = or i32 %nota, %b
152  %or2 = or i32 %notb, %a
153  %and = and i32 %or1, %or2
154  ret i32 %and
155}
156
157; (a & ~b) | (~a & b) --> a ^ b
158
159define i32 @or_to_xor1(float %fa, float %fb) {
160; CHECK-LABEL: @or_to_xor1(
161; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
162; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
163; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[A]], [[B]]
164; CHECK-NEXT:    ret i32 [[OR]]
165;
166  %a = fptosi float %fa to i32
167  %b = fptosi float %fb to i32
168  %nota = xor i32 %a, -1
169  %notb = xor i32 %b, -1
170  %and1 = and i32 %a, %notb
171  %and2 = and i32 %nota, %b
172  %or = or i32 %and1, %and2
173  ret i32 %or
174}
175
176; (a & ~b) | (b & ~a) --> a ^ b
177
178define i32 @or_to_xor2(float %fa, float %fb) {
179; CHECK-LABEL: @or_to_xor2(
180; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
181; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
182; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[A]], [[B]]
183; CHECK-NEXT:    ret i32 [[OR]]
184;
185  %a = fptosi float %fa to i32
186  %b = fptosi float %fb to i32
187  %nota = xor i32 %a, -1
188  %notb = xor i32 %b, -1
189  %and1 = and i32 %a, %notb
190  %and2 = and i32 %b, %nota
191  %or = or i32 %and1, %and2
192  ret i32 %or
193}
194
195; (~a & b) | (~b & a) --> a ^ b
196
197define i32 @or_to_xor3(float %fa, float %fb) {
198; CHECK-LABEL: @or_to_xor3(
199; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
200; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
201; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[B]], [[A]]
202; CHECK-NEXT:    ret i32 [[OR]]
203;
204  %a = fptosi float %fa to i32
205  %b = fptosi float %fb to i32
206  %nota = xor i32 %a, -1
207  %notb = xor i32 %b, -1
208  %and1 = and i32 %nota, %b
209  %and2 = and i32 %notb, %a
210  %or = or i32 %and1, %and2
211  ret i32 %or
212}
213
214; (~a & b) | (a & ~b) --> a ^ b
215
216define i32 @or_to_xor4(float %fa, float %fb) {
217; CHECK-LABEL: @or_to_xor4(
218; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
219; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
220; CHECK-NEXT:    [[OR:%.*]] = xor i32 [[B]], [[A]]
221; CHECK-NEXT:    ret i32 [[OR]]
222;
223  %a = fptosi float %fa to i32
224  %b = fptosi float %fb to i32
225  %nota = xor i32 %a, -1
226  %notb = xor i32 %b, -1
227  %and1 = and i32 %nota, %b
228  %and2 = and i32 %a, %notb
229  %or = or i32 %and1, %and2
230  ret i32 %or
231}
232
233; (a & b) | ~(a | b) --> ~(a ^ b)
234
235define i32 @or_to_nxor1(i32 %a, i32 %b) {
236; CHECK-LABEL: @or_to_nxor1(
237; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
238; CHECK-NEXT:    [[OR2:%.*]] = xor i32 [[TMP1]], -1
239; CHECK-NEXT:    ret i32 [[OR2]]
240;
241  %and = and i32 %a, %b
242  %or = or i32 %a, %b
243  %notor = xor i32 %or, -1
244  %or2 = or i32 %and, %notor
245  ret i32 %or2
246}
247
248; (a & b) | ~(b | a) --> ~(a ^ b)
249
250define i32 @or_to_nxor2(i32 %a, i32 %b) {
251; CHECK-LABEL: @or_to_nxor2(
252; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
253; CHECK-NEXT:    [[OR2:%.*]] = xor i32 [[TMP1]], -1
254; CHECK-NEXT:    ret i32 [[OR2]]
255;
256  %and = and i32 %a, %b
257  %or = or i32 %b, %a
258  %notor = xor i32 %or, -1
259  %or2 = or i32 %and, %notor
260  ret i32 %or2
261}
262
263; ~(a | b) | (a & b) --> ~(a ^ b)
264
265define i32 @or_to_nxor3(i32 %a, i32 %b) {
266; CHECK-LABEL: @or_to_nxor3(
267; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
268; CHECK-NEXT:    [[OR2:%.*]] = xor i32 [[TMP1]], -1
269; CHECK-NEXT:    ret i32 [[OR2]]
270;
271  %and = and i32 %a, %b
272  %or = or i32 %a, %b
273  %notor = xor i32 %or, -1
274  %or2 = or i32 %notor, %and
275  ret i32 %or2
276}
277
278; ~(a | b) | (b & a) --> ~(a ^ b)
279
280define i32 @or_to_nxor4(i32 %a, i32 %b) {
281; CHECK-LABEL: @or_to_nxor4(
282; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[B:%.*]], [[A:%.*]]
283; CHECK-NEXT:    [[OR2:%.*]] = xor i32 [[TMP1]], -1
284; CHECK-NEXT:    ret i32 [[OR2]]
285;
286  %and = and i32 %b, %a
287  %or = or i32 %a, %b
288  %notor = xor i32 %or, -1
289  %or2 = or i32 %notor, %and
290  ret i32 %or2
291}
292
293; (a & b) ^ (a | b) --> a ^ b
294
295define i32 @xor_to_xor1(i32 %a, i32 %b) {
296; CHECK-LABEL: @xor_to_xor1(
297; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
298; CHECK-NEXT:    ret i32 [[XOR]]
299;
300  %and = and i32 %a, %b
301  %or = or i32 %a, %b
302  %xor = xor i32 %and, %or
303  ret i32 %xor
304}
305
306; (a & b) ^ (b | a) --> a ^ b
307
308define i32 @xor_to_xor2(i32 %a, i32 %b) {
309; CHECK-LABEL: @xor_to_xor2(
310; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
311; CHECK-NEXT:    ret i32 [[XOR]]
312;
313  %and = and i32 %a, %b
314  %or = or i32 %b, %a
315  %xor = xor i32 %and, %or
316  ret i32 %xor
317}
318
319; (a | b) ^ (a & b) --> a ^ b
320
321define i32 @xor_to_xor3(i32 %a, i32 %b) {
322; CHECK-LABEL: @xor_to_xor3(
323; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
324; CHECK-NEXT:    ret i32 [[XOR]]
325;
326  %or = or i32 %a, %b
327  %and = and i32 %a, %b
328  %xor = xor i32 %or, %and
329  ret i32 %xor
330}
331
332; (a | b) ^ (b & a) --> a ^ b
333
334define i32 @xor_to_xor4(i32 %a, i32 %b) {
335; CHECK-LABEL: @xor_to_xor4(
336; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[B:%.*]], [[A:%.*]]
337; CHECK-NEXT:    ret i32 [[XOR]]
338;
339  %or = or i32 %a, %b
340  %and = and i32 %b, %a
341  %xor = xor i32 %or, %and
342  ret i32 %xor
343}
344
345; (a | ~b) ^ (~a | b) --> a ^ b
346
347; In the next 8 tests, cast instructions are used to thwart operand complexity
348; canonicalizations, so we can test all of the commuted patterns.
349
350define i32 @xor_to_xor5(float %fa, float %fb) {
351; CHECK-LABEL: @xor_to_xor5(
352; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
353; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
354; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A]], [[B]]
355; CHECK-NEXT:    ret i32 [[XOR]]
356;
357  %a = fptosi float %fa to i32
358  %b = fptosi float %fb to i32
359  %nota = xor i32 %a, -1
360  %notb = xor i32 %b, -1
361  %or1 = or i32 %a, %notb
362  %or2 = or i32 %nota, %b
363  %xor = xor i32 %or1, %or2
364  ret i32 %xor
365}
366
367; (a | ~b) ^ (b | ~a) --> a ^ b
368
369define i32 @xor_to_xor6(float %fa, float %fb) {
370; CHECK-LABEL: @xor_to_xor6(
371; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
372; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
373; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A]], [[B]]
374; CHECK-NEXT:    ret i32 [[XOR]]
375;
376  %a = fptosi float %fa to i32
377  %b = fptosi float %fb to i32
378  %nota = xor i32 %a, -1
379  %notb = xor i32 %b, -1
380  %or1 = or i32 %a, %notb
381  %or2 = or i32 %b, %nota
382  %xor = xor i32 %or1, %or2
383  ret i32 %xor
384}
385
386; (~a | b) ^ (a | ~b) --> a ^ b
387
388define i32 @xor_to_xor7(float %fa, float %fb) {
389; CHECK-LABEL: @xor_to_xor7(
390; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
391; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
392; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[B]], [[A]]
393; CHECK-NEXT:    ret i32 [[XOR]]
394;
395  %a = fptosi float %fa to i32
396  %b = fptosi float %fb to i32
397  %nota = xor i32 %a, -1
398  %notb = xor i32 %b, -1
399  %or1 = or i32 %a, %notb
400  %or2 = or i32 %nota, %b
401  %xor = xor i32 %or2, %or1
402  ret i32 %xor
403}
404
405; (~a | b) ^ (~b | a) --> a ^ b
406
407define i32 @xor_to_xor8(float %fa, float %fb) {
408; CHECK-LABEL: @xor_to_xor8(
409; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
410; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
411; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[B]], [[A]]
412; CHECK-NEXT:    ret i32 [[XOR]]
413;
414  %a = fptosi float %fa to i32
415  %b = fptosi float %fb to i32
416  %nota = xor i32 %a, -1
417  %notb = xor i32 %b, -1
418  %or1 = or i32 %notb, %a
419  %or2 = or i32 %nota, %b
420  %xor = xor i32 %or2, %or1
421  ret i32 %xor
422}
423
424; (a & ~b) ^ (~a & b) --> a ^ b
425
426define i32 @xor_to_xor9(float %fa, float %fb) {
427; CHECK-LABEL: @xor_to_xor9(
428; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
429; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
430; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A]], [[B]]
431; CHECK-NEXT:    ret i32 [[XOR]]
432;
433  %a = fptosi float %fa to i32
434  %b = fptosi float %fb to i32
435  %nota = xor i32 %a, -1
436  %notb = xor i32 %b, -1
437  %and1 = and i32 %a, %notb
438  %and2 = and i32 %nota, %b
439  %xor = xor i32 %and1, %and2
440  ret i32 %xor
441}
442
443; (a & ~b) ^ (b & ~a) --> a ^ b
444
445define i32 @xor_to_xor10(float %fa, float %fb) {
446; CHECK-LABEL: @xor_to_xor10(
447; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
448; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
449; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[A]], [[B]]
450; CHECK-NEXT:    ret i32 [[XOR]]
451;
452  %a = fptosi float %fa to i32
453  %b = fptosi float %fb to i32
454  %nota = xor i32 %a, -1
455  %notb = xor i32 %b, -1
456  %and1 = and i32 %a, %notb
457  %and2 = and i32 %b, %nota
458  %xor = xor i32 %and1, %and2
459  ret i32 %xor
460}
461
462; (~a & b) ^ (a & ~b) --> a ^ b
463
464define i32 @xor_to_xor11(float %fa, float %fb) {
465; CHECK-LABEL: @xor_to_xor11(
466; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
467; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
468; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[B]], [[A]]
469; CHECK-NEXT:    ret i32 [[XOR]]
470;
471  %a = fptosi float %fa to i32
472  %b = fptosi float %fb to i32
473  %nota = xor i32 %a, -1
474  %notb = xor i32 %b, -1
475  %and1 = and i32 %a, %notb
476  %and2 = and i32 %nota, %b
477  %xor = xor i32 %and2, %and1
478  ret i32 %xor
479}
480
481; (~a & b) ^ (~b & a) --> a ^ b
482
483define i32 @xor_to_xor12(float %fa, float %fb) {
484; CHECK-LABEL: @xor_to_xor12(
485; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
486; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
487; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[B]], [[A]]
488; CHECK-NEXT:    ret i32 [[XOR]]
489;
490  %a = fptosi float %fa to i32
491  %b = fptosi float %fb to i32
492  %nota = xor i32 %a, -1
493  %notb = xor i32 %b, -1
494  %and1 = and i32 %notb, %a
495  %and2 = and i32 %nota, %b
496  %xor = xor i32 %and2, %and1
497  ret i32 %xor
498}
499
500; https://bugs.llvm.org/show_bug.cgi?id=32830
501; Make sure we're matching operands correctly and not folding things wrongly.
502
503define i64 @PR32830(i64 %a, i64 %b, i64 %c) {
504; CHECK-LABEL: @PR32830(
505; CHECK-NEXT:    [[NOTA:%.*]] = xor i64 [[A:%.*]], -1
506; CHECK-NEXT:    [[NOTB:%.*]] = xor i64 [[B:%.*]], -1
507; CHECK-NEXT:    [[OR1:%.*]] = or i64 [[NOTB]], [[A]]
508; CHECK-NEXT:    [[OR2:%.*]] = or i64 [[NOTA]], [[C:%.*]]
509; CHECK-NEXT:    [[AND:%.*]] = and i64 [[OR1]], [[OR2]]
510; CHECK-NEXT:    ret i64 [[AND]]
511;
512  %nota = xor i64 %a, -1
513  %notb = xor i64 %b, -1
514  %or1 = or i64 %notb, %a
515  %or2 = or i64 %nota, %c
516  %and = and i64 %or1, %or2
517  ret i64 %and
518}
519
520; (~a | b) & (~b | a) --> ~(a ^ b)
521; TODO: this increases instruction count if the pieces have additional users
522define i32 @and_to_nxor_multiuse(float %fa, float %fb) {
523; CHECK-LABEL: @and_to_nxor_multiuse(
524; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
525; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
526; CHECK-NEXT:    [[NOTA:%.*]] = xor i32 [[A]], -1
527; CHECK-NEXT:    [[NOTB:%.*]] = xor i32 [[B]], -1
528; CHECK-NEXT:    [[OR1:%.*]] = or i32 [[NOTA]], [[B]]
529; CHECK-NEXT:    [[OR2:%.*]] = or i32 [[NOTB]], [[A]]
530; CHECK-NEXT:    [[AND:%.*]] = and i32 [[OR1]], [[OR2]]
531; CHECK-NEXT:    [[MUL1:%.*]] = mul i32 [[OR1]], [[OR2]]
532; CHECK-NEXT:    [[MUL2:%.*]] = mul i32 [[MUL1]], [[AND]]
533; CHECK-NEXT:    ret i32 [[MUL2]]
534;
535  %a = fptosi float %fa to i32
536  %b = fptosi float %fb to i32
537  %nota = xor i32 %a, -1
538  %notb = xor i32 %b, -1
539  %or1 = or i32 %nota, %b
540  %or2 = or i32 %notb, %a
541  %and = and i32 %or1, %or2
542  %mul1 = mul i32 %or1, %or2 ; here to increase the use count of the inputs to the and
543  %mul2 = mul i32 %mul1, %and
544  ret i32 %mul2
545}
546
547; (a & b) | ~(a | b) --> ~(a ^ b)
548; TODO: this increases instruction count if the pieces have additional users
549define i32 @or_to_nxor_multiuse(i32 %a, i32 %b) {
550; CHECK-LABEL: @or_to_nxor_multiuse(
551; CHECK-NEXT:    [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
552; CHECK-NEXT:    [[OR:%.*]] = or i32 [[A]], [[B]]
553; CHECK-NEXT:    [[NOTOR:%.*]] = xor i32 [[OR]], -1
554; CHECK-NEXT:    [[OR2:%.*]] = or i32 [[AND]], [[NOTOR]]
555; CHECK-NEXT:    [[MUL1:%.*]] = mul i32 [[AND]], [[NOTOR]]
556; CHECK-NEXT:    [[MUL2:%.*]] = mul i32 [[MUL1]], [[OR2]]
557; CHECK-NEXT:    ret i32 [[MUL2]]
558;
559  %and = and i32 %a, %b
560  %or = or i32 %a, %b
561  %notor = xor i32 %or, -1
562  %or2 = or i32 %and, %notor
563  %mul1 = mul i32 %and, %notor ; here to increase the use count of the inputs to the or
564  %mul2 = mul i32 %mul1, %or2
565  ret i32 %mul2
566}
567
568; (a | b) ^ (~a | ~b) --> ~(a ^ b)
569define i32 @xor_to_xnor1(float %fa, float %fb) {
570; CHECK-LABEL: @xor_to_xnor1(
571; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
572; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
573; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A]], [[B]]
574; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[TMP1]], -1
575; CHECK-NEXT:    ret i32 [[XOR]]
576;
577  %a = fptosi float %fa to i32
578  %b = fptosi float %fb to i32
579  %nota = xor i32 %a, -1
580  %notb = xor i32 %b, -1
581  %or1 = or i32 %a, %b
582  %or2 = or i32 %nota, %notb
583  %xor = xor i32 %or1, %or2
584  ret i32 %xor
585}
586
587; (a | b) ^ (~b | ~a) --> ~(a ^ b)
588define i32 @xor_to_xnor2(float %fa, float %fb) {
589; CHECK-LABEL: @xor_to_xnor2(
590; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
591; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
592; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A]], [[B]]
593; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[TMP1]], -1
594; CHECK-NEXT:    ret i32 [[XOR]]
595;
596  %a = fptosi float %fa to i32
597  %b = fptosi float %fb to i32
598  %nota = xor i32 %a, -1
599  %notb = xor i32 %b, -1
600  %or1 = or i32 %a, %b
601  %or2 = or i32 %notb, %nota
602  %xor = xor i32 %or1, %or2
603  ret i32 %xor
604}
605
606; (~a | ~b) ^ (a | b) --> ~(a ^ b)
607define i32 @xor_to_xnor3(float %fa, float %fb) {
608; CHECK-LABEL: @xor_to_xnor3(
609; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
610; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
611; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A]], [[B]]
612; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[TMP1]], -1
613; CHECK-NEXT:    ret i32 [[XOR]]
614;
615  %a = fptosi float %fa to i32
616  %b = fptosi float %fb to i32
617  %nota = xor i32 %a, -1
618  %notb = xor i32 %b, -1
619  %or1 = or i32 %nota, %notb
620  %or2 = or i32 %a, %b
621  %xor = xor i32 %or1, %or2
622  ret i32 %xor
623}
624
625; (~a | ~b) ^ (b | a) --> ~(a ^ b)
626define i32 @xor_to_xnor4(float %fa, float %fb) {
627; CHECK-LABEL: @xor_to_xnor4(
628; CHECK-NEXT:    [[A:%.*]] = fptosi float [[FA:%.*]] to i32
629; CHECK-NEXT:    [[B:%.*]] = fptosi float [[FB:%.*]] to i32
630; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[B]], [[A]]
631; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[TMP1]], -1
632; CHECK-NEXT:    ret i32 [[XOR]]
633;
634  %a = fptosi float %fa to i32
635  %b = fptosi float %fb to i32
636  %nota = xor i32 %a, -1
637  %notb = xor i32 %b, -1
638  %or1 = or i32 %nota, %notb
639  %or2 = or i32 %b, %a
640  %xor = xor i32 %or1, %or2
641  ret i32 %xor
642}
643