[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