diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 923ff043fe710..dc3c90ba9db16 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4181,8 +4181,14 @@ llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS, } case FCmpInst::FCMP_OGE: case FCmpInst::FCMP_ULT: { - if (ConstRHS->isNegative()) // TODO - return {nullptr, fcAllFlags}; + if (ConstRHS->isNegative()) { + // fcmp oge x, -inf -> ~fcNan + // fcmp oge fabs(x), -inf -> ~fcNan + // fcmp ult x, -inf -> fcNan + // fcmp ult fabs(x), -inf -> fcNan + Mask = ~fcNan; + break; + } // fcmp oge fabs(x), +inf -> fcInf // fcmp oge x, +inf -> fcPosInf @@ -4195,8 +4201,14 @@ llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS, } case FCmpInst::FCMP_OGT: case FCmpInst::FCMP_ULE: { - if (ConstRHS->isNegative()) - return {nullptr, fcAllFlags}; + if (ConstRHS->isNegative()) { + // fcmp ogt x, -inf -> fcmp one x, -inf + // fcmp ogt fabs(x), -inf -> fcmp ord x, x + // fcmp ule x, -inf -> fcmp ueq x, -inf + // fcmp ule fabs(x), -inf -> fcmp uno x, x + Mask = IsFabs ? ~fcNan : ~(fcNegInf | fcNan); + break; + } // No value is ordered and greater than infinity. Mask = fcNone; diff --git a/llvm/test/Transforms/InstSimplify/assume-fcmp-constant-implies-class.ll b/llvm/test/Transforms/InstSimplify/assume-fcmp-constant-implies-class.ll index ec4e3c3092414..7970f3ce6bf09 100644 --- a/llvm/test/Transforms/InstSimplify/assume-fcmp-constant-implies-class.ll +++ b/llvm/test/Transforms/InstSimplify/assume-fcmp-constant-implies-class.ll @@ -3047,8 +3047,7 @@ define i1 @assume_ogt_neginf_one_neginf(float %arg) { ; CHECK-SAME: float [[ARG:%.*]]) { ; CHECK-NEXT: [[CMP_OGT_NEGINF:%.*]] = fcmp ogt float [[ARG]], 0xFFF0000000000000 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_OGT_NEGINF]]) -; CHECK-NEXT: [[CMP:%.*]] = fcmp one float [[ARG]], 0xFFF0000000000000 -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %cmp.ogt.neginf = fcmp ogt float %arg, 0xFFF0000000000000 call void @llvm.assume(i1 %cmp.ogt.neginf) @@ -3089,8 +3088,7 @@ define i1 @assume_ult_neginf_oeq_neginf(float %arg) { ; CHECK-SAME: float [[ARG:%.*]]) { ; CHECK-NEXT: [[CMP_ULT_NEGINF:%.*]] = fcmp ult float [[ARG]], 0xFFF0000000000000 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ULT_NEGINF]]) -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[ARG]], 0xFFF0000000000000 -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %cmp.ult.neginf = fcmp ult float %arg, 0xFFF0000000000000 call void @llvm.assume(i1 %cmp.ult.neginf) @@ -3136,8 +3134,7 @@ define i1 @assume_fabs_ule_neginf_oeq_neginf(float %arg) { ; CHECK-NEXT: [[FABS_ARG:%.*]] = call float @llvm.fabs.f32(float [[ARG]]) ; CHECK-NEXT: [[CMP_OGT_NEGINF:%.*]] = fcmp ule float [[FABS_ARG]], 0xFFF0000000000000 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_OGT_NEGINF]]) -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[ARG]], 0xFFF0000000000000 -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %fabs.arg = call float @llvm.fabs.f32(float %arg) %cmp.ogt.neginf = fcmp ule float %fabs.arg, 0xFFF0000000000000 diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp index 5bd1bb37e678e..1190550340efb 100644 --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -1830,6 +1830,8 @@ TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_NInf) { " %A2 = fcmp uge double %arg, 0xFFF0000000000000" " %A3 = fcmp ogt double %arg, 0xFFF0000000000000" " %A4 = fcmp ule double %arg, 0xFFF0000000000000" + " %A5 = fcmp oge double %arg, 0xFFF0000000000000" + " %A6 = fcmp ult double %arg, 0xFFF0000000000000" " ret i1 %A\n" "}\n"); @@ -1847,14 +1849,77 @@ TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_NInf) { auto [OgtVal, OgtClass] = fcmpToClassTest(CmpInst::FCMP_OGT, *A3->getFunction(), A3->getOperand(0), A3->getOperand(1)); - EXPECT_EQ(nullptr, OgtVal); - EXPECT_EQ(fcAllFlags, OgtClass); + EXPECT_EQ(A3->getOperand(0), OgtVal); + EXPECT_EQ(~(fcNegInf | fcNan), OgtClass); auto [UleVal, UleClass] = fcmpToClassTest(CmpInst::FCMP_ULE, *A4->getFunction(), A4->getOperand(0), A4->getOperand(1)); - EXPECT_EQ(nullptr, UleVal); - EXPECT_EQ(fcAllFlags, UleClass); + EXPECT_EQ(A4->getOperand(0), UleVal); + EXPECT_EQ(fcNegInf | fcNan, UleClass); + + auto [OgeVal, OgeClass] = + fcmpToClassTest(CmpInst::FCMP_OGE, *A5->getFunction(), A5->getOperand(0), + A5->getOperand(1)); + EXPECT_EQ(A5->getOperand(0), OgeVal); + EXPECT_EQ(~fcNan, OgeClass); + + auto [UltVal, UltClass] = + fcmpToClassTest(CmpInst::FCMP_ULT, *A6->getFunction(), A6->getOperand(0), + A6->getOperand(1)); + EXPECT_EQ(A6->getOperand(0), UltVal); + EXPECT_EQ(fcNan, UltClass); +} + +TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_FabsNInf) { + parseAssembly("declare double @llvm.fabs.f64(double)\n" + "define i1 @test(double %arg) {\n" + " %fabs.arg = call double @llvm.fabs.f64(double %arg)\n" + " %A = fcmp olt double %fabs.arg, 0xFFF0000000000000" + " %A2 = fcmp uge double %fabs.arg, 0xFFF0000000000000" + " %A3 = fcmp ogt double %fabs.arg, 0xFFF0000000000000" + " %A4 = fcmp ule double %fabs.arg, 0xFFF0000000000000" + " %A5 = fcmp oge double %fabs.arg, 0xFFF0000000000000" + " %A6 = fcmp ult double %fabs.arg, 0xFFF0000000000000" + " ret i1 %A\n" + "}\n"); + + Value *ArgVal = F->getArg(0); + + auto [OltVal, OltClass] = fcmpToClassTest( + CmpInst::FCMP_OLT, *A->getFunction(), A->getOperand(0), A->getOperand(1)); + EXPECT_EQ(ArgVal, OltVal); + EXPECT_EQ(fcNone, OltClass); + + auto [UgeVal, UgeClass] = + fcmpToClassTest(CmpInst::FCMP_UGE, *A2->getFunction(), A2->getOperand(0), + A2->getOperand(1)); + EXPECT_EQ(ArgVal, UgeVal); + EXPECT_EQ(fcAllFlags, UgeClass); + + auto [OgtVal, OgtClass] = + fcmpToClassTest(CmpInst::FCMP_OGT, *A3->getFunction(), A3->getOperand(0), + A3->getOperand(1)); + EXPECT_EQ(ArgVal, OgtVal); + EXPECT_EQ(~fcNan, OgtClass); + + auto [UleVal, UleClass] = + fcmpToClassTest(CmpInst::FCMP_ULE, *A4->getFunction(), A4->getOperand(0), + A4->getOperand(1)); + EXPECT_EQ(ArgVal, UleVal); + EXPECT_EQ(fcNan, UleClass); + + auto [OgeVal, OgeClass] = + fcmpToClassTest(CmpInst::FCMP_OGE, *A5->getFunction(), A5->getOperand(0), + A5->getOperand(1)); + EXPECT_EQ(ArgVal, OgeVal); + EXPECT_EQ(~fcNan, OgeClass); + + auto [UltVal, UltClass] = + fcmpToClassTest(CmpInst::FCMP_ULT, *A6->getFunction(), A6->getOperand(0), + A6->getOperand(1)); + EXPECT_EQ(ArgVal, UltVal); + EXPECT_EQ(fcNan, UltClass); } TEST_F(ComputeKnownFPClassTest, FCmpToClassTest_PInf) {