[llvm] 922285a - [PatternMatch] Add new FP matchers. NFC.
Jay Foad via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 22 11:43:24 PDT 2020
Author: Jay Foad
Date: 2020-10-22T19:43:12+01:00
New Revision: 922285abec7cdcce1045b979ea1ff1091243bb0b
URL: https://github.com/llvm/llvm-project/commit/922285abec7cdcce1045b979ea1ff1091243bb0b
DIFF: https://github.com/llvm/llvm-project/commit/922285abec7cdcce1045b979ea1ff1091243bb0b.diff
LOG: [PatternMatch] Add new FP matchers. NFC.
This adds matchers m_NonNaN, m_NonInf, m_Finite and m_NonZeroFP as well
as generic support for binding the matched value to an APFloat.
I tried to follow the existing convention of using an FP suffix for
predicates like zero and non-zero, which could be confused with the
integer versions, but not for predicates which are clearly already
FP-specific.
Differential Revision: https://reviews.llvm.org/D89038
Added:
Modified:
llvm/include/llvm/IR/PatternMatch.h
llvm/unittests/IR/PatternMatch.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 85a358f09014..987d9c4b99fc 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -335,6 +335,33 @@ template <typename Predicate> struct api_pred_ty : public Predicate {
}
};
+/// This helper class is used to match scalar and vector constants that
+/// satisfy a specified predicate, and bind them to an APFloat.
+/// Undefs are allowed in splat vector constants.
+template <typename Predicate> struct apf_pred_ty : public Predicate {
+ const APFloat *&Res;
+
+ apf_pred_ty(const APFloat *&R) : Res(R) {}
+
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CI = dyn_cast<ConstantFP>(V))
+ if (this->isValue(CI->getValue())) {
+ Res = &CI->getValue();
+ return true;
+ }
+ if (V->getType()->isVectorTy())
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (auto *CI = dyn_cast_or_null<ConstantFP>(
+ C->getSplatValue(/* AllowUndef */ true)))
+ if (this->isValue(CI->getValue())) {
+ Res = &CI->getValue();
+ return true;
+ }
+
+ return false;
+ }
+};
+
///////////////////////////////////////////////////////////////////////////////
//
// Encapsulate constant value queries for use in templated predicate matchers.
@@ -555,6 +582,15 @@ inline cstfp_pred_ty<is_nan> m_NaN() {
return cstfp_pred_ty<is_nan>();
}
+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<is_nonnan> m_NonNaN() {
+ return cstfp_pred_ty<is_nonnan>();
+}
+
struct is_inf {
bool isValue(const APFloat &C) { return C.isInfinity(); }
};
@@ -564,6 +600,25 @@ inline cstfp_pred_ty<is_inf> m_Inf() {
return cstfp_pred_ty<is_inf>();
}
+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<is_noninf> m_NonInf() {
+ return cstfp_pred_ty<is_noninf>();
+}
+
+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<is_finite> m_Finite() {
+ return cstfp_pred_ty<is_finite>();
+}
+inline apf_pred_ty<is_finite> m_Finite(const APFloat *&V) { return V; }
+
struct is_any_zero_fp {
bool isValue(const APFloat &C) { return C.isZero(); }
};
@@ -591,6 +646,15 @@ inline cstfp_pred_ty<is_neg_zero_fp> m_NegZeroFP() {
return cstfp_pred_ty<is_neg_zero_fp>();
}
+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<is_non_zero_fp> m_NonZeroFP() {
+ return cstfp_pred_ty<is_non_zero_fp>();
+}
+
///////////////////////////////////////////////////////////////////////////////
template <typename Class> struct bind_ty {
diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp
index 97d8da5b07b4..86d9ed5e4055 100644
--- a/llvm/unittests/IR/PatternMatch.cpp
+++ b/llvm/unittests/IR/PatternMatch.cpp
@@ -1093,39 +1093,77 @@ TEST_F(PatternMatchTest, VectorUndefFloat) {
Constant *VectorZero = Constant::getNullValue(VectorTy);
Constant *ScalarPosInf = ConstantFP::getInfinity(ScalarTy, false);
Constant *ScalarNegInf = ConstantFP::getInfinity(ScalarTy, true);
+ Constant *ScalarNaN = ConstantFP::getNaN(ScalarTy, true);
- SmallVector<Constant *, 4> Elems;
- Elems.push_back(ScalarUndef);
- Elems.push_back(ScalarZero);
- Elems.push_back(ScalarUndef);
- Elems.push_back(ScalarZero);
- Constant *VectorZeroUndef = ConstantVector::get(Elems);
+ Constant *VectorZeroUndef =
+ ConstantVector::get({ScalarUndef, ScalarZero, ScalarUndef, ScalarZero});
+
+ Constant *VectorInfUndef = ConstantVector::get(
+ {ScalarPosInf, ScalarNegInf, ScalarUndef, ScalarPosInf});
- SmallVector<Constant *, 4> InfElems;
- InfElems.push_back(ScalarPosInf);
- InfElems.push_back(ScalarNegInf);
- InfElems.push_back(ScalarUndef);
- InfElems.push_back(ScalarPosInf);
- Constant *VectorInfUndef = ConstantVector::get(InfElems);
+ Constant *VectorNaNUndef =
+ ConstantVector::get({ScalarUndef, ScalarNaN, ScalarNaN, ScalarNaN});
EXPECT_TRUE(match(ScalarUndef, m_Undef()));
EXPECT_TRUE(match(VectorUndef, m_Undef()));
EXPECT_FALSE(match(ScalarZero, m_Undef()));
EXPECT_FALSE(match(VectorZero, m_Undef()));
EXPECT_FALSE(match(VectorZeroUndef, m_Undef()));
+ EXPECT_FALSE(match(VectorInfUndef, m_Undef()));
+ EXPECT_FALSE(match(VectorNaNUndef, m_Undef()));
EXPECT_FALSE(match(ScalarUndef, m_AnyZeroFP()));
EXPECT_FALSE(match(VectorUndef, m_AnyZeroFP()));
EXPECT_TRUE(match(ScalarZero, m_AnyZeroFP()));
EXPECT_TRUE(match(VectorZero, m_AnyZeroFP()));
EXPECT_TRUE(match(VectorZeroUndef, m_AnyZeroFP()));
+ EXPECT_FALSE(match(VectorInfUndef, m_AnyZeroFP()));
+ EXPECT_FALSE(match(VectorNaNUndef, m_AnyZeroFP()));
+
+ EXPECT_FALSE(match(ScalarUndef, m_NaN()));
+ EXPECT_FALSE(match(VectorUndef, m_NaN()));
+ EXPECT_FALSE(match(VectorZeroUndef, m_NaN()));
+ EXPECT_FALSE(match(ScalarPosInf, m_NaN()));
+ EXPECT_FALSE(match(ScalarNegInf, m_NaN()));
+ EXPECT_TRUE(match(ScalarNaN, m_NaN()));
+ EXPECT_FALSE(match(VectorInfUndef, m_NaN()));
+ EXPECT_TRUE(match(VectorNaNUndef, m_NaN()));
+
+ EXPECT_FALSE(match(ScalarUndef, m_NonNaN()));
+ EXPECT_FALSE(match(VectorUndef, m_NonNaN()));
+ EXPECT_TRUE(match(VectorZeroUndef, m_NonNaN()));
+ EXPECT_TRUE(match(ScalarPosInf, m_NonNaN()));
+ EXPECT_TRUE(match(ScalarNegInf, m_NonNaN()));
+ EXPECT_FALSE(match(ScalarNaN, m_NonNaN()));
+ EXPECT_TRUE(match(VectorInfUndef, m_NonNaN()));
+ EXPECT_FALSE(match(VectorNaNUndef, m_NonNaN()));
EXPECT_FALSE(match(ScalarUndef, m_Inf()));
EXPECT_FALSE(match(VectorUndef, m_Inf()));
EXPECT_FALSE(match(VectorZeroUndef, m_Inf()));
EXPECT_TRUE(match(ScalarPosInf, m_Inf()));
EXPECT_TRUE(match(ScalarNegInf, m_Inf()));
+ EXPECT_FALSE(match(ScalarNaN, m_Inf()));
EXPECT_TRUE(match(VectorInfUndef, m_Inf()));
+ EXPECT_FALSE(match(VectorNaNUndef, m_Inf()));
+
+ EXPECT_FALSE(match(ScalarUndef, m_NonInf()));
+ EXPECT_FALSE(match(VectorUndef, m_NonInf()));
+ EXPECT_TRUE(match(VectorZeroUndef, m_NonInf()));
+ EXPECT_FALSE(match(ScalarPosInf, m_NonInf()));
+ EXPECT_FALSE(match(ScalarNegInf, m_NonInf()));
+ EXPECT_TRUE(match(ScalarNaN, m_NonInf()));
+ EXPECT_FALSE(match(VectorInfUndef, m_NonInf()));
+ EXPECT_TRUE(match(VectorNaNUndef, m_NonInf()));
+
+ EXPECT_FALSE(match(ScalarUndef, m_Finite()));
+ EXPECT_FALSE(match(VectorUndef, m_Finite()));
+ EXPECT_TRUE(match(VectorZeroUndef, m_Finite()));
+ EXPECT_FALSE(match(ScalarPosInf, m_Finite()));
+ EXPECT_FALSE(match(ScalarNegInf, m_Finite()));
+ EXPECT_FALSE(match(ScalarNaN, m_Finite()));
+ EXPECT_FALSE(match(VectorInfUndef, m_Finite()));
+ EXPECT_FALSE(match(VectorNaNUndef, m_Finite()));
const APFloat *C;
// Regardless of whether undefs are allowed,
@@ -1163,6 +1201,9 @@ TEST_F(PatternMatchTest, VectorUndefFloat) {
C = nullptr;
EXPECT_TRUE(match(VectorZeroUndef, m_APFloatAllowUndef(C)));
EXPECT_TRUE(C->isZero());
+ C = nullptr;
+ EXPECT_TRUE(match(VectorZeroUndef, m_Finite(C)));
+ EXPECT_TRUE(C->isZero());
}
TEST_F(PatternMatchTest, FloatingPointFNeg) {
More information about the llvm-commits
mailing list