diff options
Diffstat (limited to 'llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 52 |
1 files changed, 21 insertions, 31 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 9729629b167..d155f6b4803 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -23,6 +23,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Analysis/CmpInstAnalysis.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/LoopAnalysisManager.h" #include "llvm/Analysis/MemoryBuiltins.h" @@ -3620,32 +3621,29 @@ static Value *simplifySelectBitTest(Value *TrueVal, Value *FalseVal, Value *X, /// An alternative way to test if a bit is set or not uses sgt/slt instead of /// eq/ne. -static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *TrueVal, - Value *FalseVal, - bool TrueWhenUnset) { +static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *CmpRHS, + ICmpInst::Predicate Pred, + Value *TrueVal, Value *FalseVal) { + Value *X; + APInt Mask; + if (!decomposeBitTestICmp(CmpLHS, CmpRHS, Pred, X, Mask)) + return nullptr; + unsigned BitWidth = TrueVal->getType()->getScalarSizeInBits(); if (!BitWidth) return nullptr; - APInt MinSignedValue; - Value *X; - if (match(CmpLHS, m_Trunc(m_Value(X))) && (X == TrueVal || X == FalseVal)) { + Value *ExtX; + if (match(X, m_Trunc(m_Value(ExtX))) && + (ExtX == TrueVal || ExtX == FalseVal)) { // icmp slt (trunc X), 0 <--> icmp ne (and X, C), 0 // icmp sgt (trunc X), -1 <--> icmp eq (and X, C), 0 - unsigned DestSize = CmpLHS->getType()->getScalarSizeInBits(); - MinSignedValue = APInt::getSignedMinValue(DestSize).zext(BitWidth); - } else { - // icmp slt X, 0 <--> icmp ne (and X, C), 0 - // icmp sgt X, -1 <--> icmp eq (and X, C), 0 - X = CmpLHS; - MinSignedValue = APInt::getSignedMinValue(BitWidth); + X = ExtX; + Mask = Mask.zext(BitWidth); } - if (Value *V = simplifySelectBitTest(TrueVal, FalseVal, X, &MinSignedValue, - TrueWhenUnset)) - return V; - - return nullptr; + return simplifySelectBitTest(TrueVal, FalseVal, X, &Mask, + Pred == ICmpInst::ICMP_EQ); } /// Try to simplify a select instruction when its condition operand is an @@ -3658,9 +3656,6 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal, if (!match(CondVal, m_ICmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS)))) return nullptr; - // FIXME: This code is nearly duplicated in InstCombine. Using/refactoring - // decomposeBitTestICmp() might help. - // FIXME this should support ICMP_SLE/SGE forms as well if (ICmpInst::isEquality(Pred) && match(CmpRHS, m_Zero())) { Value *X; const APInt *Y; @@ -3668,18 +3663,13 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal, if (Value *V = simplifySelectBitTest(TrueVal, FalseVal, X, Y, Pred == ICmpInst::ICMP_EQ)) return V; - } else if (Pred == ICmpInst::ICMP_SLT && match(CmpRHS, m_Zero())) { - // Comparing signed-less-than 0 checks if the sign bit is set. - if (Value *V = simplifySelectWithFakeICmpEq(CmpLHS, TrueVal, FalseVal, - false)) - return V; - } else if (Pred == ICmpInst::ICMP_SGT && match(CmpRHS, m_AllOnes())) { - // Comparing signed-greater-than -1 checks if the sign bit is not set. - if (Value *V = simplifySelectWithFakeICmpEq(CmpLHS, TrueVal, FalseVal, - true)) - return V; } + // Check for other compares that behave like bit test. + if (Value *V = simplifySelectWithFakeICmpEq(CmpLHS, CmpRHS, Pred, + TrueVal, FalseVal)) + return V; + if (CondVal->hasOneUse()) { const APInt *C; if (match(CmpRHS, m_APInt(C))) { |