From cb9b01f910ca0fa1a4227e6b2e16f48705929947 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 24 May 2023 12:47:57 +0100 Subject: [PATCH] ValueTracking: Handle compare to nan and -inf constants in fcmpToClassTest This will help enable a cleanup of simplifyFCmpInst --- llvm/lib/Analysis/ValueTracking.cpp | 31 ++++++++- llvm/unittests/Analysis/ValueTrackingTest.cpp | 99 +++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index e4e1a2b..88ed92e 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4012,6 +4012,14 @@ std::pair 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 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 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 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 e464407..f8910ea 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) { -- 2.7.4