forked from OSchip/llvm-project
[RISCV64] Emit correct lib call for fp(float/double) to ui/si
Since i32 is not legal in riscv64, it always promoted to i64 before emitting lib call and for conversions like float/double to int and float/double to unsigned int wrong lib call was emitted. This commit fix it using custom lowering. Differential Revision: https://reviews.llvm.org/D80526
This commit is contained in:
parent
b2f2adee00
commit
7622ea5835
|
@ -197,6 +197,14 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
|
|||
setTruncStoreAction(MVT::f64, MVT::f16, Expand);
|
||||
}
|
||||
|
||||
if (Subtarget.is64Bit() &&
|
||||
!(Subtarget.hasStdExtD() || Subtarget.hasStdExtF())) {
|
||||
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
|
||||
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
|
||||
setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i32, Custom);
|
||||
setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i32, Custom);
|
||||
}
|
||||
|
||||
setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
|
||||
setOperationAction(ISD::BlockAddress, XLenVT, Custom);
|
||||
setOperationAction(ISD::ConstantPool, XLenVT, Custom);
|
||||
|
@ -904,6 +912,32 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
|
|||
switch (N->getOpcode()) {
|
||||
default:
|
||||
llvm_unreachable("Don't know how to custom type legalize this operation!");
|
||||
case ISD::STRICT_FP_TO_SINT:
|
||||
case ISD::STRICT_FP_TO_UINT:
|
||||
case ISD::FP_TO_SINT:
|
||||
case ISD::FP_TO_UINT: {
|
||||
bool IsStrict = N->isStrictFPOpcode();
|
||||
assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
|
||||
"Unexpected custom legalisation");
|
||||
SDValue Op0 = IsStrict ? N->getOperand(1) : N->getOperand(0);
|
||||
RTLIB::Libcall LC;
|
||||
if (N->getOpcode() == ISD::FP_TO_SINT ||
|
||||
N->getOpcode() == ISD::STRICT_FP_TO_SINT)
|
||||
LC = RTLIB::getFPTOSINT(Op0.getValueType(), N->getValueType(0));
|
||||
else
|
||||
LC = RTLIB::getFPTOUINT(Op0.getValueType(), N->getValueType(0));
|
||||
MakeLibCallOptions CallOptions;
|
||||
EVT OpVT = Op0.getValueType();
|
||||
CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0), true);
|
||||
SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
|
||||
SDValue Result;
|
||||
std::tie(Result, Chain) =
|
||||
makeLibCall(DAG, LC, N->getValueType(0), Op0, CallOptions, DL, Chain);
|
||||
Results.push_back(Result);
|
||||
if (IsStrict)
|
||||
Results.push_back(Chain);
|
||||
break;
|
||||
}
|
||||
case ISD::READCYCLECOUNTER: {
|
||||
assert(!Subtarget.is64Bit() &&
|
||||
"READCYCLECOUNTER only has custom type legalization on riscv32");
|
||||
|
|
|
@ -174,7 +174,7 @@ define i32 @fcvt_w_s(float %a) nounwind {
|
|||
; RV64I: # %bb.0:
|
||||
; RV64I-NEXT: addi sp, sp, -16
|
||||
; RV64I-NEXT: sd ra, 8(sp)
|
||||
; RV64I-NEXT: call __fixsfdi
|
||||
; RV64I-NEXT: call __fixsfsi
|
||||
; RV64I-NEXT: ld ra, 8(sp)
|
||||
; RV64I-NEXT: addi sp, sp, 16
|
||||
; RV64I-NEXT: ret
|
||||
|
@ -187,7 +187,7 @@ define i32 @fcvt_wu_s(float %a) nounwind {
|
|||
; RV64I: # %bb.0:
|
||||
; RV64I-NEXT: addi sp, sp, -16
|
||||
; RV64I-NEXT: sd ra, 8(sp)
|
||||
; RV64I-NEXT: call __fixunssfdi
|
||||
; RV64I-NEXT: call __fixunssfsi
|
||||
; RV64I-NEXT: ld ra, 8(sp)
|
||||
; RV64I-NEXT: addi sp, sp, 16
|
||||
; RV64I-NEXT: ret
|
||||
|
@ -710,3 +710,123 @@ define float @fp_trunc(double %a) nounwind {
|
|||
%conv = fptrunc double %a to float
|
||||
ret float %conv
|
||||
}
|
||||
|
||||
define i32 @fp32_to_ui32(float %a) nounwind {
|
||||
; RV64I-LABEL: fp32_to_ui32:
|
||||
; RV64I: # %bb.0: # %entry
|
||||
; RV64I-NEXT: addi sp, sp, -16
|
||||
; RV64I-NEXT: sd ra, 8(sp)
|
||||
; RV64I-NEXT: call __fixunssfsi
|
||||
; RV64I-NEXT: ld ra, 8(sp)
|
||||
; RV64I-NEXT: addi sp, sp, 16
|
||||
; RV64I-NEXT: ret
|
||||
entry:
|
||||
%conv = fptoui float %a to i32
|
||||
ret i32 %conv
|
||||
}
|
||||
|
||||
define i32 @fp32_to_si32(float %a) nounwind {
|
||||
; RV64I-LABEL: fp32_to_si32:
|
||||
; RV64I: # %bb.0: # %entry
|
||||
; RV64I-NEXT: addi sp, sp, -16
|
||||
; RV64I-NEXT: sd ra, 8(sp)
|
||||
; RV64I-NEXT: call __fixsfsi
|
||||
; RV64I-NEXT: ld ra, 8(sp)
|
||||
; RV64I-NEXT: addi sp, sp, 16
|
||||
; RV64I-NEXT: ret
|
||||
entry:
|
||||
%conv = fptosi float %a to i32
|
||||
ret i32 %conv
|
||||
}
|
||||
|
||||
define i32 @fp64_to_ui32(double %a) nounwind {
|
||||
; RV64I-LABEL: fp64_to_ui32:
|
||||
; RV64I: # %bb.0: # %entry
|
||||
; RV64I-NEXT: addi sp, sp, -16
|
||||
; RV64I-NEXT: sd ra, 8(sp)
|
||||
; RV64I-NEXT: call __fixunsdfsi
|
||||
; RV64I-NEXT: ld ra, 8(sp)
|
||||
; RV64I-NEXT: addi sp, sp, 16
|
||||
; RV64I-NEXT: ret
|
||||
entry:
|
||||
%conv = fptoui double %a to i32
|
||||
ret i32 %conv
|
||||
}
|
||||
|
||||
define i32 @fp64_to_si32(double %a) nounwind {
|
||||
; RV64I-LABEL: fp64_to_si32:
|
||||
; RV64I: # %bb.0: # %entry
|
||||
; RV64I-NEXT: addi sp, sp, -16
|
||||
; RV64I-NEXT: sd ra, 8(sp)
|
||||
; RV64I-NEXT: call __fixdfsi
|
||||
; RV64I-NEXT: ld ra, 8(sp)
|
||||
; RV64I-NEXT: addi sp, sp, 16
|
||||
; RV64I-NEXT: ret
|
||||
entry:
|
||||
%conv = fptosi double %a to i32
|
||||
ret i32 %conv
|
||||
}
|
||||
|
||||
|
||||
|
||||
declare i32 @llvm.experimental.constrained.fptoui.i32.f32(float, metadata)
|
||||
declare i32 @llvm.experimental.constrained.fptosi.i32.f32(float, metadata)
|
||||
declare i32 @llvm.experimental.constrained.fptosi.i32.f64(double, metadata)
|
||||
declare i32 @llvm.experimental.constrained.fptoui.i32.f64(double, metadata)
|
||||
|
||||
define i32 @strict_fp32_to_ui32(float %a) nounwind strictfp {
|
||||
; RV64I-LABEL: strict_fp32_to_ui32:
|
||||
; RV64I: # %bb.0: # %entry
|
||||
; RV64I-NEXT: addi sp, sp, -16
|
||||
; RV64I-NEXT: sd ra, 8(sp)
|
||||
; RV64I-NEXT: call __fixunssfsi
|
||||
; RV64I-NEXT: ld ra, 8(sp)
|
||||
; RV64I-NEXT: addi sp, sp, 16
|
||||
; RV64I-NEXT: ret
|
||||
entry:
|
||||
%conv = tail call i32 @llvm.experimental.constrained.fptoui.i32.f32(float %a, metadata !"fpexcept.strict")
|
||||
ret i32 %conv
|
||||
}
|
||||
|
||||
define i32 @strict_fp32_to_si32(float %a) nounwind strictfp {
|
||||
; RV64I-LABEL: strict_fp32_to_si32:
|
||||
; RV64I: # %bb.0: # %entry
|
||||
; RV64I-NEXT: addi sp, sp, -16
|
||||
; RV64I-NEXT: sd ra, 8(sp)
|
||||
; RV64I-NEXT: call __fixsfsi
|
||||
; RV64I-NEXT: ld ra, 8(sp)
|
||||
; RV64I-NEXT: addi sp, sp, 16
|
||||
; RV64I-NEXT: ret
|
||||
entry:
|
||||
%conv = tail call i32 @llvm.experimental.constrained.fptosi.i32.f32(float %a, metadata !"fpexcept.strict")
|
||||
ret i32 %conv
|
||||
}
|
||||
|
||||
define i32 @strict_fp64_to_ui32(double %a) nounwind strictfp {
|
||||
; RV64I-LABEL: strict_fp64_to_ui32:
|
||||
; RV64I: # %bb.0: # %entry
|
||||
; RV64I-NEXT: addi sp, sp, -16
|
||||
; RV64I-NEXT: sd ra, 8(sp)
|
||||
; RV64I-NEXT: call __fixunsdfsi
|
||||
; RV64I-NEXT: ld ra, 8(sp)
|
||||
; RV64I-NEXT: addi sp, sp, 16
|
||||
; RV64I-NEXT: ret
|
||||
entry:
|
||||
%conv = tail call i32 @llvm.experimental.constrained.fptoui.i32.f64(double %a, metadata !"fpexcept.strict")
|
||||
ret i32 %conv
|
||||
}
|
||||
|
||||
define i32 @struct_fp64_to_si32(double %a) nounwind strictfp {
|
||||
; RV64I-LABEL: struct_fp64_to_si32:
|
||||
; RV64I: # %bb.0: # %entry
|
||||
; RV64I-NEXT: addi sp, sp, -16
|
||||
; RV64I-NEXT: sd ra, 8(sp)
|
||||
; RV64I-NEXT: call __fixdfsi
|
||||
; RV64I-NEXT: ld ra, 8(sp)
|
||||
; RV64I-NEXT: addi sp, sp, 16
|
||||
; RV64I-NEXT: ret
|
||||
entry:
|
||||
%conv = tail call i32 @llvm.experimental.constrained.fptosi.i32.f64(double %a, metadata !"fpexcept.strict")
|
||||
ret i32 %conv
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue