[llvm-branch-commits] [llvm] ValueTracking: Rule out nan for fdiv self special case (PR #174857)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jan 8 09:13:55 PST 2026
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 <Matthew.Arsenault at amd.com>
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]]
More information about the llvm-branch-commits
mailing list