diff options
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 57d3d8b..37c9346 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4306,11 +4306,51 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, break; } case Instruction::Select: { + Value *Cond = Op->getOperand(0); + Value *LHS = Op->getOperand(1); + Value *RHS = Op->getOperand(2); + + FPClassTest FilterLHS = fcAllFlags; + FPClassTest FilterRHS = fcAllFlags; + + Value *TestedValue = nullptr; + FPClassTest TestedMask = fcNone; + uint64_t ClassVal = 0; + const Function *F = cast<Instruction>(Op)->getFunction(); + CmpInst::Predicate Pred; + Value *CmpLHS, *CmpRHS; + if (F && match(Cond, m_FCmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS)))) { + // If the select filters out a value based on the class, it no longer + // participates in the class of the result + + // TODO: In some degenerate cases we can infer something if we try again + // without looking through sign operations. + bool LookThroughFAbsFNeg = CmpLHS != LHS && CmpLHS != RHS; + std::tie(TestedValue, TestedMask) = + fcmpToClassTest(Pred, *F, CmpLHS, CmpRHS, LookThroughFAbsFNeg); + } else if (match(Cond, + m_Intrinsic<Intrinsic::is_fpclass>( + m_Value(TestedValue), m_ConstantInt(ClassVal)))) { + TestedMask = static_cast<FPClassTest>(ClassVal); + } + + if (TestedValue == LHS) { + // match !isnan(x) ? x : y + FilterLHS = TestedMask; + } else if (TestedValue == RHS) { + // match !isnan(x) ? y : x + FilterRHS = ~TestedMask; + } + KnownFPClass Known2; - computeKnownFPClass(Op->getOperand(1), DemandedElts, InterestedClasses, - Known, Depth + 1, Q); - computeKnownFPClass(Op->getOperand(2), DemandedElts, InterestedClasses, + computeKnownFPClass(LHS, DemandedElts, InterestedClasses & FilterLHS, Known, + Depth + 1, Q); + Known.KnownFPClasses &= FilterLHS; + + computeKnownFPClass(RHS, DemandedElts, InterestedClasses & FilterRHS, Known2, Depth + 1, Q); + Known2.KnownFPClasses &= FilterRHS; + Known |= Known2; break; } |