[llvm] [KnownFPClass] Fix propagateNonNaN PreserveSign behavior (PR #218578)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 24 21:38:05 PDT 2026
https://github.com/ZERICO2005 updated https://github.com/llvm/llvm-project/pull/218578
>From b9c3fd2f6f97f98f26289c1a7d3b027e91e445f7 Mon Sep 17 00:00:00 2001
From: zerico <zerico2005 at gmail.com>
Date: Mon, 24 Aug 2026 22:37:33 -0600
Subject: [PATCH] [KnownFPClass] Fix propagateNonNaN PreserveSign behavior
---
llvm/include/llvm/Support/KnownFPClass.h | 7 +--
llvm/lib/Support/KnownFPClass.cpp | 48 +++++++++++++++----
.../Attributor/nofpclass-fptrunc.ll | 2 +-
.../CodeGen/GlobalISel/KnownFPClassTest.cpp | 4 +-
4 files changed, 44 insertions(+), 17 deletions(-)
diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h
index 60b5ae3d7e5be..516dcd191de12 100644
--- a/llvm/include/llvm/Support/KnownFPClass.h
+++ b/llvm/include/llvm/Support/KnownFPClass.h
@@ -398,13 +398,10 @@ struct KnownFPClass {
// Propagate knowledge that a non-NaN source implies the result can also not
// be a NaN. For unconstrained operations, signaling nans are not guaranteed
// to be quieted but cannot be introduced.
- void propagateNonNaN(const KnownFPClass &Src, bool PreserveSign = false) {
+ void propagateNonNaN(const KnownFPClass &Src) {
propagateNonSNaN(Src);
- if (Src.isKnownNever(fcNan)) {
+ if (Src.isKnownNever(fcNan))
knownNot(fcNan);
- if (PreserveSign)
- SignBit = Src.SignBit;
- }
}
void propagateNonNaN(const KnownFPClass &LHS, const KnownFPClass &RHS) {
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 37a6160b316ff..bc426dad74aed 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -92,6 +92,20 @@ void KnownFPClass::propagateDenormal(const KnownFPClass &Src,
}
}
+void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src,
+ DenormalMode Mode) {
+ propagateDenormal(Src, Mode);
+ propagateNonNaN(Src);
+
+ // Copy the sign of the source.
+ if (Src.isKnownNeverNaN() && Src.SignBit) {
+ if (*Src.SignBit)
+ signBitMustBeOne();
+ else
+ signBitMustBeZero();
+ }
+}
+
KnownFPClass KnownFPClass::minMaxLike(const KnownFPClass &LHS_,
const KnownFPClass &RHS_, MinMaxKind Kind,
DenormalMode Mode) {
@@ -568,12 +582,6 @@ KnownFPClass KnownFPClass::exp(const KnownFPClass &KnownSrc) {
return Known;
}
-void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src,
- DenormalMode Mode) {
- propagateDenormal(Src, Mode);
- propagateNonNaN(Src, /*PreserveSign=*/true);
-}
-
KnownFPClass KnownFPClass::log(const KnownFPClass &KnownSrc,
DenormalMode Mode) {
KnownFPClass Known;
@@ -771,7 +779,13 @@ KnownFPClass KnownFPClass::fptrunc(const KnownFPClass &KnownSrc) {
if (KnownSrc.cannotBeOrderedLessThanZero())
Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
- Known.propagateNonNaN(KnownSrc, true);
+ Known.propagateNonNaN(KnownSrc);
+ if (KnownSrc.isKnownNeverNaN() && KnownSrc.SignBit) {
+ if (*KnownSrc.SignBit)
+ Known.signBitMustBeOne();
+ else
+ Known.signBitMustBeZero();
+ }
// Infinity needs a range check.
return Known;
@@ -785,7 +799,15 @@ KnownFPClass KnownFPClass::roundToIntegral(const KnownFPClass &KnownSrc,
// Integer results cannot be subnormal.
Known.knownNot(fcSubnormal);
- Known.propagateNonNaN(KnownSrc, true);
+ Known.propagateNonNaN(KnownSrc);
+
+ // Copy the sign of the source.
+ if (KnownSrc.isKnownNeverNaN() && KnownSrc.SignBit) {
+ if (*KnownSrc.SignBit)
+ Known.signBitMustBeOne();
+ else
+ Known.signBitMustBeZero();
+ }
// Pass through infinities, except PPC_FP128 is a special case for
// intrinsics other than trunc.
@@ -837,7 +859,15 @@ KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc,
const APInt &ConstantRangeExpMax,
const fltSemantics &Flt, DenormalMode Mode) {
KnownFPClass Known;
- Known.propagateNonNaN(KnownSrc, /*PreserveSign=*/true);
+ Known.propagateNonNaN(KnownSrc);
+
+ // Copy the sign of the source.
+ if (KnownSrc.isKnownNeverNaN() && KnownSrc.SignBit) {
+ if (*KnownSrc.SignBit)
+ Known.signBitMustBeOne();
+ else
+ Known.signBitMustBeZero();
+ }
// Sign is preserved, but underflows may produce zeroes.
if (KnownSrc.isKnownNever(fcNegative))
diff --git a/llvm/test/Transforms/Attributor/nofpclass-fptrunc.ll b/llvm/test/Transforms/Attributor/nofpclass-fptrunc.ll
index ea2a4f45dc923..b0aad4c711f2d 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-fptrunc.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-fptrunc.ll
@@ -164,7 +164,7 @@ define float @ret_fptrunc_posonly_zero_nan(double nofpclass(ninf nnorm nsub nan)
}
define float @ret_fptrunc_posonly_nan(double nofpclass(ninf nnorm nsub nzero nan) %arg0) {
-; CHECK-LABEL: define nofpclass(nan ninf nsub nnorm) float @ret_fptrunc_posonly_nan
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_fptrunc_posonly_nan
; CHECK-SAME: (double nofpclass(nan ninf nzero nsub nnorm) [[ARG0:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[EXT:%.*]] = fptrunc double [[ARG0]] to float
; CHECK-NEXT: ret float [[EXT]]
diff --git a/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp
index d995c1e15f9e5..332b9a354af03 100644
--- a/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp
@@ -164,7 +164,7 @@ TEST_F(AArch64GISelMITest, TestFPClassCstZeroFPTrunc) {
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
- EXPECT_EQ(fcPosFinite | fcNegZero, Known.KnownFPClasses);
+ EXPECT_EQ(fcPosFinite, Known.KnownFPClasses);
EXPECT_EQ(false, Known.SignBit);
}
@@ -190,7 +190,7 @@ TEST_F(AArch64GISelMITest, TestFPClassCstVecZeroFPTrunc) {
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
- EXPECT_EQ(fcPosFinite | fcNegZero, Known.KnownFPClasses);
+ EXPECT_EQ(fcPosFinite, Known.KnownFPClasses);
EXPECT_EQ(false, Known.SignBit);
}
More information about the llvm-commits
mailing list