diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-12-20 04:45:35 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-12-20 04:45:35 +0000 |
commit | b0362e4ee650853b8f96689ddd8fb858f6824dc7 (patch) | |
tree | 7ef7dc6eff51075a1241ba76c7cf694200667a5b /llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | |
parent | 147f8586bebf86f6354a7d0c9c9a47c5b76798c7 (diff) | |
download | bcm5719-llvm-b0362e4ee650853b8f96689ddd8fb858f6824dc7.tar.gz bcm5719-llvm-b0362e4ee650853b8f96689ddd8fb858f6824dc7.zip |
InstCombine: Squash an icmp+select into bitwise arithmetic
(X & INT_MIN) == 0 ? X ^ INT_MIN : X into X | INT_MIN
(X & INT_MIN) != 0 ? X ^ INT_MIN : X into X & INT_MAX
This fixes PR21993.
llvm-svn: 224676
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 83a2f2c563f..df55e86f059 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -617,26 +617,44 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI, } } - { + if (unsigned BitWidth = TrueVal->getType()->getScalarSizeInBits()) { + APInt MinSignedValue = APInt::getSignBit(BitWidth); Value *X; const APInt *Y, *C; - if (match(CmpLHS, m_And(m_Value(X), m_Power2(Y))) && + bool TrueWhenUnset; + bool IsBitTest = false; + if (ICmpInst::isEquality(Pred) && + match(CmpLHS, m_And(m_Value(X), m_Power2(Y))) && match(CmpRHS, m_Zero())) { + IsBitTest = true; + TrueWhenUnset = Pred == ICmpInst::ICMP_EQ; + } else if (Pred == ICmpInst::ICMP_SLT && match(CmpRHS, m_Zero())) { + X = CmpLHS; + Y = &MinSignedValue; + IsBitTest = true; + TrueWhenUnset = false; + } else if (Pred == ICmpInst::ICMP_SGT && match(CmpRHS, m_AllOnes())) { + X = CmpLHS; + Y = &MinSignedValue; + IsBitTest = true; + TrueWhenUnset = true; + } + if (IsBitTest) { Value *V = nullptr; // (X & Y) == 0 ? X : X ^ Y --> X & ~Y - if (Pred == ICmpInst::ICMP_EQ && TrueVal == X && + if (TrueWhenUnset && TrueVal == X && match(FalseVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C) V = Builder->CreateAnd(X, ~(*Y)); // (X & Y) != 0 ? X ^ Y : X --> X & ~Y - else if (Pred == ICmpInst::ICMP_NE && FalseVal == X && + else if (!TrueWhenUnset && FalseVal == X && match(TrueVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C) V = Builder->CreateAnd(X, ~(*Y)); // (X & Y) == 0 ? X ^ Y : X --> X | Y - else if (Pred == ICmpInst::ICMP_EQ && FalseVal == X && + else if (TrueWhenUnset && FalseVal == X && match(TrueVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C) V = Builder->CreateOr(X, *Y); // (X & Y) != 0 ? X : X ^ Y --> X | Y - else if (Pred == ICmpInst::ICMP_NE && TrueVal == X && + else if (!TrueWhenUnset && TrueVal == X && match(FalseVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C) V = Builder->CreateOr(X, *Y); |