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 @@ -3515,9 +3515,9 @@ if (FPMathOp->hasNoInfs()) return true; - // Handle scalar constants. - if (auto *CFP = dyn_cast(V)) - return !CFP->isInfinity(); + // Handle scalar and fixed width vector constants. + if (isa(V)) + return match(V, m_NonInf()); if (Depth == MaxAnalysisRecursionDepth) return false; @@ -3547,25 +3547,6 @@ } } - // try to handle fixed width vector constants - auto *VFVTy = dyn_cast(V->getType()); - if (VFVTy && isa(V)) { - // For vectors, verify that each element is not infinity. - unsigned NumElts = VFVTy->getNumElements(); - for (unsigned i = 0; i != NumElts; ++i) { - Constant *Elt = cast(V)->getAggregateElement(i); - if (!Elt) - return false; - if (isa(Elt)) - continue; - auto *CElt = dyn_cast(Elt); - if (!CElt || CElt->isInfinity()) - return false; - } - // All elements were confirmed non-infinity or undefined. - return true; - } - // was not able to prove that V never contains infinity return false; } @@ -3579,9 +3560,9 @@ if (FPMathOp->hasNoNaNs()) return true; - // Handle scalar constants. - if (auto *CFP = dyn_cast(V)) - return !CFP->isNaN(); + // Handle scalar and fixed width vector constants. + if (isa(V)) + return match(V, m_NonNaN()); if (Depth == MaxAnalysisRecursionDepth) return false; @@ -3652,25 +3633,6 @@ } } - // Try to handle fixed width vector constants - auto *VFVTy = dyn_cast(V->getType()); - if (VFVTy && isa(V)) { - // For vectors, verify that each element is not NaN. - unsigned NumElts = VFVTy->getNumElements(); - for (unsigned i = 0; i != NumElts; ++i) { - Constant *Elt = cast(V)->getAggregateElement(i); - if (!Elt) - return false; - if (isa(Elt)) - continue; - auto *CElt = dyn_cast(Elt); - if (!CElt || CElt->isNaN()) - return false; - } - // All elements were confirmed not-NaN or undefined. - return true; - } - // Was not able to prove that V never contains NaN return false; } @@ -5345,7 +5307,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;