mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-02 10:32:56 +00:00
[CodeGen] Round [SU]INT_TO_FP result when promoting from f16.
If we don't, values that aren't precisely representable in f16 could be used as-is in a promoted f32 operation, which would produce incorrect results. AArch64 had the correct behavior; add a focused test. Fixes http://llvm.org/PR26871 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@268700 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ecc2a1e20c
commit
00ac1d03f5
@ -2102,9 +2102,14 @@ SDValue DAGTypeLegalizer::PromoteFloatRes_SELECT_CC(SDNode *N) {
|
|||||||
// Construct a SDNode that transforms the SINT or UINT operand to the promoted
|
// Construct a SDNode that transforms the SINT or UINT operand to the promoted
|
||||||
// float type.
|
// float type.
|
||||||
SDValue DAGTypeLegalizer::PromoteFloatRes_XINT_TO_FP(SDNode *N) {
|
SDValue DAGTypeLegalizer::PromoteFloatRes_XINT_TO_FP(SDNode *N) {
|
||||||
|
SDLoc DL(N);
|
||||||
EVT VT = N->getValueType(0);
|
EVT VT = N->getValueType(0);
|
||||||
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
|
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) {
|
SDValue DAGTypeLegalizer::PromoteFloatRes_UNDEF(SDNode *N) {
|
||||||
|
@ -446,6 +446,34 @@ define half @test_sitofp_i64(i64 %a) #0 {
|
|||||||
ret half %r
|
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-LABEL: test_fptrunc_float:
|
||||||
; CHECK-NEXT: fcvt h0, s0
|
; CHECK-NEXT: fcvt h0, s0
|
||||||
; CHECK-NEXT: ret
|
; CHECK-NEXT: ret
|
||||||
|
@ -889,4 +889,44 @@ define half @test_struct_arg(%struct.dummy %p) {
|
|||||||
ret half %a
|
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 }
|
attributes #0 = { nounwind }
|
||||||
|
@ -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"
|
target triple = "armv7a--none-eabi"
|
||||||
|
|
||||||
; CHECK-LABEL: test_vec3:
|
; CHECK-LABEL: test_vec3:
|
||||||
; CHECK: vcvtb.f32.f16
|
; CHECK-DAG: vcvtb.f32.f16 [[SREG1:s[0-9]+]],
|
||||||
; CHECK: vcvt.f32.s32
|
; CHECK-DAG: vcvt.f32.s32 [[SREG2:s[0-9]+]],
|
||||||
; CHECK: vadd.f32
|
; CHECK-DAG: vcvtb.f16.f32 [[SREG3:s[0-9]+]], [[SREG2]]
|
||||||
; CHECK-NEXT: vcvtb.f16.f32 [[SREG:s[0-9]+]], {{.*}}
|
; CHECK-DAG: vcvtb.f32.f16 [[SREG4:s[0-9]+]], [[SREG3]]
|
||||||
; CHECK-NEXT: vmov [[RREG1:r[0-9]+]], [[SREG]]
|
; 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: uxth [[RREG2:r[0-9]+]], [[RREG1]]
|
||||||
; CHECK-NEXT: pkhbt [[RREG3:r[0-9]+]], [[RREG1]], [[RREG1]], lsl #16
|
; CHECK-NEXT: pkhbt [[RREG3:r[0-9]+]], [[RREG1]], [[RREG1]], lsl #16
|
||||||
; CHECK-DAG: strh [[RREG1]], [r0, #4]
|
; CHECK-DAG: strh [[RREG1]], [r0, #4]
|
||||||
|
@ -279,4 +279,38 @@ define half @test_f80trunc_nodagcombine() #0 {
|
|||||||
ret half %2
|
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 }
|
attributes #0 = { nounwind }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user