[llvm] Support STRICT_UINT_TO_FP and STRICT_SINT_TO_FP (PR #102503)

Mikhail R. Gadelha via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 13 07:41:49 PDT 2024


https://github.com/mikhailramalho updated https://github.com/llvm/llvm-project/pull/102503

>From d3a4c180ef70d5a492141ccaca6e573d9fc79a1b Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Thu, 8 Aug 2024 21:01:15 -0300
Subject: [PATCH 1/3] Fix support for strict version of fp to (u)int and (u)int
 to fp

---
 .../SelectionDAG/LegalizeFloatTypes.cpp       | 21 ++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index edebb5ee87001b..fa877c3f348dca 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -3090,6 +3090,8 @@ void DAGTypeLegalizer::SoftPromoteHalfResult(SDNode *N, unsigned ResNo) {
     break;
   case ISD::SELECT:      R = SoftPromoteHalfRes_SELECT(N); break;
   case ISD::SELECT_CC:   R = SoftPromoteHalfRes_SELECT_CC(N); break;
+  case ISD::STRICT_SINT_TO_FP:
+  case ISD::STRICT_UINT_TO_FP:
   case ISD::SINT_TO_FP:
   case ISD::UINT_TO_FP:  R = SoftPromoteHalfRes_XINT_TO_FP(N); break;
   case ISD::UNDEF:       R = SoftPromoteHalfRes_UNDEF(N); break;
@@ -3311,7 +3313,12 @@ SDValue DAGTypeLegalizer::SoftPromoteHalfRes_XINT_TO_FP(SDNode *N) {
   EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
   SDLoc dl(N);
 
-  SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, N->getOperand(0));
+  SDValue Op = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
+
+  bool Signed = N->getOpcode() == ISD::SINT_TO_FP ||
+                N->getOpcode() == ISD::STRICT_SINT_TO_FP;
+  SDValue Res =
+      DAG.getNode(Signed ? ISD::SINT_TO_FP : ISD::UINT_TO_FP, dl, NVT, Op);
 
   // Round the value to the softened type.
   return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
@@ -3396,6 +3403,8 @@ bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
 
   case ISD::BITCAST:    Res = SoftPromoteHalfOp_BITCAST(N); break;
   case ISD::FCOPYSIGN:  Res = SoftPromoteHalfOp_FCOPYSIGN(N, OpNo); break;
+  case ISD::STRICT_FP_TO_SINT:
+  case ISD::STRICT_FP_TO_UINT:
   case ISD::FP_TO_SINT:
   case ISD::FP_TO_UINT: Res = SoftPromoteHalfOp_FP_TO_XINT(N); break;
   case ISD::FP_TO_SINT_SAT:
@@ -3422,8 +3431,7 @@ bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
 
   assert(Res.getNode() != N && "Expected a new node!");
 
-  assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
-         "Invalid operand expansion");
+  assert(Res.getValueType() == N->getValueType(0) && "Invalid operand expansion");
 
   ReplaceValueWith(SDValue(N, 0), Res);
   return false;
@@ -3479,7 +3487,7 @@ SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_EXTEND(SDNode *N) {
 
 SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT(SDNode *N) {
   EVT RVT = N->getValueType(0);
-  SDValue Op = N->getOperand(0);
+  SDValue Op = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
   EVT SVT = Op.getValueType();
   SDLoc dl(N);
 
@@ -3489,7 +3497,10 @@ SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT(SDNode *N) {
 
   SDValue Res = DAG.getNode(GetPromotionOpcode(SVT, RVT), dl, NVT, Op);
 
-  return DAG.getNode(N->getOpcode(), dl, N->getValueType(0), Res);
+  bool Signed = N->getOpcode() == ISD::FP_TO_SINT ||
+                N->getOpcode() == ISD::STRICT_FP_TO_SINT;
+  return DAG.getNode(Signed ? ISD::FP_TO_SINT : ISD::FP_TO_UINT, dl,
+                     N->getValueType(0), Res);
 }
 
 SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT_SAT(SDNode *N) {

>From c9d47ffd8c5d1ace87bca23e7b5b0cc80cb4342f Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Thu, 8 Aug 2024 21:32:49 -0300
Subject: [PATCH 2/3] Format

---
 llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index fa877c3f348dca..3f13d4a6242328 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -3431,7 +3431,8 @@ bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
 
   assert(Res.getNode() != N && "Expected a new node!");
 
-  assert(Res.getValueType() == N->getValueType(0) && "Invalid operand expansion");
+  assert(Res.getValueType() == N->getValueType(0) &&
+         "Invalid operand expansion");
 
   ReplaceValueWith(SDValue(N, 0), Res);
   return false;

>From ac36c4f61fa46381086ef0c926489d6fa1d24779 Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Tue, 13 Aug 2024 11:41:14 -0300
Subject: [PATCH 3/3] Added testcase

---
 .../test/CodeGen/RISCV/half-convert-strict.ll | 360 ++++++++++++++++++
 1 file changed, 360 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/half-convert-strict.ll b/llvm/test/CodeGen/RISCV/half-convert-strict.ll
index 8f88a4c570ea05..4505d335f95560 100644
--- a/llvm/test/CodeGen/RISCV/half-convert-strict.ll
+++ b/llvm/test/CodeGen/RISCV/half-convert-strict.ll
@@ -2165,3 +2165,363 @@ define signext i32 @fcvt_h_wu_demanded_bits(i32 signext %0, ptr %1) strictfp {
   store half %4, ptr %1, align 2
   ret i32 %3
 }
+
+define dso_local void @int_uint_to_half(i32 noundef %p1, i32 noundef %p2) {
+; CHECKIZFH-LABEL: int_uint_to_half:
+; CHECKIZFH:       # %bb.0: # %entry
+; CHECKIZFH-NEXT:    addi sp, sp, -16
+; CHECKIZFH-NEXT:    .cfi_def_cfa_offset 16
+; CHECKIZFH-NEXT:    sw a0, 12(sp)
+; CHECKIZFH-NEXT:    sw a1, 8(sp)
+; CHECKIZFH-NEXT:    fcvt.h.w fa5, a0
+; CHECKIZFH-NEXT:    fsh fa5, 6(sp)
+; CHECKIZFH-NEXT:    fcvt.h.wu fa5, a1
+; CHECKIZFH-NEXT:    fsh fa5, 4(sp)
+; CHECKIZFH-NEXT:    addi sp, sp, 16
+; CHECKIZFH-NEXT:    ret
+;
+; CHECKIZHINX-LABEL: int_uint_to_half:
+; CHECKIZHINX:       # %bb.0: # %entry
+; CHECKIZHINX-NEXT:    addi sp, sp, -16
+; CHECKIZHINX-NEXT:    .cfi_def_cfa_offset 16
+; CHECKIZHINX-NEXT:    sw a0, 12(sp)
+; CHECKIZHINX-NEXT:    sw a1, 8(sp)
+; CHECKIZHINX-NEXT:    fcvt.h.w a0, a0
+; CHECKIZHINX-NEXT:    sh a0, 6(sp)
+; CHECKIZHINX-NEXT:    fcvt.h.wu a0, a1
+; CHECKIZHINX-NEXT:    sh a0, 4(sp)
+; CHECKIZHINX-NEXT:    addi sp, sp, 16
+; CHECKIZHINX-NEXT:    ret
+;
+; RV32IDZFH-LABEL: int_uint_to_half:
+; RV32IDZFH:       # %bb.0: # %entry
+; RV32IDZFH-NEXT:    addi sp, sp, -16
+; RV32IDZFH-NEXT:    .cfi_def_cfa_offset 16
+; RV32IDZFH-NEXT:    sw a0, 12(sp)
+; RV32IDZFH-NEXT:    sw a1, 8(sp)
+; RV32IDZFH-NEXT:    fcvt.h.w fa5, a0
+; RV32IDZFH-NEXT:    fsh fa5, 6(sp)
+; RV32IDZFH-NEXT:    fcvt.h.wu fa5, a1
+; RV32IDZFH-NEXT:    fsh fa5, 4(sp)
+; RV32IDZFH-NEXT:    addi sp, sp, 16
+; RV32IDZFH-NEXT:    ret
+;
+; RV64IDZFH-LABEL: int_uint_to_half:
+; RV64IDZFH:       # %bb.0: # %entry
+; RV64IDZFH-NEXT:    addi sp, sp, -16
+; RV64IDZFH-NEXT:    .cfi_def_cfa_offset 16
+; RV64IDZFH-NEXT:    sw a0, 12(sp)
+; RV64IDZFH-NEXT:    sw a1, 8(sp)
+; RV64IDZFH-NEXT:    fcvt.h.w fa5, a0
+; RV64IDZFH-NEXT:    fsh fa5, 6(sp)
+; RV64IDZFH-NEXT:    fcvt.h.wu fa5, a1
+; RV64IDZFH-NEXT:    fsh fa5, 4(sp)
+; RV64IDZFH-NEXT:    addi sp, sp, 16
+; RV64IDZFH-NEXT:    ret
+;
+; RV32IZDINXZHINX-LABEL: int_uint_to_half:
+; RV32IZDINXZHINX:       # %bb.0: # %entry
+; RV32IZDINXZHINX-NEXT:    addi sp, sp, -16
+; RV32IZDINXZHINX-NEXT:    .cfi_def_cfa_offset 16
+; RV32IZDINXZHINX-NEXT:    sw a0, 12(sp)
+; RV32IZDINXZHINX-NEXT:    sw a1, 8(sp)
+; RV32IZDINXZHINX-NEXT:    fcvt.h.w a0, a0
+; RV32IZDINXZHINX-NEXT:    sh a0, 6(sp)
+; RV32IZDINXZHINX-NEXT:    fcvt.h.wu a0, a1
+; RV32IZDINXZHINX-NEXT:    sh a0, 4(sp)
+; RV32IZDINXZHINX-NEXT:    addi sp, sp, 16
+; RV32IZDINXZHINX-NEXT:    ret
+;
+; RV64IZDINXZHINX-LABEL: int_uint_to_half:
+; RV64IZDINXZHINX:       # %bb.0: # %entry
+; RV64IZDINXZHINX-NEXT:    addi sp, sp, -16
+; RV64IZDINXZHINX-NEXT:    .cfi_def_cfa_offset 16
+; RV64IZDINXZHINX-NEXT:    sw a0, 12(sp)
+; RV64IZDINXZHINX-NEXT:    sw a1, 8(sp)
+; RV64IZDINXZHINX-NEXT:    fcvt.h.w a0, a0
+; RV64IZDINXZHINX-NEXT:    sh a0, 6(sp)
+; RV64IZDINXZHINX-NEXT:    fcvt.h.wu a0, a1
+; RV64IZDINXZHINX-NEXT:    sh a0, 4(sp)
+; RV64IZDINXZHINX-NEXT:    addi sp, sp, 16
+; RV64IZDINXZHINX-NEXT:    ret
+;
+; CHECK32-IZFHMIN-LABEL: int_uint_to_half:
+; CHECK32-IZFHMIN:       # %bb.0: # %entry
+; CHECK32-IZFHMIN-NEXT:    addi sp, sp, -16
+; CHECK32-IZFHMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK32-IZFHMIN-NEXT:    sw a0, 12(sp)
+; CHECK32-IZFHMIN-NEXT:    sw a1, 8(sp)
+; CHECK32-IZFHMIN-NEXT:    fcvt.s.w fa5, a0
+; CHECK32-IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
+; CHECK32-IZFHMIN-NEXT:    fsh fa5, 6(sp)
+; CHECK32-IZFHMIN-NEXT:    fcvt.s.wu fa5, a1
+; CHECK32-IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
+; CHECK32-IZFHMIN-NEXT:    fsh fa5, 4(sp)
+; CHECK32-IZFHMIN-NEXT:    addi sp, sp, 16
+; CHECK32-IZFHMIN-NEXT:    ret
+;
+; CHECK64-IZFHMIN-LABEL: int_uint_to_half:
+; CHECK64-IZFHMIN:       # %bb.0: # %entry
+; CHECK64-IZFHMIN-NEXT:    addi sp, sp, -16
+; CHECK64-IZFHMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK64-IZFHMIN-NEXT:    slli a2, a1, 32
+; CHECK64-IZFHMIN-NEXT:    srli a2, a2, 32
+; CHECK64-IZFHMIN-NEXT:    sext.w a3, a0
+; CHECK64-IZFHMIN-NEXT:    sw a0, 12(sp)
+; CHECK64-IZFHMIN-NEXT:    sw a1, 8(sp)
+; CHECK64-IZFHMIN-NEXT:    fcvt.s.l fa5, a3
+; CHECK64-IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
+; CHECK64-IZFHMIN-NEXT:    fsh fa5, 6(sp)
+; CHECK64-IZFHMIN-NEXT:    fcvt.s.lu fa5, a2
+; CHECK64-IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
+; CHECK64-IZFHMIN-NEXT:    fsh fa5, 4(sp)
+; CHECK64-IZFHMIN-NEXT:    addi sp, sp, 16
+; CHECK64-IZFHMIN-NEXT:    ret
+;
+; CHECK32-IZHINXMIN-LABEL: int_uint_to_half:
+; CHECK32-IZHINXMIN:       # %bb.0: # %entry
+; CHECK32-IZHINXMIN-NEXT:    addi sp, sp, -16
+; CHECK32-IZHINXMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK32-IZHINXMIN-NEXT:    sw a0, 12(sp)
+; CHECK32-IZHINXMIN-NEXT:    sw a1, 8(sp)
+; CHECK32-IZHINXMIN-NEXT:    fcvt.s.w a0, a0
+; CHECK32-IZHINXMIN-NEXT:    fcvt.h.s a0, a0
+; CHECK32-IZHINXMIN-NEXT:    sh a0, 6(sp)
+; CHECK32-IZHINXMIN-NEXT:    fcvt.s.wu a0, a1
+; CHECK32-IZHINXMIN-NEXT:    fcvt.h.s a0, a0
+; CHECK32-IZHINXMIN-NEXT:    sh a0, 4(sp)
+; CHECK32-IZHINXMIN-NEXT:    addi sp, sp, 16
+; CHECK32-IZHINXMIN-NEXT:    ret
+;
+; CHECK64-IZHINXMIN-LABEL: int_uint_to_half:
+; CHECK64-IZHINXMIN:       # %bb.0: # %entry
+; CHECK64-IZHINXMIN-NEXT:    addi sp, sp, -16
+; CHECK64-IZHINXMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK64-IZHINXMIN-NEXT:    slli a2, a1, 32
+; CHECK64-IZHINXMIN-NEXT:    srli a2, a2, 32
+; CHECK64-IZHINXMIN-NEXT:    sext.w a3, a0
+; CHECK64-IZHINXMIN-NEXT:    sw a0, 12(sp)
+; CHECK64-IZHINXMIN-NEXT:    sw a1, 8(sp)
+; CHECK64-IZHINXMIN-NEXT:    fcvt.s.l a0, a3
+; CHECK64-IZHINXMIN-NEXT:    fcvt.h.s a0, a0
+; CHECK64-IZHINXMIN-NEXT:    sh a0, 6(sp)
+; CHECK64-IZHINXMIN-NEXT:    fcvt.s.lu a0, a2
+; CHECK64-IZHINXMIN-NEXT:    fcvt.h.s a0, a0
+; CHECK64-IZHINXMIN-NEXT:    sh a0, 4(sp)
+; CHECK64-IZHINXMIN-NEXT:    addi sp, sp, 16
+; CHECK64-IZHINXMIN-NEXT:    ret
+;
+; CHECK32-IZDINXZHINXMIN-LABEL: int_uint_to_half:
+; CHECK32-IZDINXZHINXMIN:       # %bb.0: # %entry
+; CHECK32-IZDINXZHINXMIN-NEXT:    addi sp, sp, -16
+; CHECK32-IZDINXZHINXMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK32-IZDINXZHINXMIN-NEXT:    sw a0, 12(sp)
+; CHECK32-IZDINXZHINXMIN-NEXT:    sw a1, 8(sp)
+; CHECK32-IZDINXZHINXMIN-NEXT:    fcvt.s.w a0, a0
+; CHECK32-IZDINXZHINXMIN-NEXT:    fcvt.h.s a0, a0
+; CHECK32-IZDINXZHINXMIN-NEXT:    sh a0, 6(sp)
+; CHECK32-IZDINXZHINXMIN-NEXT:    fcvt.s.wu a0, a1
+; CHECK32-IZDINXZHINXMIN-NEXT:    fcvt.h.s a0, a0
+; CHECK32-IZDINXZHINXMIN-NEXT:    sh a0, 4(sp)
+; CHECK32-IZDINXZHINXMIN-NEXT:    addi sp, sp, 16
+; CHECK32-IZDINXZHINXMIN-NEXT:    ret
+;
+; CHECK64-IZDINXZHINXMIN-LABEL: int_uint_to_half:
+; CHECK64-IZDINXZHINXMIN:       # %bb.0: # %entry
+; CHECK64-IZDINXZHINXMIN-NEXT:    addi sp, sp, -16
+; CHECK64-IZDINXZHINXMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK64-IZDINXZHINXMIN-NEXT:    slli a2, a1, 32
+; CHECK64-IZDINXZHINXMIN-NEXT:    srli a2, a2, 32
+; CHECK64-IZDINXZHINXMIN-NEXT:    sext.w a3, a0
+; CHECK64-IZDINXZHINXMIN-NEXT:    sw a0, 12(sp)
+; CHECK64-IZDINXZHINXMIN-NEXT:    sw a1, 8(sp)
+; CHECK64-IZDINXZHINXMIN-NEXT:    fcvt.s.l a0, a3
+; CHECK64-IZDINXZHINXMIN-NEXT:    fcvt.h.s a0, a0
+; CHECK64-IZDINXZHINXMIN-NEXT:    sh a0, 6(sp)
+; CHECK64-IZDINXZHINXMIN-NEXT:    fcvt.s.lu a0, a2
+; CHECK64-IZDINXZHINXMIN-NEXT:    fcvt.h.s a0, a0
+; CHECK64-IZDINXZHINXMIN-NEXT:    sh a0, 4(sp)
+; CHECK64-IZDINXZHINXMIN-NEXT:    addi sp, sp, 16
+; CHECK64-IZDINXZHINXMIN-NEXT:    ret
+entry:
+  %p1.addr = alloca i32, align 4
+  %p2.addr = alloca i32, align 4
+  %f1 = alloca half, align 2
+  %f2 = alloca half, align 2
+  store i32 %p1, ptr %p1.addr, align 4
+  store i32 %p2, ptr %p2.addr, align 4
+  %0 = load i32, ptr %p1.addr, align 4
+  %conv = call half @llvm.experimental.constrained.sitofp.f16.i32(i32 %0, metadata !"round.dynamic", metadata !"fpexcept.ignore") #2
+  store half %conv, ptr %f1, align 2
+  %1 = load i32, ptr %p2.addr, align 4
+  %conv1 = call half @llvm.experimental.constrained.uitofp.f16.i32(i32 %1, metadata !"round.dynamic", metadata !"fpexcept.ignore") #2
+  store half %conv1, ptr %f2, align 2
+  ret void
+}
+
+define dso_local void @half_to_int_uint(half noundef %p1) {
+; CHECKIZFH-LABEL: half_to_int_uint:
+; CHECKIZFH:       # %bb.0: # %entry
+; CHECKIZFH-NEXT:    addi sp, sp, -16
+; CHECKIZFH-NEXT:    .cfi_def_cfa_offset 16
+; CHECKIZFH-NEXT:    fsh fa0, 14(sp)
+; CHECKIZFH-NEXT:    fcvt.w.h a0, fa0, rtz
+; CHECKIZFH-NEXT:    sw a0, 8(sp)
+; CHECKIZFH-NEXT:    fcvt.wu.h a0, fa0, rtz
+; CHECKIZFH-NEXT:    sw a0, 4(sp)
+; CHECKIZFH-NEXT:    addi sp, sp, 16
+; CHECKIZFH-NEXT:    ret
+;
+; CHECKIZHINX-LABEL: half_to_int_uint:
+; CHECKIZHINX:       # %bb.0: # %entry
+; CHECKIZHINX-NEXT:    addi sp, sp, -16
+; CHECKIZHINX-NEXT:    .cfi_def_cfa_offset 16
+; CHECKIZHINX-NEXT:    sh a0, 14(sp)
+; CHECKIZHINX-NEXT:    fcvt.w.h a1, a0, rtz
+; CHECKIZHINX-NEXT:    sw a1, 8(sp)
+; CHECKIZHINX-NEXT:    fcvt.wu.h a0, a0, rtz
+; CHECKIZHINX-NEXT:    sw a0, 4(sp)
+; CHECKIZHINX-NEXT:    addi sp, sp, 16
+; CHECKIZHINX-NEXT:    ret
+;
+; RV32IDZFH-LABEL: half_to_int_uint:
+; RV32IDZFH:       # %bb.0: # %entry
+; RV32IDZFH-NEXT:    addi sp, sp, -16
+; RV32IDZFH-NEXT:    .cfi_def_cfa_offset 16
+; RV32IDZFH-NEXT:    fsh fa0, 14(sp)
+; RV32IDZFH-NEXT:    fcvt.w.h a0, fa0, rtz
+; RV32IDZFH-NEXT:    sw a0, 8(sp)
+; RV32IDZFH-NEXT:    fcvt.wu.h a0, fa0, rtz
+; RV32IDZFH-NEXT:    sw a0, 4(sp)
+; RV32IDZFH-NEXT:    addi sp, sp, 16
+; RV32IDZFH-NEXT:    ret
+;
+; RV64IDZFH-LABEL: half_to_int_uint:
+; RV64IDZFH:       # %bb.0: # %entry
+; RV64IDZFH-NEXT:    addi sp, sp, -16
+; RV64IDZFH-NEXT:    .cfi_def_cfa_offset 16
+; RV64IDZFH-NEXT:    fsh fa0, 14(sp)
+; RV64IDZFH-NEXT:    fcvt.w.h a0, fa0, rtz
+; RV64IDZFH-NEXT:    sw a0, 8(sp)
+; RV64IDZFH-NEXT:    fcvt.wu.h a0, fa0, rtz
+; RV64IDZFH-NEXT:    sw a0, 4(sp)
+; RV64IDZFH-NEXT:    addi sp, sp, 16
+; RV64IDZFH-NEXT:    ret
+;
+; RV32IZDINXZHINX-LABEL: half_to_int_uint:
+; RV32IZDINXZHINX:       # %bb.0: # %entry
+; RV32IZDINXZHINX-NEXT:    addi sp, sp, -16
+; RV32IZDINXZHINX-NEXT:    .cfi_def_cfa_offset 16
+; RV32IZDINXZHINX-NEXT:    sh a0, 14(sp)
+; RV32IZDINXZHINX-NEXT:    fcvt.w.h a1, a0, rtz
+; RV32IZDINXZHINX-NEXT:    sw a1, 8(sp)
+; RV32IZDINXZHINX-NEXT:    fcvt.wu.h a0, a0, rtz
+; RV32IZDINXZHINX-NEXT:    sw a0, 4(sp)
+; RV32IZDINXZHINX-NEXT:    addi sp, sp, 16
+; RV32IZDINXZHINX-NEXT:    ret
+;
+; RV64IZDINXZHINX-LABEL: half_to_int_uint:
+; RV64IZDINXZHINX:       # %bb.0: # %entry
+; RV64IZDINXZHINX-NEXT:    addi sp, sp, -16
+; RV64IZDINXZHINX-NEXT:    .cfi_def_cfa_offset 16
+; RV64IZDINXZHINX-NEXT:    sh a0, 14(sp)
+; RV64IZDINXZHINX-NEXT:    fcvt.w.h a1, a0, rtz
+; RV64IZDINXZHINX-NEXT:    sw a1, 8(sp)
+; RV64IZDINXZHINX-NEXT:    fcvt.wu.h a0, a0, rtz
+; RV64IZDINXZHINX-NEXT:    sw a0, 4(sp)
+; RV64IZDINXZHINX-NEXT:    addi sp, sp, 16
+; RV64IZDINXZHINX-NEXT:    ret
+;
+; CHECK32-IZFHMIN-LABEL: half_to_int_uint:
+; CHECK32-IZFHMIN:       # %bb.0: # %entry
+; CHECK32-IZFHMIN-NEXT:    addi sp, sp, -16
+; CHECK32-IZFHMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK32-IZFHMIN-NEXT:    fsh fa0, 14(sp)
+; CHECK32-IZFHMIN-NEXT:    fcvt.s.h fa5, fa0
+; CHECK32-IZFHMIN-NEXT:    fcvt.w.s a0, fa5, rtz
+; CHECK32-IZFHMIN-NEXT:    sw a0, 8(sp)
+; CHECK32-IZFHMIN-NEXT:    fcvt.wu.s a0, fa5, rtz
+; CHECK32-IZFHMIN-NEXT:    sw a0, 4(sp)
+; CHECK32-IZFHMIN-NEXT:    addi sp, sp, 16
+; CHECK32-IZFHMIN-NEXT:    ret
+;
+; CHECK64-IZFHMIN-LABEL: half_to_int_uint:
+; CHECK64-IZFHMIN:       # %bb.0: # %entry
+; CHECK64-IZFHMIN-NEXT:    addi sp, sp, -16
+; CHECK64-IZFHMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK64-IZFHMIN-NEXT:    fsh fa0, 14(sp)
+; CHECK64-IZFHMIN-NEXT:    fcvt.s.h fa5, fa0
+; CHECK64-IZFHMIN-NEXT:    fcvt.w.s a0, fa5, rtz
+; CHECK64-IZFHMIN-NEXT:    sw a0, 8(sp)
+; CHECK64-IZFHMIN-NEXT:    fcvt.s.h fa5, fa0
+; CHECK64-IZFHMIN-NEXT:    fcvt.wu.s a0, fa5, rtz
+; CHECK64-IZFHMIN-NEXT:    sw a0, 4(sp)
+; CHECK64-IZFHMIN-NEXT:    addi sp, sp, 16
+; CHECK64-IZFHMIN-NEXT:    ret
+;
+; CHECK32-IZHINXMIN-LABEL: half_to_int_uint:
+; CHECK32-IZHINXMIN:       # %bb.0: # %entry
+; CHECK32-IZHINXMIN-NEXT:    addi sp, sp, -16
+; CHECK32-IZHINXMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK32-IZHINXMIN-NEXT:    sh a0, 14(sp)
+; CHECK32-IZHINXMIN-NEXT:    fcvt.s.h a0, a0
+; CHECK32-IZHINXMIN-NEXT:    fcvt.w.s a1, a0, rtz
+; CHECK32-IZHINXMIN-NEXT:    sw a1, 8(sp)
+; CHECK32-IZHINXMIN-NEXT:    fcvt.wu.s a0, a0, rtz
+; CHECK32-IZHINXMIN-NEXT:    sw a0, 4(sp)
+; CHECK32-IZHINXMIN-NEXT:    addi sp, sp, 16
+; CHECK32-IZHINXMIN-NEXT:    ret
+;
+; CHECK64-IZHINXMIN-LABEL: half_to_int_uint:
+; CHECK64-IZHINXMIN:       # %bb.0: # %entry
+; CHECK64-IZHINXMIN-NEXT:    addi sp, sp, -16
+; CHECK64-IZHINXMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK64-IZHINXMIN-NEXT:    sh a0, 14(sp)
+; CHECK64-IZHINXMIN-NEXT:    fcvt.s.h a1, a0
+; CHECK64-IZHINXMIN-NEXT:    fcvt.w.s a1, a1, rtz
+; CHECK64-IZHINXMIN-NEXT:    sw a1, 8(sp)
+; CHECK64-IZHINXMIN-NEXT:    fcvt.s.h a0, a0
+; CHECK64-IZHINXMIN-NEXT:    fcvt.wu.s a0, a0, rtz
+; CHECK64-IZHINXMIN-NEXT:    sw a0, 4(sp)
+; CHECK64-IZHINXMIN-NEXT:    addi sp, sp, 16
+; CHECK64-IZHINXMIN-NEXT:    ret
+;
+; CHECK32-IZDINXZHINXMIN-LABEL: half_to_int_uint:
+; CHECK32-IZDINXZHINXMIN:       # %bb.0: # %entry
+; CHECK32-IZDINXZHINXMIN-NEXT:    addi sp, sp, -16
+; CHECK32-IZDINXZHINXMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK32-IZDINXZHINXMIN-NEXT:    sh a0, 14(sp)
+; CHECK32-IZDINXZHINXMIN-NEXT:    fcvt.s.h a0, a0
+; CHECK32-IZDINXZHINXMIN-NEXT:    fcvt.w.s a1, a0, rtz
+; CHECK32-IZDINXZHINXMIN-NEXT:    sw a1, 8(sp)
+; CHECK32-IZDINXZHINXMIN-NEXT:    fcvt.wu.s a0, a0, rtz
+; CHECK32-IZDINXZHINXMIN-NEXT:    sw a0, 4(sp)
+; CHECK32-IZDINXZHINXMIN-NEXT:    addi sp, sp, 16
+; CHECK32-IZDINXZHINXMIN-NEXT:    ret
+;
+; CHECK64-IZDINXZHINXMIN-LABEL: half_to_int_uint:
+; CHECK64-IZDINXZHINXMIN:       # %bb.0: # %entry
+; CHECK64-IZDINXZHINXMIN-NEXT:    addi sp, sp, -16
+; CHECK64-IZDINXZHINXMIN-NEXT:    .cfi_def_cfa_offset 16
+; CHECK64-IZDINXZHINXMIN-NEXT:    sh a0, 14(sp)
+; CHECK64-IZDINXZHINXMIN-NEXT:    fcvt.s.h a1, a0
+; CHECK64-IZDINXZHINXMIN-NEXT:    fcvt.w.s a1, a1, rtz
+; CHECK64-IZDINXZHINXMIN-NEXT:    sw a1, 8(sp)
+; CHECK64-IZDINXZHINXMIN-NEXT:    fcvt.s.h a0, a0
+; CHECK64-IZDINXZHINXMIN-NEXT:    fcvt.wu.s a0, a0, rtz
+; CHECK64-IZDINXZHINXMIN-NEXT:    sw a0, 4(sp)
+; CHECK64-IZDINXZHINXMIN-NEXT:    addi sp, sp, 16
+; CHECK64-IZDINXZHINXMIN-NEXT:    ret
+entry:
+  %p1.addr = alloca half, align 2
+  %i1 = alloca i32, align 4
+  %i2 = alloca i32, align 4
+  store half %p1, ptr %p1.addr, align 2
+  %0 = load half, ptr %p1.addr, align 2
+  %conv = call i32 @llvm.experimental.constrained.fptosi.i32.f16(half %0, metadata !"fpexcept.ignore") #2
+  store i32 %conv, ptr %i1, align 4
+  %1 = load half, ptr %p1.addr, align 2
+  %conv1 = call i32 @llvm.experimental.constrained.fptoui.i32.f16(half %1, metadata !"fpexcept.ignore") #2
+  store i32 %conv1, ptr %i2, align 4
+  ret void
+}



More information about the llvm-commits mailing list