Skip to content

[RISCV] Custom legalize f16/bf16 FCOPYSIGN with Zfhmin/Zbfmin. #107039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 67 additions & 2 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -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);
Expand Down Expand Up @@ -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) \
Expand Down Expand Up @@ -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()))
Expand Down
98 changes: 28 additions & 70 deletions llvm/test/CodeGen/RISCV/bfloat-arith.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
120 changes: 42 additions & 78 deletions llvm/test/CodeGen/RISCV/copysign-casts.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
Loading
Loading