Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -14741,6 +14741,47 @@ When specified with the fast-math-flag 'afn', the result may be approximated using a less accurate calculation. +.. _int_exp10: + +'``llvm.exp10.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.exp10`` on any +floating-point or vector of floating-point type. Not all targets support +all types however. + +:: + + declare float @llvm.exp10.f32(float %Val) + declare double @llvm.exp10.f64(double %Val) + declare x86_fp80 @llvm.exp10.f80(x86_fp80 %Val) + declare fp128 @llvm.exp10.f128(fp128 %Val) + declare ppc_fp128 @llvm.exp10.ppcf128(ppc_fp128 %Val) + +Overview: +""""""""" + +The '``llvm.exp10.*``' intrinsics compute the base-10 exponential of the +specified value. + +Arguments: +"""""""""" + +The argument and return value are floating-point numbers of the same type. + +Semantics: +"""""""""" + +Return the same value as a corresponding libm '``exp10``' function but without +trapping or setting ``errno``. + +When specified with the fast-math-flag 'afn', the result may be approximated +using a less accurate calculation. + + '``llvm.ldexp.*``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Index: llvm/docs/ReleaseNotes.rst =================================================================== --- llvm/docs/ReleaseNotes.rst +++ llvm/docs/ReleaseNotes.rst @@ -53,6 +53,8 @@ * The `llvm.stacksave` and `llvm.stackrestore` intrinsics now use an overloaded pointer type to support non-0 address spaces. +* Added `llvm.exp10` intrinsic. + Changes to LLVM infrastructure ------------------------------ Index: llvm/include/llvm/CodeGen/BasicTTIImpl.h =================================================================== --- llvm/include/llvm/CodeGen/BasicTTIImpl.h +++ llvm/include/llvm/CodeGen/BasicTTIImpl.h @@ -1788,6 +1788,9 @@ case Intrinsic::exp2: ISD = ISD::FEXP2; break; + case Intrinsic::exp10: + ISD = ISD::FEXP10; + break; case Intrinsic::log: ISD = ISD::FLOG; break; Index: llvm/include/llvm/CodeGen/ISDOpcodes.h =================================================================== --- llvm/include/llvm/CodeGen/ISDOpcodes.h +++ llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -942,6 +942,7 @@ FLOG10, FEXP, FEXP2, + FEXP10, FCEIL, FTRUNC, FRINT, Index: llvm/include/llvm/IR/Intrinsics.td =================================================================== --- llvm/include/llvm/IR/Intrinsics.td +++ llvm/include/llvm/IR/Intrinsics.td @@ -1004,6 +1004,7 @@ def int_log2 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_exp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_exp2 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_exp10 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_fabs : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_copysign : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; Index: llvm/include/llvm/IR/RuntimeLibcalls.def =================================================================== --- llvm/include/llvm/IR/RuntimeLibcalls.def +++ llvm/include/llvm/IR/RuntimeLibcalls.def @@ -182,6 +182,11 @@ HANDLE_LIBCALL(EXP2_FINITE_F80, "__exp2l_finite") HANDLE_LIBCALL(EXP2_FINITE_F128, "__exp2l_finite") HANDLE_LIBCALL(EXP2_FINITE_PPCF128, "__exp2l_finite") +HANDLE_LIBCALL(EXP10_F32, "exp10f") +HANDLE_LIBCALL(EXP10_F64, "exp10") +HANDLE_LIBCALL(EXP10_F80, "exp10l") +HANDLE_LIBCALL(EXP10_F128, "exp10l") +HANDLE_LIBCALL(EXP10_PPCF128, "exp10l") HANDLE_LIBCALL(SIN_F32, "sinf") HANDLE_LIBCALL(SIN_F64, "sin") HANDLE_LIBCALL(SIN_F80, "sinl") Index: llvm/include/llvm/Support/TargetOpcodes.def =================================================================== --- llvm/include/llvm/Support/TargetOpcodes.def +++ llvm/include/llvm/Support/TargetOpcodes.def @@ -613,6 +613,9 @@ /// Generic base-2 exponential of a value. HANDLE_TARGET_OPCODE(G_FEXP2) +/// Generic base-10 exponential of a value. +HANDLE_TARGET_OPCODE(G_FEXP10) + /// Floating point base-e logarithm of a value. HANDLE_TARGET_OPCODE(G_FLOG) Index: llvm/include/llvm/Target/GenericOpcodes.td =================================================================== --- llvm/include/llvm/Target/GenericOpcodes.td +++ llvm/include/llvm/Target/GenericOpcodes.td @@ -914,6 +914,13 @@ let hasSideEffects = false; } +// Floating point base-10 exponential of a value. +def G_FEXP10 : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1); + let hasSideEffects = false; +} + // Floating point base-e logarithm of a value. def G_FLOG : GenericInstruction { let OutOperandList = (outs type0:$dst); Index: llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td =================================================================== --- llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -106,6 +106,7 @@ def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; +def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; Index: llvm/include/llvm/Target/TargetSelectionDAG.td =================================================================== --- llvm/include/llvm/Target/TargetSelectionDAG.td +++ llvm/include/llvm/Target/TargetSelectionDAG.td @@ -504,6 +504,7 @@ def fsin : SDNode<"ISD::FSIN" , SDTFPUnaryOp>; def fcos : SDNode<"ISD::FCOS" , SDTFPUnaryOp>; def fexp2 : SDNode<"ISD::FEXP2" , SDTFPUnaryOp>; +def fexp10 : SDNode<"ISD::FEXP10" , SDTFPUnaryOp>; def fpow : SDNode<"ISD::FPOW" , SDTFPBinOp>; def flog2 : SDNode<"ISD::FLOG2" , SDTFPUnaryOp>; def fldexp : SDNode<"ISD::FLDEXP" , SDTFPExpOp>; Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1742,6 +1742,8 @@ return TargetOpcode::G_FEXP; case Intrinsic::exp2: return TargetOpcode::G_FEXP2; + case Intrinsic::exp10: + return TargetOpcode::G_FEXP10; case Intrinsic::fabs: return TargetOpcode::G_FABS; case Intrinsic::copysign: Index: llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -525,6 +525,8 @@ RTLIBCASE(EXP_F); case TargetOpcode::G_FEXP2: RTLIBCASE(EXP2_F); + case TargetOpcode::G_FEXP10: + RTLIBCASE(EXP10_F); case TargetOpcode::G_FREM: RTLIBCASE(REM_F); case TargetOpcode::G_FPOW: @@ -830,6 +832,7 @@ case TargetOpcode::G_FLDEXP: case TargetOpcode::G_FEXP: case TargetOpcode::G_FEXP2: + case TargetOpcode::G_FEXP10: case TargetOpcode::G_FCEIL: case TargetOpcode::G_FFLOOR: case TargetOpcode::G_FMINNUM: @@ -2545,6 +2548,7 @@ case TargetOpcode::G_FSQRT: case TargetOpcode::G_FEXP: case TargetOpcode::G_FEXP2: + case TargetOpcode::G_FEXP10: case TargetOpcode::G_FPOW: case TargetOpcode::G_INTRINSIC_TRUNC: case TargetOpcode::G_INTRINSIC_ROUND: @@ -4187,6 +4191,7 @@ case G_FPOW: case G_FEXP: case G_FEXP2: + case G_FEXP10: case G_FLOG: case G_FLOG2: case G_FLOG10: Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -4418,6 +4418,10 @@ ExpandFPLibCall(Node, RTLIB::EXP2_F32, RTLIB::EXP2_F64, RTLIB::EXP2_F80, RTLIB::EXP2_F128, RTLIB::EXP2_PPCF128, Results); break; + case ISD::FEXP10: + ExpandFPLibCall(Node, RTLIB::EXP10_F32, RTLIB::EXP10_F64, RTLIB::EXP10_F80, + RTLIB::EXP10_F128, RTLIB::EXP10_PPCF128, Results); + break; case ISD::FTRUNC: case ISD::STRICT_FTRUNC: ExpandFPLibCall(Node, RTLIB::TRUNC_F32, RTLIB::TRUNC_F64, @@ -5261,6 +5265,7 @@ case ISD::FABS: case ISD::FEXP: case ISD::FEXP2: + case ISD::FEXP10: Tmp1 = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Node->getOperand(0)); Tmp2 = DAG.getNode(Node->getOpcode(), dl, NVT, Tmp1); Results.push_back( Index: llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -88,6 +88,7 @@ case ISD::FEXP: R = SoftenFloatRes_FEXP(N); break; case ISD::STRICT_FEXP2: case ISD::FEXP2: R = SoftenFloatRes_FEXP2(N); break; + case ISD::FEXP10: R = SoftenFloatRes_FEXP10(N); break; case ISD::STRICT_FFLOOR: case ISD::FFLOOR: R = SoftenFloatRes_FFLOOR(N); break; case ISD::STRICT_FLOG: @@ -414,6 +415,13 @@ RTLIB::EXP2_PPCF128)); } +SDValue DAGTypeLegalizer::SoftenFloatRes_FEXP10(SDNode *N) { + return SoftenFloatRes_Unary( + N, + GetFPLibCall(N->getValueType(0), RTLIB::EXP10_F32, RTLIB::EXP10_F64, + RTLIB::EXP10_F80, RTLIB::EXP10_F128, RTLIB::EXP10_PPCF128)); +} + SDValue DAGTypeLegalizer::SoftenFloatRes_FFLOOR(SDNode *N) { return SoftenFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), RTLIB::FLOOR_F32, @@ -1305,6 +1313,7 @@ case ISD::FEXP: ExpandFloatRes_FEXP(N, Lo, Hi); break; case ISD::STRICT_FEXP2: case ISD::FEXP2: ExpandFloatRes_FEXP2(N, Lo, Hi); break; + case ISD::FEXP10: ExpandFloatRes_FEXP10(N, Lo, Hi); break; case ISD::STRICT_FFLOOR: case ISD::FFLOOR: ExpandFloatRes_FFLOOR(N, Lo, Hi); break; case ISD::STRICT_FLOG: @@ -1500,6 +1509,15 @@ RTLIB::EXP2_PPCF128), Lo, Hi); } +void DAGTypeLegalizer::ExpandFloatRes_FEXP10(SDNode *N, SDValue &Lo, + SDValue &Hi) { + ExpandFloatRes_Unary(N, + GetFPLibCall(N->getValueType(0), RTLIB::EXP10_F32, + RTLIB::EXP10_F64, RTLIB::EXP10_F80, + RTLIB::EXP10_F128, RTLIB::EXP10_PPCF128), + Lo, Hi); +} + void DAGTypeLegalizer::ExpandFloatRes_FFLOOR(SDNode *N, SDValue &Lo, SDValue &Hi) { ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), @@ -2340,6 +2358,7 @@ case ISD::FCOS: case ISD::FEXP: case ISD::FEXP2: + case ISD::FEXP10: case ISD::FFLOOR: case ISD::FLOG: case ISD::FLOG2: @@ -2721,6 +2740,7 @@ case ISD::FCOS: case ISD::FEXP: case ISD::FEXP2: + case ISD::FEXP10: case ISD::FFLOOR: case ISD::FLOG: case ISD::FLOG2: Index: llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -551,6 +551,7 @@ SDValue SoftenFloatRes_FDIV(SDNode *N); SDValue SoftenFloatRes_FEXP(SDNode *N); SDValue SoftenFloatRes_FEXP2(SDNode *N); + SDValue SoftenFloatRes_FEXP10(SDNode *N); SDValue SoftenFloatRes_FFLOOR(SDNode *N); SDValue SoftenFloatRes_FLOG(SDNode *N); SDValue SoftenFloatRes_FLOG2(SDNode *N); @@ -632,6 +633,7 @@ void ExpandFloatRes_FDIV (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandFloatRes_FEXP (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandFloatRes_FEXP2 (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FEXP10 (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandFloatRes_FFLOOR (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandFloatRes_FLOG (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandFloatRes_FLOG2 (SDNode *N, SDValue &Lo, SDValue &Hi); Index: llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @@ -385,6 +385,7 @@ case ISD::FLOG10: case ISD::FEXP: case ISD::FEXP2: + case ISD::FEXP10: case ISD::FCEIL: case ISD::FTRUNC: case ISD::FRINT: Index: llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -88,6 +88,7 @@ case ISD::FCOS: case ISD::FEXP: case ISD::FEXP2: + case ISD::FEXP10: case ISD::FFLOOR: case ISD::FLOG: case ISD::FLOG10: @@ -1075,6 +1076,7 @@ case ISD::FCOS: case ISD::FEXP: case ISD::FEXP2: + case ISD::FEXP10: case ISD::FFLOOR: case ISD::VP_FFLOOR: case ISD::FLOG: @@ -4200,6 +4202,7 @@ case ISD::FCOS: case ISD::FEXP: case ISD::FEXP2: + case ISD::FEXP10: case ISD::FFLOOR: case ISD::FLOG: case ISD::FLOG10: Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4953,6 +4953,7 @@ case ISD::FCANONICALIZE: case ISD::FEXP: case ISD::FEXP2: + case ISD::FEXP10: case ISD::FTRUNC: case ISD::FFLOOR: case ISD::FCEIL: Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6381,6 +6381,7 @@ case Intrinsic::fabs: case Intrinsic::sin: case Intrinsic::cos: + case Intrinsic::exp10: case Intrinsic::floor: case Intrinsic::ceil: case Intrinsic::trunc: @@ -6396,6 +6397,7 @@ case Intrinsic::fabs: Opcode = ISD::FABS; break; case Intrinsic::sin: Opcode = ISD::FSIN; break; case Intrinsic::cos: Opcode = ISD::FCOS; break; + case Intrinsic::exp10: Opcode = ISD::FEXP10; break; case Intrinsic::floor: Opcode = ISD::FFLOOR; break; case Intrinsic::ceil: Opcode = ISD::FCEIL; break; case Intrinsic::trunc: Opcode = ISD::FTRUNC; break; @@ -8659,6 +8661,12 @@ if (visitUnaryFloatCall(I, ISD::FEXP2)) return; break; + case LibFunc_exp10: + case LibFunc_exp10f: + case LibFunc_exp10l: + if (visitUnaryFloatCall(I, ISD::FEXP10)) + return; + break; case LibFunc_ldexp: case LibFunc_ldexpf: case LibFunc_ldexpl: Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp @@ -222,6 +222,7 @@ case ISD::STRICT_FEXP: return "strict_fexp"; case ISD::FEXP2: return "fexp2"; case ISD::STRICT_FEXP2: return "strict_fexp2"; + case ISD::FEXP10: return "fexp10"; case ISD::FLOG: return "flog"; case ISD::STRICT_FLOG: return "strict_flog"; case ISD::FLOG2: return "flog2"; Index: llvm/lib/CodeGen/TargetLoweringBase.cpp =================================================================== --- llvm/lib/CodeGen/TargetLoweringBase.cpp +++ llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -926,9 +926,9 @@ // These library functions default to expand. setOperationAction({ISD::FCBRT, ISD::FLOG, ISD::FLOG2, ISD::FLOG10, ISD::FEXP, - ISD::FEXP2, ISD::FFLOOR, ISD::FNEARBYINT, ISD::FCEIL, - ISD::FRINT, ISD::FTRUNC, ISD::LROUND, ISD::LLROUND, - ISD::LRINT, ISD::LLRINT}, + ISD::FEXP2, ISD::FEXP10, ISD::FFLOOR, ISD::FNEARBYINT, + ISD::FCEIL, ISD::FRINT, ISD::FTRUNC, ISD::LROUND, + ISD::LLROUND, ISD::LRINT, ISD::LLRINT}, {MVT::f32, MVT::f64, MVT::f128}, Expand); // Default ISD::TRAP to expand (which turns it into abort). Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -677,8 +677,9 @@ for (auto Op : {ISD::FREM, ISD::FPOW, ISD::FPOWI, ISD::FCOS, ISD::FSIN, ISD::FSINCOS, - ISD::FEXP, ISD::FEXP2, ISD::FLOG, - ISD::FLOG2, ISD::FLOG10, ISD::STRICT_FREM, + ISD::FEXP, ISD::FEXP2, ISD::FEXP10, + ISD::FLOG, ISD::FLOG2, ISD::FLOG10, + ISD::STRICT_FREM, ISD::STRICT_FPOW, ISD::STRICT_FPOWI, ISD::STRICT_FCOS, ISD::STRICT_FSIN, ISD::STRICT_FEXP, ISD::STRICT_FEXP2, ISD::STRICT_FLOG, ISD::STRICT_FLOG2, ISD::STRICT_FLOG10}) { @@ -1474,6 +1475,7 @@ setOperationAction(ISD::FSINCOS, VT, Expand); setOperationAction(ISD::FEXP, VT, Expand); setOperationAction(ISD::FEXP2, VT, Expand); + setOperationAction(ISD::FEXP10, VT, Expand); setOperationAction(ISD::FLOG, VT, Expand); setOperationAction(ISD::FLOG2, VT, Expand); setOperationAction(ISD::FLOG10, VT, Expand); @@ -1643,6 +1645,7 @@ setOperationAction(ISD::FLOG10, VT, Expand); setOperationAction(ISD::FEXP, VT, Expand); setOperationAction(ISD::FEXP2, VT, Expand); + setOperationAction(ISD::FEXP10, VT, Expand); } // But we do support custom-lowering for FCOPYSIGN. Index: llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -265,7 +265,7 @@ .legalFor({s16, s32, s64, v2s32, v4s32, v2s64, v2s16, v4s16, v8s16}); getActionDefinitionsBuilder( - {G_FCOS, G_FSIN, G_FLOG10, G_FLOG, G_FLOG2, G_FEXP, G_FEXP2, G_FPOW}) + {G_FCOS, G_FSIN, G_FLOG10, G_FLOG, G_FLOG2, G_FEXP, G_FEXP2, G_FEXP10, G_FPOW}) // We need a call for these, so we always need to scalarize. .scalarize(0) // Regardless of FP16 support, widen 16-bit elements to 32-bits. Index: llvm/lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- llvm/lib/Target/ARM/ARMISelLowering.cpp +++ llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -371,6 +371,7 @@ setOperationAction(ISD::FLOG10, VT, Expand); setOperationAction(ISD::FEXP, VT, Expand); setOperationAction(ISD::FEXP2, VT, Expand); + setOperationAction(ISD::FEXP10, VT, Expand); setOperationAction(ISD::FNEARBYINT, VT, Expand); } } @@ -880,6 +881,7 @@ setOperationAction(ISD::FLOG10, MVT::v2f64, Expand); setOperationAction(ISD::FEXP, MVT::v2f64, Expand); setOperationAction(ISD::FEXP2, MVT::v2f64, Expand); + setOperationAction(ISD::FEXP10, MVT::v2f64, Expand); // FIXME: Create unittest for FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR. setOperationAction(ISD::FCEIL, MVT::v2f64, Expand); setOperationAction(ISD::FTRUNC, MVT::v2f64, Expand); @@ -901,6 +903,7 @@ setOperationAction(ISD::FLOG10, MVT::v4f32, Expand); setOperationAction(ISD::FEXP, MVT::v4f32, Expand); setOperationAction(ISD::FEXP2, MVT::v4f32, Expand); + setOperationAction(ISD::FEXP10, MVT::v4f32, Expand); setOperationAction(ISD::FCEIL, MVT::v4f32, Expand); setOperationAction(ISD::FTRUNC, MVT::v4f32, Expand); setOperationAction(ISD::FRINT, MVT::v4f32, Expand); @@ -917,6 +920,7 @@ setOperationAction(ISD::FLOG10, MVT::v2f32, Expand); setOperationAction(ISD::FEXP, MVT::v2f32, Expand); setOperationAction(ISD::FEXP2, MVT::v2f32, Expand); + setOperationAction(ISD::FEXP10, MVT::v2f32, Expand); setOperationAction(ISD::FCEIL, MVT::v2f32, Expand); setOperationAction(ISD::FTRUNC, MVT::v2f32, Expand); setOperationAction(ISD::FRINT, MVT::v2f32, Expand); @@ -1058,6 +1062,7 @@ setOperationAction(ISD::FLOG10, MVT::f64, Expand); setOperationAction(ISD::FEXP, MVT::f64, Expand); setOperationAction(ISD::FEXP2, MVT::f64, Expand); + setOperationAction(ISD::FEXP10, MVT::f64, Expand); setOperationAction(ISD::FCEIL, MVT::f64, Expand); setOperationAction(ISD::FTRUNC, MVT::f64, Expand); setOperationAction(ISD::FRINT, MVT::f64, Expand); @@ -1534,6 +1539,7 @@ setOperationAction(ISD::FPOW, MVT::f16, Promote); setOperationAction(ISD::FEXP, MVT::f16, Promote); setOperationAction(ISD::FEXP2, MVT::f16, Promote); + setOperationAction(ISD::FEXP10, MVT::f16, Promote); setOperationAction(ISD::FLOG, MVT::f16, Promote); setOperationAction(ISD::FLOG10, MVT::f16, Promote); setOperationAction(ISD::FLOG2, MVT::f16, Promote); Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -423,7 +423,8 @@ Subtarget.hasStdExtZfa() ? Legal : Promote); setOperationAction({ISD::FREM, ISD::FPOW, ISD::FPOWI, ISD::FCOS, ISD::FSIN, ISD::FSINCOS, ISD::FEXP, - ISD::FEXP2, ISD::FLOG, ISD::FLOG2, ISD::FLOG10}, + ISD::FEXP2, ISD::FEXP10, ISD::FLOG, ISD::FLOG2, + ISD::FLOG10}, MVT::f16, Promote); // FIXME: Need to promote f16 STRICT_* to f32 libcalls, but we don't have @@ -852,6 +853,7 @@ setOperationAction(ISD::FSINCOS, VT, Expand); setOperationAction(ISD::FEXP, VT, Expand); setOperationAction(ISD::FEXP2, VT, Expand); + setOperationAction(ISD::FEXP10, VT, Expand); setOperationAction(ISD::FLOG, VT, Expand); setOperationAction(ISD::FLOG2, VT, Expand); setOperationAction(ISD::FLOG10, VT, Expand); Index: llvm/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.cpp +++ llvm/lib/Target/X86/X86ISelLowering.cpp @@ -576,6 +576,7 @@ setOperationAction(ISD::FLOG10, VT, Action); setOperationAction(ISD::FEXP, VT, Action); setOperationAction(ISD::FEXP2, VT, Action); + setOperationAction(ISD::FEXP10, VT, Action); setOperationAction(ISD::FCEIL, VT, Action); setOperationAction(ISD::FFLOOR, VT, Action); setOperationAction(ISD::FNEARBYINT, VT, Action); @@ -888,6 +889,7 @@ setOperationAction(ISD::FLOG10, MVT::f80, Expand); setOperationAction(ISD::FEXP, MVT::f80, Expand); setOperationAction(ISD::FEXP2, MVT::f80, Expand); + setOperationAction(ISD::FEXP10, MVT::f80, Expand); setOperationAction(ISD::FMINNUM, MVT::f80, Expand); setOperationAction(ISD::FMAXNUM, MVT::f80, Expand); @@ -906,6 +908,7 @@ setOperationAction(ISD::FLOG10, VT, Expand); setOperationAction(ISD::FEXP, VT, Expand); setOperationAction(ISD::FEXP2, VT, Expand); + setOperationAction(ISD::FEXP10, VT, Expand); } // First set operation action for all vector types to either promote Index: llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir =================================================================== --- llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -470,6 +470,10 @@ # DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}} # DEBUG-NEXT: .. the first uncovered type index: 1, OK # DEBUG-NEXT: .. the first uncovered imm index: 0, OK +# DEBUG-NEXT: G_FEXP10 (opcode {{[0-9]+}}): 1 type index, 0 imm indices +# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}} +# DEBUG-NEXT: .. the first uncovered type index: 1, OK +# DEBUG-NEXT: .. the first uncovered imm index: 0, OK # DEBUG-NEXT: G_FLOG (opcode {{[0-9]+}}): 1 type index, 0 imm indices # DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}} # DEBUG-NEXT: .. the first uncovered type index: 1, OK Index: llvm/test/CodeGen/AArch64/llvm.exp10.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/llvm.exp10.ll @@ -0,0 +1,739 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -global-isel=0 -mtriple=aarch64-unknown-unknown < %s | FileCheck -check-prefixes=CHECK,CVT,SDAG,CVT-SDAG %s +; RUN: llc -global-isel=0 -mtriple=aarch64-unknown-unknown -mattr=+fullfp16 < %s | FileCheck -check-prefixes=CHECK,FP16,SDAG,FP16-SDAG %s +; RUN: llc -global-isel=1 -mtriple=aarch64-unknown-unknown < %s | FileCheck -check-prefixes=CHECK,CVT,GISEL,CVT-GISEL %s +; RUN: llc -global-isel=1 -mtriple=aarch64-unknown-unknown -mattr=+fullfp16 < %s | FileCheck -check-prefixes=CHECK,FP16,GISEL,FP16-GISEL %s + +declare half @llvm.exp10.f16(half) +declare <1 x half> @llvm.exp10.v1f16(<1 x half>) +declare <2 x half> @llvm.exp10.v2f16(<2 x half>) +declare <3 x half> @llvm.exp10.v3f16(<3 x half>) +declare <4 x half> @llvm.exp10.v4f16(<4 x half>) +declare float @llvm.exp10.f32(float) +declare <1 x float> @llvm.exp10.v1f32(<1 x float>) +declare <2 x float> @llvm.exp10.v2f32(<2 x float>) +declare <3 x float> @llvm.exp10.v3f32(<3 x float>) +declare <4 x float> @llvm.exp10.v4f32(<4 x float>) +declare double @llvm.exp10.f64(double) +declare <1 x double> @llvm.exp10.v1f64(<1 x double>) +declare <2 x double> @llvm.exp10.v2f64(<2 x double>) +declare <3 x double> @llvm.exp10.v3f64(<3 x double>) +declare <4 x double> @llvm.exp10.v4f64(<4 x double>) + +define half @exp10_f16(half %x) { +; CHECK-LABEL: exp10_f16: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: fcvt s0, h0 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: fcvt h0, s0 +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret + %r = call half @llvm.exp10.f16(half %x) + ret half %r +} + +define <1 x half> @exp10_v1f16(<1 x half> %x) { +; CHECK-LABEL: exp10_v1f16: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: fcvt s0, h0 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: fcvt h0, s0 +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret + %r = call <1 x half> @llvm.exp10.v1f16(<1 x half> %x) + ret <1 x half> %r +} + +define <2 x half> @exp10_v2f16(<2 x half> %x) { +; SDAG-LABEL: exp10_v2f16: +; SDAG: // %bb.0: +; SDAG-NEXT: sub sp, sp, #48 +; SDAG-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; SDAG-NEXT: .cfi_def_cfa_offset 48 +; SDAG-NEXT: .cfi_offset w30, -16 +; SDAG-NEXT: // kill: def $d0 killed $d0 def $q0 +; SDAG-NEXT: mov h1, v0.h[1] +; SDAG-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; SDAG-NEXT: fcvt s0, h1 +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: fcvt h0, s0 +; SDAG-NEXT: fcvt s1, h1 +; SDAG-NEXT: str q0, [sp] // 16-byte Folded Spill +; SDAG-NEXT: fmov s0, s1 +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: fcvt h2, s0 +; SDAG-NEXT: mov h1, v1.h[2] +; SDAG-NEXT: fcvt s0, h1 +; SDAG-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; SDAG-NEXT: mov v2.h[1], v1.h[0] +; SDAG-NEXT: str q2, [sp] // 16-byte Folded Spill +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: fcvt h2, s0 +; SDAG-NEXT: mov h1, v1.h[3] +; SDAG-NEXT: fcvt s0, h1 +; SDAG-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; SDAG-NEXT: mov v1.h[2], v2.h[0] +; SDAG-NEXT: str q1, [sp] // 16-byte Folded Spill +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: fcvt h1, s0 +; SDAG-NEXT: ldr q0, [sp] // 16-byte Folded Reload +; SDAG-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; SDAG-NEXT: mov v0.h[3], v1.h[0] +; SDAG-NEXT: // kill: def $d0 killed $d0 killed $q0 +; SDAG-NEXT: add sp, sp, #48 +; SDAG-NEXT: ret +; +; GISEL-LABEL: exp10_v2f16: +; GISEL: // %bb.0: +; GISEL-NEXT: sub sp, sp, #32 +; GISEL-NEXT: str d8, [sp, #16] // 8-byte Folded Spill +; GISEL-NEXT: str x30, [sp, #24] // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 32 +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset b8, -16 +; GISEL-NEXT: fmov x8, d0 +; GISEL-NEXT: fmov s0, w8 +; GISEL-NEXT: mov h8, v0.h[1] +; GISEL-NEXT: fcvt s0, h0 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: fcvt s1, h8 +; GISEL-NEXT: fcvt h0, s0 +; GISEL-NEXT: str q0, [sp] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s1 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: fcvt h0, s0 +; GISEL-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; GISEL-NEXT: ldr x30, [sp, #24] // 8-byte Folded Reload +; GISEL-NEXT: ldr d8, [sp, #16] // 8-byte Folded Reload +; GISEL-NEXT: mov v1.h[1], v0.h[0] +; GISEL-NEXT: mov v1.h[2], v0.h[0] +; GISEL-NEXT: mov v1.h[3], v0.h[0] +; GISEL-NEXT: mov v0.16b, v1.16b +; GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0 +; GISEL-NEXT: add sp, sp, #32 +; GISEL-NEXT: ret + %r = call <2 x half> @llvm.exp10.v2f16(<2 x half> %x) + ret <2 x half> %r +} + +define <3 x half> @exp10_v3f16(<3 x half> %x) { +; SDAG-LABEL: exp10_v3f16: +; SDAG: // %bb.0: +; SDAG-NEXT: sub sp, sp, #48 +; SDAG-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; SDAG-NEXT: .cfi_def_cfa_offset 48 +; SDAG-NEXT: .cfi_offset w30, -16 +; SDAG-NEXT: // kill: def $d0 killed $d0 def $q0 +; SDAG-NEXT: mov h1, v0.h[1] +; SDAG-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; SDAG-NEXT: fcvt s0, h1 +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: fcvt h0, s0 +; SDAG-NEXT: fcvt s1, h1 +; SDAG-NEXT: str q0, [sp] // 16-byte Folded Spill +; SDAG-NEXT: fmov s0, s1 +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: fcvt h2, s0 +; SDAG-NEXT: mov h1, v1.h[2] +; SDAG-NEXT: fcvt s0, h1 +; SDAG-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; SDAG-NEXT: mov v2.h[1], v1.h[0] +; SDAG-NEXT: str q2, [sp] // 16-byte Folded Spill +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: fcvt h2, s0 +; SDAG-NEXT: mov h1, v1.h[3] +; SDAG-NEXT: fcvt s0, h1 +; SDAG-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; SDAG-NEXT: mov v1.h[2], v2.h[0] +; SDAG-NEXT: str q1, [sp] // 16-byte Folded Spill +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: fcvt h1, s0 +; SDAG-NEXT: ldr q0, [sp] // 16-byte Folded Reload +; SDAG-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; SDAG-NEXT: mov v0.h[3], v1.h[0] +; SDAG-NEXT: // kill: def $d0 killed $d0 killed $q0 +; SDAG-NEXT: add sp, sp, #48 +; SDAG-NEXT: ret +; +; GISEL-LABEL: exp10_v3f16: +; GISEL: // %bb.0: +; GISEL-NEXT: sub sp, sp, #64 +; GISEL-NEXT: stp d9, d8, [sp, #32] // 16-byte Folded Spill +; GISEL-NEXT: str x30, [sp, #48] // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 64 +; GISEL-NEXT: .cfi_offset w30, -16 +; GISEL-NEXT: .cfi_offset b8, -24 +; GISEL-NEXT: .cfi_offset b9, -32 +; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 +; GISEL-NEXT: mov h8, v0.h[1] +; GISEL-NEXT: mov h9, v0.h[2] +; GISEL-NEXT: fcvt s0, h0 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: fcvt s1, h8 +; GISEL-NEXT: fcvt h0, s0 +; GISEL-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s1 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: fcvt s1, h9 +; GISEL-NEXT: fcvt h0, s0 +; GISEL-NEXT: str q0, [sp] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s1 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: ldp q2, q1, [sp] // 32-byte Folded Reload +; GISEL-NEXT: fcvt h0, s0 +; GISEL-NEXT: mov v1.h[1], v2.h[0] +; GISEL-NEXT: ldr x30, [sp, #48] // 8-byte Folded Reload +; GISEL-NEXT: ldp d9, d8, [sp, #32] // 16-byte Folded Reload +; GISEL-NEXT: mov v1.h[2], v0.h[0] +; GISEL-NEXT: mov v1.h[3], v0.h[0] +; GISEL-NEXT: mov v0.16b, v1.16b +; GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0 +; GISEL-NEXT: add sp, sp, #64 +; GISEL-NEXT: ret + %r = call <3 x half> @llvm.exp10.v3f16(<3 x half> %x) + ret <3 x half> %r +} + +define <4 x half> @exp10_v4f16(<4 x half> %x) { +; SDAG-LABEL: exp10_v4f16: +; SDAG: // %bb.0: +; SDAG-NEXT: sub sp, sp, #48 +; SDAG-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; SDAG-NEXT: .cfi_def_cfa_offset 48 +; SDAG-NEXT: .cfi_offset w30, -16 +; SDAG-NEXT: // kill: def $d0 killed $d0 def $q0 +; SDAG-NEXT: mov h1, v0.h[1] +; SDAG-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; SDAG-NEXT: fcvt s0, h1 +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: fcvt h0, s0 +; SDAG-NEXT: fcvt s1, h1 +; SDAG-NEXT: str q0, [sp] // 16-byte Folded Spill +; SDAG-NEXT: fmov s0, s1 +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: fcvt h2, s0 +; SDAG-NEXT: mov h1, v1.h[2] +; SDAG-NEXT: fcvt s0, h1 +; SDAG-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; SDAG-NEXT: mov v2.h[1], v1.h[0] +; SDAG-NEXT: str q2, [sp] // 16-byte Folded Spill +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: fcvt h2, s0 +; SDAG-NEXT: mov h1, v1.h[3] +; SDAG-NEXT: fcvt s0, h1 +; SDAG-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; SDAG-NEXT: mov v1.h[2], v2.h[0] +; SDAG-NEXT: str q1, [sp] // 16-byte Folded Spill +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: fcvt h1, s0 +; SDAG-NEXT: ldr q0, [sp] // 16-byte Folded Reload +; SDAG-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; SDAG-NEXT: mov v0.h[3], v1.h[0] +; SDAG-NEXT: // kill: def $d0 killed $d0 killed $q0 +; SDAG-NEXT: add sp, sp, #48 +; SDAG-NEXT: ret +; +; GISEL-LABEL: exp10_v4f16: +; GISEL: // %bb.0: +; GISEL-NEXT: sub sp, sp, #80 +; GISEL-NEXT: str d10, [sp, #48] // 8-byte Folded Spill +; GISEL-NEXT: stp d9, d8, [sp, #56] // 16-byte Folded Spill +; GISEL-NEXT: str x30, [sp, #72] // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 80 +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset b8, -16 +; GISEL-NEXT: .cfi_offset b9, -24 +; GISEL-NEXT: .cfi_offset b10, -32 +; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 +; GISEL-NEXT: mov h8, v0.h[1] +; GISEL-NEXT: mov h9, v0.h[2] +; GISEL-NEXT: mov h10, v0.h[3] +; GISEL-NEXT: fcvt s0, h0 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: fcvt s1, h8 +; GISEL-NEXT: fcvt h0, s0 +; GISEL-NEXT: str q0, [sp, #32] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s1 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: fcvt s1, h9 +; GISEL-NEXT: fcvt h0, s0 +; GISEL-NEXT: str q0, [sp] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s1 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: fcvt s1, h10 +; GISEL-NEXT: fcvt h0, s0 +; GISEL-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s1 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: ldr q1, [sp, #32] // 16-byte Folded Reload +; GISEL-NEXT: fcvt h0, s0 +; GISEL-NEXT: ldr q2, [sp] // 16-byte Folded Reload +; GISEL-NEXT: ldp d9, d8, [sp, #56] // 16-byte Folded Reload +; GISEL-NEXT: mov v1.h[1], v2.h[0] +; GISEL-NEXT: ldr q2, [sp, #16] // 16-byte Folded Reload +; GISEL-NEXT: ldr x30, [sp, #72] // 8-byte Folded Reload +; GISEL-NEXT: ldr d10, [sp, #48] // 8-byte Folded Reload +; GISEL-NEXT: mov v1.h[2], v2.h[0] +; GISEL-NEXT: mov v1.h[3], v0.h[0] +; GISEL-NEXT: mov v0.16b, v1.16b +; GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0 +; GISEL-NEXT: add sp, sp, #80 +; GISEL-NEXT: ret + %r = call <4 x half> @llvm.exp10.v4f16(<4 x half> %x) + ret <4 x half> %r +} + +define float @exp10_f32(float %x) { +; SDAG-LABEL: exp10_f32: +; SDAG: // %bb.0: +; SDAG-NEXT: b exp10f +; +; GISEL-LABEL: exp10_f32: +; GISEL: // %bb.0: +; GISEL-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 16 +; GISEL-NEXT: .cfi_offset w30, -16 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; GISEL-NEXT: ret + %r = call float @llvm.exp10.f32(float %x) + ret float %r +} + +define <1 x float> @exp10_v1f32(<1 x float> %x) { +; SDAG-LABEL: exp10_v1f32: +; SDAG: // %bb.0: +; SDAG-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; SDAG-NEXT: .cfi_def_cfa_offset 16 +; SDAG-NEXT: .cfi_offset w30, -16 +; SDAG-NEXT: // kill: def $d0 killed $d0 def $q0 +; SDAG-NEXT: // kill: def $s0 killed $s0 killed $q0 +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: // kill: def $s0 killed $s0 def $d0 +; SDAG-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; SDAG-NEXT: ret +; +; GISEL-LABEL: exp10_v1f32: +; GISEL: // %bb.0: +; GISEL-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 16 +; GISEL-NEXT: .cfi_offset w30, -16 +; GISEL-NEXT: fmov x8, d0 +; GISEL-NEXT: fmov s0, w8 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: // kill: def $s0 killed $s0 def $d0 +; GISEL-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; GISEL-NEXT: ret + %r = call <1 x float> @llvm.exp10.v1f32(<1 x float> %x) + ret <1 x float> %r +} + +define <2 x float> @exp10_v2f32(<2 x float> %x) { +; SDAG-LABEL: exp10_v2f32: +; SDAG: // %bb.0: +; SDAG-NEXT: sub sp, sp, #48 +; SDAG-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; SDAG-NEXT: .cfi_def_cfa_offset 48 +; SDAG-NEXT: .cfi_offset w30, -16 +; SDAG-NEXT: // kill: def $d0 killed $d0 def $q0 +; SDAG-NEXT: str q0, [sp] // 16-byte Folded Spill +; SDAG-NEXT: mov s0, v0.s[1] +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: str d0, [sp, #16] // 16-byte Folded Spill +; SDAG-NEXT: ldr q0, [sp] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $s0 killed $s0 killed $q0 +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $s0 killed $s0 def $q0 +; SDAG-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; SDAG-NEXT: mov v0.s[1], v1.s[0] +; SDAG-NEXT: // kill: def $d0 killed $d0 killed $q0 +; SDAG-NEXT: add sp, sp, #48 +; SDAG-NEXT: ret +; +; GISEL-LABEL: exp10_v2f32: +; GISEL: // %bb.0: +; GISEL-NEXT: sub sp, sp, #32 +; GISEL-NEXT: str d8, [sp, #16] // 8-byte Folded Spill +; GISEL-NEXT: str x30, [sp, #24] // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 32 +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset b8, -16 +; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 +; GISEL-NEXT: mov s8, v0.s[1] +; GISEL-NEXT: // kill: def $s0 killed $s0 killed $q0 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: str d0, [sp] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s8 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; GISEL-NEXT: // kill: def $s0 killed $s0 def $q0 +; GISEL-NEXT: ldr x30, [sp, #24] // 8-byte Folded Reload +; GISEL-NEXT: ldr d8, [sp, #16] // 8-byte Folded Reload +; GISEL-NEXT: mov v1.s[1], v0.s[0] +; GISEL-NEXT: fmov d0, d1 +; GISEL-NEXT: add sp, sp, #32 +; GISEL-NEXT: ret + %r = call <2 x float> @llvm.exp10.v2f32(<2 x float> %x) + ret <2 x float> %r +} + +define <3 x float> @exp10_v3f32(<3 x float> %x) { +; SDAG-LABEL: exp10_v3f32: +; SDAG: // %bb.0: +; SDAG-NEXT: sub sp, sp, #48 +; SDAG-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; SDAG-NEXT: .cfi_def_cfa_offset 48 +; SDAG-NEXT: .cfi_offset w30, -16 +; SDAG-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; SDAG-NEXT: mov s0, v0.s[1] +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: str d0, [sp] // 16-byte Folded Spill +; SDAG-NEXT: ldr q0, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $s0 killed $s0 killed $q0 +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $s0 killed $s0 def $q0 +; SDAG-NEXT: mov v0.s[1], v1.s[0] +; SDAG-NEXT: str q0, [sp] // 16-byte Folded Spill +; SDAG-NEXT: ldr q0, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: mov s0, v0.s[2] +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $s0 killed $s0 def $q0 +; SDAG-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; SDAG-NEXT: mov v1.s[2], v0.s[0] +; SDAG-NEXT: mov v0.16b, v1.16b +; SDAG-NEXT: add sp, sp, #48 +; SDAG-NEXT: ret +; +; GISEL-LABEL: exp10_v3f32: +; GISEL: // %bb.0: +; GISEL-NEXT: sub sp, sp, #64 +; GISEL-NEXT: stp d9, d8, [sp, #32] // 16-byte Folded Spill +; GISEL-NEXT: str x30, [sp, #48] // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 64 +; GISEL-NEXT: .cfi_offset w30, -16 +; GISEL-NEXT: .cfi_offset b8, -24 +; GISEL-NEXT: .cfi_offset b9, -32 +; GISEL-NEXT: mov s8, v0.s[1] +; GISEL-NEXT: mov s9, v0.s[2] +; GISEL-NEXT: // kill: def $s0 killed $s0 killed $q0 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: str d0, [sp, #16] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s8 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: str d0, [sp] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s9 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: ldp q2, q1, [sp] // 32-byte Folded Reload +; GISEL-NEXT: // kill: def $s0 killed $s0 def $q0 +; GISEL-NEXT: mov v1.s[1], v2.s[0] +; GISEL-NEXT: ldr x30, [sp, #48] // 8-byte Folded Reload +; GISEL-NEXT: ldp d9, d8, [sp, #32] // 16-byte Folded Reload +; GISEL-NEXT: mov v1.s[2], v0.s[0] +; GISEL-NEXT: mov v1.s[3], v0.s[0] +; GISEL-NEXT: mov v0.16b, v1.16b +; GISEL-NEXT: add sp, sp, #64 +; GISEL-NEXT: ret + %r = call <3 x float> @llvm.exp10.v3f32(<3 x float> %x) + ret <3 x float> %r +} + +define <4 x float> @exp10_v4f32(<4 x float> %x) { +; SDAG-LABEL: exp10_v4f32: +; SDAG: // %bb.0: +; SDAG-NEXT: sub sp, sp, #48 +; SDAG-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; SDAG-NEXT: .cfi_def_cfa_offset 48 +; SDAG-NEXT: .cfi_offset w30, -16 +; SDAG-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; SDAG-NEXT: mov s0, v0.s[1] +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: str d0, [sp] // 16-byte Folded Spill +; SDAG-NEXT: ldr q0, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $s0 killed $s0 killed $q0 +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $s0 killed $s0 def $q0 +; SDAG-NEXT: mov v0.s[1], v1.s[0] +; SDAG-NEXT: str q0, [sp] // 16-byte Folded Spill +; SDAG-NEXT: ldr q0, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: mov s0, v0.s[2] +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $s0 killed $s0 def $q0 +; SDAG-NEXT: mov v1.s[2], v0.s[0] +; SDAG-NEXT: ldr q0, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: mov s0, v0.s[3] +; SDAG-NEXT: str q1, [sp] // 16-byte Folded Spill +; SDAG-NEXT: bl exp10f +; SDAG-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $s0 killed $s0 def $q0 +; SDAG-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; SDAG-NEXT: mov v1.s[3], v0.s[0] +; SDAG-NEXT: mov v0.16b, v1.16b +; SDAG-NEXT: add sp, sp, #48 +; SDAG-NEXT: ret +; +; GISEL-LABEL: exp10_v4f32: +; GISEL: // %bb.0: +; GISEL-NEXT: sub sp, sp, #80 +; GISEL-NEXT: str d10, [sp, #48] // 8-byte Folded Spill +; GISEL-NEXT: stp d9, d8, [sp, #56] // 16-byte Folded Spill +; GISEL-NEXT: str x30, [sp, #72] // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 80 +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset b8, -16 +; GISEL-NEXT: .cfi_offset b9, -24 +; GISEL-NEXT: .cfi_offset b10, -32 +; GISEL-NEXT: mov s8, v0.s[1] +; GISEL-NEXT: mov s9, v0.s[2] +; GISEL-NEXT: mov s10, v0.s[3] +; GISEL-NEXT: // kill: def $s0 killed $s0 killed $q0 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: str d0, [sp, #32] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s8 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: str d0, [sp, #16] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s9 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: str d0, [sp] // 16-byte Folded Spill +; GISEL-NEXT: fmov s0, s10 +; GISEL-NEXT: bl exp10f +; GISEL-NEXT: ldp q2, q1, [sp, #16] // 32-byte Folded Reload +; GISEL-NEXT: // kill: def $s0 killed $s0 def $q0 +; GISEL-NEXT: mov v1.s[1], v2.s[0] +; GISEL-NEXT: ldr q2, [sp] // 16-byte Folded Reload +; GISEL-NEXT: ldp d9, d8, [sp, #56] // 16-byte Folded Reload +; GISEL-NEXT: ldr x30, [sp, #72] // 8-byte Folded Reload +; GISEL-NEXT: mov v1.s[2], v2.s[0] +; GISEL-NEXT: ldr d10, [sp, #48] // 8-byte Folded Reload +; GISEL-NEXT: mov v1.s[3], v0.s[0] +; GISEL-NEXT: mov v0.16b, v1.16b +; GISEL-NEXT: add sp, sp, #80 +; GISEL-NEXT: ret + %r = call <4 x float> @llvm.exp10.v4f32(<4 x float> %x) + ret <4 x float> %r +} + +define double @exp10_f64(double %x) { +; SDAG-LABEL: exp10_f64: +; SDAG: // %bb.0: +; SDAG-NEXT: b exp10 +; +; GISEL-LABEL: exp10_f64: +; GISEL: // %bb.0: +; GISEL-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 16 +; GISEL-NEXT: .cfi_offset w30, -16 +; GISEL-NEXT: bl exp10 +; GISEL-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; GISEL-NEXT: ret + %r = call double @llvm.exp10.f64(double %x) + ret double %r +} + +; FIXME: Broken +; define <1 x double> @exp10_v1f64(<1 x double> %x) { +; %r = call <1 x double> @llvm.exp10.v1f64(<1 x double> %x) +; ret <1 x double> %r +; } + +define <2 x double> @exp10_v2f64(<2 x double> %x) { +; SDAG-LABEL: exp10_v2f64: +; SDAG: // %bb.0: +; SDAG-NEXT: sub sp, sp, #48 +; SDAG-NEXT: str x30, [sp, #32] // 8-byte Folded Spill +; SDAG-NEXT: .cfi_def_cfa_offset 48 +; SDAG-NEXT: .cfi_offset w30, -16 +; SDAG-NEXT: str q0, [sp] // 16-byte Folded Spill +; SDAG-NEXT: mov d0, v0.d[1] +; SDAG-NEXT: bl exp10 +; SDAG-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; SDAG-NEXT: ldr q0, [sp] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $d0 killed $d0 killed $q0 +; SDAG-NEXT: bl exp10 +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $d0 killed $d0 def $q0 +; SDAG-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload +; SDAG-NEXT: mov v0.d[1], v1.d[0] +; SDAG-NEXT: add sp, sp, #48 +; SDAG-NEXT: ret +; +; GISEL-LABEL: exp10_v2f64: +; GISEL: // %bb.0: +; GISEL-NEXT: sub sp, sp, #32 +; GISEL-NEXT: str d8, [sp, #16] // 8-byte Folded Spill +; GISEL-NEXT: str x30, [sp, #24] // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 32 +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset b8, -16 +; GISEL-NEXT: mov d8, v0.d[1] +; GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0 +; GISEL-NEXT: bl exp10 +; GISEL-NEXT: str q0, [sp] // 16-byte Folded Spill +; GISEL-NEXT: fmov d0, d8 +; GISEL-NEXT: bl exp10 +; GISEL-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 +; GISEL-NEXT: ldr x30, [sp, #24] // 8-byte Folded Reload +; GISEL-NEXT: ldr d8, [sp, #16] // 8-byte Folded Reload +; GISEL-NEXT: mov v1.d[1], v0.d[0] +; GISEL-NEXT: mov v0.16b, v1.16b +; GISEL-NEXT: add sp, sp, #32 +; GISEL-NEXT: ret + %r = call <2 x double> @llvm.exp10.v2f64(<2 x double> %x) + ret <2 x double> %r +} + +define <3 x double> @exp10_v3f64(<3 x double> %x) { +; SDAG-LABEL: exp10_v3f64: +; SDAG: // %bb.0: +; SDAG-NEXT: str d10, [sp, #-32]! // 8-byte Folded Spill +; SDAG-NEXT: stp d9, d8, [sp, #8] // 16-byte Folded Spill +; SDAG-NEXT: str x30, [sp, #24] // 8-byte Folded Spill +; SDAG-NEXT: .cfi_def_cfa_offset 32 +; SDAG-NEXT: .cfi_offset w30, -8 +; SDAG-NEXT: .cfi_offset b8, -16 +; SDAG-NEXT: .cfi_offset b9, -24 +; SDAG-NEXT: .cfi_offset b10, -32 +; SDAG-NEXT: fmov d8, d2 +; SDAG-NEXT: fmov d9, d1 +; SDAG-NEXT: bl exp10 +; SDAG-NEXT: fmov d10, d0 +; SDAG-NEXT: fmov d0, d9 +; SDAG-NEXT: bl exp10 +; SDAG-NEXT: fmov d9, d0 +; SDAG-NEXT: fmov d0, d8 +; SDAG-NEXT: bl exp10 +; SDAG-NEXT: fmov d1, d9 +; SDAG-NEXT: ldr x30, [sp, #24] // 8-byte Folded Reload +; SDAG-NEXT: ldp d9, d8, [sp, #8] // 16-byte Folded Reload +; SDAG-NEXT: fmov d2, d0 +; SDAG-NEXT: fmov d0, d10 +; SDAG-NEXT: ldr d10, [sp], #32 // 8-byte Folded Reload +; SDAG-NEXT: ret +; +; GISEL-LABEL: exp10_v3f64: +; GISEL: // %bb.0: +; GISEL-NEXT: str d10, [sp, #-32]! // 8-byte Folded Spill +; GISEL-NEXT: stp d9, d8, [sp, #8] // 16-byte Folded Spill +; GISEL-NEXT: str x30, [sp, #24] // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 32 +; GISEL-NEXT: .cfi_offset w30, -8 +; GISEL-NEXT: .cfi_offset b8, -16 +; GISEL-NEXT: .cfi_offset b9, -24 +; GISEL-NEXT: .cfi_offset b10, -32 +; GISEL-NEXT: fmov d8, d1 +; GISEL-NEXT: fmov d9, d2 +; GISEL-NEXT: bl exp10 +; GISEL-NEXT: fmov d10, d0 +; GISEL-NEXT: fmov d0, d8 +; GISEL-NEXT: bl exp10 +; GISEL-NEXT: fmov d8, d0 +; GISEL-NEXT: fmov d0, d9 +; GISEL-NEXT: bl exp10 +; GISEL-NEXT: fmov d1, d8 +; GISEL-NEXT: ldr x30, [sp, #24] // 8-byte Folded Reload +; GISEL-NEXT: ldp d9, d8, [sp, #8] // 16-byte Folded Reload +; GISEL-NEXT: fmov d2, d0 +; GISEL-NEXT: fmov d0, d10 +; GISEL-NEXT: ldr d10, [sp], #32 // 8-byte Folded Reload +; GISEL-NEXT: ret + %r = call <3 x double> @llvm.exp10.v3f64(<3 x double> %x) + ret <3 x double> %r +} + +define <4 x double> @exp10_v4f64(<4 x double> %x) { +; SDAG-LABEL: exp10_v4f64: +; SDAG: // %bb.0: +; SDAG-NEXT: sub sp, sp, #64 +; SDAG-NEXT: str x30, [sp, #48] // 8-byte Folded Spill +; SDAG-NEXT: .cfi_def_cfa_offset 64 +; SDAG-NEXT: .cfi_offset w30, -16 +; SDAG-NEXT: str q0, [sp] // 16-byte Folded Spill +; SDAG-NEXT: mov d0, v0.d[1] +; SDAG-NEXT: str q1, [sp, #32] // 16-byte Folded Spill +; SDAG-NEXT: bl exp10 +; SDAG-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; SDAG-NEXT: ldr q0, [sp] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $d0 killed $d0 killed $q0 +; SDAG-NEXT: bl exp10 +; SDAG-NEXT: ldr q1, [sp, #16] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $d0 killed $d0 def $q0 +; SDAG-NEXT: mov v0.d[1], v1.d[0] +; SDAG-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; SDAG-NEXT: ldr q0, [sp, #32] // 16-byte Folded Reload +; SDAG-NEXT: mov d0, v0.d[1] +; SDAG-NEXT: bl exp10 +; SDAG-NEXT: str q0, [sp] // 16-byte Folded Spill +; SDAG-NEXT: ldr q0, [sp, #32] // 16-byte Folded Reload +; SDAG-NEXT: // kill: def $d0 killed $d0 killed $q0 +; SDAG-NEXT: bl exp10 +; SDAG-NEXT: fmov d1, d0 +; SDAG-NEXT: ldr x30, [sp, #48] // 8-byte Folded Reload +; SDAG-NEXT: ldp q2, q0, [sp] // 32-byte Folded Reload +; SDAG-NEXT: mov v1.d[1], v2.d[0] +; SDAG-NEXT: add sp, sp, #64 +; SDAG-NEXT: ret +; +; GISEL-LABEL: exp10_v4f64: +; GISEL: // %bb.0: +; GISEL-NEXT: sub sp, sp, #80 +; GISEL-NEXT: stp d9, d8, [sp, #48] // 16-byte Folded Spill +; GISEL-NEXT: str x30, [sp, #64] // 8-byte Folded Spill +; GISEL-NEXT: .cfi_def_cfa_offset 80 +; GISEL-NEXT: .cfi_offset w30, -16 +; GISEL-NEXT: .cfi_offset b8, -24 +; GISEL-NEXT: .cfi_offset b9, -32 +; GISEL-NEXT: str q1, [sp] // 16-byte Folded Spill +; GISEL-NEXT: mov d8, v0.d[1] +; GISEL-NEXT: mov d9, v1.d[1] +; GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0 +; GISEL-NEXT: bl exp10 +; GISEL-NEXT: str q0, [sp, #32] // 16-byte Folded Spill +; GISEL-NEXT: fmov d0, d8 +; GISEL-NEXT: bl exp10 +; GISEL-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; GISEL-NEXT: ldr q0, [sp] // 16-byte Folded Reload +; GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0 +; GISEL-NEXT: bl exp10 +; GISEL-NEXT: str q0, [sp] // 16-byte Folded Spill +; GISEL-NEXT: fmov d0, d9 +; GISEL-NEXT: bl exp10 +; GISEL-NEXT: ldp q1, q2, [sp, #16] // 32-byte Folded Reload +; GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 +; GISEL-NEXT: mov v2.d[1], v1.d[0] +; GISEL-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; GISEL-NEXT: ldp d9, d8, [sp, #48] // 16-byte Folded Reload +; GISEL-NEXT: ldr x30, [sp, #64] // 8-byte Folded Reload +; GISEL-NEXT: mov v1.d[1], v0.d[0] +; GISEL-NEXT: mov v0.16b, v2.16b +; GISEL-NEXT: add sp, sp, #80 +; GISEL-NEXT: ret + %r = call <4 x double> @llvm.exp10.v4f64(<4 x double> %x) + ret <4 x double> %r +} +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; CVT: {{.*}} +; CVT-GISEL: {{.*}} +; CVT-SDAG: {{.*}} +; FP16: {{.*}} +; FP16-GISEL: {{.*}} +; FP16-SDAG: {{.*}} Index: llvm/test/CodeGen/ARM/llvm.exp10.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/ARM/llvm.exp10.ll @@ -0,0 +1,318 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mtriple=thumbv7-unknown-linux < %s | FileCheck -check-prefixes=CHECK %s + +declare half @llvm.exp10.f16(half) +declare <1 x half> @llvm.exp10.v1f16(<1 x half>) +declare <2 x half> @llvm.exp10.v2f16(<2 x half>) +declare <3 x half> @llvm.exp10.v3f16(<3 x half>) +declare <4 x half> @llvm.exp10.v4f16(<4 x half>) +declare float @llvm.exp10.f32(float) +declare <1 x float> @llvm.exp10.v1f32(<1 x float>) +declare <2 x float> @llvm.exp10.v2f32(<2 x float>) +declare <3 x float> @llvm.exp10.v3f32(<3 x float>) +declare <4 x float> @llvm.exp10.v4f32(<4 x float>) +declare double @llvm.exp10.f64(double) +declare <1 x double> @llvm.exp10.v1f64(<1 x double>) +declare <2 x double> @llvm.exp10.v2f64(<2 x double>) +declare <3 x double> @llvm.exp10.v3f64(<3 x double>) +declare <4 x double> @llvm.exp10.v4f64(<4 x double>) + +define half @exp10_f16(half %x) { +; CHECK-LABEL: exp10_f16: +; CHECK: @ %bb.0: +; CHECK-NEXT: push {r7, lr} +; CHECK-NEXT: bl __gnu_h2f_ieee +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: bl __gnu_f2h_ieee +; CHECK-NEXT: pop {r7, pc} + %r = call half @llvm.exp10.f16(half %x) + ret half %r +} + +define <1 x half> @exp10_v1f16(<1 x half> %x) { +; CHECK-LABEL: exp10_v1f16: +; CHECK: @ %bb.0: +; CHECK-NEXT: push {r7, lr} +; CHECK-NEXT: bl __gnu_f2h_ieee +; CHECK-NEXT: bl __gnu_h2f_ieee +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: pop {r7, pc} + %r = call <1 x half> @llvm.exp10.v1f16(<1 x half> %x) + ret <1 x half> %r +} + +define <2 x half> @exp10_v2f16(<2 x half> %x) { +; CHECK-LABEL: exp10_v2f16: +; CHECK: @ %bb.0: +; CHECK-NEXT: push {r4, r5, r7, lr} +; CHECK-NEXT: mov r4, r1 +; CHECK-NEXT: bl __gnu_h2f_ieee +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: bl __gnu_f2h_ieee +; CHECK-NEXT: mov r5, r0 +; CHECK-NEXT: mov r0, r4 +; CHECK-NEXT: bl __gnu_h2f_ieee +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: bl __gnu_f2h_ieee +; CHECK-NEXT: mov r1, r0 +; CHECK-NEXT: mov r0, r5 +; CHECK-NEXT: pop {r4, r5, r7, pc} + %r = call <2 x half> @llvm.exp10.v2f16(<2 x half> %x) + ret <2 x half> %r +} + +define <3 x half> @exp10_v3f16(<3 x half> %x) { +; CHECK-LABEL: exp10_v3f16: +; CHECK: @ %bb.0: +; CHECK-NEXT: push {r4, r5, r6, lr} +; CHECK-NEXT: mov r4, r2 +; CHECK-NEXT: mov r6, r1 +; CHECK-NEXT: bl __gnu_h2f_ieee +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: bl __gnu_f2h_ieee +; CHECK-NEXT: mov r5, r0 +; CHECK-NEXT: mov r0, r6 +; CHECK-NEXT: bl __gnu_h2f_ieee +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: bl __gnu_f2h_ieee +; CHECK-NEXT: mov r6, r0 +; CHECK-NEXT: mov r0, r4 +; CHECK-NEXT: bl __gnu_h2f_ieee +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: bl __gnu_f2h_ieee +; CHECK-NEXT: mov r2, r0 +; CHECK-NEXT: mov r0, r5 +; CHECK-NEXT: mov r1, r6 +; CHECK-NEXT: pop {r4, r5, r6, pc} + %r = call <3 x half> @llvm.exp10.v3f16(<3 x half> %x) + ret <3 x half> %r +} + +define <4 x half> @exp10_v4f16(<4 x half> %x) { +; CHECK-LABEL: exp10_v4f16: +; CHECK: @ %bb.0: +; CHECK-NEXT: push {r4, r5, r6, r7, lr} +; CHECK-NEXT: sub sp, #4 +; CHECK-NEXT: mov r4, r3 +; CHECK-NEXT: mov r6, r2 +; CHECK-NEXT: mov r7, r1 +; CHECK-NEXT: bl __gnu_h2f_ieee +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: bl __gnu_f2h_ieee +; CHECK-NEXT: mov r5, r0 +; CHECK-NEXT: mov r0, r7 +; CHECK-NEXT: bl __gnu_h2f_ieee +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: bl __gnu_f2h_ieee +; CHECK-NEXT: mov r7, r0 +; CHECK-NEXT: mov r0, r6 +; CHECK-NEXT: bl __gnu_h2f_ieee +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: bl __gnu_f2h_ieee +; CHECK-NEXT: mov r6, r0 +; CHECK-NEXT: mov r0, r4 +; CHECK-NEXT: bl __gnu_h2f_ieee +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: bl __gnu_f2h_ieee +; CHECK-NEXT: mov r3, r0 +; CHECK-NEXT: mov r0, r5 +; CHECK-NEXT: mov r1, r7 +; CHECK-NEXT: mov r2, r6 +; CHECK-NEXT: add sp, #4 +; CHECK-NEXT: pop {r4, r5, r6, r7, pc} + %r = call <4 x half> @llvm.exp10.v4f16(<4 x half> %x) + ret <4 x half> %r +} + +define float @exp10_f32(float %x) { +; CHECK-LABEL: exp10_f32: +; CHECK: @ %bb.0: +; CHECK-NEXT: b exp10f + %r = call float @llvm.exp10.f32(float %x) + ret float %r +} + +define <1 x float> @exp10_v1f32(<1 x float> %x) { +; CHECK-LABEL: exp10_v1f32: +; CHECK: @ %bb.0: +; CHECK-NEXT: push {r7, lr} +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: pop {r7, pc} + %r = call <1 x float> @llvm.exp10.v1f32(<1 x float> %x) + ret <1 x float> %r +} + +define <2 x float> @exp10_v2f32(<2 x float> %x) { +; CHECK-LABEL: exp10_v2f32: +; CHECK: @ %bb.0: +; CHECK-NEXT: push {r4, lr} +; CHECK-NEXT: vpush {d8} +; CHECK-NEXT: vmov d8, r0, r1 +; CHECK-NEXT: vmov r0, s17 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: mov r4, r0 +; CHECK-NEXT: vmov r0, s16 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: mov r1, r4 +; CHECK-NEXT: vpop {d8} +; CHECK-NEXT: pop {r4, pc} + %r = call <2 x float> @llvm.exp10.v2f32(<2 x float> %x) + ret <2 x float> %r +} + +define <3 x float> @exp10_v3f32(<3 x float> %x) { +; CHECK-LABEL: exp10_v3f32: +; CHECK: @ %bb.0: +; CHECK-NEXT: push {r4, r5, r6, lr} +; CHECK-NEXT: vpush {d8, d9} +; CHECK-NEXT: vmov d1, r2, r3 +; CHECK-NEXT: mov r5, r0 +; CHECK-NEXT: vmov d0, r0, r1 +; CHECK-NEXT: mov r4, r1 +; CHECK-NEXT: vmov r0, s2 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: mov r6, r0 +; CHECK-NEXT: mov r0, r4 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: vmov s17, r0 +; CHECK-NEXT: mov r0, r5 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: vmov s16, r0 +; CHECK-NEXT: vmov s18, r6 +; CHECK-NEXT: vmov r0, r1, d8 +; CHECK-NEXT: vmov r2, r3, d9 +; CHECK-NEXT: vpop {d8, d9} +; CHECK-NEXT: pop {r4, r5, r6, pc} + %r = call <3 x float> @llvm.exp10.v3f32(<3 x float> %x) + ret <3 x float> %r +} + +define <4 x float> @exp10_v4f32(<4 x float> %x) { +; CHECK-LABEL: exp10_v4f32: +; CHECK: @ %bb.0: +; CHECK-NEXT: push {r4, r5, r6, r7, lr} +; CHECK-NEXT: sub sp, #4 +; CHECK-NEXT: vpush {d8, d9} +; CHECK-NEXT: mov r6, r0 +; CHECK-NEXT: mov r0, r1 +; CHECK-NEXT: mov r4, r3 +; CHECK-NEXT: mov r5, r2 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: mov r7, r0 +; CHECK-NEXT: mov r0, r4 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: vmov s19, r0 +; CHECK-NEXT: mov r0, r5 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: vmov s18, r0 +; CHECK-NEXT: mov r0, r6 +; CHECK-NEXT: vmov s17, r7 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: vmov s16, r0 +; CHECK-NEXT: vmov r2, r3, d9 +; CHECK-NEXT: vmov r0, r1, d8 +; CHECK-NEXT: vpop {d8, d9} +; CHECK-NEXT: add sp, #4 +; CHECK-NEXT: pop {r4, r5, r6, r7, pc} + %r = call <4 x float> @llvm.exp10.v4f32(<4 x float> %x) + ret <4 x float> %r +} + +define double @exp10_f64(double %x) { +; CHECK-LABEL: exp10_f64: +; CHECK: @ %bb.0: +; CHECK-NEXT: b exp10 + %r = call double @llvm.exp10.f64(double %x) + ret double %r +} + +; FIXME: Broken +; define <1 x double> @exp10_v1f64(<1 x double> %x) { +; %r = call <1 x double> @llvm.exp10.v1f64(<1 x double> %x) +; ret <1 x double> %r +; } + +define <2 x double> @exp10_v2f64(<2 x double> %x) { +; CHECK-LABEL: exp10_v2f64: +; CHECK: @ %bb.0: +; CHECK-NEXT: push {r4, r5, r6, r7, lr} +; CHECK-NEXT: sub sp, #4 +; CHECK-NEXT: mov r4, r3 +; CHECK-NEXT: mov r5, r2 +; CHECK-NEXT: bl exp10 +; CHECK-NEXT: mov r6, r0 +; CHECK-NEXT: mov r7, r1 +; CHECK-NEXT: mov r0, r5 +; CHECK-NEXT: mov r1, r4 +; CHECK-NEXT: bl exp10 +; CHECK-NEXT: mov r2, r0 +; CHECK-NEXT: mov r3, r1 +; CHECK-NEXT: mov r0, r6 +; CHECK-NEXT: mov r1, r7 +; CHECK-NEXT: add sp, #4 +; CHECK-NEXT: pop {r4, r5, r6, r7, pc} + %r = call <2 x double> @llvm.exp10.v2f64(<2 x double> %x) + ret <2 x double> %r +} + +define <3 x double> @exp10_v3f64(<3 x double> %x) { +; CHECK-LABEL: exp10_v3f64: +; CHECK: @ %bb.0: +; CHECK-NEXT: push {r4, lr} +; CHECK-NEXT: vpush {d8, d9} +; CHECK-NEXT: mov r4, r0 +; CHECK-NEXT: mov r1, r3 +; CHECK-NEXT: mov r0, r2 +; CHECK-NEXT: bl exp10 +; CHECK-NEXT: ldrd r2, r3, [sp, #24] +; CHECK-NEXT: vmov d8, r0, r1 +; CHECK-NEXT: mov r1, r3 +; CHECK-NEXT: mov r0, r2 +; CHECK-NEXT: bl exp10 +; CHECK-NEXT: ldrd r2, r3, [sp, #32] +; CHECK-NEXT: vmov d9, r0, r1 +; CHECK-NEXT: mov r1, r3 +; CHECK-NEXT: vst1.64 {d8, d9}, [r4:128]! +; CHECK-NEXT: mov r0, r2 +; CHECK-NEXT: bl exp10 +; CHECK-NEXT: strd r0, r1, [r4] +; CHECK-NEXT: vpop {d8, d9} +; CHECK-NEXT: pop {r4, pc} + %r = call <3 x double> @llvm.exp10.v3f64(<3 x double> %x) + ret <3 x double> %r +} + +define <4 x double> @exp10_v4f64(<4 x double> %x) { +; CHECK-LABEL: exp10_v4f64: +; CHECK: @ %bb.0: +; CHECK-NEXT: push.w {r4, r5, r6, r7, r8, lr} +; CHECK-NEXT: vpush {d8, d9, d10, d11} +; CHECK-NEXT: mov r4, r0 +; CHECK-NEXT: mov r1, r3 +; CHECK-NEXT: mov r0, r2 +; CHECK-NEXT: bl exp10 +; CHECK-NEXT: add r2, sp, #64 +; CHECK-NEXT: vmov d8, r0, r1 +; CHECK-NEXT: vld1.64 {d16, d17}, [r2] +; CHECK-NEXT: vmov r2, r3, d17 +; CHECK-NEXT: vmov r5, r8, d16 +; CHECK-NEXT: mov r0, r2 +; CHECK-NEXT: mov r1, r3 +; CHECK-NEXT: bl exp10 +; CHECK-NEXT: mov r7, r0 +; CHECK-NEXT: mov r6, r1 +; CHECK-NEXT: ldrd r0, r1, [sp, #56] +; CHECK-NEXT: bl exp10 +; CHECK-NEXT: vmov d9, r0, r1 +; CHECK-NEXT: mov r0, r5 +; CHECK-NEXT: mov r1, r8 +; CHECK-NEXT: vmov d11, r7, r6 +; CHECK-NEXT: bl exp10 +; CHECK-NEXT: vmov d10, r0, r1 +; CHECK-NEXT: vst1.64 {d8, d9}, [r4:128]! +; CHECK-NEXT: vst1.64 {d10, d11}, [r4:128] +; CHECK-NEXT: vpop {d8, d9, d10, d11} +; CHECK-NEXT: pop.w {r4, r5, r6, r7, r8, pc} + %r = call <4 x double> @llvm.exp10.v4f64(<4 x double> %x) + ret <4 x double> %r +} Index: llvm/test/CodeGen/PowerPC/exp10-libcall.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/exp10-libcall.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mcpu=pwr9 -mtriple=powerpc64le-unknown-unknown \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names < %s | FileCheck %s + +define float @call_exp10f(float %a) { +; CHECK-LABEL: call_exp10f: +; CHECK: # %bb.0: +; CHECK-NEXT: mflr r0 +; CHECK-NEXT: stdu r1, -32(r1) +; CHECK-NEXT: std r0, 48(r1) +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK-NEXT: .cfi_offset lr, 16 +; CHECK-NEXT: bl exp10f +; CHECK-NEXT: nop +; CHECK-NEXT: addi r1, r1, 32 +; CHECK-NEXT: ld r0, 16(r1) +; CHECK-NEXT: mtlr r0 +; CHECK-NEXT: blr + %result = call float @exp10f(float %a) + ret float %result +} + +define double @call_exp10(double %a) { +; CHECK-LABEL: call_exp10: +; CHECK: # %bb.0: +; CHECK-NEXT: mflr r0 +; CHECK-NEXT: stdu r1, -32(r1) +; CHECK-NEXT: std r0, 48(r1) +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK-NEXT: .cfi_offset lr, 16 +; CHECK-NEXT: bl exp10 +; CHECK-NEXT: nop +; CHECK-NEXT: addi r1, r1, 32 +; CHECK-NEXT: ld r0, 16(r1) +; CHECK-NEXT: mtlr r0 +; CHECK-NEXT: blr + %result = call double @exp10(double %a) + ret double %result +} + +define ppc_fp128 @call_exp10l(ppc_fp128 %a) { +; CHECK-LABEL: call_exp10l: +; CHECK: # %bb.0: +; CHECK-NEXT: mflr r0 +; CHECK-NEXT: stdu r1, -32(r1) +; CHECK-NEXT: std r0, 48(r1) +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK-NEXT: .cfi_offset lr, 16 +; CHECK-NEXT: bl exp10l +; CHECK-NEXT: nop +; CHECK-NEXT: addi r1, r1, 32 +; CHECK-NEXT: ld r0, 16(r1) +; CHECK-NEXT: mtlr r0 +; CHECK-NEXT: blr + %result = call ppc_fp128 @exp10l(ppc_fp128 %a) + ret ppc_fp128 %result +} + +declare float @exp10f(float %a) #0 +declare double @exp10(double %a) #0 +declare ppc_fp128 @exp10l(ppc_fp128 %a) #0 + +attributes #0 = { nounwind readonly } Index: llvm/test/CodeGen/RISCV/llvm.exp10.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/RISCV/llvm.exp10.ll @@ -0,0 +1,876 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mtriple=riscv32 -mattr=+d \ +; RUN: -verify-machineinstrs -target-abi=ilp32d < %s \ +; RUN: | FileCheck -check-prefixes=CHECK,RV32IFD %s +; RUN: llc -mtriple=riscv64 -mattr=+d \ +; RUN: -verify-machineinstrs -target-abi=lp64d < %s \ +; RUN: | FileCheck -check-prefixes=CHECK,RV64IFD %s + +declare half @llvm.exp10.f16(half) +declare <1 x half> @llvm.exp10.v1f16(<1 x half>) +declare <2 x half> @llvm.exp10.v2f16(<2 x half>) +declare <3 x half> @llvm.exp10.v3f16(<3 x half>) +declare <4 x half> @llvm.exp10.v4f16(<4 x half>) +declare float @llvm.exp10.f32(float) +declare <1 x float> @llvm.exp10.v1f32(<1 x float>) +declare <2 x float> @llvm.exp10.v2f32(<2 x float>) +declare <3 x float> @llvm.exp10.v3f32(<3 x float>) +declare <4 x float> @llvm.exp10.v4f32(<4 x float>) +declare double @llvm.exp10.f64(double) +declare <1 x double> @llvm.exp10.v1f64(<1 x double>) +declare <2 x double> @llvm.exp10.v2f64(<2 x double>) +declare <3 x double> @llvm.exp10.v3f64(<3 x double>) +declare <4 x double> @llvm.exp10.v4f64(<4 x double>) + +define half @exp10_f16(half %x) { +; RV32IFD-LABEL: exp10_f16: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: .cfi_def_cfa_offset 16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: call __extendhfsf2@plt +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: call __truncsfhf2@plt +; RV32IFD-NEXT: fmv.x.w a0, fa0 +; RV32IFD-NEXT: lui a1, 1048560 +; RV32IFD-NEXT: or a0, a0, a1 +; RV32IFD-NEXT: fmv.w.x fa0, a0 +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_f16: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: .cfi_def_cfa_offset 16 +; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: call __extendhfsf2@plt +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: call __truncsfhf2@plt +; RV64IFD-NEXT: fmv.x.w a0, fa0 +; RV64IFD-NEXT: lui a1, 1048560 +; RV64IFD-NEXT: or a0, a0, a1 +; RV64IFD-NEXT: fmv.w.x fa0, a0 +; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %r = call half @llvm.exp10.f16(half %x) + ret half %r +} + +define <1 x half> @exp10_v1f16(<1 x half> %x) { +; RV32IFD-LABEL: exp10_v1f16: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: .cfi_def_cfa_offset 16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: fmv.w.x fa0, a0 +; RV32IFD-NEXT: call __extendhfsf2@plt +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: call __truncsfhf2@plt +; RV32IFD-NEXT: fmv.x.w a0, fa0 +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_v1f16: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: .cfi_def_cfa_offset 16 +; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: fmv.w.x fa0, a0 +; RV64IFD-NEXT: call __extendhfsf2@plt +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: call __truncsfhf2@plt +; RV64IFD-NEXT: fmv.x.w a0, fa0 +; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %r = call <1 x half> @llvm.exp10.v1f16(<1 x half> %x) + ret <1 x half> %r +} + +define <2 x half> @exp10_v2f16(<2 x half> %x) { +; RV32IFD-LABEL: exp10_v2f16: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: .cfi_def_cfa_offset 16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: .cfi_offset s0, -8 +; RV32IFD-NEXT: .cfi_offset fs0, -16 +; RV32IFD-NEXT: fmv.w.x fs0, a1 +; RV32IFD-NEXT: fmv.w.x fa0, a0 +; RV32IFD-NEXT: call __extendhfsf2@plt +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: call __truncsfhf2@plt +; RV32IFD-NEXT: fmv.x.w s0, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs0 +; RV32IFD-NEXT: call __extendhfsf2@plt +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: call __truncsfhf2@plt +; RV32IFD-NEXT: fmv.x.w a1, fa0 +; RV32IFD-NEXT: mv a0, s0 +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_v2f16: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -32 +; RV64IFD-NEXT: .cfi_def_cfa_offset 32 +; RV64IFD-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s1, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: .cfi_offset s0, -16 +; RV64IFD-NEXT: .cfi_offset s1, -24 +; RV64IFD-NEXT: mv s0, a1 +; RV64IFD-NEXT: fmv.w.x fa0, a0 +; RV64IFD-NEXT: call __extendhfsf2@plt +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: call __truncsfhf2@plt +; RV64IFD-NEXT: fmv.x.w s1, fa0 +; RV64IFD-NEXT: fmv.w.x fa0, s0 +; RV64IFD-NEXT: call __extendhfsf2@plt +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: call __truncsfhf2@plt +; RV64IFD-NEXT: fmv.x.w a1, fa0 +; RV64IFD-NEXT: mv a0, s1 +; RV64IFD-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s1, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 32 +; RV64IFD-NEXT: ret + %r = call <2 x half> @llvm.exp10.v2f16(<2 x half> %x) + ret <2 x half> %r +} + +define <3 x half> @exp10_v3f16(<3 x half> %x) { +; RV32IFD-LABEL: exp10_v3f16: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -48 +; RV32IFD-NEXT: .cfi_def_cfa_offset 48 +; RV32IFD-NEXT: sw ra, 44(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 40(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s1, 36(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: fsd fs0, 24(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs1, 16(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs2, 8(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: .cfi_offset s0, -8 +; RV32IFD-NEXT: .cfi_offset s1, -12 +; RV32IFD-NEXT: .cfi_offset fs0, -24 +; RV32IFD-NEXT: .cfi_offset fs1, -32 +; RV32IFD-NEXT: .cfi_offset fs2, -40 +; RV32IFD-NEXT: lhu a2, 8(a1) +; RV32IFD-NEXT: lhu a3, 0(a1) +; RV32IFD-NEXT: lhu a1, 4(a1) +; RV32IFD-NEXT: mv s0, a0 +; RV32IFD-NEXT: fmv.w.x fs0, a2 +; RV32IFD-NEXT: fmv.w.x fs1, a3 +; RV32IFD-NEXT: fmv.w.x fa0, a1 +; RV32IFD-NEXT: call __extendhfsf2@plt +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: call __truncsfhf2@plt +; RV32IFD-NEXT: fmv.s fs2, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs1 +; RV32IFD-NEXT: call __extendhfsf2@plt +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: fmv.x.w a0, fs2 +; RV32IFD-NEXT: slli s1, a0, 16 +; RV32IFD-NEXT: call __truncsfhf2@plt +; RV32IFD-NEXT: fmv.x.w a0, fa0 +; RV32IFD-NEXT: slli a0, a0, 16 +; RV32IFD-NEXT: srli a0, a0, 16 +; RV32IFD-NEXT: or s1, a0, s1 +; RV32IFD-NEXT: fmv.s fa0, fs0 +; RV32IFD-NEXT: call __extendhfsf2@plt +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: call __truncsfhf2@plt +; RV32IFD-NEXT: fmv.x.w a0, fa0 +; RV32IFD-NEXT: sh a0, 4(s0) +; RV32IFD-NEXT: sw s1, 0(s0) +; RV32IFD-NEXT: lw ra, 44(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 40(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s1, 36(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: fld fs0, 24(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs1, 16(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs2, 8(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 48 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_v3f16: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -48 +; RV64IFD-NEXT: .cfi_def_cfa_offset 48 +; RV64IFD-NEXT: sd ra, 40(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s0, 32(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s1, 24(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s2, 16(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs0, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: .cfi_offset s0, -16 +; RV64IFD-NEXT: .cfi_offset s1, -24 +; RV64IFD-NEXT: .cfi_offset s2, -32 +; RV64IFD-NEXT: .cfi_offset fs0, -40 +; RV64IFD-NEXT: lhu s1, 16(a1) +; RV64IFD-NEXT: lhu s2, 0(a1) +; RV64IFD-NEXT: lhu a1, 8(a1) +; RV64IFD-NEXT: mv s0, a0 +; RV64IFD-NEXT: fmv.w.x fa0, a1 +; RV64IFD-NEXT: call __extendhfsf2@plt +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: call __truncsfhf2@plt +; RV64IFD-NEXT: fmv.s fs0, fa0 +; RV64IFD-NEXT: fmv.w.x fa0, s2 +; RV64IFD-NEXT: call __extendhfsf2@plt +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: fmv.x.w a0, fs0 +; RV64IFD-NEXT: slli s2, a0, 16 +; RV64IFD-NEXT: call __truncsfhf2@plt +; RV64IFD-NEXT: fmv.x.w a0, fa0 +; RV64IFD-NEXT: slli a0, a0, 48 +; RV64IFD-NEXT: srli a0, a0, 48 +; RV64IFD-NEXT: or s2, a0, s2 +; RV64IFD-NEXT: fmv.w.x fa0, s1 +; RV64IFD-NEXT: call __extendhfsf2@plt +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: call __truncsfhf2@plt +; RV64IFD-NEXT: fmv.x.w a0, fa0 +; RV64IFD-NEXT: sh a0, 4(s0) +; RV64IFD-NEXT: sw s2, 0(s0) +; RV64IFD-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s0, 32(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s1, 24(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s2, 16(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs0, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 48 +; RV64IFD-NEXT: ret + %r = call <3 x half> @llvm.exp10.v3f16(<3 x half> %x) + ret <3 x half> %r +} + +define <4 x half> @exp10_v4f16(<4 x half> %x) { +; RV32IFD-LABEL: exp10_v4f16: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -64 +; RV32IFD-NEXT: .cfi_def_cfa_offset 64 +; RV32IFD-NEXT: sw ra, 60(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 56(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s1, 52(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s2, 48(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s3, 44(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: fsd fs0, 32(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs1, 24(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs2, 16(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs3, 8(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: .cfi_offset s0, -8 +; RV32IFD-NEXT: .cfi_offset s1, -12 +; RV32IFD-NEXT: .cfi_offset s2, -16 +; RV32IFD-NEXT: .cfi_offset s3, -20 +; RV32IFD-NEXT: .cfi_offset fs0, -32 +; RV32IFD-NEXT: .cfi_offset fs1, -40 +; RV32IFD-NEXT: .cfi_offset fs2, -48 +; RV32IFD-NEXT: .cfi_offset fs3, -56 +; RV32IFD-NEXT: mv s0, a0 +; RV32IFD-NEXT: lhu a0, 12(a1) +; RV32IFD-NEXT: lhu a2, 0(a1) +; RV32IFD-NEXT: lhu a3, 4(a1) +; RV32IFD-NEXT: lhu a1, 8(a1) +; RV32IFD-NEXT: fmv.w.x fs0, a0 +; RV32IFD-NEXT: fmv.w.x fs1, a2 +; RV32IFD-NEXT: fmv.w.x fs2, a3 +; RV32IFD-NEXT: fmv.w.x fa0, a1 +; RV32IFD-NEXT: call __extendhfsf2@plt +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: call __truncsfhf2@plt +; RV32IFD-NEXT: fmv.s fs3, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs2 +; RV32IFD-NEXT: call __extendhfsf2@plt +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: call __truncsfhf2@plt +; RV32IFD-NEXT: fmv.s fs2, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs1 +; RV32IFD-NEXT: call __extendhfsf2@plt +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: call __truncsfhf2@plt +; RV32IFD-NEXT: fmv.s fs1, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs0 +; RV32IFD-NEXT: call __extendhfsf2@plt +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: fmv.x.w s1, fs1 +; RV32IFD-NEXT: fmv.x.w s2, fs2 +; RV32IFD-NEXT: fmv.x.w s3, fs3 +; RV32IFD-NEXT: call __truncsfhf2@plt +; RV32IFD-NEXT: fmv.x.w a0, fa0 +; RV32IFD-NEXT: sh a0, 6(s0) +; RV32IFD-NEXT: sh s3, 4(s0) +; RV32IFD-NEXT: sh s2, 2(s0) +; RV32IFD-NEXT: sh s1, 0(s0) +; RV32IFD-NEXT: lw ra, 60(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 56(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s1, 52(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s2, 48(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s3, 44(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: fld fs0, 32(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs1, 24(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs2, 16(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs3, 8(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 64 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_v4f16: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -64 +; RV64IFD-NEXT: .cfi_def_cfa_offset 64 +; RV64IFD-NEXT: sd ra, 56(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s0, 48(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s1, 40(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s2, 32(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s3, 24(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs2, 0(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: .cfi_offset s0, -16 +; RV64IFD-NEXT: .cfi_offset s1, -24 +; RV64IFD-NEXT: .cfi_offset s2, -32 +; RV64IFD-NEXT: .cfi_offset s3, -40 +; RV64IFD-NEXT: .cfi_offset fs0, -48 +; RV64IFD-NEXT: .cfi_offset fs1, -56 +; RV64IFD-NEXT: .cfi_offset fs2, -64 +; RV64IFD-NEXT: lhu s1, 24(a1) +; RV64IFD-NEXT: lhu s2, 0(a1) +; RV64IFD-NEXT: lhu s3, 8(a1) +; RV64IFD-NEXT: lhu a1, 16(a1) +; RV64IFD-NEXT: mv s0, a0 +; RV64IFD-NEXT: fmv.w.x fa0, a1 +; RV64IFD-NEXT: call __extendhfsf2@plt +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: call __truncsfhf2@plt +; RV64IFD-NEXT: fmv.s fs0, fa0 +; RV64IFD-NEXT: fmv.w.x fa0, s3 +; RV64IFD-NEXT: call __extendhfsf2@plt +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: call __truncsfhf2@plt +; RV64IFD-NEXT: fmv.s fs1, fa0 +; RV64IFD-NEXT: fmv.w.x fa0, s2 +; RV64IFD-NEXT: call __extendhfsf2@plt +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: call __truncsfhf2@plt +; RV64IFD-NEXT: fmv.s fs2, fa0 +; RV64IFD-NEXT: fmv.w.x fa0, s1 +; RV64IFD-NEXT: call __extendhfsf2@plt +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: fmv.x.w s1, fs2 +; RV64IFD-NEXT: fmv.x.w s2, fs1 +; RV64IFD-NEXT: fmv.x.w s3, fs0 +; RV64IFD-NEXT: call __truncsfhf2@plt +; RV64IFD-NEXT: fmv.x.w a0, fa0 +; RV64IFD-NEXT: sh a0, 6(s0) +; RV64IFD-NEXT: sh s3, 4(s0) +; RV64IFD-NEXT: sh s2, 2(s0) +; RV64IFD-NEXT: sh s1, 0(s0) +; RV64IFD-NEXT: ld ra, 56(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s0, 48(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s1, 40(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s2, 32(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s3, 24(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs2, 0(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 64 +; RV64IFD-NEXT: ret + %r = call <4 x half> @llvm.exp10.v4f16(<4 x half> %x) + ret <4 x half> %r +} + +define float @exp10_f32(float %x) { +; CHECK-LABEL: exp10_f32: +; CHECK: # %bb.0: +; CHECK-NEXT: tail exp10f@plt + %r = call float @llvm.exp10.f32(float %x) + ret float %r +} + +define <1 x float> @exp10_v1f32(<1 x float> %x) { +; RV32IFD-LABEL: exp10_v1f32: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: .cfi_def_cfa_offset 16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 16 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_v1f32: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: .cfi_def_cfa_offset 16 +; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 16 +; RV64IFD-NEXT: ret + %r = call <1 x float> @llvm.exp10.v1f32(<1 x float> %x) + ret <1 x float> %r +} + +define <2 x float> @exp10_v2f32(<2 x float> %x) { +; RV32IFD-LABEL: exp10_v2f32: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -32 +; RV32IFD-NEXT: .cfi_def_cfa_offset 32 +; RV32IFD-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: .cfi_offset fs0, -16 +; RV32IFD-NEXT: .cfi_offset fs1, -24 +; RV32IFD-NEXT: fmv.s fs0, fa1 +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: fmv.s fs1, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs0 +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: fmv.s fa1, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs1 +; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 32 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_v2f32: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -32 +; RV64IFD-NEXT: .cfi_def_cfa_offset 32 +; RV64IFD-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: .cfi_offset fs0, -16 +; RV64IFD-NEXT: .cfi_offset fs1, -24 +; RV64IFD-NEXT: fmv.s fs0, fa1 +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: fmv.s fs1, fa0 +; RV64IFD-NEXT: fmv.s fa0, fs0 +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: fmv.s fa1, fa0 +; RV64IFD-NEXT: fmv.s fa0, fs1 +; RV64IFD-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 32 +; RV64IFD-NEXT: ret + %r = call <2 x float> @llvm.exp10.v2f32(<2 x float> %x) + ret <2 x float> %r +} + +define <3 x float> @exp10_v3f32(<3 x float> %x) { +; RV32IFD-LABEL: exp10_v3f32: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -32 +; RV32IFD-NEXT: .cfi_def_cfa_offset 32 +; RV32IFD-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 24(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs2, 0(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: .cfi_offset s0, -8 +; RV32IFD-NEXT: .cfi_offset fs0, -16 +; RV32IFD-NEXT: .cfi_offset fs1, -24 +; RV32IFD-NEXT: .cfi_offset fs2, -32 +; RV32IFD-NEXT: fmv.s fs0, fa2 +; RV32IFD-NEXT: fmv.s fs1, fa1 +; RV32IFD-NEXT: mv s0, a0 +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: fmv.s fs2, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs1 +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: fmv.s fs1, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs0 +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: fsw fa0, 8(s0) +; RV32IFD-NEXT: fsw fs1, 4(s0) +; RV32IFD-NEXT: fsw fs2, 0(s0) +; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 24(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs2, 0(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 32 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_v3f32: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -48 +; RV64IFD-NEXT: .cfi_def_cfa_offset 48 +; RV64IFD-NEXT: sd ra, 40(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s0, 32(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s1, 24(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: .cfi_offset s0, -16 +; RV64IFD-NEXT: .cfi_offset s1, -24 +; RV64IFD-NEXT: .cfi_offset fs0, -32 +; RV64IFD-NEXT: .cfi_offset fs1, -40 +; RV64IFD-NEXT: fmv.s fs0, fa2 +; RV64IFD-NEXT: fmv.s fs1, fa0 +; RV64IFD-NEXT: mv s0, a0 +; RV64IFD-NEXT: fmv.s fa0, fa1 +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: fmv.x.w a0, fa0 +; RV64IFD-NEXT: slli s1, a0, 32 +; RV64IFD-NEXT: fmv.s fa0, fs1 +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: fmv.x.w a0, fa0 +; RV64IFD-NEXT: slli a0, a0, 32 +; RV64IFD-NEXT: srli a0, a0, 32 +; RV64IFD-NEXT: or s1, a0, s1 +; RV64IFD-NEXT: fmv.s fa0, fs0 +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: fsw fa0, 8(s0) +; RV64IFD-NEXT: sd s1, 0(s0) +; RV64IFD-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s0, 32(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s1, 24(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 48 +; RV64IFD-NEXT: ret + %r = call <3 x float> @llvm.exp10.v3f32(<3 x float> %x) + ret <3 x float> %r +} + +define <4 x float> @exp10_v4f32(<4 x float> %x) { +; RV32IFD-LABEL: exp10_v4f32: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -48 +; RV32IFD-NEXT: .cfi_def_cfa_offset 48 +; RV32IFD-NEXT: sw ra, 44(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 40(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: fsd fs0, 32(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs1, 24(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs2, 16(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs3, 8(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: .cfi_offset s0, -8 +; RV32IFD-NEXT: .cfi_offset fs0, -16 +; RV32IFD-NEXT: .cfi_offset fs1, -24 +; RV32IFD-NEXT: .cfi_offset fs2, -32 +; RV32IFD-NEXT: .cfi_offset fs3, -40 +; RV32IFD-NEXT: fmv.s fs0, fa3 +; RV32IFD-NEXT: fmv.s fs1, fa2 +; RV32IFD-NEXT: fmv.s fs2, fa1 +; RV32IFD-NEXT: mv s0, a0 +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: fmv.s fs3, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs2 +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: fmv.s fs2, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs1 +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: fmv.s fs1, fa0 +; RV32IFD-NEXT: fmv.s fa0, fs0 +; RV32IFD-NEXT: call exp10f@plt +; RV32IFD-NEXT: fsw fa0, 12(s0) +; RV32IFD-NEXT: fsw fs1, 8(s0) +; RV32IFD-NEXT: fsw fs2, 4(s0) +; RV32IFD-NEXT: fsw fs3, 0(s0) +; RV32IFD-NEXT: lw ra, 44(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 40(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: fld fs0, 32(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs1, 24(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs2, 16(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs3, 8(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 48 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_v4f32: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -48 +; RV64IFD-NEXT: .cfi_def_cfa_offset 48 +; RV64IFD-NEXT: sd ra, 40(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s0, 32(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs0, 24(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs1, 16(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs2, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs3, 0(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: .cfi_offset s0, -16 +; RV64IFD-NEXT: .cfi_offset fs0, -24 +; RV64IFD-NEXT: .cfi_offset fs1, -32 +; RV64IFD-NEXT: .cfi_offset fs2, -40 +; RV64IFD-NEXT: .cfi_offset fs3, -48 +; RV64IFD-NEXT: fmv.s fs0, fa3 +; RV64IFD-NEXT: fmv.s fs1, fa2 +; RV64IFD-NEXT: fmv.s fs2, fa1 +; RV64IFD-NEXT: mv s0, a0 +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: fmv.s fs3, fa0 +; RV64IFD-NEXT: fmv.s fa0, fs2 +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: fmv.s fs2, fa0 +; RV64IFD-NEXT: fmv.s fa0, fs1 +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: fmv.s fs1, fa0 +; RV64IFD-NEXT: fmv.s fa0, fs0 +; RV64IFD-NEXT: call exp10f@plt +; RV64IFD-NEXT: fsw fa0, 12(s0) +; RV64IFD-NEXT: fsw fs1, 8(s0) +; RV64IFD-NEXT: fsw fs2, 4(s0) +; RV64IFD-NEXT: fsw fs3, 0(s0) +; RV64IFD-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s0, 32(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs0, 24(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs1, 16(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs2, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs3, 0(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 48 +; RV64IFD-NEXT: ret + %r = call <4 x float> @llvm.exp10.v4f32(<4 x float> %x) + ret <4 x float> %r +} + +define double @exp10_f64(double %x) { +; CHECK-LABEL: exp10_f64: +; CHECK: # %bb.0: +; CHECK-NEXT: tail exp10@plt + %r = call double @llvm.exp10.f64(double %x) + ret double %r +} + +; FIXME: Broken +; define <1 x double> @exp10_v1f64(<1 x double> %x) { +; %r = call <1 x double> @llvm.exp10.v1f64(<1 x double> %x) +; ret <1 x double> %r +; } + +define <2 x double> @exp10_v2f64(<2 x double> %x) { +; RV32IFD-LABEL: exp10_v2f64: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -32 +; RV32IFD-NEXT: .cfi_def_cfa_offset 32 +; RV32IFD-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: .cfi_offset fs0, -16 +; RV32IFD-NEXT: .cfi_offset fs1, -24 +; RV32IFD-NEXT: fmv.d fs0, fa1 +; RV32IFD-NEXT: call exp10@plt +; RV32IFD-NEXT: fmv.d fs1, fa0 +; RV32IFD-NEXT: fmv.d fa0, fs0 +; RV32IFD-NEXT: call exp10@plt +; RV32IFD-NEXT: fmv.d fa1, fa0 +; RV32IFD-NEXT: fmv.d fa0, fs1 +; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 32 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_v2f64: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -32 +; RV64IFD-NEXT: .cfi_def_cfa_offset 32 +; RV64IFD-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: .cfi_offset fs0, -16 +; RV64IFD-NEXT: .cfi_offset fs1, -24 +; RV64IFD-NEXT: fmv.d fs0, fa1 +; RV64IFD-NEXT: call exp10@plt +; RV64IFD-NEXT: fmv.d fs1, fa0 +; RV64IFD-NEXT: fmv.d fa0, fs0 +; RV64IFD-NEXT: call exp10@plt +; RV64IFD-NEXT: fmv.d fa1, fa0 +; RV64IFD-NEXT: fmv.d fa0, fs1 +; RV64IFD-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 32 +; RV64IFD-NEXT: ret + %r = call <2 x double> @llvm.exp10.v2f64(<2 x double> %x) + ret <2 x double> %r +} + +define <3 x double> @exp10_v3f64(<3 x double> %x) { +; RV32IFD-LABEL: exp10_v3f64: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -32 +; RV32IFD-NEXT: .cfi_def_cfa_offset 32 +; RV32IFD-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 24(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: fsd fs0, 16(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs1, 8(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs2, 0(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: .cfi_offset s0, -8 +; RV32IFD-NEXT: .cfi_offset fs0, -16 +; RV32IFD-NEXT: .cfi_offset fs1, -24 +; RV32IFD-NEXT: .cfi_offset fs2, -32 +; RV32IFD-NEXT: fmv.d fs0, fa2 +; RV32IFD-NEXT: fmv.d fs1, fa1 +; RV32IFD-NEXT: mv s0, a0 +; RV32IFD-NEXT: call exp10@plt +; RV32IFD-NEXT: fmv.d fs2, fa0 +; RV32IFD-NEXT: fmv.d fa0, fs1 +; RV32IFD-NEXT: call exp10@plt +; RV32IFD-NEXT: fmv.d fs1, fa0 +; RV32IFD-NEXT: fmv.d fa0, fs0 +; RV32IFD-NEXT: call exp10@plt +; RV32IFD-NEXT: fsd fa0, 16(s0) +; RV32IFD-NEXT: fsd fs1, 8(s0) +; RV32IFD-NEXT: fsd fs2, 0(s0) +; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 24(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: fld fs0, 16(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs1, 8(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs2, 0(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 32 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_v3f64: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -48 +; RV64IFD-NEXT: .cfi_def_cfa_offset 48 +; RV64IFD-NEXT: sd ra, 40(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s0, 32(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs0, 24(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs1, 16(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs2, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: .cfi_offset s0, -16 +; RV64IFD-NEXT: .cfi_offset fs0, -24 +; RV64IFD-NEXT: .cfi_offset fs1, -32 +; RV64IFD-NEXT: .cfi_offset fs2, -40 +; RV64IFD-NEXT: fmv.d fs0, fa2 +; RV64IFD-NEXT: fmv.d fs1, fa1 +; RV64IFD-NEXT: mv s0, a0 +; RV64IFD-NEXT: call exp10@plt +; RV64IFD-NEXT: fmv.d fs2, fa0 +; RV64IFD-NEXT: fmv.d fa0, fs1 +; RV64IFD-NEXT: call exp10@plt +; RV64IFD-NEXT: fmv.d fs1, fa0 +; RV64IFD-NEXT: fmv.d fa0, fs0 +; RV64IFD-NEXT: call exp10@plt +; RV64IFD-NEXT: fsd fa0, 16(s0) +; RV64IFD-NEXT: fsd fs1, 8(s0) +; RV64IFD-NEXT: fsd fs2, 0(s0) +; RV64IFD-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s0, 32(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs0, 24(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs1, 16(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs2, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 48 +; RV64IFD-NEXT: ret + %r = call <3 x double> @llvm.exp10.v3f64(<3 x double> %x) + ret <3 x double> %r +} + +define <4 x double> @exp10_v4f64(<4 x double> %x) { +; RV32IFD-LABEL: exp10_v4f64: +; RV32IFD: # %bb.0: +; RV32IFD-NEXT: addi sp, sp, -48 +; RV32IFD-NEXT: .cfi_def_cfa_offset 48 +; RV32IFD-NEXT: sw ra, 44(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 40(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: fsd fs0, 32(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs1, 24(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs2, 16(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fsd fs3, 8(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: .cfi_offset ra, -4 +; RV32IFD-NEXT: .cfi_offset s0, -8 +; RV32IFD-NEXT: .cfi_offset fs0, -16 +; RV32IFD-NEXT: .cfi_offset fs1, -24 +; RV32IFD-NEXT: .cfi_offset fs2, -32 +; RV32IFD-NEXT: .cfi_offset fs3, -40 +; RV32IFD-NEXT: fmv.d fs0, fa3 +; RV32IFD-NEXT: fmv.d fs1, fa2 +; RV32IFD-NEXT: fmv.d fs2, fa1 +; RV32IFD-NEXT: mv s0, a0 +; RV32IFD-NEXT: call exp10@plt +; RV32IFD-NEXT: fmv.d fs3, fa0 +; RV32IFD-NEXT: fmv.d fa0, fs2 +; RV32IFD-NEXT: call exp10@plt +; RV32IFD-NEXT: fmv.d fs2, fa0 +; RV32IFD-NEXT: fmv.d fa0, fs1 +; RV32IFD-NEXT: call exp10@plt +; RV32IFD-NEXT: fmv.d fs1, fa0 +; RV32IFD-NEXT: fmv.d fa0, fs0 +; RV32IFD-NEXT: call exp10@plt +; RV32IFD-NEXT: fsd fa0, 24(s0) +; RV32IFD-NEXT: fsd fs1, 16(s0) +; RV32IFD-NEXT: fsd fs2, 8(s0) +; RV32IFD-NEXT: fsd fs3, 0(s0) +; RV32IFD-NEXT: lw ra, 44(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 40(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: fld fs0, 32(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs1, 24(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs2, 16(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: fld fs3, 8(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 48 +; RV32IFD-NEXT: ret +; +; RV64IFD-LABEL: exp10_v4f64: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: addi sp, sp, -48 +; RV64IFD-NEXT: .cfi_def_cfa_offset 48 +; RV64IFD-NEXT: sd ra, 40(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: sd s0, 32(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs0, 24(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs1, 16(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs2, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs3, 0(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: .cfi_offset ra, -8 +; RV64IFD-NEXT: .cfi_offset s0, -16 +; RV64IFD-NEXT: .cfi_offset fs0, -24 +; RV64IFD-NEXT: .cfi_offset fs1, -32 +; RV64IFD-NEXT: .cfi_offset fs2, -40 +; RV64IFD-NEXT: .cfi_offset fs3, -48 +; RV64IFD-NEXT: fmv.d fs0, fa3 +; RV64IFD-NEXT: fmv.d fs1, fa2 +; RV64IFD-NEXT: fmv.d fs2, fa1 +; RV64IFD-NEXT: mv s0, a0 +; RV64IFD-NEXT: call exp10@plt +; RV64IFD-NEXT: fmv.d fs3, fa0 +; RV64IFD-NEXT: fmv.d fa0, fs2 +; RV64IFD-NEXT: call exp10@plt +; RV64IFD-NEXT: fmv.d fs2, fa0 +; RV64IFD-NEXT: fmv.d fa0, fs1 +; RV64IFD-NEXT: call exp10@plt +; RV64IFD-NEXT: fmv.d fs1, fa0 +; RV64IFD-NEXT: fmv.d fa0, fs0 +; RV64IFD-NEXT: call exp10@plt +; RV64IFD-NEXT: fsd fa0, 24(s0) +; RV64IFD-NEXT: fsd fs1, 16(s0) +; RV64IFD-NEXT: fsd fs2, 8(s0) +; RV64IFD-NEXT: fsd fs3, 0(s0) +; RV64IFD-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld s0, 32(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs0, 24(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs1, 16(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs2, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: fld fs3, 0(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 48 +; RV64IFD-NEXT: ret + %r = call <4 x double> @llvm.exp10.v4f64(<4 x double> %x) + ret <4 x double> %r +} Index: llvm/test/CodeGen/X86/exp10-libcall.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/exp10-libcall.ll @@ -0,0 +1,81 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s +; RUN: llc < %s -mtriple=i386-pc-win32 | FileCheck %s -check-prefix=CHECK-WIN + +define float @call_exp10f(float %a) { +; CHECK-LABEL: call_exp10f: +; CHECK: # %bb.0: +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: callq exp10f@PLT +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: retq +; +; CHECK-WIN-LABEL: call_exp10f: +; CHECK-WIN: # %bb.0: +; CHECK-WIN-NEXT: pushl %eax +; CHECK-WIN-NEXT: flds {{[0-9]+}}(%esp) +; CHECK-WIN-NEXT: fstps (%esp) +; CHECK-WIN-NEXT: calll _exp10f +; CHECK-WIN-NEXT: popl %eax +; CHECK-WIN-NEXT: retl + %result = call float @exp10f(float %a) + ret float %result +} + +define double @call_exp10(double %a) { +; CHECK-LABEL: call_exp10: +; CHECK: # %bb.0: +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: callq exp10@PLT +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: retq +; +; CHECK-WIN-LABEL: call_exp10: +; CHECK-WIN: # %bb.0: +; CHECK-WIN-NEXT: subl $8, %esp +; CHECK-WIN-NEXT: fldl {{[0-9]+}}(%esp) +; CHECK-WIN-NEXT: fstpl (%esp) +; CHECK-WIN-NEXT: calll _exp10 +; CHECK-WIN-NEXT: addl $8, %esp +; CHECK-WIN-NEXT: retl + %result = call double @exp10(double %a) + ret double %result +} + +define x86_fp80 @call_exp10l(x86_fp80 %a) { +; CHECK-LABEL: call_exp10l: +; CHECK: # %bb.0: +; CHECK-NEXT: subq $24, %rsp +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK-NEXT: fldt {{[0-9]+}}(%rsp) +; CHECK-NEXT: fstpt (%rsp) +; CHECK-NEXT: callq exp10l@PLT +; CHECK-NEXT: addq $24, %rsp +; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: retq +; +; CHECK-WIN-LABEL: call_exp10l: +; CHECK-WIN: # %bb.0: +; CHECK-WIN-NEXT: pushl %ebp +; CHECK-WIN-NEXT: movl %esp, %ebp +; CHECK-WIN-NEXT: andl $-16, %esp +; CHECK-WIN-NEXT: subl $32, %esp +; CHECK-WIN-NEXT: fldt 8(%ebp) +; CHECK-WIN-NEXT: fstpt (%esp) +; CHECK-WIN-NEXT: calll _exp10l +; CHECK-WIN-NEXT: movl %ebp, %esp +; CHECK-WIN-NEXT: popl %ebp +; CHECK-WIN-NEXT: retl + %result = call x86_fp80 @exp10l(x86_fp80 %a) + ret x86_fp80 %result +} + +declare float @exp10f(float %a) #0 +declare double @exp10(double %a) #0 +declare x86_fp80 @exp10l(x86_fp80 %a) #0 + +attributes #0 = { nounwind readonly }