diff --git a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp index 6c0193a7673..38639a2a3a2 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -2102,9 +2102,14 @@ SDValue DAGTypeLegalizer::PromoteFloatRes_SELECT_CC(SDNode *N) { // Construct a SDNode that transforms the SINT or UINT operand to the promoted // float type. SDValue DAGTypeLegalizer::PromoteFloatRes_XINT_TO_FP(SDNode *N) { + SDLoc DL(N); EVT VT = N->getValueType(0); EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); - return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, N->getOperand(0)); + SDValue NV = DAG.getNode(N->getOpcode(), DL, NVT, N->getOperand(0)); + // Round the value to the desired precision (that of the source type). + return DAG.getNode( + ISD::FP_EXTEND, DL, NVT, + DAG.getNode(ISD::FP_ROUND, DL, VT, NV, DAG.getIntPtrConstant(0, DL))); } SDValue DAGTypeLegalizer::PromoteFloatRes_UNDEF(SDNode *N) { diff --git a/test/CodeGen/AArch64/f16-instructions.ll b/test/CodeGen/AArch64/f16-instructions.ll index 8ba4e363741..df26cefa328 100644 --- a/test/CodeGen/AArch64/f16-instructions.ll +++ b/test/CodeGen/AArch64/f16-instructions.ll @@ -446,6 +446,34 @@ define half @test_sitofp_i64(i64 %a) #0 { ret half %r } +; CHECK-LABEL: test_uitofp_i32_fadd: +; CHECK-NEXT: ucvtf s1, w0 +; CHECK-NEXT: fcvt h1, s1 +; CHECK-NEXT: fcvt s0, h0 +; CHECK-NEXT: fcvt s1, h1 +; CHECK-NEXT: fadd s0, s0, s1 +; CHECK-NEXT: fcvt h0, s0 +; CHECK-NEXT: ret +define half @test_uitofp_i32_fadd(i32 %a, half %b) #0 { + %c = uitofp i32 %a to half + %r = fadd half %b, %c + ret half %r +} + +; CHECK-LABEL: test_sitofp_i32_fadd: +; CHECK-NEXT: scvtf s1, w0 +; CHECK-NEXT: fcvt h1, s1 +; CHECK-NEXT: fcvt s0, h0 +; CHECK-NEXT: fcvt s1, h1 +; CHECK-NEXT: fadd s0, s0, s1 +; CHECK-NEXT: fcvt h0, s0 +; CHECK-NEXT: ret +define half @test_sitofp_i32_fadd(i32 %a, half %b) #0 { + %c = sitofp i32 %a to half + %r = fadd half %b, %c + ret half %r +} + ; CHECK-LABEL: test_fptrunc_float: ; CHECK-NEXT: fcvt h0, s0 ; CHECK-NEXT: ret diff --git a/test/CodeGen/ARM/fp16-promote.ll b/test/CodeGen/ARM/fp16-promote.ll index 2a2eb8d2b6b..4da56b7ef35 100644 --- a/test/CodeGen/ARM/fp16-promote.ll +++ b/test/CodeGen/ARM/fp16-promote.ll @@ -889,4 +889,44 @@ define half @test_struct_arg(%struct.dummy %p) { ret half %a } +; CHECK-LABEL: test_uitofp_i32_fadd: +; CHECK-VFP-DAG: vcvt.f32.u32 +; CHECK-NOVFP-DAG: bl __aeabi_ui2f + +; CHECK-FP16-DAG: vcvtb.f16.f32 +; CHECK-FP16-DAG: vcvtb.f32.f16 +; CHECK-LIBCALL-DAG: bl __aeabi_h2f +; CHECK-LIBCALL-DAG: bl __aeabi_h2f + +; CHECK-VFP-DAG: vadd.f32 +; CHECK-NOVFP-DAG: bl __aeabi_fadd + +; CHECK-FP16-DAG: vcvtb.f16.f32 +; CHECK-LIBCALL-DAG: bl __aeabi_f2h +define half @test_uitofp_i32_fadd(i32 %a, half %b) #0 { + %c = uitofp i32 %a to half + %r = fadd half %b, %c + ret half %r +} + +; CHECK-LABEL: test_sitofp_i32_fadd: +; CHECK-VFP-DAG: vcvt.f32.s32 +; CHECK-NOVFP-DAG: bl __aeabi_i2f + +; CHECK-FP16-DAG: vcvtb.f16.f32 +; CHECK-FP16-DAG: vcvtb.f32.f16 +; CHECK-LIBCALL-DAG: bl __aeabi_h2f +; CHECK-LIBCALL-DAG: bl __aeabi_h2f + +; CHECK-VFP-DAG: vadd.f32 +; CHECK-NOVFP-DAG: bl __aeabi_fadd + +; CHECK-FP16-DAG: vcvtb.f16.f32 +; CHECK-LIBCALL-DAG: bl __aeabi_f2h +define half @test_sitofp_i32_fadd(i32 %a, half %b) #0 { + %c = sitofp i32 %a to half + %r = fadd half %b, %c + ret half %r +} + attributes #0 = { nounwind } diff --git a/test/CodeGen/ARM/fp16-v3.ll b/test/CodeGen/ARM/fp16-v3.ll index 4a120723542..e26455e61e7 100644 --- a/test/CodeGen/ARM/fp16-v3.ll +++ b/test/CodeGen/ARM/fp16-v3.ll @@ -4,11 +4,13 @@ target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" target triple = "armv7a--none-eabi" ; CHECK-LABEL: test_vec3: -; CHECK: vcvtb.f32.f16 -; CHECK: vcvt.f32.s32 -; CHECK: vadd.f32 -; CHECK-NEXT: vcvtb.f16.f32 [[SREG:s[0-9]+]], {{.*}} -; CHECK-NEXT: vmov [[RREG1:r[0-9]+]], [[SREG]] +; CHECK-DAG: vcvtb.f32.f16 [[SREG1:s[0-9]+]], +; CHECK-DAG: vcvt.f32.s32 [[SREG2:s[0-9]+]], +; CHECK-DAG: vcvtb.f16.f32 [[SREG3:s[0-9]+]], [[SREG2]] +; CHECK-DAG: vcvtb.f32.f16 [[SREG4:s[0-9]+]], [[SREG3]] +; CHECK: vadd.f32 [[SREG5:s[0-9]+]], [[SREG4]], [[SREG1]] +; CHECK-NEXT: vcvtb.f16.f32 [[SREG6:s[0-9]+]], [[SREG5]] +; CHECK-NEXT: vmov [[RREG1:r[0-9]+]], [[SREG6]] ; CHECK-NEXT: uxth [[RREG2:r[0-9]+]], [[RREG1]] ; CHECK-NEXT: pkhbt [[RREG3:r[0-9]+]], [[RREG1]], [[RREG1]], lsl #16 ; CHECK-DAG: strh [[RREG1]], [r0, #4] diff --git a/test/CodeGen/X86/half.ll b/test/CodeGen/X86/half.ll index 9a9fb582055..717ddbfa6fd 100644 --- a/test/CodeGen/X86/half.ll +++ b/test/CodeGen/X86/half.ll @@ -279,4 +279,38 @@ define half @test_f80trunc_nodagcombine() #0 { ret half %2 } +; CHECK-LABEL: test_sitofp_fadd_i32: + +; CHECK-LIBCALL-NEXT: pushq %rbx +; CHECK-LIBCALL-NEXT: subq $16, %rsp +; CHECK-LIBCALL-NEXT: movl %edi, %ebx +; CHECK-LIBCALL-NEXT: movzwl (%rsi), %edi +; CHECK-LIBCALL-NEXT: callq __gnu_h2f_ieee +; CHECK-LIBCALL-NEXT: movss %xmm0, 12(%rsp) +; CHECK-LIBCALL-NEXT: cvtsi2ssl %ebx, %xmm0 +; CHECK-LIBCALL-NEXT: callq __gnu_f2h_ieee +; CHECK-LIBCALL-NEXT: movzwl %ax, %edi +; CHECK-LIBCALL-NEXT: callq __gnu_h2f_ieee +; CHECK-LIBCALL-NEXT: addss 12(%rsp), %xmm0 +; CHECK-LIBCALL-NEXT: addq $16, %rsp +; CHECK-LIBCALL-NEXT: popq %rbx +; CHECK-LIBCALL-NEXT: retq + +; CHECK-F16C-NEXT: movswl (%rsi), %eax +; CHECK-F16C-NEXT: vmovd %eax, %xmm0 +; CHECK-F16C-NEXT: vcvtph2ps %xmm0, %xmm0 +; CHECK-F16C-NEXT: vcvtsi2ssl %edi, %xmm0, %xmm1 +; CHECK-F16C-NEXT: vcvtps2ph $4, %xmm1, %xmm1 +; CHECK-F16C-NEXT: vcvtph2ps %xmm1, %xmm1 +; CHECK-F16C-NEXT: vaddss %xmm1, %xmm0, %xmm0 +; CHECK-F16C-NEXT: retq + +define float @test_sitofp_fadd_i32(i32 %a, half* %b) #0 { + %tmp0 = load half, half* %b + %tmp1 = sitofp i32 %a to half + %tmp2 = fadd half %tmp0, %tmp1 + %tmp3 = fpext half %tmp2 to float + ret float %tmp3 +} + attributes #0 = { nounwind }