Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -4339,18 +4339,21 @@ return; } + const Operator *Op = dyn_cast(V); FPClassTest KnownNotFromFlags = fcNone; - if (const auto *CB = dyn_cast(V)) - KnownNotFromFlags |= CB->getRetNoFPClass(); - else if (const auto *Arg = dyn_cast(V)) - KnownNotFromFlags |= Arg->getNoFPClass(); - const Operator *Op = dyn_cast(V); - if (const FPMathOperator *FPOp = dyn_cast_or_null(Op)) { - if (FPOp->hasNoNaNs()) - KnownNotFromFlags |= fcNan; - if (FPOp->hasNoInfs()) - KnownNotFromFlags |= fcInf; + if (Q.IIQ.UseInstrInfo) { + if (const auto *CB = dyn_cast(V)) + KnownNotFromFlags |= CB->getRetNoFPClass(); + else if (const auto *Arg = dyn_cast(V)) + KnownNotFromFlags |= Arg->getNoFPClass(); + + if (const FPMathOperator *FPOp = dyn_cast_or_null(Op)) { + if (FPOp->hasNoNaNs()) + KnownNotFromFlags |= fcNan; + if (FPOp->hasNoInfs()) + KnownNotFromFlags |= fcInf; + } } if (Q.AC) { Index: llvm/unittests/Analysis/ValueTrackingTest.cpp =================================================================== --- llvm/unittests/Analysis/ValueTrackingTest.cpp +++ llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -1943,7 +1943,7 @@ KnownFPClass NoUseInstrInfoNoNan = computeKnownFPClass(A3, M->getDataLayout(), fcAllFlags, 0, nullptr, nullptr, nullptr, nullptr, /*UseInstrInfo=*/false); - EXPECT_EQ(fcPositive | fcNegZero | fcQNan, + EXPECT_EQ(fcPositive | fcNegZero | fcNan, NoUseInstrInfoNoNan.KnownFPClasses); EXPECT_EQ(std::nullopt, NoUseInstrInfoNoNan.SignBit); } @@ -1958,12 +1958,73 @@ KnownFPClass NoUseInstrInfoNSZNoNan = computeKnownFPClass(A4, M->getDataLayout(), fcAllFlags, 0, nullptr, nullptr, nullptr, nullptr, /*UseInstrInfo=*/false); - EXPECT_EQ(fcPositive | fcNegZero | fcQNan, + EXPECT_EQ(fcPositive | fcNegZero | fcNan, NoUseInstrInfoNSZNoNan.KnownFPClasses); EXPECT_EQ(std::nullopt, NoUseInstrInfoNSZNoNan.SignBit); } } +/// Test that the UseInstrInfo parameter is respected. +TEST_F(ComputeKnownFPClassTest, RespectIgnoreFlags) { + parseAssembly( + "declare float @func()\n" + "define float @test(i1 %cond, float %arg0, float %arg1) {\n" + " %A = fadd nnan float %arg0, %arg1\n" + " %A2 = fmul ninf float %arg0, %arg1\n" + " %A3 = call nofpclass(inf nan) float @func()\n" + " ret float %A\n" + "}\n"); + + { + KnownFPClass UseInstrInfoNoNaN = + computeKnownFPClass(A, M->getDataLayout(), fcAllFlags, 0, nullptr, + nullptr, nullptr, nullptr, /*UseInstrInfo=*/true); + EXPECT_EQ(~fcNan, UseInstrInfoNoNaN.KnownFPClasses); + EXPECT_EQ(std::nullopt, UseInstrInfoNoNaN.SignBit); + } + + { + KnownFPClass UseInstrInfoNoInf = + computeKnownFPClass(A2, M->getDataLayout(), fcAllFlags, 0, nullptr, + nullptr, nullptr, nullptr, /*UseInstrInfo=*/true); + EXPECT_EQ(~fcInf, UseInstrInfoNoInf.KnownFPClasses); + EXPECT_EQ(std::nullopt, UseInstrInfoNoInf.SignBit); + } + + { + KnownFPClass NoUseInstrInfoNoNaN = + computeKnownFPClass(A, M->getDataLayout(), fcAllFlags, 0, nullptr, + nullptr, nullptr, nullptr, /*UseInstrInfo=*/false); + EXPECT_EQ(fcAllFlags, NoUseInstrInfoNoNaN.KnownFPClasses); + EXPECT_EQ(std::nullopt, NoUseInstrInfoNoNaN.SignBit); + } + + { + KnownFPClass NoUseInstrInfoNoInf = + computeKnownFPClass(A2, M->getDataLayout(), fcAllFlags, 0, nullptr, + nullptr, nullptr, nullptr, /*UseInstrInfo=*/false); + EXPECT_EQ(fcAllFlags, NoUseInstrInfoNoInf.KnownFPClasses); + EXPECT_EQ(std::nullopt, NoUseInstrInfoNoInf.SignBit); + } + + { + KnownFPClass UseInstrUsesOther = + computeKnownFPClass(A3, M->getDataLayout(), fcAllFlags, 0, nullptr, + nullptr, nullptr, nullptr, /*UseInstrInfo=*/true); + EXPECT_EQ(~(fcNan | fcInf), UseInstrUsesOther.KnownFPClasses); + EXPECT_EQ(std::nullopt, UseInstrUsesOther.SignBit); + } + + // No looking at nofpclass attribute + { + KnownFPClass NoUseInstrUsesOther = + computeKnownFPClass(A3, M->getDataLayout(), fcAllFlags, 0, nullptr, + nullptr, nullptr, nullptr, /*UseInstrInfo=*/false); + EXPECT_EQ(fcAllFlags, NoUseInstrUsesOther.KnownFPClasses); + EXPECT_EQ(std::nullopt, NoUseInstrUsesOther.SignBit); + } +} + TEST_F(ValueTrackingTest, isNonZeroRecurrence) { parseAssembly(R"( define i1 @test(i8 %n, i8 %r) {