diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-09-01 15:08:59 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-09-01 15:08:59 +0000 |
commit | 099b1a4b0c2513cffbc588012b1efcdcb67e3f2c (patch) | |
tree | edb833f35542c0eaa7f481643d9b9bfe21b61c02 /llvm/lib/Transforms | |
parent | 454258671dbb8b528432073a091610f31b58b8c8 (diff) | |
download | bcm5719-llvm-099b1a4b0c2513cffbc588012b1efcdcb67e3f2c.tar.gz bcm5719-llvm-099b1a4b0c2513cffbc588012b1efcdcb67e3f2c.zip |
[InstCombine] simplify code for 'or' fold
This is no-outwardly-visible-change intended, so no test.
But the code is smaller and more efficient. The check for
a 'not' op is intended to avoid the expensive value tracking
call when it should not be necessary, and it might prevent
infinite looping when we resurrect:
rL300977
llvm-svn: 341280
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 41 |
1 files changed, 13 insertions, 28 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index e631e7396b1..7b8c1db77ce 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2156,37 +2156,22 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { if (Instruction *FoldedLogic = foldBinOpIntoSelectOrPhi(I)) return FoldedLogic; - // Given an OR instruction, check to see if this is a bswap. if (Instruction *BSwap = MatchBSwap(I)) return BSwap; - Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); - { - 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, - ConstantInt::get(NOr->getType(), *C)); - } - - // 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, - ConstantInt::get(NOr->getType(), *C)); - } + Value *X, *Y; + const APInt *CV; + if (match(&I, m_c_Or(m_OneUse(m_Xor(m_Value(X), m_APInt(CV))), m_Value(Y))) && + !CV->isAllOnesValue() && MaskedValueIsZero(Y, *CV, 0, &I)) { + // (X ^ C) | Y -> (X | Y) ^ C iff Y & C == 0 + // The check for a 'not' op is for efficiency (if Y is known zero --> ~X). + Value *Or = Builder.CreateOr(X, Y); + return BinaryOperator::CreateXor(Or, ConstantInt::get(I.getType(), *CV)); } - Value *A, *B; - // (A & C)|(B & D) - Value *C = nullptr, *D = nullptr; + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + Value *A, *B, *C, *D; if (match(Op0, m_And(m_Value(A), m_Value(C))) && match(Op1, m_And(m_Value(B), m_Value(D)))) { ConstantInt *C1 = dyn_cast<ConstantInt>(C); @@ -2378,12 +2363,12 @@ 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; + ConstantInt *CI; if (Op0->hasOneUse() && !isa<ConstantInt>(Op1) && - match(Op0, m_Or(m_Value(A), m_ConstantInt(C1)))) { + match(Op0, m_Or(m_Value(A), m_ConstantInt(CI)))) { Value *Inner = Builder.CreateOr(A, Op1); Inner->takeName(Op0); - return BinaryOperator::CreateOr(Inner, C1); + return BinaryOperator::CreateOr(Inner, CI); } // Change (or (bool?A:B),(bool?C:D)) --> (bool?(or A,C):(or B,D)) |