[llvm] [DAG] computeKnownFPClass - add ISD::EXTRACT_SUBVECTOR/INSERT_SUBVECTOR handling. (PR #190378)

via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 3 11:04:48 PDT 2026


https://github.com/Xylecrack created https://github.com/llvm/llvm-project/pull/190378

This patch implements ` ISD::EXTRACT_SUBVECTOR` and `ISD::INSERT_SUBVECTOR` handling in `SelectionDAG::computeKnownFPClass`. 
Fixes: #189586 



>From dfc52b98e47e9fec39594dcd6c86b915daaf4a0b Mon Sep 17 00:00:00 2001
From: Dhruva Narayan <dhruvakodiadka at gmail.com>
Date: Fri, 3 Apr 2026 23:21:55 +0530
Subject: [PATCH] add EXTRACT_SUBVECTOR/INSERT_SUBVECTOR handling in
 computeKnownFPclass

---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  44 ++++++++
 llvm/test/CodeGen/RISCV/subvector-fpclass.ll  | 104 ++++++++++++++++++
 2 files changed, 148 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/subvector-fpclass.ll

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 6eb8853550a19..3eaebd438a5ab 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6100,6 +6100,50 @@ KnownFPClass SelectionDAG::computeKnownFPClass(SDValue Op,
     Known.fabs();
     break;
   }
+  case ISD::EXTRACT_SUBVECTOR: {
+    SDValue Src = Op.getOperand(0);
+    EVT SrcVT = Src.getValueType();
+    if (SrcVT.isFixedLengthVector()) {
+      unsigned Idx = Op.getConstantOperandVal(1);
+      unsigned NumSrcElts = SrcVT.getVectorNumElements();
+
+      APInt DemandedSrcElts = DemandedElts.zextOrTrunc(NumSrcElts).shl(Idx);
+      Known = computeKnownFPClass(Src, DemandedSrcElts, InterestedClasses,
+                                  Depth + 1);
+    } else
+      Known = computeKnownFPClass(Src, InterestedClasses, Depth + 1);
+    break;
+  }
+
+  case ISD::INSERT_SUBVECTOR: {
+    SDValue BaseVector = Op.getOperand(0);
+    SDValue SubVector = Op.getOperand(1);
+    EVT BaseVT = BaseVector.getValueType();
+    if (BaseVT.isFixedLengthVector()) {
+      unsigned Idx = Op.getConstantOperandVal(2);
+      unsigned NumBaseElts = BaseVT.getVectorNumElements();
+      unsigned NumSubElts = SubVector.getValueType().getVectorNumElements();
+
+      APInt DemandedMask =
+          APInt::getBitsSet(NumBaseElts, Idx, Idx + NumSubElts);
+      APInt DemandedSrcElts = DemandedElts & ~DemandedMask;
+      APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx);
+
+      if (!DemandedSrcElts.isZero())
+        Known = computeKnownFPClass(BaseVector, DemandedSrcElts,
+                                    InterestedClasses, Depth + 1);
+      if (!DemandedSubElts.isZero()) {
+        KnownFPClass SubKnown = computeKnownFPClass(
+            SubVector, DemandedSubElts, InterestedClasses, Depth + 1);
+        Known = DemandedSrcElts.isZero() ? SubKnown : (Known | SubKnown);
+      }
+
+    } else
+      Known = computeKnownFPClass(BaseVector, InterestedClasses, Depth + 1) |
+              computeKnownFPClass(SubVector, InterestedClasses, Depth + 1);
+    break;
+  }
+
   default:
     if (Opcode >= ISD::BUILTIN_OP_END || Opcode == ISD::INTRINSIC_WO_CHAIN ||
         Opcode == ISD::INTRINSIC_W_CHAIN || Opcode == ISD::INTRINSIC_VOID) {
diff --git a/llvm/test/CodeGen/RISCV/subvector-fpclass.ll b/llvm/test/CodeGen/RISCV/subvector-fpclass.ll
new file mode 100644
index 0000000000000..83c0fd412a1b7
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/subvector-fpclass.ll
@@ -0,0 +1,104 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=riscv64 -mattr=+v,+f,+d | FileCheck %s
+
+define i1 @extract_subvec(<8 x float> %a0){
+; CHECK-LABEL: extract_subvec:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
+; CHECK-NEXT:    vfabs.v v8, v8
+; CHECK-NEXT:    vsetivli zero, 4, e32, m2, ta, ma
+; CHECK-NEXT:    vslidedown.vi v8, v8, 4
+; CHECK-NEXT:    vfmv.f.s fa5, v8
+; CHECK-NEXT:    fclass.s a0, fa5
+; CHECK-NEXT:    andi a0, a0, 15
+; CHECK-NEXT:    snez a0, a0
+; CHECK-NEXT:    ret
+  %abs = call <8 x float> @llvm.fabs.v8f32(<8 x float> %a0)
+  %sub = call <4 x float> @llvm.vector.extract.v4f32.v8f32(<8 x float> %abs, i64 4)
+  %elt = extractelement <4 x float> %sub, i32 0
+  %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 60)
+  ret i1 %res
+}
+
+define i1 @extract_subvec_scalable(<vscale x 8 x float> %a0){
+; CHECK-LABEL: extract_subvec_scalable:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
+; CHECK-NEXT:    vfabs.v v8, v8
+; CHECK-NEXT:    vfmv.f.s fa5, v8
+; CHECK-NEXT:    fclass.s a0, fa5
+; CHECK-NEXT:    andi a0, a0, 15
+; CHECK-NEXT:    snez a0, a0
+; CHECK-NEXT:    ret
+  %abs = call <vscale x 8 x float> @llvm.fabs.nxv8f32(<vscale x 8 x float> %a0)
+  %sub = call <vscale x 4 x float> @llvm.vector.extract.nxv4f32.nxv8f32(<vscale x 8 x float> %abs, i64 0)
+  %elt = extractelement <vscale x 4 x float> %sub, i32 0
+  %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 60)
+  ret i1 %res
+}
+
+define <4 x i1> @insert_subvec_base_demanded(<4 x float> %base, <2 x float> %sub){
+; CHECK-LABEL: insert_subvec_base_demanded:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT:    vfabs.v v8, v8
+; CHECK-NEXT:    vslideup.vi v8, v9, 2
+; CHECK-NEXT:    vfclass.v v8, v8
+; CHECK-NEXT:    vand.vi v8, v8, 15
+; CHECK-NEXT:    vmsne.vi v0, v8, 0
+; CHECK-NEXT:    ret
+  %absbase = call <4 x float> @llvm.fabs.v4f32(<4 x float> %base)
+  %ins = call <4 x float> @llvm.vector.insert.v4f32.v2f32(<4 x float> %absbase, <2 x float> %sub, i64 2)
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %ins, i32 60)
+  ret <4 x i1> %res
+}
+
+define i1 @insert_subvec_sub_demanded(<4 x float> %base, <2 x float> %sub){
+; CHECK-LABEL: insert_subvec_sub_demanded:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 2, e32, mf2, ta, ma
+; CHECK-NEXT:    vfabs.v v8, v9
+; CHECK-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT:    vslideup.vi v9, v8, 2
+; CHECK-NEXT:    vslidedown.vi v8, v9, 2
+; CHECK-NEXT:    vfmv.f.s fa5, v8
+; CHECK-NEXT:    fclass.s a0, fa5
+; CHECK-NEXT:    andi a0, a0, 15
+; CHECK-NEXT:    snez a0, a0
+; CHECK-NEXT:    ret
+  %abssub = call <2 x float> @llvm.fabs.v2f32(<2 x float> %sub)
+  %ins = call <4 x float> @llvm.vector.insert.v4f32.v2f32(<4 x float> %base, <2 x float> %abssub, i64 2)
+  %elt = extractelement <4 x float> %ins, i32 2
+  %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 60)
+  ret i1 %res
+}
+define <4 x i1> @insert_subvec_both_demanded(<4 x float> %base, <2 x float> %sub){
+; CHECK-LABEL: insert_subvec_both_demanded:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e8, mf4, ta, ma
+; CHECK-NEXT:    vmclr.m v0
+; CHECK-NEXT:    ret
+  %absbase = call <4 x float> @llvm.fabs.v4f32(<4 x float> %base)
+  %abssub  = call <2 x float> @llvm.fabs.v2f32(<2 x float> %sub)
+  %ins = call <4 x float> @llvm.vector.insert.v4f32.v2f32(<4 x float> %absbase, <2 x float> %abssub, i64 2)
+  %res = call <4 x i1> @llvm.is.fpclass.v4f32(<4 x float> %ins, i32 60)
+  ret <4 x i1> %res
+}
+
+define i1 @insert_subvec_scalable_both(<vscale x 4 x float> %base, <vscale x 2 x float> %sub){
+; CHECK-LABEL: insert_subvec_scalable_both:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e32, m1, ta, ma
+; CHECK-NEXT:    vfabs.v v8, v10
+; CHECK-NEXT:    vfmv.f.s fa5, v8
+; CHECK-NEXT:    fclass.s a0, fa5
+; CHECK-NEXT:    andi a0, a0, 15
+; CHECK-NEXT:    snez a0, a0
+; CHECK-NEXT:    ret
+  %absbase = call <vscale x 4 x float> @llvm.fabs.nxv4f32(<vscale x 4 x float> %base)
+  %abssub  = call <vscale x 2 x float> @llvm.fabs.nxv2f32(<vscale x 2 x float> %sub)
+  %ins = call <vscale x 4 x float> @llvm.vector.insert.nxv4f32.nxv2f32(<vscale x 4 x float> %absbase, <vscale x 2 x float> %abssub, i64 0)
+  %elt = extractelement <vscale x 4 x float> %ins, i32 0
+  %res = call i1 @llvm.is.fpclass.f32(float %elt, i32 60)
+  ret i1 %res
+}



More information about the llvm-commits mailing list