1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
8 ; (a | b) & ~(a & b) --> a ^ b
10 define 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]]
17 %not = xor i32 %and, -1
18 %and2 = and i32 %or, %not
22 ; ~(a & b) & (a | b) --> a ^ b
24 define 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]]
31 %not = xor i32 %and, -1
32 %and2 = and i32 %not, %or
36 ; (a | b) & ~(b & a) --> a ^ b
38 define 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]]
45 %not = xor i32 %and, -1
46 %and2 = and i32 %or, %not
50 ; ~(a & b) & (b | a) --> a ^ b
52 define 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]]
59 %not = xor i32 %and, -1
60 %and2 = and i32 %not, %or
64 define <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]]
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
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.
79 ; (a | ~b) & (~a | b) --> ~(a ^ b)
81 define 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]]
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
99 ; (a | ~b) & (b | ~a) --> ~(a ^ b)
101 define 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]]
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
119 ; (~a | b) & (a | ~b) --> ~(a ^ b)
121 define 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]]
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
139 ; (~a | b) & (~b | a) --> ~(a ^ b)
141 define 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]]
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
159 ; (a & ~b) | (~a & b) --> a ^ b
161 define 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]]
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
178 ; (a & ~b) | (b & ~a) --> a ^ b
180 define 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]]
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
197 ; (~a & b) | (~b & a) --> a ^ b
199 define 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]]
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
216 ; (~a & b) | (a & ~b) --> a ^ b
218 define 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]]
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
235 ; (a & b) | ~(a | b) --> ~(a ^ b)
237 define 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]]
243 %and = and i32 %a, %b
245 %notor = xor i32 %or, -1
246 %or2 = or i32 %and, %notor
250 ; (a & b) | ~(b | a) --> ~(a ^ b)
252 define 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]]
258 %and = and i32 %a, %b
260 %notor = xor i32 %or, -1
261 %or2 = or i32 %and, %notor
265 ; ~(a | b) | (a & b) --> ~(a ^ b)
267 define 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]]
273 %and = and i32 %a, %b
275 %notor = xor i32 %or, -1
276 %or2 = or i32 %notor, %and
280 ; ~(a | b) | (b & a) --> ~(a ^ b)
282 define 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]]
288 %and = and i32 %b, %a
290 %notor = xor i32 %or, -1
291 %or2 = or i32 %notor, %and
295 ; (a & b) ^ (a | b) --> a ^ b
297 define 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]]
302 %and = and i32 %a, %b
304 %xor = xor i32 %and, %or
308 ; (a & b) ^ (b | a) --> a ^ b
310 define 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]]
315 %and = and i32 %a, %b
317 %xor = xor i32 %and, %or
321 ; (a | b) ^ (a & b) --> a ^ b
323 define 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]]
329 %and = and i32 %a, %b
330 %xor = xor i32 %or, %and
334 ; (a | b) ^ (b & a) --> a ^ b
336 define 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]]
342 %and = and i32 %b, %a
343 %xor = xor i32 %or, %and
347 ; (a | ~b) ^ (~a | b) --> a ^ b
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.
352 define 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]]
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
369 ; (a | ~b) ^ (b | ~a) --> a ^ b
371 define 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]]
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
388 ; (~a | b) ^ (a | ~b) --> a ^ b
390 define 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]]
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
407 ; (~a | b) ^ (~b | a) --> a ^ b
409 define 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]]
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
426 ; (a & ~b) ^ (~a & b) --> a ^ b
428 define 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]]
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
445 ; (a & ~b) ^ (b & ~a) --> a ^ b
447 define 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]]
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
464 ; (~a & b) ^ (a & ~b) --> a ^ b
466 define 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]]
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
483 ; (~a & b) ^ (~b & a) --> a ^ b
485 define 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]]
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
502 ; https://bugs.llvm.org/show_bug.cgi?id=32830
503 ; Make sure we're matching operands correctly and not folding things wrongly.
505 define 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 [[NOTB]], [[A]]
510 ; CHECK-NEXT: [[OR2:%.*]] = or i64 [[NOTA]], [[C:%.*]]
511 ; CHECK-NEXT: [[AND:%.*]] = and i64 [[OR1]], [[OR2]]
512 ; CHECK-NEXT: ret i64 [[AND]]
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
522 ; (~a | b) & (~b | a) --> ~(a ^ b)
523 ; TODO: this increases instruction count if the pieces have additional users
524 define 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]]
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
549 ; (a & b) | ~(a | b) --> ~(a ^ b)
550 ; TODO: this increases instruction count if the pieces have additional users
551 define 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]]
561 %and = and 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
570 ; (a | b) ^ (~a | ~b) --> ~(a ^ b)
571 define 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]]
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
584 %or2 = or i32 %nota, %notb
585 %xor = xor i32 %or1, %or2
589 ; (a | b) ^ (~b | ~a) --> ~(a ^ b)
590 define 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]]
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
603 %or2 = or i32 %notb, %nota
604 %xor = xor i32 %or1, %or2
608 ; (~a | ~b) ^ (a | b) --> ~(a ^ b)
609 define 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]]
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
623 %xor = xor i32 %or1, %or2
627 ; (~a | ~b) ^ (b | a) --> ~(a ^ b)
628 define 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]]
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
642 %xor = xor i32 %or1, %or2
646 define 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
651 %xyz = and i4 %xy, %z
652 %not_xyz = xor i4 %xyz, -1
653 %r = or i4 %not_xyz, %x
657 define 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
662 %xyz = and i4 %xy, %z
663 %not_xyz = xor i4 %xyz, -1
664 %r = or i4 %not_xyz, %x
668 ; The common operand may bubble through multiple instructions.
670 define 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
674 %z = mul i4 %p, %p ; thwart complexity-based canonicalization
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
683 define <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> <i4 -1, i4 -1>
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
695 define 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
701 call void @use(i4 %x)
703 %not_xyz = xor i4 %xyz, -1
704 %r = and i4 %not_xyz, %x
708 define 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
714 %not_xyz = xor i4 %xyz, -1
715 %r = and i4 %not_xyz, %x
719 ; The common operand may bubble through multiple instructions.
721 define 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
725 %z = mul i4 %p, %p ; thwart complexity-based canonicalization
728 %xyzq = or i4 %xyz, %q
729 %not_xyzq = xor i4 %xyzq, -1
730 %r = and i4 %not_xyzq, %x
734 define <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
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
746 define 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
752 call void @use(i4 %y)
754 %not_xyz = xor i4 %xyz, -1
755 %r = and i4 %not_xyz, %x
759 ; TODO: This should simplify.
761 define 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: [[TMP1:%.*]] = or i4 [[X:%.*]], [[Z:%.*]]
765 ; CHECK-NEXT: [[XYZ:%.*]] = or i4 [[TMP1]], [[Y]]
766 ; CHECK-NEXT: [[NOT_XYZ:%.*]] = xor i4 [[XYZ]], -1
767 ; CHECK-NEXT: [[R:%.*]] = and i4 [[NOT_XYZ]], [[X]]
768 ; CHECK-NEXT: ret i4 [[R]]
771 call void @use(i4 %y)
773 %not_xyz = xor i4 %xyz, -1
774 %r = and i4 %not_xyz, %x
778 ; TODO: This should simplify.
780 define i4 @simplify_and_common_op_use3(i4 %x, i4 %y, i4 %z) {
781 ; CHECK-LABEL: @simplify_and_common_op_use3(
782 ; CHECK-NEXT: [[XY:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
783 ; CHECK-NEXT: [[XYZ:%.*]] = or i4 [[XY]], [[Z:%.*]]
784 ; CHECK-NEXT: call void @use(i4 [[Z]])
785 ; CHECK-NEXT: [[NOT_XYZ:%.*]] = xor i4 [[XYZ]], -1
786 ; CHECK-NEXT: [[R:%.*]] = and i4 [[NOT_XYZ]], [[X]]
787 ; CHECK-NEXT: ret i4 [[R]]
791 call void @use(i4 %z)
792 %not_xyz = xor i4 %xyz, -1
793 %r = and i4 %not_xyz, %x
797 define i4 @reduce_xor_common_op_commute0(i4 %x, i4 %y, i4 %z) {
798 ; CHECK-LABEL: @reduce_xor_common_op_commute0(
799 ; CHECK-NEXT: [[TMP1:%.*]] = xor i4 [[Y:%.*]], [[Z:%.*]]
800 ; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[X:%.*]]
801 ; CHECK-NEXT: ret i4 [[R]]
804 %xyz = xor i4 %xy, %z
809 define i4 @reduce_xor_common_op_commute1(i4 %x, i4 %y, i4 %z) {
810 ; CHECK-LABEL: @reduce_xor_common_op_commute1(
811 ; CHECK-NEXT: [[TMP1:%.*]] = xor i4 [[Y:%.*]], [[Z:%.*]]
812 ; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[X:%.*]]
813 ; CHECK-NEXT: ret i4 [[R]]
816 %xyz = xor i4 %xy, %z
821 define i4 @annihilate_xor_common_op_commute2(i4 %x, i4 %y, i4 %p, i4 %q) {
822 ; CHECK-LABEL: @annihilate_xor_common_op_commute2(
823 ; CHECK-NEXT: [[Z:%.*]] = mul i4 [[P:%.*]], [[P]]
824 ; CHECK-NEXT: [[TMP1:%.*]] = xor i4 [[Z]], [[Y:%.*]]
825 ; CHECK-NEXT: [[TMP2:%.*]] = xor i4 [[TMP1]], [[Q:%.*]]
826 ; CHECK-NEXT: ret i4 [[TMP2]]
828 %z = mul i4 %p, %p ; thwart complexity-based canonicalization
830 %xyz = xor i4 %z, %xy
831 %xyzq = xor i4 %xyz, %q
832 %r = xor i4 %xyzq, %x
836 define <2 x i4> @reduce_xor_common_op_commute3(<2 x i4> %x, <2 x i4> %y, <2 x i4> %p) {
837 ; CHECK-LABEL: @reduce_xor_common_op_commute3(
838 ; CHECK-NEXT: [[Z:%.*]] = mul <2 x i4> [[P:%.*]], [[P]]
839 ; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i4> [[Z]], [[Y:%.*]]
840 ; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[TMP1]], [[X:%.*]]
841 ; CHECK-NEXT: ret <2 x i4> [[R]]
843 %z = mul <2 x i4> %p, %p ; thwart complexity-based canonicalization
844 %xy = xor <2 x i4> %y, %x
845 %xyz = xor <2 x i4> %z, %xy
846 %r = or <2 x i4> %x, %xyz