[llvm] [SelectionDAG] Use `KnownBits` to determine if an operand may be NaN. (PR #188606)

via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 26 07:45:58 PDT 2026


https://github.com/zGoldthorpe updated https://github.com/llvm/llvm-project/pull/188606

>From f0fb561bb4e75fa1b5733359923f28d6fad08483 Mon Sep 17 00:00:00 2001
From: Zach Goldthorpe <Zach.Goldthorpe at amd.com>
Date: Wed, 25 Mar 2026 15:37:09 -0500
Subject: [PATCH 1/4] [SelectionDAG] Use `KnownBits` to determine if an operand
 may be NaN.

---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 23 +++++++++++++++++++
 .../CodeGen/AMDGPU/fneg-modifier-casting.ll   |  4 ++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 028c9955a6bb1..eaf24fa8bdf06 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6193,6 +6193,29 @@ bool SelectionDAG::isKnownNeverNaN(SDValue Op, const APInt &DemandedElts,
                                                Depth);
     }
 
+    // Try to infer NaN from known bits, but only for detecting signaling or
+    // nonsignaling NaNs
+    if (!SNaN) {
+      EVT VT = Op.getValueType().getScalarType();
+      const unsigned Mantissa = VT == MVT::f16    ? 10
+                                : VT == MVT::f32  ? 23
+                                : VT == MVT::f64  ? 52
+                                : VT == MVT::f128 ? 112
+                                                  : 0;
+      const unsigned Exponent = VT == MVT::f16    ? 5
+                                : VT == MVT::f32  ? 8
+                                : VT == MVT::f64  ? 11
+                                : VT == MVT::f128 ? 15
+                                                  : 0;
+
+      if (Mantissa) {
+        KnownBits Known = computeKnownBits(Op, DemandedElts);
+        KnownBits KnownMan = Known.extractBits(Mantissa, 0);
+        KnownBits KnownExp = Known.extractBits(Exponent, Mantissa);
+        if (!KnownExp.getMaxValue().isAllOnes() || KnownMan.isZero())
+          return true;
+      }
+    }
     return false;
   }
 }
