mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[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
This commit is contained in:
parent
2c68bc5043
commit
f8c9e8db39
@ -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 {
|
||||
|
@ -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});
|
||||
|
||||
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 *VectorInfUndef = ConstantVector::get(
|
||||
{ScalarPosInf, ScalarNegInf, ScalarUndef, ScalarPosInf});
|
||||
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user