https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/174857
>From 5bb93c09faa05f24ecf4a86f78ca07dc0ad155c7 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Tue, 6 Jan 2026 09:22:14 +0100 Subject: [PATCH] ValueTracking: Rule out nan for fdiv self special case Addresses TODO for signaling nan handling. --- llvm/lib/Analysis/ValueTracking.cpp | 22 +++++++++++++++++-- .../Transforms/Attributor/nofpclass-fdiv.ll | 18 +++++++-------- .../Transforms/Attributor/nofpclass-frem.ll | 18 +++++++-------- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 4776020df0bc5..964adfcb761dd 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5642,9 +5642,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, } case Instruction::FDiv: case Instruction::FRem: { + const bool WantNan = (InterestedClasses & fcNan) != fcNone; + if (Op->getOperand(0) == Op->getOperand(1) && isGuaranteedNotToBeUndef(Op->getOperand(0), Q.AC, Q.CxtI, Q.DT)) { - // TODO: Could filter out snan if we inspect the operand if (Op->getOpcode() == Instruction::FDiv) { // X / X is always exactly 1.0 or a NaN. Known.KnownFPClasses = fcNan | fcPosNormal; @@ -5653,10 +5654,27 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, Known.KnownFPClasses = fcNan | fcZero; } + if (!WantNan) + break; + + KnownFPClass KnownSrc; + computeKnownFPClass(Op->getOperand(0), DemandedElts, + fcNan | fcInf | fcZero | fcSubnormal, KnownSrc, Q, + Depth + 1); + const Function *F = cast<Instruction>(Op)->getFunction(); + const fltSemantics &FltSem = + Op->getType()->getScalarType()->getFltSemantics(); + + if (KnownSrc.isKnownNever(fcNan) && KnownSrc.isKnownNeverInfinity() && + KnownSrc.isKnownNeverLogicalZero(F ? F->getDenormalMode(FltSem) + : DenormalMode::getDynamic())) + Known.knownNot(fcNan); + else if (KnownSrc.isKnownNever(fcSNan)) + Known.knownNot(fcSNan); + break; } - const bool WantNan = (InterestedClasses & fcNan) != fcNone; const bool WantNegative = (InterestedClasses & fcNegative) != fcNone; const bool WantPositive = Opc == Instruction::FRem && (InterestedClasses & fcPositive) != fcNone; diff --git a/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll b/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll index 8efed69d9d7c4..fbf302b48cd3a 100644 --- a/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll +++ b/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll @@ -376,7 +376,7 @@ define float @ret_fdiv_same_operands_maybe_undef(float %arg) #0 { } define float @ret_fdiv_same_operands_nosnan(float noundef nofpclass(snan) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nosnan +; CHECK-LABEL: define noundef nofpclass(snan inf zero sub nnorm) float @ret_fdiv_same_operands_nosnan ; CHECK-SAME: (float noundef nofpclass(snan) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FDIV]] @@ -396,7 +396,7 @@ define float @ret_fdiv_same_operands_noqnan(float noundef nofpclass(qnan) %arg) } define float @ret_fdiv_same_operands_nonan(float noundef nofpclass(nan) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan +; CHECK-LABEL: define noundef nofpclass(snan inf zero sub nnorm) float @ret_fdiv_same_operands_nonan ; CHECK-SAME: (float noundef nofpclass(nan) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FDIV]] @@ -406,7 +406,7 @@ define float @ret_fdiv_same_operands_nonan(float noundef nofpclass(nan) %arg) #0 } define float @ret_fdiv_same_operands_nonan_noinf(float noundef nofpclass(nan inf) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf +; CHECK-LABEL: define noundef nofpclass(snan inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf ; CHECK-SAME: (float noundef nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FDIV]] @@ -416,7 +416,7 @@ define float @ret_fdiv_same_operands_nonan_noinf(float noundef nofpclass(nan inf } define float @ret_fdiv_same_operands_nonan_nozero(float noundef nofpclass(nan zero) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_nozero +; CHECK-LABEL: define noundef nofpclass(snan inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_nozero ; CHECK-SAME: (float noundef nofpclass(nan zero) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FDIV]] @@ -426,7 +426,7 @@ define float @ret_fdiv_same_operands_nonan_nozero(float noundef nofpclass(nan ze } define float @ret_fdiv_same_operands_nonan_noinf_nozero(float noundef nofpclass(nan inf zero) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero +; CHECK-LABEL: define noundef nofpclass(nan inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero ; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FDIV]] @@ -436,7 +436,7 @@ define float @ret_fdiv_same_operands_nonan_noinf_nozero(float noundef nofpclass( } define float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub(float noundef nofpclass(nan inf zero) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub +; CHECK-LABEL: define noundef nofpclass(nan inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub ; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FDIV]] @@ -447,7 +447,7 @@ define float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub(float noundef nofp ; May be nan if denormal is flushed define float @ret_fdiv_same_operands_nonan_noinf_nozero__daz(float noundef nofpclass(nan inf zero) %arg) #1 { -; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero__daz +; CHECK-LABEL: define noundef nofpclass(snan inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero__daz ; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FDIV]] @@ -458,7 +458,7 @@ define float @ret_fdiv_same_operands_nonan_noinf_nozero__daz(float noundef nofpc ; Can't have a flushed input define float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub__daz(float noundef nofpclass(nan inf sub zero) %arg) #1 { -; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub__daz +; CHECK-LABEL: define noundef nofpclass(nan inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub__daz ; CHECK-SAME: (float noundef nofpclass(nan inf zero sub) [[ARG:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FDIV]] @@ -469,7 +469,7 @@ define float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub__daz(float noundef ; Can't have a flushed input define float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub__dynamic(float noundef nofpclass(nan inf sub zero) %arg) #3 { -; CHECK-LABEL: define noundef nofpclass(inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub__dynamic +; CHECK-LABEL: define noundef nofpclass(nan inf zero sub nnorm) float @ret_fdiv_same_operands_nonan_noinf_nozero_nosub__dynamic ; CHECK-SAME: (float noundef nofpclass(nan inf zero sub) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FDIV]] diff --git a/llvm/test/Transforms/Attributor/nofpclass-frem.ll b/llvm/test/Transforms/Attributor/nofpclass-frem.ll index 36c3ae108c1f8..2c442c10289f5 100644 --- a/llvm/test/Transforms/Attributor/nofpclass-frem.ll +++ b/llvm/test/Transforms/Attributor/nofpclass-frem.ll @@ -376,7 +376,7 @@ define float @ret_frem_same_operands_maybe_undef(float %arg) #0 { } define float @ret_frem_same_operands_nosnan(float noundef nofpclass(snan) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nosnan +; CHECK-LABEL: define noundef nofpclass(snan inf sub norm) float @ret_frem_same_operands_nosnan ; CHECK-SAME: (float noundef nofpclass(snan) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FREM]] @@ -396,7 +396,7 @@ define float @ret_frem_same_operands_noqnan(float noundef nofpclass(qnan) %arg) } define float @ret_frem_same_operands_nonan(float noundef nofpclass(nan) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan +; CHECK-LABEL: define noundef nofpclass(snan inf sub norm) float @ret_frem_same_operands_nonan ; CHECK-SAME: (float noundef nofpclass(nan) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FREM]] @@ -406,7 +406,7 @@ define float @ret_frem_same_operands_nonan(float noundef nofpclass(nan) %arg) #0 } define float @ret_frem_same_operands_nonan_noinf(float noundef nofpclass(nan inf) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf +; CHECK-LABEL: define noundef nofpclass(snan inf sub norm) float @ret_frem_same_operands_nonan_noinf ; CHECK-SAME: (float noundef nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FREM]] @@ -416,7 +416,7 @@ define float @ret_frem_same_operands_nonan_noinf(float noundef nofpclass(nan inf } define float @ret_frem_same_operands_nonan_nozero(float noundef nofpclass(nan zero) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_nozero +; CHECK-LABEL: define noundef nofpclass(snan inf sub norm) float @ret_frem_same_operands_nonan_nozero ; CHECK-SAME: (float noundef nofpclass(nan zero) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FREM]] @@ -426,7 +426,7 @@ define float @ret_frem_same_operands_nonan_nozero(float noundef nofpclass(nan ze } define float @ret_frem_same_operands_nonan_noinf_nozero(float noundef nofpclass(nan inf zero) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero +; CHECK-LABEL: define noundef nofpclass(nan inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero ; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FREM]] @@ -436,7 +436,7 @@ define float @ret_frem_same_operands_nonan_noinf_nozero(float noundef nofpclass( } define float @ret_frem_same_operands_nonan_noinf_nozero_nosub(float noundef nofpclass(nan inf zero) %arg) #0 { -; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero_nosub +; CHECK-LABEL: define noundef nofpclass(nan inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero_nosub ; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FREM]] @@ -447,7 +447,7 @@ define float @ret_frem_same_operands_nonan_noinf_nozero_nosub(float noundef nofp ; May be nan if denormal is flushed define float @ret_frem_same_operands_nonan_noinf_nozero__daz(float noundef nofpclass(nan inf zero) %arg) #1 { -; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero__daz +; CHECK-LABEL: define noundef nofpclass(snan inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero__daz ; CHECK-SAME: (float noundef nofpclass(nan inf zero) [[ARG:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FREM]] @@ -458,7 +458,7 @@ define float @ret_frem_same_operands_nonan_noinf_nozero__daz(float noundef nofpc ; Can't have a flushed input define float @ret_frem_same_operands_nonan_noinf_nozero_nosub__daz(float noundef nofpclass(nan inf sub zero) %arg) #1 { -; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero_nosub__daz +; CHECK-LABEL: define noundef nofpclass(nan inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero_nosub__daz ; CHECK-SAME: (float noundef nofpclass(nan inf zero sub) [[ARG:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FREM]] @@ -469,7 +469,7 @@ define float @ret_frem_same_operands_nonan_noinf_nozero_nosub__daz(float noundef ; Can't have a flushed input define float @ret_frem_same_operands_nonan_noinf_nozero_nosub__dynamic(float noundef nofpclass(nan inf sub zero) %arg) #3 { -; CHECK-LABEL: define noundef nofpclass(inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero_nosub__dynamic +; CHECK-LABEL: define noundef nofpclass(nan inf sub norm) float @ret_frem_same_operands_nonan_noinf_nozero_nosub__dynamic ; CHECK-SAME: (float noundef nofpclass(nan inf zero sub) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[FREM]] _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
