diff options
author | Chad Rosier <mcrosier@apple.com> | 2012-04-26 23:29:14 +0000 |
---|---|---|
committer | Chad Rosier <mcrosier@apple.com> | 2012-04-26 23:29:14 +0000 |
commit | c1fc5e4464788be072509eab7d66a73dc7a5f275 (patch) | |
tree | 96ae0b82dcbddacb15088b53743e7ad3e79277ce | |
parent | 0d5c32327a5a1ee12a60cfd0842dbd5c21fe8d91 (diff) | |
download | llvm-c1fc5e4464788be072509eab7d66a73dc7a5f275.tar.gz llvm-c1fc5e4464788be072509eab7d66a73dc7a5f275.tar.bz2 llvm-c1fc5e4464788be072509eab7d66a73dc7a5f275.tar.xz |
Add instcombine patterns for the following transformations:
(x & y) | (x ^ y) -> x | y
(x & y) + (x ^ y) -> x | y
Patch by Manman Ren.
rdar://10770603
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155674 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineAddSub.cpp | 14 | ||||
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 5 | ||||
-rw-r--r-- | test/Transforms/InstCombine/and-xor-or.ll | 24 |
3 files changed, 43 insertions, 0 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 05e702fa43..6a39fc33d4 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -329,6 +329,20 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { } } + // Check for (x & y) + (x ^ y) + { + Value *A = 0, *B = 0; + if (match(RHS, m_Xor(m_Value(A), m_Value(B))) && + (match(LHS, m_And(m_Specific(A), m_Specific(B))) || + match(LHS, m_And(m_Specific(B), m_Specific(A))))) + return BinaryOperator::CreateOr(A, B); + + if (match(LHS, m_Xor(m_Value(A), m_Value(B))) && + (match(RHS, m_And(m_Specific(A), m_Specific(B))) || + match(RHS, m_And(m_Specific(B), m_Specific(A))))) + return BinaryOperator::CreateOr(A, B); + } + return Changed ? &I : 0; } diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 0dbe11d2f0..665b3c65a1 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1932,10 +1932,15 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { // A | ( A ^ B) -> A | B // A | (~A ^ B) -> A | ~B + // (A & B) | (A ^ B) if (match(Op1, m_Xor(m_Value(A), m_Value(B)))) { if (Op0 == A || Op0 == B) return BinaryOperator::CreateOr(A, B); + if (match(Op0, m_And(m_Specific(A), m_Specific(B))) || + match(Op0, m_And(m_Specific(B), m_Specific(A)))) + return BinaryOperator::CreateOr(A, B); + if (Op1->hasOneUse() && match(A, m_Not(m_Specific(Op0)))) { Value *Not = Builder->CreateNot(B, B->getName()+".not"); return BinaryOperator::CreateOr(Not, Op0); diff --git a/test/Transforms/InstCombine/and-xor-or.ll b/test/Transforms/InstCombine/and-xor-or.ll new file mode 100644 index 0000000000..7ff810b6ee --- /dev/null +++ b/test/Transforms/InstCombine/and-xor-or.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; rdar://10770603 +; (x & y) | (x ^ y) -> x | y +define i64 @or(i64 %x, i64 %y) nounwind uwtable readnone ssp { + %1 = and i64 %y, %x + %2 = xor i64 %y, %x + %3 = add i64 %1, %2 + ret i64 %3 +; CHECK: @or +; CHECK: or i64 +; CHECK-NEXT: ret +} + +; (x & y) + (x ^ y) -> x | y +define i64 @or2(i64 %x, i64 %y) nounwind uwtable readnone ssp { + %1 = and i64 %y, %x + %2 = xor i64 %y, %x + %3 = or i64 %1, %2 + ret i64 %3 +; CHECK: @or2 +; CHECK: or i64 +; CHECK-NEXT: ret +} |