[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