[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