Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -4457,6 +4457,22 @@ break; } + case Instruction::FMul: { + KnownFPClass KnownLHS, KnownRHS; + computeKnownFPClass(Op->getOperand(1), DemandedElts, fcNan | fcInf, + KnownRHS, Depth + 1, Q, TLI); + if (KnownRHS.isKnownNeverNaN() && KnownRHS.isKnownNeverInfinity()) { + computeKnownFPClass(Op->getOperand(0), DemandedElts, fcNan | fcInf, + KnownLHS, Depth + 1, Q, TLI); + + // Zero multiplied with infinity produces NaN. + // FIXME: If neither side can be zero fmul never produces NaN. + if (KnownLHS.isKnownNeverNaN() && KnownLHS.isKnownNeverInfinity()) + Known.knownNot(fcNan); + } + + break; + } case Instruction::SIToFP: case Instruction::UIToFP: { // Cannot produce nan Index: llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll =================================================================== --- llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll +++ llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll @@ -22,7 +22,7 @@ } define float @ret_fmul_nonan_noinf__nonan_noinf(float nofpclass(nan inf) %arg0, float nofpclass(nan inf) %arg1) { -; CHECK-LABEL: define float @ret_fmul_nonan_noinf__nonan_noinf +; CHECK-LABEL: define nofpclass(nan) float @ret_fmul_nonan_noinf__nonan_noinf ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[FMUL]] Index: llvm/unittests/Analysis/ValueTrackingTest.cpp =================================================================== --- llvm/unittests/Analysis/ValueTrackingTest.cpp +++ llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -1575,6 +1575,23 @@ expectKnownFPClass(fcAllFlags, std::nullopt, A5); } +TEST_F(ComputeKnownFPClassTest, FMul) { + parseAssembly( + "define float @test(float nofpclass(nan inf) %nnan.ninf, float nofpclass(nan) %nnan, float nofpclass(qnan) %no.qnan, float %unknown) {\n" + " %A = fmul float %nnan.ninf, %nnan.ninf" + " %A2 = fmul float %nnan.ninf, %nnan" + " %A3 = fmul float %nnan, %nnan.ninf" + " %A4 = fmul float %nnan.ninf, %no.qnan" + " %A5 = fmul float %nnan, %nnan" + " ret float %A\n" + "}\n"); + expectKnownFPClass(fcFinite | fcInf, std::nullopt, A); + expectKnownFPClass(fcAllFlags, std::nullopt, A2); + expectKnownFPClass(fcAllFlags, std::nullopt, A3); + expectKnownFPClass(fcAllFlags, std::nullopt, A4); + expectKnownFPClass(fcAllFlags, std::nullopt, A5); +} + TEST_F(ValueTrackingTest, isNonZeroRecurrence) { parseAssembly(R"( define i1 @test(i8 %n, i8 %r) {