[llvm] [DAG] computeKnownFPClass - add ISD::SINT_TO_FP/UINT_TO_FP handling (PR #190539)

Pau Sum via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 7 18:17:40 PDT 2026


https://github.com/pau-sum updated https://github.com/llvm/llvm-project/pull/190539

>From 0e82bd5d812a9a581aaedc3d5b9667fa6f449966 Mon Sep 17 00:00:00 2001
From: Pau Sum <pau at sumpau.com>
Date: Sun, 5 Apr 2026 08:50:09 -0400
Subject: [PATCH 1/4] [DAG] computeKnownFPClass - add
 ISD::SINT_TO_FP/UINT_TO_FP handling

---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  55 ++++
 llvm/test/CodeGen/RISCV/combine-is_fpclass.ll | 281 ++++++++++++++++++
 2 files changed, 336 insertions(+)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 137922aa62557..aaec1d9eb0f4f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6082,6 +6082,61 @@ KnownFPClass SelectionDAG::computeKnownFPClass(SDValue Op,
     Known = computeKnownFPClass(Op.getOperand(0), InterestedClasses, Depth + 1);
     break;
   }
+  case ISD::SINT_TO_FP:
+  case ISD::UINT_TO_FP: {
+    // Cannot produce nan
+    Known.knownNot(fcNan);
+
+    // Integers cannot be subnormal
+    Known.knownNot(fcSubnormal);
+
+    // sitofp and uitofp turn into +0.0 for zero.
+    Known.knownNot(fcNegZero);
+
+    // UIToFP is always non-negative regardless of known bits.
+    if (Opcode == ISD::UINT_TO_FP)
+      Known.signBitMustBeZero();
+
+    // Only compute known bits if we can learn something useful from them.
+    if (!(InterestedClasses & (fcPosZero | fcNormal | fcInf)))
+      break;
+
+    KnownBits IntKnown =
+        computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
+
+    // If the integer is non-zero, the result cannot be +0.0
+    if (IntKnown.isNonZero())
+      Known.knownNot(fcPosZero);
+
+    if (Opcode == ISD::SINT_TO_FP) {
+      // If the signed integer is known non-negative, the result is
+      // non-negative. If the signed integer is known negative, the result is
+      // negative.
+      if (IntKnown.isNonNegative())
+        Known.signBitMustBeZero();
+      else if (IntKnown.isNegative())
+        Known.signBitMustBeOne();
+    }
+
+    // Guard kept for ilogb()
+    if (InterestedClasses & fcInf) {
+      // Get width of largest magnitude integer known.
+      // This still works for a signed minimum value because the largest FP
+      // value is scaled by some fraction close to 2.0 (1.0 + 0.xxxx).
+      int IntSize = IntKnown.getBitWidth();
+      if (Opcode == ISD::UINT_TO_FP)
+        IntSize -= IntKnown.countMinLeadingZeros();
+      else if (Opcode == ISD::SINT_TO_FP)
+        IntSize -= IntKnown.countMinSignBits();
+
+      // If the exponent of the largest finite FP value can hold the largest
+      // integer, the result of the cast must be finite.
+      if (ilogb(APFloat::getLargest(VT.getScalarType().getFltSemantics())) >=
+          IntSize)
+        Known.knownNot(fcInf);
+    }
+    break;
+  }
   case ISD::BITCAST: {
     // FIXME: It should not be necessary to check for an elementwise bitcast.
     // If a bitcast is not elementwise between vector / scalar types,
diff --git a/llvm/test/CodeGen/RISCV/combine-is_fpclass.ll b/llvm/test/CodeGen/RISCV/combine-is_fpclass.ll
index 5049775710628..beeacc1391653 100644
--- a/llvm/test/CodeGen/RISCV/combine-is_fpclass.ll
+++ b/llvm/test/CodeGen/RISCV/combine-is_fpclass.ll
@@ -22,6 +22,287 @@ define i8 @iszero_constant_v4f32() nounwind {
   ret i8 %r
 }
 
+define i1 @uitofp_isnan(i32 %x) {
+; CHECK-LABEL: uitofp_isnan:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %f = uitofp i32 %x to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 3) ; 3 = nan
+  ret i1 %res
+}
+
+define i1 @uitofp_issubnormal(i32 %x) {
+; CHECK-LABEL: uitofp_issubnormal:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %f = uitofp i32 %x to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 144) ; 144 = subnormal
+  ret i1 %res
+}
+
+define i1 @uitofp_isnegzero(i32 %x) {
+; CHECK-LABEL: uitofp_isnegzero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %f = uitofp i32 %x to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 32) ; 32 = neg_zero
+  ret i1 %res
+}
+
+define i1 @uitofp_isneg(i32 %x) {
+; CHECK-LABEL: uitofp_isneg:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %f = uitofp i32 %x to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 60) ; 60 = negative
+  ret i1 %res
+}
+
+define i1 @uitofp_isposzero(i32 %x) {
+; CHECK-LABEL: uitofp_isposzero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %nz = or i32 %x, 1            ; Ensure nonzero
+  %f = uitofp i32 %nz to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 64) ; 64 = pos_zero
+  ret i1 %res
+}
+
+define i1 @uitofp_isinf(i32 %x) {
+; CHECK-LABEL: uitofp_isinf:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %f = uitofp i32 %x to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 516) ; 516 = inf
+  ret i1 %res
+}
+
+define i1 @sitofp_isnan(i32 %x) {
+; CHECK-LABEL: sitofp_isnan:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %f = sitofp i32 %x to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 3) ; 3 = nan
+  ret i1 %res
+}
+
+define i1 @sitofp_issubnormal(i32 %x) {
+; CHECK-LABEL: sitofp_issubnormal:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %f = sitofp i32 %x to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 144) ; 144 = subnormal
+  ret i1 %res
+}
+
+define i1 @sitofp_isnegzero(i32 %x) {
+; CHECK-LABEL: sitofp_isnegzero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %f = sitofp i32 %x to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 32) ; 32 = neg_zero
+  ret i1 %res
+}
+
+define i1 @sitofp_isposzero(i32 %x) {
+; CHECK-LABEL: sitofp_isposzero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %npz = or i32 %x, -2147483648 ; | 0x80000000: Set sign bit
+  %f = sitofp i32 %npz to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 64) ; 64 = pos_zero
+  ret i1 %res
+}
+
+define i1 @sitofp_isneg(i32 %x) {
+; CHECK-LABEL: sitofp_isneg:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %nn = and i32 %x, 2147483647 ; & 0x7FFFFFFF: Clear sign bit
+  %f = sitofp i32 %nn to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 60) ; 60 = negative
+  ret i1 %res
+}
+
+define i1 @sitofp_isnonneg(i32 %x) {
+; CHECK-LABEL: sitofp_isnonneg:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %n = or i32 %x, -2147483648 ; | 0x80000000: Set sign bit
+  %f = sitofp i32 %n to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 960) ; 960 = positive
+  ret i1 %res
+}
+
+define i1 @sitofp_isinf(i32 %x) {
+; CHECK-LABEL: sitofp_isinf:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %f = sitofp i32 %x to float
+  %res = call i1 @llvm.is.fpclass.f32(float %f, i32 516) ; 516 = inf
+  ret i1 %res
+}
+
+define <4 x i1> @uitofp_v4_isnan(<4 x i32> %x) {
+; CHECK-LABEL: uitofp_v4_isnan:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %f = uitofp <4 x i32> %x to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 3) ; 3 = nan
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @uitofp_v4_issubnormal(<4 x i32> %x) {
+; CHECK-LABEL: uitofp_v4_issubnormal:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %f = uitofp <4 x i32> %x to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 144) ; 144 subnormal
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @uitofp_v4_isnegzero(<4 x i32> %x) {
+; CHECK-LABEL: uitofp_v4_isnegzero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %f = uitofp <4 x i32> %x to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 32); 32 = neg_zero
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @uitofp_v4_isneg(<4 x i32> %x) {
+; CHECK-LABEL: uitofp_v4_isneg:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %f = uitofp <4 x i32> %x to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 60) ; 60 = negative
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @uitofp_v4_isposzero(<4 x i32> %x) {
+; CHECK-LABEL: uitofp_v4_isposzero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %nz = or <4 x i32> %x, <i32 1, i32 1, i32 1, i32 1>
+  %f = uitofp <4 x i32> %nz to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 64) ; 64 = pos_zero
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @uitofp_v4_isinf(<4 x i32> %x) {
+; CHECK-LABEL: uitofp_v4_isinf:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %f = uitofp <4 x i32> %x to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 516) ; 516 = inf
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @sitofp_v4_isnan(<4 x i32> %x) {
+; CHECK-LABEL: sitofp_v4_isnan:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %f = sitofp <4 x i32> %x to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 3) ; 3 = nan
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @sitofp_v4_issubnormal(<4 x i32> %x) {
+; CHECK-LABEL: sitofp_v4_issubnormal:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %f = sitofp <4 x i32> %x to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 144) ; 144 = subnormal
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @sitofp_v4_isnegzero(<4 x i32> %x) {
+; CHECK-LABEL: sitofp_v4_isnegzero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %f = sitofp <4 x i32> %x to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 32) ; 32 = neg_zero
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @sitofp_v4_isposzero(<4 x i32> %x) {
+; CHECK-LABEL: sitofp_v4_isposzero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %npz = or <4 x i32> %x, <i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648> ; | 0x80000000: Set sign bit
+  %f = sitofp <4 x i32> %npz to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 64)  ; 64 = pos_zero
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @sitofp_v4_isneg(<4 x i32> %x) {
+; CHECK-LABEL: sitofp_v4_isneg:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %nn = and <4 x i32> %x, <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647> ; & 0x7FFFFFFF: Clear sign bit
+  %f = sitofp <4 x i32> %nn to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 60) ; 60 = negative
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @sitofp_v4_isnonneg(<4 x i32> %x) {
+; CHECK-LABEL: sitofp_v4_isnonneg:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %n = or <4 x i32> %x, <i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648> ;  | 0x80000000: Set sign bit
+  %f = sitofp <4 x i32> %n to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 960) ; 960 = positive
+  ret <4 x i1> %res
+}
+
+define <4 x i1> @sitofp_v4_isinf(<4 x i32> %x) {
+; CHECK-LABEL: sitofp_v4_isinf:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %f = sitofp <4 x i32> %x to <4 x float>
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %f, i32 516) ; 516 = inf
+  ret <4 x i1> %res
+}
+
 define <vscale x 4 x i1> @splat_constant_is_pos_normal() {
 ; CHECK-LABEL: splat_constant_is_pos_normal:
 ; CHECK:       # %bb.0:

>From 9d9bd5d541de47e06440bfa032ca2dc2f266ce08 Mon Sep 17 00:00:00 2001
From: Pau Sum <pau at sumpau.com>
Date: Tue, 7 Apr 2026 20:57:34 -0400
Subject: [PATCH 2/4] Add itofp logic to Support/KnownFPClass

---
 llvm/include/llvm/Support/KnownFPClass.h |  7 +++
 llvm/lib/Support/KnownFPClass.cpp        | 67 ++++++++++++++++++++++++
 2 files changed, 74 insertions(+)

diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h
index c48e0f8b7b65b..1c05ad416a20c 100644
--- a/llvm/include/llvm/Support/KnownFPClass.h
+++ b/llvm/include/llvm/Support/KnownFPClass.h
@@ -229,6 +229,13 @@ struct KnownFPClass {
   LLVM_ABI static KnownFPClass bitcast(const fltSemantics &FltSemantics,
                                        const KnownBits &Bits);
 
+  LLVM_ABI static KnownFPClass sitofp(const KnownBits &KnownSrc,
+                                      const fltSemantics &FltSem,
+                                      FPClassTest InterestedClasses);
+  LLVM_ABI static KnownFPClass uitofp(const KnownBits &KnownSrc,
+                                      const fltSemantics &FltSem,
+                                      FPClassTest InterestedClasses);
+
   /// Report known values for fadd
   LLVM_ABI static KnownFPClass
   fadd(const KnownFPClass &LHS, const KnownFPClass &RHS,
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 4f704eabfc6ec..849f0081708b2 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -287,6 +287,73 @@ KnownFPClass KnownFPClass::bitcast(const fltSemantics &FltSemantics,
   return Known;
 }
 
+static KnownFPClass itofp_impl(const KnownBits &KnownSrc,
+                               const fltSemantics &FltSem,
+                               FPClassTest InterestedClasses, bool IsSigned) {
+  KnownFPClass Known;
+  // Cannot produce nan
+  Known.knownNot(fcNan);
+
+  // Integers cannot be subnormal
+  Known.knownNot(fcSubnormal);
+
+  // sitofp and uitofp turn into +0.0 for zero.
+  Known.knownNot(fcNegZero);
+
+  // UIToFP is always non-negative regardless of known bits.
+  if (!IsSigned)
+    Known.signBitMustBeZero();
+
+  // Only compute known bits if we can learn something useful from them.
+  if (!(InterestedClasses & (fcPosZero | fcNormal | fcInf)))
+    return Known;
+
+  // If the integer is non-zero, the result cannot be +0.0
+  if (KnownSrc.isNonZero())
+    Known.knownNot(fcPosZero);
+
+  if (IsSigned) {
+    // If the signed integer is known non-negative, the result is
+    // non-negative. If the signed integer is known negative, the result is
+    // negative.
+    if (KnownSrc.isNonNegative())
+      Known.signBitMustBeZero();
+    else if (KnownSrc.isNegative())
+      Known.signBitMustBeOne();
+  }
+
+  // Guard kept for ilogb()
+  if (InterestedClasses & fcInf) {
+    // Get width of largest magnitude integer known.
+    // This still works for a signed minimum value because the largest FP
+    // value is scaled by some fraction close to 2.0 (1.0 + 0.xxxx).
+    int IntSize = KnownSrc.getBitWidth();
+    if (!IsSigned)
+      IntSize -= KnownSrc.countMinLeadingZeros();
+    else
+      IntSize -= KnownSrc.countMinSignBits();
+
+    // If the exponent of the largest finite FP value can hold the largest
+    // integer, the result of the cast must be finite.
+    if (APFloat::semanticsMaxExponent(FltSem) >= IntSize)
+      Known.knownNot(fcInf);
+  }
+
+  return Known;
+}
+
+KnownFPClass KnownFPClass::sitofp(const KnownBits &SrcKnown,
+                                  const fltSemantics &FltSem,
+                                  FPClassTest InterestedClasses) {
+  return itofp_impl(SrcKnown, FltSem, InterestedClasses, /*IsSigned=*/true);
+}
+
+KnownFPClass KnownFPClass::uitofp(const KnownBits &SrcKnown,
+                                  const fltSemantics &FltSem,
+                                  FPClassTest InterestedClasses) {
+  return itofp_impl(SrcKnown, FltSem, InterestedClasses, /*IsSigned=*/false);
+}
+
 // Handle known sign bit and nan cases for fadd.
 static KnownFPClass fadd_impl(const KnownFPClass &KnownLHS,
                               const KnownFPClass &KnownRHS, DenormalMode Mode) {

>From bede3ff20570c8de61249f528f985862675cbbdc Mon Sep 17 00:00:00 2001
From: Pau Sum <pau at sumpau.com>
Date: Tue, 7 Apr 2026 20:59:08 -0400
Subject: [PATCH 3/4] refactor: Use Support/KnownFPClass for itofp cases for
 SelDAG

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

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index aaec1d9eb0f4f..c17aa2e51b764 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6084,57 +6084,12 @@ KnownFPClass SelectionDAG::computeKnownFPClass(SDValue Op,
   }
   case ISD::SINT_TO_FP:
   case ISD::UINT_TO_FP: {
-    // Cannot produce nan
-    Known.knownNot(fcNan);
-
-    // Integers cannot be subnormal
-    Known.knownNot(fcSubnormal);
-
-    // sitofp and uitofp turn into +0.0 for zero.
-    Known.knownNot(fcNegZero);
-
-    // UIToFP is always non-negative regardless of known bits.
-    if (Opcode == ISD::UINT_TO_FP)
-      Known.signBitMustBeZero();
-
-    // Only compute known bits if we can learn something useful from them.
-    if (!(InterestedClasses & (fcPosZero | fcNormal | fcInf)))
-      break;
-
     KnownBits IntKnown =
         computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
-
-    // If the integer is non-zero, the result cannot be +0.0
-    if (IntKnown.isNonZero())
-      Known.knownNot(fcPosZero);
-
-    if (Opcode == ISD::SINT_TO_FP) {
-      // If the signed integer is known non-negative, the result is
-      // non-negative. If the signed integer is known negative, the result is
-      // negative.
-      if (IntKnown.isNonNegative())
-        Known.signBitMustBeZero();
-      else if (IntKnown.isNegative())
-        Known.signBitMustBeOne();
-    }
-
-    // Guard kept for ilogb()
-    if (InterestedClasses & fcInf) {
-      // Get width of largest magnitude integer known.
-      // This still works for a signed minimum value because the largest FP
-      // value is scaled by some fraction close to 2.0 (1.0 + 0.xxxx).
-      int IntSize = IntKnown.getBitWidth();
-      if (Opcode == ISD::UINT_TO_FP)
-        IntSize -= IntKnown.countMinLeadingZeros();
-      else if (Opcode == ISD::SINT_TO_FP)
-        IntSize -= IntKnown.countMinSignBits();
-
-      // If the exponent of the largest finite FP value can hold the largest
-      // integer, the result of the cast must be finite.
-      if (ilogb(APFloat::getLargest(VT.getScalarType().getFltSemantics())) >=
-          IntSize)
-        Known.knownNot(fcInf);
-    }
+    const fltSemantics &FltSem = VT.getScalarType().getFltSemantics();
+    Known = Opcode == ISD::SINT_TO_FP
+                ? KnownFPClass::sitofp(IntKnown, FltSem, InterestedClasses)
+                : KnownFPClass::uitofp(IntKnown, FltSem, InterestedClasses);
     break;
   }
   case ISD::BITCAST: {

>From ca5e49fc108a1ccdc5e008cd0a4ef41ae467e240 Mon Sep 17 00:00:00 2001
From: Pau Sum <pau at sumpau.com>
Date: Tue, 7 Apr 2026 21:01:59 -0400
Subject: [PATCH 4/4] refactor: Use Support/KnownFPClass for itofp cases in
 ValueTracking

---
 llvm/lib/Analysis/ValueTracking.cpp | 56 +++--------------------------
 1 file changed, 5 insertions(+), 51 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index a0fb28612c534..529f42e821462 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5769,59 +5769,13 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
   }
   case Instruction::SIToFP:
   case Instruction::UIToFP: {
-    // Cannot produce nan
-    Known.knownNot(fcNan);
-
-    // Integers cannot be subnormal
-    Known.knownNot(fcSubnormal);
-
-    // sitofp and uitofp turn into +0.0 for zero.
-    Known.knownNot(fcNegZero);
-
-    // UIToFP is always non-negative regardless of known bits.
-    if (Op->getOpcode() == Instruction::UIToFP)
-      Known.signBitMustBeZero();
-
-    // Only compute known bits if we can learn something useful from them.
-    if (!(InterestedClasses & (fcPosZero | fcNormal | fcInf)))
-      break;
-
     KnownBits IntKnown =
         computeKnownBits(Op->getOperand(0), DemandedElts, Q, Depth + 1);
-
-    // If the integer is non-zero, the result cannot be +0.0
-    if (IntKnown.isNonZero())
-      Known.knownNot(fcPosZero);
-
-    if (Op->getOpcode() == Instruction::SIToFP) {
-      // If the signed integer is known non-negative, the result is
-      // non-negative. If the signed integer is known negative, the result is
-      // negative.
-      if (IntKnown.isNonNegative()) {
-        Known.signBitMustBeZero();
-      } else if (IntKnown.isNegative()) {
-        Known.signBitMustBeOne();
-      }
-    }
-
-    // Guard kept for ilogb()
-    if (InterestedClasses & fcInf) {
-      // Get width of largest magnitude integer known.
-      // This still works for a signed minimum value because the largest FP
-      // value is scaled by some fraction close to 2.0 (1.0 + 0.xxxx).
-      int IntSize = IntKnown.getBitWidth();
-      if (Op->getOpcode() == Instruction::UIToFP)
-        IntSize -= IntKnown.countMinLeadingZeros();
-      else if (Op->getOpcode() == Instruction::SIToFP)
-        IntSize -= IntKnown.countMinSignBits();
-
-      // If the exponent of the largest finite FP value can hold the largest
-      // integer, the result of the cast must be finite.
-      Type *FPTy = Op->getType()->getScalarType();
-      if (ilogb(APFloat::getLargest(FPTy->getFltSemantics())) >= IntSize)
-        Known.knownNot(fcInf);
-    }
-
+    const fltSemantics &FltSem =
+        Op->getType()->getScalarType()->getFltSemantics();
+    Known = Op->getOpcode() == Instruction::SIToFP
+                ? KnownFPClass::sitofp(IntKnown, FltSem, InterestedClasses)
+                : KnownFPClass::uitofp(IntKnown, FltSem, InterestedClasses);
     break;
   }
   case Instruction::ExtractElement: {



More information about the llvm-commits mailing list