From 90818085218f23c8e2cdcc1aa68e66fb6ae7e07c Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sun, 23 Apr 2017 14:51:03 +0000 Subject: [PATCH] [InstCombine] add tests for xor-to-xor; NFC Besides missing 2 commuted patterns, the way we handle these folds is inefficient. llvm-svn: 301128 --- llvm/test/Transforms/InstCombine/and-or-not.ll | 215 +++++++++++++++++++++++++ 1 file changed, 215 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/and-or-not.ll b/llvm/test/Transforms/InstCombine/and-or-not.ll index 4398594..48ae620 100644 --- a/llvm/test/Transforms/InstCombine/and-or-not.ll +++ b/llvm/test/Transforms/InstCombine/and-or-not.ll @@ -70,6 +70,221 @@ define <4 x i32> @and_to_xor1_vec(<4 x i32> %a, <4 x i32> %b) { ret <4 x i32> %and2 } +; (a & b) ^ (a | b) --> a ^ b + +define i32 @xor_to_xor1(i32 %a, i32 %b) { +; CHECK-LABEL: @xor_to_xor1( +; CHECK-NEXT: [[XOR:%.*]] = xor i32 %a, %b +; CHECK-NEXT: ret i32 [[XOR]] +; + %and = and i32 %a, %b + %or = or i32 %a, %b + %xor = xor i32 %and, %or + ret i32 %xor +} + +; (a & b) ^ (b | a) --> a ^ b + +define i32 @xor_to_xor2(i32 %a, i32 %b) { +; CHECK-LABEL: @xor_to_xor2( +; CHECK-NEXT: [[XOR:%.*]] = xor i32 %a, %b +; CHECK-NEXT: ret i32 [[XOR]] +; + %and = and i32 %a, %b + %or = or i32 %b, %a + %xor = xor i32 %and, %or + ret i32 %xor +} + +; (a | b) ^ (a & b) --> a ^ b + +define i32 @xor_to_xor3(i32 %a, i32 %b) { +; CHECK-LABEL: @xor_to_xor3( +; CHECK-NEXT: [[XOR:%.*]] = xor i32 %a, %b +; CHECK-NEXT: ret i32 [[XOR]] +; + %or = or i32 %a, %b + %and = and i32 %a, %b + %xor = xor i32 %or, %and + ret i32 %xor +} + +; (a | b) ^ (b & a) --> a ^ b + +define i32 @xor_to_xor4(i32 %a, i32 %b) { +; CHECK-LABEL: @xor_to_xor4( +; CHECK-NEXT: [[XOR:%.*]] = xor i32 %a, %b +; CHECK-NEXT: ret i32 [[XOR]] +; + %or = or i32 %a, %b + %and = and i32 %b, %a + %xor = xor i32 %or, %and + ret i32 %xor +} + +; (a | ~b) ^ (~a | b) --> a ^ b + +; In the next 8 tests, cast instructions are used to thwart operand complexity +; canonicalizations, so we can test all of the commuted patterns. + +define i32 @xor_to_xor5(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor5( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %a, %notb + %or2 = or i32 %nota, %b + %xor = xor i32 %or1, %or2 + ret i32 %xor +} + +; (a | ~b) ^ (b | ~a) --> a ^ b + +define i32 @xor_to_xor6(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor6( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[NOTA:%.*]] = xor i32 [[A]], -1 +; CHECK-NEXT: [[NOTB:%.*]] = xor i32 [[B]], -1 +; CHECK-NEXT: [[OR1:%.*]] = or i32 [[A]], [[NOTB]] +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[B]], [[NOTA]] +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[OR1]], [[OR2]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %a, %notb + %or2 = or i32 %b, %nota + %xor = xor i32 %or1, %or2 + ret i32 %xor +} + +; (~a | b) ^ (a | ~b) --> a ^ b + +define i32 @xor_to_xor7(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor7( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %a, %notb + %or2 = or i32 %nota, %b + %xor = xor i32 %or2, %or1 + ret i32 %xor +} + +; (~a | b) ^ (~b | a) --> a ^ b + +define i32 @xor_to_xor8(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor8( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %or1 = or i32 %notb, %a + %or2 = or i32 %nota, %b + %xor = xor i32 %or2, %or1 + ret i32 %xor +} + +; (a & ~b) ^ (~a & b) --> a ^ b + +define i32 @xor_to_xor9(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor9( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %a, %notb + %and2 = and i32 %nota, %b + %xor = xor i32 %and1, %and2 + ret i32 %xor +} + +; (a & ~b) ^ (b & ~a) --> a ^ b + +define i32 @xor_to_xor10(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor10( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[NOTA:%.*]] = xor i32 [[A]], -1 +; CHECK-NEXT: [[NOTB:%.*]] = xor i32 [[B]], -1 +; CHECK-NEXT: [[AND1:%.*]] = and i32 [[A]], [[NOTB]] +; CHECK-NEXT: [[AND2:%.*]] = and i32 [[B]], [[NOTA]] +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[AND1]], [[AND2]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %a, %notb + %and2 = and i32 %b, %nota + %xor = xor i32 %and1, %and2 + ret i32 %xor +} + +; (~a & b) ^ (a & ~b) --> a ^ b + +define i32 @xor_to_xor11(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor11( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %a, %notb + %and2 = and i32 %nota, %b + %xor = xor i32 %and2, %and1 + ret i32 %xor +} + +; (~a & b) ^ (~b & a) --> a ^ b + +define i32 @xor_to_xor12(float %fa, float %fb) { +; CHECK-LABEL: @xor_to_xor12( +; CHECK-NEXT: [[A:%.*]] = fptosi float %fa to i32 +; CHECK-NEXT: [[B:%.*]] = fptosi float %fb to i32 +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] +; CHECK-NEXT: ret i32 [[XOR]] +; + %a = fptosi float %fa to i32 + %b = fptosi float %fb to i32 + %nota = xor i32 %a, -1 + %notb = xor i32 %b, -1 + %and1 = and i32 %notb, %a + %and2 = and i32 %nota, %b + %xor = xor i32 %and2, %and1 + ret i32 %xor +} + ; ~(~(a | b) | (a & b)) --> (a | b) & ~(a & b) -> a ^ b define i32 @demorgan_plus_and_to_xor(i32 %a, i32 %b) { -- 2.7.4