From: Craig Topper Date: Sun, 9 Apr 2017 06:12:41 +0000 (+0000) Subject: [InstCombine] Extend some OR combines to support vectors. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=239032f6685ab96b764d5f7f969b478779399295;p=llvm [InstCombine] Extend some OR combines to support vectors. This adds support for these combines for vectors (X^C)|Y -> (X|Y)^C iff Y&C == 0 Y|(X^C) -> (X|Y)^C iff Y&C == 0 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@299822 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index e94b6797d11..0bc85e4b6e4 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2070,26 +2070,29 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { if (Instruction *BSwap = MatchBSwap(I)) return BSwap; - Value *A = nullptr, *B = nullptr; - ConstantInt *C1 = nullptr, *C2 = nullptr; + { + Value *A; + const APInt *C; + // (X^C)|Y -> (X|Y)^C iff Y&C == 0 + if (match(Op0, m_OneUse(m_Xor(m_Value(A), m_APInt(C)))) && + MaskedValueIsZero(Op1, *C, 0, &I)) { + Value *NOr = Builder->CreateOr(A, Op1); + NOr->takeName(Op0); + return BinaryOperator::CreateXor(NOr, + cast(Op0)->getOperand(1)); + } - // (X^C)|Y -> (X|Y)^C iff Y&C == 0 - if (Op0->hasOneUse() && - match(Op0, m_Xor(m_Value(A), m_ConstantInt(C1))) && - MaskedValueIsZero(Op1, C1->getValue(), 0, &I)) { - Value *NOr = Builder->CreateOr(A, Op1); - NOr->takeName(Op0); - return BinaryOperator::CreateXor(NOr, C1); + // Y|(X^C) -> (X|Y)^C iff Y&C == 0 + if (match(Op1, m_OneUse(m_Xor(m_Value(A), m_APInt(C)))) && + MaskedValueIsZero(Op0, *C, 0, &I)) { + Value *NOr = Builder->CreateOr(A, Op0); + NOr->takeName(Op0); + return BinaryOperator::CreateXor(NOr, + cast(Op1)->getOperand(1)); + } } - // Y|(X^C) -> (X|Y)^C iff Y&C == 0 - if (Op1->hasOneUse() && - match(Op1, m_Xor(m_Value(A), m_ConstantInt(C1))) && - MaskedValueIsZero(Op0, C1->getValue(), 0, &I)) { - Value *NOr = Builder->CreateOr(A, Op0); - NOr->takeName(Op0); - return BinaryOperator::CreateXor(NOr, C1); - } + Value *A, *B; // ((~A & B) | A) -> (A | B) if (match(Op0, m_c_And(m_Not(m_Specific(Op1)), m_Value(A)))) @@ -2121,8 +2124,8 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { if (match(Op0, m_And(m_Value(A), m_Value(C))) && match(Op1, m_And(m_Value(B), m_Value(D)))) { Value *V1 = nullptr, *V2 = nullptr; - C1 = dyn_cast(C); - C2 = dyn_cast(D); + ConstantInt *C1 = dyn_cast(C); + ConstantInt *C2 = dyn_cast(D); if (C1 && C2) { // (A & C1)|(B & C2) if ((C1->getValue() & C2->getValue()) == 0) { // ((V | N) & C1) | (V & C2) --> (V|N) & (C1|C2) @@ -2347,6 +2350,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { // be simplified by a later pass either, so we try swapping the inner/outer // ORs in the hopes that we'll be able to simplify it this way. // (X|C) | V --> (X|V) | C + ConstantInt *C1; if (Op0->hasOneUse() && !isa(Op1) && match(Op0, m_Or(m_Value(A), m_ConstantInt(C1)))) { Value *Inner = Builder->CreateOr(A, Op1); diff --git a/test/Transforms/InstCombine/and.ll b/test/Transforms/InstCombine/and.ll index 868042be773..cc2e0bb7b70 100644 --- a/test/Transforms/InstCombine/and.ll +++ b/test/Transforms/InstCombine/and.ll @@ -431,10 +431,7 @@ define i32 @test33b(i32 %b) { define <2 x i32> @test33vec(<2 x i32> %b) { ; CHECK-LABEL: @test33vec( -; CHECK-NEXT: [[TMP_4_MASK:%.*]] = and <2 x i32> [[B:%.*]], -; CHECK-NEXT: [[TMP_10:%.*]] = xor <2 x i32> [[TMP_4_MASK]], -; CHECK-NEXT: [[TMP_12:%.*]] = and <2 x i32> [[B]], -; CHECK-NEXT: [[TMP_13:%.*]] = or <2 x i32> [[TMP_12]], [[TMP_10]] +; CHECK-NEXT: [[TMP_13:%.*]] = xor <2 x i32> [[B:%.*]], ; CHECK-NEXT: ret <2 x i32> [[TMP_13]] ; %tmp.4.mask = and <2 x i32> %b, @@ -446,10 +443,7 @@ define <2 x i32> @test33vec(<2 x i32> %b) { define <2 x i32> @test33vecb(<2 x i32> %b) { ; CHECK-LABEL: @test33vecb( -; CHECK-NEXT: [[TMP_4_MASK:%.*]] = and <2 x i32> [[B:%.*]], -; CHECK-NEXT: [[TMP_10:%.*]] = xor <2 x i32> [[TMP_4_MASK]], -; CHECK-NEXT: [[TMP_12:%.*]] = and <2 x i32> [[B]], -; CHECK-NEXT: [[TMP_13:%.*]] = or <2 x i32> [[TMP_10]], [[TMP_12]] +; CHECK-NEXT: [[TMP_13:%.*]] = xor <2 x i32> [[B:%.*]], ; CHECK-NEXT: ret <2 x i32> [[TMP_13]] ; %tmp.4.mask = and <2 x i32> %b,