From: Craig Topper Date: Tue, 13 Jun 2017 17:18:45 +0000 (+0000) Subject: Fix m_[Ord|Unord][FMin|FMax] matchers to correctly match ordering. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=90d2b4be84346dfcd4e687fb328cd797d818eaac;p=llvm 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 --- diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 542570aaaa2..015a17e8e7c 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -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 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 inline MaxMin_match m_OrdFMin(const LHS &L, @@ -1154,13 +1154,28 @@ inline MaxMin_match 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 inline MaxMin_match m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match(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 +inline MaxMin_match +m_UnordFMin(const LHS &L, const RHS &R) { + return MaxMin_match(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(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 -inline MaxMin_match -m_UnordFMin(const LHS &L, const RHS &R) { - return MaxMin_match(L, R); -} - template struct Argument_match { unsigned OpI; Opnd_t Val; diff --git a/unittests/IR/PatternMatch.cpp b/unittests/IR/PatternMatch.cpp index 02ef87f5b13..5c13ba6ecd9 100644 --- a/unittests/IR/PatternMatch.cpp +++ b/unittests/IR/PatternMatch.cpp @@ -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); }