[llvm] [DAG] computeKnownFPClass - add ISD::SQRT handling + test coverage (PR #195405)

Tharun V K via llvm-commits llvm-commits at lists.llvm.org
Sat May 2 06:07:09 PDT 2026


https://github.com/tharunvk updated https://github.com/llvm/llvm-project/pull/195405

>From 91778b3472f2cf7292afefa19790c7c4f0dcd960 Mon Sep 17 00:00:00 2001
From: Tharun V K <tharunms98 at gmail.com>
Date: Sat, 2 May 2026 00:29:17 +0530
Subject: [PATCH 1/3] [DAG] computeKnownFPClass - add ISD::SQRT handling + test
 coverage

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp |   4 +
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  29 +++++
 .../CodeGen/RISCV/fold-is-fpclass-sqrt.ll     | 120 ++++++++++++++++++
 3 files changed, 153 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/fold-is-fpclass-sqrt.ll

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 302393ffbe036..9d3affd0036fe 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -16204,6 +16204,10 @@ SDValue DAGCombiner::visitIS_FPCLASS(SDNode *N) {
 
   KnownFPClass Known = DAG.computeKnownFPClass(Src, Mask);
 
+if ((Known.KnownFPClasses & Mask) == fcNone) {
+    return DAG.getBoolConstant(false, DL, VT, Src.getValueType());
+  }
+
   // All possible classes are within the mask: result is always true.
   if ((~Mask & Known.KnownFPClasses) == fcNone)
     return DAG.getBoolConstant(true, DL, VT, Src.getValueType());
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 969fb18dcd284..3a1b2efcb9636 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6073,6 +6073,35 @@ KnownFPClass SelectionDAG::computeKnownFPClass(SDValue Op,
     Known.fneg();
     break;
   }
+  case ISD::FSQRT: {
+    FPClassTest InterestedSrcs = InterestedClasses;
+    if (InterestedClasses & fcNan)
+      InterestedSrcs |= KnownFPClass::OrderedLessThanZeroMask;
+
+    KnownFPClass KnownSrc = computeKnownFPClass(
+        Op.getOperand(0), DemandedElts, InterestedSrcs, Depth + 1);
+
+
+    DenormalMode Mode = DenormalMode::getDynamic();
+
+    bool HasNSZ = Op->getFlags().hasNoSignedZeros();
+    bool nnan = Op->getFlags().hasNoNaNs();
+
+    if (!HasNSZ) {
+      const fltSemantics &FltSem =
+          Op.getValueType().getScalarType().getFltSemantics();
+      Mode = getMachineFunction().getDenormalMode(FltSem);
+    }
+
+    Known = KnownFPClass::sqrt(KnownSrc, Mode);
+
+    if (HasNSZ)
+      Known.knownNot(fcNegZero);
+
+    if (nnan)
+      Known.knownNot(fcNan);
+    break;
+  }
   case ISD::BUILD_VECTOR: {
     assert(!VT.isScalableVector());
     bool First = true;
diff --git a/llvm/test/CodeGen/RISCV/fold-is-fpclass-sqrt.ll b/llvm/test/CodeGen/RISCV/fold-is-fpclass-sqrt.ll
new file mode 100644
index 0000000000000..6aba36e6d8667
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/fold-is-fpclass-sqrt.ll
@@ -0,0 +1,120 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv64 -mattr=+f,+d,+v -target-abi=lp64d < %s | FileCheck %s
+
+
+define i1 @sqrt_nnan_check_f32(float %a0) {
+; CHECK-LABEL: sqrt_nnan_check_f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %sqr = call nnan float @llvm.sqrt.f32(float %a0)
+  %res = tail call i1 @llvm.is.fpclass.f32(float %sqr, i32 3)
+  ret i1 %res
+}
+
+define i1 @sqrt_neginf_f32(float %a0) {
+; CHECK-LABEL: sqrt_neginf_f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %sqr = call float @llvm.sqrt.f32(float %a0)
+  %res = tail call i1 @llvm.is.fpclass.f32(float %sqr, i32 4)
+  ret i1 %res
+}
+
+define i1 @sqrt_negnormal_f32(float %a0) {
+; CHECK-LABEL: sqrt_negnormal_f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %sqr = call float @llvm.sqrt.f32(float %a0)
+  %res = tail call i1 @llvm.is.fpclass.f32(float %sqr, i32 8)
+  ret i1 %res
+}
+
+define i1 @sqrt_nsz_negzero_f32(float %a0) {
+; CHECK-LABEL: sqrt_nsz_negzero_f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %sqr = call nsz float @llvm.sqrt.f32(float %a0)
+  %res = tail call i1 @llvm.is.fpclass.f32(float %sqr, i32 32)
+  ret i1 %res
+}
+
+define i1 @sqrt_posinf_f32(float %a0) {
+; CHECK-LABEL: sqrt_posinf_f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fsqrt.s fa5, fa0
+; CHECK-NEXT:    fclass.s a0, fa5
+; CHECK-NEXT:    slli a0, a0, 56
+; CHECK-NEXT:    srli a0, a0, 63
+; CHECK-NEXT:    ret
+  %sqr = call float @llvm.sqrt.f32(float %a0)
+  %res = tail call i1 @llvm.is.fpclass.f32(float %sqr, i32 512)
+  ret i1 %res
+}
+
+declare float @llvm.sqrt.f32(float)
+declare i1 @llvm.is.fpclass.f32(float, i32)
+
+declare <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float>)
+declare <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float>, i32)
+
+define <vscale x 2 x i1> @vsqrt_nnan_check_nxv2f32(<vscale x 2 x float> %a0) {
+; CHECK-LABEL: vsqrt_nnan_check_nxv2f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %sqr = call nnan <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float> %a0)
+  %res = tail call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float> %sqr, i32 3)
+  ret <vscale x 2 x i1> %res
+}
+
+define <vscale x 2 x i1> @vsqrt_neginf_nxv2f32(<vscale x 2 x float> %a0) {
+; CHECK-LABEL: vsqrt_neginf_nxv2f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %sqr = call <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float> %a0)
+  %res = tail call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float> %sqr, i32 4)
+  ret <vscale x 2 x i1> %res
+}
+
+define <vscale x 2 x i1> @vsqrt_negnormal_nxv2f32(<vscale x 2 x float> %a0) {
+; CHECK-LABEL: vsqrt_negnormal_nxv2f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %sqr = call <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float> %a0)
+  %res = tail call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float> %sqr, i32 8)
+  ret <vscale x 2 x i1> %res
+}
+
+define <vscale x 2 x i1> @vsqrt_nsz_negzero_nxv2f32(<vscale x 2 x float> %a0) {
+; CHECK-LABEL: vsqrt_nsz_negzero_nxv2f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %sqr = call nsz <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float> %a0)
+  %res = tail call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float> %sqr, i32 32)
+  ret <vscale x 2 x i1> %res
+}
+
+define <vscale x 2 x i1> @vsqrt_posinf_nxv2f32(<vscale x 2 x float> %a0) {
+; CHECK-LABEL: vsqrt_posinf_nxv2f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e32, m1, ta, ma
+; CHECK-NEXT:    vfsqrt.v v8, v8
+; CHECK-NEXT:    vfclass.v v8, v8
+; CHECK-NEXT:    li a0, 128
+; CHECK-NEXT:    vmseq.vx v0, v8, a0
+; CHECK-NEXT:    ret
+  %sqr = call <vscale x 2 x float> @llvm.sqrt.nxv2f32(<vscale x 2 x float> %a0)
+  %res = tail call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f32(<vscale x 2 x float> %sqr, i32 512)
+  ret <vscale x 2 x i1> %res
+}

