diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td --- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -1755,6 +1755,11 @@ def int_ppc_test_data_class_f : Intrinsic<[llvm_i32_ty], [llvm_float_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; + + def int_ppc_convert_f128_to_ppcf128 + : Intrinsic<[llvm_ppcf128_ty], [llvm_f128_ty], [IntrNoMem]>; + def int_ppc_convert_ppcf128_to_f128 + : Intrinsic<[llvm_f128_ty], [llvm_ppcf128_ty], [IntrNoMem]>; } //===----------------------------------------------------------------------===// diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def b/llvm/include/llvm/IR/RuntimeLibcalls.def --- a/llvm/include/llvm/IR/RuntimeLibcalls.def +++ b/llvm/include/llvm/IR/RuntimeLibcalls.def @@ -376,6 +376,8 @@ HANDLE_LIBCALL(UINTTOFP_I128_F80, "__floatuntixf") HANDLE_LIBCALL(UINTTOFP_I128_F128, "__floatuntitf") HANDLE_LIBCALL(UINTTOFP_I128_PPCF128, "__floatuntitf") +HANDLE_LIBCALL(CONVERT_F128_PPCF128, "__extendkftf2") +HANDLE_LIBCALL(CONVERT_PPCF128_F128, "__trunctfkf2") // Comparison HANDLE_LIBCALL(OEQ_F32, "__eqsf2") diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -10484,6 +10484,17 @@ DAG.getTargetConstant(PPC::PRED_EQ, dl, MVT::i32)}), 0); } + case Intrinsic::ppc_convert_f128_to_ppcf128: + case Intrinsic::ppc_convert_ppcf128_to_f128: { + RTLIB::Libcall LC = IntrinsicID == Intrinsic::ppc_convert_ppcf128_to_f128 + ? RTLIB::CONVERT_PPCF128_F128 + : RTLIB::CONVERT_F128_PPCF128; + MakeLibCallOptions CallOptions; + std::pair Result = + makeLibCall(DAG, LC, Op.getValueType(), Op.getOperand(1), CallOptions, + dl, SDValue()); + return Result.first; + } } // If this is a lowered altivec predicate compare, CompareOpc is set to the @@ -11122,12 +11133,15 @@ break; } case ISD::INTRINSIC_WO_CHAIN: { - unsigned IntrinsicID = - cast(N->getOperand(0))->getZExtValue(); - - if (IntrinsicID == Intrinsic::ppc_pack_longdouble) + switch (cast(N->getOperand(0))->getZExtValue()) { + case Intrinsic::ppc_pack_longdouble: Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::ppcf128, N->getOperand(2), N->getOperand(1))); + break; + case Intrinsic::ppc_convert_f128_to_ppcf128: + Results.push_back(LowerINTRINSIC_WO_CHAIN(SDValue(N, 0), DAG)); + break; + } break; } case ISD::VAARG: { diff --git a/llvm/test/CodeGen/PowerPC/f128-truncateNconv.ll b/llvm/test/CodeGen/PowerPC/f128-truncateNconv.ll --- a/llvm/test/CodeGen/PowerPC/f128-truncateNconv.ll +++ b/llvm/test/CodeGen/PowerPC/f128-truncateNconv.ll @@ -1403,3 +1403,96 @@ store i8 %conv, i8* %res, align 1 ret void } + +define void @qpConvppcf128(fp128 %src, ppc_fp128* %dst) { +; CHECK-LABEL: qpConvppcf128: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mflr r0 +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: .cfi_offset lr, 16 +; CHECK-NEXT: .cfi_offset r30, -16 +; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill +; CHECK-NEXT: std r0, 16(r1) +; CHECK-NEXT: stdu r1, -48(r1) +; CHECK-NEXT: mr r30, r5 +; CHECK-NEXT: bl __extendkftf2 +; CHECK-NEXT: nop +; CHECK-NEXT: stfd f2, 8(r30) +; CHECK-NEXT: stfd f1, 0(r30) +; CHECK-NEXT: addi r1, r1, 48 +; CHECK-NEXT: ld r0, 16(r1) +; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload +; CHECK-NEXT: mtlr r0 +; CHECK-NEXT: blr +; +; CHECK-P8-LABEL: qpConvppcf128: +; CHECK-P8: # %bb.0: # %entry +; CHECK-P8-NEXT: mflr r0 +; CHECK-P8-NEXT: .cfi_def_cfa_offset 48 +; CHECK-P8-NEXT: .cfi_offset lr, 16 +; CHECK-P8-NEXT: .cfi_offset r30, -16 +; CHECK-P8-NEXT: std r30, -16(r1) # 8-byte Folded Spill +; CHECK-P8-NEXT: std r0, 16(r1) +; CHECK-P8-NEXT: stdu r1, -48(r1) +; CHECK-P8-NEXT: mr r30, r5 +; CHECK-P8-NEXT: bl __extendkftf2 +; CHECK-P8-NEXT: nop +; CHECK-P8-NEXT: stfd f2, 8(r30) +; CHECK-P8-NEXT: stfd f1, 0(r30) +; CHECK-P8-NEXT: addi r1, r1, 48 +; CHECK-P8-NEXT: ld r0, 16(r1) +; CHECK-P8-NEXT: ld r30, -16(r1) # 8-byte Folded Reload +; CHECK-P8-NEXT: mtlr r0 +; CHECK-P8-NEXT: blr +entry: + %res = call ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128 %src) + store ppc_fp128 %res, ppc_fp128* %dst, align 16 + ret void +} + +define void @ppcf128Convqp(ppc_fp128 %src, fp128* %dst) { +; CHECK-LABEL: ppcf128Convqp: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mflr r0 +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: .cfi_offset lr, 16 +; CHECK-NEXT: .cfi_offset r30, -16 +; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill +; CHECK-NEXT: std r0, 16(r1) +; CHECK-NEXT: stdu r1, -48(r1) +; CHECK-NEXT: mr r30, r5 +; CHECK-NEXT: bl __trunctfkf2 +; CHECK-NEXT: nop +; CHECK-NEXT: stxv v2, 0(r30) +; CHECK-NEXT: addi r1, r1, 48 +; CHECK-NEXT: ld r0, 16(r1) +; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload +; CHECK-NEXT: mtlr r0 +; CHECK-NEXT: blr +; +; CHECK-P8-LABEL: ppcf128Convqp: +; CHECK-P8: # %bb.0: # %entry +; CHECK-P8-NEXT: mflr r0 +; CHECK-P8-NEXT: .cfi_def_cfa_offset 48 +; CHECK-P8-NEXT: .cfi_offset lr, 16 +; CHECK-P8-NEXT: .cfi_offset r30, -16 +; CHECK-P8-NEXT: std r30, -16(r1) # 8-byte Folded Spill +; CHECK-P8-NEXT: std r0, 16(r1) +; CHECK-P8-NEXT: stdu r1, -48(r1) +; CHECK-P8-NEXT: mr r30, r5 +; CHECK-P8-NEXT: bl __trunctfkf2 +; CHECK-P8-NEXT: nop +; CHECK-P8-NEXT: stvx v2, 0, r30 +; CHECK-P8-NEXT: addi r1, r1, 48 +; CHECK-P8-NEXT: ld r0, 16(r1) +; CHECK-P8-NEXT: ld r30, -16(r1) # 8-byte Folded Reload +; CHECK-P8-NEXT: mtlr r0 +; CHECK-P8-NEXT: blr +entry: + %res = call fp128 @llvm.ppc.convert.ppcf128.to.f128(ppc_fp128 %src) + store fp128 %res, fp128* %dst, align 16 + ret void +} + +declare ppc_fp128 @llvm.ppc.convert.f128.to.ppcf128(fp128) +declare fp128 @llvm.ppc.convert.ppcf128.to.f128(ppc_fp128)