[PATCH] Instcombine (A|B) ^(A^B) to A&B

Karthik Bhat kv.bhat at samsung.com
Tue Aug 12 07:03:30 PDT 2014


Hi majnemer, rafael,

Hi All,
This patch implements transform for pattern (A|B) ^(A^B)  to  A&B.

Please find the correctness proof of the transform using CVC3 -

$ cat t.cvc
A, B : BITVECTOR(32);
QUERY BVXOR(A | B, BVXOR(A,B) ) = A & B;

$ cvc3  t.cvc
Valid.

Please let me know if this is good to commit.

Thanks
Karthik Bhat

http://reviews.llvm.org/D4866

Files:
  lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
  test/Transforms/InstCombine/or-xor.ll

Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2436,18 +2436,28 @@
       if (Instruction *NV = FoldOpIntoPhi(I))
         return NV;
   }
-
+  BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0);
   BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1);
   if (Op1I) {
     Value *A, *B;
+    Value *A1, *B1;
     if (match(Op1I, m_Or(m_Value(A), m_Value(B)))) {
       if (A == Op0) {              // B^(B|A) == (A|B)^B
         Op1I->swapOperands();
         I.swapOperands();
         std::swap(Op0, Op1);
       } else if (B == Op0) {       // B^(A|B) == (A|B)^B
         I.swapOperands();     // Simplified below.
         std::swap(Op0, Op1);
+      } else if (Op0I && match(Op0I, m_Xor(m_Value(A1), m_Value(B1)))) {
+        if (A1 == A && B1 == B) {
+          I.swapOperands();    // (A^B)^(A|B) == (A|B)^(A^B)
+          std::swap(Op0, Op1); // Simplified below.
+        } else if (A1 == B && B1 == A) {
+          Op1I->swapOperands(); // (A^B)^(B|A) == (A|B)^(A^B)
+          I.swapOperands();     // Simplied below.
+          std::swap(Op0, Op1);
+        }
       }
     } else if (match(Op1I, m_And(m_Value(A), m_Value(B))) &&
                Op1I->hasOneUse()){
@@ -2462,17 +2472,25 @@
     }
   }
 
-  BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0);
   if (Op0I) {
     Value *A, *B;
+    Value *A1, *B1;
     if (match(Op0I, m_Or(m_Value(A), m_Value(B))) &&
         Op0I->hasOneUse()) {
       if (A == Op1)                                  // (B|A)^B == (A|B)^B
         std::swap(A, B);
       if (B == Op1)                                  // (A|B)^B == A & ~B
         return BinaryOperator::CreateAnd(A, Builder->CreateNot(Op1));
-    } else if (match(Op0I, m_And(m_Value(A), m_Value(B))) &&
-               Op0I->hasOneUse()){
+      if (Op1I && match(Op1I, m_Xor(m_Value(A1), m_Value(B1))) &&
+          Op1I->hasOneUse()) {
+        if ((A == A1 && B == B1) || (A == B1 && B == A1)) {
+          // (A|B)^(A^B) == A & B
+          // (A|B)^(B^A) == A & B
+          return BinaryOperator::CreateAnd(A, B);
+        }
+      }
+    } else if (Op0I && match(Op0I, m_And(m_Value(A), m_Value(B))) &&
+               Op0I->hasOneUse()) {
       if (A == Op1)                                        // (A&B)^A -> (B&A)^A
         std::swap(A, B);
       if (B == Op1 &&                                      // (B&A)^A == ~B & A
Index: test/Transforms/InstCombine/or-xor.ll
===================================================================
--- test/Transforms/InstCombine/or-xor.ll
+++ test/Transforms/InstCombine/or-xor.ll
@@ -136,3 +136,13 @@
 ; CHECK-NEXT: %and = and i32 %x, %y
 ; CHECK-NEXT: ret i32 %and
 }
+
+define i32 @test15(i32 %x, i32 %y) #0 {
+  %1 = xor i32 %y, %x
+  %2 = or i32 %y, %x
+  %3 = xor i32 %2, %1
+  ret i32 %3
+; CHECK-LABEL: @test15(
+; CHECK-NEXT: %1 = and i32 %y, %x
+; CHECK-NEXT: ret i32 %1
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4866.12399.patch
Type: text/x-patch
Size: 3051 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140812/0f0c0ef8/attachment.bin>


More information about the llvm-commits mailing list