diff options
author | Matt Arsenault <Matthew.Arsenault@amd.com> | 2023-06-15 07:54:40 -0400 |
---|---|---|
committer | Matt Arsenault <Matthew.Arsenault@amd.com> | 2023-07-12 13:14:05 -0400 |
commit | 6ed48ebf2e80c3ada88b95c0122ead24c4cd4f29 (patch) | |
tree | b7345f2b668f17c8645378555cd8e42f7ffb7939 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | 05f0de3d74e97b594da99225a7a0b44e6ea1f3b1 (diff) | |
download | llvm-6ed48ebf2e80c3ada88b95c0122ead24c4cd4f29.zip llvm-6ed48ebf2e80c3ada88b95c0122ead24c4cd4f29.tar.gz llvm-6ed48ebf2e80c3ada88b95c0122ead24c4cd4f29.tar.bz2 |
ValueTracking: Recognize fpclass clamping select patterns
Improve computeKnownFPClass select handling to cover the case where
the condition performs a class test. This allows us to recognize
no-nans in cases like:
%not.nan = fcmp ord float %x, 0.0
%select = select i1 %not.nan, float %x, float 0.0
Math library code has similar edge case filtering on the inputs and
final results.
https://reviews.llvm.org/D153089
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; } |