[llvm] [RISCV] Custom legalize f16/bf16 FCOPYSIGN with Zfhmin/Zbfmin. (PR #107039)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 2 19:15:52 PDT 2024


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

The LegalizeDAG expansion will go through memory since i16 isn't a legal type. Avoid this by using FMV nodes.

Similar to what we did for #106886 for FNEG and FABS. Special care is needed to handle the Sign operand being a different type.

>From 8529580d9888c8663c9fbb2673da3abf8bad82ba Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Mon, 2 Sep 2024 18:44:12 -0700
Subject: [PATCH] [RISCV] Custom legalize f16/bf16 FCOPYSIGN with
 Zfhmin/Zbfmin.

The LegalizeDAG expansion will go through memory since i16 isn't a legal
type. Avoid this by using FMV nodes.

Similar to what we did for #106886 for FNEG and FABS. Special care
is needed to handle the Sign operand being a different type.
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  69 ++++-
 llvm/test/CodeGen/RISCV/bfloat-arith.ll       |  98 ++-----
 llvm/test/CodeGen/RISCV/copysign-casts.ll     | 120 +++------
 llvm/test/CodeGen/RISCV/half-arith.ll         | 246 +++++-------------
 .../RISCV/half-bitmanip-dagcombines.ll        |  66 +----
 llvm/test/CodeGen/RISCV/half-intrinsics.ll    |  66 ++---
 6 files changed, 235 insertions(+), 430 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 250d1c60b9f59e..f50d378ed97aa6 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -459,7 +459,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::FREM, MVT::bf16, Promote);
     setOperationAction(ISD::FABS, MVT::bf16, Custom);
     setOperationAction(ISD::FNEG, MVT::bf16, Custom);
-    setOperationAction(ISD::FCOPYSIGN, MVT::bf16, Expand);
+    setOperationAction(ISD::FCOPYSIGN, MVT::bf16, Custom);
   }
 
   if (Subtarget.hasStdExtZfhminOrZhinxmin()) {
@@ -477,7 +477,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
         setOperationAction(Op, MVT::f16, Custom);
       setOperationAction(ISD::FABS, MVT::f16, Custom);
       setOperationAction(ISD::FNEG, MVT::f16, Custom);
-      setOperationAction(ISD::FCOPYSIGN, MVT::f16, Expand);
+      setOperationAction(ISD::FCOPYSIGN, MVT::f16, Custom);
     }
 
     setOperationAction(ISD::STRICT_FP_ROUND, MVT::f16, Legal);
@@ -5964,6 +5964,69 @@ static SDValue lowerFABSorFNEG(SDValue Op, SelectionDAG &DAG,
   return DAG.getNode(RISCVISD::FMV_H_X, DL, VT, Logic);
 }
 
