[PATCH] Instcombine (A|B) ^(A^B) to A&B
David Majnemer
david.majnemer at gmail.com
Tue Aug 12 09:10:45 PDT 2014
I believe the following is a simpler, but equivalent, wording of this transform.
```
--- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2508,6 +2508,18 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
if ((A == C && B == D) || (A == D && B == C))
return BinaryOperator::CreateXor(A, B);
}
+ // (A ^ B)^(A | B) -> A & B
+ if (match(Op0I, m_Xor(m_Value(A), m_Value(B))) &&
+ match(Op1I, m_Or(m_Value(C), m_Value(D)))) {
+ if ((A == C && B == D) || (A == D && B == C))
+ return BinaryOperator::CreateAnd(A, B);
+ }
+ // (A | B)^(A ^ B) -> A & B
+ if (match(Op0I, m_Or(m_Value(A), m_Value(B))) &&
+ match(Op1I, m_Xor(m_Value(C), m_Value(D)))) {
+ if ((A == C && B == D) || (A == D && B == C))
+ return BinaryOperator::CreateAnd(A, B);
+ }
// (A & B) ^ (A ^ B) -> (A | B)
if (match(Op0I, m_And(m_Value(A), m_Value(B))) &&
match(Op1I, m_Xor(m_Specific(A), m_Specific(B))))
```
================
Comment at: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp:2452-2460
@@ -2450,2 +2451,11 @@
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);
+ }
}
----------------
I think this would be simpler as:
} else if (match(Op0, m_Xor(m_Specific(A), m_Specific(B)))) {
I.swapOperands(); // (A^B)^(A|B) == (A|B)^(A^B)
std::swap(Op0, Op1); // Simplified below.
} else if (match(Op0, m_Xor(m_Specific(B), m_Specific(A)))) {
Op1I->swapOperands(); // (A^B)^(B|A) == (A|B)^(A^B)
I.swapOperands(); // Simplied below.
std::swap(Op0, Op1);
You would avoid needing `A1` and `B1` *and* you could avoid hoisting `Op0I`.
================
Comment at: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp:2492-2493
@@ -2476,1 +2491,4 @@
+ }
+ } else if (Op0I && match(Op0I, m_And(m_Value(A), m_Value(B))) &&
+ Op0I->hasOneUse()) {
if (A == Op1) // (A&B)^A -> (B&A)^A
----------------
This code shouldn't have been changed. `Op0I` is already checked for `null`.
================
Comment at: test/Transforms/InstCombine/or-xor.ll:140
@@ +139,3 @@
+
+define i32 @test15(i32 %x, i32 %y) #0 {
+ %1 = xor i32 %y, %x
----------------
Kill the reference to `#0`.
http://reviews.llvm.org/D4866
More information about the llvm-commits
mailing list