From 6fe6ea740cf6b7b1139ee8825571e8194aa4cc89 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Fri, 5 Sep 2014 06:09:24 +0000 Subject: [PATCH] InstCombine: Remove a special case pattern The special case did not work when run under -reassociate and can easily be expressed by a further generalization of an existing pattern. llvm-svn: 217227 --- .../InstCombine/InstCombineAndOrXor.cpp | 31 ++++++++++--------- llvm/test/Transforms/InstCombine/xor2.ll | 27 ++++++++++++---- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index b19e8b4d72de..ed6253532e09 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2614,17 +2614,25 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { match(Op1I, m_And(m_Specific(A), m_Not(m_Specific(B))))) { 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 ^ C)^(A | B) -> ((~A) & B) ^ C + if (match(Op0I, m_Xor(m_Value(D), m_Value(C))) && + match(Op1I, m_Or(m_Value(A), m_Value(B)))) { + if (D == A) + return BinaryOperator::CreateXor( + Builder->CreateAnd(Builder->CreateNot(A), B), C); + if (D == B) + return BinaryOperator::CreateXor( + Builder->CreateAnd(Builder->CreateNot(B), A), C); } - // (A | B)^(A ^ B) -> A & B + // (A | B)^(A ^ C) -> ((~A) & B) ^ C 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); + match(Op1I, m_Xor(m_Value(D), m_Value(C)))) { + if (D == A) + return BinaryOperator::CreateXor( + Builder->CreateAnd(Builder->CreateNot(A), B), C); + if (D == B) + return BinaryOperator::CreateXor( + Builder->CreateAnd(Builder->CreateNot(B), A), C); } // (A & B) ^ (A ^ B) -> (A | B) if (match(Op0I, m_And(m_Value(A), m_Value(B))) && @@ -2636,12 +2644,7 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { return BinaryOperator::CreateOr(A, B); } - // (A | B)^(~A) -> (A | ~B) Value *A = nullptr, *B = nullptr; - if (match(Op0, m_Or(m_Value(A), m_Value(B))) && - match(Op1, m_Not(m_Specific(A)))) - return BinaryOperator::CreateOr(A, Builder->CreateNot(B)); - // (A & ~B) ^ (~A) -> ~(A & B) if (match(Op0, m_And(m_Value(A), m_Not(m_Value(B)))) && match(Op1, m_Not(m_Specific(A)))) diff --git a/llvm/test/Transforms/InstCombine/xor2.ll b/llvm/test/Transforms/InstCombine/xor2.ll index 2f78b294a75a..a449e12c5b0e 100644 --- a/llvm/test/Transforms/InstCombine/xor2.ll +++ b/llvm/test/Transforms/InstCombine/xor2.ll @@ -85,25 +85,27 @@ define i32 @test6(i32 %x) { ; (A | B) ^ (~A) -> (A | ~B) -define i32 @test7(i32 %a, i32 %b) #0 { +define i32 @test7(i32 %a, i32 %b) { %or = or i32 %a, %b %neg = xor i32 %a, -1 %xor = xor i32 %or, %neg ret i32 %xor ; CHECK-LABEL: @test7( -; CHECK-NEXT: %1 = xor i32 %b, -1 -; CHECK-NEXT: %xor = or i32 %a, %1 +; CHECK-NEXT: %[[b_not:.*]] = xor i32 %b, -1 +; CHECK-NEXT: %[[or:.*]] = or i32 %a, %[[b_not]] +; CHECK-NEXT: ret i32 %[[or]] } ; (~A) ^ (A | B) -> (A | ~B) -define i32 @test8(i32 %a, i32 %b) #0 { +define i32 @test8(i32 %a, i32 %b) { %neg = xor i32 %a, -1 %or = or i32 %a, %b %xor = xor i32 %neg, %or ret i32 %xor ; CHECK-LABEL: @test8( -; CHECK-NEXT: %1 = xor i32 %b, -1 -; CHECK-NEXT: %xor = or i32 %a, %1 +; CHECK-NEXT: %[[b_not:.*]] = xor i32 %b, -1 +; CHECK-NEXT: %[[or:.*]] = or i32 %a, %[[b_not]] +; CHECK-NEXT: ret i32 %[[or]] } ; (A & B) ^ (A ^ B) -> (A | B) @@ -167,3 +169,16 @@ define i32 @test14(i32 %a, i32 %b) { ; CHECK-NEXT: %1 = and i32 %a, %b ; CHECK-NEXT: %xor = xor i32 %1, -1 } + +; (A ^ C) ^ (A | B) -> ((~A) & B) ^ C +define i32 @test15(i32 %a, i32 %b, i32 %c) { + %neg = xor i32 %a, %c + %or = or i32 %a, %b + %xor = xor i32 %neg, %or + ret i32 %xor +; CHECK-LABEL: @test15( +; CHECK-NEXT: %[[not:.*]] = xor i32 %a, -1 +; CHECK-NEXT: %[[and:.*]] = and i32 %[[not]], %b +; CHECK-NEXT: %[[xor:.*]] = xor i32 %[[and]], %c +; CHECK-NEXT: ret i32 %[[xor]] +}