[llvm] b121d23 - [RISCV] Promote f16 log/pow/exp/sin/cos/etc. to f32 libcalls.
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 29 18:49:53 PST 2021
Author: Craig Topper
Date: 2021-11-29T18:49:11-08:00
New Revision: b121d23a9cea711e832505c0b2495de6a51591c1
URL: https://github.com/llvm/llvm-project/commit/b121d23a9cea711e832505c0b2495de6a51591c1
DIFF: https://github.com/llvm/llvm-project/commit/b121d23a9cea711e832505c0b2495de6a51591c1.diff
LOG: [RISCV] Promote f16 log/pow/exp/sin/cos/etc. to f32 libcalls.
Prevents crashes or cannot select errors.
Reviewed By: frasercrmck
Differential Revision: https://reviews.llvm.org/D113822
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/test/CodeGen/RISCV/half-intrinsics.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 0f1a6e5f9154..a26795ddc8c4 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -335,17 +335,29 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SELECT_CC, MVT::f16, Expand);
setOperationAction(ISD::SELECT, MVT::f16, Custom);
setOperationAction(ISD::BR_CC, MVT::f16, Expand);
- for (auto Op : FPOpToExpand)
- setOperationAction(Op, MVT::f16, Expand);
setOperationAction(ISD::FREM, MVT::f16, Promote);
- setOperationAction(ISD::FCEIL, MVT::f16, Promote);
- setOperationAction(ISD::FFLOOR, MVT::f16, Promote);
- setOperationAction(ISD::FNEARBYINT, MVT::f16, Promote);
- setOperationAction(ISD::FRINT, MVT::f16, Promote);
- setOperationAction(ISD::FROUND, MVT::f16, Promote);
- setOperationAction(ISD::FROUNDEVEN, MVT::f16, Promote);
- setOperationAction(ISD::FTRUNC, MVT::f16, Promote);
+ setOperationAction(ISD::FCEIL, MVT::f16, Promote);
+ setOperationAction(ISD::FFLOOR, MVT::f16, Promote);
+ setOperationAction(ISD::FNEARBYINT, MVT::f16, Promote);
+ setOperationAction(ISD::FRINT, MVT::f16, Promote);
+ setOperationAction(ISD::FROUND, MVT::f16, Promote);
+ setOperationAction(ISD::FROUNDEVEN, MVT::f16, Promote);
+ setOperationAction(ISD::FTRUNC, MVT::f16, Promote);
+ setOperationAction(ISD::FPOW, MVT::f16, Promote);
+ setOperationAction(ISD::FPOWI, MVT::f16, Promote);
+ setOperationAction(ISD::FCOS, MVT::f16, Promote);
+ setOperationAction(ISD::FSIN, MVT::f16, Promote);
+ setOperationAction(ISD::FSINCOS, MVT::f16, Promote);
+ setOperationAction(ISD::FEXP, MVT::f16, Promote);
+ setOperationAction(ISD::FEXP2, MVT::f16, Promote);
+ setOperationAction(ISD::FLOG, MVT::f16, Promote);
+ setOperationAction(ISD::FLOG2, MVT::f16, Promote);
+ setOperationAction(ISD::FLOG10, MVT::f16, Promote);
+
+ // We need to custom promote this.
+ if (Subtarget.is64Bit())
+ setOperationAction(ISD::FPOWI, MVT::i32, Custom);
}
if (Subtarget.hasStdExtF()) {
@@ -2670,6 +2682,20 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
DAG.getConstant(3, DL, VT));
return DAG.getNode(ISD::MUL, DL, VT, VScale, Op.getOperand(0));
}
+ case ISD::FPOWI: {
+ // Custom promote f16 powi with illegal i32 integer type on RV64. Once
+ // promoted this will be legalized into a libcall by LegalizeIntegerTypes.
+ if (Op.getValueType() == MVT::f16 && Subtarget.is64Bit() &&
+ Op.getOperand(1).getValueType() == MVT::i32) {
+ SDLoc DL(Op);
+ SDValue Op0 = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Op.getOperand(0));
+ SDValue Powi =
+ DAG.getNode(ISD::FPOWI, DL, MVT::f32, Op0, Op.getOperand(1));
+ return DAG.getNode(ISD::FP_ROUND, DL, MVT::f16, Powi,
+ DAG.getIntPtrConstant(0, DL));
+ }
+ return SDValue();
+ }
case ISD::FP_EXTEND: {
// RVV can only do fp_extend to types double the size as the source. We
// custom-lower f16->f64 extensions to two hops of ISD::FP_EXTEND, going
diff --git a/llvm/test/CodeGen/RISCV/half-intrinsics.ll b/llvm/test/CodeGen/RISCV/half-intrinsics.ll
index 432faf999d89..128c61947cb0 100644
--- a/llvm/test/CodeGen/RISCV/half-intrinsics.ll
+++ b/llvm/test/CodeGen/RISCV/half-intrinsics.ll
@@ -72,6 +72,903 @@ define half @sqrt_f16(half %a) nounwind {
ret half %1
}
+declare half @llvm.powi.f16.i32(half, i32)
+
+define half @powi_f16(half %a, i32 %b) nounwind {
+; RV32IZFH-LABEL: powi_f16:
+; RV32IZFH: # %bb.0:
+; RV32IZFH-NEXT: addi sp, sp, -16
+; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IZFH-NEXT: call __powisf2 at plt
+; RV32IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: addi sp, sp, 16
+; RV32IZFH-NEXT: ret
+;
+; RV64IZFH-LABEL: powi_f16:
+; RV64IZFH: # %bb.0:
+; RV64IZFH-NEXT: addi sp, sp, -16
+; RV64IZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IZFH-NEXT: sext.w a0, a0
+; RV64IZFH-NEXT: call __powisf2 at plt
+; RV64IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFH-NEXT: addi sp, sp, 16
+; RV64IZFH-NEXT: ret
+;
+; RV32IDZFH-LABEL: powi_f16:
+; RV32IDZFH: # %bb.0:
+; RV32IDZFH-NEXT: addi sp, sp, -16
+; RV32IDZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IDZFH-NEXT: call __powisf2 at plt
+; RV32IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IDZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IDZFH-NEXT: addi sp, sp, 16
+; RV32IDZFH-NEXT: ret
+;
+; RV64IDZFH-LABEL: powi_f16:
+; RV64IDZFH: # %bb.0:
+; RV64IDZFH-NEXT: addi sp, sp, -16
+; RV64IDZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IDZFH-NEXT: sext.w a0, a0
+; RV64IDZFH-NEXT: call __powisf2 at plt
+; RV64IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IDZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: addi sp, sp, 16
+; RV64IDZFH-NEXT: ret
+;
+; RV32I-LABEL: powi_f16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32I-NEXT: mv s0, a1
+; RV32I-NEXT: lui a1, 16
+; RV32I-NEXT: addi a1, a1, -1
+; RV32I-NEXT: and a0, a0, a1
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: mv a1, s0
+; RV32I-NEXT: call __powisf2 at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: powi_f16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s0, 0(sp) # 8-byte Folded Spill
+; RV64I-NEXT: mv s0, a1
+; RV64I-NEXT: lui a1, 16
+; RV64I-NEXT: addiw a1, a1, -1
+; RV64I-NEXT: and a0, a0, a1
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: sext.w a1, s0
+; RV64I-NEXT: call __powisf2 at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call half @llvm.powi.f16.i32(half %a, i32 %b)
+ ret half %1
+}
+
+declare half @llvm.sin.f16(half)
+
+define half @sin_f16(half %a) nounwind {
+; RV32IZFH-LABEL: sin_f16:
+; RV32IZFH: # %bb.0:
+; RV32IZFH-NEXT: addi sp, sp, -16
+; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IZFH-NEXT: call sinf at plt
+; RV32IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: addi sp, sp, 16
+; RV32IZFH-NEXT: ret
+;
+; RV64IZFH-LABEL: sin_f16:
+; RV64IZFH: # %bb.0:
+; RV64IZFH-NEXT: addi sp, sp, -16
+; RV64IZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IZFH-NEXT: call sinf at plt
+; RV64IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFH-NEXT: addi sp, sp, 16
+; RV64IZFH-NEXT: ret
+;
+; RV32IDZFH-LABEL: sin_f16:
+; RV32IDZFH: # %bb.0:
+; RV32IDZFH-NEXT: addi sp, sp, -16
+; RV32IDZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IDZFH-NEXT: call sinf at plt
+; RV32IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IDZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IDZFH-NEXT: addi sp, sp, 16
+; RV32IDZFH-NEXT: ret
+;
+; RV64IDZFH-LABEL: sin_f16:
+; RV64IDZFH: # %bb.0:
+; RV64IDZFH-NEXT: addi sp, sp, -16
+; RV64IDZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IDZFH-NEXT: call sinf at plt
+; RV64IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IDZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: addi sp, sp, 16
+; RV64IDZFH-NEXT: ret
+;
+; RV32I-LABEL: sin_f16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lui a1, 16
+; RV32I-NEXT: addi a1, a1, -1
+; RV32I-NEXT: and a0, a0, a1
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: call sinf at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: sin_f16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lui a1, 16
+; RV64I-NEXT: addiw a1, a1, -1
+; RV64I-NEXT: and a0, a0, a1
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: call sinf at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call half @llvm.sin.f16(half %a)
+ ret half %1
+}
+
+declare half @llvm.cos.f16(half)
+
+define half @cos_f16(half %a) nounwind {
+; RV32IZFH-LABEL: cos_f16:
+; RV32IZFH: # %bb.0:
+; RV32IZFH-NEXT: addi sp, sp, -16
+; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IZFH-NEXT: call cosf at plt
+; RV32IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: addi sp, sp, 16
+; RV32IZFH-NEXT: ret
+;
+; RV64IZFH-LABEL: cos_f16:
+; RV64IZFH: # %bb.0:
+; RV64IZFH-NEXT: addi sp, sp, -16
+; RV64IZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IZFH-NEXT: call cosf at plt
+; RV64IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFH-NEXT: addi sp, sp, 16
+; RV64IZFH-NEXT: ret
+;
+; RV32IDZFH-LABEL: cos_f16:
+; RV32IDZFH: # %bb.0:
+; RV32IDZFH-NEXT: addi sp, sp, -16
+; RV32IDZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IDZFH-NEXT: call cosf at plt
+; RV32IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IDZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IDZFH-NEXT: addi sp, sp, 16
+; RV32IDZFH-NEXT: ret
+;
+; RV64IDZFH-LABEL: cos_f16:
+; RV64IDZFH: # %bb.0:
+; RV64IDZFH-NEXT: addi sp, sp, -16
+; RV64IDZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IDZFH-NEXT: call cosf at plt
+; RV64IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IDZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: addi sp, sp, 16
+; RV64IDZFH-NEXT: ret
+;
+; RV32I-LABEL: cos_f16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lui a1, 16
+; RV32I-NEXT: addi a1, a1, -1
+; RV32I-NEXT: and a0, a0, a1
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: call cosf at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: cos_f16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lui a1, 16
+; RV64I-NEXT: addiw a1, a1, -1
+; RV64I-NEXT: and a0, a0, a1
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: call cosf at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call half @llvm.cos.f16(half %a)
+ ret half %1
+}
+
+; The sin+cos combination results in an FSINCOS SelectionDAG node.
+define half @sincos_f16(half %a) nounwind {
+; RV32IZFH-LABEL: sincos_f16:
+; RV32IZFH: # %bb.0:
+; RV32IZFH-NEXT: addi sp, sp, -16
+; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fsw fs0, 8(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fsw fs1, 4(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fcvt.s.h fs0, fa0
+; RV32IZFH-NEXT: fmv.s fa0, fs0
+; RV32IZFH-NEXT: call sinf at plt
+; RV32IZFH-NEXT: fcvt.h.s fs1, fa0
+; RV32IZFH-NEXT: fmv.s fa0, fs0
+; RV32IZFH-NEXT: call cosf at plt
+; RV32IZFH-NEXT: fcvt.h.s ft0, fa0
+; RV32IZFH-NEXT: fadd.h fa0, fs1, ft0
+; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: flw fs0, 8(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: flw fs1, 4(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: addi sp, sp, 16
+; RV32IZFH-NEXT: ret
+;
+; RV64IZFH-LABEL: sincos_f16:
+; RV64IZFH: # %bb.0:
+; RV64IZFH-NEXT: addi sp, sp, -16
+; RV64IZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFH-NEXT: fsw fs0, 4(sp) # 4-byte Folded Spill
+; RV64IZFH-NEXT: fsw fs1, 0(sp) # 4-byte Folded Spill
+; RV64IZFH-NEXT: fcvt.s.h fs0, fa0
+; RV64IZFH-NEXT: fmv.s fa0, fs0
+; RV64IZFH-NEXT: call sinf at plt
+; RV64IZFH-NEXT: fcvt.h.s fs1, fa0
+; RV64IZFH-NEXT: fmv.s fa0, fs0
+; RV64IZFH-NEXT: call cosf at plt
+; RV64IZFH-NEXT: fcvt.h.s ft0, fa0
+; RV64IZFH-NEXT: fadd.h fa0, fs1, ft0
+; RV64IZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFH-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload
+; RV64IZFH-NEXT: flw fs1, 0(sp) # 4-byte Folded Reload
+; RV64IZFH-NEXT: addi sp, sp, 16
+; RV64IZFH-NEXT: ret
+;
+; RV32IDZFH-LABEL: sincos_f16:
+; RV32IDZFH: # %bb.0:
+; RV32IDZFH-NEXT: addi sp, sp, -32
+; RV32IDZFH-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
+; RV32IDZFH-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill
+; RV32IDZFH-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill
+; RV32IDZFH-NEXT: fcvt.s.h fs0, fa0
+; RV32IDZFH-NEXT: fmv.s fa0, fs0
+; RV32IDZFH-NEXT: call sinf at plt
+; RV32IDZFH-NEXT: fcvt.h.s fs1, fa0
+; RV32IDZFH-NEXT: fmv.s fa0, fs0
+; RV32IDZFH-NEXT: call cosf at plt
+; RV32IDZFH-NEXT: fcvt.h.s ft0, fa0
+; RV32IDZFH-NEXT: fadd.h fa0, fs1, ft0
+; RV32IDZFH-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
+; RV32IDZFH-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload
+; RV32IDZFH-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload
+; RV32IDZFH-NEXT: addi sp, sp, 32
+; RV32IDZFH-NEXT: ret
+;
+; RV64IDZFH-LABEL: sincos_f16:
+; RV64IDZFH: # %bb.0:
+; RV64IDZFH-NEXT: addi sp, sp, -32
+; RV64IDZFH-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fcvt.s.h fs0, fa0
+; RV64IDZFH-NEXT: fmv.s fa0, fs0
+; RV64IDZFH-NEXT: call sinf at plt
+; RV64IDZFH-NEXT: fcvt.h.s fs1, fa0
+; RV64IDZFH-NEXT: fmv.s fa0, fs0
+; RV64IDZFH-NEXT: call cosf at plt
+; RV64IDZFH-NEXT: fcvt.h.s ft0, fa0
+; RV64IDZFH-NEXT: fadd.h fa0, fs1, ft0
+; RV64IDZFH-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: addi sp, sp, 32
+; RV64IDZFH-NEXT: ret
+;
+; RV32I-LABEL: sincos_f16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lui a1, 16
+; RV32I-NEXT: addi s1, a1, -1
+; RV32I-NEXT: and a0, a0, s1
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: mv s0, a0
+; RV32I-NEXT: call sinf at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: mv s2, a0
+; RV32I-NEXT: mv a0, s0
+; RV32I-NEXT: call cosf at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: mv s0, a0
+; RV32I-NEXT: and a0, s2, s1
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: mv s2, a0
+; RV32I-NEXT: and a0, s0, s1
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: mv a1, a0
+; RV32I-NEXT: mv a0, s2
+; RV32I-NEXT: call __addsf3 at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: sincos_f16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -32
+; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lui a1, 16
+; RV64I-NEXT: addiw s1, a1, -1
+; RV64I-NEXT: and a0, a0, s1
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: mv s0, a0
+; RV64I-NEXT: call sinf at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: mv s2, a0
+; RV64I-NEXT: mv a0, s0
+; RV64I-NEXT: call cosf at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: mv s0, a0
+; RV64I-NEXT: and a0, s2, s1
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: mv s2, a0
+; RV64I-NEXT: and a0, s0, s1
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: mv a1, a0
+; RV64I-NEXT: mv a0, s2
+; RV64I-NEXT: call __addsf3 at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 32
+; RV64I-NEXT: ret
+ %1 = call half @llvm.sin.f16(half %a)
+ %2 = call half @llvm.cos.f16(half %a)
+ %3 = fadd half %1, %2
+ ret half %3
+}
+
+declare half @llvm.pow.f16(half, half)
+
+define half @pow_f16(half %a, half %b) nounwind {
+; RV32IZFH-LABEL: pow_f16:
+; RV32IZFH: # %bb.0:
+; RV32IZFH-NEXT: addi sp, sp, -16
+; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IZFH-NEXT: fcvt.s.h fa1, fa1
+; RV32IZFH-NEXT: call powf at plt
+; RV32IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: addi sp, sp, 16
+; RV32IZFH-NEXT: ret
+;
+; RV64IZFH-LABEL: pow_f16:
+; RV64IZFH: # %bb.0:
+; RV64IZFH-NEXT: addi sp, sp, -16
+; RV64IZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IZFH-NEXT: fcvt.s.h fa1, fa1
+; RV64IZFH-NEXT: call powf at plt
+; RV64IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFH-NEXT: addi sp, sp, 16
+; RV64IZFH-NEXT: ret
+;
+; RV32IDZFH-LABEL: pow_f16:
+; RV32IDZFH: # %bb.0:
+; RV32IDZFH-NEXT: addi sp, sp, -16
+; RV32IDZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IDZFH-NEXT: fcvt.s.h fa1, fa1
+; RV32IDZFH-NEXT: call powf at plt
+; RV32IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IDZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IDZFH-NEXT: addi sp, sp, 16
+; RV32IDZFH-NEXT: ret
+;
+; RV64IDZFH-LABEL: pow_f16:
+; RV64IDZFH: # %bb.0:
+; RV64IDZFH-NEXT: addi sp, sp, -16
+; RV64IDZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IDZFH-NEXT: fcvt.s.h fa1, fa1
+; RV64IDZFH-NEXT: call powf at plt
+; RV64IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IDZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: addi sp, sp, 16
+; RV64IDZFH-NEXT: ret
+;
+; RV32I-LABEL: pow_f16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill
+; RV32I-NEXT: mv s2, a1
+; RV32I-NEXT: lui a1, 16
+; RV32I-NEXT: addi s0, a1, -1
+; RV32I-NEXT: and a0, a0, s0
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: mv s1, a0
+; RV32I-NEXT: and a0, s2, s0
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: mv a1, a0
+; RV32I-NEXT: mv a0, s1
+; RV32I-NEXT: call powf at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: pow_f16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -32
+; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
+; RV64I-NEXT: mv s2, a1
+; RV64I-NEXT: lui a1, 16
+; RV64I-NEXT: addiw s0, a1, -1
+; RV64I-NEXT: and a0, a0, s0
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: mv s1, a0
+; RV64I-NEXT: and a0, s2, s0
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: mv a1, a0
+; RV64I-NEXT: mv a0, s1
+; RV64I-NEXT: call powf at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 32
+; RV64I-NEXT: ret
+ %1 = call half @llvm.pow.f16(half %a, half %b)
+ ret half %1
+}
+
+declare half @llvm.exp.f16(half)
+
+define half @exp_f16(half %a) nounwind {
+; RV32IZFH-LABEL: exp_f16:
+; RV32IZFH: # %bb.0:
+; RV32IZFH-NEXT: addi sp, sp, -16
+; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IZFH-NEXT: call expf at plt
+; RV32IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: addi sp, sp, 16
+; RV32IZFH-NEXT: ret
+;
+; RV64IZFH-LABEL: exp_f16:
+; RV64IZFH: # %bb.0:
+; RV64IZFH-NEXT: addi sp, sp, -16
+; RV64IZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IZFH-NEXT: call expf at plt
+; RV64IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFH-NEXT: addi sp, sp, 16
+; RV64IZFH-NEXT: ret
+;
+; RV32IDZFH-LABEL: exp_f16:
+; RV32IDZFH: # %bb.0:
+; RV32IDZFH-NEXT: addi sp, sp, -16
+; RV32IDZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IDZFH-NEXT: call expf at plt
+; RV32IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IDZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IDZFH-NEXT: addi sp, sp, 16
+; RV32IDZFH-NEXT: ret
+;
+; RV64IDZFH-LABEL: exp_f16:
+; RV64IDZFH: # %bb.0:
+; RV64IDZFH-NEXT: addi sp, sp, -16
+; RV64IDZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IDZFH-NEXT: call expf at plt
+; RV64IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IDZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: addi sp, sp, 16
+; RV64IDZFH-NEXT: ret
+;
+; RV32I-LABEL: exp_f16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lui a1, 16
+; RV32I-NEXT: addi a1, a1, -1
+; RV32I-NEXT: and a0, a0, a1
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: call expf at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: exp_f16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lui a1, 16
+; RV64I-NEXT: addiw a1, a1, -1
+; RV64I-NEXT: and a0, a0, a1
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: call expf at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call half @llvm.exp.f16(half %a)
+ ret half %1
+}
+
+declare half @llvm.exp2.f16(half)
+
+define half @exp2_f16(half %a) nounwind {
+; RV32IZFH-LABEL: exp2_f16:
+; RV32IZFH: # %bb.0:
+; RV32IZFH-NEXT: addi sp, sp, -16
+; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IZFH-NEXT: call exp2f at plt
+; RV32IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: addi sp, sp, 16
+; RV32IZFH-NEXT: ret
+;
+; RV64IZFH-LABEL: exp2_f16:
+; RV64IZFH: # %bb.0:
+; RV64IZFH-NEXT: addi sp, sp, -16
+; RV64IZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IZFH-NEXT: call exp2f at plt
+; RV64IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFH-NEXT: addi sp, sp, 16
+; RV64IZFH-NEXT: ret
+;
+; RV32IDZFH-LABEL: exp2_f16:
+; RV32IDZFH: # %bb.0:
+; RV32IDZFH-NEXT: addi sp, sp, -16
+; RV32IDZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IDZFH-NEXT: call exp2f at plt
+; RV32IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IDZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IDZFH-NEXT: addi sp, sp, 16
+; RV32IDZFH-NEXT: ret
+;
+; RV64IDZFH-LABEL: exp2_f16:
+; RV64IDZFH: # %bb.0:
+; RV64IDZFH-NEXT: addi sp, sp, -16
+; RV64IDZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IDZFH-NEXT: call exp2f at plt
+; RV64IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IDZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: addi sp, sp, 16
+; RV64IDZFH-NEXT: ret
+;
+; RV32I-LABEL: exp2_f16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lui a1, 16
+; RV32I-NEXT: addi a1, a1, -1
+; RV32I-NEXT: and a0, a0, a1
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: call exp2f at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: exp2_f16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lui a1, 16
+; RV64I-NEXT: addiw a1, a1, -1
+; RV64I-NEXT: and a0, a0, a1
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: call exp2f at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call half @llvm.exp2.f16(half %a)
+ ret half %1
+}
+
+declare half @llvm.log.f16(half)
+
+define half @log_f16(half %a) nounwind {
+; RV32IZFH-LABEL: log_f16:
+; RV32IZFH: # %bb.0:
+; RV32IZFH-NEXT: addi sp, sp, -16
+; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IZFH-NEXT: call logf at plt
+; RV32IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: addi sp, sp, 16
+; RV32IZFH-NEXT: ret
+;
+; RV64IZFH-LABEL: log_f16:
+; RV64IZFH: # %bb.0:
+; RV64IZFH-NEXT: addi sp, sp, -16
+; RV64IZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IZFH-NEXT: call logf at plt
+; RV64IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFH-NEXT: addi sp, sp, 16
+; RV64IZFH-NEXT: ret
+;
+; RV32IDZFH-LABEL: log_f16:
+; RV32IDZFH: # %bb.0:
+; RV32IDZFH-NEXT: addi sp, sp, -16
+; RV32IDZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IDZFH-NEXT: call logf at plt
+; RV32IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IDZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IDZFH-NEXT: addi sp, sp, 16
+; RV32IDZFH-NEXT: ret
+;
+; RV64IDZFH-LABEL: log_f16:
+; RV64IDZFH: # %bb.0:
+; RV64IDZFH-NEXT: addi sp, sp, -16
+; RV64IDZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IDZFH-NEXT: call logf at plt
+; RV64IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IDZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: addi sp, sp, 16
+; RV64IDZFH-NEXT: ret
+;
+; RV32I-LABEL: log_f16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lui a1, 16
+; RV32I-NEXT: addi a1, a1, -1
+; RV32I-NEXT: and a0, a0, a1
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: call logf at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: log_f16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lui a1, 16
+; RV64I-NEXT: addiw a1, a1, -1
+; RV64I-NEXT: and a0, a0, a1
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: call logf at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call half @llvm.log.f16(half %a)
+ ret half %1
+}
+
+declare half @llvm.log10.f16(half)
+
+define half @log10_f16(half %a) nounwind {
+; RV32IZFH-LABEL: log10_f16:
+; RV32IZFH: # %bb.0:
+; RV32IZFH-NEXT: addi sp, sp, -16
+; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IZFH-NEXT: call log10f at plt
+; RV32IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: addi sp, sp, 16
+; RV32IZFH-NEXT: ret
+;
+; RV64IZFH-LABEL: log10_f16:
+; RV64IZFH: # %bb.0:
+; RV64IZFH-NEXT: addi sp, sp, -16
+; RV64IZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IZFH-NEXT: call log10f at plt
+; RV64IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFH-NEXT: addi sp, sp, 16
+; RV64IZFH-NEXT: ret
+;
+; RV32IDZFH-LABEL: log10_f16:
+; RV32IDZFH: # %bb.0:
+; RV32IDZFH-NEXT: addi sp, sp, -16
+; RV32IDZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IDZFH-NEXT: call log10f at plt
+; RV32IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IDZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IDZFH-NEXT: addi sp, sp, 16
+; RV32IDZFH-NEXT: ret
+;
+; RV64IDZFH-LABEL: log10_f16:
+; RV64IDZFH: # %bb.0:
+; RV64IDZFH-NEXT: addi sp, sp, -16
+; RV64IDZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IDZFH-NEXT: call log10f at plt
+; RV64IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IDZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: addi sp, sp, 16
+; RV64IDZFH-NEXT: ret
+;
+; RV32I-LABEL: log10_f16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lui a1, 16
+; RV32I-NEXT: addi a1, a1, -1
+; RV32I-NEXT: and a0, a0, a1
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: call log10f at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: log10_f16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lui a1, 16
+; RV64I-NEXT: addiw a1, a1, -1
+; RV64I-NEXT: and a0, a0, a1
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: call log10f at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call half @llvm.log10.f16(half %a)
+ ret half %1
+}
+
+declare half @llvm.log2.f16(half)
+
+define half @log2_f16(half %a) nounwind {
+; RV32IZFH-LABEL: log2_f16:
+; RV32IZFH: # %bb.0:
+; RV32IZFH-NEXT: addi sp, sp, -16
+; RV32IZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IZFH-NEXT: call log2f at plt
+; RV32IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFH-NEXT: addi sp, sp, 16
+; RV32IZFH-NEXT: ret
+;
+; RV64IZFH-LABEL: log2_f16:
+; RV64IZFH: # %bb.0:
+; RV64IZFH-NEXT: addi sp, sp, -16
+; RV64IZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IZFH-NEXT: call log2f at plt
+; RV64IZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFH-NEXT: addi sp, sp, 16
+; RV64IZFH-NEXT: ret
+;
+; RV32IDZFH-LABEL: log2_f16:
+; RV32IDZFH: # %bb.0:
+; RV32IDZFH-NEXT: addi sp, sp, -16
+; RV32IDZFH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV32IDZFH-NEXT: call log2f at plt
+; RV32IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV32IDZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IDZFH-NEXT: addi sp, sp, 16
+; RV32IDZFH-NEXT: ret
+;
+; RV64IDZFH-LABEL: log2_f16:
+; RV64IDZFH: # %bb.0:
+; RV64IDZFH-NEXT: addi sp, sp, -16
+; RV64IDZFH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IDZFH-NEXT: fcvt.s.h fa0, fa0
+; RV64IDZFH-NEXT: call log2f at plt
+; RV64IDZFH-NEXT: fcvt.h.s fa0, fa0
+; RV64IDZFH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IDZFH-NEXT: addi sp, sp, 16
+; RV64IDZFH-NEXT: ret
+;
+; RV32I-LABEL: log2_f16:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: lui a1, 16
+; RV32I-NEXT: addi a1, a1, -1
+; RV32I-NEXT: and a0, a0, a1
+; RV32I-NEXT: call __gnu_h2f_ieee at plt
+; RV32I-NEXT: call log2f at plt
+; RV32I-NEXT: call __gnu_f2h_ieee at plt
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: log2_f16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: lui a1, 16
+; RV64I-NEXT: addiw a1, a1, -1
+; RV64I-NEXT: and a0, a0, a1
+; RV64I-NEXT: call __gnu_h2f_ieee at plt
+; RV64I-NEXT: call log2f at plt
+; RV64I-NEXT: call __gnu_f2h_ieee at plt
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %1 = call half @llvm.log2.f16(half %a)
+ ret half %1
+}
+
declare half @llvm.fma.f16(half, half, half)
define half @fma_f16(half %a, half %b, half %c) nounwind {
@@ -462,6 +1359,23 @@ define half @maxnum_f16(half %a, half %b) nounwind {
ret half %1
}
+; TODO: FMINNAN and FMAXNAN aren't handled in
+; SelectionDAGLegalize::ExpandNode.
+
+; declare half @llvm.minimum.f16(half, half)
+
+; define half @fminimum_f16(half %a, half %b) nounwind {
+; %1 = call half @llvm.minimum.f16(half %a, half %b)
+; ret half %1
+; }
+
+; declare half @llvm.maximum.f16(half, half)
+
+; define half @fmaximum_f16(half %a, half %b) nounwind {
+; %1 = call half @llvm.maximum.f16(half %a, half %b)
+; ret half %1
+; }
+
declare half @llvm.copysign.f16(half, half)
define half @copysign_f16(half %a, half %b) nounwind {
More information about the llvm-commits
mailing list