From 0fd4e2e5a1836e52e0851e0ebb811e301dfd807e Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Sun, 19 Oct 2014 08:32:32 +0000 Subject: [PATCH] InstCombine: (sub (or A B) (xor A B)) --> (and A B) The following implements the transformation: (sub (or A B) (xor A B)) --> (and A B). Patch by Ankur Garg! Differential Revision: http://reviews.llvm.org/D5719 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220163 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombineAddSub.cpp | 9 +++++++++ test/Transforms/InstCombine/sub.ll | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index ace75978331..ef6875238dd 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1621,6 +1621,15 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { return BinaryOperator::CreateNeg(Y); } + // (sub (or A, B) (xor A, B)) --> (and A, B) + { + Value *A = nullptr, *B = nullptr; + if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && + (match(Op0, m_Or(m_Specific(A), m_Specific(B))) || + match(Op0, m_Or(m_Specific(B), m_Specific(A))))) + return BinaryOperator::CreateAnd(A, B); + } + if (Op1->hasOneUse()) { Value *X = nullptr, *Y = nullptr, *Z = nullptr; Constant *C = nullptr; diff --git a/test/Transforms/InstCombine/sub.ll b/test/Transforms/InstCombine/sub.ll index 1d1bedc0a7b..95a61b1747c 100644 --- a/test/Transforms/InstCombine/sub.ll +++ b/test/Transforms/InstCombine/sub.ll @@ -530,3 +530,13 @@ define i32 @test44(i32 %x) { ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 %x, -32768 ; CHECK: ret i32 [[ADD]] } + +define i32 @test45(i32 %x, i32 %y) { + %or = or i32 %x, %y + %xor = xor i32 %x, %y + %sub = sub i32 %or, %xor + ret i32 %sub +; CHECK-LABEL: @test45( +; CHECK-NEXT: %sub = and i32 %x, %y +; CHECK: ret i32 %sub +}