From e8be18e8a32141fa54b37b27889e334ca1653488 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Mon, 11 Aug 2014 22:32:02 +0000 Subject: [PATCH] InstCombine: Combine (add (and %a, %b) (or %a, %b)) to (add %a, %b) What follows bellow is a correctness proof of the transform using CVC3. $ < t.cvc A, B : BITVECTOR(32); QUERY BVPLUS(32, A & B, A | B) = BVPLUS(32, A, B); $ cvc3 < t.cvc Valid. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215400 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineAddSub.cpp | 24 ++++++++++- test/Transforms/InstCombine/add2.ll | 40 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index ed0e1c90888..b18c10dd57b 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1240,7 +1240,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { } } - // Check for (x & y) + (x ^ y) + // (add (xor A, B) (and A, B)) --> (or A, B) { Value *A = nullptr, *B = nullptr; if (match(RHS, m_Xor(m_Value(A), m_Value(B))) && @@ -1254,6 +1254,28 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { return BinaryOperator::CreateOr(A, B); } + // (add (or A, B) (and A, B)) --> (add A, B) + { + Value *A = nullptr, *B = nullptr; + if (match(RHS, m_Or(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))))) { + auto *New = BinaryOperator::CreateAdd(A, B); + New->setHasNoSignedWrap(I.hasNoSignedWrap()); + New->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); + return New; + } + + if (match(LHS, m_Or(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))))) { + auto *New = BinaryOperator::CreateAdd(A, B); + New->setHasNoSignedWrap(I.hasNoSignedWrap()); + New->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); + return New; + } + } + // TODO(jingyue): Consider WillNotOverflowSignedAdd and // WillNotOverflowUnsignedAdd to reduce the number of invocations of // computeKnownBits. diff --git a/test/Transforms/InstCombine/add2.ll b/test/Transforms/InstCombine/add2.ll index d7eac4b0fd2..2a63082e111 100644 --- a/test/Transforms/InstCombine/add2.ll +++ b/test/Transforms/InstCombine/add2.ll @@ -313,3 +313,43 @@ define i16 @add_cttz_2(i16 %a) { ret i16 %b } !1 = metadata !{i16 0, i16 32} + +define i32 @add_or_and(i32 %x, i32 %y) { + %or = or i32 %x, %y + %and = and i32 %x, %y + %add = add i32 %or, %and + ret i32 %add +; CHECK-LABEL: @add_or_and( +; CHECK-NEXT: add i32 %x, %y +; CHECK-NEXT: ret i32 +} + +define i32 @add_nsw_or_and(i32 %x, i32 %y) { + %or = or i32 %x, %y + %and = and i32 %x, %y + %add = add nsw i32 %or, %and + ret i32 %add +; CHECK-LABEL: @add_nsw_or_and( +; CHECK-NEXT: add nsw i32 %x, %y +; CHECK-NEXT: ret i32 +} + +define i32 @add_nuw_or_and(i32 %x, i32 %y) { + %or = or i32 %x, %y + %and = and i32 %x, %y + %add = add nuw i32 %or, %and + ret i32 %add +; CHECK-LABEL: @add_nuw_or_and( +; CHECK-NEXT: add nuw i32 %x, %y +; CHECK-NEXT: ret i32 +} + +define i32 @add_nuw_nsw_or_and(i32 %x, i32 %y) { + %or = or i32 %x, %y + %and = and i32 %x, %y + %add = add nsw nuw i32 %or, %and + ret i32 %add +; CHECK-LABEL: @add_nuw_nsw_or_and( +; CHECK-NEXT: add nuw nsw i32 %x, %y +; CHECK-NEXT: ret i32 +} -- 2.34.1