diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -335,6 +335,31 @@ } }; +/// This helper class is used to match scalar and vector constants that +/// satisfy a specified predicate, and bind them to an APFloat. +template struct apf_pred_ty : public Predicate { + const APFloat *&Res; + + apf_pred_ty(const APFloat *&R) : Res(R) {} + + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) + if (this->isValue(CI->getValue())) { + Res = &CI->getValue(); + return true; + } + if (V->getType()->isVectorTy()) + if (const auto *C = dyn_cast(V)) + if (auto *CI = dyn_cast_or_null(C->getSplatValue())) + if (this->isValue(CI->getValue())) { + Res = &CI->getValue(); + return true; + } + + return false; + } +}; + /////////////////////////////////////////////////////////////////////////////// // // Encapsulate constant value queries for use in templated predicate matchers. @@ -555,6 +580,15 @@ return cstfp_pred_ty(); } +struct is_nonnan { + bool isValue(const APFloat &C) { return !C.isNaN(); } +}; +/// Match a non-NaN FP constant. +/// For vectors, this includes constants with undefined elements. +inline cstfp_pred_ty m_NonNaN() { + return cstfp_pred_ty(); +} + struct is_inf { bool isValue(const APFloat &C) { return C.isInfinity(); } }; @@ -564,6 +598,25 @@ return cstfp_pred_ty(); } +struct is_noninf { + bool isValue(const APFloat &C) { return !C.isInfinity(); } +}; +/// Match a non-infinity FP constant, i.e. finite or NaN. +/// For vectors, this includes constants with undefined elements. +inline cstfp_pred_ty m_NonInf() { + return cstfp_pred_ty(); +} + +struct is_finite { + bool isValue(const APFloat &C) { return C.isFinite(); } +}; +/// Match a finite FP constant, i.e. not infinity or NaN. +/// For vectors, this includes constants with undefined elements. +inline cstfp_pred_ty m_Finite() { + return cstfp_pred_ty(); +} +inline apf_pred_ty m_Finite(const APFloat *&V) { return V; } + struct is_any_zero_fp { bool isValue(const APFloat &C) { return C.isZero(); } }; @@ -591,6 +644,15 @@ return cstfp_pred_ty(); } +struct is_non_zero_fp { + bool isValue(const APFloat &C) { return C.isNonZero(); } +}; +/// Match a floating-point non-zero. +/// For vectors, this includes constants with undefined elements. +inline cstfp_pred_ty m_NonZeroFP() { + return cstfp_pred_ty(); +} + /////////////////////////////////////////////////////////////////////////////// template struct bind_ty { diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4036,9 +4036,7 @@ // change the sign of a zero operand. bool HasNoSignedZeros = Q.CxtI && isa(Q.CxtI) && Q.CxtI->hasNoSignedZeros(); - const APFloat *C; - if (HasNoSignedZeros || (match(T, m_APFloat(C)) && C->isNonZero()) || - (match(F, m_APFloat(C)) && C->isNonZero())) { + if (HasNoSignedZeros || match(T, m_NonZeroFP()) || match(F, m_NonZeroFP())) { // (T == F) ? T : F --> F // (F == T) ? T : F --> F if (Pred == FCmpInst::FCMP_OEQ) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -3558,8 +3558,7 @@ return false; if (isa(Elt)) continue; - auto *CElt = dyn_cast(Elt); - if (!CElt || CElt->isInfinity()) + if (!match(Elt, m_NonInf())) return false; } // All elements were confirmed non-infinity or undefined. @@ -3663,8 +3662,7 @@ return false; if (isa(Elt)) continue; - auto *CElt = dyn_cast(Elt); - if (!CElt || CElt->isNaN()) + if (!match(Elt, m_NonNaN())) return false; } // All elements were confirmed not-NaN or undefined. @@ -5345,7 +5343,7 @@ RHS = FalseVal; const APFloat *FC1; - if (CmpRHS != TrueVal || !match(CmpRHS, m_APFloat(FC1)) || !FC1->isFinite()) + if (CmpRHS != TrueVal || !match(CmpRHS, m_Finite(FC1))) return {SPF_UNKNOWN, SPNB_NA, false}; const APFloat *FC2;