>From b60929771072e3ce0ce1739a1868c479295c15b4 Mon Sep 17 00:00:00 2001
From: Tharun V K <tharunms98 at gmail.com>
Date: Sat, 2 May 2026 10:30:54 +0530
Subject: [PATCH 2/3] Fix formatting

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp  | 2 +-
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 9d3affd0036fe..e3c441375fed5 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -16204,7 +16204,7 @@ SDValue DAGCombiner::visitIS_FPCLASS(SDNode *N) {
 
   KnownFPClass Known = DAG.computeKnownFPClass(Src, Mask);
 
-if ((Known.KnownFPClasses & Mask) == fcNone) {
+  if ((Known.KnownFPClasses & Mask) == fcNone) {
     return DAG.getBoolConstant(false, DL, VT, Src.getValueType());
   }
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 3a1b2efcb9636..9b24c1c21ec28 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6078,9 +6078,8 @@ KnownFPClass SelectionDAG::computeKnownFPClass(SDValue Op,
     if (InterestedClasses & fcNan)
       InterestedSrcs |= KnownFPClass::OrderedLessThanZeroMask;
 
-    KnownFPClass KnownSrc = computeKnownFPClass(
-        Op.getOperand(0), DemandedElts, InterestedSrcs, Depth + 1);
-
+    KnownFPClass KnownSrc = computeKnownFPClass(Op.getOperand(0), DemandedElts,
+                                                InterestedSrcs, Depth + 1);
 
     DenormalMode Mode = DenormalMode::getDynamic();
 

>From 6b6b40fbc158c02c293e5997ed2f234b551f303a Mon Sep 17 00:00:00 2001
From: Tharun V K <tharunms98 at gmail.com>
Date: Sat, 2 May 2026 18:36:53 +0530
Subject: [PATCH 3/3] Avoid promoting nsz to poison

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

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 9b24c1c21ec28..a0852e3734593 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6094,9 +6094,6 @@ KnownFPClass SelectionDAG::computeKnownFPClass(SDValue Op,
 
     Known = KnownFPClass::sqrt(KnownSrc, Mode);
 
-    if (HasNSZ)
-      Known.knownNot(fcNegZero);
-
     if (nnan)
       Known.knownNot(fcNan);
     break;



More information about the llvm-commits mailing list