[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