diff --git a/llvm/test/CodeGen/AMDGPU/fneg-modifier-casting.ll b/llvm/test/CodeGen/AMDGPU/fneg-modifier-casting.ll
index 9b44acd5c0716..64431cb31ea6e 100644
--- a/llvm/test/CodeGen/AMDGPU/fneg-modifier-casting.ll
+++ b/llvm/test/CodeGen/AMDGPU/fneg-modifier-casting.ll
@@ -1680,7 +1680,7 @@ define amdgpu_kernel void @fnge_select_f32_multi_use_regression(float %.i2369) {
 ; GCN-NEXT:    s_waitcnt lgkmcnt(0)
 ; GCN-NEXT:    v_cmp_nlt_f32_e64 s[0:1], s0, 0
 ; GCN-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[0:1]
-; GCN-NEXT:    v_cmp_nge_f32_e32 vcc, 0, v0
+; GCN-NEXT:    v_cmp_lt_f32_e32 vcc, 0, v0
 ; GCN-NEXT:    v_cndmask_b32_e32 v1, 0, v0, vcc
 ; GCN-NEXT:    v_mul_f32_e64 v0, -v0, v1
 ; GCN-NEXT:    v_cmp_le_f32_e32 vcc, 0, v0
@@ -1694,7 +1694,7 @@ define amdgpu_kernel void @fnge_select_f32_multi_use_regression(float %.i2369) {
 ; GFX11-NEXT:    v_cmp_nlt_f32_e64 s0, s0, 0
 ; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
 ; GFX11-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s0
-; GFX11-NEXT:    v_cmp_nge_f32_e32 vcc_lo, 0, v0
+; GFX11-NEXT:    v_cmp_lt_f32_e32 vcc_lo, 0, v0
 ; GFX11-NEXT:    v_cndmask_b32_e32 v1, 0, v0, vcc_lo
 ; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
 ; GFX11-NEXT:    v_mul_f32_e64 v0, -v0, v1

>From fcfd5a757ab1f3e64c4a68d92e99642b3c242107 Mon Sep 17 00:00:00 2001
From: Zach Goldthorpe <Zach.Goldthorpe at amd.com>
Date: Wed, 25 Mar 2026 16:43:52 -0500
Subject: [PATCH 2/4] Use `fltSemantics`

---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 40 +++++++++++--------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index eaf24fa8bdf06..bb76e08894e20 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6196,24 +6196,32 @@ bool SelectionDAG::isKnownNeverNaN(SDValue Op, const APInt &DemandedElts,
     // Try to infer NaN from known bits, but only for detecting signaling or
     // nonsignaling NaNs
     if (!SNaN) {
-      EVT VT = Op.getValueType().getScalarType();
-      const unsigned Mantissa = VT == MVT::f16    ? 10
-                                : VT == MVT::f32  ? 23
-                                : VT == MVT::f64  ? 52
-                                : VT == MVT::f128 ? 112
-                                                  : 0;
-      const unsigned Exponent = VT == MVT::f16    ? 5
-                                : VT == MVT::f32  ? 8
-                                : VT == MVT::f64  ? 11
-                                : VT == MVT::f128 ? 15
-                                                  : 0;
-
-      if (Mantissa) {
-        KnownBits Known = computeKnownBits(Op, DemandedElts);
-        KnownBits KnownMan = Known.extractBits(Mantissa, 0);
-        KnownBits KnownExp = Known.extractBits(Exponent, Mantissa);
+      const fltSemantics &FltSem = Op.getValueType().getFltSemantics();
+      const KnownBits Known = computeKnownBits(Op, DemandedElts);
+      const unsigned Mantissa = FltSem.precision - 1;
+      const unsigned Exponent = FltSem.sizeInBits - FltSem.precision;
+      const KnownBits KnownMan = Known.extractBits(Mantissa, 0);
+      const KnownBits KnownExp = Known.extractBits(Exponent, Mantissa);
+
+      switch (FltSem.nanEncoding) {
+      default:
+        break;
+      case fltNanEncoding::IEEE: {
         if (!KnownExp.getMaxValue().isAllOnes() || KnownMan.isZero())
           return true;
+        break;
+      }
+      case fltNanEncoding::AllOnes: {
+        if (!KnownExp.getMaxValue().isAllOnes() ||
+            !KnownMan.getMaxValue().isAllOnes())
+          return true;
+        break;
+      }
+      case fltNanEncoding::NegativeZero:
+        if (Known.Zero.isSignBitSet() || !KnownExp.isZero() ||
+            !KnownMan.isZero())
+          return true;
+        break;
       }
     }
     return false;

>From e427b07c5e1422108478cbf57dc84a61715861ad Mon Sep 17 00:00:00 2001
From: Zach Goldthorpe <Zach.Goldthorpe at amd.com>
Date: Wed, 25 Mar 2026 17:34:12 -0500
Subject: [PATCH 3/4] Remove unnecessary `default` block.

---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index bb76e08894e20..872efa20c3587 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6204,8 +6204,6 @@ bool SelectionDAG::isKnownNeverNaN(SDValue Op, const APInt &DemandedElts,
       const KnownBits KnownExp = Known.extractBits(Exponent, Mantissa);
 
       switch (FltSem.nanEncoding) {
-      default:
-        break;
       case fltNanEncoding::IEEE: {
         if (!KnownExp.getMaxValue().isAllOnes() || KnownMan.isZero())
           return true;

>From f45aaee4ecf5b8323d1370290f32fce601b24980 Mon Sep 17 00:00:00 2001
From: Zach Goldthorpe <Zach.Goldthorpe at amd.com>
Date: Thu, 26 Mar 2026 09:45:23 -0500
Subject: [PATCH 4/4] Added guards and removed consts.

---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 53 ++++++++++---------
 1 file changed, 28 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 872efa20c3587..53cee1970f739 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6195,31 +6195,34 @@ bool SelectionDAG::isKnownNeverNaN(SDValue Op, const APInt &DemandedElts,
 
     // Try to infer NaN from known bits, but only for detecting signaling or
     // nonsignaling NaNs
-    if (!SNaN) {
-      const fltSemantics &FltSem = Op.getValueType().getFltSemantics();
-      const KnownBits Known = computeKnownBits(Op, DemandedElts);
-      const unsigned Mantissa = FltSem.precision - 1;
-      const unsigned Exponent = FltSem.sizeInBits - FltSem.precision;
-      const KnownBits KnownMan = Known.extractBits(Mantissa, 0);
-      const KnownBits KnownExp = Known.extractBits(Exponent, Mantissa);
-
-      switch (FltSem.nanEncoding) {
-      case fltNanEncoding::IEEE: {
-        if (!KnownExp.getMaxValue().isAllOnes() || KnownMan.isZero())
-          return true;
-        break;
-      }
-      case fltNanEncoding::AllOnes: {
-        if (!KnownExp.getMaxValue().isAllOnes() ||
-            !KnownMan.getMaxValue().isAllOnes())
-          return true;
-        break;
-      }
-      case fltNanEncoding::NegativeZero:
-        if (Known.Zero.isSignBitSet() || !KnownExp.isZero() ||
-            !KnownMan.isZero())
-          return true;
-        break;
+    EVT VT = Op.getValueType();
+    if (!SNaN && VT.isFloatingPoint()) {
+      const fltSemantics &FltSem = VT.getFltSemantics();
+      if (FltSem.precision > 0) {
+        KnownBits Known = computeKnownBits(Op, DemandedElts);
+        unsigned Mantissa = FltSem.precision - 1;
+        unsigned Exponent = FltSem.sizeInBits - FltSem.precision;
+        KnownBits KnownMan = Known.extractBits(Mantissa, 0);
+        KnownBits KnownExp = Known.extractBits(Exponent, Mantissa);
+
+        switch (FltSem.nanEncoding) {
+        case fltNanEncoding::IEEE: {
+          if (!KnownExp.getMaxValue().isAllOnes() || KnownMan.isZero())
+            return true;
+          break;
+        }
+        case fltNanEncoding::AllOnes: {
+          if (!KnownExp.getMaxValue().isAllOnes() ||
+              !KnownMan.getMaxValue().isAllOnes())
+            return true;
+          break;
+        }
+        case fltNanEncoding::NegativeZero:
+          if (Known.Zero.isSignBitSet() || !KnownExp.isZero() ||
+              !KnownMan.isZero())
+            return true;
+          break;
+        }
       }
     }
     return false;



More information about the llvm-commits mailing list