[llvm] cb9b01f - ValueTracking: Handle compare to nan and -inf constants in fcmpToClassTest
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 19 08:49:05 PDT 2023
Author: Matt Arsenault
Date: 2023-06-19T11:31:58-04:00
New Revision: cb9b01f910ca0fa1a4227e6b2e16f48705929947
URL: https://github.com/llvm/llvm-project/commit/cb9b01f910ca0fa1a4227e6b2e16f48705929947
DIFF: https://github.com/llvm/llvm-project/commit/cb9b01f910ca0fa1a4227e6b2e16f48705929947.diff
LOG: ValueTracking: Handle compare to nan and -inf constants in fcmpToClassTest
This will help enable a cleanup of simplifyFCmpInst
Added:
Modified:
llvm/lib/Analysis/ValueTracking.cpp
llvm/unittests/Analysis/ValueTrackingTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index e4e1a2b4707dc..88ed92e031892 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4012,6 +4012,14 @@ std::pair<Value *, FPClassTest> llvm::fcmpToClassTest(FCmpInst::Predicate Pred,
if (!match(RHS, m_APFloat(ConstRHS)))
return {nullptr, fcNone};
+ // fcmp ord x, zero|normal|subnormal|inf -> ~fcNan
+ if (Pred == FCmpInst::FCMP_ORD && !ConstRHS->isNaN())
+ return {LHS, ~fcNan};
+
+ // fcmp uno x, zero|normal|subnormal|inf -> fcNan
+ if (Pred == FCmpInst::FCMP_UNO && !ConstRHS->isNaN())
+ return {LHS, fcNan};
+
if (ConstRHS->isZero()) {
// Compares with fcNone are only exactly equal to fcZero if input denormals
// are not flushed.
@@ -4118,8 +4126,14 @@ std::pair<Value *, FPClassTest> llvm::fcmpToClassTest(FCmpInst::Predicate Pred,
}
case FCmpInst::FCMP_OLT:
case FCmpInst::FCMP_UGE: {
- if (ConstRHS->isNegative()) // TODO
- return {nullptr, fcNone};
+ if (ConstRHS->isNegative()) {
+ // No value is ordered and less than negative infinity.
+ // All values are unordered with or at least negative infinity.
+ // fcmp olt x, -inf -> false
+ // fcmp uge x, -inf -> true
+ Mask = fcNone;
+ break;
+ }
// fcmp olt fabs(x), +inf -> fcFinite
// fcmp uge fabs(x), +inf -> ~fcFinite
@@ -4144,6 +4158,15 @@ std::pair<Value *, FPClassTest> llvm::fcmpToClassTest(FCmpInst::Predicate Pred,
Mask |= fcNegInf;
break;
}
+ case FCmpInst::FCMP_OGT:
+ case FCmpInst::FCMP_ULE: {
+ if (ConstRHS->isNegative())
+ return {nullptr, fcNone};
+
+ // No value is ordered and greater than infinity.
+ Mask = fcNone;
+ break;
+ }
default:
return {nullptr, fcNone};
}
@@ -4176,6 +4199,10 @@ std::pair<Value *, FPClassTest> llvm::fcmpToClassTest(FCmpInst::Predicate Pred,
default:
return {nullptr, fcNone};
}
+ } else if (ConstRHS->isNaN()) {
+ // fcmp o__ x, nan -> false
+ // fcmp u__ x, nan -> true
+ Mask = fcNone;
} else
return {nullptr, fcNone};
diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp
index e464407197d63..f8910ea21e6ec 100644
--- a/llvm/unittests/Analysis/ValueTrackingTest.cpp
+++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -1791,6 +1791,105 @@ TEST_F(ComputeKnownFPClassTest, CannotBeOrderedLessThanZero) {
.cannotBeOrderedLessThanZero());
}
+TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_OrdNan) {
+ parseAssembly("define i1 @test(double %arg) {\n"
+ " %A = fcmp ord double %arg, 0x7FF8000000000000"
+ " %A2 = fcmp uno double %arg, 0x7FF8000000000000"
+ " %A3 = fcmp oeq double %arg, 0x7FF8000000000000"
+ " %A4 = fcmp ueq double %arg, 0x7FF8000000000000"
+ " ret i1 %A\n"
+ "}\n");
+
+ auto [OrdVal, OrdClass] = fcmpToClassTest(
+ CmpInst::FCMP_ORD, *A->getFunction(), A->getOperand(0), A->getOperand(1));
+ EXPECT_EQ(A->getOperand(0), OrdVal);
+ EXPECT_EQ(fcNone, OrdClass);
+
+ auto [UnordVal, UnordClass] =
+ fcmpToClassTest(CmpInst::FCMP_UNO, *A2->getFunction(), A2->getOperand(0),
+ A2->getOperand(1));
+ EXPECT_EQ(A2->getOperand(0), UnordVal);
+ EXPECT_EQ(fcAllFlags, UnordClass);
+
+ auto [OeqVal, OeqClass] =
+ fcmpToClassTest(CmpInst::FCMP_OEQ, *A3->getFunction(), A3->getOperand(0),
+ A3->getOperand(1));
+ EXPECT_EQ(A3->getOperand(0), OeqVal);
+ EXPECT_EQ(fcNone, OeqClass);
+
+ auto [UeqVal, UeqClass] =
+ fcmpToClassTest(CmpInst::FCMP_UEQ, *A3->getFunction(), A3->getOperand(0),
+ A3->getOperand(1));
+ EXPECT_EQ(A3->getOperand(0), UeqVal);
+ EXPECT_EQ(fcAllFlags, UeqClass);
+}
+
+TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_NInf) {
+ parseAssembly("define i1 @test(double %arg) {\n"
+ " %A = fcmp olt double %arg, 0xFFF0000000000000"
+ " %A2 = fcmp uge double %arg, 0xFFF0000000000000"
+ " %A3 = fcmp ogt double %arg, 0xFFF0000000000000"
+ " %A4 = fcmp ule double %arg, 0xFFF0000000000000"
+ " ret i1 %A\n"
+ "}\n");
+
+ auto [OltVal, OltClass] = fcmpToClassTest(
+ CmpInst::FCMP_OLT, *A->getFunction(), A->getOperand(0), A->getOperand(1));
+ EXPECT_EQ(A->getOperand(0), OltVal);
+ EXPECT_EQ(fcNone, OltClass);
+
+ auto [UgeVal, UgeClass] =
+ fcmpToClassTest(CmpInst::FCMP_UGE, *A2->getFunction(), A2->getOperand(0),
+ A2->getOperand(1));
+ EXPECT_EQ(A2->getOperand(0), UgeVal);
+ EXPECT_EQ(fcAllFlags, UgeClass);
+
+ auto [OgtVal, OgtClass] =
+ fcmpToClassTest(CmpInst::FCMP_OGT, *A3->getFunction(), A3->getOperand(0),
+ A3->getOperand(1));
+ EXPECT_EQ(nullptr, OgtVal);
+ EXPECT_EQ(fcNone, OgtClass);
+
+ auto [UleVal, UleClass] =
+ fcmpToClassTest(CmpInst::FCMP_ULE, *A4->getFunction(), A4->getOperand(0),
+ A4->getOperand(1));
+ EXPECT_EQ(nullptr, UleVal);
+ EXPECT_EQ(fcNone, UleClass);
+}
+
+TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_PInf) {
+ parseAssembly("define i1 @test(double %arg) {\n"
+ " %A = fcmp ogt double %arg, 0x7FF0000000000000"
+ " %A2 = fcmp ule double %arg, 0x7FF0000000000000"
+ " %A3 = fcmp ole double %arg, 0x7FF0000000000000"
+ " %A4 = fcmp ugt double %arg, 0x7FF0000000000000"
+ " ret i1 %A\n"
+ "}\n");
+
+ auto [OgtVal, OgtClass] = fcmpToClassTest(
+ CmpInst::FCMP_OGT, *A->getFunction(), A->getOperand(0), A->getOperand(1));
+ EXPECT_EQ(A->getOperand(0), OgtVal);
+ EXPECT_EQ(fcNone, OgtClass);
+
+ auto [UleVal, UleClass] =
+ fcmpToClassTest(CmpInst::FCMP_ULE, *A2->getFunction(), A2->getOperand(0),
+ A2->getOperand(1));
+ EXPECT_EQ(A2->getOperand(0), UleVal);
+ EXPECT_EQ(fcAllFlags, UleClass);
+
+ auto [OleVal, OleClass] =
+ fcmpToClassTest(CmpInst::FCMP_OLE, *A3->getFunction(), A3->getOperand(0),
+ A3->getOperand(1));
+ EXPECT_EQ(nullptr, OleVal);
+ EXPECT_EQ(fcNone, OleClass);
+
+ auto [UgtVal, UgtClass] =
+ fcmpToClassTest(CmpInst::FCMP_UGT, *A4->getFunction(), A4->getOperand(0),
+ A4->getOperand(1));
+ EXPECT_EQ(nullptr, UgtVal);
+ EXPECT_EQ(fcNone, UgtClass);
+}
+
TEST_F(ValueTrackingTest, isNonZeroRecurrence) {
parseAssembly(R"(
define i1 @test(i8 %n, i8 %r) {
More information about the llvm-commits
mailing list