[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