aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2023-06-15 07:54:40 -0400
committerMatt Arsenault <Matthew.Arsenault@amd.com>2023-07-12 13:14:05 -0400
commit6ed48ebf2e80c3ada88b95c0122ead24c4cd4f29 (patch)
treeb7345f2b668f17c8645378555cd8e42f7ffb7939 /llvm/lib/Analysis/ValueTracking.cpp
parent05f0de3d74e97b594da99225a7a0b44e6ea1f3b1 (diff)
downloadllvm-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.cpp46
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;
}