mirror of
https://github.com/RPCSX/llvm.git
synced 2026-01-31 01:05:23 +01:00
Fix m_[Ord|Unord][FMin|FMax] matchers to correctly match ordering.
Previously, the matching was done incorrectly for the case where operands for FCmpInst and SelectInst were in opposite order. Patch by Andrei Elovikov. Differential Revision: https://reviews.llvm.org/D33185 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305308 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1027,7 +1027,7 @@ struct MaxMin_match {
|
||||
(TrueVal != RHS || FalseVal != LHS))
|
||||
return false;
|
||||
typename CmpInst_t::Predicate Pred =
|
||||
LHS == TrueVal ? Cmp->getPredicate() : Cmp->getSwappedPredicate();
|
||||
LHS == TrueVal ? Cmp->getPredicate() : Cmp->getInversePredicate();
|
||||
// Does "(x pred y) ? x : y" represent the desired max/min operation?
|
||||
if (!Pred_t::match(Pred))
|
||||
return false;
|
||||
@@ -1138,7 +1138,7 @@ inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty> m_OrdFMax(const LHS &L,
|
||||
/// semantics. In the presence of 'NaN' we have to preserve the original
|
||||
/// select(fcmp(olt/le, L, R), L, R) semantics matched by this predicate.
|
||||
///
|
||||
/// max(L, R) iff L and R are not NaN
|
||||
/// min(L, R) iff L and R are not NaN
|
||||
/// m_OrdFMin(L, R) = R iff L or R are NaN
|
||||
template <typename LHS, typename RHS>
|
||||
inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> m_OrdFMin(const LHS &L,
|
||||
@@ -1154,13 +1154,28 @@ inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> m_OrdFMin(const LHS &L,
|
||||
/// select(fcmp(ugt/ge, L, R), L, R) semantics matched by this predicate.
|
||||
///
|
||||
/// max(L, R) iff L and R are not NaN
|
||||
/// m_UnordFMin(L, R) = L iff L or R are NaN
|
||||
/// m_UnordFMax(L, R) = L iff L or R are NaN
|
||||
template <typename LHS, typename RHS>
|
||||
inline MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>
|
||||
m_UnordFMax(const LHS &L, const RHS &R) {
|
||||
return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R);
|
||||
}
|
||||
|
||||
/// \brief Match an 'unordered' floating point minimum function.
|
||||
/// Floating point has one special value 'NaN'. Therefore, there is no total
|
||||
/// order. However, if we can ignore the 'NaN' value (for example, because of a
|
||||
/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum'
|
||||
/// semantics. In the presence of 'NaN' we have to preserve the original
|
||||
/// select(fcmp(ult/le, L, R), L, R) semantics matched by this predicate.
|
||||
///
|
||||
/// min(L, R) iff L and R are not NaN
|
||||
/// m_UnordFMin(L, R) = L iff L or R are NaN
|
||||
template <typename LHS, typename RHS>
|
||||
inline MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>
|
||||
m_UnordFMin(const LHS &L, const RHS &R) {
|
||||
return MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>(L, R);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Matchers for overflow check patterns: e.g. (a + b) u< a
|
||||
//
|
||||
@@ -1207,21 +1222,6 @@ m_UAddWithOverflow(const LHS_t &L, const RHS_t &R, const Sum_t &S) {
|
||||
return UAddWithOverflow_match<LHS_t, RHS_t, Sum_t>(L, R, S);
|
||||
}
|
||||
|
||||
/// \brief Match an 'unordered' floating point minimum function.
|
||||
/// Floating point has one special value 'NaN'. Therefore, there is no total
|
||||
/// order. However, if we can ignore the 'NaN' value (for example, because of a
|
||||
/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum'
|
||||
/// semantics. In the presence of 'NaN' we have to preserve the original
|
||||
/// select(fcmp(ult/le, L, R), L, R) semantics matched by this predicate.
|
||||
///
|
||||
/// max(L, R) iff L and R are not NaN
|
||||
/// m_UnordFMin(L, R) = L iff L or R are NaN
|
||||
template <typename LHS, typename RHS>
|
||||
inline MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>
|
||||
m_UnordFMin(const LHS &L, const RHS &R) {
|
||||
return MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>(L, R);
|
||||
}
|
||||
|
||||
template <typename Opnd_t> struct Argument_match {
|
||||
unsigned OpI;
|
||||
Opnd_t Val;
|
||||
|
||||
@@ -91,15 +91,26 @@ TEST_F(PatternMatchTest, FloatingPointOrderedMin) {
|
||||
EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R)));
|
||||
|
||||
// Test match on OGE with inverted select.
|
||||
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
// Test inverted selects. Note, that this "inverts" the ordering, e.g.:
|
||||
// %cmp = fcmp oge L, R
|
||||
// %min = select %cmp R, L
|
||||
// Given L == NaN
|
||||
// the above is expanded to %cmp == false ==> %min = L
|
||||
// which is true for UnordFMin, not OrdFMin, so test that:
|
||||
|
||||
// [OU]GE with inverted select.
|
||||
EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L)));
|
||||
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L)));
|
||||
EXPECT_EQ(L, MatchL);
|
||||
EXPECT_EQ(R, MatchR);
|
||||
|
||||
// Test match on OGT with inverted select.
|
||||
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
// [OU]GT with inverted select.
|
||||
EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L)));
|
||||
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L)));
|
||||
EXPECT_EQ(L, MatchL);
|
||||
EXPECT_EQ(R, MatchR);
|
||||
}
|
||||
@@ -130,15 +141,27 @@ TEST_F(PatternMatchTest, FloatingPointOrderedMax) {
|
||||
EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R)));
|
||||
|
||||
// Test match on OLE with inverted select.
|
||||
|
||||
// Test inverted selects. Note, that this "inverts" the ordering, e.g.:
|
||||
// %cmp = fcmp ole L, R
|
||||
// %max = select %cmp, R, L
|
||||
// Given L == NaN,
|
||||
// the above is expanded to %cmp == false ==> %max == L
|
||||
// which is true for UnordFMax, not OrdFMax, so test that:
|
||||
|
||||
// [OU]LE with inverted select.
|
||||
EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L)));
|
||||
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L)));
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L)));
|
||||
EXPECT_EQ(L, MatchL);
|
||||
EXPECT_EQ(R, MatchR);
|
||||
|
||||
// Test match on OLT with inverted select.
|
||||
// [OUT]LT with inverted select.
|
||||
EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L)));
|
||||
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L)));
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L)));
|
||||
EXPECT_EQ(L, MatchL);
|
||||
EXPECT_EQ(R, MatchR);
|
||||
}
|
||||
@@ -169,15 +192,26 @@ TEST_F(PatternMatchTest, FloatingPointUnorderedMin) {
|
||||
EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R)));
|
||||
|
||||
// Test match on UGE with inverted select.
|
||||
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
// Test inverted selects. Note, that this "inverts" the ordering, e.g.:
|
||||
// %cmp = fcmp uge L, R
|
||||
// %min = select %cmp R, L
|
||||
// Given L == NaN
|
||||
// the above is expanded to %cmp == true ==> %min = R
|
||||
// which is true for OrdFMin, not UnordFMin, so test that:
|
||||
|
||||
// [UO]GE with inverted select.
|
||||
EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L)));
|
||||
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L)));
|
||||
EXPECT_EQ(L, MatchL);
|
||||
EXPECT_EQ(R, MatchR);
|
||||
|
||||
// Test match on UGT with inverted select.
|
||||
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
// [UO]GT with inverted select.
|
||||
EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L)));
|
||||
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L)));
|
||||
EXPECT_EQ(L, MatchL);
|
||||
EXPECT_EQ(R, MatchR);
|
||||
}
|
||||
@@ -208,15 +242,26 @@ TEST_F(PatternMatchTest, FloatingPointUnorderedMax) {
|
||||
EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R)));
|
||||
|
||||
// Test match on ULE with inverted select.
|
||||
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
// Test inverted selects. Note, that this "inverts" the ordering, e.g.:
|
||||
// %cmp = fcmp ule L, R
|
||||
// %max = select %cmp R, L
|
||||
// Given L == NaN
|
||||
// the above is expanded to %cmp == true ==> %max = R
|
||||
// which is true for OrdFMax, not UnordFMax, so test that:
|
||||
|
||||
// [UO]LE with inverted select.
|
||||
EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L)));
|
||||
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L)));
|
||||
EXPECT_EQ(L, MatchL);
|
||||
EXPECT_EQ(R, MatchR);
|
||||
|
||||
// Test match on ULT with inverted select.
|
||||
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
// [UO]LT with inverted select.
|
||||
EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L)));
|
||||
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
||||
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L)));
|
||||
EXPECT_EQ(L, MatchL);
|
||||
EXPECT_EQ(R, MatchR);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user