+static SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG,
+                              const RISCVSubtarget &Subtarget) {
+  assert(Op.getOpcode() == ISD::FCOPYSIGN && "Unexpected opcode");
+
+  MVT XLenVT = Subtarget.getXLenVT();
+  MVT VT = Op.getSimpleValueType();
+  assert((VT == MVT::f16 || VT == MVT::bf16) && "Unexpected type");
+
+  SDValue Mag = Op.getOperand(0);
+  SDValue Sign = Op.getOperand(1);
+
+  SDLoc DL(Op);
+
+  // Get sign bit into an integer value.
+  SDValue SignAsInt;
+  unsigned SignSize = Sign.getValueSizeInBits();
+  if (SignSize == Subtarget.getXLen()) {
+    SignAsInt = DAG.getNode(ISD::BITCAST, DL, XLenVT, Sign);
+  } else if (SignSize == 16) {
+    SignAsInt = DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, Sign);
+  } else if (SignSize == 32) {
+    SignAsInt = DAG.getNode(RISCVISD::FMV_X_ANYEXTW_RV64, DL, XLenVT, Sign);
+  } else if (SignSize == 64) {
+    assert(XLenVT == MVT::i32 && "Unexpected type");
+    // Copy the upper word to integer.
+    SignAsInt = DAG.getNode(RISCVISD::SplitF64, DL, {MVT::i32, MVT::i32}, Sign)
+                    .getValue(1);
+    SignSize = 32;
+  } else
+    llvm_unreachable("Unexpected sign size");
+
+  // Get the signbit at the right position for MagAsInt.
+  int ShiftAmount = (int)SignSize - (int)Mag.getValueSizeInBits();
+  if (ShiftAmount > 0) {
+    SignAsInt = DAG.getNode(ISD::SRL, DL, XLenVT, SignAsInt,
+                            DAG.getConstant(ShiftAmount, DL, XLenVT));
+  } else if (ShiftAmount < 0) {
+    SignAsInt = DAG.getNode(ISD::SHL, DL, XLenVT, SignAsInt,
+                            DAG.getConstant(-ShiftAmount, DL, XLenVT));
+  }
+
+  // Mask the sign bit and any bits above it. The extra bits will be dropped
+  // when we convert back to FP.
+  SDValue SignMask = DAG.getConstant(
+      APInt::getSignMask(16).sext(Subtarget.getXLen()), DL, XLenVT);
+  SDValue SignBit = DAG.getNode(ISD::AND, DL, XLenVT, SignAsInt, SignMask);
+
+  // Transform Mag value to integer, and clear the sign bit.
+  SDValue MagAsInt = DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, Mag);
+  SDValue ClearSignMask = DAG.getConstant(
+      APInt::getSignedMaxValue(16).sext(Subtarget.getXLen()), DL, XLenVT);
+  SDValue ClearedSign =
+      DAG.getNode(ISD::AND, DL, XLenVT, MagAsInt, ClearSignMask);
+
+  SDNodeFlags Flags;
+  Flags.setDisjoint(true);
+
+  SDValue CopiedSign =
+      DAG.getNode(ISD::OR, DL, XLenVT, ClearedSign, SignBit, Flags);
+
+  return DAG.getNode(RISCVISD::FMV_H_X, DL, VT, CopiedSign);
+}
+
 /// Get a RISC-V target specified VL op for a given SDNode.
 static unsigned getRISCVVLOp(SDValue Op) {
 #define OP_CASE(NODE)                                                          \
@@ -7164,6 +7227,8 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
   case ISD::VSELECT:
     return lowerFixedLengthVectorSelectToRVV(Op, DAG);
   case ISD::FCOPYSIGN:
+    if (Op.getValueType() == MVT::f16 || Op.getValueType() == MVT::bf16)
+      return lowerFCOPYSIGN(Op, DAG, Subtarget);
     if (Op.getValueType() == MVT::nxv32f16 &&
         (Subtarget.hasVInstructionsF16Minimal() &&
          !Subtarget.hasVInstructionsF16()))
diff --git a/llvm/test/CodeGen/RISCV/bfloat-arith.ll b/llvm/test/CodeGen/RISCV/bfloat-arith.ll
index 965d7e0132e60b..b688af4234e65a 100644
--- a/llvm/test/CodeGen/RISCV/bfloat-arith.ll
+++ b/llvm/test/CodeGen/RISCV/bfloat-arith.ll
@@ -73,42 +73,26 @@ declare bfloat @llvm.copysign.bf16(bfloat, bfloat)
 define bfloat @fsgnj_bf16(bfloat %a, bfloat %b) nounwind {
 ; RV32IZFBFMIN-LABEL: fsgnj_bf16:
 ; RV32IZFBFMIN:       # %bb.0:
-; RV32IZFBFMIN-NEXT:    addi sp, sp, -16
-; RV32IZFBFMIN-NEXT:    fsh fa1, 12(sp)
-; RV32IZFBFMIN-NEXT:    lbu a0, 13(sp)
+; RV32IZFBFMIN-NEXT:    fmv.x.h a0, fa1
+; RV32IZFBFMIN-NEXT:    lui a1, 1048568
+; RV32IZFBFMIN-NEXT:    and a0, a0, a1
 ; RV32IZFBFMIN-NEXT:    fmv.x.h a1, fa0
 ; RV32IZFBFMIN-NEXT:    slli a1, a1, 17
-; RV32IZFBFMIN-NEXT:    andi a2, a0, 128
-; RV32IZFBFMIN-NEXT:    srli a0, a1, 17
-; RV32IZFBFMIN-NEXT:    beqz a2, .LBB5_2
-; RV32IZFBFMIN-NEXT:  # %bb.1:
-; RV32IZFBFMIN-NEXT:    lui a1, 1048568
-; RV32IZFBFMIN-NEXT:    or a0, a0, a1
-; RV32IZFBFMIN-NEXT:  .LBB5_2:
-; RV32IZFBFMIN-NEXT:    fmv.h.x fa5, a0
-; RV32IZFBFMIN-NEXT:    fcvt.s.bf16 fa5, fa5
-; RV32IZFBFMIN-NEXT:    fcvt.bf16.s fa0, fa5
-; RV32IZFBFMIN-NEXT:    addi sp, sp, 16
+; RV32IZFBFMIN-NEXT:    srli a1, a1, 17
+; RV32IZFBFMIN-NEXT:    or a0, a1, a0
+; RV32IZFBFMIN-NEXT:    fmv.h.x fa0, a0
 ; RV32IZFBFMIN-NEXT:    ret
 ;
 ; RV64IZFBFMIN-LABEL: fsgnj_bf16:
 ; RV64IZFBFMIN:       # %bb.0:
-; RV64IZFBFMIN-NEXT:    addi sp, sp, -16
-; RV64IZFBFMIN-NEXT:    fsh fa1, 8(sp)
-; RV64IZFBFMIN-NEXT:    lbu a0, 9(sp)
+; RV64IZFBFMIN-NEXT:    fmv.x.h a0, fa1
+; RV64IZFBFMIN-NEXT:    lui a1, 1048568
+; RV64IZFBFMIN-NEXT:    and a0, a0, a1
 ; RV64IZFBFMIN-NEXT:    fmv.x.h a1, fa0
 ; RV64IZFBFMIN-NEXT:    slli a1, a1, 49
-; RV64IZFBFMIN-NEXT:    andi a2, a0, 128
-; RV64IZFBFMIN-NEXT:    srli a0, a1, 49
-; RV64IZFBFMIN-NEXT:    beqz a2, .LBB5_2
-; RV64IZFBFMIN-NEXT:  # %bb.1:
-; RV64IZFBFMIN-NEXT:    lui a1, 1048568
-; RV64IZFBFMIN-NEXT:    or a0, a0, a1
-; RV64IZFBFMIN-NEXT:  .LBB5_2:
-; RV64IZFBFMIN-NEXT:    fmv.h.x fa5, a0
-; RV64IZFBFMIN-NEXT:    fcvt.s.bf16 fa5, fa5
-; RV64IZFBFMIN-NEXT:    fcvt.bf16.s fa0, fa5
-; RV64IZFBFMIN-NEXT:    addi sp, sp, 16
+; RV64IZFBFMIN-NEXT:    srli a1, a1, 49
+; RV64IZFBFMIN-NEXT:    or a0, a1, a0
+; RV64IZFBFMIN-NEXT:    fmv.h.x fa0, a0
 ; RV64IZFBFMIN-NEXT:    ret
   %1 = call bfloat @llvm.copysign.bf16(bfloat %a, bfloat %b)
   ret bfloat %1
@@ -138,62 +122,36 @@ define i32 @fneg_bf16(bfloat %a, bfloat %b) nounwind {
 define bfloat @fsgnjn_bf16(bfloat %a, bfloat %b) nounwind {
 ; RV32IZFBFMIN-LABEL: fsgnjn_bf16:
 ; RV32IZFBFMIN:       # %bb.0:
-; RV32IZFBFMIN-NEXT:    addi sp, sp, -16
 ; RV32IZFBFMIN-NEXT:    fcvt.s.bf16 fa5, fa1
 ; RV32IZFBFMIN-NEXT:    fcvt.s.bf16 fa4, fa0
 ; RV32IZFBFMIN-NEXT:    fadd.s fa5, fa4, fa5
 ; RV32IZFBFMIN-NEXT:    fcvt.bf16.s fa5, fa5
-; RV32IZFBFMIN-NEXT:    fmv.x.h a1, fa5
-; RV32IZFBFMIN-NEXT:    lui a0, 1048568
-; RV32IZFBFMIN-NEXT:    xor a1, a1, a0
-; RV32IZFBFMIN-NEXT:    fmv.h.x fa5, a1
-; RV32IZFBFMIN-NEXT:    fsh fa5, 12(sp)
-; RV32IZFBFMIN-NEXT:    lbu a1, 13(sp)
-; RV32IZFBFMIN-NEXT:    fmv.x.h a2, fa0
-; RV32IZFBFMIN-NEXT:    slli a2, a2, 17
-; RV32IZFBFMIN-NEXT:    andi a3, a1, 128
-; RV32IZFBFMIN-NEXT:    srli a1, a2, 17
-; RV32IZFBFMIN-NEXT:    bnez a3, .LBB7_2
-; RV32IZFBFMIN-NEXT:  # %bb.1:
-; RV32IZFBFMIN-NEXT:    fmv.h.x fa5, a1
-; RV32IZFBFMIN-NEXT:    j .LBB7_3
-; RV32IZFBFMIN-NEXT:  .LBB7_2:
+; RV32IZFBFMIN-NEXT:    fmv.x.h a0, fa5
+; RV32IZFBFMIN-NEXT:    not a0, a0
+; RV32IZFBFMIN-NEXT:    lui a1, 1048568
+; RV32IZFBFMIN-NEXT:    and a0, a0, a1
+; RV32IZFBFMIN-NEXT:    fmv.x.h a1, fa0
+; RV32IZFBFMIN-NEXT:    slli a1, a1, 17
+; RV32IZFBFMIN-NEXT:    srli a1, a1, 17
 ; RV32IZFBFMIN-NEXT:    or a0, a1, a0
-; RV32IZFBFMIN-NEXT:    fmv.h.x fa5, a0
-; RV32IZFBFMIN-NEXT:  .LBB7_3:
-; RV32IZFBFMIN-NEXT:    fcvt.s.bf16 fa5, fa5
-; RV32IZFBFMIN-NEXT:    fcvt.bf16.s fa0, fa5
-; RV32IZFBFMIN-NEXT:    addi sp, sp, 16
+; RV32IZFBFMIN-NEXT:    fmv.h.x fa0, a0
 ; RV32IZFBFMIN-NEXT:    ret
 ;
 ; RV64IZFBFMIN-LABEL: fsgnjn_bf16:
 ; RV64IZFBFMIN:       # %bb.0:
-; RV64IZFBFMIN-NEXT:    addi sp, sp, -16
 ; RV64IZFBFMIN-NEXT:    fcvt.s.bf16 fa5, fa1
 ; RV64IZFBFMIN-NEXT:    fcvt.s.bf16 fa4, fa0
 ; RV64IZFBFMIN-NEXT:    fadd.s fa5, fa4, fa5
 ; RV64IZFBFMIN-NEXT:    fcvt.bf16.s fa5, fa5
-; RV64IZFBFMIN-NEXT:    fmv.x.h a1, fa5
-; RV64IZFBFMIN-NEXT:    lui a0, 1048568
-; RV64IZFBFMIN-NEXT:    xor a1, a1, a0
-; RV64IZFBFMIN-NEXT:    fmv.h.x fa5, a1
-; RV64IZFBFMIN-NEXT:    fsh fa5, 8(sp)
-; RV64IZFBFMIN-NEXT:    lbu a1, 9(sp)
-; RV64IZFBFMIN-NEXT:    fmv.x.h a2, fa0
-; RV64IZFBFMIN-NEXT:    slli a2, a2, 49
-; RV64IZFBFMIN-NEXT:    andi a3, a1, 128
-; RV64IZFBFMIN-NEXT:    srli a1, a2, 49
-; RV64IZFBFMIN-NEXT:    bnez a3, .LBB7_2
-; RV64IZFBFMIN-NEXT:  # %bb.1:
-; RV64IZFBFMIN-NEXT:    fmv.h.x fa5, a1
-; RV64IZFBFMIN-NEXT:    j .LBB7_3
-; RV64IZFBFMIN-NEXT:  .LBB7_2:
+; RV64IZFBFMIN-NEXT:    fmv.x.h a0, fa5
+; RV64IZFBFMIN-NEXT:    not a0, a0
+; RV64IZFBFMIN-NEXT:    lui a1, 1048568
+; RV64IZFBFMIN-NEXT:    and a0, a0, a1
+; RV64IZFBFMIN-NEXT:    fmv.x.h a1, fa0
+; RV64IZFBFMIN-NEXT:    slli a1, a1, 49
+; RV64IZFBFMIN-NEXT:    srli a1, a1, 49
 ; RV64IZFBFMIN-NEXT:    or a0, a1, a0
-; RV64IZFBFMIN-NEXT:    fmv.h.x fa5, a0
-; RV64IZFBFMIN-NEXT:  .LBB7_3:
-; RV64IZFBFMIN-NEXT:    fcvt.s.bf16 fa5, fa5
-; RV64IZFBFMIN-NEXT:    fcvt.bf16.s fa0, fa5
-; RV64IZFBFMIN-NEXT:    addi sp, sp, 16
+; RV64IZFBFMIN-NEXT:    fmv.h.x fa0, a0
 ; RV64IZFBFMIN-NEXT:    ret
   %1 = fadd bfloat %a, %b
   %2 = fneg bfloat %1
diff --git a/llvm/test/CodeGen/RISCV/copysign-casts.ll b/llvm/test/CodeGen/RISCV/copysign-casts.ll
index 12c35b87dc6771..d8019c0ad61123 100644
--- a/llvm/test/CodeGen/RISCV/copysign-casts.ll
+++ b/llvm/test/CodeGen/RISCV/copysign-casts.ll
@@ -503,54 +503,38 @@ define half @fold_demote_h_s(half %a, float %b) nounwind {
 ;
 ; RV32IFZFHMIN-LABEL: fold_demote_h_s:
 ; RV32IFZFHMIN:       # %bb.0:
-; RV32IFZFHMIN-NEXT:    fmv.x.h a0, fa0
-; RV32IFZFHMIN-NEXT:    slli a0, a0, 17
-; RV32IFZFHMIN-NEXT:    fmv.x.w a1, fa1
-; RV32IFZFHMIN-NEXT:    srli a0, a0, 17
-; RV32IFZFHMIN-NEXT:    bgez a1, .LBB4_2
-; RV32IFZFHMIN-NEXT:  # %bb.1:
-; RV32IFZFHMIN-NEXT:    lui a1, 1048568
-; RV32IFZFHMIN-NEXT:    or a0, a0, a1
-; RV32IFZFHMIN-NEXT:  .LBB4_2:
-; RV32IFZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV32IFZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV32IFZFHMIN-NEXT:    fcvt.h.s fa0, fa5
+; RV32IFZFHMIN-NEXT:    fmv.x.w a0, fa1
+; RV32IFZFHMIN-NEXT:    srli a0, a0, 31
+; RV32IFZFHMIN-NEXT:    slli a0, a0, 15
+; RV32IFZFHMIN-NEXT:    fmv.x.h a1, fa0
+; RV32IFZFHMIN-NEXT:    slli a1, a1, 17
+; RV32IFZFHMIN-NEXT:    srli a1, a1, 17
+; RV32IFZFHMIN-NEXT:    or a0, a1, a0
+; RV32IFZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV32IFZFHMIN-NEXT:    ret
 ;
 ; RV32IFDZFHMIN-LABEL: fold_demote_h_s:
 ; RV32IFDZFHMIN:       # %bb.0:
-; RV32IFDZFHMIN-NEXT:    fmv.x.h a0, fa0
-; RV32IFDZFHMIN-NEXT:    slli a0, a0, 17
-; RV32IFDZFHMIN-NEXT:    fmv.x.w a1, fa1
-; RV32IFDZFHMIN-NEXT:    srli a0, a0, 17
-; RV32IFDZFHMIN-NEXT:    bgez a1, .LBB4_2
-; RV32IFDZFHMIN-NEXT:  # %bb.1:
-; RV32IFDZFHMIN-NEXT:    lui a1, 1048568
-; RV32IFDZFHMIN-NEXT:    or a0, a0, a1
-; RV32IFDZFHMIN-NEXT:  .LBB4_2:
-; RV32IFDZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV32IFDZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV32IFDZFHMIN-NEXT:    fcvt.h.s fa0, fa5
+; RV32IFDZFHMIN-NEXT:    fmv.x.w a0, fa1
+; RV32IFDZFHMIN-NEXT:    srli a0, a0, 31
+; RV32IFDZFHMIN-NEXT:    slli a0, a0, 15
+; RV32IFDZFHMIN-NEXT:    fmv.x.h a1, fa0
+; RV32IFDZFHMIN-NEXT:    slli a1, a1, 17
+; RV32IFDZFHMIN-NEXT:    srli a1, a1, 17
+; RV32IFDZFHMIN-NEXT:    or a0, a1, a0
+; RV32IFDZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV32IFDZFHMIN-NEXT:    ret
 ;
 ; RV64IFDZFHMIN-LABEL: fold_demote_h_s:
 ; RV64IFDZFHMIN:       # %bb.0:
-; RV64IFDZFHMIN-NEXT:    addi sp, sp, -16
-; RV64IFDZFHMIN-NEXT:    fsw fa1, 8(sp)
-; RV64IFDZFHMIN-NEXT:    lbu a0, 11(sp)
+; RV64IFDZFHMIN-NEXT:    fmv.x.w a0, fa1
+; RV64IFDZFHMIN-NEXT:    srli a0, a0, 31
+; RV64IFDZFHMIN-NEXT:    slli a0, a0, 15
 ; RV64IFDZFHMIN-NEXT:    fmv.x.h a1, fa0
 ; RV64IFDZFHMIN-NEXT:    slli a1, a1, 49
-; RV64IFDZFHMIN-NEXT:    andi a2, a0, 128
-; RV64IFDZFHMIN-NEXT:    srli a0, a1, 49
-; RV64IFDZFHMIN-NEXT:    beqz a2, .LBB4_2
-; RV64IFDZFHMIN-NEXT:  # %bb.1:
-; RV64IFDZFHMIN-NEXT:    lui a1, 1048568
-; RV64IFDZFHMIN-NEXT:    or a0, a0, a1
-; RV64IFDZFHMIN-NEXT:  .LBB4_2:
-; RV64IFDZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV64IFDZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV64IFDZFHMIN-NEXT:    fcvt.h.s fa0, fa5
-; RV64IFDZFHMIN-NEXT:    addi sp, sp, 16
+; RV64IFDZFHMIN-NEXT:    srli a1, a1, 49
+; RV64IFDZFHMIN-NEXT:    or a0, a1, a0
+; RV64IFDZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV64IFDZFHMIN-NEXT:    ret
   %c = fptrunc float %b to half
   %t = call half @llvm.copysign.f16(half %a, half %c)
@@ -646,60 +630,40 @@ define half @fold_demote_h_d(half %a, double %b) nounwind {
 ;
 ; RV32IFZFHMIN-LABEL: fold_demote_h_d:
 ; RV32IFZFHMIN:       # %bb.0:
-; RV32IFZFHMIN-NEXT:    addi sp, sp, -16
-; RV32IFZFHMIN-NEXT:    srli a1, a1, 16
-; RV32IFZFHMIN-NEXT:    fmv.h.x fa5, a1
-; RV32IFZFHMIN-NEXT:    fsh fa5, 12(sp)
-; RV32IFZFHMIN-NEXT:    lbu a0, 13(sp)
-; RV32IFZFHMIN-NEXT:    fmv.x.h a1, fa0
-; RV32IFZFHMIN-NEXT:    slli a1, a1, 17
-; RV32IFZFHMIN-NEXT:    andi a2, a0, 128
-; RV32IFZFHMIN-NEXT:    srli a0, a1, 17
-; RV32IFZFHMIN-NEXT:    beqz a2, .LBB5_2
-; RV32IFZFHMIN-NEXT:  # %bb.1:
-; RV32IFZFHMIN-NEXT:    lui a1, 1048568
+; RV32IFZFHMIN-NEXT:    srli a1, a1, 31
+; RV32IFZFHMIN-NEXT:    slli a1, a1, 15
+; RV32IFZFHMIN-NEXT:    fmv.x.h a0, fa0
+; RV32IFZFHMIN-NEXT:    slli a0, a0, 17
+; RV32IFZFHMIN-NEXT:    srli a0, a0, 17
 ; RV32IFZFHMIN-NEXT:    or a0, a0, a1
-; RV32IFZFHMIN-NEXT:  .LBB5_2:
-; RV32IFZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV32IFZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV32IFZFHMIN-NEXT:    fcvt.h.s fa0, fa5
-; RV32IFZFHMIN-NEXT:    addi sp, sp, 16
+; RV32IFZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV32IFZFHMIN-NEXT:    ret
 ;
 ; RV32IFDZFHMIN-LABEL: fold_demote_h_d:
 ; RV32IFDZFHMIN:       # %bb.0:
 ; RV32IFDZFHMIN-NEXT:    addi sp, sp, -16
 ; RV32IFDZFHMIN-NEXT:    fsd fa1, 8(sp)
-; RV32IFDZFHMIN-NEXT:    lbu a0, 15(sp)
+; RV32IFDZFHMIN-NEXT:    lw a0, 12(sp)
+; RV32IFDZFHMIN-NEXT:    srli a0, a0, 31
+; RV32IFDZFHMIN-NEXT:    slli a0, a0, 15
 ; RV32IFDZFHMIN-NEXT:    fmv.x.h a1, fa0
 ; RV32IFDZFHMIN-NEXT:    slli a1, a1, 17
-; RV32IFDZFHMIN-NEXT:    andi a2, a0, 128
-; RV32IFDZFHMIN-NEXT:    srli a0, a1, 17
-; RV32IFDZFHMIN-NEXT:    beqz a2, .LBB5_2
-; RV32IFDZFHMIN-NEXT:  # %bb.1:
-; RV32IFDZFHMIN-NEXT:    lui a1, 1048568
-; RV32IFDZFHMIN-NEXT:    or a0, a0, a1
-; RV32IFDZFHMIN-NEXT:  .LBB5_2:
-; RV32IFDZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV32IFDZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV32IFDZFHMIN-NEXT:    fcvt.h.s fa0, fa5
+; RV32IFDZFHMIN-NEXT:    srli a1, a1, 17
+; RV32IFDZFHMIN-NEXT:    or a0, a1, a0
+; RV32IFDZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV32IFDZFHMIN-NEXT:    addi sp, sp, 16
 ; RV32IFDZFHMIN-NEXT:    ret
 ;
 ; RV64IFDZFHMIN-LABEL: fold_demote_h_d:
 ; RV64IFDZFHMIN:       # %bb.0:
-; RV64IFDZFHMIN-NEXT:    fmv.x.h a0, fa0
-; RV64IFDZFHMIN-NEXT:    slli a0, a0, 49
-; RV64IFDZFHMIN-NEXT:    fmv.x.d a1, fa1
-; RV64IFDZFHMIN-NEXT:    srli a0, a0, 49
-; RV64IFDZFHMIN-NEXT:    bgez a1, .LBB5_2
-; RV64IFDZFHMIN-NEXT:  # %bb.1:
-; RV64IFDZFHMIN-NEXT:    lui a1, 1048568
-; RV64IFDZFHMIN-NEXT:    or a0, a0, a1
-; RV64IFDZFHMIN-NEXT:  .LBB5_2:
-; RV64IFDZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV64IFDZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV64IFDZFHMIN-NEXT:    fcvt.h.s fa0, fa5
+; RV64IFDZFHMIN-NEXT:    fmv.x.d a0, fa1
+; RV64IFDZFHMIN-NEXT:    srli a0, a0, 63
+; RV64IFDZFHMIN-NEXT:    slli a0, a0, 15
+; RV64IFDZFHMIN-NEXT:    fmv.x.h a1, fa0
+; RV64IFDZFHMIN-NEXT:    slli a1, a1, 49
+; RV64IFDZFHMIN-NEXT:    srli a1, a1, 49
+; RV64IFDZFHMIN-NEXT:    or a0, a1, a0
+; RV64IFDZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV64IFDZFHMIN-NEXT:    ret
   %c = fptrunc double %b to half
   %t = call half @llvm.copysign.f16(half %a, half %c)
diff --git a/llvm/test/CodeGen/RISCV/half-arith.ll b/llvm/test/CodeGen/RISCV/half-arith.ll
index 4c64e6c7a20906..f8522b09970bf9 100644
--- a/llvm/test/CodeGen/RISCV/half-arith.ll
+++ b/llvm/test/CodeGen/RISCV/half-arith.ll
@@ -442,78 +442,44 @@ define half @fsgnj_h(half %a, half %b) nounwind {
 ;
 ; RV32IZFHMIN-LABEL: fsgnj_h:
 ; RV32IZFHMIN:       # %bb.0:
-; RV32IZFHMIN-NEXT:    addi sp, sp, -16
-; RV32IZFHMIN-NEXT:    fsh fa1, 12(sp)
-; RV32IZFHMIN-NEXT:    lbu a0, 13(sp)
+; RV32IZFHMIN-NEXT:    fmv.x.h a0, fa1
+; RV32IZFHMIN-NEXT:    lui a1, 1048568
+; RV32IZFHMIN-NEXT:    and a0, a0, a1
 ; RV32IZFHMIN-NEXT:    fmv.x.h a1, fa0
 ; RV32IZFHMIN-NEXT:    slli a1, a1, 17
-; RV32IZFHMIN-NEXT:    andi a2, a0, 128
-; RV32IZFHMIN-NEXT:    srli a0, a1, 17
-; RV32IZFHMIN-NEXT:    beqz a2, .LBB5_2
-; RV32IZFHMIN-NEXT:  # %bb.1:
-; RV32IZFHMIN-NEXT:    lui a1, 1048568
-; RV32IZFHMIN-NEXT:    or a0, a0, a1
-; RV32IZFHMIN-NEXT:  .LBB5_2:
-; RV32IZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV32IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
-; RV32IZFHMIN-NEXT:    addi sp, sp, 16
+; RV32IZFHMIN-NEXT:    srli a1, a1, 17
+; RV32IZFHMIN-NEXT:    or a0, a1, a0
+; RV32IZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV32IZFHMIN-NEXT:    ret
 ;
 ; RV64IZFHMIN-LABEL: fsgnj_h:
 ; RV64IZFHMIN:       # %bb.0:
-; RV64IZFHMIN-NEXT:    addi sp, sp, -16
-; RV64IZFHMIN-NEXT:    fsh fa1, 8(sp)
-; RV64IZFHMIN-NEXT:    lbu a0, 9(sp)
+; RV64IZFHMIN-NEXT:    fmv.x.h a0, fa1
+; RV64IZFHMIN-NEXT:    lui a1, 1048568
+; RV64IZFHMIN-NEXT:    and a0, a0, a1
 ; RV64IZFHMIN-NEXT:    fmv.x.h a1, fa0
 ; RV64IZFHMIN-NEXT:    slli a1, a1, 49
-; RV64IZFHMIN-NEXT:    andi a2, a0, 128
-; RV64IZFHMIN-NEXT:    srli a0, a1, 49
-; RV64IZFHMIN-NEXT:    beqz a2, .LBB5_2
-; RV64IZFHMIN-NEXT:  # %bb.1:
-; RV64IZFHMIN-NEXT:    lui a1, 1048568
-; RV64IZFHMIN-NEXT:    or a0, a0, a1
-; RV64IZFHMIN-NEXT:  .LBB5_2:
-; RV64IZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV64IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
-; RV64IZFHMIN-NEXT:    addi sp, sp, 16
+; RV64IZFHMIN-NEXT:    srli a1, a1, 49
+; RV64IZFHMIN-NEXT:    or a0, a1, a0
+; RV64IZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV64IZFHMIN-NEXT:    ret
 ;
 ; RV32IZHINXMIN-LABEL: fsgnj_h:
 ; RV32IZHINXMIN:       # %bb.0:
-; RV32IZHINXMIN-NEXT:    addi sp, sp, -16
-; RV32IZHINXMIN-NEXT:    sh a1, 12(sp)
-; RV32IZHINXMIN-NEXT:    lbu a1, 13(sp)
+; RV32IZHINXMIN-NEXT:    lui a2, 1048568
+; RV32IZHINXMIN-NEXT:    and a1, a1, a2
 ; RV32IZHINXMIN-NEXT:    slli a0, a0, 17
-; RV32IZHINXMIN-NEXT:    andi a1, a1, 128
 ; RV32IZHINXMIN-NEXT:    srli a0, a0, 17
-; RV32IZHINXMIN-NEXT:    beqz a1, .LBB5_2
-; RV32IZHINXMIN-NEXT:  # %bb.1:
-; RV32IZHINXMIN-NEXT:    lui a1, 1048568
 ; RV32IZHINXMIN-NEXT:    or a0, a0, a1
-; RV32IZHINXMIN-NEXT:  .LBB5_2:
-; RV32IZHINXMIN-NEXT:    fcvt.s.h a0, a0
-; RV32IZHINXMIN-NEXT:    fcvt.h.s a0, a0
-; RV32IZHINXMIN-NEXT:    addi sp, sp, 16
 ; RV32IZHINXMIN-NEXT:    ret
 ;
 ; RV64IZHINXMIN-LABEL: fsgnj_h:
 ; RV64IZHINXMIN:       # %bb.0:
-; RV64IZHINXMIN-NEXT:    addi sp, sp, -16
-; RV64IZHINXMIN-NEXT:    sh a1, 8(sp)
-; RV64IZHINXMIN-NEXT:    lbu a1, 9(sp)
+; RV64IZHINXMIN-NEXT:    lui a2, 1048568
+; RV64IZHINXMIN-NEXT:    and a1, a1, a2
 ; RV64IZHINXMIN-NEXT:    slli a0, a0, 49
-; RV64IZHINXMIN-NEXT:    andi a1, a1, 128
 ; RV64IZHINXMIN-NEXT:    srli a0, a0, 49
-; RV64IZHINXMIN-NEXT:    beqz a1, .LBB5_2
-; RV64IZHINXMIN-NEXT:  # %bb.1:
-; RV64IZHINXMIN-NEXT:    lui a1, 1048568
 ; RV64IZHINXMIN-NEXT:    or a0, a0, a1
-; RV64IZHINXMIN-NEXT:  .LBB5_2:
-; RV64IZHINXMIN-NEXT:    fcvt.s.h a0, a0
-; RV64IZHINXMIN-NEXT:    fcvt.h.s a0, a0
-; RV64IZHINXMIN-NEXT:    addi sp, sp, 16
 ; RV64IZHINXMIN-NEXT:    ret
   %1 = call half @llvm.copysign.f16(half %a, half %b)
   ret half %1
@@ -725,108 +691,64 @@ define half @fsgnjn_h(half %a, half %b) nounwind {
 ;
 ; RV32IZFHMIN-LABEL: fsgnjn_h:
 ; RV32IZFHMIN:       # %bb.0:
-; RV32IZFHMIN-NEXT:    addi sp, sp, -16
 ; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa1
 ; RV32IZFHMIN-NEXT:    fcvt.s.h fa4, fa0
 ; RV32IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
 ; RV32IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
-; RV32IZFHMIN-NEXT:    fmv.x.h a1, fa5
-; RV32IZFHMIN-NEXT:    lui a0, 1048568
-; RV32IZFHMIN-NEXT:    xor a1, a1, a0
-; RV32IZFHMIN-NEXT:    fmv.h.x fa5, a1
-; RV32IZFHMIN-NEXT:    fsh fa5, 12(sp)
-; RV32IZFHMIN-NEXT:    lbu a1, 13(sp)
-; RV32IZFHMIN-NEXT:    fmv.x.h a2, fa0
-; RV32IZFHMIN-NEXT:    slli a2, a2, 17
-; RV32IZFHMIN-NEXT:    andi a3, a1, 128
-; RV32IZFHMIN-NEXT:    srli a1, a2, 17
-; RV32IZFHMIN-NEXT:    bnez a3, .LBB7_2
-; RV32IZFHMIN-NEXT:  # %bb.1:
-; RV32IZFHMIN-NEXT:    fmv.h.x fa5, a1
-; RV32IZFHMIN-NEXT:    j .LBB7_3
-; RV32IZFHMIN-NEXT:  .LBB7_2:
+; RV32IZFHMIN-NEXT:    fmv.x.h a0, fa5
+; RV32IZFHMIN-NEXT:    not a0, a0
+; RV32IZFHMIN-NEXT:    lui a1, 1048568
+; RV32IZFHMIN-NEXT:    and a0, a0, a1
+; RV32IZFHMIN-NEXT:    fmv.x.h a1, fa0
+; RV32IZFHMIN-NEXT:    slli a1, a1, 17
+; RV32IZFHMIN-NEXT:    srli a1, a1, 17
 ; RV32IZFHMIN-NEXT:    or a0, a1, a0
-; RV32IZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV32IZFHMIN-NEXT:  .LBB7_3:
-; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV32IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
-; RV32IZFHMIN-NEXT:    addi sp, sp, 16
+; RV32IZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV32IZFHMIN-NEXT:    ret
 ;
 ; RV64IZFHMIN-LABEL: fsgnjn_h:
 ; RV64IZFHMIN:       # %bb.0:
-; RV64IZFHMIN-NEXT:    addi sp, sp, -16
 ; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa1
 ; RV64IZFHMIN-NEXT:    fcvt.s.h fa4, fa0
 ; RV64IZFHMIN-NEXT:    fadd.s fa5, fa4, fa5
 ; RV64IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
-; RV64IZFHMIN-NEXT:    fmv.x.h a1, fa5
-; RV64IZFHMIN-NEXT:    lui a0, 1048568
-; RV64IZFHMIN-NEXT:    xor a1, a1, a0
-; RV64IZFHMIN-NEXT:    fmv.h.x fa5, a1
-; RV64IZFHMIN-NEXT:    fsh fa5, 8(sp)
-; RV64IZFHMIN-NEXT:    lbu a1, 9(sp)
-; RV64IZFHMIN-NEXT:    fmv.x.h a2, fa0
-; RV64IZFHMIN-NEXT:    slli a2, a2, 49
-; RV64IZFHMIN-NEXT:    andi a3, a1, 128
-; RV64IZFHMIN-NEXT:    srli a1, a2, 49
-; RV64IZFHMIN-NEXT:    bnez a3, .LBB7_2
-; RV64IZFHMIN-NEXT:  # %bb.1:
-; RV64IZFHMIN-NEXT:    fmv.h.x fa5, a1
-; RV64IZFHMIN-NEXT:    j .LBB7_3
-; RV64IZFHMIN-NEXT:  .LBB7_2:
+; RV64IZFHMIN-NEXT:    fmv.x.h a0, fa5
+; RV64IZFHMIN-NEXT:    not a0, a0
+; RV64IZFHMIN-NEXT:    lui a1, 1048568
+; RV64IZFHMIN-NEXT:    and a0, a0, a1
+; RV64IZFHMIN-NEXT:    fmv.x.h a1, fa0
+; RV64IZFHMIN-NEXT:    slli a1, a1, 49
+; RV64IZFHMIN-NEXT:    srli a1, a1, 49
 ; RV64IZFHMIN-NEXT:    or a0, a1, a0
-; RV64IZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV64IZFHMIN-NEXT:  .LBB7_3:
-; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV64IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
-; RV64IZFHMIN-NEXT:    addi sp, sp, 16
+; RV64IZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV64IZFHMIN-NEXT:    ret
 ;
 ; RV32IZHINXMIN-LABEL: fsgnjn_h:
 ; RV32IZHINXMIN:       # %bb.0:
-; RV32IZHINXMIN-NEXT:    addi sp, sp, -16
 ; RV32IZHINXMIN-NEXT:    fcvt.s.h a1, a1
 ; RV32IZHINXMIN-NEXT:    fcvt.s.h a2, a0
 ; RV32IZHINXMIN-NEXT:    fadd.s a1, a2, a1
-; RV32IZHINXMIN-NEXT:    fcvt.h.s a2, a1
-; RV32IZHINXMIN-NEXT:    lui a1, 1048568
-; RV32IZHINXMIN-NEXT:    xor a2, a2, a1
-; RV32IZHINXMIN-NEXT:    sh a2, 12(sp)
-; RV32IZHINXMIN-NEXT:    lbu a2, 13(sp)
+; RV32IZHINXMIN-NEXT:    fcvt.h.s a1, a1
+; RV32IZHINXMIN-NEXT:    not a1, a1
+; RV32IZHINXMIN-NEXT:    lui a2, 1048568
+; RV32IZHINXMIN-NEXT:    and a1, a1, a2
 ; RV32IZHINXMIN-NEXT:    slli a0, a0, 17
-; RV32IZHINXMIN-NEXT:    andi a2, a2, 128
 ; RV32IZHINXMIN-NEXT:    srli a0, a0, 17
-; RV32IZHINXMIN-NEXT:    beqz a2, .LBB7_2
-; RV32IZHINXMIN-NEXT:  # %bb.1:
 ; RV32IZHINXMIN-NEXT:    or a0, a0, a1
-; RV32IZHINXMIN-NEXT:  .LBB7_2:
-; RV32IZHINXMIN-NEXT:    fcvt.s.h a0, a0
-; RV32IZHINXMIN-NEXT:    fcvt.h.s a0, a0
-; RV32IZHINXMIN-NEXT:    addi sp, sp, 16
 ; RV32IZHINXMIN-NEXT:    ret
 ;
 ; RV64IZHINXMIN-LABEL: fsgnjn_h:
 ; RV64IZHINXMIN:       # %bb.0:
-; RV64IZHINXMIN-NEXT:    addi sp, sp, -16
 ; RV64IZHINXMIN-NEXT:    fcvt.s.h a1, a1
 ; RV64IZHINXMIN-NEXT:    fcvt.s.h a2, a0
 ; RV64IZHINXMIN-NEXT:    fadd.s a1, a2, a1
-; RV64IZHINXMIN-NEXT:    fcvt.h.s a2, a1
-; RV64IZHINXMIN-NEXT:    lui a1, 1048568
-; RV64IZHINXMIN-NEXT:    xor a2, a2, a1
-; RV64IZHINXMIN-NEXT:    sh a2, 8(sp)
-; RV64IZHINXMIN-NEXT:    lbu a2, 9(sp)
+; RV64IZHINXMIN-NEXT:    fcvt.h.s a1, a1
+; RV64IZHINXMIN-NEXT:    not a1, a1
+; RV64IZHINXMIN-NEXT:    lui a2, 1048568
+; RV64IZHINXMIN-NEXT:    and a1, a1, a2
 ; RV64IZHINXMIN-NEXT:    slli a0, a0, 49
-; RV64IZHINXMIN-NEXT:    andi a2, a2, 128
 ; RV64IZHINXMIN-NEXT:    srli a0, a0, 49
-; RV64IZHINXMIN-NEXT:    beqz a2, .LBB7_2
-; RV64IZHINXMIN-NEXT:  # %bb.1:
 ; RV64IZHINXMIN-NEXT:    or a0, a0, a1
-; RV64IZHINXMIN-NEXT:  .LBB7_2:
-; RV64IZHINXMIN-NEXT:    fcvt.s.h a0, a0
-; RV64IZHINXMIN-NEXT:    fcvt.h.s a0, a0
-; RV64IZHINXMIN-NEXT:    addi sp, sp, 16
 ; RV64IZHINXMIN-NEXT:    ret
   %1 = fadd half %a, %b
   %2 = fneg half %1
@@ -2954,96 +2876,68 @@ define half @fsgnjx_f16(half %x, half %y) nounwind {
 ;
 ; RV32IZFHMIN-LABEL: fsgnjx_f16:
 ; RV32IZFHMIN:       # %bb.0:
-; RV32IZFHMIN-NEXT:    addi sp, sp, -16
-; RV32IZFHMIN-NEXT:    fsh fa0, 12(sp)
-; RV32IZFHMIN-NEXT:    lbu a0, 13(sp)
-; RV32IZFHMIN-NEXT:    andi a0, a0, 128
-; RV32IZFHMIN-NEXT:    bnez a0, .LBB23_2
-; RV32IZFHMIN-NEXT:  # %bb.1:
 ; RV32IZFHMIN-NEXT:    lui a0, %hi(.LCPI23_0)
 ; RV32IZFHMIN-NEXT:    flh fa5, %lo(.LCPI23_0)(a0)
-; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV32IZFHMIN-NEXT:    j .LBB23_3
-; RV32IZFHMIN-NEXT:  .LBB23_2:
-; RV32IZFHMIN-NEXT:    lui a0, 784384
-; RV32IZFHMIN-NEXT:    fmv.w.x fa5, a0
-; RV32IZFHMIN-NEXT:  .LBB23_3:
-; RV32IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
+; RV32IZFHMIN-NEXT:    fmv.x.h a0, fa0
+; RV32IZFHMIN-NEXT:    lui a1, 1048568
+; RV32IZFHMIN-NEXT:    and a0, a0, a1
+; RV32IZFHMIN-NEXT:    fmv.x.h a1, fa5
+; RV32IZFHMIN-NEXT:    slli a1, a1, 17
+; RV32IZFHMIN-NEXT:    srli a1, a1, 17
+; RV32IZFHMIN-NEXT:    or a0, a1, a0
+; RV32IZFHMIN-NEXT:    fmv.h.x fa5, a0
 ; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
 ; RV32IZFHMIN-NEXT:    fcvt.s.h fa4, fa1
 ; RV32IZFHMIN-NEXT:    fmul.s fa5, fa5, fa4
 ; RV32IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
-; RV32IZFHMIN-NEXT:    addi sp, sp, 16
 ; RV32IZFHMIN-NEXT:    ret
 ;
 ; RV64IZFHMIN-LABEL: fsgnjx_f16:
 ; RV64IZFHMIN:       # %bb.0:
-; RV64IZFHMIN-NEXT:    addi sp, sp, -16
-; RV64IZFHMIN-NEXT:    fsh fa0, 8(sp)
-; RV64IZFHMIN-NEXT:    lbu a0, 9(sp)
-; RV64IZFHMIN-NEXT:    andi a0, a0, 128
-; RV64IZFHMIN-NEXT:    bnez a0, .LBB23_2
-; RV64IZFHMIN-NEXT:  # %bb.1:
 ; RV64IZFHMIN-NEXT:    lui a0, %hi(.LCPI23_0)
 ; RV64IZFHMIN-NEXT:    flh fa5, %lo(.LCPI23_0)(a0)
-; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV64IZFHMIN-NEXT:    j .LBB23_3
-; RV64IZFHMIN-NEXT:  .LBB23_2:
-; RV64IZFHMIN-NEXT:    lui a0, 784384
-; RV64IZFHMIN-NEXT:    fmv.w.x fa5, a0
-; RV64IZFHMIN-NEXT:  .LBB23_3:
-; RV64IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
+; RV64IZFHMIN-NEXT:    fmv.x.h a0, fa0
+; RV64IZFHMIN-NEXT:    lui a1, 1048568
+; RV64IZFHMIN-NEXT:    and a0, a0, a1
+; RV64IZFHMIN-NEXT:    fmv.x.h a1, fa5
+; RV64IZFHMIN-NEXT:    slli a1, a1, 49
+; RV64IZFHMIN-NEXT:    srli a1, a1, 49
+; RV64IZFHMIN-NEXT:    or a0, a1, a0
+; RV64IZFHMIN-NEXT:    fmv.h.x fa5, a0
 ; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
 ; RV64IZFHMIN-NEXT:    fcvt.s.h fa4, fa1
 ; RV64IZFHMIN-NEXT:    fmul.s fa5, fa5, fa4
 ; RV64IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
-; RV64IZFHMIN-NEXT:    addi sp, sp, 16
 ; RV64IZFHMIN-NEXT:    ret
 ;
 ; RV32IZHINXMIN-LABEL: fsgnjx_f16:
 ; RV32IZHINXMIN:       # %bb.0:
-; RV32IZHINXMIN-NEXT:    addi sp, sp, -16
-; RV32IZHINXMIN-NEXT:    sh a0, 12(sp)
-; RV32IZHINXMIN-NEXT:    lbu a0, 13(sp)
-; RV32IZHINXMIN-NEXT:    andi a0, a0, 128
-; RV32IZHINXMIN-NEXT:    bnez a0, .LBB23_2
-; RV32IZHINXMIN-NEXT:  # %bb.1:
-; RV32IZHINXMIN-NEXT:    lui a0, %hi(.LCPI23_0)
-; RV32IZHINXMIN-NEXT:    lh a0, %lo(.LCPI23_0)(a0)
-; RV32IZHINXMIN-NEXT:    fcvt.s.h a0, a0
-; RV32IZHINXMIN-NEXT:    j .LBB23_3
-; RV32IZHINXMIN-NEXT:  .LBB23_2:
-; RV32IZHINXMIN-NEXT:    lui a0, 784384
-; RV32IZHINXMIN-NEXT:  .LBB23_3:
-; RV32IZHINXMIN-NEXT:    fcvt.h.s a0, a0
+; RV32IZHINXMIN-NEXT:    lui a2, %hi(.LCPI23_0)
+; RV32IZHINXMIN-NEXT:    lh a2, %lo(.LCPI23_0)(a2)
+; RV32IZHINXMIN-NEXT:    lui a3, 1048568
+; RV32IZHINXMIN-NEXT:    and a0, a0, a3
+; RV32IZHINXMIN-NEXT:    slli a2, a2, 17
+; RV32IZHINXMIN-NEXT:    srli a2, a2, 17
+; RV32IZHINXMIN-NEXT:    or a0, a2, a0
 ; RV32IZHINXMIN-NEXT:    fcvt.s.h a0, a0
 ; RV32IZHINXMIN-NEXT:    fcvt.s.h a1, a1
 ; RV32IZHINXMIN-NEXT:    fmul.s a0, a0, a1
 ; RV32IZHINXMIN-NEXT:    fcvt.h.s a0, a0
-; RV32IZHINXMIN-NEXT:    addi sp, sp, 16
 ; RV32IZHINXMIN-NEXT:    ret
 ;
 ; RV64IZHINXMIN-LABEL: fsgnjx_f16:
 ; RV64IZHINXMIN:       # %bb.0:
-; RV64IZHINXMIN-NEXT:    addi sp, sp, -16
-; RV64IZHINXMIN-NEXT:    sh a0, 8(sp)
-; RV64IZHINXMIN-NEXT:    lbu a0, 9(sp)
-; RV64IZHINXMIN-NEXT:    andi a0, a0, 128
-; RV64IZHINXMIN-NEXT:    bnez a0, .LBB23_2
-; RV64IZHINXMIN-NEXT:  # %bb.1:
-; RV64IZHINXMIN-NEXT:    lui a0, %hi(.LCPI23_0)
-; RV64IZHINXMIN-NEXT:    lh a0, %lo(.LCPI23_0)(a0)
-; RV64IZHINXMIN-NEXT:    fcvt.s.h a0, a0
-; RV64IZHINXMIN-NEXT:    j .LBB23_3
-; RV64IZHINXMIN-NEXT:  .LBB23_2:
-; RV64IZHINXMIN-NEXT:    lui a0, 784384
-; RV64IZHINXMIN-NEXT:  .LBB23_3:
-; RV64IZHINXMIN-NEXT:    fcvt.h.s a0, a0
+; RV64IZHINXMIN-NEXT:    lui a2, %hi(.LCPI23_0)
+; RV64IZHINXMIN-NEXT:    lh a2, %lo(.LCPI23_0)(a2)
+; RV64IZHINXMIN-NEXT:    lui a3, 1048568
+; RV64IZHINXMIN-NEXT:    and a0, a0, a3
+; RV64IZHINXMIN-NEXT:    slli a2, a2, 49
+; RV64IZHINXMIN-NEXT:    srli a2, a2, 49
+; RV64IZHINXMIN-NEXT:    or a0, a2, a0
 ; RV64IZHINXMIN-NEXT:    fcvt.s.h a0, a0
 ; RV64IZHINXMIN-NEXT:    fcvt.s.h a1, a1
 ; RV64IZHINXMIN-NEXT:    fmul.s a0, a0, a1
 ; RV64IZHINXMIN-NEXT:    fcvt.h.s a0, a0
-; RV64IZHINXMIN-NEXT:    addi sp, sp, 16
 ; RV64IZHINXMIN-NEXT:    ret
   %z = call half @llvm.copysign.f16(half 1.0, half %x)
   %mul = fmul half %z, %y
diff --git a/llvm/test/CodeGen/RISCV/half-bitmanip-dagcombines.ll b/llvm/test/CodeGen/RISCV/half-bitmanip-dagcombines.ll
index 399ab2f68814cf..506b7027a8b35f 100644
--- a/llvm/test/CodeGen/RISCV/half-bitmanip-dagcombines.ll
+++ b/llvm/test/CodeGen/RISCV/half-bitmanip-dagcombines.ll
@@ -207,84 +207,42 @@ define half @fcopysign_fneg(half %a, half %b) nounwind {
 ;
 ; RV32IZFHMIN-LABEL: fcopysign_fneg:
 ; RV32IZFHMIN:       # %bb.0:
-; RV32IZFHMIN-NEXT:    addi sp, sp, -16
+; RV32IZFHMIN-NEXT:    not a1, a1
 ; RV32IZFHMIN-NEXT:    lui a2, 1048568
-; RV32IZFHMIN-NEXT:    xor a1, a1, a2
-; RV32IZFHMIN-NEXT:    fmv.h.x fa5, a1
-; RV32IZFHMIN-NEXT:    fsh fa5, 12(sp)
-; RV32IZFHMIN-NEXT:    lbu a1, 13(sp)
+; RV32IZFHMIN-NEXT:    and a1, a1, a2
 ; RV32IZFHMIN-NEXT:    slli a0, a0, 17
-; RV32IZFHMIN-NEXT:    andi a1, a1, 128
 ; RV32IZFHMIN-NEXT:    srli a0, a0, 17
-; RV32IZFHMIN-NEXT:    beqz a1, .LBB2_2
-; RV32IZFHMIN-NEXT:  # %bb.1:
-; RV32IZFHMIN-NEXT:    or a0, a0, a2
-; RV32IZFHMIN-NEXT:  .LBB2_2:
-; RV32IZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV32IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
-; RV32IZFHMIN-NEXT:    fmv.x.h a0, fa5
-; RV32IZFHMIN-NEXT:    addi sp, sp, 16
+; RV32IZFHMIN-NEXT:    or a0, a0, a1
 ; RV32IZFHMIN-NEXT:    ret
 ;
 ; RV64IZFHMIN-LABEL: fcopysign_fneg:
 ; RV64IZFHMIN:       # %bb.0:
-; RV64IZFHMIN-NEXT:    addi sp, sp, -16
+; RV64IZFHMIN-NEXT:    not a1, a1
 ; RV64IZFHMIN-NEXT:    lui a2, 1048568
-; RV64IZFHMIN-NEXT:    xor a1, a1, a2
-; RV64IZFHMIN-NEXT:    fmv.h.x fa5, a1
-; RV64IZFHMIN-NEXT:    fsh fa5, 8(sp)
-; RV64IZFHMIN-NEXT:    lbu a1, 9(sp)
+; RV64IZFHMIN-NEXT:    and a1, a1, a2
 ; RV64IZFHMIN-NEXT:    slli a0, a0, 49
-; RV64IZFHMIN-NEXT:    andi a1, a1, 128
 ; RV64IZFHMIN-NEXT:    srli a0, a0, 49
-; RV64IZFHMIN-NEXT:    beqz a1, .LBB2_2
-; RV64IZFHMIN-NEXT:  # %bb.1:
-; RV64IZFHMIN-NEXT:    or a0, a0, a2
-; RV64IZFHMIN-NEXT:  .LBB2_2:
-; RV64IZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV64IZFHMIN-NEXT:    fcvt.h.s fa5, fa5
-; RV64IZFHMIN-NEXT:    fmv.x.h a0, fa5
-; RV64IZFHMIN-NEXT:    addi sp, sp, 16
+; RV64IZFHMIN-NEXT:    or a0, a0, a1
 ; RV64IZFHMIN-NEXT:    ret
 ;
 ; RV32IZHINXMIN-LABEL: fcopysign_fneg:
 ; RV32IZHINXMIN:       # %bb.0:
-; RV32IZHINXMIN-NEXT:    addi sp, sp, -16
+; RV32IZHINXMIN-NEXT:    not a1, a1
 ; RV32IZHINXMIN-NEXT:    lui a2, 1048568
-; RV32IZHINXMIN-NEXT:    xor a1, a1, a2
-; RV32IZHINXMIN-NEXT:    sh a1, 12(sp)
-; RV32IZHINXMIN-NEXT:    lbu a1, 13(sp)
+; RV32IZHINXMIN-NEXT:    and a1, a1, a2
 ; RV32IZHINXMIN-NEXT:    slli a0, a0, 17
-; RV32IZHINXMIN-NEXT:    andi a1, a1, 128
 ; RV32IZHINXMIN-NEXT:    srli a0, a0, 17
-; RV32IZHINXMIN-NEXT:    beqz a1, .LBB2_2
-; RV32IZHINXMIN-NEXT:  # %bb.1:
-; RV32IZHINXMIN-NEXT:    or a0, a0, a2
-; RV32IZHINXMIN-NEXT:  .LBB2_2:
-; RV32IZHINXMIN-NEXT:    fcvt.s.h a0, a0
-; RV32IZHINXMIN-NEXT:    fcvt.h.s a0, a0
-; RV32IZHINXMIN-NEXT:    addi sp, sp, 16
+; RV32IZHINXMIN-NEXT:    or a0, a0, a1
 ; RV32IZHINXMIN-NEXT:    ret
 ;
 ; RV64IZHINXMIN-LABEL: fcopysign_fneg:
 ; RV64IZHINXMIN:       # %bb.0:
-; RV64IZHINXMIN-NEXT:    addi sp, sp, -16
+; RV64IZHINXMIN-NEXT:    not a1, a1
 ; RV64IZHINXMIN-NEXT:    lui a2, 1048568
-; RV64IZHINXMIN-NEXT:    xor a1, a1, a2
-; RV64IZHINXMIN-NEXT:    sh a1, 8(sp)
-; RV64IZHINXMIN-NEXT:    lbu a1, 9(sp)
+; RV64IZHINXMIN-NEXT:    and a1, a1, a2
 ; RV64IZHINXMIN-NEXT:    slli a0, a0, 49
-; RV64IZHINXMIN-NEXT:    andi a1, a1, 128
 ; RV64IZHINXMIN-NEXT:    srli a0, a0, 49
-; RV64IZHINXMIN-NEXT:    beqz a1, .LBB2_2
-; RV64IZHINXMIN-NEXT:  # %bb.1:
-; RV64IZHINXMIN-NEXT:    or a0, a0, a2
-; RV64IZHINXMIN-NEXT:  .LBB2_2:
-; RV64IZHINXMIN-NEXT:    fcvt.s.h a0, a0
-; RV64IZHINXMIN-NEXT:    fcvt.h.s a0, a0
-; RV64IZHINXMIN-NEXT:    addi sp, sp, 16
+; RV64IZHINXMIN-NEXT:    or a0, a0, a1
 ; RV64IZHINXMIN-NEXT:    ret
   %1 = fneg half %b
   %2 = call half @llvm.copysign.f16(half %a, half %1)
diff --git a/llvm/test/CodeGen/RISCV/half-intrinsics.ll b/llvm/test/CodeGen/RISCV/half-intrinsics.ll
index f40e4ba8f64bd4..40363b321848d7 100644
--- a/llvm/test/CodeGen/RISCV/half-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/half-intrinsics.ll
@@ -2070,78 +2070,44 @@ define half @copysign_f16(half %a, half %b) nounwind {
 ;
 ; RV32IZFHMIN-LABEL: copysign_f16:
 ; RV32IZFHMIN:       # %bb.0:
-; RV32IZFHMIN-NEXT:    addi sp, sp, -16
-; RV32IZFHMIN-NEXT:    fsh fa1, 12(sp)
-; RV32IZFHMIN-NEXT:    lbu a0, 13(sp)
+; RV32IZFHMIN-NEXT:    fmv.x.h a0, fa1
+; RV32IZFHMIN-NEXT:    lui a1, 1048568
+; RV32IZFHMIN-NEXT:    and a0, a0, a1
 ; RV32IZFHMIN-NEXT:    fmv.x.h a1, fa0
 ; RV32IZFHMIN-NEXT:    slli a1, a1, 17
-; RV32IZFHMIN-NEXT:    andi a2, a0, 128
-; RV32IZFHMIN-NEXT:    srli a0, a1, 17
-; RV32IZFHMIN-NEXT:    beqz a2, .LBB16_2
-; RV32IZFHMIN-NEXT:  # %bb.1:
-; RV32IZFHMIN-NEXT:    lui a1, 1048568
-; RV32IZFHMIN-NEXT:    or a0, a0, a1
-; RV32IZFHMIN-NEXT:  .LBB16_2:
-; RV32IZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV32IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV32IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
-; RV32IZFHMIN-NEXT:    addi sp, sp, 16
+; RV32IZFHMIN-NEXT:    srli a1, a1, 17
+; RV32IZFHMIN-NEXT:    or a0, a1, a0
+; RV32IZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV32IZFHMIN-NEXT:    ret
 ;
 ; RV64IZFHMIN-LABEL: copysign_f16:
 ; RV64IZFHMIN:       # %bb.0:
-; RV64IZFHMIN-NEXT:    addi sp, sp, -16
-; RV64IZFHMIN-NEXT:    fsh fa1, 8(sp)
-; RV64IZFHMIN-NEXT:    lbu a0, 9(sp)
+; RV64IZFHMIN-NEXT:    fmv.x.h a0, fa1
+; RV64IZFHMIN-NEXT:    lui a1, 1048568
+; RV64IZFHMIN-NEXT:    and a0, a0, a1
 ; RV64IZFHMIN-NEXT:    fmv.x.h a1, fa0
 ; RV64IZFHMIN-NEXT:    slli a1, a1, 49
-; RV64IZFHMIN-NEXT:    andi a2, a0, 128
-; RV64IZFHMIN-NEXT:    srli a0, a1, 49
-; RV64IZFHMIN-NEXT:    beqz a2, .LBB16_2
-; RV64IZFHMIN-NEXT:  # %bb.1:
-; RV64IZFHMIN-NEXT:    lui a1, 1048568
-; RV64IZFHMIN-NEXT:    or a0, a0, a1
-; RV64IZFHMIN-NEXT:  .LBB16_2:
-; RV64IZFHMIN-NEXT:    fmv.h.x fa5, a0
-; RV64IZFHMIN-NEXT:    fcvt.s.h fa5, fa5
-; RV64IZFHMIN-NEXT:    fcvt.h.s fa0, fa5
-; RV64IZFHMIN-NEXT:    addi sp, sp, 16
+; RV64IZFHMIN-NEXT:    srli a1, a1, 49
+; RV64IZFHMIN-NEXT:    or a0, a1, a0
+; RV64IZFHMIN-NEXT:    fmv.h.x fa0, a0
 ; RV64IZFHMIN-NEXT:    ret
 ;
 ; RV32IZHINXMIN-LABEL: copysign_f16:
 ; RV32IZHINXMIN:       # %bb.0:
-; RV32IZHINXMIN-NEXT:    addi sp, sp, -16
-; RV32IZHINXMIN-NEXT:    sh a1, 12(sp)
-; RV32IZHINXMIN-NEXT:    lbu a1, 13(sp)
+; RV32IZHINXMIN-NEXT:    lui a2, 1048568
+; RV32IZHINXMIN-NEXT:    and a1, a1, a2
 ; RV32IZHINXMIN-NEXT:    slli a0, a0, 17
-; RV32IZHINXMIN-NEXT:    andi a1, a1, 128
 ; RV32IZHINXMIN-NEXT:    srli a0, a0, 17
-; RV32IZHINXMIN-NEXT:    beqz a1, .LBB16_2
-; RV32IZHINXMIN-NEXT:  # %bb.1:
-; RV32IZHINXMIN-NEXT:    lui a1, 1048568
 ; RV32IZHINXMIN-NEXT:    or a0, a0, a1
-; RV32IZHINXMIN-NEXT:  .LBB16_2:
-; RV32IZHINXMIN-NEXT:    fcvt.s.h a0, a0
-; RV32IZHINXMIN-NEXT:    fcvt.h.s a0, a0
-; RV32IZHINXMIN-NEXT:    addi sp, sp, 16
 ; RV32IZHINXMIN-NEXT:    ret
 ;
 ; RV64IZHINXMIN-LABEL: copysign_f16:
 ; RV64IZHINXMIN:       # %bb.0:
-; RV64IZHINXMIN-NEXT:    addi sp, sp, -16
-; RV64IZHINXMIN-NEXT:    sh a1, 8(sp)
-; RV64IZHINXMIN-NEXT:    lbu a1, 9(sp)
+; RV64IZHINXMIN-NEXT:    lui a2, 1048568
+; RV64IZHINXMIN-NEXT:    and a1, a1, a2
 ; RV64IZHINXMIN-NEXT:    slli a0, a0, 49
-; RV64IZHINXMIN-NEXT:    andi a1, a1, 128
 ; RV64IZHINXMIN-NEXT:    srli a0, a0, 49
-; RV64IZHINXMIN-NEXT:    beqz a1, .LBB16_2
-; RV64IZHINXMIN-NEXT:  # %bb.1:
-; RV64IZHINXMIN-NEXT:    lui a1, 1048568
 ; RV64IZHINXMIN-NEXT:    or a0, a0, a1
-; RV64IZHINXMIN-NEXT:  .LBB16_2:
-; RV64IZHINXMIN-NEXT:    fcvt.s.h a0, a0
-; RV64IZHINXMIN-NEXT:    fcvt.h.s a0, a0
-; RV64IZHINXMIN-NEXT:    addi sp, sp, 16
 ; RV64IZHINXMIN-NEXT:    ret
   %1 = call half @llvm.copysign.f16(half %a, half %b)
   ret half %1



More information about the llvm-commits mailing list