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
This commit is contained in:
David Majnemer 2014-08-11 22:32:02 +00:00
parent 13f4476c55
commit e8be18e8a3
2 changed files with 63 additions and 1 deletions

View File

@ -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.

View File

@ -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
}