[llvm] [RISCV] Add for splitting LMUL=8 f16 fixed vectors (s/u)ittofp/fpto(s/u)i. (PR #191568)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 10 16:17:05 PDT 2026


https://github.com/topperc created https://github.com/llvm/llvm-project/pull/191568

The conversion needs to be by promoting to f32. If we're already at LMUL=8, we need to promote before we can split.

>From 2898e399195befaa1e5dd9c6a6ea4567fbb4d8d1 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 10 Apr 2026 15:23:12 -0700
Subject: [PATCH] [RISCV] Add for splitting LMUL=8 f16 fixed vectors
 (s/u)ittofp/fpto(s/u)i.

The conversion needs to be by promoting to f32. If we're already
at LMUL=8, we need to promote before we can split.
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  12 +-
 .../CodeGen/RISCV/rvv/fixed-vectors-fp2i.ll   | 118 ++++++++++++++++++
 .../CodeGen/RISCV/rvv/fixed-vectors-i2fp.ll   | 118 ++++++++++++++++++
 3 files changed, 242 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 73210f3743aa6..1782e07b91fad 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -8062,12 +8062,12 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
           (Subtarget.hasVInstructionsF16Minimal() &&
            !Subtarget.hasVInstructionsF16())) ||
          Op.getValueType().getScalarType() == MVT::bf16)) {
-      if (isPromotedOpNeedingSplit(Op, Subtarget))
+      MVT NVT =
+          MVT::getVectorVT(MVT::f32, Op.getValueType().getVectorElementCount());
+      if (!isTypeLegal(NVT))
         return SplitVectorOp(Op, DAG);
       // int -> f32
       SDLoc DL(Op);
-      MVT NVT =
-          MVT::getVectorVT(MVT::f32, Op.getValueType().getVectorElementCount());
       SDValue NC = DAG.getNode(Op.getOpcode(), DL, NVT, Op->ops());
       // f32 -> [b]f16
       return DAG.getNode(ISD::FP_ROUND, DL, Op.getValueType(), NC,
@@ -8082,12 +8082,12 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
           (Subtarget.hasVInstructionsF16Minimal() &&
            !Subtarget.hasVInstructionsF16())) ||
          Op1.getValueType().getScalarType() == MVT::bf16)) {
-      if (isPromotedOpNeedingSplit(Op1, Subtarget))
+      MVT NVT = MVT::getVectorVT(MVT::f32,
+                                 Op1.getValueType().getVectorElementCount());
+      if (!isTypeLegal(NVT))
         return SplitVectorOp(Op, DAG);
       // [b]f16 -> f32
       SDLoc DL(Op);
-      MVT NVT = MVT::getVectorVT(MVT::f32,
-                                 Op1.getValueType().getVectorElementCount());
       SDValue WidenVec = DAG.getNode(ISD::FP_EXTEND, DL, NVT, Op1);
       // f32 -> int
       return DAG.getNode(Op.getOpcode(), DL, Op.getValueType(), WidenVec);
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp2i.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp2i.ll
index ea791a155d3d6..e9357b629628c 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp2i.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp2i.ll
@@ -474,6 +474,56 @@ define <2 x i1> @fp2ui_v2bf16_v2i1(<2 x bfloat> %x) {
   ret <2 x i1> %z
 }
 
+define void @fp2si_v64bf16_v64i16(ptr %x, ptr %y) {
+; CHECK-LABEL: fp2si_v64bf16_v64i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a2, 64
+; CHECK-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; CHECK-NEXT:    vle16.v v8, (a0)
+; CHECK-NEXT:    li a0, 32
+; CHECK-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; CHECK-NEXT:    vfwcvtbf16.f.f.v v16, v8
+; CHECK-NEXT:    vsetvli zero, a0, e16, m8, ta, ma
+; CHECK-NEXT:    vslidedown.vx v24, v8, a0
+; CHECK-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; CHECK-NEXT:    vfncvt.rtz.x.f.w v8, v16
+; CHECK-NEXT:    vfwcvtbf16.f.f.v v16, v24
+; CHECK-NEXT:    vfncvt.rtz.x.f.w v24, v16
+; CHECK-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; CHECK-NEXT:    vslideup.vx v8, v24, a0
+; CHECK-NEXT:    vse16.v v8, (a1)
+; CHECK-NEXT:    ret
+  %a = load <64 x bfloat>, ptr %x
+  %d = fptosi <64 x bfloat> %a to <64 x i16>
+  store <64 x i16> %d, ptr %y
+  ret void
+}
+
+define void @fp2ui_v64bf16_v64i16(ptr %x, ptr %y) {
+; CHECK-LABEL: fp2ui_v64bf16_v64i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a2, 64
+; CHECK-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; CHECK-NEXT:    vle16.v v8, (a0)
+; CHECK-NEXT:    li a0, 32
+; CHECK-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; CHECK-NEXT:    vfwcvtbf16.f.f.v v16, v8
+; CHECK-NEXT:    vsetvli zero, a0, e16, m8, ta, ma
+; CHECK-NEXT:    vslidedown.vx v24, v8, a0
+; CHECK-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; CHECK-NEXT:    vfncvt.rtz.xu.f.w v8, v16
+; CHECK-NEXT:    vfwcvtbf16.f.f.v v16, v24
+; CHECK-NEXT:    vfncvt.rtz.xu.f.w v24, v16
+; CHECK-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; CHECK-NEXT:    vslideup.vx v8, v24, a0
+; CHECK-NEXT:    vse16.v v8, (a1)
+; CHECK-NEXT:    ret
+  %a = load <64 x bfloat>, ptr %x
+  %d = fptoui <64 x bfloat> %a to <64 x i16>
+  store <64 x i16> %d, ptr %y
+  ret void
+}
+
 define void @fp2si_v2f16_v2i64(ptr %x, ptr %y) {
 ; CHECK-LABEL: fp2si_v2f16_v2i64:
 ; CHECK:       # %bb.0:
@@ -544,6 +594,74 @@ define <2 x i1> @fp2ui_v2f16_v2i1(<2 x half> %x) {
   ret <2 x i1> %z
 }
 
+define void @fp2si_v64f16_v64i16(ptr %x, ptr %y) {
+; ZVFH-LABEL: fp2si_v64f16_v64i16:
+; ZVFH:       # %bb.0:
+; ZVFH-NEXT:    li a2, 64
+; ZVFH-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFH-NEXT:    vle16.v v8, (a0)
+; ZVFH-NEXT:    vfcvt.rtz.x.f.v v8, v8
+; ZVFH-NEXT:    vse16.v v8, (a1)
+; ZVFH-NEXT:    ret
+;
+; ZVFHMIN-LABEL: fp2si_v64f16_v64i16:
+; ZVFHMIN:       # %bb.0:
+; ZVFHMIN-NEXT:    li a2, 64
+; ZVFHMIN-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vle16.v v8, (a0)
+; ZVFHMIN-NEXT:    li a0, 32
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; ZVFHMIN-NEXT:    vfwcvt.f.f.v v16, v8
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vslidedown.vx v24, v8, a0
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; ZVFHMIN-NEXT:    vfncvt.rtz.x.f.w v8, v16
+; ZVFHMIN-NEXT:    vfwcvt.f.f.v v16, v24
+; ZVFHMIN-NEXT:    vfncvt.rtz.x.f.w v24, v16
+; ZVFHMIN-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vslideup.vx v8, v24, a0
+; ZVFHMIN-NEXT:    vse16.v v8, (a1)
+; ZVFHMIN-NEXT:    ret
+  %a = load <64 x half>, ptr %x
+  %d = fptosi <64 x half> %a to <64 x i16>
+  store <64 x i16> %d, ptr %y
+  ret void
+}
+
+define void @fp2ui_v64f16_v64i16(ptr %x, ptr %y) {
+; ZVFH-LABEL: fp2ui_v64f16_v64i16:
+; ZVFH:       # %bb.0:
+; ZVFH-NEXT:    li a2, 64
+; ZVFH-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFH-NEXT:    vle16.v v8, (a0)
+; ZVFH-NEXT:    vfcvt.rtz.xu.f.v v8, v8
+; ZVFH-NEXT:    vse16.v v8, (a1)
+; ZVFH-NEXT:    ret
+;
+; ZVFHMIN-LABEL: fp2ui_v64f16_v64i16:
+; ZVFHMIN:       # %bb.0:
+; ZVFHMIN-NEXT:    li a2, 64
+; ZVFHMIN-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vle16.v v8, (a0)
+; ZVFHMIN-NEXT:    li a0, 32
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; ZVFHMIN-NEXT:    vfwcvt.f.f.v v16, v8
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vslidedown.vx v24, v8, a0
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; ZVFHMIN-NEXT:    vfncvt.rtz.xu.f.w v8, v16
+; ZVFHMIN-NEXT:    vfwcvt.f.f.v v16, v24
+; ZVFHMIN-NEXT:    vfncvt.rtz.xu.f.w v24, v16
+; ZVFHMIN-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vslideup.vx v8, v24, a0
+; ZVFHMIN-NEXT:    vse16.v v8, (a1)
+; ZVFHMIN-NEXT:    ret
+  %a = load <64 x half>, ptr %x
+  %d = fptoui <64 x half> %a to <64 x i16>
+  store <64 x i16> %d, ptr %y
+  ret void
+}
+
 define void @fp2si_v2f64_v2i8(ptr %x, ptr %y) {
 ; CHECK-LABEL: fp2si_v2f64_v2i8:
 ; CHECK:       # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-i2fp.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-i2fp.ll
index b52b082282ec4..613421d27fb83 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-i2fp.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-i2fp.ll
@@ -534,6 +534,56 @@ define <8 x bfloat> @ui2fp_v8i1_v8bf16(<8 x i1> %x) {
   ret <8 x bfloat> %z
 }
 
+define void @si2fp_v64i16_v64bf16(ptr %x, ptr %y) {
+; CHECK-LABEL: si2fp_v64i16_v64bf16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a2, 64
+; CHECK-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; CHECK-NEXT:    vle16.v v8, (a0)
+; CHECK-NEXT:    li a0, 32
+; CHECK-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; CHECK-NEXT:    vfwcvt.f.x.v v16, v8
+; CHECK-NEXT:    vsetvli zero, a0, e16, m8, ta, ma
+; CHECK-NEXT:    vslidedown.vx v24, v8, a0
+; CHECK-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; CHECK-NEXT:    vfncvtbf16.f.f.w v8, v16
+; CHECK-NEXT:    vfwcvt.f.x.v v16, v24
+; CHECK-NEXT:    vfncvtbf16.f.f.w v24, v16
+; CHECK-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; CHECK-NEXT:    vslideup.vx v8, v24, a0
+; CHECK-NEXT:    vse16.v v8, (a1)
+; CHECK-NEXT:    ret
+  %a = load <64 x i16>, ptr %x
+  %d = sitofp <64 x i16> %a to <64 x bfloat>
+  store <64 x bfloat> %d, ptr %y
+  ret void
+}
+
+define void @ui2fp_v64i16_v64bf16(ptr %x, ptr %y) {
+; CHECK-LABEL: ui2fp_v64i16_v64bf16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a2, 64
+; CHECK-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; CHECK-NEXT:    vle16.v v8, (a0)
+; CHECK-NEXT:    li a0, 32
+; CHECK-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; CHECK-NEXT:    vfwcvt.f.xu.v v16, v8
+; CHECK-NEXT:    vsetvli zero, a0, e16, m8, ta, ma
+; CHECK-NEXT:    vslidedown.vx v24, v8, a0
+; CHECK-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; CHECK-NEXT:    vfncvtbf16.f.f.w v8, v16
+; CHECK-NEXT:    vfwcvt.f.xu.v v16, v24
+; CHECK-NEXT:    vfncvtbf16.f.f.w v24, v16
+; CHECK-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; CHECK-NEXT:    vslideup.vx v8, v24, a0
+; CHECK-NEXT:    vse16.v v8, (a1)
+; CHECK-NEXT:    ret
+  %a = load <64 x i16>, ptr %x
+  %d = uitofp <64 x i16> %a to <64 x bfloat>
+  store <64 x bfloat> %d, ptr %y
+  ret void
+}
+
 define void @si2fp_v2i64_v2f16(ptr %x, ptr %y) {
 ; CHECK-LABEL: si2fp_v2i64_v2f16:
 ; CHECK:       # %bb.0:
@@ -681,3 +731,71 @@ define <8 x half> @ui2fp_v8i1_v8f16(<8 x i1> %x) {
   %z = uitofp <8 x i1> %x to <8 x half>
   ret <8 x half> %z
 }
+
+define void @si2fp_v64i16_v64f16(ptr %x, ptr %y) {
+; ZVFH-LABEL: si2fp_v64i16_v64f16:
+; ZVFH:       # %bb.0:
+; ZVFH-NEXT:    li a2, 64
+; ZVFH-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFH-NEXT:    vle16.v v8, (a0)
+; ZVFH-NEXT:    vfcvt.f.x.v v8, v8
+; ZVFH-NEXT:    vse16.v v8, (a1)
+; ZVFH-NEXT:    ret
+;
+; ZVFHMIN-LABEL: si2fp_v64i16_v64f16:
+; ZVFHMIN:       # %bb.0:
+; ZVFHMIN-NEXT:    li a2, 64
+; ZVFHMIN-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vle16.v v8, (a0)
+; ZVFHMIN-NEXT:    li a0, 32
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; ZVFHMIN-NEXT:    vfwcvt.f.x.v v16, v8
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vslidedown.vx v24, v8, a0
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; ZVFHMIN-NEXT:    vfncvt.f.f.w v8, v16
+; ZVFHMIN-NEXT:    vfwcvt.f.x.v v16, v24
+; ZVFHMIN-NEXT:    vfncvt.f.f.w v24, v16
+; ZVFHMIN-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vslideup.vx v8, v24, a0
+; ZVFHMIN-NEXT:    vse16.v v8, (a1)
+; ZVFHMIN-NEXT:    ret
+  %a = load <64 x i16>, ptr %x
+  %d = sitofp <64 x i16> %a to <64 x half>
+  store <64 x half> %d, ptr %y
+  ret void
+}
+
+define void @ui2fp_v64i16_v64f16(ptr %x, ptr %y) {
+; ZVFH-LABEL: ui2fp_v64i16_v64f16:
+; ZVFH:       # %bb.0:
+; ZVFH-NEXT:    li a2, 64
+; ZVFH-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFH-NEXT:    vle16.v v8, (a0)
+; ZVFH-NEXT:    vfcvt.f.xu.v v8, v8
+; ZVFH-NEXT:    vse16.v v8, (a1)
+; ZVFH-NEXT:    ret
+;
+; ZVFHMIN-LABEL: ui2fp_v64i16_v64f16:
+; ZVFHMIN:       # %bb.0:
+; ZVFHMIN-NEXT:    li a2, 64
+; ZVFHMIN-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vle16.v v8, (a0)
+; ZVFHMIN-NEXT:    li a0, 32
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; ZVFHMIN-NEXT:    vfwcvt.f.xu.v v16, v8
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vslidedown.vx v24, v8, a0
+; ZVFHMIN-NEXT:    vsetvli zero, a0, e16, m4, ta, ma
+; ZVFHMIN-NEXT:    vfncvt.f.f.w v8, v16
+; ZVFHMIN-NEXT:    vfwcvt.f.xu.v v16, v24
+; ZVFHMIN-NEXT:    vfncvt.f.f.w v24, v16
+; ZVFHMIN-NEXT:    vsetvli zero, a2, e16, m8, ta, ma
+; ZVFHMIN-NEXT:    vslideup.vx v8, v24, a0
+; ZVFHMIN-NEXT:    vse16.v v8, (a1)
+; ZVFHMIN-NEXT:    ret
+  %a = load <64 x i16>, ptr %x
+  %d = uitofp <64 x i16> %a to <64 x half>
+  store <64 x half> %d, ptr %y
+  ret void
+}



More information about the llvm-commits mailing list