[llvm] [SelectionDAG] Soften STRICT_FP16_TO_FP and STRICT_BF16_TO_FP (PR #230889)
Aochang Liu via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 10 22:00:36 PDT 2026
https://github.com/HelloWorldU created https://github.com/llvm/llvm-project/pull/230889
On targets where `f16` is soft-promoted and `f32` is softened (for example, RISC-V without F), a strict conversion from `f16` to an integer creates a `STRICT_FP16_TO_FP` with an `f32` result. `SoftenFloatResult` did not handle it, so the conversion crashed with "Do not know how to soften the result of this operator!".
Handle `STRICT_FP16_TO_FP` like `FP16_TO_FP`, and pass the chain through the libcalls.
`bf16` had the same gap. `SoftenFloatRes_BF16_TO_FP` always read operand 0, which is the chain for a strict node, so strict `bf16` conversions and strict `fpext` from `bf16` crashed. Handle `STRICT_BF16_TO_FP` there too. As in the non-strict case, the `bf16` expansion is a shift, so it does not quiet signaling NaNs or raise exceptions.
Fixes #230786
Assisted-by: Claude Opus 5.5
>From 4f35591bd0a8927dee23aea7c1755564613931d1 Mon Sep 17 00:00:00 2001
From: HelloWorldU <asd001liu at gmail.com>
Date: Sun, 11 Oct 2026 12:52:39 +0800
Subject: [PATCH] [SelectionDAG] Soften STRICT_FP16_TO_FP and STRICT_BF16_TO_FP
On targets where f16 is soft-promoted and f32 is softened (for example,
RISC-V without F), a strict conversion from f16 to an integer creates a
STRICT_FP16_TO_FP with an f32 result. SoftenFloatResult did not handle
it, so the conversion crashed with "Do not know how to soften the result
of this operator!".
Handle STRICT_FP16_TO_FP like FP16_TO_FP, and pass the chain through the
libcalls.
bf16 had the same gap. SoftenFloatRes_BF16_TO_FP always read operand 0,
which is the chain for a strict node, so strict bf16 conversions and
strict fpext from bf16 crashed. Handle STRICT_BF16_TO_FP there too. As in
the non-strict case, the bf16 expansion is a shift, so it does not quiet
signaling NaNs or raise exceptions.
Fixes #230786
Assisted-by: Claude Opus 5.5
---
.../SelectionDAG/LegalizeFloatTypes.cpp | 40 +-
.../CodeGen/RISCV/bfloat-convert-strict.ll | 115 ++++
.../test/CodeGen/RISCV/half-convert-strict.ll | 643 ++++++++++++++++++
3 files changed, 784 insertions(+), 14 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/bfloat-convert-strict.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index e14a97d91495a..d5ae5a3670c28 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -130,7 +130,9 @@ void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
case ISD::FP_EXTEND: R = SoftenFloatRes_FP_EXTEND(N); break;
case ISD::STRICT_FP_ROUND:
case ISD::FP_ROUND: R = SoftenFloatRes_FP_ROUND(N); break;
+ case ISD::STRICT_FP16_TO_FP:
case ISD::FP16_TO_FP: R = SoftenFloatRes_FP16_TO_FP(N); break;
+ case ISD::STRICT_BF16_TO_FP:
case ISD::BF16_TO_FP: R = SoftenFloatRes_BF16_TO_FP(N); break;
case ISD::STRICT_FPOW:
case ISD::FPOW: R = SoftenFloatRes_FPOW(N); break;
@@ -582,10 +584,8 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FP_EXTEND(SDNode *N) {
}
}
- if (Op.getValueType() == MVT::bf16) {
- // FIXME: Need ReplaceValueWith on chain in strict case
+ if (Op.getValueType() == MVT::bf16)
return SoftenFloatRes_BF16_TO_FP(N);
- }
RTLIB::Libcall LC = RTLIB::getFPEXT(Op.getValueType(), N->getValueType(0));
if (LC == RTLIB::UNKNOWN_LIBCALL) {
@@ -610,20 +610,27 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FP_EXTEND(SDNode *N) {
// FIXME: Should we just use 'normal' FP_EXTEND / FP_TRUNC instead of special
// nodes?
SDValue DAGTypeLegalizer::SoftenFloatRes_FP16_TO_FP(SDNode *N) {
+ bool IsStrict = N->isStrictFPOpcode();
EVT MidVT = TLI.getTypeToTransformTo(*DAG.getContext(), MVT::f32);
- SDValue Op = N->getOperand(0);
+ SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
+ SDValue Op = N->getOperand(IsStrict ? 1 : 0);
TargetLowering::MakeLibCallOptions CallOptions;
- EVT OpsVT[1] = { N->getOperand(0).getValueType() };
+ EVT OpsVT[1] = {Op.getValueType()};
CallOptions.setTypeListBeforeSoften(OpsVT, N->getValueType(0));
- SDValue Res32 = TLI.makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MidVT, Op,
- CallOptions, SDLoc(N)).first;
- if (N->getValueType(0) == MVT::f32)
- return Res32;
+ std::pair<SDValue, SDValue> Tmp = TLI.makeLibCall(
+ DAG, RTLIB::FPEXT_F16_F32, MidVT, Op, CallOptions, SDLoc(N), Chain);
- EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
- RTLIB::Libcall LC = RTLIB::getFPEXT(MVT::f32, N->getValueType(0));
- assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_EXTEND!");
- return TLI.makeLibCall(DAG, LC, NVT, Res32, CallOptions, SDLoc(N)).first;
+ if (N->getValueType(0) != MVT::f32) {
+ EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
+ RTLIB::Libcall LC = RTLIB::getFPEXT(MVT::f32, N->getValueType(0));
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_EXTEND!");
+ Tmp = TLI.makeLibCall(DAG, LC, NVT, Tmp.first, CallOptions, SDLoc(N),
+ IsStrict ? Tmp.second : SDValue());
+ }
+
+ if (IsStrict)
+ ReplaceValueWith(SDValue(N, 1), Tmp.second);
+ return Tmp.first;
}
// FIXME: Should we just use 'normal' FP_EXTEND / FP_TRUNC instead of special
@@ -631,13 +638,18 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FP16_TO_FP(SDNode *N) {
SDValue DAGTypeLegalizer::SoftenFloatRes_BF16_TO_FP(SDNode *N) {
assert(N->getValueType(0) == MVT::f32 &&
"Can only soften BF16_TO_FP with f32 result");
+ bool IsStrict = N->isStrictFPOpcode();
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), MVT::f32);
- SDValue Op = N->getOperand(0);
+ SDValue Op = N->getOperand(IsStrict ? 1 : 0);
SDLoc DL(N);
Op = DAG.getNode(ISD::ANY_EXTEND, DL, NVT,
DAG.getNode(ISD::BITCAST, DL, MVT::i16, Op));
SDValue Res = DAG.getNode(ISD::SHL, DL, NVT, Op,
DAG.getShiftAmountConstant(16, NVT, DL));
+ // As in the non-strict case, this does not quiet signaling NaNs or raise
+ // exceptions, so the chain passes through.
+ if (IsStrict)
+ ReplaceValueWith(SDValue(N, 1), N->getOperand(0));
return Res;
}
diff --git a/llvm/test/CodeGen/RISCV/bfloat-convert-strict.ll b/llvm/test/CodeGen/RISCV/bfloat-convert-strict.ll
new file mode 100644
index 0000000000000..4c03ea6702047
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/bfloat-convert-strict.ll
@@ -0,0 +1,115 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs \
+; RUN: -disable-strictnode-mutation < %s | FileCheck -check-prefixes=RV32I %s
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs \
+; RUN: -disable-strictnode-mutation < %s | FileCheck -check-prefixes=RV64I %s
+
+define i32 @fcvt_w_bf16(bfloat %a) nounwind strictfp {
+; RV32I-LABEL: fcvt_w_bf16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: call __fixsfsi
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_w_bf16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slliw a0, a0, 16
+; RV64I-NEXT: call __fixsfdi
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call i32 @llvm.experimental.constrained.fptosi.i32.bf16(bfloat %a, metadata !"fpexcept.strict") strictfp
+ ret i32 %1
+}
+
+define i32 @fcvt_wu_bf16(bfloat %a) nounwind strictfp {
+; RV32I-LABEL: fcvt_wu_bf16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: call __fixunssfsi
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_wu_bf16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slliw a0, a0, 16
+; RV64I-NEXT: call __fixunssfdi
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call i32 @llvm.experimental.constrained.fptoui.i32.bf16(bfloat %a, metadata !"fpexcept.strict") strictfp
+ ret i32 %1
+}
+
+define i64 @fcvt_l_bf16(bfloat %a) nounwind strictfp {
+; RV32I-LABEL: fcvt_l_bf16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: call __fixsfdi
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_l_bf16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slliw a0, a0, 16
+; RV64I-NEXT: call __fixsfdi
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call i64 @llvm.experimental.constrained.fptosi.i64.bf16(bfloat %a, metadata !"fpexcept.strict") strictfp
+ ret i64 %1
+}
+
+define float @fcvt_s_bf16(bfloat %a) nounwind strictfp {
+; RV32I-LABEL: fcvt_s_bf16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_s_bf16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: slliw a0, a0, 16
+; RV64I-NEXT: ret
+ %1 = call float @llvm.experimental.constrained.fpext.f32.bf16(bfloat %a, metadata !"fpexcept.strict") strictfp
+ ret float %1
+}
+
+define double @fcvt_d_bf16(bfloat %a) nounwind strictfp {
+; RV32I-LABEL: fcvt_d_bf16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: call __extendsfdf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_d_bf16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slliw a0, a0, 16
+; RV64I-NEXT: call __extendsfdf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call double @llvm.experimental.constrained.fpext.f64.bf16(bfloat %a, metadata !"fpexcept.strict") strictfp
+ ret double %1
+}
diff --git a/llvm/test/CodeGen/RISCV/half-convert-strict.ll b/llvm/test/CodeGen/RISCV/half-convert-strict.ll
index 8653943cc94c9..c07670a195f9d 100644
--- a/llvm/test/CodeGen/RISCV/half-convert-strict.ll
+++ b/llvm/test/CodeGen/RISCV/half-convert-strict.ll
@@ -54,6 +54,12 @@
; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs \
; RUN: -target-abi ilp32d -disable-strictnode-mutation < %s \
; RUN: | FileCheck -check-prefixes=CHECK32-D %s
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs \
+; RUN: -disable-strictnode-mutation < %s \
+; RUN: | FileCheck -check-prefixes=RV32I %s
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs \
+; RUN: -disable-strictnode-mutation < %s \
+; RUN: | FileCheck -check-prefixes=RV64I %s
; NOTE: The rounding mode metadata does not effect which instruction is
; selected. Dynamic rounding mode is always used for operations that
@@ -117,6 +123,30 @@ define i16 @fcvt_si_h(half %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_si_h:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: srli a0, a0, 16
+; RV32I-NEXT: call __extendhfsf2
+; RV32I-NEXT: call __fixsfsi
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_si_h:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slli a0, a0, 48
+; RV64I-NEXT: srli a0, a0, 48
+; RV64I-NEXT: call __extendhfsf2
+; RV64I-NEXT: call __fixsfdi
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call i16 @llvm.experimental.constrained.fptosi.i16.f16(half %a, metadata !"fpexcept.strict")
ret i16 %1
}
@@ -179,6 +209,30 @@ define i16 @fcvt_ui_h(half %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_ui_h:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: srli a0, a0, 16
+; RV32I-NEXT: call __extendhfsf2
+; RV32I-NEXT: call __fixunssfsi
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_ui_h:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slli a0, a0, 48
+; RV64I-NEXT: srli a0, a0, 48
+; RV64I-NEXT: call __extendhfsf2
+; RV64I-NEXT: call __fixunssfdi
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call i16 @llvm.experimental.constrained.fptoui.i16.f16(half %a, metadata !"fpexcept.strict")
ret i16 %1
}
@@ -241,6 +295,30 @@ define i32 @fcvt_w_h(half %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_w_h:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: srli a0, a0, 16
+; RV32I-NEXT: call __extendhfsf2
+; RV32I-NEXT: call __fixsfsi
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_w_h:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slli a0, a0, 48
+; RV64I-NEXT: srli a0, a0, 48
+; RV64I-NEXT: call __extendhfsf2
+; RV64I-NEXT: call __fixsfdi
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call i32 @llvm.experimental.constrained.fptosi.i32.f16(half %a, metadata !"fpexcept.strict")
ret i32 %1
}
@@ -303,6 +381,30 @@ define i32 @fcvt_wu_h(half %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_wu_h:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: srli a0, a0, 16
+; RV32I-NEXT: call __extendhfsf2
+; RV32I-NEXT: call __fixunssfsi
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_wu_h:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slli a0, a0, 48
+; RV64I-NEXT: srli a0, a0, 48
+; RV64I-NEXT: call __extendhfsf2
+; RV64I-NEXT: call __fixunssfdi
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call i32 @llvm.experimental.constrained.fptoui.i32.f16(half %a, metadata !"fpexcept.strict")
ret i32 %1
}
@@ -390,6 +492,42 @@ define i32 @fcvt_wu_h_multiple_use(half %x, ptr %y) strictfp {
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: .cfi_def_cfa_offset 0
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_wu_h_multiple_use:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: .cfi_def_cfa_offset 16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: .cfi_offset ra, -4
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: srli a0, a0, 16
+; RV32I-NEXT: call __extendhfsf2
+; RV32I-NEXT: call __fixunssfsi
+; RV32I-NEXT: seqz a1, a0
+; RV32I-NEXT: add a0, a0, a1
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: .cfi_restore ra
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: .cfi_def_cfa_offset 0
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_wu_h_multiple_use:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: .cfi_def_cfa_offset 16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: .cfi_offset ra, -8
+; RV64I-NEXT: slli a0, a0, 48
+; RV64I-NEXT: srli a0, a0, 48
+; RV64I-NEXT: call __extendhfsf2
+; RV64I-NEXT: call __fixunssfdi
+; RV64I-NEXT: seqz a1, a0
+; RV64I-NEXT: add a0, a0, a1
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: .cfi_restore ra
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: .cfi_def_cfa_offset 0
+; RV64I-NEXT: ret
%a = call i32 @llvm.experimental.constrained.fptoui.i32.f16(half %x, metadata !"fpexcept.strict")
%b = icmp eq i32 %a, 0
%c = select i1 %b, i32 1, i32 %a
@@ -458,6 +596,28 @@ define i64 @fcvt_l_h(half %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_l_h:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __extendhfsf2
+; RV32I-NEXT: call __fixsfdi
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_l_h:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slli a0, a0, 48
+; RV64I-NEXT: srli a0, a0, 48
+; RV64I-NEXT: call __extendhfsf2
+; RV64I-NEXT: call __fixsfdi
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call i64 @llvm.experimental.constrained.fptosi.i64.f16(half %a, metadata !"fpexcept.strict")
ret i64 %1
}
@@ -524,6 +684,28 @@ define i64 @fcvt_lu_h(half %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_lu_h:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __extendhfsf2
+; RV32I-NEXT: call __fixunssfdi
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_lu_h:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slli a0, a0, 48
+; RV64I-NEXT: srli a0, a0, 48
+; RV64I-NEXT: call __extendhfsf2
+; RV64I-NEXT: call __fixunssfdi
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call i64 @llvm.experimental.constrained.fptoui.i64.f16(half %a, metadata !"fpexcept.strict")
ret i64 %1
}
@@ -604,6 +786,30 @@ define half @fcvt_h_si(i16 %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_si:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: srai a0, a0, 16
+; RV32I-NEXT: call __floatsisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_si:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slli a0, a0, 48
+; RV64I-NEXT: srai a0, a0, 48
+; RV64I-NEXT: call __floatsisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call half @llvm.experimental.constrained.sitofp.f16.i16(i16 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
}
@@ -666,6 +872,26 @@ define half @fcvt_h_si_signext(i16 signext %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_si_signext:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __floatsisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_si_signext:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call __floatsisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call half @llvm.experimental.constrained.sitofp.f16.i16(i16 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
}
@@ -746,6 +972,30 @@ define half @fcvt_h_ui(i16 %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_ui:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: srli a0, a0, 16
+; RV32I-NEXT: call __floatunsisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_ui:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: slli a0, a0, 48
+; RV64I-NEXT: srli a0, a0, 48
+; RV64I-NEXT: call __floatunsisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call half @llvm.experimental.constrained.uitofp.f16.i16(i16 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
}
@@ -808,6 +1058,26 @@ define half @fcvt_h_ui_zeroext(i16 zeroext %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_ui_zeroext:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __floatunsisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_ui_zeroext:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call __floatunsisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call half @llvm.experimental.constrained.uitofp.f16.i16(i16 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
}
@@ -870,6 +1140,27 @@ define half @fcvt_h_w(i32 %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_w:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __floatsisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_w:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sext.w a0, a0
+; RV64I-NEXT: call __floatsisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call half @llvm.experimental.constrained.sitofp.f16.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
}
@@ -941,6 +1232,28 @@ define half @fcvt_h_w_load(ptr %p) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_w_load:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lw a0, 0(a0)
+; RV32I-NEXT: call __floatsisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_w_load:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lw a0, 0(a0)
+; RV64I-NEXT: call __floatsisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%a = load i32, ptr %p
%1 = call half @llvm.experimental.constrained.sitofp.f16.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
@@ -1004,6 +1317,27 @@ define half @fcvt_h_wu(i32 %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_wu:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __floatunsisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_wu:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sext.w a0, a0
+; RV64I-NEXT: call __floatunsisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call half @llvm.experimental.constrained.uitofp.f16.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
}
@@ -1075,6 +1409,28 @@ define half @fcvt_h_wu_load(ptr %p) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_wu_load:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lw a0, 0(a0)
+; RV32I-NEXT: call __floatunsisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_wu_load:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lw a0, 0(a0)
+; RV64I-NEXT: call __floatunsisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%a = load i32, ptr %p
%1 = call half @llvm.experimental.constrained.uitofp.f16.i32(i32 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
@@ -1152,6 +1508,26 @@ define half @fcvt_h_l(i64 %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_l:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __floatdisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_l:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call __floatdisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call half @llvm.experimental.constrained.sitofp.f16.i64(i64 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
}
@@ -1228,6 +1604,26 @@ define half @fcvt_h_lu(i64 %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_lu:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __floatundisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_lu:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call __floatundisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call half @llvm.experimental.constrained.uitofp.f16.i64(i64 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
}
@@ -1285,6 +1681,24 @@ define half @fcvt_h_s(float %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_s:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_s:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call half @llvm.experimental.constrained.fptrunc.f16.f32(float %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
}
@@ -1342,6 +1756,24 @@ define float @fcvt_s_h(half %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_s_h:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __extendhfsf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_s_h:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call __extendhfsf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call float @llvm.experimental.constrained.fpext.f32.f16(half %a, metadata !"fpexcept.strict")
ret float %1
}
@@ -1451,6 +1883,24 @@ define half @fcvt_h_d(double %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_d:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __truncdfhf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_d:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call __truncdfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call half @llvm.experimental.constrained.fptrunc.f16.f64(double %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
}
@@ -1569,6 +2019,26 @@ define double @fcvt_d_h(half %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_d_h:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call __extendhfsf2
+; RV32I-NEXT: call __extendsfdf2
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_d_h:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call __extendhfsf2
+; RV64I-NEXT: call __extendsfdf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call double @llvm.experimental.constrained.fpext.f64.f16(half %a, metadata !"fpexcept.strict")
ret double %1
}
@@ -1661,6 +2131,62 @@ define signext i32 @fcvt_h_w_demanded_bits(i32 signext %0, ptr %1) strictfp {
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: .cfi_def_cfa_offset 0
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_w_demanded_bits:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: .cfi_def_cfa_offset 16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
+; RV32I-NEXT: .cfi_offset ra, -4
+; RV32I-NEXT: .cfi_offset s0, -8
+; RV32I-NEXT: .cfi_offset s1, -12
+; RV32I-NEXT: mv s0, a1
+; RV32I-NEXT: addi s1, a0, 1
+; RV32I-NEXT: mv a0, s1
+; RV32I-NEXT: call __floatsisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: mv a1, a0
+; RV32I-NEXT: mv a0, s1
+; RV32I-NEXT: sh a1, 0(s0)
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
+; RV32I-NEXT: .cfi_restore ra
+; RV32I-NEXT: .cfi_restore s0
+; RV32I-NEXT: .cfi_restore s1
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: .cfi_def_cfa_offset 0
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_w_demanded_bits:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -32
+; RV64I-NEXT: .cfi_def_cfa_offset 32
+; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: .cfi_offset ra, -8
+; RV64I-NEXT: .cfi_offset s0, -16
+; RV64I-NEXT: .cfi_offset s1, -24
+; RV64I-NEXT: mv s0, a1
+; RV64I-NEXT: addiw s1, a0, 1
+; RV64I-NEXT: mv a0, s1
+; RV64I-NEXT: call __floatsisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: mv a1, a0
+; RV64I-NEXT: mv a0, s1
+; RV64I-NEXT: sh a1, 0(s0)
+; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: .cfi_restore ra
+; RV64I-NEXT: .cfi_restore s0
+; RV64I-NEXT: .cfi_restore s1
+; RV64I-NEXT: addi sp, sp, 32
+; RV64I-NEXT: .cfi_def_cfa_offset 0
+; RV64I-NEXT: ret
%3 = add i32 %0, 1
%4 = call half @llvm.experimental.constrained.sitofp.f16.i32(i32 %3, metadata !"round.dynamic", metadata !"fpexcept.strict")
store half %4, ptr %1, align 2
@@ -1755,6 +2281,62 @@ define signext i32 @fcvt_h_wu_demanded_bits(i32 signext %0, ptr %1) strictfp {
; CHECK32-D-NEXT: addi sp, sp, 16
; CHECK32-D-NEXT: .cfi_def_cfa_offset 0
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_wu_demanded_bits:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: .cfi_def_cfa_offset 16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
+; RV32I-NEXT: .cfi_offset ra, -4
+; RV32I-NEXT: .cfi_offset s0, -8
+; RV32I-NEXT: .cfi_offset s1, -12
+; RV32I-NEXT: mv s0, a1
+; RV32I-NEXT: addi s1, a0, 1
+; RV32I-NEXT: mv a0, s1
+; RV32I-NEXT: call __floatunsisf
+; RV32I-NEXT: call __truncsfhf2
+; RV32I-NEXT: mv a1, a0
+; RV32I-NEXT: mv a0, s1
+; RV32I-NEXT: sh a1, 0(s0)
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
+; RV32I-NEXT: .cfi_restore ra
+; RV32I-NEXT: .cfi_restore s0
+; RV32I-NEXT: .cfi_restore s1
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: .cfi_def_cfa_offset 0
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_wu_demanded_bits:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -32
+; RV64I-NEXT: .cfi_def_cfa_offset 32
+; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: .cfi_offset ra, -8
+; RV64I-NEXT: .cfi_offset s0, -16
+; RV64I-NEXT: .cfi_offset s1, -24
+; RV64I-NEXT: mv s0, a1
+; RV64I-NEXT: addiw s1, a0, 1
+; RV64I-NEXT: mv a0, s1
+; RV64I-NEXT: call __floatunsisf
+; RV64I-NEXT: call __truncsfhf2
+; RV64I-NEXT: mv a1, a0
+; RV64I-NEXT: mv a0, s1
+; RV64I-NEXT: sh a1, 0(s0)
+; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: .cfi_restore ra
+; RV64I-NEXT: .cfi_restore s0
+; RV64I-NEXT: .cfi_restore s1
+; RV64I-NEXT: addi sp, sp, 32
+; RV64I-NEXT: .cfi_def_cfa_offset 0
+; RV64I-NEXT: ret
%3 = add i32 %0, 1
%4 = call half @llvm.experimental.constrained.uitofp.f16.i32(i32 %3, metadata !"round.dynamic", metadata !"fpexcept.strict")
store half %4, ptr %1, align 2
@@ -1891,6 +2473,33 @@ define half @fcvt_h_q(fp128 %a) nounwind strictfp {
; CHECK32-D-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 32
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_h_q:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -32
+; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lw a1, 0(a0)
+; RV32I-NEXT: lw a2, 4(a0)
+; RV32I-NEXT: lw a3, 8(a0)
+; RV32I-NEXT: lw a4, 12(a0)
+; RV32I-NEXT: addi a0, sp, 8
+; RV32I-NEXT: sw a1, 8(sp)
+; RV32I-NEXT: sw a2, 12(sp)
+; RV32I-NEXT: sw a3, 16(sp)
+; RV32I-NEXT: sw a4, 20(sp)
+; RV32I-NEXT: call __trunctfhf2
+; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 32
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_h_q:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call __trunctfhf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call half @llvm.experimental.constrained.fptrunc.f16.f128(fp128 %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
ret half %1
}
@@ -2049,6 +2658,40 @@ define fp128 @fcvt_q_h(half %a) nounwind strictfp {
; CHECK32-D-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
; CHECK32-D-NEXT: addi sp, sp, 32
; CHECK32-D-NEXT: ret
+;
+; RV32I-LABEL: fcvt_q_h:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -32
+; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
+; RV32I-NEXT: mv s0, a0
+; RV32I-NEXT: mv a0, a1
+; RV32I-NEXT: call __extendhfsf2
+; RV32I-NEXT: mv a1, a0
+; RV32I-NEXT: addi a0, sp, 8
+; RV32I-NEXT: call __extendsftf2
+; RV32I-NEXT: lw a0, 8(sp)
+; RV32I-NEXT: lw a1, 12(sp)
+; RV32I-NEXT: lw a2, 16(sp)
+; RV32I-NEXT: lw a3, 20(sp)
+; RV32I-NEXT: sw a0, 0(s0)
+; RV32I-NEXT: sw a1, 4(s0)
+; RV32I-NEXT: sw a2, 8(s0)
+; RV32I-NEXT: sw a3, 12(s0)
+; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 32
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: fcvt_q_h:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call __extendhfsf2
+; RV64I-NEXT: call __extendsftf2
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
%1 = call fp128 @llvm.experimental.constrained.fpext.f128.f16(half %a, metadata !"fpexcept.strict")
ret fp128 %1
}
More information about the llvm-commits
mailing list