[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / and-or-not.ll
blob7bd4ad7b3bb70e5b850723b2e4df7edd54a1bd12
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; PR1510
6 ; (a | b) & ~(a & b) --> a ^ b
8 define 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]]
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
20 ; ~(a & b) & (a | b) --> a ^ b
22 define 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]]
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
34 ; (a | b) & ~(b & a) --> a ^ b
36 define 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]]
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
48 ; ~(a & b) & (b | a) --> a ^ b
50 define 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]]
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
62 define <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]]
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
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.
77 ; (a | ~b) & (~a | b) --> ~(a ^ b)
79 define 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]]
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
97 ; (a | ~b) & (b | ~a) --> ~(a ^ b)
99 define 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]]
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
117 ; (~a | b) & (a | ~b) --> ~(a ^ b)
119 define 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]]
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
137 ; (~a | b) & (~b | a) --> ~(a ^ b)
139 define 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]]
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
157 ; (a & ~b) | (~a & b) --> a ^ b
159 define 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]]
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
176 ; (a & ~b) | (b & ~a) --> a ^ b
178 define 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]]
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
195 ; (~a & b) | (~b & a) --> a ^ b
197 define 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]]
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
214 ; (~a & b) | (a & ~b) --> a ^ b
216 define 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]]
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
233 ; (a & b) | ~(a | b) --> ~(a ^ b)
235 define 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]]
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
248 ; (a & b) | ~(b | a) --> ~(a ^ b)
250 define 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]]
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
263 ; ~(a | b) | (a & b) --> ~(a ^ b)
265 define 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]]
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
278 ; ~(a | b) | (b & a) --> ~(a ^ b)
280 define 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]]
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
293 ; (a & b) ^ (a | b) --> a ^ b
295 define 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]]
300   %and = and i32 %a, %b
301   %or = or i32 %a, %b
302   %xor = xor i32 %and, %or
303   ret i32 %xor
306 ; (a & b) ^ (b | a) --> a ^ b
308 define 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]]
313   %and = and i32 %a, %b
314   %or = or i32 %b, %a
315   %xor = xor i32 %and, %or
316   ret i32 %xor
319 ; (a | b) ^ (a & b) --> a ^ b
321 define 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]]
326   %or = or i32 %a, %b
327   %and = and i32 %a, %b
328   %xor = xor i32 %or, %and
329   ret i32 %xor
332 ; (a | b) ^ (b & a) --> a ^ b
334 define 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]]
339   %or = or i32 %a, %b
340   %and = and i32 %b, %a
341   %xor = xor i32 %or, %and
342   ret i32 %xor
345 ; (a | ~b) ^ (~a | b) --> a ^ b
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.
350 define 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]]
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
367 ; (a | ~b) ^ (b | ~a) --> a ^ b
369 define 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]]
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
386 ; (~a | b) ^ (a | ~b) --> a ^ b
388 define 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]]
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
405 ; (~a | b) ^ (~b | a) --> a ^ b
407 define 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]]
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
424 ; (a & ~b) ^ (~a & b) --> a ^ b
426 define 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]]
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
443 ; (a & ~b) ^ (b & ~a) --> a ^ b
445 define 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]]
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
462 ; (~a & b) ^ (a & ~b) --> a ^ b
464 define 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]]
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
481 ; (~a & b) ^ (~b & a) --> a ^ b
483 define 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]]
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
500 ; https://bugs.llvm.org/show_bug.cgi?id=32830
501 ; Make sure we're matching operands correctly and not folding things wrongly.
503 define 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]]
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
520 ; (~a | b) & (~b | a) --> ~(a ^ b)
521 ; TODO: this increases instruction count if the pieces have additional users
522 define 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]]
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
547 ; (a & b) | ~(a | b) --> ~(a ^ b)
548 ; TODO: this increases instruction count if the pieces have additional users
549 define 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]]
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
568 ; (a | b) ^ (~a | ~b) --> ~(a ^ b)
569 define 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]]
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
587 ; (a | b) ^ (~b | ~a) --> ~(a ^ b)
588 define 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]]
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
606 ; (~a | ~b) ^ (a | b) --> ~(a ^ b)
607 define 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]]
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
625 ; (~a | ~b) ^ (b | a) --> ~(a ^ b)
626 define 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]]
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